// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "webkit/media/webmediaplayer_proxy.h" #include "base/bind.h" #include "base/logging.h" #include "base/message_loop_proxy.h" #include "media/base/pipeline_status.h" #include "media/filters/chunk_demuxer.h" #include "media/filters/video_renderer_base.h" #include "webkit/media/webmediaplayer_impl.h" using media::NetworkEvent; using media::PipelineStatus; namespace webkit_media { // Limits the maximum outstanding repaints posted on render thread. // This number of 50 is a guess, it does not take too much memory on the task // queue but gives up a pretty good latency on repaint. static const int kMaxOutstandingRepaints = 50; WebMediaPlayerProxy::WebMediaPlayerProxy( const scoped_refptr& render_loop, WebMediaPlayerImpl* webmediaplayer) : render_loop_(render_loop), webmediaplayer_(webmediaplayer), outstanding_repaints_(0) { DCHECK(render_loop_); DCHECK(webmediaplayer_); } WebMediaPlayerProxy::~WebMediaPlayerProxy() { Detach(); } void WebMediaPlayerProxy::Repaint() { base::AutoLock auto_lock(lock_); if (outstanding_repaints_ < kMaxOutstandingRepaints) { ++outstanding_repaints_; render_loop_->PostTask(FROM_HERE, base::Bind( &WebMediaPlayerProxy::RepaintTask, this)); } } void WebMediaPlayerProxy::SetOpaque(bool opaque) { render_loop_->PostTask(FROM_HERE, base::Bind( &WebMediaPlayerProxy::SetOpaqueTask, this, opaque)); } void WebMediaPlayerProxy::Paint(SkCanvas* canvas, const gfx::Rect& dest_rect) { DCHECK(render_loop_->BelongsToCurrentThread()); if (frame_provider_) { scoped_refptr video_frame; frame_provider_->GetCurrentFrame(&video_frame); video_renderer_.Paint(video_frame, canvas, dest_rect); frame_provider_->PutCurrentFrame(video_frame); } } bool WebMediaPlayerProxy::HasSingleOrigin() { DCHECK(render_loop_->BelongsToCurrentThread()); if (data_source_) return data_source_->HasSingleOrigin(); return true; } void WebMediaPlayerProxy::AbortDataSource() { DCHECK(render_loop_->BelongsToCurrentThread()); if (data_source_) data_source_->Abort(); } void WebMediaPlayerProxy::Detach() { DCHECK(render_loop_->BelongsToCurrentThread()); webmediaplayer_ = NULL; data_source_ = NULL; frame_provider_ = NULL; } void WebMediaPlayerProxy::PipelineInitializationCallback( PipelineStatus status) { render_loop_->PostTask(FROM_HERE, base::Bind( &WebMediaPlayerProxy::PipelineInitializationTask, this, status)); } void WebMediaPlayerProxy::PipelineSeekCallback(PipelineStatus status) { render_loop_->PostTask(FROM_HERE, base::Bind( &WebMediaPlayerProxy::PipelineSeekTask, this, status)); } void WebMediaPlayerProxy::PipelineEndedCallback(PipelineStatus status) { render_loop_->PostTask(FROM_HERE, base::Bind( &WebMediaPlayerProxy::PipelineEndedTask, this, status)); } void WebMediaPlayerProxy::PipelineErrorCallback(PipelineStatus error) { DCHECK_NE(error, media::PIPELINE_OK); render_loop_->PostTask(FROM_HERE, base::Bind( &WebMediaPlayerProxy::PipelineErrorTask, this, error)); } void WebMediaPlayerProxy::NetworkEventCallback(NetworkEvent type) { render_loop_->PostTask(FROM_HERE, base::Bind( &WebMediaPlayerProxy::NetworkEventTask, this, type)); } void WebMediaPlayerProxy::RepaintTask() { DCHECK(render_loop_->BelongsToCurrentThread()); { base::AutoLock auto_lock(lock_); --outstanding_repaints_; DCHECK_GE(outstanding_repaints_, 0); } if (webmediaplayer_) { webmediaplayer_->Repaint(); } } void WebMediaPlayerProxy::PipelineInitializationTask(PipelineStatus status) { DCHECK(render_loop_->BelongsToCurrentThread()); if (webmediaplayer_) webmediaplayer_->OnPipelineInitialize(status); } void WebMediaPlayerProxy::PipelineSeekTask(PipelineStatus status) { DCHECK(render_loop_->BelongsToCurrentThread()); if (webmediaplayer_) webmediaplayer_->OnPipelineSeek(status); } void WebMediaPlayerProxy::PipelineEndedTask(PipelineStatus status) { DCHECK(render_loop_->BelongsToCurrentThread()); if (webmediaplayer_) webmediaplayer_->OnPipelineEnded(status); } void WebMediaPlayerProxy::PipelineErrorTask(PipelineStatus error) { DCHECK(render_loop_->BelongsToCurrentThread()); if (webmediaplayer_) webmediaplayer_->OnPipelineError(error); } void WebMediaPlayerProxy::NetworkEventTask(NetworkEvent type) { DCHECK(render_loop_->BelongsToCurrentThread()); if (webmediaplayer_) webmediaplayer_->OnNetworkEvent(type); } void WebMediaPlayerProxy::SetOpaqueTask(bool opaque) { DCHECK(render_loop_->BelongsToCurrentThread()); if (webmediaplayer_) webmediaplayer_->SetOpaque(opaque); } void WebMediaPlayerProxy::GetCurrentFrame( scoped_refptr* frame_out) { if (frame_provider_) frame_provider_->GetCurrentFrame(frame_out); } void WebMediaPlayerProxy::PutCurrentFrame( scoped_refptr frame) { if (frame_provider_) frame_provider_->PutCurrentFrame(frame); } void WebMediaPlayerProxy::DemuxerOpened(media::ChunkDemuxer* demuxer) { render_loop_->PostTask(FROM_HERE, base::Bind( &WebMediaPlayerProxy::DemuxerOpenedTask, this, scoped_refptr(demuxer))); } void WebMediaPlayerProxy::DemuxerClosed() { render_loop_->PostTask(FROM_HERE, base::Bind( &WebMediaPlayerProxy::DemuxerClosedTask, this)); } void WebMediaPlayerProxy::DemuxerFlush() { if (chunk_demuxer_.get()) chunk_demuxer_->FlushData(); } bool WebMediaPlayerProxy::DemuxerAppend(const uint8* data, size_t length) { if (chunk_demuxer_.get()) return chunk_demuxer_->AppendData(data, length); return false; } void WebMediaPlayerProxy::DemuxerEndOfStream(media::PipelineStatus status) { if (chunk_demuxer_.get()) chunk_demuxer_->EndOfStream(status); } void WebMediaPlayerProxy::DemuxerShutdown() { if (chunk_demuxer_.get()) chunk_demuxer_->Shutdown(); } void WebMediaPlayerProxy::DemuxerOpenedTask( const scoped_refptr& demuxer) { DCHECK(render_loop_->BelongsToCurrentThread()); chunk_demuxer_ = demuxer; if (webmediaplayer_) webmediaplayer_->OnDemuxerOpened(); } void WebMediaPlayerProxy::DemuxerClosedTask() { chunk_demuxer_ = NULL; } } // namespace webkit_media