summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xchrome/chrome.sln1
-rw-r--r--chrome/renderer/media/audio_renderer_impl.cc9
-rw-r--r--chrome/renderer/media/audio_renderer_impl.h17
-rw-r--r--chrome/renderer/media/data_source_impl.cc9
-rw-r--r--chrome/renderer/media/data_source_impl.h17
-rw-r--r--chrome/renderer/media/video_renderer_impl.cc18
-rw-r--r--chrome/renderer/media/video_renderer_impl.h34
-rw-r--r--chrome/renderer/render_view.cc2
-rw-r--r--chrome/renderer/webmediaplayer_delegate_impl.cc324
-rw-r--r--chrome/renderer/webmediaplayer_delegate_impl.h169
-rw-r--r--media/base/pipeline_impl.h2
-rw-r--r--webkit/glue/webmediaplayer.h12
-rw-r--r--webkit/glue/webmediaplayer_delegate.h10
-rw-r--r--webkit/glue/webmediaplayer_impl.cc88
-rw-r--r--webkit/glue/webmediaplayer_impl.h36
15 files changed, 516 insertions, 232 deletions
diff --git a/chrome/chrome.sln b/chrome/chrome.sln
index 86cf71d..7c2e483 100755
--- a/chrome/chrome.sln
+++ b/chrome/chrome.sln
@@ -29,6 +29,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "renderer", "renderer\render
Release.AspNetCompiler.Debug = "False"
EndProjectSection
ProjectSection(ProjectDependencies) = postProject
+ {6AE76406-B03B-11DD-94B1-80B556D89593} = {6AE76406-B03B-11DD-94B1-80B556D89593}
{D9DDAF60-663F-49CC-90DC-3D08CC3D1B28} = {D9DDAF60-663F-49CC-90DC-3D08CC3D1B28}
EndProjectSection
EndProject
diff --git a/chrome/renderer/media/audio_renderer_impl.cc b/chrome/renderer/media/audio_renderer_impl.cc
index ab59833..113d700 100644
--- a/chrome/renderer/media/audio_renderer_impl.cc
+++ b/chrome/renderer/media/audio_renderer_impl.cc
@@ -4,7 +4,8 @@
#include "chrome/renderer/media/audio_renderer_impl.h"
-AudioRendererImpl::AudioRendererImpl() {
+AudioRendererImpl::AudioRendererImpl(WebMediaPlayerDelegateImpl* delegate)
+ : delegate_(delegate) {
}
AudioRendererImpl::~AudioRendererImpl() {
@@ -25,3 +26,9 @@ void AudioRendererImpl::SetVolume(float volume) {
// TODO(scherkus): implement SetVolume.
NOTIMPLEMENTED();
}
+
+bool AudioRendererImpl::IsMediaFormatSupported(
+ const media::MediaFormat* format) {
+ // TODO(hclam): check the format correct.
+ return true;
+}
diff --git a/chrome/renderer/media/audio_renderer_impl.h b/chrome/renderer/media/audio_renderer_impl.h
index 94cb048..e76bf64 100644
--- a/chrome/renderer/media/audio_renderer_impl.h
+++ b/chrome/renderer/media/audio_renderer_impl.h
@@ -5,11 +5,14 @@
#ifndef CHROME_RENDERER_MEDIA_AUDIO_RENDERER_IMPL_H_
#define CHROME_RENDERER_MEDIA_AUDIO_RENDERER_IMPL_H_
+#include "media/base/factory.h"
#include "media/base/filters.h"
+class WebMediaPlayerDelegateImpl;
+
class AudioRendererImpl : public media::AudioRenderer {
public:
- AudioRendererImpl();
+ AudioRendererImpl(WebMediaPlayerDelegateImpl* delegate);
// media::MediaFilter implementation.
virtual void Stop();
@@ -18,10 +21,22 @@ class AudioRendererImpl : public media::AudioRenderer {
virtual bool Initialize(media::AudioDecoder* decoder);
virtual void SetVolume(float volume);
+ // Static method for creating factory for this object.
+ static media::FilterFactory* CreateFactory(
+ WebMediaPlayerDelegateImpl* delegate) {
+ return new media::FilterFactoryImpl1<AudioRendererImpl,
+ WebMediaPlayerDelegateImpl*>(delegate);
+ }
+
+ // Answers question from the factory to see if we accept |format|.
+ static bool IsMediaFormatSupported(const media::MediaFormat* format);
+
protected:
virtual ~AudioRendererImpl();
private:
+ WebMediaPlayerDelegateImpl* delegate_;
+
DISALLOW_COPY_AND_ASSIGN(AudioRendererImpl);
};
diff --git a/chrome/renderer/media/data_source_impl.cc b/chrome/renderer/media/data_source_impl.cc
index 7193fcc..24dc4d2 100644
--- a/chrome/renderer/media/data_source_impl.cc
+++ b/chrome/renderer/media/data_source_impl.cc
@@ -4,7 +4,8 @@
#include "chrome/renderer/media/data_source_impl.h"
-DataSourceImpl::DataSourceImpl() {
+DataSourceImpl::DataSourceImpl(WebMediaPlayerDelegateImpl* delegate)
+ : delegate_(delegate) {
}
DataSourceImpl::~DataSourceImpl() {
@@ -50,3 +51,9 @@ bool DataSourceImpl::GetSize(int64* size_out) {
NOTIMPLEMENTED();
return false;
}
+
+bool DataSourceImpl::IsMediaFormatSupported(const media::MediaFormat* format) {
+ // TODO(hclam: implement this.
+ NOTIMPLEMENTED();
+ return true;
+}
diff --git a/chrome/renderer/media/data_source_impl.h b/chrome/renderer/media/data_source_impl.h
index fe5bab8..33cbadf 100644
--- a/chrome/renderer/media/data_source_impl.h
+++ b/chrome/renderer/media/data_source_impl.h
@@ -7,12 +7,15 @@
#include <string>
+#include "media/base/factory.h"
#include "media/base/filters.h"
#include "media/base/media_format.h"
+class WebMediaPlayerDelegateImpl;
+
class DataSourceImpl : public media::DataSource {
public:
- DataSourceImpl();
+ DataSourceImpl(WebMediaPlayerDelegateImpl* delegate);
// media::MediaFilter implementation.
virtual void Stop();
@@ -25,10 +28,22 @@ class DataSourceImpl : public media::DataSource {
virtual bool SetPosition(int64 position);
virtual bool GetSize(int64* size_out);
+ // Static method for creating factory for this object.
+ static media::FilterFactory* CreateFactory(
+ WebMediaPlayerDelegateImpl* delegate) {
+ return new media::FilterFactoryImpl1<DataSourceImpl,
+ WebMediaPlayerDelegateImpl*>(delegate);
+ }
+
+ // Answers question from the factory to see if we accept |format|.
+ static bool IsMediaFormatSupported(const media::MediaFormat* format);
+
protected:
virtual ~DataSourceImpl();
private:
+ WebMediaPlayerDelegateImpl* delegate_;
+
DISALLOW_COPY_AND_ASSIGN(DataSourceImpl);
};
diff --git a/chrome/renderer/media/video_renderer_impl.cc b/chrome/renderer/media/video_renderer_impl.cc
index 77d9d90..8159f00 100644
--- a/chrome/renderer/media/video_renderer_impl.cc
+++ b/chrome/renderer/media/video_renderer_impl.cc
@@ -4,7 +4,8 @@
#include "chrome/renderer/media/video_renderer_impl.h"
-VideoRendererImpl::VideoRendererImpl() {
+VideoRendererImpl::VideoRendererImpl(WebMediaPlayerDelegateImpl* delegate)
+ : delegate_(delegate) {
}
VideoRendererImpl::~VideoRendererImpl() {
@@ -20,3 +21,18 @@ bool VideoRendererImpl::Initialize(media::VideoDecoder* decoder) {
NOTIMPLEMENTED();
return false;
}
+
+bool VideoRendererImpl::IsMediaFormatSupported(
+ const media::MediaFormat* format) {
+ // TODO(hclam): check the format correctly.
+ return true;
+}
+
+void VideoRendererImpl::Paint(skia::PlatformCanvas *canvas,
+ const gfx::Rect& rect) {
+ // TODO(hclam): add stuff here.
+}
+
+void VideoRendererImpl::SetRect(const gfx::Rect& rect) {
+ // TODO(hclam): add stuff here.
+}
diff --git a/chrome/renderer/media/video_renderer_impl.h b/chrome/renderer/media/video_renderer_impl.h
index 9b58266..38a7124 100644
--- a/chrome/renderer/media/video_renderer_impl.h
+++ b/chrome/renderer/media/video_renderer_impl.h
@@ -1,15 +1,29 @@
// Copyright (c) 2009 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.
+//
+// The video renderer implementation to be use by the media pipeline. It lives
+// inside video renderer thread and also WebKit's main thread. We need to be
+// extra careful about members shared by two different threads, especially
+// video frame buffers.
+//
+// Methods called from WebKit's main thread:
+// Paint()
+// SetRect()
#ifndef CHROME_RENDERER_MEDIA_VIDEO_RENDERER_H_
#define CHROME_RENDERER_MEDIA_VIDEO_RENDERER_H_
+#include "base/gfx/platform_canvas.h"
+#include "base/gfx/rect.h"
+#include "media/base/factory.h"
#include "media/base/filters.h"
+class WebMediaPlayerDelegateImpl;
+
class VideoRendererImpl : public media::VideoRenderer {
public:
- VideoRendererImpl();
+ VideoRendererImpl(WebMediaPlayerDelegateImpl* delegate);
// media::MediaFilter implementation.
virtual void Stop();
@@ -17,10 +31,28 @@ class VideoRendererImpl : public media::VideoRenderer {
// media::VideoRenderer implementation.
virtual bool Initialize(media::VideoDecoder* decoder);
+ // Called from WebMediaPlayerDelegateImpl from WebKit's main thread.
+ void Paint(skia::PlatformCanvas* canvas, const gfx::Rect& rect);
+
+ // Called from WebMediaPlayerDelegateImpl from WebKit's main thread.
+ void SetRect(const gfx::Rect& rect);
+
+ // Static method for creating factory for this object.
+ static media::FilterFactory* CreateFactory(
+ WebMediaPlayerDelegateImpl* delegate) {
+ return new media::FilterFactoryImpl1<
+ VideoRendererImpl, WebMediaPlayerDelegateImpl*>(delegate);
+ }
+
+ // Answers question from the factory to see if we accept |format|.
+ static bool IsMediaFormatSupported(const media::MediaFormat* format);
+
protected:
virtual ~VideoRendererImpl();
private:
+ WebMediaPlayerDelegateImpl* delegate_;
+
DISALLOW_COPY_AND_ASSIGN(VideoRendererImpl);
};
diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc
index 24ec3cf..932e042 100644
--- a/chrome/renderer/render_view.cc
+++ b/chrome/renderer/render_view.cc
@@ -1927,7 +1927,7 @@ WebPluginDelegate* RenderView::CreatePluginDelegate(
}
webkit_glue::WebMediaPlayerDelegate* RenderView::CreateMediaPlayerDelegate() {
- return new WebMediaPlayerDelegateImpl();
+ return new WebMediaPlayerDelegateImpl(this);
}
void RenderView::OnMissingPluginStatus(WebPluginDelegate* delegate,
diff --git a/chrome/renderer/webmediaplayer_delegate_impl.cc b/chrome/renderer/webmediaplayer_delegate_impl.cc
index 516a9c9..4eb3317 100644
--- a/chrome/renderer/webmediaplayer_delegate_impl.cc
+++ b/chrome/renderer/webmediaplayer_delegate_impl.cc
@@ -5,131 +5,337 @@
#include "chrome/renderer/media/audio_renderer_impl.h"
#include "chrome/renderer/media/data_source_impl.h"
#include "chrome/renderer/media/video_renderer_impl.h"
+#include "chrome/renderer/render_view.h"
#include "chrome/renderer/webmediaplayer_delegate_impl.h"
+#include "googleurl/src/gurl.h"
-WebMediaPlayerDelegateImpl::WebMediaPlayerDelegateImpl()
- : bytes_loaded_(0),
- current_time_(0.0f),
- data_rate_(0),
- duration_(0.0f),
- height_(0),
- network_state_(webkit_glue::WebMediaPlayer::EMPTY),
- paused_(true),
- playback_rate_(0.0f),
+/////////////////////////////////////////////////////////////////////////////
+// Task to be posted on main thread that fire WebMediaPlayer methods.
+
+class NotifyWebMediaPlayerTask : public CancelableTask {
+ public:
+ NotifyWebMediaPlayerTask(webkit_glue::WebMediaPlayer* web_media_player_,
+ WebMediaPlayerMethod method)
+ : method_(method) {}
+
+ virtual void Run() {
+ if (web_media_player_) {
+ (web_media_player_->*(method_))();
+ }
+ }
+
+ virtual void Cancel() {
+ web_media_player_ = NULL;
+ }
+
+ private:
+ webkit_glue::WebMediaPlayer* web_media_player_;
+ WebMediaPlayerMethod method_;
+
+ DISALLOW_COPY_AND_ASSIGN(NotifyWebMediaPlayerTask);
+};
+
+/////////////////////////////////////////////////////////////////////////////
+// WebMediaPlayerDelegateImpl implementation
+
+WebMediaPlayerDelegateImpl::WebMediaPlayerDelegateImpl(RenderView* render_view)
+ : network_state_(webkit_glue::WebMediaPlayer::EMPTY),
ready_state_(webkit_glue::WebMediaPlayer::DATA_UNAVAILABLE),
- seeking_(false),
- total_bytes_(0),
- video_(false),
- visible_(false),
- volume_(0.0f),
+ main_loop_(NULL),
+ filter_factory_(new media::FilterFactoryCollection()),
web_media_player_(NULL),
- width_(0) {
- // TODO(hclam): initialize the media player here
-
- // TODO(scherkus): remove these when actually in use -- right now I declare
- // these to force compiler/linker errors to reveal themselves.
- scoped_refptr<AudioRendererImpl> audio_renderer;
- audio_renderer = new AudioRendererImpl();
- scoped_refptr<DataSourceImpl> data_source;
- data_source = new DataSourceImpl();
- scoped_refptr<VideoRendererImpl> video_renderer;
- video_renderer = new VideoRendererImpl();
+ render_view_(render_view),
+ tasks_(kLastTaskIndex) {
+ // TODO(hclam): Add filter factory for demuxer and decoders.
+ filter_factory_->AddFactory(AudioRendererImpl::CreateFactory(this));
+ filter_factory_->AddFactory(VideoRendererImpl::CreateFactory(this));
+ filter_factory_->AddFactory(DataSourceImpl::CreateFactory(this));
}
WebMediaPlayerDelegateImpl::~WebMediaPlayerDelegateImpl() {
- // TODO(hclam): do the following things here:
- // 1. Destroy the internal media player
- // 2. Destroy the associated WebMediaPlayer
+ // Stop the pipeline in the first place so we won't receive any more method
+ // calls from it.
+ pipeline_.Stop();
+
+ // Cancel all tasks posted on the main_loop_.
+ CancelAllTasks();
+
+ // After cancelling all tasks, we are sure there will be no calls to
+ // web_media_player_, so we are safe to delete it.
+ if (web_media_player_) {
+ delete web_media_player_;
+ }
+
+ // Finally tell the main_loop_ we don't want to be notified of destruction
+ // event.
+ if (main_loop_) {
+ main_loop_->RemoveDestructionObserver(this);
+ }
}
void WebMediaPlayerDelegateImpl::Initialize(
webkit_glue::WebMediaPlayer* media_player) {
+ DCHECK(!web_media_player_);
web_media_player_ = media_player;
+
+ // Saves the current message loop.
+ DCHECK(!main_loop_);
+ main_loop_ = MessageLoop::current();
+
+ // Also we want to be notified of main_loop_ destruction.
+ main_loop_->AddDestructionObserver(this);
}
void WebMediaPlayerDelegateImpl::Load(const GURL& url) {
+ DCHECK(main_loop_ && MessageLoop::current() == main_loop_);
+
+ // Initialize the pipeline
+ pipeline_.Start(filter_factory_.get(), url.spec(),
+ NewCallback(this, &WebMediaPlayerDelegateImpl::DidInitializePipeline));
+
+ // TODO(hclam): Calls to render_view_ to kick start a resource load.
}
void WebMediaPlayerDelegateImpl::CancelLoad() {
- // TODO(hclam): delegate to google's media player
+ DCHECK(main_loop_ && MessageLoop::current() == main_loop_);
+
+ // TODO(hclam): Calls to render_view_ to stop resource load
}
void WebMediaPlayerDelegateImpl::Play() {
- // TODO(hclam): delegate to google's media player
+ DCHECK(main_loop_ && MessageLoop::current() == main_loop_);
+
+ // TODO(hclam): We should restore the previous playback rate rather than
+ // having it at 1.0.
+ pipeline_.SetPlaybackRate(1.0f);
}
void WebMediaPlayerDelegateImpl::Pause() {
- // TODO(hclam): delegate to google's media player
+ DCHECK(main_loop_ && MessageLoop::current() == main_loop_);
+
+ pipeline_.SetPlaybackRate(0.0f);
}
void WebMediaPlayerDelegateImpl::Stop() {
- // TODO(hclam): delegate to google's media player
+ DCHECK(main_loop_ && MessageLoop::current() == main_loop_);
+
+ // We can fire Stop() multiple times.
+ pipeline_.Stop();
}
void WebMediaPlayerDelegateImpl::Seek(float time) {
- // TODO(hclam): delegate to google's media player
+ DCHECK(main_loop_ && MessageLoop::current() == main_loop_);
+
+ pipeline_.Seek(base::TimeDelta::FromMilliseconds(static_cast<int64>(time)));
}
void WebMediaPlayerDelegateImpl::SetEndTime(float time) {
- // TODO(hclam): delegate to google's media player
+ DCHECK(main_loop_ && MessageLoop::current() == main_loop_);
+
+ // TODO(hclam): add method call when it has been implemented.
+ return;
}
-
+
void WebMediaPlayerDelegateImpl::SetPlaybackRate(float rate) {
- // TODO(hclam): delegate to google's media player
+ DCHECK(main_loop_ && MessageLoop::current() == main_loop_);
+
+ pipeline_.SetPlaybackRate(rate);
}
void WebMediaPlayerDelegateImpl::SetVolume(float volume) {
- // TODO(hclam): delegate to google's media player
+ DCHECK(main_loop_ && MessageLoop::current() == main_loop_);
+
+ pipeline_.SetVolume(volume);
}
void WebMediaPlayerDelegateImpl::SetVisible(bool visible) {
- // TODO(hclam): delegate to google's media player
+ DCHECK(main_loop_ && MessageLoop::current() == main_loop_);
+
+ // TODO(hclam): add appropriate method call when pipeline has it implemented.
+ return;
}
-
+
bool WebMediaPlayerDelegateImpl::IsTotalBytesKnown() {
- // TODO(hclam): delegate to google's media player
+ DCHECK(main_loop_ && MessageLoop::current() == main_loop_);
+
+ return pipeline_.GetTotalBytes() != 0;
+}
+
+bool WebMediaPlayerDelegateImpl::IsVideo() const {
+ DCHECK(main_loop_ && MessageLoop::current() == main_loop_);
+
+ size_t width, height;
+ pipeline_.GetVideoSize(&width, &height);
+ return width != 0 && height != 0;
+}
+
+size_t WebMediaPlayerDelegateImpl::GetWidth() const {
+ DCHECK(main_loop_ && MessageLoop::current() == main_loop_);
+
+ size_t width, height;
+ pipeline_.GetVideoSize(&width, &height);
+ return width;
+}
+
+size_t WebMediaPlayerDelegateImpl::GetHeight() const {
+ DCHECK(main_loop_ && MessageLoop::current() == main_loop_);
+
+ size_t width, height;
+ pipeline_.GetVideoSize(&width, &height);
+ return height;
+}
+
+bool WebMediaPlayerDelegateImpl::IsPaused() const {
+ DCHECK(main_loop_ && MessageLoop::current() == main_loop_);
+
+ return pipeline_.GetPlaybackRate() == 0.0f;
+}
+
+bool WebMediaPlayerDelegateImpl::IsSeeking() const {
+ DCHECK(main_loop_ && MessageLoop::current() == main_loop_);
+
+ // TODO(hclam): Add this method call if pipeline has it in the interface.
return false;
}
+float WebMediaPlayerDelegateImpl::GetDuration() const {
+ DCHECK(main_loop_ && MessageLoop::current() == main_loop_);
+
+ return static_cast<float>(pipeline_.GetDuration().InSecondsF());
+}
+
+float WebMediaPlayerDelegateImpl::GetCurrentTime() const {
+ DCHECK(main_loop_ && MessageLoop::current() == main_loop_);
+
+ return static_cast<float>(pipeline_.GetTime().InSecondsF());
+}
+
+
+float WebMediaPlayerDelegateImpl::GetPlayBackRate() const {
+ DCHECK(main_loop_ && MessageLoop::current() == main_loop_);
+
+ return pipeline_.GetPlaybackRate();
+}
+
+float WebMediaPlayerDelegateImpl::GetVolume() const {
+ DCHECK(main_loop_ && MessageLoop::current() == main_loop_);
+
+ return pipeline_.GetVolume();
+}
+
+int WebMediaPlayerDelegateImpl::GetDataRate() const {
+ DCHECK(main_loop_ && MessageLoop::current() == main_loop_);
+
+ // TODO(hclam): Add this method call if pipeline has it in the interface.
+ return 0;
+}
+
float WebMediaPlayerDelegateImpl::GetMaxTimeBuffered() const {
- // TODO(hclam): delegate to google's media player
- return 0.0f;
+ DCHECK(main_loop_ && MessageLoop::current() == main_loop_);
+
+ return static_cast<float>(pipeline_.GetBufferedTime().InSecondsF());
}
float WebMediaPlayerDelegateImpl::GetMaxTimeSeekable() const {
- // TODO(hclam): delegate to google's media player
+ DCHECK(main_loop_ && MessageLoop::current() == main_loop_);
+
+ // TODO(hclam): add this method when pipeline has this method implemented.
return 0.0f;
}
+int64 WebMediaPlayerDelegateImpl::GetBytesLoaded() const {
+ DCHECK(main_loop_ && MessageLoop::current() == main_loop_);
+
+ return pipeline_.GetBufferedBytes();
+}
+
+int64 WebMediaPlayerDelegateImpl::GetTotalBytes() const {
+ DCHECK(main_loop_ && MessageLoop::current() == main_loop_);
+
+ return pipeline_.GetTotalBytes();
+}
+
void WebMediaPlayerDelegateImpl::SetRect(const gfx::Rect& rect) {
- // TODO(hclam): Figure out what to do here..
+ DCHECK(main_loop_ && MessageLoop::current() == main_loop_);
+
+ if (video_renderer_) {
+ video_renderer_->SetRect(rect);
+ }
}
void WebMediaPlayerDelegateImpl::Paint(skia::PlatformCanvas *canvas,
const gfx::Rect& rect) {
- // TODO(hclam): grab a frame from the internal player and draw it.
+ if (video_renderer_) {
+ video_renderer_->Paint(canvas, rect);
+ }
}
-void WebMediaPlayerDelegateImpl::WillSendRequest(WebRequest& request,
- const WebResponse& response) {
- // TODO(hclam): do we need to change the request?
+void WebMediaPlayerDelegateImpl::WillDestroyCurrentMessageLoop() {
+ // Stop the pipeline when the main thread is being destroyed so we won't be
+ // posting any more messages onto it. And we just let this obejct and
+ // associated WebMediaPlayer to leak.
+ pipeline_.Stop();
}
-void WebMediaPlayerDelegateImpl::DidReceiveResponse(
- const WebResponse& response) {
- // TODO(hclam): tell the video piepline to prepare for arriving bytes.
+void WebMediaPlayerDelegateImpl::DidInitializePipeline(bool successful) {
+ if (successful) {
+ // Since we have initialized the pipeline, we should be able to play it.
+ // And we skip LOADED_METADATA state and starting with LOADED_FIRST_FRAME.
+ ready_state_ = webkit_glue::WebMediaPlayer::CAN_PLAY;
+ network_state_ = webkit_glue::WebMediaPlayer::LOADED_FIRST_FRAME;
+ } else {
+ // TODO(hclam): should use pipeline_.GetError() to determine the state
+ // properly and reports error using MediaError.
+ ready_state_ = webkit_glue::WebMediaPlayer::DATA_UNAVAILABLE;
+ network_state_ = webkit_glue::WebMediaPlayer::LOAD_FAILED;
+ }
+
+ PostTask(kNetworkStateTaskIndex,
+ &webkit_glue::WebMediaPlayer::NotifyNetworkStateChange);
+ PostTask(kReadyStateTaskIndex,
+ &webkit_glue::WebMediaPlayer::NotifyReadyStateChange);
}
-void WebMediaPlayerDelegateImpl::DidReceiveData(const char* buf, size_t size) {
- // TODO(hclam): direct the data to video pipeline's data source
+void WebMediaPlayerDelegateImpl::SetVideoRenderer(
+ VideoRendererImpl* video_renderer) {
+ DCHECK(!video_renderer_);
+ video_renderer_ = video_renderer;
}
-void WebMediaPlayerDelegateImpl::DidFinishLoading() {
- // TODO(hclam): do appropriate actions related to load. We should wait
- // for video pipeline to be initialized and fire a LOADED event.
+void WebMediaPlayerDelegateImpl::DidTask(CancelableTask* task) {
+ AutoLock auto_lock(task_lock_);
+
+ for (size_t i = 0; i < tasks_.size(); ++i) {
+ if (tasks_[i] == task) {
+ tasks_[i] = NULL;
+ return;
+ }
+ }
+ NOTREACHED();
+}
+
+void WebMediaPlayerDelegateImpl::CancelAllTasks() {
+ AutoLock auto_lock(task_lock_);
+ // Loop through the list of tasks and cancel tasks that are still alive.
+ for (size_t i = 0; i < tasks_.size(); ++i) {
+ if (tasks_[i])
+ tasks_[i]->Cancel();
+ }
+}
+
+void WebMediaPlayerDelegateImpl::PostTask(int index,
+ WebMediaPlayerMethod method) {
+ DCHECK(main_loop_);
+
+ AutoLock auto_lock(task_lock_);
+ if(!tasks_[index]) {
+ CancelableTask* task = new NotifyWebMediaPlayerTask(web_media_player_,
+ method);
+ tasks_[index] = task;
+ main_loop_->PostTask(FROM_HERE, task);
+ }
}
-void WebMediaPlayerDelegateImpl::DidFail(const WebError& error) {
- // Simply fires a LOAD_FAILED event.
- // TODO(hclam): will also need to fire a MediaError event.
+void WebMediaPlayerDelegateImpl::PostRepaintTask() {
+ PostTask(kRepaintTaskIndex, &webkit_glue::WebMediaPlayer::Repaint);
}
diff --git a/chrome/renderer/webmediaplayer_delegate_impl.h b/chrome/renderer/webmediaplayer_delegate_impl.h
index 8da1889..7e62b16 100644
--- a/chrome/renderer/webmediaplayer_delegate_impl.h
+++ b/chrome/renderer/webmediaplayer_delegate_impl.h
@@ -3,25 +3,67 @@
// LICENSE file.
//
// Delegate calls from WebCore::MediaPlayerPrivate to google's video player.
-// It is a friend of VideoStackMediaPlayer, which is the actual media player
-// VideoStackMediaPlayer will use WebMediaPlayer to create a resource loader
-// and bridges the WebCore::ResourceHandle and media::DataSource, so that
-// VideoStackMediaPlayer would have no knowledge of WebCore::ResourceHandle.
+// It contains PipelineImpl which is the actual media player pipeline, it glues
+// the media player pipeline, data source, audio renderer and renderer.
+// PipelineImpl would creates multiple threads and access some public methods
+// of this class, so we need to be extra careful about concurrent access of
+// methods and members.
+//
+// Properties that are shared by main thread and media threads:
+// CancelableTaskList tasks_;
+// ^--- This property is shared for keeping records of the tasks posted to
+// make sure there will be only one task for each task type that can
+// exist in the main thread.
+//
+// Methods that are accessed in media threads:
+// SetVideoRenderer()
+// ^--- Called during the initialization of the pipeline, essentially from the
+// the pipeline thread.
+// PostRepaintTask()
+// ^--- Called from the video renderer thread to notify a video frame has
+// been prepared.
+// PostTask()
+// ^--- A method that helps posting tasks to the main thread, it is
+// accessed from main thread and media threads, it access the |tasks_|
+// internally. Needs locking inside to avoid concurrent access to
+// |tasks_|.
+//
+//
+// Other issues:
+// During tear down of the whole browser or a tab, the DOM tree may not be
+// destructed nicely, and there will be some dangling media threads trying to
+// the main thread, so we need this class to listen to destruction event of the
+// main thread and cleanup the media threads when the even is received. Also
+// at destruction of this class we will need to unhook it from destruction event
+// list of the main thread.
#ifndef CHROME_RENDERER_WEBMEDIAPLAYER_DELEGATE_IMPL_H_
#define CHROME_RENDERER_WEBMEDIAPLAYER_DELEGATE_IMPL_H_
+#include <vector>
+
+#include "base/lock.h"
+#include "base/message_loop.h"
+#include "media/base/factory.h"
+#include "media/base/filters.h"
+#include "media/base/pipeline_impl.h"
#include "webkit/glue/webmediaplayer_delegate.h"
-namespace media {
-class VideoStackMediaPlayer;
-}
+class RenderView;
+class VideoRendererImpl;
+
+// This typedef is used for WebMediaPlayerDelegateImpl::PostTask() and
+// NotifyWebMediaPlayerTask in the source file.
+typedef void (webkit_glue::WebMediaPlayer::*WebMediaPlayerMethod)();
-class WebMediaPlayerDelegateImpl : public webkit_glue::WebMediaPlayerDelegate {
+class WebMediaPlayerDelegateImpl : public webkit_glue::WebMediaPlayerDelegate,
+ public MessageLoop::DestructionObserver {
public:
- WebMediaPlayerDelegateImpl();
+ explicit WebMediaPlayerDelegateImpl(RenderView* render_view);
virtual ~WebMediaPlayerDelegateImpl();
+ // Implementations of WebMediaPlayerDelegate, theses following methods are
+ // called from the WebKit, essentially lives inside the main thread.
virtual void Initialize(webkit_glue::WebMediaPlayer* media_player);
virtual void Load(const GURL& url);
@@ -44,26 +86,28 @@ class WebMediaPlayerDelegateImpl : public webkit_glue::WebMediaPlayerDelegate {
virtual void Paint(skia::PlatformCanvas *canvas, const gfx::Rect& rect);
// True if a video is loaded.
- virtual bool IsVideo() const { return video_; }
+ virtual bool IsVideo() const;
// Dimension of the video.
- virtual size_t GetWidth() const { return width_; }
- virtual size_t GetHeight() const { return height_; }
-
- // Getters fo playback state.
- virtual bool IsPaused() const { return paused_; }
- virtual bool IsSeeking() const { return seeking_; }
- virtual float GetDuration() const { return duration_; }
- virtual float GetCurrentTime() const { return current_time_; }
- virtual float GetPlayBackRate() const { return playback_rate_; }
- virtual float GetVolume() const { return volume_; }
+ virtual size_t GetWidth() const;
+ virtual size_t GetHeight() const;
+
+ // Getters of playback state.
+ virtual bool IsPaused() const;
+ virtual bool IsSeeking() const;
+ virtual float GetDuration() const;
+ virtual float GetCurrentTime() const;
+ virtual float GetPlayBackRate() const;
+ virtual float GetVolume() const;
virtual float GetMaxTimeBuffered() const;
virtual float GetMaxTimeSeekable() const;
// Get rate of loading the resource.
- virtual int32 GetDataRate() const { return data_rate_; }
+ virtual int32 GetDataRate() const;
// Internal states of loading and network.
+ // TODO(hclam): Ask the pipeline about the state rather than having reading
+ // them from members which would cause race conditions.
virtual webkit_glue::WebMediaPlayer::NetworkState GetNetworkState() const {
return network_state_;
}
@@ -71,38 +115,75 @@ class WebMediaPlayerDelegateImpl : public webkit_glue::WebMediaPlayerDelegate {
return ready_state_;
}
- virtual int64 GetBytesLoaded() const { return bytes_loaded_; }
- virtual int64 GetTotalBytes() const { return total_bytes_; }
+ virtual int64 GetBytesLoaded() const;
+ virtual int64 GetTotalBytes() const;
- // Data handlers.
- virtual void WillSendRequest(WebRequest& request,
- const WebResponse& response);
- virtual void DidReceiveResponse(const WebResponse& response);
- virtual void DidReceiveData(const char* buf, size_t size);
- virtual void DidFinishLoading();
- virtual void DidFail(const WebError& error);
+ // As we are closing the tab or even the browser, main_loop_ is destroyed
+ // even before this object gets destructed, so we need to know when
+ // main_loop_ is being destroyed and we can stop posting repaint task
+ // to it.
+ virtual void WillDestroyCurrentMessageLoop();
+
+ // Callbacks.
+ void DidInitializePipeline(bool successful);
// Inline getters.
webkit_glue::WebMediaPlayer* web_media_player() { return web_media_player_; }
+ // Called from tasks posted to main_loop_ from this object to remove
+ // reference of them.
+ void DidTask(CancelableTask* task);
+
+ // Public methods to be called from renderers and data source.
+ void SetVideoRenderer(VideoRendererImpl* video_renderer);
+
+ // Called from VideoRenderer to fire a repaint task to main_loop_.
+ void PostRepaintTask();
+
private:
- int64 bytes_loaded_;
- float current_time_;
- int32 data_rate_;
- float duration_;
- size_t height_;
+ // Methods for posting tasks and cancelling tasks. This method may lives in
+ // the main thread or the media threads.
+ void PostTask(int index, WebMediaPlayerMethod method);
+
+ // Cancel all tasks currently lives in |main_loop_|.
+ void CancelAllTasks();
+
+ // Indexes for tasks.
+ enum {
+ kRepaintTaskIndex = 0,
+ kReadyStateTaskIndex,
+ kNetworkStateTaskIndex,
+ kLastTaskIndex
+ };
+
+ // TODO(hclam): get rid of these members and read from the pipeline directly.
webkit_glue::WebMediaPlayer::NetworkState network_state_;
- bool paused_;
- float playback_rate_;
webkit_glue::WebMediaPlayer::ReadyState ready_state_;
- bool seeking_;
- int64 total_bytes_;
- bool video_;
- media::VideoStackMediaPlayer* video_stack_media_player_;
- bool visible_;
- float volume_;
+
+ // Message loops for posting tasks between Chrome's main thread. Also used
+ // for DCHECKs so methods calls won't execute in the wrong thread.
+ MessageLoop* main_loop_;
+
+ // A collection of factories for creating filters.
+ scoped_refptr<media::FilterFactoryCollection> filter_factory_;
+
+ // The actual pipeline. We do it a composition here because we expect to have
+ // the same lifetime as the pipeline.
+ media::PipelineImpl pipeline_;
+
+ // We have the interface to VideoRenderer to delegate paint messages to it
+ // from WebKit.
+ VideoRendererImpl* video_renderer_;
+
webkit_glue::WebMediaPlayer* web_media_player_;
- size_t width_;
+ RenderView* render_view_;
+
+ // List of tasks for holding pointers to all tasks currently in the
+ // |main_loop_|. |tasks_| can be access from main thread or the media threads
+ // we need a lock for protecting it.
+ Lock task_lock_;
+ typedef std::vector<CancelableTask*> CancelableTaskList;
+ CancelableTaskList tasks_;
DISALLOW_COPY_AND_ASSIGN(WebMediaPlayerDelegateImpl);
};
diff --git a/media/base/pipeline_impl.h b/media/base/pipeline_impl.h
index 764caac..bf0a756d 100644
--- a/media/base/pipeline_impl.h
+++ b/media/base/pipeline_impl.h
@@ -29,7 +29,7 @@ class PipelineThread;
class PipelineImpl : public Pipeline {
public:
PipelineImpl();
- ~PipelineImpl();
+ virtual ~PipelineImpl();
// Implementation of PipelineStatus methods.
virtual bool IsInitialized() const;
diff --git a/webkit/glue/webmediaplayer.h b/webkit/glue/webmediaplayer.h
index f8e5a94..b786c7e 100644
--- a/webkit/glue/webmediaplayer.h
+++ b/webkit/glue/webmediaplayer.h
@@ -40,7 +40,7 @@ public:
virtual WebFrame* GetWebFrame() = 0;
// Notify the media player about network state change.
- virtual void NotifynetworkStateChange() = 0;
+ virtual void NotifyNetworkStateChange() = 0;
// Notify the media player about ready state change.
virtual void NotifyReadyStateChange() = 0;
@@ -54,16 +54,10 @@ public:
// Tell the media player to repaint itself.
virtual void Repaint() = 0;
- // Load a media resource.
- virtual void LoadMediaResource(const GURL& url) = 0;
-
- // Cancel loading the media resource.
- virtual void CancelLoad() = 0;
-
-private:
+ private:
DISALLOW_COPY_AND_ASSIGN(WebMediaPlayer);
};
} // namespace webkit_glue
-#endif // ifndef WEBKIT_GLUE_WEBMEDIAPLAYER_H_
+#endif // WEBKIT_GLUE_WEBMEDIAPLAYER_H_
diff --git a/webkit/glue/webmediaplayer_delegate.h b/webkit/glue/webmediaplayer_delegate.h
index 3414114..1f4d695 100644
--- a/webkit/glue/webmediaplayer_delegate.h
+++ b/webkit/glue/webmediaplayer_delegate.h
@@ -74,18 +74,10 @@ class WebMediaPlayerDelegate {
virtual int64 GetBytesLoaded() const = 0;
virtual int64 GetTotalBytes() const = 0;
- // Data handlers called from WebMediaPlayer
- virtual void WillSendRequest(WebRequest& request,
- const WebResponse& response) = 0;
- virtual void DidReceiveData(const char* buf, size_t size) = 0;
- virtual void DidReceiveResponse(const WebResponse& response) = 0;
- virtual void DidFinishLoading() = 0;
- virtual void DidFail(const WebError& error) = 0;
-
private:
DISALLOW_COPY_AND_ASSIGN(WebMediaPlayerDelegate);
};
} // namespace webkit_glue
-#endif // ifndef WEBKIT_GLUE_WEBMEDIAPLAYER_DELEGATE_H_
+#endif // WEBKIT_GLUE_WEBMEDIAPLAYER_DELEGATE_H_
diff --git a/webkit/glue/webmediaplayer_impl.cc b/webkit/glue/webmediaplayer_impl.cc
index 2c9fea3..e262ec4 100644
--- a/webkit/glue/webmediaplayer_impl.cc
+++ b/webkit/glue/webmediaplayer_impl.cc
@@ -37,7 +37,7 @@ void WebMediaPlayerImpl::Initialize(WebMediaPlayerDelegate* delegate){
}
WebFrame* WebMediaPlayerImpl::GetWebFrame() {
- if (media_player_private_->frameView()->frame()) {
+ if (media_player_private_ && media_player_private_->frameView()->frame()) {
return WebFrameImpl::FromFrame(
media_player_private_->frameView()->frame());
} else {
@@ -45,93 +45,31 @@ WebFrame* WebMediaPlayerImpl::GetWebFrame() {
}
}
-void WebMediaPlayerImpl::NotifynetworkStateChange() {
- media_player_private_->networkStateChanged();
+void WebMediaPlayerImpl::NotifyNetworkStateChange() {
+ if (media_player_private_)
+ media_player_private_->networkStateChanged();
}
void WebMediaPlayerImpl::NotifyReadyStateChange() {
- media_player_private_->readyStateChanged();
+ if (media_player_private_)
+ media_player_private_->readyStateChanged();
}
void WebMediaPlayerImpl::NotifyTimeChange() {
- media_player_private_->timeChanged();
+ if (media_player_private_)
+ media_player_private_->timeChanged();
}
void WebMediaPlayerImpl::NotifyVolumeChange() {
- media_player_private_->volumeChanged();
+ if (media_player_private_)
+ media_player_private_->volumeChanged();
}
void WebMediaPlayerImpl::Repaint() {
- media_player_private_->repaint();
-}
-
-void WebMediaPlayerImpl::LoadMediaResource(const GURL& url) {
- // Make sure we cancel the previous load request before starting a new one.
- CancelLoad();
-
- WebCore::Frame* frame = static_cast<WebFrameImpl*>(GetWebFrame())->frame();
- WebCore::ResourceRequest request(webkit_glue::GURLToKURL(url),
- WebCore::String(""),
- WebCore::UseProtocolCachePolicy);
- request.setTargetType(WebCore::ResourceRequest::TargetIsMedia);
- request.setFrame(frame);
-
- resource_handle_ = WebCore::ResourceHandle::create(request,
- this,
- frame,
- false,
- true);
-}
-
-void WebMediaPlayerImpl::CancelLoad() {
- // Delegate the cancel call to ResourceHandle, this should be enough to
- // stop any further callbacks from ResouceHandle.
- if (resource_handle_) {
- resource_handle_->cancel();
- resource_handle_ = NULL;
- }
-}
-
-void WebMediaPlayerImpl::willSendRequest(
- WebCore::ResourceHandle* handle,
- WebCore::ResourceRequest& request,
- const WebCore::ResourceResponse& response) {
- if (delegate_) {
- delegate_->WillSendRequest(WebRequestImpl(request),
- WebResponseImpl(response));
- }
-}
-
-void WebMediaPlayerImpl::didReceiveResponse(
- WebCore::ResourceHandle* handle,
- const WebCore::ResourceResponse& response) {
- if (delegate_) {
- delegate_->DidReceiveResponse(WebResponseImpl(response));
- }
-}
-
-void WebMediaPlayerImpl::didReceiveData(WebCore::ResourceHandle* handle,
- const char *buffer,
- int length,
- int bytes_received) {
- if (delegate_) {
- delegate_->DidReceiveData(buffer, length);
- }
-}
-
-void WebMediaPlayerImpl::didFinishLoading(WebCore::ResourceHandle* handle) {
- if (delegate_) {
- delegate_->DidFinishLoading();
- }
-}
-
-void WebMediaPlayerImpl::didFail(WebCore::ResourceHandle* handle,
- const WebCore::ResourceError& error) {
- if (delegate_) {
- delegate_->DidFail(WebErrorImpl(error));
- }
+ if (media_player_private_)
+ media_player_private_->repaint();
}
} // namespace webkit_glue
-#endif
+#endif // ENABLE(VIDEO)
diff --git a/webkit/glue/webmediaplayer_impl.h b/webkit/glue/webmediaplayer_impl.h
index ddbdc16..0f9e53e 100644
--- a/webkit/glue/webmediaplayer_impl.h
+++ b/webkit/glue/webmediaplayer_impl.h
@@ -8,8 +8,6 @@
#ifndef WEBKIT_GLUE_WEBMEDIAPLAYER_IMPL_H_
#define WEBKIT_GLUE_WEBMEDIAPLAYER_IMPL_H_
-#include "ResourceHandleClient.h"
-
#include "webkit/glue/webmediaplayer.h"
#if ENABLE(VIDEO)
@@ -23,10 +21,10 @@ namespace webkit_glue {
class WebMediaPlayerDelegate;
-class WebMediaPlayerImpl : public WebMediaPlayer,
- WebCore::ResourceHandleClient {
-public:
- WebMediaPlayerImpl(WebCore::MediaPlayerPrivate* media_player_private);
+class WebMediaPlayerImpl : public WebMediaPlayer {
+ public:
+ explicit WebMediaPlayerImpl(
+ WebCore::MediaPlayerPrivate* media_player_private);
virtual ~WebMediaPlayerImpl();
@@ -36,7 +34,7 @@ public:
virtual WebFrame* GetWebFrame();
// Notify the media player about network state change.
- virtual void NotifynetworkStateChange();
+ virtual void NotifyNetworkStateChange();
// Notify the media player about ready state change.
virtual void NotifyReadyStateChange();
@@ -50,33 +48,15 @@ public:
// Tell the media player to repaint itself.
virtual void Repaint();
- // Load a media resource.
- virtual void LoadMediaResource(const GURL& url);
-
- // Cancel loading the media resource.
- virtual void CancelLoad();
-
- // ResourceHandleClient methods
- void willSendRequest(WebCore::ResourceHandle* handle,
- WebCore::ResourceRequest& request,
- const WebCore::ResourceResponse&);
- void didReceiveResponse(WebCore::ResourceHandle* handle,
- const WebCore::ResourceResponse& response);
- void didReceiveData(WebCore::ResourceHandle* handle, const char *buffer,
- int length, int);
- void didFinishLoading(WebCore::ResourceHandle* handle);
- void didFail(WebCore::ResourceHandle* handle, const WebCore::ResourceError&);
-
-private:
+ private:
WebCore::MediaPlayerPrivate* media_player_private_;
WebMediaPlayerDelegate* delegate_;
- RefPtr<WebCore::ResourceHandle> resource_handle_;
DISALLOW_COPY_AND_ASSIGN(WebMediaPlayerImpl);
};
} // namespace webkit_glue
-#endif // ENABLE(VIDEO)
+#endif // ENABLE(VIDEO)
-#endif // ifndef WEBKIT_GLUE_WEBMEDIAPLAYER_H_
+#endif // WEBKIT_GLUE_WEBMEDIAPLAYER_H_