#include "base/location.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop_proxy.h"
-#include "base/process/process.h"
+#include "base/process/process_handle.h"
#include "base/synchronization/lock.h"
#include "cc/output/context_provider.h"
#include "content/common/android/surface_texture_peer.h"
virtual ~StreamTextureProxyImpl();
// StreamTextureProxy implementation:
- virtual void BindToCurrentThread(int32 stream_id) OVERRIDE;
- virtual void SetClient(cc::VideoFrameProvider::Client* client) OVERRIDE;
- virtual void Release() OVERRIDE;
+ virtual void BindToLoop(int32 stream_id,
+ cc::VideoFrameProvider::Client* client,
+ scoped_refptr<base::MessageLoopProxy> loop) override;
+ virtual void Release() override;
private:
- void BindOnCompositorThread(int stream_id);
+ void BindOnThread(int32 stream_id);
void OnFrameAvailable();
- scoped_refptr<base::MessageLoopProxy> loop_;
- base::Lock client_lock_;
+ // Protects access to |client_| and |loop_|.
+ base::Lock lock_;
cc::VideoFrameProvider::Client* client_;
- base::Closure callback_;
+ scoped_refptr<base::MessageLoopProxy> loop_;
+ // Accessed on the |loop_| thread only.
+ base::Closure callback_;
scoped_refptr<StreamTextureFactorySynchronousImpl::ContextProvider>
context_provider_;
scoped_refptr<gfx::SurfaceTexture> surface_texture_;
-
float current_matrix_[16];
bool has_updated_;
StreamTextureProxyImpl::StreamTextureProxyImpl(
StreamTextureFactorySynchronousImpl::ContextProvider* provider)
- : context_provider_(provider), has_updated_(false) {
- DCHECK(RenderThreadImpl::current());
- loop_ = RenderThreadImpl::current()->compositor_message_loop_proxy();
+ : client_(NULL), context_provider_(provider), has_updated_(false) {
std::fill(current_matrix_, current_matrix_ + 16, 0);
}
StreamTextureProxyImpl::~StreamTextureProxyImpl() {}
void StreamTextureProxyImpl::Release() {
- SetClient(NULL);
- if (!loop_->BelongsToCurrentThread())
- loop_->DeleteSoon(FROM_HERE, this);
- else
+ {
+ // Cannot call into |client_| anymore (from any thread) after returning
+ // from here.
+ base::AutoLock lock(lock_);
+ client_ = NULL;
+ }
+ // Release is analogous to the destructor, so there should be no more external
+ // calls to this object in Release. Therefore there is no need to acquire the
+ // lock to access |loop_|.
+ if (!loop_.get() || loop_->BelongsToCurrentThread() ||
+ !loop_->DeleteSoon(FROM_HERE, this)) {
delete this;
+ }
}
-void StreamTextureProxyImpl::SetClient(cc::VideoFrameProvider::Client* client) {
- base::AutoLock lock(client_lock_);
- client_ = client;
-}
+void StreamTextureProxyImpl::BindToLoop(
+ int32 stream_id,
+ cc::VideoFrameProvider::Client* client,
+ scoped_refptr<base::MessageLoopProxy> loop) {
+ DCHECK(loop.get());
+
+ {
+ base::AutoLock lock(lock_);
+ DCHECK(!loop_.get() || (loop.get() == loop_.get()));
+ loop_ = loop;
+ client_ = client;
+ }
-void StreamTextureProxyImpl::BindToCurrentThread(int stream_id) {
- if (loop_->BelongsToCurrentThread()) {
- BindOnCompositorThread(stream_id);
+ if (loop->BelongsToCurrentThread()) {
+ BindOnThread(stream_id);
return;
}
-
- // Weakptr is only used on compositor thread loop, so this is safe.
- loop_->PostTask(FROM_HERE,
- base::Bind(&StreamTextureProxyImpl::BindOnCompositorThread,
- AsWeakPtr(),
- stream_id));
+ // Unretained is safe here only because the object is deleted on |loop_|
+ // thread.
+ loop->PostTask(FROM_HERE,
+ base::Bind(&StreamTextureProxyImpl::BindOnThread,
+ base::Unretained(this),
+ stream_id));
}
-void StreamTextureProxyImpl::BindOnCompositorThread(int stream_id) {
+void StreamTextureProxyImpl::BindOnThread(int32 stream_id) {
surface_texture_ = context_provider_->GetSurfaceTexture(stream_id);
- if (!surface_texture_) {
+ if (!surface_texture_.get()) {
LOG(ERROR) << "Failed to get SurfaceTexture for stream.";
return;
}
if (memcmp(current_matrix_, matrix, sizeof(matrix)) != 0) {
memcpy(current_matrix_, matrix, sizeof(matrix));
- base::AutoLock lock(client_lock_);
+ base::AutoLock lock(lock_);
if (client_)
client_->DidUpdateMatrix(current_matrix_);
}
// updateTexImage since after we received the first frame.
has_updated_ = true;
- base::AutoLock lock(client_lock_);
+ base::AutoLock lock(lock_);
if (client_)
client_->DidReceiveFrame();
}
scoped_refptr<StreamTextureFactorySynchronousImpl>
StreamTextureFactorySynchronousImpl::Create(
const CreateContextProviderCallback& try_create_callback,
- int view_id) {
- return new StreamTextureFactorySynchronousImpl(try_create_callback, view_id);
+ int frame_id) {
+ return new StreamTextureFactorySynchronousImpl(try_create_callback, frame_id);
}
StreamTextureFactorySynchronousImpl::StreamTextureFactorySynchronousImpl(
const CreateContextProviderCallback& try_create_callback,
- int view_id)
+ int frame_id)
: create_context_provider_callback_(try_create_callback),
context_provider_(create_context_provider_callback_.Run()),
- view_id_(view_id) {}
+ frame_id_(frame_id),
+ observer_(NULL) {}
StreamTextureFactorySynchronousImpl::~StreamTextureFactorySynchronousImpl() {}
StreamTextureProxy* StreamTextureFactorySynchronousImpl::CreateProxy() {
- if (!context_provider_)
+ bool had_proxy = !!context_provider_.get();
+ if (!had_proxy)
context_provider_ = create_context_provider_callback_.Run();
- if (!context_provider_)
+ if (!context_provider_.get())
return NULL;
- return new StreamTextureProxyImpl(context_provider_);
+
+ if (observer_ && !had_proxy)
+ context_provider_->AddObserver(observer_);
+ return new StreamTextureProxyImpl(context_provider_.get());
}
void StreamTextureFactorySynchronousImpl::EstablishPeer(int32 stream_id,
int player_id) {
- DCHECK(context_provider_);
+ DCHECK(context_provider_.get());
scoped_refptr<gfx::SurfaceTexture> surface_texture =
context_provider_->GetSurfaceTexture(stream_id);
- if (surface_texture) {
+ if (surface_texture.get()) {
SurfaceTexturePeer::GetInstance()->EstablishSurfaceTexturePeer(
- base::Process::Current().handle(),
+ base::GetCurrentProcessHandle(),
surface_texture,
- view_id_,
+ frame_id_,
player_id);
}
}
unsigned texture_target,
unsigned* texture_id,
gpu::Mailbox* texture_mailbox) {
- DCHECK(context_provider_);
+ DCHECK(context_provider_.get());
unsigned stream_id = 0;
GLES2Interface* gl = context_provider_->ContextGL();
gl->GenTextures(1, texture_id);
stream_id = gl->CreateStreamTextureCHROMIUM(*texture_id);
gl->GenMailboxCHROMIUM(texture_mailbox->name);
- gl->BindTexture(texture_target, *texture_id);
- gl->ProduceTextureCHROMIUM(texture_target, texture_mailbox->name);
+ gl->ProduceTextureDirectCHROMIUM(
+ *texture_id, texture_target, texture_mailbox->name);
return stream_id;
}
const gfx::Size& size) {}
gpu::gles2::GLES2Interface* StreamTextureFactorySynchronousImpl::ContextGL() {
- DCHECK(context_provider_);
+ DCHECK(context_provider_.get());
return context_provider_->ContextGL();
}
+void StreamTextureFactorySynchronousImpl::AddObserver(
+ StreamTextureFactoryContextObserver* obs) {
+ DCHECK(!observer_);
+ observer_ = obs;
+ if (context_provider_.get())
+ context_provider_->AddObserver(obs);
+}
+
+void StreamTextureFactorySynchronousImpl::RemoveObserver(
+ StreamTextureFactoryContextObserver* obs) {
+ DCHECK_EQ(observer_, obs);
+ observer_ = NULL;
+ if (context_provider_.get())
+ context_provider_->RemoveObserver(obs);
+}
+
} // namespace content