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/process/process_handle.h"
14 #include "base/single_thread_task_runner.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 ~StreamTextureProxyImpl() override
;
36 // StreamTextureProxy implementation:
37 void BindToLoop(int32 stream_id
,
38 cc::VideoFrameProvider::Client
* client
,
39 scoped_refptr
<base::SingleThreadTaskRunner
> loop
) override
;
40 void Release() override
;
43 void BindOnThread(int32 stream_id
);
44 void OnFrameAvailable();
46 // Protects access to |client_| and |loop_|.
48 cc::VideoFrameProvider::Client
* client_
;
49 scoped_refptr
<base::SingleThreadTaskRunner
> loop_
;
51 // Accessed on the |loop_| thread only.
52 base::Closure callback_
;
53 scoped_refptr
<StreamTextureFactorySynchronousImpl::ContextProvider
>
55 scoped_refptr
<gfx::SurfaceTexture
> surface_texture_
;
56 float current_matrix_
[16];
59 DISALLOW_IMPLICIT_CONSTRUCTORS(StreamTextureProxyImpl
);
62 StreamTextureProxyImpl::StreamTextureProxyImpl(
63 StreamTextureFactorySynchronousImpl::ContextProvider
* provider
)
64 : client_(NULL
), context_provider_(provider
), has_updated_(false) {
65 std::fill(current_matrix_
, current_matrix_
+ 16, 0);
68 StreamTextureProxyImpl::~StreamTextureProxyImpl() {}
70 void StreamTextureProxyImpl::Release() {
72 // Cannot call into |client_| anymore (from any thread) after returning
74 base::AutoLock
lock(lock_
);
77 // Release is analogous to the destructor, so there should be no more external
78 // calls to this object in Release. Therefore there is no need to acquire the
79 // lock to access |loop_|.
80 if (!loop_
.get() || loop_
->BelongsToCurrentThread() ||
81 !loop_
->DeleteSoon(FROM_HERE
, this)) {
86 void StreamTextureProxyImpl::BindToLoop(
88 cc::VideoFrameProvider::Client
* client
,
89 scoped_refptr
<base::SingleThreadTaskRunner
> loop
) {
93 base::AutoLock
lock(lock_
);
94 DCHECK(!loop_
.get() || (loop
.get() == loop_
.get()));
99 if (loop
->BelongsToCurrentThread()) {
100 BindOnThread(stream_id
);
103 // Unretained is safe here only because the object is deleted on |loop_|
105 loop
->PostTask(FROM_HERE
,
106 base::Bind(&StreamTextureProxyImpl::BindOnThread
,
107 base::Unretained(this),
111 void StreamTextureProxyImpl::BindOnThread(int32 stream_id
) {
112 surface_texture_
= context_provider_
->GetSurfaceTexture(stream_id
);
113 if (!surface_texture_
.get()) {
114 LOG(ERROR
) << "Failed to get SurfaceTexture for stream.";
119 base::Bind(&StreamTextureProxyImpl::OnFrameAvailable
, AsWeakPtr());
120 surface_texture_
->SetFrameAvailableCallback(callback_
);
123 void StreamTextureProxyImpl::OnFrameAvailable() {
124 // GetTransformMatrix only returns something valid after both is true:
125 // - OnFrameAvailable was called
126 // - we called UpdateTexImage
129 surface_texture_
->GetTransformMatrix(matrix
);
131 if (memcmp(current_matrix_
, matrix
, sizeof(matrix
)) != 0) {
132 memcpy(current_matrix_
, matrix
, sizeof(matrix
));
134 base::AutoLock
lock(lock_
);
136 client_
->DidUpdateMatrix(current_matrix_
);
139 // OnFrameAvailable being called a second time implies that we called
140 // updateTexImage since after we received the first frame.
143 base::AutoLock
lock(lock_
);
145 client_
->DidReceiveFrame();
151 scoped_refptr
<StreamTextureFactorySynchronousImpl
>
152 StreamTextureFactorySynchronousImpl::Create(
153 const CreateContextProviderCallback
& try_create_callback
,
155 return new StreamTextureFactorySynchronousImpl(try_create_callback
, frame_id
);
158 StreamTextureFactorySynchronousImpl::StreamTextureFactorySynchronousImpl(
159 const CreateContextProviderCallback
& try_create_callback
,
161 : create_context_provider_callback_(try_create_callback
),
162 context_provider_(create_context_provider_callback_
.Run()),
166 StreamTextureFactorySynchronousImpl::~StreamTextureFactorySynchronousImpl() {}
168 StreamTextureProxy
* StreamTextureFactorySynchronousImpl::CreateProxy() {
169 bool had_proxy
= !!context_provider_
.get();
171 context_provider_
= create_context_provider_callback_
.Run();
173 if (!context_provider_
.get())
176 if (observer_
&& !had_proxy
)
177 context_provider_
->AddObserver(observer_
);
178 return new StreamTextureProxyImpl(context_provider_
.get());
181 void StreamTextureFactorySynchronousImpl::EstablishPeer(int32 stream_id
,
183 DCHECK(context_provider_
.get());
184 scoped_refptr
<gfx::SurfaceTexture
> surface_texture
=
185 context_provider_
->GetSurfaceTexture(stream_id
);
186 if (surface_texture
.get()) {
187 SurfaceTexturePeer::GetInstance()->EstablishSurfaceTexturePeer(
188 base::GetCurrentProcessHandle(),
195 unsigned StreamTextureFactorySynchronousImpl::CreateStreamTexture(
196 unsigned texture_target
,
197 unsigned* texture_id
,
198 gpu::Mailbox
* texture_mailbox
) {
199 DCHECK(context_provider_
.get());
200 unsigned stream_id
= 0;
201 GLES2Interface
* gl
= context_provider_
->ContextGL();
202 gl
->GenTextures(1, texture_id
);
203 stream_id
= gl
->CreateStreamTextureCHROMIUM(*texture_id
);
205 gl
->GenMailboxCHROMIUM(texture_mailbox
->name
);
206 gl
->ProduceTextureDirectCHROMIUM(
207 *texture_id
, texture_target
, texture_mailbox
->name
);
211 void StreamTextureFactorySynchronousImpl::SetStreamTextureSize(
213 const gfx::Size
& size
) {}
215 gpu::gles2::GLES2Interface
* StreamTextureFactorySynchronousImpl::ContextGL() {
216 DCHECK(context_provider_
.get());
217 return context_provider_
->ContextGL();
220 void StreamTextureFactorySynchronousImpl::AddObserver(
221 StreamTextureFactoryContextObserver
* obs
) {
224 if (context_provider_
.get())
225 context_provider_
->AddObserver(obs
);
228 void StreamTextureFactorySynchronousImpl::RemoveObserver(
229 StreamTextureFactoryContextObserver
* obs
) {
230 DCHECK_EQ(observer_
, obs
);
232 if (context_provider_
.get())
233 context_provider_
->RemoveObserver(obs
);
236 } // namespace content