Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / content / renderer / media / android / stream_texture_factory_synchronous_impl.cc
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.
4
5 #include "content/renderer/media/android/stream_texture_factory_synchronous_impl.h"
6
7 #include <algorithm>
8
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"
21
22 using gpu::gles2::GLES2Interface;
23
24 namespace content {
25
26 namespace {
27
28 class StreamTextureProxyImpl
29     : public StreamTextureProxy,
30       public base::SupportsWeakPtr<StreamTextureProxyImpl> {
31  public:
32   explicit StreamTextureProxyImpl(
33       StreamTextureFactorySynchronousImpl::ContextProvider* provider);
34   virtual ~StreamTextureProxyImpl();
35
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;
40
41  private:
42   void OnFrameAvailable();
43
44   scoped_refptr<base::MessageLoopProxy> loop_;
45   base::Lock client_lock_;
46   cc::VideoFrameProvider::Client* client_;
47   base::Closure callback_;
48
49   scoped_refptr<StreamTextureFactorySynchronousImpl::ContextProvider>
50       context_provider_;
51   scoped_refptr<gfx::SurfaceTexture> surface_texture_;
52
53   float current_matrix_[16];
54   bool has_updated_;
55
56   DISALLOW_IMPLICIT_CONSTRUCTORS(StreamTextureProxyImpl);
57 };
58
59 StreamTextureProxyImpl::StreamTextureProxyImpl(
60     StreamTextureFactorySynchronousImpl::ContextProvider* provider)
61     : context_provider_(provider), has_updated_(false) {
62   std::fill(current_matrix_, current_matrix_ + 16, 0);
63 }
64
65 StreamTextureProxyImpl::~StreamTextureProxyImpl() {}
66
67 void StreamTextureProxyImpl::Release() {
68   SetClient(NULL);
69   if (loop_.get() && !loop_->BelongsToCurrentThread())
70     loop_->DeleteSoon(FROM_HERE, this);
71   else
72     delete this;
73 }
74
75 void StreamTextureProxyImpl::SetClient(cc::VideoFrameProvider::Client* client) {
76   base::AutoLock lock(client_lock_);
77   client_ = client;
78 }
79
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.";
85     return;
86   }
87
88   callback_ =
89       base::Bind(&StreamTextureProxyImpl::OnFrameAvailable, AsWeakPtr());
90   surface_texture_->SetFrameAvailableCallback(callback_);
91 }
92
93 void StreamTextureProxyImpl::OnFrameAvailable() {
94   // GetTransformMatrix only returns something valid after both is true:
95   // - OnFrameAvailable was called
96   // - we called UpdateTexImage
97   if (has_updated_) {
98     float matrix[16];
99     surface_texture_->GetTransformMatrix(matrix);
100
101     if (memcmp(current_matrix_, matrix, sizeof(matrix)) != 0) {
102       memcpy(current_matrix_, matrix, sizeof(matrix));
103
104       base::AutoLock lock(client_lock_);
105       if (client_)
106         client_->DidUpdateMatrix(current_matrix_);
107     }
108   }
109   // OnFrameAvailable being called a second time implies that we called
110   // updateTexImage since after we received the first frame.
111   has_updated_ = true;
112
113   base::AutoLock lock(client_lock_);
114   if (client_)
115     client_->DidReceiveFrame();
116 }
117
118 }  // namespace
119
120 // static
121 scoped_refptr<StreamTextureFactorySynchronousImpl>
122 StreamTextureFactorySynchronousImpl::Create(
123     const CreateContextProviderCallback& try_create_callback,
124     int frame_id) {
125   return new StreamTextureFactorySynchronousImpl(try_create_callback, frame_id);
126 }
127
128 StreamTextureFactorySynchronousImpl::StreamTextureFactorySynchronousImpl(
129     const CreateContextProviderCallback& try_create_callback,
130     int frame_id)
131     : create_context_provider_callback_(try_create_callback),
132       context_provider_(create_context_provider_callback_.Run()),
133       frame_id_(frame_id) {}
134
135 StreamTextureFactorySynchronousImpl::~StreamTextureFactorySynchronousImpl() {}
136
137 StreamTextureProxy* StreamTextureFactorySynchronousImpl::CreateProxy() {
138   if (!context_provider_)
139     context_provider_ = create_context_provider_callback_.Run();
140
141   if (!context_provider_)
142     return NULL;
143   return new StreamTextureProxyImpl(context_provider_);
144 }
145
146 void StreamTextureFactorySynchronousImpl::EstablishPeer(int32 stream_id,
147                                                         int player_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(),
154         surface_texture,
155         frame_id_,
156         player_id);
157   }
158 }
159
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);
169
170   gl->GenMailboxCHROMIUM(texture_mailbox->name);
171   gl->ProduceTextureDirectCHROMIUM(
172       *texture_id, texture_target, texture_mailbox->name);
173   return stream_id;
174 }
175
176 void StreamTextureFactorySynchronousImpl::SetStreamTextureSize(
177     int32 stream_id,
178     const gfx::Size& size) {}
179
180 gpu::gles2::GLES2Interface* StreamTextureFactorySynchronousImpl::ContextGL() {
181   DCHECK(context_provider_);
182   return context_provider_->ContextGL();
183 }
184
185 }  // namespace content