1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/renderer/media/android/stream_texture_factory_synchronous_impl.h"
10 #include "base/callback.h"
11 #include "base/location.h"
12 #include "base/memory/weak_ptr.h"
13 #include "base/message_loop/message_loop_proxy.h"
14 #include "base/process/process.h"
15 #include "base/synchronization/lock.h"
16 #include "cc/output/context_provider.h"
17 #include "content/common/android/surface_texture_peer.h"
18 #include "content/renderer/render_thread_impl.h"
19 #include "gpu/command_buffer/client/gles2_interface.h"
20 #include "ui/gl/android/surface_texture.h"
22 using gpu::gles2::GLES2Interface;
28 class StreamTextureProxyImpl
29 : public StreamTextureProxy,
30 public base::SupportsWeakPtr<StreamTextureProxyImpl> {
32 explicit StreamTextureProxyImpl(
33 StreamTextureFactorySynchronousImpl::ContextProvider* provider);
34 virtual ~StreamTextureProxyImpl();
36 // StreamTextureProxy implementation:
37 virtual void BindToCurrentThread(int32 stream_id) OVERRIDE;
38 virtual void SetClient(cc::VideoFrameProvider::Client* client) OVERRIDE;
39 virtual void Release() OVERRIDE;
42 void OnFrameAvailable();
44 scoped_refptr<base::MessageLoopProxy> loop_;
45 base::Lock client_lock_;
46 cc::VideoFrameProvider::Client* client_;
47 base::Closure callback_;
49 scoped_refptr<StreamTextureFactorySynchronousImpl::ContextProvider>
51 scoped_refptr<gfx::SurfaceTexture> surface_texture_;
53 float current_matrix_[16];
56 DISALLOW_IMPLICIT_CONSTRUCTORS(StreamTextureProxyImpl);
59 StreamTextureProxyImpl::StreamTextureProxyImpl(
60 StreamTextureFactorySynchronousImpl::ContextProvider* provider)
61 : context_provider_(provider), has_updated_(false) {
62 std::fill(current_matrix_, current_matrix_ + 16, 0);
65 StreamTextureProxyImpl::~StreamTextureProxyImpl() {}
67 void StreamTextureProxyImpl::Release() {
69 if (loop_.get() && !loop_->BelongsToCurrentThread())
70 loop_->DeleteSoon(FROM_HERE, this);
75 void StreamTextureProxyImpl::SetClient(cc::VideoFrameProvider::Client* client) {
76 base::AutoLock lock(client_lock_);
80 void StreamTextureProxyImpl::BindToCurrentThread(int stream_id) {
81 loop_ = base::MessageLoopProxy::current();
82 surface_texture_ = context_provider_->GetSurfaceTexture(stream_id);
83 if (!surface_texture_) {
84 LOG(ERROR) << "Failed to get SurfaceTexture for stream.";
89 base::Bind(&StreamTextureProxyImpl::OnFrameAvailable, AsWeakPtr());
90 surface_texture_->SetFrameAvailableCallback(callback_);
93 void StreamTextureProxyImpl::OnFrameAvailable() {
94 // GetTransformMatrix only returns something valid after both is true:
95 // - OnFrameAvailable was called
96 // - we called UpdateTexImage
99 surface_texture_->GetTransformMatrix(matrix);
101 if (memcmp(current_matrix_, matrix, sizeof(matrix)) != 0) {
102 memcpy(current_matrix_, matrix, sizeof(matrix));
104 base::AutoLock lock(client_lock_);
106 client_->DidUpdateMatrix(current_matrix_);
109 // OnFrameAvailable being called a second time implies that we called
110 // updateTexImage since after we received the first frame.
113 base::AutoLock lock(client_lock_);
115 client_->DidReceiveFrame();
121 scoped_refptr<StreamTextureFactorySynchronousImpl>
122 StreamTextureFactorySynchronousImpl::Create(
123 const CreateContextProviderCallback& try_create_callback,
125 return new StreamTextureFactorySynchronousImpl(try_create_callback, frame_id);
128 StreamTextureFactorySynchronousImpl::StreamTextureFactorySynchronousImpl(
129 const CreateContextProviderCallback& try_create_callback,
131 : create_context_provider_callback_(try_create_callback),
132 context_provider_(create_context_provider_callback_.Run()),
133 frame_id_(frame_id) {}
135 StreamTextureFactorySynchronousImpl::~StreamTextureFactorySynchronousImpl() {}
137 StreamTextureProxy* StreamTextureFactorySynchronousImpl::CreateProxy() {
138 if (!context_provider_)
139 context_provider_ = create_context_provider_callback_.Run();
141 if (!context_provider_)
143 return new StreamTextureProxyImpl(context_provider_);
146 void StreamTextureFactorySynchronousImpl::EstablishPeer(int32 stream_id,
148 DCHECK(context_provider_);
149 scoped_refptr<gfx::SurfaceTexture> surface_texture =
150 context_provider_->GetSurfaceTexture(stream_id);
151 if (surface_texture) {
152 SurfaceTexturePeer::GetInstance()->EstablishSurfaceTexturePeer(
153 base::Process::Current().handle(),
160 unsigned StreamTextureFactorySynchronousImpl::CreateStreamTexture(
161 unsigned texture_target,
162 unsigned* texture_id,
163 gpu::Mailbox* texture_mailbox) {
164 DCHECK(context_provider_);
165 unsigned stream_id = 0;
166 GLES2Interface* gl = context_provider_->ContextGL();
167 gl->GenTextures(1, texture_id);
168 stream_id = gl->CreateStreamTextureCHROMIUM(*texture_id);
170 gl->GenMailboxCHROMIUM(texture_mailbox->name);
171 gl->ProduceTextureDirectCHROMIUM(
172 *texture_id, texture_target, texture_mailbox->name);
176 void StreamTextureFactorySynchronousImpl::SetStreamTextureSize(
178 const gfx::Size& size) {}
180 gpu::gles2::GLES2Interface* StreamTextureFactorySynchronousImpl::ContextGL() {
181 DCHECK(context_provider_);
182 return context_provider_->ContextGL();
185 } // namespace content