Replace FINAL and OVERRIDE with their C++11 counterparts in content/renderer
[chromium-blink-merge.git] / content / renderer / media / android / stream_texture_factory_synchronous_impl.cc
blob5c0fb59065cdb91a5b37e7096ace45b6768d1199
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"
7 #include <algorithm>
9 #include "base/bind.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;
24 namespace content {
26 namespace {
28 class StreamTextureProxyImpl
29 : public StreamTextureProxy,
30 public base::SupportsWeakPtr<StreamTextureProxyImpl> {
31 public:
32 explicit StreamTextureProxyImpl(
33 StreamTextureFactorySynchronousImpl::ContextProvider* provider);
34 virtual ~StreamTextureProxyImpl();
36 // StreamTextureProxy implementation:
37 virtual void BindToLoop(int32 stream_id,
38 cc::VideoFrameProvider::Client* client,
39 scoped_refptr<base::MessageLoopProxy> loop) override;
40 virtual void Release() override;
42 private:
43 void BindOnThread(int32 stream_id);
44 void OnFrameAvailable();
46 // Protects access to |client_| and |loop_|.
47 base::Lock lock_;
48 cc::VideoFrameProvider::Client* client_;
49 scoped_refptr<base::MessageLoopProxy> loop_;
51 // Accessed on the |loop_| thread only.
52 base::Closure callback_;
53 scoped_refptr<StreamTextureFactorySynchronousImpl::ContextProvider>
54 context_provider_;
55 scoped_refptr<gfx::SurfaceTexture> surface_texture_;
56 float current_matrix_[16];
57 bool has_updated_;
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
73 // from here.
74 base::AutoLock lock(lock_);
75 client_ = NULL;
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)) {
82 delete this;
86 void StreamTextureProxyImpl::BindToLoop(
87 int32 stream_id,
88 cc::VideoFrameProvider::Client* client,
89 scoped_refptr<base::MessageLoopProxy> loop) {
90 DCHECK(loop.get());
93 base::AutoLock lock(lock_);
94 DCHECK(!loop_.get() || (loop.get() == loop_.get()));
95 loop_ = loop;
96 client_ = client;
99 if (loop->BelongsToCurrentThread()) {
100 BindOnThread(stream_id);
101 return;
103 // Unretained is safe here only because the object is deleted on |loop_|
104 // thread.
105 loop->PostTask(FROM_HERE,
106 base::Bind(&StreamTextureProxyImpl::BindOnThread,
107 base::Unretained(this),
108 stream_id));
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.";
115 return;
118 callback_ =
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
127 if (has_updated_) {
128 float matrix[16];
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_);
135 if (client_)
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.
141 has_updated_ = true;
143 base::AutoLock lock(lock_);
144 if (client_)
145 client_->DidReceiveFrame();
148 } // namespace
150 // static
151 scoped_refptr<StreamTextureFactorySynchronousImpl>
152 StreamTextureFactorySynchronousImpl::Create(
153 const CreateContextProviderCallback& try_create_callback,
154 int frame_id) {
155 return new StreamTextureFactorySynchronousImpl(try_create_callback, frame_id);
158 StreamTextureFactorySynchronousImpl::StreamTextureFactorySynchronousImpl(
159 const CreateContextProviderCallback& try_create_callback,
160 int frame_id)
161 : create_context_provider_callback_(try_create_callback),
162 context_provider_(create_context_provider_callback_.Run()),
163 frame_id_(frame_id),
164 observer_(NULL) {}
166 StreamTextureFactorySynchronousImpl::~StreamTextureFactorySynchronousImpl() {}
168 StreamTextureProxy* StreamTextureFactorySynchronousImpl::CreateProxy() {
169 bool had_proxy = !!context_provider_.get();
170 if (!had_proxy)
171 context_provider_ = create_context_provider_callback_.Run();
173 if (!context_provider_.get())
174 return NULL;
176 if (observer_ && !had_proxy)
177 context_provider_->AddObserver(observer_);
178 return new StreamTextureProxyImpl(context_provider_.get());
181 void StreamTextureFactorySynchronousImpl::EstablishPeer(int32 stream_id,
182 int player_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::Process::Current().handle(),
189 surface_texture,
190 frame_id_,
191 player_id);
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);
208 return stream_id;
211 void StreamTextureFactorySynchronousImpl::SetStreamTextureSize(
212 int32 stream_id,
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) {
222 DCHECK(!observer_);
223 observer_ = obs;
224 if (context_provider_.get())
225 context_provider_->AddObserver(obs);
228 void StreamTextureFactorySynchronousImpl::RemoveObserver(
229 StreamTextureFactoryContextObserver* obs) {
230 DCHECK_EQ(observer_, obs);
231 observer_ = NULL;
232 if (context_provider_.get())
233 context_provider_->RemoveObserver(obs);
236 } // namespace content