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_impl.h" 6 7#include "cc/output/context_provider.h" 8#include "content/common/gpu/client/gpu_channel_host.h" 9#include "content/common/gpu/gpu_messages.h" 10#include "content/renderer/gpu/stream_texture_host_android.h" 11#include "gpu/command_buffer/client/gles2_interface.h" 12#include "ui/gfx/size.h" 13 14namespace content { 15 16namespace { 17 18class StreamTextureProxyImpl : public StreamTextureProxy, 19 public StreamTextureHost::Listener { 20 public: 21 explicit StreamTextureProxyImpl(StreamTextureHost* host); 22 virtual ~StreamTextureProxyImpl(); 23 24 // StreamTextureProxy implementation: 25 virtual void BindToLoop(int32 stream_id, 26 cc::VideoFrameProvider::Client* client, 27 scoped_refptr<base::MessageLoopProxy> loop) OVERRIDE; 28 virtual void Release() OVERRIDE; 29 30 // StreamTextureHost::Listener implementation: 31 virtual void OnFrameAvailable() OVERRIDE; 32 virtual void OnMatrixChanged(const float matrix[16]) OVERRIDE; 33 34 private: 35 void BindOnThread(int32 stream_id); 36 37 const scoped_ptr<StreamTextureHost> host_; 38 39 // Protects access to |client_| and |loop_|. 40 base::Lock lock_; 41 cc::VideoFrameProvider::Client* client_; 42 scoped_refptr<base::MessageLoopProxy> loop_; 43 44 DISALLOW_IMPLICIT_CONSTRUCTORS(StreamTextureProxyImpl); 45}; 46 47StreamTextureProxyImpl::StreamTextureProxyImpl(StreamTextureHost* host) 48 : host_(host), client_(NULL) {} 49 50StreamTextureProxyImpl::~StreamTextureProxyImpl() {} 51 52void StreamTextureProxyImpl::Release() { 53 { 54 // Cannot call into |client_| anymore (from any thread) after returning 55 // from here. 56 base::AutoLock lock(lock_); 57 client_ = NULL; 58 } 59 // Release is analogous to the destructor, so there should be no more external 60 // calls to this object in Release. Therefore there is no need to acquire the 61 // lock to access |loop_|. 62 if (!loop_.get() || loop_->BelongsToCurrentThread() || 63 !loop_->DeleteSoon(FROM_HERE, this)) { 64 delete this; 65 } 66} 67 68void StreamTextureProxyImpl::BindToLoop( 69 int32 stream_id, 70 cc::VideoFrameProvider::Client* client, 71 scoped_refptr<base::MessageLoopProxy> loop) { 72 DCHECK(loop); 73 74 { 75 base::AutoLock lock(lock_); 76 DCHECK(!loop_ || (loop == loop_)); 77 loop_ = loop; 78 client_ = client; 79 } 80 81 if (loop->BelongsToCurrentThread()) { 82 BindOnThread(stream_id); 83 return; 84 } 85 // Unretained is safe here only because the object is deleted on |loop_| 86 // thread. 87 loop->PostTask(FROM_HERE, 88 base::Bind(&StreamTextureProxyImpl::BindOnThread, 89 base::Unretained(this), 90 stream_id)); 91} 92 93void StreamTextureProxyImpl::BindOnThread(int32 stream_id) { 94 host_->BindToCurrentThread(stream_id, this); 95} 96 97void StreamTextureProxyImpl::OnFrameAvailable() { 98 base::AutoLock lock(lock_); 99 if (client_) 100 client_->DidReceiveFrame(); 101} 102 103void StreamTextureProxyImpl::OnMatrixChanged(const float matrix[16]) { 104 base::AutoLock lock(lock_); 105 if (client_) 106 client_->DidUpdateMatrix(matrix); 107} 108 109} // namespace 110 111// static 112scoped_refptr<StreamTextureFactoryImpl> StreamTextureFactoryImpl::Create( 113 const scoped_refptr<cc::ContextProvider>& context_provider, 114 GpuChannelHost* channel, 115 int frame_id) { 116 return new StreamTextureFactoryImpl(context_provider, channel, frame_id); 117} 118 119StreamTextureFactoryImpl::StreamTextureFactoryImpl( 120 const scoped_refptr<cc::ContextProvider>& context_provider, 121 GpuChannelHost* channel, 122 int frame_id) 123 : context_provider_(context_provider), 124 channel_(channel), 125 frame_id_(frame_id) { 126 DCHECK(channel); 127} 128 129StreamTextureFactoryImpl::~StreamTextureFactoryImpl() {} 130 131StreamTextureProxy* StreamTextureFactoryImpl::CreateProxy() { 132 DCHECK(channel_.get()); 133 StreamTextureHost* host = new StreamTextureHost(channel_.get()); 134 return new StreamTextureProxyImpl(host); 135} 136 137void StreamTextureFactoryImpl::EstablishPeer(int32 stream_id, int player_id) { 138 DCHECK(channel_.get()); 139 channel_->Send( 140 new GpuStreamTextureMsg_EstablishPeer(stream_id, frame_id_, player_id)); 141} 142 143unsigned StreamTextureFactoryImpl::CreateStreamTexture( 144 unsigned texture_target, 145 unsigned* texture_id, 146 gpu::Mailbox* texture_mailbox) { 147 GLuint stream_id = 0; 148 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); 149 gl->GenTextures(1, texture_id); 150 151 stream_id = gl->CreateStreamTextureCHROMIUM(*texture_id); 152 153 gl->GenMailboxCHROMIUM(texture_mailbox->name); 154 gl->ProduceTextureDirectCHROMIUM( 155 *texture_id, texture_target, texture_mailbox->name); 156 return stream_id; 157} 158 159void StreamTextureFactoryImpl::SetStreamTextureSize(int32 stream_id, 160 const gfx::Size& size) { 161 channel_->Send(new GpuStreamTextureMsg_SetSize(stream_id, size)); 162} 163 164gpu::gles2::GLES2Interface* StreamTextureFactoryImpl::ContextGL() { 165 return context_provider_->ContextGL(); 166} 167 168void StreamTextureFactoryImpl::AddObserver( 169 StreamTextureFactoryContextObserver* obs) { 170} 171 172void StreamTextureFactoryImpl::RemoveObserver( 173 StreamTextureFactoryContextObserver* obs) { 174} 175 176} // namespace content 177