// 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::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, uint8_t alpha) { DCHECK(render_loop_->BelongsToCurrentThread()); if (frame_provider_) { scoped_refptr video_frame; frame_provider_->GetCurrentFrame(&video_frame); video_renderer_.Paint(video_frame, canvas, dest_rect, alpha); frame_provider_->PutCurrentFrame(video_frame); } } bool WebMediaPlayerProxy::HasSingleOrigin() { DCHECK(render_loop_->BelongsToCurrentThread()); if (data_source_) return data_source_->HasSingleOrigin(); return true; } bool WebMediaPlayerProxy::DidPassCORSAccessCheck() const { DCHECK(render_loop_->BelongsToCurrentThread()); if (data_source_) return data_source_->DidPassCORSAccessCheck(); return false; } 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; video_decoder_ = 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::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::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::DemuxerNeedKey(scoped_array init_data, int init_data_size) { render_loop_->PostTask(FROM_HERE, base::Bind( &WebMediaPlayerProxy::NeedKeyTask, this, "", "", base::Passed(&init_data), init_data_size)); } void WebMediaPlayerProxy::DemuxerStartWaitingForSeek() { if (chunk_demuxer_.get()) chunk_demuxer_->StartWaitingForSeek(); } media::ChunkDemuxer::Status WebMediaPlayerProxy::DemuxerAddId( const std::string& id, const std::string& type, std::vector& codecs) { return chunk_demuxer_->AddId(id, type, codecs); } void WebMediaPlayerProxy::DemuxerRemoveId(const std::string& id) { chunk_demuxer_->RemoveId(id); } media::Ranges WebMediaPlayerProxy::DemuxerBufferedRange( const std::string& id) { return chunk_demuxer_->GetBufferedRanges(id); } bool WebMediaPlayerProxy::DemuxerAppend(const std::string& id, const uint8* data, size_t length) { return chunk_demuxer_->AppendData(id, data, length); } void WebMediaPlayerProxy::DemuxerAbort(const std::string& id) { chunk_demuxer_->Abort(id); } void WebMediaPlayerProxy::DemuxerEndOfStream(media::PipelineStatus status) { 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; } void WebMediaPlayerProxy::KeyAdded(const std::string& key_system, const std::string& session_id) { render_loop_->PostTask(FROM_HERE, base::Bind( &WebMediaPlayerProxy::KeyAddedTask, this, key_system, session_id)); } void WebMediaPlayerProxy::KeyError(const std::string& key_system, const std::string& session_id, media::Decryptor::KeyError error_code, int system_code) { render_loop_->PostTask(FROM_HERE, base::Bind( &WebMediaPlayerProxy::KeyErrorTask, this, key_system, session_id, error_code, system_code)); } void WebMediaPlayerProxy::KeyMessage(const std::string& key_system, const std::string& session_id, scoped_array message, int message_length, const std::string& default_url) { render_loop_->PostTask(FROM_HERE, base::Bind( &WebMediaPlayerProxy::KeyMessageTask, this, key_system, session_id, base::Passed(&message), message_length, default_url)); } void WebMediaPlayerProxy::NeedKey(const std::string& key_system, const std::string& session_id, scoped_array init_data, int init_data_size) { render_loop_->PostTask(FROM_HERE, base::Bind( &WebMediaPlayerProxy::NeedKeyTask, this, key_system, session_id, base::Passed(&init_data), init_data_size)); } void WebMediaPlayerProxy::KeyAddedTask(const std::string& key_system, const std::string& session_id) { DCHECK(render_loop_->BelongsToCurrentThread()); if (webmediaplayer_) webmediaplayer_->OnKeyAdded(key_system, session_id); } void WebMediaPlayerProxy::KeyErrorTask(const std::string& key_system, const std::string& session_id, media::Decryptor::KeyError error_code, int system_code) { DCHECK(render_loop_->BelongsToCurrentThread()); if (webmediaplayer_) webmediaplayer_->OnKeyError(key_system, session_id, error_code, system_code); } void WebMediaPlayerProxy::KeyMessageTask(const std::string& key_system, const std::string& session_id, scoped_array message, int message_length, const std::string& default_url) { DCHECK(render_loop_->BelongsToCurrentThread()); if (webmediaplayer_) webmediaplayer_->OnKeyMessage(key_system, session_id, message.Pass(), message_length, default_url); } void WebMediaPlayerProxy::NeedKeyTask(const std::string& key_system, const std::string& session_id, scoped_array init_data, int init_data_size) { DCHECK(render_loop_->BelongsToCurrentThread()); if (webmediaplayer_) webmediaplayer_->OnNeedKey(key_system, session_id, init_data.Pass(), init_data_size); } } // namespace webkit_media