diff options
author | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-23 01:20:37 +0000 |
---|---|---|
committer | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-23 01:20:37 +0000 |
commit | 457d83467c00c236e806bb150796a2efdc88bfcf (patch) | |
tree | 36c58186b34d36300374b232fb79540457307b23 | |
parent | 77a397cc5cf8106e559aa87a5228478afc28cec1 (diff) | |
download | chromium_src-457d83467c00c236e806bb150796a2efdc88bfcf.zip chromium_src-457d83467c00c236e806bb150796a2efdc88bfcf.tar.gz chromium_src-457d83467c00c236e806bb150796a2efdc88bfcf.tar.bz2 |
Terminate FilterFactory and his nasty friends
FilterFactory, IsMediaFormatSupported and CreateFactory are the source
of evil. They also have have a gang of template functions. This patch
terminate them all and make the world a better place.
BUG=28207
TEST=<video> runs
Review URL: http://codereview.chromium.org/3878001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@63609 0039d316-1c4b-4281-b951-d872f2087c98
57 files changed, 579 insertions, 1421 deletions
diff --git a/chrome/renderer/media/audio_renderer_impl.cc b/chrome/renderer/media/audio_renderer_impl.cc index 2ce02ab..e5c2f0c 100644 --- a/chrome/renderer/media/audio_renderer_impl.cc +++ b/chrome/renderer/media/audio_renderer_impl.cc @@ -51,14 +51,6 @@ base::TimeDelta AudioRendererImpl::ConvertToDuration(int bytes) { return base::TimeDelta(); } -bool AudioRendererImpl::IsMediaFormatSupported( - const media::MediaFormat& media_format) { - int channels; - int sample_rate; - int sample_bits; - return ParseMediaFormat(media_format, &channels, &sample_rate, &sample_bits); -} - bool AudioRendererImpl::OnInitialize(const media::MediaFormat& media_format) { // Parse integer values in MediaFormat. if (!ParseMediaFormat(media_format, diff --git a/chrome/renderer/media/audio_renderer_impl.h b/chrome/renderer/media/audio_renderer_impl.h index 57fb8eb..5c27ef3 100644 --- a/chrome/renderer/media/audio_renderer_impl.h +++ b/chrome/renderer/media/audio_renderer_impl.h @@ -46,7 +46,6 @@ #include "chrome/renderer/audio_message_filter.h" #include "media/audio/audio_io.h" #include "media/audio/audio_manager.h" -#include "media/base/factory.h" #include "media/base/filters.h" #include "media/filters/audio_renderer_base.h" @@ -56,13 +55,9 @@ class AudioRendererImpl : public media::AudioRendererBase, public AudioMessageFilter::Delegate, public MessageLoop::DestructionObserver { public: - // Methods called on render thread ------------------------------------------ - // Methods called during construction. - static media::FilterFactory* CreateFactory(AudioMessageFilter* filter) { - return new media::FilterFactoryImpl1<AudioRendererImpl, - AudioMessageFilter*>(filter); - } - static bool IsMediaFormatSupported(const media::MediaFormat& format); + // Methods called on Render thread ------------------------------------------ + explicit AudioRendererImpl(AudioMessageFilter* filter); + virtual ~AudioRendererImpl(); // Methods called on IO thread ---------------------------------------------- // AudioMessageFilter::Delegate methods, called by AudioMessageFilter. @@ -94,18 +89,11 @@ class AudioRendererImpl : public media::AudioRendererBase, virtual void OnReadComplete(media::Buffer* buffer_in); private: - friend class media::FilterFactoryImpl1<AudioRendererImpl, - AudioMessageFilter*>; - // For access to constructor and IO thread methods. friend class AudioRendererImplTest; FRIEND_TEST_ALL_PREFIXES(AudioRendererImplTest, Stop); FRIEND_TEST_ALL_PREFIXES(AudioRendererImplTest, DestroyedMessageLoop_OnReadComplete); - - explicit AudioRendererImpl(AudioMessageFilter* filter); - virtual ~AudioRendererImpl(); - // Helper methods. // Convert number of bytes to duration of time using information about the // number of channels, sample rate and sample bits. diff --git a/chrome/renderer/media/ipc_video_decoder.cc b/chrome/renderer/media/ipc_video_decoder.cc index d06130e..12b262a 100644 --- a/chrome/renderer/media/ipc_video_decoder.cc +++ b/chrome/renderer/media/ipc_video_decoder.cc @@ -188,23 +188,3 @@ void IpcVideoDecoder::ConsumeVideoFrame( void IpcVideoDecoder::ProduceVideoSample(scoped_refptr<media::Buffer> buffer) { demuxer_stream_->Read(NewCallback(this, &IpcVideoDecoder::OnReadComplete)); } - -// static -media::FilterFactory* IpcVideoDecoder::CreateFactory( - MessageLoop* message_loop, ggl::Context* ggl_context) { - return new media::FilterFactoryImpl2< - IpcVideoDecoder, MessageLoop*, ggl::Context*>(message_loop, ggl_context); -} - -// static -bool IpcVideoDecoder::IsMediaFormatSupported(const media::MediaFormat& format) { - std::string mime_type; - if (!format.GetAsString(media::MediaFormat::kMimeType, &mime_type) && - media::mime_type::kFFmpegVideo != mime_type) - return false; - - // TODO(jiesun): Although we current only support H264 hardware decoding, - // in the future, we should query GpuVideoService for capabilities. - int codec_id; - return format.GetAsInteger(media::MediaFormat::kFFmpegCodecID, &codec_id); -} diff --git a/chrome/renderer/media/ipc_video_decoder.h b/chrome/renderer/media/ipc_video_decoder.h index c9d800d..c1f12fb 100644 --- a/chrome/renderer/media/ipc_video_decoder.h +++ b/chrome/renderer/media/ipc_video_decoder.h @@ -21,14 +21,9 @@ class Context; class IpcVideoDecoder : public media::VideoDecoder, public media::VideoDecodeEngine::EventHandler { public: - explicit IpcVideoDecoder(MessageLoop* message_loop, - ggl::Context* ggl_context); + IpcVideoDecoder(MessageLoop* message_loop, ggl::Context* ggl_context); virtual ~IpcVideoDecoder(); - static media::FilterFactory* CreateFactory(MessageLoop* message_loop, - ggl::Context* ggl_context); - static bool IsMediaFormatSupported(const media::MediaFormat& media_format); - // MediaFilter implementation. virtual void Stop(media::FilterCallback* callback); virtual void Seek(base::TimeDelta time, media::FilterCallback* callback); diff --git a/chrome/renderer/media/ipc_video_renderer.cc b/chrome/renderer/media/ipc_video_renderer.cc index d9a194d..fcf8c61 100644 --- a/chrome/renderer/media/ipc_video_renderer.cc +++ b/chrome/renderer/media/ipc_video_renderer.cc @@ -9,37 +9,15 @@ #include "media/base/video_frame.h" #include "media/base/media_format.h" -IPCVideoRenderer::IPCVideoRenderer( - webkit_glue::WebMediaPlayerImpl::Proxy* proxy, - int routing_id) - : proxy_(proxy), - created_(false), +IPCVideoRenderer::IPCVideoRenderer(int routing_id) + : created_(false), routing_id_(routing_id), stopped_(false, false) { - // TODO(hclam): decide whether to do the following line in this thread or - // in the render thread. - proxy->SetVideoRenderer(this); } IPCVideoRenderer::~IPCVideoRenderer() { } -// static -media::FilterFactory* IPCVideoRenderer::CreateFactory( - webkit_glue::WebMediaPlayerImpl::Proxy* proxy, - int routing_id) { - return new media::FilterFactoryImpl2< - IPCVideoRenderer, - webkit_glue::WebMediaPlayerImpl::Proxy*, - int>(proxy, routing_id); -} - -// static -bool IPCVideoRenderer::IsMediaFormatSupported( - const media::MediaFormat& media_format) { - return ParseMediaFormat(media_format, NULL, NULL, NULL, NULL); -} - bool IPCVideoRenderer::OnInitialize(media::VideoDecoder* decoder) { video_size_.SetSize(width(), height()); @@ -64,6 +42,11 @@ void IPCVideoRenderer::OnFrameAvailable() { NewRunnableMethod(this, &IPCVideoRenderer::DoUpdateVideo)); } +void IPCVideoRenderer::SetWebMediaPlayerImplProxy( + webkit_glue::WebMediaPlayerImpl::Proxy* proxy) { + proxy_ = proxy; +} + void IPCVideoRenderer::SetRect(const gfx::Rect& rect) { DCHECK(MessageLoop::current() == proxy_->message_loop()); diff --git a/chrome/renderer/media/ipc_video_renderer.h b/chrome/renderer/media/ipc_video_renderer.h index c934291..d032469 100644 --- a/chrome/renderer/media/ipc_video_renderer.h +++ b/chrome/renderer/media/ipc_video_renderer.h @@ -22,7 +22,12 @@ class IPCVideoRenderer : public webkit_glue::WebVideoRenderer { public: + explicit IPCVideoRenderer(int routing_id); + virtual ~IPCVideoRenderer(); + // WebVideoRenderer implementation. + virtual void SetWebMediaPlayerImplProxy( + webkit_glue::WebMediaPlayerImpl::Proxy* proxy); virtual void SetRect(const gfx::Rect& rect); virtual void Paint(skia::PlatformCanvas* canvas, const gfx::Rect& dest_rect); @@ -30,33 +35,6 @@ class IPCVideoRenderer : public webkit_glue::WebVideoRenderer { void OnUpdateVideoAck(); void OnDestroyVideo(); - // Static method for creating factory for this object. - static media::FilterFactory* CreateFactory( - webkit_glue::WebMediaPlayerImpl::Proxy* proxy, - int routing_id); - - // FilterFactoryImpl2 implementation. - static bool IsMediaFormatSupported(const media::MediaFormat& media_format); - - // TODO(scherkus): remove this mega-hack, see http://crbug.com/28207 - class FactoryFactory : public webkit_glue::WebVideoRendererFactoryFactory { - public: - explicit FactoryFactory(int routing_id) - : webkit_glue::WebVideoRendererFactoryFactory(), - routing_id_(routing_id) { - } - - virtual media::FilterFactory* CreateFactory( - webkit_glue::WebMediaPlayerImpl::Proxy* proxy) { - return IPCVideoRenderer::CreateFactory(proxy, routing_id_); - } - - private: - int routing_id_; - - DISALLOW_COPY_AND_ASSIGN(FactoryFactory); - }; - protected: // VideoRendererBase implementation. virtual bool OnInitialize(media::VideoDecoder* decoder); @@ -64,15 +42,6 @@ class IPCVideoRenderer : public webkit_glue::WebVideoRenderer { virtual void OnFrameAvailable(); private: - // Only the filter factories can create instances. - friend class media::FilterFactoryImpl2< - IPCVideoRenderer, - webkit_glue::WebMediaPlayerImpl::Proxy*, - int>; - IPCVideoRenderer(webkit_glue::WebMediaPlayerImpl::Proxy* proxy, - int routing_id); - virtual ~IPCVideoRenderer(); - // Send an IPC message to the browser process. The routing ID of the message // is assumed to match |routing_id_|. void Send(IPC::Message* msg); diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index 850800b..baac89a 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -2539,14 +2539,13 @@ WebSharedWorker* RenderView::createSharedWorker( WebMediaPlayer* RenderView::createMediaPlayer( WebFrame* frame, WebMediaPlayerClient* client) { - scoped_refptr<media::FilterFactoryCollection> factory = - new media::FilterFactoryCollection(); + media::MediaFilterCollection collection; + // Add in any custom filter factories first. const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); if (!cmd_line->HasSwitch(switches::kDisableAudio)) { // Add the chrome specific audio renderer. - factory->AddFactory( - AudioRendererImpl::CreateFactory(audio_message_filter())); + collection.push_back(new AudioRendererImpl(audio_message_filter())); } if (cmd_line->HasSwitch(switches::kEnableAcceleratedDecoding) && @@ -2557,7 +2556,7 @@ WebMediaPlayer* RenderView::createMediaPlayer( bool ret = frame->view()->graphicsContext3D()->makeContextCurrent(); CHECK(ret) << "Failed to switch context"; - factory->AddFactory(IpcVideoDecoder::CreateFactory( + collection.push_back(new IpcVideoDecoder( MessageLoop::current(), ggl::GetCurrentContext())); } @@ -2565,7 +2564,17 @@ WebMediaPlayer* RenderView::createMediaPlayer( WebApplicationCacheHostImpl::FromFrame(frame); // TODO(hclam): obtain the following parameters from |client|. - webkit_glue::MediaResourceLoaderBridgeFactory* bridge_factory = + // Create two bridge factory for two data sources. + webkit_glue::MediaResourceLoaderBridgeFactory* bridge_factory_simple = + new webkit_glue::MediaResourceLoaderBridgeFactory( + GURL(frame->url()), // referrer + "null", // frame origin + "null", // main_frame_origin + base::GetCurrentProcId(), + appcache_host ? appcache_host->host_id() : appcache::kNoHostId, + routing_id()); + + webkit_glue::MediaResourceLoaderBridgeFactory* bridge_factory_buffered = new webkit_glue::MediaResourceLoaderBridgeFactory( GURL(frame->url()), // referrer "null", // frame origin @@ -2574,18 +2583,23 @@ WebMediaPlayer* RenderView::createMediaPlayer( appcache_host ? appcache_host->host_id() : appcache::kNoHostId, routing_id()); - webkit_glue::WebVideoRendererFactoryFactory* factory_factory = NULL; + scoped_refptr<webkit_glue::WebVideoRenderer> video_renderer; if (cmd_line->HasSwitch(switches::kEnableVideoLayering)) { - factory_factory = new IPCVideoRenderer::FactoryFactory(routing_id_); + scoped_refptr<IPCVideoRenderer> renderer = + new IPCVideoRenderer(routing_id_); + collection.push_back(renderer); + video_renderer = renderer; } else { bool pts_logging = cmd_line->HasSwitch(switches::kEnableVideoLogging); - factory_factory = - new webkit_glue::VideoRendererImpl::FactoryFactory(pts_logging); + scoped_refptr<webkit_glue::VideoRendererImpl> renderer = + new webkit_glue::VideoRendererImpl(pts_logging); + collection.push_back(renderer); + video_renderer = renderer; } return new webkit_glue::WebMediaPlayerImpl( - client, factory, bridge_factory, - cmd_line->HasSwitch(switches::kSimpleDataSource), factory_factory); + client, collection, bridge_factory_simple, bridge_factory_buffered, + cmd_line->HasSwitch(switches::kSimpleDataSource),video_renderer); } WebApplicationCacheHost* RenderView::createApplicationCacheHost( diff --git a/chrome/renderer/webmediaplayer_impl.h b/chrome/renderer/webmediaplayer_impl.h deleted file mode 100644 index fdaf652..0000000 --- a/chrome/renderer/webmediaplayer_impl.h +++ /dev/null @@ -1,203 +0,0 @@ -// Copyright (c) 2010 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. - -// Delegate calls from WebCore::MediaPlayerPrivate to Chrome's video player. -// 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: -// SetAudioRenderer() -// ^--- Called during the initialization of the pipeline, essentially from the -// the pipeline thread. -// 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_IMPL_H_ -#define CHROME_RENDERER_WEBMEDIAPLAYER_IMPL_H_ -#pragma once - -#include <vector> - -#include "base/lock.h" -#include "base/message_loop.h" -#include "media/base/filters.h" -#include "media/base/pipeline_impl.h" -#include "skia/ext/platform_canvas.h" -#include "third_party/WebKit/WebKit/chromium/public/WebMediaPlayer.h" -#include "third_party/WebKit/WebKit/chromium/public/WebMediaPlayerClient.h" - -class AudioRendererImpl; -class DataSourceImpl; -class GURL; -class RenderView; -class VideoRendererImpl; - -namespace media { -class FilterFactoryCollection; -} - -// This typedef is used for WebMediaPlayerImpl::PostTask() and -// NotifyWebMediaPlayerTask in the source file. -typedef void (WebKit::WebMediaPlayerClient::*WebMediaPlayerClientMethod)(); - -class WebMediaPlayerImpl : public WebKit::WebMediaPlayer, - public MessageLoop::DestructionObserver { - public: - WebMediaPlayerImpl(RenderView* view, WebKit::WebMediaPlayerClient* client); - virtual ~WebMediaPlayerImpl(); - - virtual void load(const WebKit::WebURL& url); - virtual void cancelLoad(); - - // Playback controls. - virtual void play(); - virtual void pause(); - virtual void stop(); - virtual void seek(float seconds); - virtual void setEndTime(float seconds); - virtual void setRate(float rate); - virtual void setVolume(float volume); - virtual void setVisible(bool visible); - virtual bool setAutoBuffer(bool autoBuffer); - virtual bool totalBytesKnown(); - virtual float maxTimeBuffered() const; - virtual float maxTimeSeekable() const; - - // Methods for painting. - virtual void setSize(const WebKit::WebSize& size); - - virtual void paint(WebKit::WebCanvas* canvas, const WebKit::WebRect& rect); - - // True if a video is loaded. - virtual bool hasVideo() const; - - // Dimensions of the video. - virtual WebKit::WebSize naturalSize() const; - - // Getters of playback state. - virtual bool paused() const; - virtual bool seeking() const; - virtual float duration() const; - virtual float currentTime() const; - - // Get rate of loading the resource. - virtual int32 dataRate() 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::WebMediaPlayer::NetworkState networkState() const { - return network_state_; - } - virtual WebKit::WebMediaPlayer::ReadyState readyState() const { - return ready_state_; - } - - virtual unsigned long long bytesLoaded() const; - virtual unsigned long long totalBytes() const; - - // 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(); - - // Notification from |pipeline_| when initialization has finished. - void OnPipelineInitialize(bool successful); - - // Notification from |pipeline_| when a seek has finished. - void OnPipelineSeek(bool successful); - - // 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 so that - // WebMediaPlayerImpl has references to them. - void SetVideoRenderer(VideoRendererImpl* video_renderer); - - // Called from VideoRenderer to fire a repaint task to |main_loop_|. - void PostRepaintTask(); - - // Inline getters. - WebKit::WebMediaPlayerClient* client() { return client_; } - RenderView* view() { return view_; } - - private: - // Methods for posting tasks and cancelling tasks. This method may lives in - // the main thread or the media threads. - void PostTask(int index, WebMediaPlayerClientMethod method); - - // Cancel all tasks currently live in |main_loop_|. - void CancelAllTasks(); - - // Indexes for tasks. - enum { - kRepaintTaskIndex = 0, - kReadyStateTaskIndex, - kNetworkStateTaskIndex, - kTimeChangedTaskIndex, - kLastTaskIndex - }; - - // TODO(hclam): get rid of these members and read from the pipeline directly. - WebKit::WebMediaPlayer::NetworkState network_state_; - WebKit::WebMediaPlayer::ReadyState ready_state_; - - // 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. - scoped_refptr<VideoRendererImpl> video_renderer_; - - WebKit::WebMediaPlayerClient* client_; - RenderView* 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(WebMediaPlayerImpl); -}; - -#endif // CHROME_RENDERER_WEBMEDIAPLAYER_IMPL_H_ diff --git a/media/base/factory.cc b/media/base/factory.cc deleted file mode 100644 index 685d1e7..0000000 --- a/media/base/factory.cc +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2010 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 "media/base/factory.h" - -namespace media { - -FilterFactory::FilterFactory() {} - -FilterFactory::~FilterFactory() {} - -FilterFactoryCollection::FilterFactoryCollection() {} - -void FilterFactoryCollection::AddFactory(FilterFactory* factory) { - factories_.push_back(factory); -} - -MediaFilter* FilterFactoryCollection::Create(FilterType filter_type, - const MediaFormat& media_format) { - MediaFilter* filter = NULL; - for (FactoryVector::iterator factory = factories_.begin(); - !filter && factory != factories_.end(); - ++factory) { - filter = (*factory)->Create(filter_type, media_format); - } - return filter; -} - -FilterFactoryCollection::~FilterFactoryCollection() {} - - -} // namespace media diff --git a/media/base/factory.h b/media/base/factory.h deleted file mode 100644 index d5dd9a7..0000000 --- a/media/base/factory.h +++ /dev/null @@ -1,253 +0,0 @@ -// Copyright (c) 2006-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. - -// A filter factory handles the creation of filters given a FilterType (i.e., -// FILTER_AUDIO_DECODER) and a MediaFormat. Generally a filter factory handles -// creating a single type of filter, with multiple factories combined into a -// FilterFactoryCollection. We use some template tricks to enforce type-safety -// and eliminate casting for callers. -// -// The majority of applications will only use FilterFactoryCollection since -// filter factory classes can be created from templates: -// FilterFactoryCollection filter_factory = new FilterFactoryCollection(); -// filter_factory->AddFactory(new TypeFilterFactory<YourAudioDecoder>()); -// filter_factory->AddFactory(new TypeFilterFactory<YourAudioRenderer>()); -// etc... -// AudioDecoder* filter; -// if (filter_factory->Create<AudioDecoder>(media_format, &filter) { -// do stuff with the filter... -// } -// -// The only requirement is that your filter implementation provide a static -// Create method with the following signature: -// -// Returns true and assigns |filter_out| if the filter was created, false -// and assigns NULL otherwise. -// static bool Create(MediaFormat& media_format, YourFilterType** filter_out); -// - -#ifndef MEDIA_BASE_FACTORY_H_ -#define MEDIA_BASE_FACTORY_H_ - -#include <vector> - -#include "base/logging.h" -#include "base/ref_counted.h" -#include "media/base/filters.h" - -namespace media { - -class FilterFactoryCollection; - -class FilterFactory : public base::RefCountedThreadSafe<FilterFactory> { - public: - // Creates a filter implementing the specified interface. Hides the casting - // and FilterType constants from the callers and produces cleaner code: - // socped_refptr<MyAudioDecoder> d = Create<MyAudioDecoder>(media_format); - // If the factory does not support the specific filter type or does not - // support the |media_format| then NULL is returned. - template <class Filter> - Filter* Create(const MediaFormat& media_format) { - return reinterpret_cast<Filter*>(Create(Filter::filter_type(), - media_format)); - } - - protected: - // For accessing the protected version of Create. - friend class FilterFactoryCollection; - - // Attempt to create a filter of the given type using the information stored - // in |media_format|. If successful, the filter is returned. If the filter - // cannot be created for any reason, NULL is returned. - // - // It is assumed that the MediaFilter interface can be safely cast to the - // corresponding interface type (i.e., FILTER_AUDIO_DECODER -> AudioDecoder). - virtual MediaFilter* Create(FilterType filter_type, - const MediaFormat& media_format) = 0; - - friend class base::RefCountedThreadSafe<FilterFactory>; - FilterFactory(); - virtual ~FilterFactory(); -}; - - -// Maintains a collection of FilterFactories. -class FilterFactoryCollection : public FilterFactory { - public: - FilterFactoryCollection(); - - // Adds a factory to the end of the collection. - void AddFactory(FilterFactory* factory); - - protected: - // Attempts to create a filter by walking down the list of filter factories. - MediaFilter* Create(FilterType filter_type, const MediaFormat& media_format); - - private: - ~FilterFactoryCollection(); - - typedef std::vector< scoped_refptr<FilterFactory> > FactoryVector; - FactoryVector factories_; - - DISALLOW_COPY_AND_ASSIGN(FilterFactoryCollection); -}; - -//----------------------------------------------------------------------------- - -// This template is used by classes to implement a type-safe filter factory. -// If the derived class needs to examine the |media_format| passed to the -// Create method then they should implement the static method -// IsMediaFormatSupported. Classes should implement their contructor as private -// and make FilterFactoryImpl<MyClass> a friend class. -template <class Filter> -class FilterFactoryImpl0 : public FilterFactory { - public: - FilterFactoryImpl0() {} - - protected: - virtual MediaFilter* Create(FilterType filter_type, - const MediaFormat& media_format) { - Filter* filter = NULL; - if (Filter::filter_type() == filter_type && - Filter::IsMediaFormatSupported(media_format)) { - filter = new Filter(); - } - return filter; - } - - private: - ~FilterFactoryImpl0() {} - - DISALLOW_COPY_AND_ASSIGN(FilterFactoryImpl0); -}; - -// This template can be used by classes that need to be constructed with a -// parameter that needs to be used in the construction of the actual filter. -// This would usually be a "parent" object which the instantiated filter needs -// to communicate with. The class's CreateFactory method would look like: -// static FilterFactory* CreateFactory(MyRequiredParentClass* parent) { -// return new FilterFactoryImpl1<MyClass>(parent); -// } -// The class would be constructed with the same pointer passed to the -// CreateFactory method. -template <class Filter, class A> -class FilterFactoryImpl1 : public FilterFactory { - public: - explicit FilterFactoryImpl1(A a) : a_(a) {} - - protected: - virtual MediaFilter* Create(FilterType filter_type, - const MediaFormat& media_format) { - Filter* filter = NULL; - if (Filter::filter_type() == filter_type && - Filter::IsMediaFormatSupported(media_format)) { - filter = new Filter(a_); - } - return filter; - } - - private: - ~FilterFactoryImpl1() {} - - A const a_; - DISALLOW_COPY_AND_ASSIGN(FilterFactoryImpl1); -}; - -template <class Filter, class A, class B> -class FilterFactoryImpl2 : public FilterFactory { - public: - FilterFactoryImpl2(A a, B b) : a_(a), b_(b) {} - - protected: - virtual MediaFilter* Create(FilterType filter_type, - const MediaFormat& media_format) { - Filter* filter = NULL; - if (Filter::filter_type() == filter_type && - Filter::IsMediaFormatSupported(media_format)) { - filter = new Filter(a_, b_); - } - return filter; - } - - private: - ~FilterFactoryImpl2() {} - - A const a_; - B const b_; - - DISALLOW_COPY_AND_ASSIGN(FilterFactoryImpl2); -}; - -template <class Filter, class A, class B, class C> -class FilterFactoryImpl3 : public FilterFactory { - public: - FilterFactoryImpl3(A a, B b, C c) : a_(a), b_(b), c_(c) {} - - protected: - virtual MediaFilter* Create(FilterType filter_type, - const MediaFormat& media_format) { - Filter* filter = NULL; - if (Filter::filter_type() == filter_type && - Filter::IsMediaFormatSupported(media_format)) { - filter = new Filter(a_, b_, c_); - } - return filter; - } - - private: - ~FilterFactoryImpl3() {} - - A const a_; - B const b_; - C const c_; - - DISALLOW_COPY_AND_ASSIGN(FilterFactoryImpl3); -}; - -//------------------------------------------------------------------------------ - -// This specialized factory is typically used by test programs that create -// a filter instance, and want to return that specific instance of the test -// filter to the pipeline. It takes an already created filter in the -// constructor, and then hands that instance out when the Create method is -// called. The factory makes sure to only return a single copy of the -// filter. The normal patern of use for this factory is: -// scoped_refptr<MyTestFilter> my_test_filter = new MyTestFilter(); -// filter_factory_collection->AddFactory( -// new InstanceFilterFactory<MyTestFilter>(my_test_filter)); -template <class Filter> -class InstanceFilterFactory : public FilterFactory { - public: - explicit InstanceFilterFactory(Filter* filter) - : filter_(filter), - create_called_(false) { - } - - protected: - virtual MediaFilter* Create(FilterType filter_type, - const MediaFormat& media_format) { - if (Filter::filter_type() == filter_type && - Filter::IsMediaFormatSupported(media_format)) { - if (!create_called_) { - create_called_ = true; - return filter_; - } else { - NOTREACHED(); - } - } - return NULL; - } - - private: - ~InstanceFilterFactory() {} - - scoped_refptr<Filter> filter_; - bool create_called_; - - DISALLOW_COPY_AND_ASSIGN(InstanceFilterFactory); -}; - -} // namespace media - -#endif // MEDIA_BASE_FACTORY_H_ diff --git a/media/base/filters.cc b/media/base/filters.cc index 2ade8d2..4c9ab4f 100644 --- a/media/base/filters.cc +++ b/media/base/filters.cc @@ -11,6 +11,10 @@ namespace media { MediaFilter::MediaFilter() : host_(NULL), message_loop_(NULL) {} +const char* MediaFilter::major_mime_type() const { + return ""; +} + void MediaFilter::set_host(FilterHost* host) { DCHECK(host); DCHECK(!host_); @@ -77,6 +81,50 @@ void MediaFilter::OnAudioRendererDisabled() { MediaFilter::~MediaFilter() {} +bool DataSource::IsUrlSupported(const std::string& url) { + return true; +} + +FilterType DataSource::filter_type() const { + return FILTER_DATA_SOURCE; +} + +FilterType Demuxer::filter_type() const { + return FILTER_DEMUXER; +} + +FilterType AudioDecoder::filter_type() const { + return FILTER_AUDIO_DECODER; +} + +const char* AudioDecoder::major_mime_type() const { + return mime_type::kMajorTypeAudio; +} + +FilterType AudioRenderer::filter_type() const { + return FILTER_AUDIO_RENDERER; +} + +const char* AudioRenderer::major_mime_type() const { + return mime_type::kMajorTypeAudio; +} + +FilterType VideoDecoder::filter_type() const { + return FILTER_VIDEO_DECODER; +} + +const char* VideoDecoder::major_mime_type() const { + return mime_type::kMajorTypeVideo; +} + +FilterType VideoRenderer::filter_type() const { + return FILTER_VIDEO_RENDERER; +} + +const char* VideoRenderer::major_mime_type() const { + return mime_type::kMajorTypeVideo; +} + DemuxerStream::~DemuxerStream() {} VideoDecoder::VideoDecoder() {} diff --git a/media/base/filters.h b/media/base/filters.h index d9edfc1..02bc596 100644 --- a/media/base/filters.h +++ b/media/base/filters.h @@ -24,6 +24,7 @@ #define MEDIA_BASE_FILTERS_H_ #include <limits> +#include <list> #include <string> #include "base/callback.h" @@ -41,11 +42,12 @@ class Buffer; class Decoder; class DemuxerStream; class FilterHost; +class MediaFilter; class WritableBuffer; -// Identifies the type of filter implementation. Used in conjunction with some -// template wizardry to enforce strongly typed operations. More or less a -// knock off of MSVC's __uuidof() operator. +// Identifies the type of filter implementation. Each filter has to be one of +// the following types. This is used to identify filter object during +// initialization of pipeline. enum FilterType { FILTER_DATA_SOURCE, FILTER_DEMUXER, @@ -58,10 +60,22 @@ enum FilterType { // Used for completing asynchronous methods. typedef Callback0::Type FilterCallback; +// This is a list of MediaFilter objects. Objects in this list is used to +// form a media playback pipeline. See src/media/base/pipeline.h for more +// information. +typedef std::list<scoped_refptr<MediaFilter> > MediaFilterCollection; + class MediaFilter : public base::RefCountedThreadSafe<MediaFilter> { public: MediaFilter(); + // Return the type of this filter. All implementor has to provide this + // method. + virtual FilterType filter_type() const = 0; + + // Return the major mime type for this filter. + virtual const char* major_mime_type() const; + // Sets the private member |host_|. This is the first method called by // the FilterHost after a filter is created. The host holds a strong // reference to the filter. The reference held by the host is guaranteed @@ -126,29 +140,19 @@ class MediaFilter : public base::RefCountedThreadSafe<MediaFilter> { DISALLOW_COPY_AND_ASSIGN(MediaFilter); }; - class DataSource : public MediaFilter { public: typedef Callback1<size_t>::Type ReadCallback; static const size_t kReadError = static_cast<size_t>(-1); - static FilterType filter_type() { - return FILTER_DATA_SOURCE; - } + virtual bool IsUrlSupported(const std::string& url); - static bool IsMediaFormatSupported(const MediaFormat& media_format) { - std::string mime_type; - return (media_format.GetAsString(MediaFormat::kMimeType, &mime_type) && - mime_type == mime_type::kURL); - } + virtual FilterType filter_type() const; // Initialize a DataSource for the given URL, executing the callback upon // completion. virtual void Initialize(const std::string& url, FilterCallback* callback) = 0; - // Returns the MediaFormat for this filter. - virtual const MediaFormat& media_format() = 0; - // Reads |size| bytes from |position| into |data|. And when the read is done // or failed, |read_callback| is called with the number of bytes read or // kReadError in case of error. @@ -169,15 +173,7 @@ class DataSource : public MediaFilter { class Demuxer : public MediaFilter { public: - static FilterType filter_type() { - return FILTER_DEMUXER; - } - - static bool IsMediaFormatSupported(const MediaFormat& media_format) { - std::string mime_type; - return (media_format.GetAsString(MediaFormat::kMimeType, &mime_type) && - mime_type == mime_type::kApplicationOctetStream); - } + virtual FilterType filter_type() const; // Initialize a Demuxer with the given DataSource, executing the callback upon // completion. @@ -194,9 +190,6 @@ class Demuxer : public MediaFilter { class DemuxerStream : public base::RefCountedThreadSafe<DemuxerStream> { public: - // Returns the MediaFormat for this filter. - virtual const MediaFormat& media_format() = 0; - // Schedules a read. When the |read_callback| is called, the downstream // filter takes ownership of the buffer by AddRef()'ing the buffer. // @@ -214,6 +207,9 @@ class DemuxerStream : public base::RefCountedThreadSafe<DemuxerStream> { return (NULL != i); }; + // Returns the media format of this stream. + virtual const MediaFormat& media_format() = 0; + virtual void EnableBitstreamConverter() = 0; protected: @@ -232,21 +228,14 @@ class DemuxerStream : public base::RefCountedThreadSafe<DemuxerStream> { class VideoDecoder : public MediaFilter { public: - static FilterType filter_type() { - return FILTER_VIDEO_DECODER; - } + virtual FilterType filter_type() const; - static const char* major_mime_type() { - return mime_type::kMajorTypeVideo; - } + virtual const char* major_mime_type() const; // Initialize a VideoDecoder with the given DemuxerStream, executing the // callback upon completion. virtual void Initialize(DemuxerStream* stream, FilterCallback* callback) = 0; - // Returns the MediaFormat for this filter. - virtual const MediaFormat& media_format() = 0; - // |set_fill_buffer_done_callback| install permanent callback from downstream // filter (i.e. Renderer). The callback is used to deliver video frames at // runtime to downstream filter @@ -263,6 +252,9 @@ class VideoDecoder : public MediaFilter { // Indicate whether decoder provides its own output buffers virtual bool ProvidesBuffer() = 0; + // Returns the media format produced by this decoder. + virtual const MediaFormat& media_format() = 0; + protected: // A video frame is ready to be consumed. This method invoke // |consume_video_frame_callback_| internally. @@ -280,21 +272,14 @@ class VideoDecoder : public MediaFilter { class AudioDecoder : public MediaFilter { public: - static FilterType filter_type() { - return FILTER_AUDIO_DECODER; - } + virtual FilterType filter_type() const; - static const char* major_mime_type() { - return mime_type::kMajorTypeAudio; - } + virtual const char* major_mime_type() const; // Initialize a AudioDecoder with the given DemuxerStream, executing the // callback upon completion. virtual void Initialize(DemuxerStream* stream, FilterCallback* callback) = 0; - // Returns the MediaFormat for this filter. - virtual const MediaFormat& media_format() = 0; - // |set_fill_buffer_done_callback| install permanent callback from downstream // filter (i.e. Renderer). The callback is used to deliver buffers at // runtime to downstream filter. @@ -312,6 +297,9 @@ class AudioDecoder : public MediaFilter { // We could also pass empty pointer here to let decoder provide buffers pool. virtual void ProduceAudioSamples(scoped_refptr<Buffer> buffer) = 0; + // Returns the media format produced by this decoder. + virtual const MediaFormat& media_format() = 0; + protected: AudioDecoder(); ~AudioDecoder(); @@ -323,13 +311,9 @@ class AudioDecoder : public MediaFilter { class VideoRenderer : public MediaFilter { public: - static FilterType filter_type() { - return FILTER_VIDEO_RENDERER; - } + virtual FilterType filter_type() const; - static const char* major_mime_type() { - return mime_type::kMajorTypeVideo; - } + virtual const char* major_mime_type() const; // Initialize a VideoRenderer with the given VideoDecoder, executing the // callback upon completion. @@ -343,13 +327,9 @@ class VideoRenderer : public MediaFilter { class AudioRenderer : public MediaFilter { public: - static FilterType filter_type() { - return FILTER_AUDIO_RENDERER; - } + virtual FilterType filter_type() const; - static const char* major_mime_type() { - return mime_type::kMajorTypeAudio; - } + virtual const char* major_mime_type() const; // Initialize a AudioRenderer with the given AudioDecoder, executing the // callback upon completion. diff --git a/media/base/mock_filter_host.h b/media/base/mock_filter_host.h index 5868333..9043854 100644 --- a/media/base/mock_filter_host.h +++ b/media/base/mock_filter_host.h @@ -12,12 +12,8 @@ #include <string> #include "base/scoped_ptr.h" -#include "media/base/factory.h" #include "media/base/filter_host.h" -#include "media/base/filters.h" -#include "media/base/media_format.h" #include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" namespace media { diff --git a/media/base/mock_filters.h b/media/base/mock_filters.h index fe5a58d..97710fe 100644 --- a/media/base/mock_filters.h +++ b/media/base/mock_filters.h @@ -16,7 +16,6 @@ #include <string> #include "base/callback.h" -#include "media/base/factory.h" #include "media/base/filters.h" #include "media/base/video_frame.h" #include "testing/gmock/include/gmock/gmock.h" @@ -101,6 +100,7 @@ class MockDataSource : public DataSource { MOCK_METHOD0(OnAudioRendererDisabled, void()); // DataSource implementation. + MOCK_METHOD1(IsUrlSupported, bool(const std::string& url)); MOCK_METHOD2(Initialize, void(const std::string& url, FilterCallback* callback)); MOCK_METHOD0(media_format, const MediaFormat&()); @@ -262,12 +262,11 @@ class MockAudioRenderer : public AudioRenderer { }; // FilterFactory that returns canned instances of mock filters. You can set -// expectations on the filters and then pass the factory into a pipeline. -class MockFilterFactory : public FilterFactory { +// expectations on the filters and then pass the collection into a pipeline. +class MockFilterCollection { public: - MockFilterFactory() - : creation_successful_(true), - data_source_(new MockDataSource()), + MockFilterCollection() + : data_source_(new MockDataSource()), demuxer_(new MockDemuxer()), video_decoder_(new MockVideoDecoder()), audio_decoder_(new MockAudioDecoder()), @@ -275,12 +274,7 @@ class MockFilterFactory : public FilterFactory { audio_renderer_(new MockAudioRenderer()) { } - virtual ~MockFilterFactory() {} - - // Controls whether the Create() method is successful or not. - void set_creation_successful(bool creation_successful) { - creation_successful_ = creation_successful; - } + virtual ~MockFilterCollection() {} // Mock accessors. MockDataSource* data_source() const { return data_source_; } @@ -290,33 +284,18 @@ class MockFilterFactory : public FilterFactory { MockVideoRenderer* video_renderer() const { return video_renderer_; } MockAudioRenderer* audio_renderer() const { return audio_renderer_; } - protected: - MediaFilter* Create(FilterType filter_type, const MediaFormat& media_format) { - if (!creation_successful_) { - return NULL; - } - - switch (filter_type) { - case FILTER_DATA_SOURCE: - return data_source_; - case FILTER_DEMUXER: - return demuxer_; - case FILTER_VIDEO_DECODER: - return video_decoder_; - case FILTER_AUDIO_DECODER: - return audio_decoder_; - case FILTER_VIDEO_RENDERER: - return video_renderer_; - case FILTER_AUDIO_RENDERER: - return audio_renderer_; - default: - NOTREACHED() << "Unknown filter type: " << filter_type; - } - return NULL; + MediaFilterCollection filter_collection() const { + MediaFilterCollection collection; + collection.push_back(data_source_); + collection.push_back(demuxer_); + collection.push_back(video_decoder_); + collection.push_back(audio_decoder_); + collection.push_back(video_renderer_); + collection.push_back(audio_renderer_); + return collection; } private: - bool creation_successful_; scoped_refptr<MockDataSource> data_source_; scoped_refptr<MockDemuxer> demuxer_; scoped_refptr<MockVideoDecoder> video_decoder_; @@ -324,7 +303,7 @@ class MockFilterFactory : public FilterFactory { scoped_refptr<MockVideoRenderer> video_renderer_; scoped_refptr<MockAudioRenderer> audio_renderer_; - DISALLOW_COPY_AND_ASSIGN(MockFilterFactory); + DISALLOW_COPY_AND_ASSIGN(MockFilterCollection); }; // Helper gmock function that immediately executes and destroys the diff --git a/media/base/pipeline.h b/media/base/pipeline.h index 4af77db..0519b35 100644 --- a/media/base/pipeline.h +++ b/media/base/pipeline.h @@ -3,7 +3,7 @@ // found in the LICENSE file. // The pipeline is the public API clients use for playing back media. Clients -// provide a filter factory containing the filters they want the pipeline to +// provide a filter collection containing the filters they want the pipeline to // use to render media. #ifndef MEDIA_BASE_PIPELINE_H_ @@ -12,7 +12,7 @@ #include <string> #include "base/callback.h" -#include "media/base/factory.h" +#include "media/base/filters.h" namespace base { class TimeDelta; @@ -47,8 +47,8 @@ typedef Callback0::Type PipelineCallback; class Pipeline : public base::RefCountedThreadSafe<Pipeline> { public: - // Build a pipeline to render the given URL using the given filter factory to - // construct a filter chain. Returns true if successful, false otherwise + // Build a pipeline to render the given URL using the given filter collection + // to construct a filter chain. Returns true if successful, false otherwise // (i.e., pipeline already started). Note that a return value of true // only indicates that the initialization process has started successfully. // Pipeline initialization is an inherently asynchronous process. Clients can @@ -59,7 +59,7 @@ class Pipeline : public base::RefCountedThreadSafe<Pipeline> { // If the caller provides a |start_callback|, it will be called when the // pipeline initialization completes. Clients are expected to call GetError() // to check whether initialization succeeded. - virtual bool Start(FilterFactory* filter_factory, + virtual bool Start(const MediaFilterCollection& filter_collection, const std::string& url, PipelineCallback* start_callback) = 0; diff --git a/media/base/pipeline_impl.cc b/media/base/pipeline_impl.cc index bc825f6..2128c34 100644 --- a/media/base/pipeline_impl.cc +++ b/media/base/pipeline_impl.cc @@ -19,9 +19,8 @@ namespace { // Small helper function to help us transition over to injected message loops. // // TODO(scherkus): have every filter support injected message loops. -template <class Filter> -bool SupportsSetMessageLoop() { - switch (Filter::filter_type()) { +bool SupportsSetMessageLoop(FilterType type) { + switch (type) { case FILTER_DEMUXER: case FILTER_AUDIO_DECODER: case FILTER_VIDEO_DECODER: @@ -35,17 +34,16 @@ bool SupportsSetMessageLoop() { // Skipping default case so compiler will warn on a missed enumeration. } - NOTREACHED() << "Unexpected filter type " << Filter::filter_type(); + NOTREACHED() << "Unexpected filter type " << type; return false; } // Small helper function to help us name filter threads for debugging. // // TODO(scherkus): figure out a cleaner way to derive the filter thread name. -template <class Filter> -const char* GetThreadName() { - DCHECK(SupportsSetMessageLoop<Filter>()); - switch (Filter::filter_type()) { +const char* GetThreadName(FilterType type) { + DCHECK(SupportsSetMessageLoop(type)); + switch (type) { case FILTER_DEMUXER: return "DemuxerThread"; case FILTER_AUDIO_DECODER: @@ -77,17 +75,17 @@ PipelineImpl::~PipelineImpl() { } // Creates the PipelineInternal and calls it's start method. -bool PipelineImpl::Start(FilterFactory* factory, +bool PipelineImpl::Start(const MediaFilterCollection& collection, const std::string& url, PipelineCallback* start_callback) { AutoLock auto_lock(lock_); - DCHECK(factory); scoped_ptr<PipelineCallback> callback(start_callback); if (running_) { VLOG(1) << "Media pipeline is already running"; return false; } - if (!factory) + + if (collection.empty()) return false; // Kick off initialization! @@ -96,7 +94,7 @@ bool PipelineImpl::Start(FilterFactory* factory, FROM_HERE, NewRunnableMethod(this, &PipelineImpl::StartTask, - make_scoped_refptr(factory), + collection, url, callback.release())); return true; @@ -403,7 +401,6 @@ void PipelineImpl::FinishInitialization() { seek_callback_->Run(); seek_callback_.reset(); } - filter_factory_ = NULL; } // static @@ -569,12 +566,12 @@ void PipelineImpl::OnFilterStateTransition() { NewRunnableMethod(this, &PipelineImpl::FilterStateTransitionTask)); } -void PipelineImpl::StartTask(FilterFactory* filter_factory, +void PipelineImpl::StartTask(const MediaFilterCollection& filter_collection, const std::string& url, PipelineCallback* start_callback) { DCHECK_EQ(MessageLoop::current(), message_loop_); DCHECK_EQ(kCreated, state_); - filter_factory_ = filter_factory; + filter_collection_ = filter_collection; url_ = url; seek_callback_.reset(start_callback); @@ -614,14 +611,14 @@ void PipelineImpl::InitializeTask() { // Just created, create data source. if (state_ == kCreated) { state_ = kInitDataSource; - CreateDataSource(); + InitializeDataSource(); return; } // Data source created, create demuxer. if (state_ == kInitDataSource) { state_ = kInitDemuxer; - CreateDemuxer(); + InitializeDemuxer(); return; } @@ -629,7 +626,7 @@ void PipelineImpl::InitializeTask() { if (state_ == kInitDemuxer) { state_ = kInitAudioDecoder; // If this method returns false, then there's no audio stream. - if (CreateDecoder<AudioDecoder>()) + if (InitializeAudioDecoder()) return; } @@ -637,8 +634,8 @@ void PipelineImpl::InitializeTask() { if (state_ == kInitAudioDecoder) { state_ = kInitAudioRenderer; // Returns false if there's no audio stream. - if (CreateRenderer<AudioDecoder, AudioRenderer>()) { - InsertRenderedMimeType(AudioDecoder::major_mime_type()); + if (InitializeAudioRenderer()) { + InsertRenderedMimeType(mime_type::kMajorTypeAudio); return; } } @@ -647,15 +644,15 @@ void PipelineImpl::InitializeTask() { if (state_ == kInitAudioRenderer) { // Then perform the stage of initialization, i.e. initialize video decoder. state_ = kInitVideoDecoder; - if (CreateDecoder<VideoDecoder>()) + if (InitializeVideoDecoder()) return; } // Assuming video decoder was created, create video renderer. if (state_ == kInitVideoDecoder) { state_ = kInitVideoRenderer; - if (CreateRenderer<VideoDecoder, VideoRenderer>()) { - InsertRenderedMimeType(VideoDecoder::major_mime_type()); + if (InitializeVideoRenderer()) { + InsertRenderedMimeType(mime_type::kMajorTypeVideo); return; } } @@ -666,6 +663,9 @@ void PipelineImpl::InitializeTask() { return; } + // Clear the collection of filters. + filter_collection_.clear(); + // Initialization was successful, we are now considered paused, so it's safe // to set the initial playback rate and volume. PlaybackRateChangedTask(GetPlaybackRate()); @@ -750,7 +750,7 @@ void PipelineImpl::VolumeChangedTask(float volume) { DCHECK_EQ(MessageLoop::current(), message_loop_); scoped_refptr<AudioRenderer> audio_renderer; - GetFilter(&audio_renderer); + GetInitializedFilter(FILTER_AUDIO_RENDERER, &audio_renderer); if (audio_renderer) { audio_renderer->SetVolume(volume); } @@ -808,8 +808,8 @@ void PipelineImpl::NotifyEndedTask() { // Grab the renderers, if they exist. scoped_refptr<AudioRenderer> audio_renderer; scoped_refptr<VideoRenderer> video_renderer; - GetFilter(&audio_renderer); - GetFilter(&video_renderer); + GetInitializedFilter(FILTER_AUDIO_RENDERER, &audio_renderer); + GetInitializedFilter(FILTER_VIDEO_RENDERER, &video_renderer); DCHECK(audio_renderer || video_renderer); // Make sure every extant renderer has ended. @@ -972,23 +972,46 @@ void PipelineImpl::FinishDestroyingFiltersTask() { } } -template <class Filter, class Source> -void PipelineImpl::CreateFilter(FilterFactory* filter_factory, - Source source, - const MediaFormat& media_format) { +template <class Filter> +void PipelineImpl::SelectFilter( + FilterType filter_type, scoped_refptr<Filter>* filter_out) const { DCHECK_EQ(MessageLoop::current(), message_loop_); - DCHECK(IsPipelineOk()); - // Create the filter. - scoped_refptr<Filter> filter = filter_factory->Create<Filter>(media_format); - if (!filter) { - SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); + MediaFilterCollection::const_iterator it = filter_collection_.begin(); + while (it != filter_collection_.end()) { + if ((*it)->filter_type() == filter_type) + break; + ++it; + } + + if (it == filter_collection_.end()) + *filter_out = NULL; + else + *filter_out = reinterpret_cast<Filter*>(it->get()); +} + +void PipelineImpl::RemoveFilter(scoped_refptr<MediaFilter> filter) { + MediaFilterCollection::iterator it = filter_collection_.begin(); + while (it != filter_collection_.end()) { + if (*it == filter) + break; + ++it; + } + if (it == filter_collection_.end()) { + NOTREACHED() << "Removing a filter that doesn't exist"; return; } + filter_collection_.erase(it); +} + +void PipelineImpl::PrepareFilter(scoped_refptr<MediaFilter> filter) { + DCHECK_EQ(MessageLoop::current(), message_loop_); + DCHECK(IsPipelineOk()); // Create a dedicated thread for this filter if applicable. - if (SupportsSetMessageLoop<Filter>()) { - scoped_ptr<base::Thread> thread(new base::Thread(GetThreadName<Filter>())); + if (SupportsSetMessageLoop(filter->filter_type())) { + scoped_ptr<base::Thread> thread( + new base::Thread(GetThreadName(filter->filter_type()))); if (!thread.get() || !thread->Start()) { NOTREACHED() << "Could not start filter thread"; SetError(PIPELINE_ERROR_INITIALIZATION_FAILED); @@ -1001,82 +1024,172 @@ void PipelineImpl::CreateFilter(FilterFactory* filter_factory, // Register ourselves as the filter's host. DCHECK(IsPipelineOk()); - DCHECK(filter_types_.find(Filter::filter_type()) == filter_types_.end()) - << "Filter type " << Filter::filter_type() << " already exists"; + DCHECK(filter_types_.find(filter->filter_type()) == filter_types_.end()) + << "Filter type " << filter->filter_type() << " already exists"; filter->set_host(this); filters_.push_back(filter.get()); - filter_types_[Filter::filter_type()] = filter.get(); + filter_types_[filter->filter_type()] = filter.get(); +} + +void PipelineImpl::InitializeDataSource() { + DCHECK_EQ(MessageLoop::current(), message_loop_); + DCHECK(IsPipelineOk()); + + scoped_refptr<DataSource> data_source; + while (true) { + SelectFilter(FILTER_DATA_SOURCE, &data_source); + if (!data_source || data_source->IsUrlSupported(url_)) + break; + RemoveFilter(data_source); + } + + if (!data_source) { + SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); + return; + } + + RemoveFilter(data_source); + PrepareFilter(data_source); + data_source->Initialize( + url_, NewCallback(this, &PipelineImpl::OnFilterInitialize)); +} + +void PipelineImpl::InitializeDemuxer() { + DCHECK_EQ(MessageLoop::current(), message_loop_); + DCHECK(IsPipelineOk()); + + scoped_refptr<DataSource> data_source; + scoped_refptr<Demuxer> demuxer; + + GetInitializedFilter(FILTER_DATA_SOURCE, &data_source); + CHECK(data_source); + + SelectFilter(FILTER_DEMUXER, &demuxer); + if (!demuxer) { + SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); + return; + } - // Now initialize the filter. - filter->Initialize(source, + RemoveFilter(demuxer); + PrepareFilter(demuxer); + demuxer->Initialize(data_source, + NewCallback(this, &PipelineImpl::OnFilterInitialize)); +} + +bool PipelineImpl::InitializeAudioDecoder() { + DCHECK_EQ(MessageLoop::current(), message_loop_); + DCHECK(IsPipelineOk()); + + scoped_refptr<DemuxerStream> stream = + FindDemuxerStream(mime_type::kMajorTypeAudio); + scoped_refptr<AudioDecoder> audio_decoder; + SelectFilter(FILTER_AUDIO_DECODER, &audio_decoder); + + // If there is such stream but audio decoder is not found. + if (stream && !audio_decoder) + SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); + if (!stream || !audio_decoder) + return false; + + RemoveFilter(audio_decoder); + PrepareFilter(audio_decoder); + audio_decoder->Initialize( + stream, NewCallback(this, &PipelineImpl::OnFilterInitialize)); + return true; } -void PipelineImpl::CreateDataSource() { +bool PipelineImpl::InitializeVideoDecoder() { DCHECK_EQ(MessageLoop::current(), message_loop_); DCHECK(IsPipelineOk()); - MediaFormat url_format; - url_format.SetAsString(MediaFormat::kMimeType, mime_type::kURL); - url_format.SetAsString(MediaFormat::kURL, url_); - CreateFilter<DataSource>(filter_factory_, url_, url_format); + scoped_refptr<DemuxerStream> stream = + FindDemuxerStream(mime_type::kMajorTypeVideo); + scoped_refptr<VideoDecoder> video_decoder; + SelectFilter(FILTER_VIDEO_DECODER, &video_decoder); + + // If there is such stream but video decoder is not found. + if (stream && !video_decoder) + SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); + if (!stream || !video_decoder) + return false; + + RemoveFilter(video_decoder); + PrepareFilter(video_decoder); + video_decoder->Initialize( + stream, + NewCallback(this, &PipelineImpl::OnFilterInitialize)); + return true; } -void PipelineImpl::CreateDemuxer() { +bool PipelineImpl::InitializeAudioRenderer() { DCHECK_EQ(MessageLoop::current(), message_loop_); DCHECK(IsPipelineOk()); - scoped_refptr<DataSource> data_source; - GetFilter(&data_source); - DCHECK(data_source); - CreateFilter<Demuxer, DataSource>(filter_factory_, data_source); + scoped_refptr<AudioDecoder> decoder; + GetInitializedFilter(FILTER_AUDIO_DECODER, &decoder); + scoped_refptr<AudioRenderer> audio_renderer; + SelectFilter(FILTER_AUDIO_RENDERER, &audio_renderer); + + // If there is such decoder but renderer is not found. + if (decoder && !audio_renderer) + SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); + if (!decoder || !audio_renderer) + return false; + + RemoveFilter(audio_renderer); + PrepareFilter(audio_renderer); + audio_renderer->Initialize( + decoder, NewCallback(this, &PipelineImpl::OnFilterInitialize)); + return true; } -template <class Decoder> -bool PipelineImpl::CreateDecoder() { +bool PipelineImpl::InitializeVideoRenderer() { DCHECK_EQ(MessageLoop::current(), message_loop_); DCHECK(IsPipelineOk()); + scoped_refptr<VideoDecoder> decoder; + GetInitializedFilter(FILTER_VIDEO_DECODER, &decoder); + scoped_refptr<VideoRenderer> video_renderer; + SelectFilter(FILTER_VIDEO_RENDERER, &video_renderer); + + // If there is such decoder but renderer is not found. + if (decoder && !video_renderer) + SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); + if (!decoder || !video_renderer) + return false; + + RemoveFilter(video_renderer); + PrepareFilter(video_renderer); + video_renderer->Initialize( + decoder, NewCallback(this, &PipelineImpl::OnFilterInitialize)); + return true; +} + +scoped_refptr<DemuxerStream> PipelineImpl::FindDemuxerStream( + std::string major_mime_type) { scoped_refptr<Demuxer> demuxer; - GetFilter(&demuxer); + GetInitializedFilter(FILTER_DEMUXER, &demuxer); DCHECK(demuxer); - const std::string major_mime_type = Decoder::major_mime_type(); const int num_outputs = demuxer->GetNumberOfStreams(); for (int i = 0; i < num_outputs; ++i) { - scoped_refptr<DemuxerStream> stream = demuxer->GetStream(i); std::string value; - if (stream->media_format().GetAsString(MediaFormat::kMimeType, &value) && - 0 == value.compare(0, major_mime_type.length(), major_mime_type)) { - CreateFilter<Decoder, DemuxerStream>(filter_factory_, stream); - return true; + if (demuxer->GetStream(i)->media_format().GetAsString( + MediaFormat::kMimeType, &value) && + !value.compare(0, major_mime_type.length(), major_mime_type)) { + return demuxer->GetStream(i); } } - return false; -} - -template <class Decoder, class Renderer> -bool PipelineImpl::CreateRenderer() { - DCHECK_EQ(MessageLoop::current(), message_loop_); - DCHECK(IsPipelineOk()); - - scoped_refptr<Decoder> decoder; - GetFilter(&decoder); - - if (decoder) { - // If the decoder was created. - const std::string major_mime_type = Decoder::major_mime_type(); - CreateFilter<Renderer, Decoder>(filter_factory_, decoder); - return true; - } - return false; + return NULL; } template <class Filter> -void PipelineImpl::GetFilter(scoped_refptr<Filter>* filter_out) const { +void PipelineImpl::GetInitializedFilter( + FilterType filter_type, scoped_refptr<Filter>* filter_out) const { DCHECK_EQ(MessageLoop::current(), message_loop_); - FilterTypeMap::const_iterator ft = filter_types_.find(Filter::filter_type()); + FilterTypeMap::const_iterator ft = filter_types_.find(filter_type); if (ft == filter_types_.end()) { *filter_out = NULL; } else { diff --git a/media/base/pipeline_impl.h b/media/base/pipeline_impl.h index 2060cef..0370fd5 100644 --- a/media/base/pipeline_impl.h +++ b/media/base/pipeline_impl.h @@ -66,7 +66,7 @@ class PipelineImpl : public Pipeline, public FilterHost { explicit PipelineImpl(MessageLoop* message_loop); // Pipeline implementation. - virtual bool Start(FilterFactory* filter_factory, + virtual bool Start(const MediaFilterCollection& filter_collection, const std::string& uri, PipelineCallback* start_callback); virtual void Stop(PipelineCallback* stop_callback); @@ -147,7 +147,7 @@ class PipelineImpl : public Pipeline, public FilterHost { bool IsPipelineSeeking(); // Helper method to execute callback from Start() and reset - // |filter_factory_|. Called when initialization completes + // |filter_collection_|. Called when initialization completes // normally or when pipeline is stopped or error occurs during // initialization. void FinishInitialization(); @@ -194,7 +194,7 @@ class PipelineImpl : public Pipeline, public FilterHost { // The following "task" methods correspond to the public methods, but these // methods are run as the result of posting a task to the PipelineInternal's // message loop. - void StartTask(FilterFactory* filter_factory, + void StartTask(const MediaFilterCollection& filter_collection, const std::string& url, PipelineCallback* start_callback); @@ -241,64 +241,47 @@ class PipelineImpl : public Pipeline, public FilterHost { // Internal methods used in the implementation of the pipeline thread. All // of these methods are only called on the pipeline thread. - // The following template functions make use of the fact that media filter - // derived interfaces are self-describing in the sense that they all contain - // the static method filter_type() which returns a FilterType enum that - // uniquely identifies the filter's interface. In addition, filters that are - // specific to audio or video also support a static method major_mime_type() - // which returns a string of "audio/" or "video/". - // - // Uses the FilterFactory to create a new filter of the Filter class, and - // initializes it using the Source object. The source may be another filter - // or it could be a string in the case of a DataSource. - // - // The CreateFilter() method actually does much more than simply creating the - // filter. It also creates the filter's thread and injects a FilterHost and - // MessageLoop. Finally, it calls the filter's type-specific Initialize() - // method to initialize the filter. If the required filter cannot be created, - // PIPELINE_ERROR_REQUIRED_FILTER_MISSING is raised, initialization is halted - // and this object will remain in the "Error" state. - template <class Filter, class Source> - void CreateFilter(FilterFactory* filter_factory, - Source source, - const MediaFormat& source_media_format); - - // Creates a Filter and initializes it with the given |source|. If a Filter - // could not be created or an error occurred, this method returns NULL and the - // pipeline's |error_| member will contain a specific error code. Note that - // the Source could be a filter or a DemuxerStream, but it must support the - // GetMediaFormat() method. - template <class Filter, class Source> - void CreateFilter(FilterFactory* filter_factory, Source* source) { - CreateFilter<Filter, Source*>(filter_factory, - source, - source->media_format()); - } - - // Creates a DataSource (the first filter in a pipeline). - void CreateDataSource(); - - // Creates a Demuxer. - void CreateDemuxer(); - - // Creates a decoder of type Decoder. Returns true if the asynchronous action - // of creating decoder has started. Returns false if this method did nothing - // because the corresponding audio/video stream does not exist. - template <class Decoder> - bool CreateDecoder(); - - // Creates a renderer of type Renderer and connects it with Decoder. Returns - // true if the asynchronous action of creating renderer has started. Returns + // Uses the MediaFilterCollection to return a filter of |filter_type|. + // If the required filter cannot be found, NULL is returned. + template <class Filter> + void SelectFilter(FilterType filter_type, + scoped_refptr<Filter>* filter_out) const; + + // Remove a filer from MediaFilterCollection. + void RemoveFilter(scoped_refptr<MediaFilter> filter); + + // PrepareFilter() creates the filter's thread and injects a FilterHost and + // MessageLoop. + void PrepareFilter(scoped_refptr<MediaFilter> filter); + + // The following initialize methods are used to select a specific type of + // MediaFilter object from MediaFilterCollection and initialize it + // asynchronously. + void InitializeDataSource(); + void InitializeDemuxer(); + + // Returns true if the asynchronous action of creating decoder has started. + // Returns false if this method did nothing because the corresponding + // audio/video stream does not exist. + bool InitializeAudioDecoder(); + bool InitializeVideoDecoder(); + + // Initializes a renderer and connects it with decoder. Returns true if the + // asynchronous action of creating renderer has started. Returns // false if this method did nothing because the corresponding audio/video // stream does not exist. - template <class Decoder, class Renderer> - bool CreateRenderer(); + bool InitializeAudioRenderer(); + bool InitializeVideoRenderer(); + + // Helper to find the demuxer of |major_mime_type| from Demuxer. + scoped_refptr<DemuxerStream> FindDemuxerStream(std::string major_mime_type); - // Examine the list of existing filters to find one that supports the - // specified Filter interface. If one exists, the |filter_out| will contain + // Examine the list of initialized filters to find one that matches the + // specified filter type. If one exists, the |filter_out| will contain // the filter, |*filter_out| will be NULL. template <class Filter> - void GetFilter(scoped_refptr<Filter>* filter_out) const; + void GetInitializedFilter(FilterType filter_type, + scoped_refptr<Filter>* filter_out) const; // Kicks off destroying filters. Called by StopTask() and ErrorChangedTask(). // When we start to tear down the pipeline, we will consider two cases: @@ -416,8 +399,8 @@ class PipelineImpl : public Pipeline, public FilterHost { // TODO(vrk): This is a hack. base::TimeDelta max_buffered_time_; - // Filter factory as passed in by Start(). - scoped_refptr<FilterFactory> filter_factory_; + // Filter collection as passed in by Start(). + MediaFilterCollection filter_collection_; // URL for the data source as passed in by Start(). std::string url_; diff --git a/media/base/pipeline_impl_unittest.cc b/media/base/pipeline_impl_unittest.cc index dc5783f..544e000 100644 --- a/media/base/pipeline_impl_unittest.cc +++ b/media/base/pipeline_impl_unittest.cc @@ -9,12 +9,11 @@ #include "media/base/pipeline_impl.h" #include "media/base/media_format.h" #include "media/base/filters.h" -#include "media/base/factory.h" #include "media/base/filter_host.h" #include "media/base/mock_filters.h" #include "testing/gtest/include/gtest/gtest.h" -using ::testing::DoAll; +using ::testing::_; using ::testing::InSequence; using ::testing::Invoke; using ::testing::Mock; @@ -61,11 +60,11 @@ class CallbackHelper { class PipelineImplTest : public ::testing::Test { public: PipelineImplTest() - : pipeline_(new PipelineImpl(&message_loop_)), - mocks_(new MockFilterFactory()) { + : pipeline_(new PipelineImpl(&message_loop_)) { pipeline_->SetPipelineErrorCallback(NewCallback( reinterpret_cast<CallbackHelper*>(&callbacks_), &CallbackHelper::OnError)); + mocks_.reset(new MockFilterCollection()); } virtual ~PipelineImplTest() { @@ -82,9 +81,7 @@ class PipelineImplTest : public ::testing::Test { // Free allocated media formats (if any). STLDeleteElements(&stream_media_formats_); - // Release the filter factory to workaround a gMock bug. - // See: http://code.google.com/p/googlemock/issues/detail?id=79 - mocks_ = NULL; + mocks_.reset(); } protected: @@ -95,12 +92,12 @@ class PipelineImplTest : public ::testing::Test { SetBufferedBytes(mocks_->data_source(), kBufferedBytes), Invoke(&RunFilterCallback))); EXPECT_CALL(*mocks_->data_source(), SetPlaybackRate(0.0f)); + EXPECT_CALL(*mocks_->data_source(), IsUrlSupported(_)) + .WillOnce(Return(true)); EXPECT_CALL(*mocks_->data_source(), Seek(base::TimeDelta(), NotNull())) .WillOnce(Invoke(&RunFilterCallback)); EXPECT_CALL(*mocks_->data_source(), Stop(NotNull())) .WillOnce(Invoke(&RunStopFilterCallback)); - EXPECT_CALL(*mocks_->data_source(), media_format()) - .WillOnce(ReturnRef(data_source_media_format_)); } // Sets up expectations to allow the demuxer to initialize. @@ -152,8 +149,6 @@ class PipelineImplTest : public ::testing::Test { .WillOnce(Invoke(&RunFilterCallback)); EXPECT_CALL(*mocks_->video_decoder(), Stop(NotNull())) .WillOnce(Invoke(&RunStopFilterCallback)); - EXPECT_CALL(*mocks_->video_decoder(), media_format()) - .WillOnce(ReturnRef(video_decoder_media_format_)); } // Sets up expectations to allow the audio decoder to initialize. @@ -165,8 +160,6 @@ class PipelineImplTest : public ::testing::Test { .WillOnce(Invoke(&RunFilterCallback)); EXPECT_CALL(*mocks_->audio_decoder(), Stop(NotNull())) .WillOnce(Invoke(&RunStopFilterCallback)); - EXPECT_CALL(*mocks_->audio_decoder(), media_format()) - .WillOnce(ReturnRef(audio_decoder_media_format_)); } // Sets up expectations to allow the video renderer to initialize. @@ -199,7 +192,7 @@ class PipelineImplTest : public ::testing::Test { void InitializePipeline() { // Expect an initialization callback. EXPECT_CALL(callbacks_, OnStart()); - pipeline_->Start(mocks_, "", + pipeline_->Start(mocks_->filter_collection(), "", NewCallback(reinterpret_cast<CallbackHelper*>(&callbacks_), &CallbackHelper::OnStart)); message_loop_.RunAllPending(); @@ -262,14 +255,10 @@ class PipelineImplTest : public ::testing::Test { StrictMock<CallbackHelper> callbacks_; MessageLoop message_loop_; scoped_refptr<PipelineImpl> pipeline_; - scoped_refptr<media::MockFilterFactory> mocks_; + scoped_ptr<media::MockFilterCollection> mocks_; scoped_refptr<StrictMock<MockDemuxerStream> > audio_stream_; scoped_refptr<StrictMock<MockDemuxerStream> > video_stream_; - MediaFormat data_source_media_format_; - MediaFormat audio_decoder_media_format_; - MediaFormat video_decoder_media_format_; - typedef std::vector<MediaFormat*> MediaFormatVector; MediaFormatVector stream_media_formats_; @@ -293,8 +282,8 @@ TEST_F(PipelineImplTest, NotStarted) { EXPECT_FALSE(pipeline_->IsRunning()); EXPECT_FALSE(pipeline_->IsInitialized()); EXPECT_FALSE(pipeline_->IsRendered("")); - EXPECT_FALSE(pipeline_->IsRendered(AudioDecoder::major_mime_type())); - EXPECT_FALSE(pipeline_->IsRendered(VideoDecoder::major_mime_type())); + EXPECT_FALSE(pipeline_->IsRendered(mime_type::kMajorTypeAudio)); + EXPECT_FALSE(pipeline_->IsRendered(mime_type::kMajorTypeVideo)); // Setting should still work. EXPECT_EQ(0.0f, pipeline_->GetPlaybackRate()); @@ -330,13 +319,15 @@ TEST_F(PipelineImplTest, NotStarted) { TEST_F(PipelineImplTest, NeverInitializes) { EXPECT_CALL(*mocks_->data_source(), Initialize("", NotNull())) .WillOnce(Invoke(&DestroyFilterCallback)); + EXPECT_CALL(*mocks_->data_source(), IsUrlSupported(_)) + .WillOnce(Return(true)); EXPECT_CALL(*mocks_->data_source(), Stop(NotNull())) .WillOnce(Invoke(&RunStopFilterCallback)); // This test hangs during initialization by never calling // InitializationComplete(). StrictMock<> will ensure that the callback is // never executed. - pipeline_->Start(mocks_, "", + pipeline_->Start(mocks_->filter_collection(), "", NewCallback(reinterpret_cast<CallbackHelper*>(&callbacks_), &CallbackHelper::OnStart)); message_loop_.RunAllPending(); @@ -353,9 +344,20 @@ TEST_F(PipelineImplTest, NeverInitializes) { TEST_F(PipelineImplTest, RequiredFilterMissing) { EXPECT_CALL(callbacks_, OnError()); - mocks_->set_creation_successful(false); - InitializePipeline(); + // Sets up expectations on the callback and initializes the pipeline. Called + // after tests have set expectations any filters they wish to use. + // Expect an initialization callback. + EXPECT_CALL(callbacks_, OnStart()); + + // Create a filter collection with missing filter. + MediaFilterCollection collection = mocks_->filter_collection(); + collection.pop_front(); + pipeline_->Start(collection, "", + NewCallback(reinterpret_cast<CallbackHelper*>(&callbacks_), + &CallbackHelper::OnStart)); + message_loop_.RunAllPending(); + EXPECT_FALSE(pipeline_->IsInitialized()); EXPECT_EQ(PIPELINE_ERROR_REQUIRED_FILTER_MISSING, pipeline_->GetError()); @@ -366,6 +368,8 @@ TEST_F(PipelineImplTest, URLNotFound) { .WillOnce(DoAll(SetError(mocks_->data_source(), PIPELINE_ERROR_URL_NOT_FOUND), Invoke(&RunFilterCallback))); + EXPECT_CALL(*mocks_->data_source(), IsUrlSupported(_)) + .WillOnce(Return(true)); EXPECT_CALL(callbacks_, OnError()); EXPECT_CALL(*mocks_->data_source(), Stop(NotNull())) .WillOnce(Invoke(&RunStopFilterCallback)); @@ -380,10 +384,10 @@ TEST_F(PipelineImplTest, NoStreams) { // we cannot fully initialize the pipeline. EXPECT_CALL(*mocks_->data_source(), Initialize("", NotNull())) .WillOnce(Invoke(&RunFilterCallback)); + EXPECT_CALL(*mocks_->data_source(), IsUrlSupported(_)) + .WillOnce(Return(true)); EXPECT_CALL(*mocks_->data_source(), Stop(NotNull())) .WillOnce(Invoke(&RunStopFilterCallback)); - EXPECT_CALL(*mocks_->data_source(), media_format()) - .WillOnce(ReturnRef(data_source_media_format_)); EXPECT_CALL(*mocks_->demuxer(), Initialize(mocks_->data_source(), NotNull())) .WillOnce(Invoke(&RunFilterCallback)); diff --git a/media/filters/audio_renderer_base.h b/media/filters/audio_renderer_base.h index 36a90f0..f9b7aee 100644 --- a/media/filters/audio_renderer_base.h +++ b/media/filters/audio_renderer_base.h @@ -22,7 +22,6 @@ #include "base/lock.h" #include "media/base/buffers.h" -#include "media/base/factory.h" #include "media/base/filters.h" #include "media/filters/audio_renderer_algorithm_base.h" @@ -30,6 +29,9 @@ namespace media { class AudioRendererBase : public AudioRenderer { public: + AudioRendererBase(); + virtual ~AudioRendererBase(); + // MediaFilter implementation. virtual void Play(FilterCallback* callback); virtual void Pause(FilterCallback* callback); @@ -42,10 +44,6 @@ class AudioRendererBase : public AudioRenderer { virtual bool HasEnded(); protected: - // Only allow a factory to create this class. - AudioRendererBase(); - virtual ~AudioRendererBase(); - // Called by Initialize(). |media_format| is the format of the AudioDecoder. // Subclasses should return true if they were able to initialize, false // otherwise. diff --git a/media/filters/audio_renderer_impl.cc b/media/filters/audio_renderer_impl.cc index 69188b3..5634ab2 100644 --- a/media/filters/audio_renderer_impl.cc +++ b/media/filters/audio_renderer_impl.cc @@ -29,15 +29,6 @@ AudioRendererImpl::~AudioRendererImpl() { } } -bool AudioRendererImpl::IsMediaFormatSupported( - const MediaFormat& media_format) { - int channels; - int sample_rate; - int sample_bits; - return AudioManager::GetAudioManager()->HasAudioOutputDevices() && - ParseMediaFormat(media_format, &channels, &sample_rate, &sample_bits); -} - void AudioRendererImpl::SetPlaybackRate(float rate) { // TODO(fbarchard): limit rate to reasonable values AudioRendererBase::SetPlaybackRate(rate); diff --git a/media/filters/audio_renderer_impl.h b/media/filters/audio_renderer_impl.h index fc61f80..1e18a41 100644 --- a/media/filters/audio_renderer_impl.h +++ b/media/filters/audio_renderer_impl.h @@ -20,7 +20,6 @@ #include "base/lock.h" #include "media/audio/audio_io.h" #include "media/base/buffers.h" -#include "media/base/factory.h" #include "media/base/filters.h" #include "media/filters/audio_renderer_base.h" @@ -29,12 +28,8 @@ namespace media { class AudioRendererImpl : public AudioRendererBase, public AudioOutputStream::AudioSourceCallback { public: - // FilterFactory provider. - static FilterFactory* CreateFilterFactory() { - return new FilterFactoryImpl0<AudioRendererImpl>(); - } - - static bool IsMediaFormatSupported(const MediaFormat& media_format); + AudioRendererImpl(); + virtual ~AudioRendererImpl(); // MediaFilter implementation. virtual void SetPlaybackRate(float playback_rate); @@ -49,11 +44,6 @@ class AudioRendererImpl : public AudioRendererBase, virtual void OnError(AudioOutputStream* stream, int code); protected: - // Only allow a factory to create this class. - friend class FilterFactoryImpl0<AudioRendererImpl>; - AudioRendererImpl(); - virtual ~AudioRendererImpl(); - // AudioRendererBase implementation. virtual bool OnInitialize(const MediaFormat& media_format); virtual void OnStop(); diff --git a/media/filters/decoder_base_unittest.cc b/media/filters/decoder_base_unittest.cc index ec80915..41dcf9a 100644 --- a/media/filters/decoder_base_unittest.cc +++ b/media/filters/decoder_base_unittest.cc @@ -67,6 +67,10 @@ class MockDecoderImpl : public media::DecoderBase< virtual ~MockDecoderImpl() {} + virtual media::FilterType filter_type() const { + return media::FILTER_VIDEO_DECODER; + } + // DecoderBase Implementations. MOCK_METHOD3(DoInitialize, void(media::DemuxerStream* demuxer_stream, diff --git a/media/filters/ffmpeg_audio_decoder.cc b/media/filters/ffmpeg_audio_decoder.cc index e8abeac..1895221 100644 --- a/media/filters/ffmpeg_audio_decoder.cc +++ b/media/filters/ffmpeg_audio_decoder.cc @@ -35,13 +35,6 @@ FFmpegAudioDecoder::FFmpegAudioDecoder() FFmpegAudioDecoder::~FFmpegAudioDecoder() { } -// static -bool FFmpegAudioDecoder::IsMediaFormatSupported(const MediaFormat& format) { - std::string mime_type; - return format.GetAsString(MediaFormat::kMimeType, &mime_type) && - mime_type::kFFmpegAudio == mime_type; -} - void FFmpegAudioDecoder::DoInitialize(DemuxerStream* demuxer_stream, bool* success, Task* done_cb) { diff --git a/media/filters/ffmpeg_audio_decoder.h b/media/filters/ffmpeg_audio_decoder.h index d0ad27f..0a7a915 100644 --- a/media/filters/ffmpeg_audio_decoder.h +++ b/media/filters/ffmpeg_audio_decoder.h @@ -5,7 +5,6 @@ #ifndef MEDIA_FILTERS_FFMPEG_AUDIO_DECODER_H_ #define MEDIA_FILTERS_FFMPEG_AUDIO_DECODER_H_ -#include "media/base/factory.h" #include "media/filters/decoder_base.h" struct AVCodecContext; @@ -17,11 +16,8 @@ class ScopedPtrAVFree; class FFmpegAudioDecoder : public DecoderBase<AudioDecoder, Buffer> { public: - static FilterFactory* CreateFactory() { - return new FilterFactoryImpl0<FFmpegAudioDecoder>(); - } - - static bool IsMediaFormatSupported(const MediaFormat& media_format); + FFmpegAudioDecoder(); + virtual ~FFmpegAudioDecoder(); protected: virtual void DoInitialize(DemuxerStream* demuxer_stream, bool* success, @@ -32,10 +28,6 @@ class FFmpegAudioDecoder : public DecoderBase<AudioDecoder, Buffer> { virtual void DoDecode(Buffer* input); private: - friend class FilterFactoryImpl0<FFmpegAudioDecoder>; - FFmpegAudioDecoder(); - virtual ~FFmpegAudioDecoder(); - // Calculates the duration of an audio buffer based on the sample rate, // channels and bits per sample given the size in bytes. base::TimeDelta CalculateDuration(size_t size); diff --git a/media/filters/ffmpeg_demuxer.h b/media/filters/ffmpeg_demuxer.h index ef74abe..a1f921d 100644 --- a/media/filters/ffmpeg_demuxer.h +++ b/media/filters/ffmpeg_demuxer.h @@ -29,7 +29,6 @@ #include "base/gtest_prod_util.h" #include "base/waitable_event.h" #include "media/base/buffers.h" -#include "media/base/factory.h" #include "media/base/filters.h" #include "media/base/media_format.h" #include "media/filters/ffmpeg_glue.h" @@ -122,10 +121,8 @@ class FFmpegDemuxerStream : public DemuxerStream, public AVStreamProvider { class FFmpegDemuxer : public Demuxer, public FFmpegURLProtocol { public: - // FilterFactory provider. - static FilterFactory* CreateFilterFactory() { - return new FilterFactoryImpl0<FFmpegDemuxer>(); - } + FFmpegDemuxer(); + virtual ~FFmpegDemuxer(); // Posts a task to perform additional demuxing. virtual void PostDemuxTask(); @@ -149,13 +146,9 @@ class FFmpegDemuxer : public Demuxer, private: // Only allow a factory to create this class. - friend class FilterFactoryImpl0<FFmpegDemuxer>; friend class MockFFmpegDemuxer; FRIEND_TEST_ALL_PREFIXES(FFmpegDemuxerTest, ProtocolRead); - FFmpegDemuxer(); - virtual ~FFmpegDemuxer(); - // Carries out initialization on the demuxer thread. void InitializeTask(DataSource* data_source, FilterCallback* callback); diff --git a/media/filters/ffmpeg_demuxer_unittest.cc b/media/filters/ffmpeg_demuxer_unittest.cc index 5ac1cbd..ecf87b5 100644 --- a/media/filters/ffmpeg_demuxer_unittest.cc +++ b/media/filters/ffmpeg_demuxer_unittest.cc @@ -65,11 +65,7 @@ class FFmpegDemuxerTest : public testing::Test { FFmpegDemuxerTest() { // Create an FFmpegDemuxer. - factory_ = FFmpegDemuxer::CreateFilterFactory(); - MediaFormat media_format; - media_format.SetAsString(MediaFormat::kMimeType, - mime_type::kApplicationOctetStream); - demuxer_ = factory_->Create<FFmpegDemuxer>(media_format); + demuxer_ = new FFmpegDemuxer(); DCHECK(demuxer_); // Inject a filter host and message loop and prepare a data source. @@ -159,7 +155,6 @@ class FFmpegDemuxerTest : public testing::Test { } // Fixture members. - scoped_refptr<FilterFactory> factory_; scoped_refptr<FFmpegDemuxer> demuxer_; scoped_refptr<StrictMock<MockDataSource> > data_source_; StrictMock<MockFilterHost> host_; @@ -190,22 +185,6 @@ const uint8 FFmpegDemuxerTest::kAudioData[kDataSize] = {0, 1, 2, 3}; const uint8 FFmpegDemuxerTest::kVideoData[kDataSize] = {4, 5, 6, 7}; const uint8* FFmpegDemuxerTest::kNullData = NULL; -TEST(FFmpegDemuxerFactoryTest, Create) { - // Should only accept application/octet-stream type. - scoped_refptr<FilterFactory> factory = FFmpegDemuxer::CreateFilterFactory(); - MediaFormat media_format; - media_format.SetAsString(MediaFormat::kMimeType, "foo/x-bar"); - scoped_refptr<Demuxer> demuxer(factory->Create<Demuxer>(media_format)); - ASSERT_FALSE(demuxer); - - // Try again with application/octet-stream mime type. - media_format.Clear(); - media_format.SetAsString(MediaFormat::kMimeType, - mime_type::kApplicationOctetStream); - demuxer = factory->Create<Demuxer>(media_format); - ASSERT_TRUE(demuxer); -} - TEST_F(FFmpegDemuxerTest, Initialize_OpenFails) { // Simulate av_open_input_file() failing. EXPECT_CALL(*MockFFmpeg::get(), AVOpenInputFile(_, _, NULL, 0, NULL)) diff --git a/media/filters/ffmpeg_glue_unittest.cc b/media/filters/ffmpeg_glue_unittest.cc index c2f0f6b..d217f9c 100644 --- a/media/filters/ffmpeg_glue_unittest.cc +++ b/media/filters/ffmpeg_glue_unittest.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/logging.h" #include "base/scoped_ptr.h" #include "media/base/mock_ffmpeg.h" #include "media/base/mock_filters.h" diff --git a/media/filters/ffmpeg_video_decoder.cc b/media/filters/ffmpeg_video_decoder.cc index 68d2046..45357f2 100644 --- a/media/filters/ffmpeg_video_decoder.cc +++ b/media/filters/ffmpeg_video_decoder.cc @@ -18,17 +18,15 @@ #include "media/filters/ffmpeg_interfaces.h" #include "media/video/ffmpeg_video_decode_engine.h" #include "media/video/video_decode_context.h" -#include "media/video/video_decode_engine.h" namespace media { -FFmpegVideoDecoder::FFmpegVideoDecoder(VideoDecodeEngine* decode_engine, - VideoDecodeContext* decode_context) +FFmpegVideoDecoder::FFmpegVideoDecoder(VideoDecodeContext* decode_context) : width_(0), height_(0), time_base_(new AVRational()), state_(kUnInitialized), - decode_engine_(decode_engine), + decode_engine_(new FFmpegVideoDecodeEngine()), decode_context_(decode_context) { memset(&info_, 0, sizeof(info_)); } @@ -440,20 +438,4 @@ void FFmpegVideoDecoder::SetVideoDecodeEngineForTest( decode_engine_.reset(engine); } -// static -FilterFactory* FFmpegVideoDecoder::CreateFactory( - VideoDecodeContext* decode_context) { - return new FilterFactoryImpl2<FFmpegVideoDecoder, - VideoDecodeEngine*, - VideoDecodeContext*>( - new FFmpegVideoDecodeEngine(), decode_context); -} - -// static -bool FFmpegVideoDecoder::IsMediaFormatSupported(const MediaFormat& format) { - std::string mime_type; - return format.GetAsString(MediaFormat::kMimeType, &mime_type) && - mime_type::kFFmpegVideo == mime_type; -} - } // namespace media diff --git a/media/filters/ffmpeg_video_decoder.h b/media/filters/ffmpeg_video_decoder.h index 150a0e1..415ab7d 100644 --- a/media/filters/ffmpeg_video_decoder.h +++ b/media/filters/ffmpeg_video_decoder.h @@ -9,7 +9,6 @@ #include "base/gtest_prod_util.h" #include "base/time.h" -#include "media/base/factory.h" #include "media/base/filters.h" #include "media/base/pts_heap.h" #include "media/base/video_frame.h" @@ -26,13 +25,9 @@ class VideoDecodeEngine; class FFmpegVideoDecoder : public VideoDecoder, public VideoDecodeEngine::EventHandler { public: - FFmpegVideoDecoder(VideoDecodeEngine* decode_engine, - VideoDecodeContext* decode_context); + explicit FFmpegVideoDecoder(VideoDecodeContext* decode_context); virtual ~FFmpegVideoDecoder(); - static FilterFactory* CreateFactory(VideoDecodeContext* decode_context); - static bool IsMediaFormatSupported(const MediaFormat& media_format); - // MediaFilter implementation. virtual void Stop(FilterCallback* callback); virtual void Seek(base::TimeDelta time, FilterCallback* callback); @@ -57,7 +52,6 @@ class FFmpegVideoDecoder : public VideoDecoder, virtual void ProduceVideoSample(scoped_refptr<Buffer> buffer); virtual void ConsumeVideoFrame(scoped_refptr<VideoFrame> frame); - friend class FilterFactoryImpl1<FFmpegVideoDecoder, VideoDecodeEngine*>; friend class DecoderPrivateMock; friend class FFmpegVideoDecoderTest; FRIEND_TEST_ALL_PREFIXES(FFmpegVideoDecoderTest, FindPtsAndDuration); diff --git a/media/filters/ffmpeg_video_decoder_unittest.cc b/media/filters/ffmpeg_video_decoder_unittest.cc index a81125d..d94e90e 100644 --- a/media/filters/ffmpeg_video_decoder_unittest.cc +++ b/media/filters/ffmpeg_video_decoder_unittest.cc @@ -71,8 +71,8 @@ class MockVideoDecodeEngine : public VideoDecodeEngine { // Class that just mocks the private functions. class DecoderPrivateMock : public FFmpegVideoDecoder { public: - DecoderPrivateMock(VideoDecodeEngine* engine, VideoDecodeContext* context) - : FFmpegVideoDecoder(engine, context) { + explicit DecoderPrivateMock(VideoDecodeContext* context) + : FFmpegVideoDecoder(context) { } // change access qualifier for test: used in actions. @@ -125,8 +125,7 @@ class FFmpegVideoDecoderTest : public testing::Test { // Create an FFmpegVideoDecoder, and MockVideoDecodeEngine. // // TODO(ajwong): Break the test's dependency on FFmpegVideoDecoder. - factory_ = FFmpegVideoDecoder::CreateFactory(NULL); - decoder_ = factory_->Create<DecoderPrivateMock>(media_format); + decoder_ = new DecoderPrivateMock(NULL); renderer_ = new MockVideoRenderer(); engine_ = new StrictMock<MockVideoDecodeEngine>(); @@ -194,7 +193,6 @@ class FFmpegVideoDecoderTest : public testing::Test { message_loop_.RunAllPending(); } // Fixture members. - scoped_refptr<FilterFactory> factory_; MockVideoDecodeEngine* engine_; // Owned by |decoder_|. scoped_refptr<DecoderPrivateMock> decoder_; scoped_refptr<MockVideoRenderer> renderer_; @@ -229,24 +227,6 @@ const FFmpegVideoDecoder::TimeTuple FFmpegVideoDecoderTest::kTestPts3 = { base::TimeDelta::FromMicroseconds(789), base::TimeDelta::FromMicroseconds(60) }; -TEST(FFmpegVideoDecoderFactoryTest, Create) { - // Should only accept video/x-ffmpeg mime type. - scoped_refptr<FilterFactory> factory = - FFmpegVideoDecoder::CreateFactory(NULL); - MediaFormat media_format; - media_format.SetAsString(MediaFormat::kMimeType, "foo/x-bar"); - scoped_refptr<VideoDecoder> decoder = - factory->Create<VideoDecoder>(media_format); - ASSERT_FALSE(decoder); - - // Try again with video/x-ffmpeg mime type. - media_format.Clear(); - media_format.SetAsString(MediaFormat::kMimeType, - mime_type::kFFmpegVideo); - decoder = factory->Create<VideoDecoder>(media_format); - ASSERT_TRUE(decoder); -} - TEST_F(FFmpegVideoDecoderTest, Initialize_QueryInterfaceFails) { // Test QueryInterface returning NULL. EXPECT_CALL(*demuxer_, QueryInterface(AVStreamProvider::interface_id())) diff --git a/media/filters/file_data_source.h b/media/filters/file_data_source.h index 4457890..584663a 100644 --- a/media/filters/file_data_source.h +++ b/media/filters/file_data_source.h @@ -17,10 +17,8 @@ namespace media { // system to read data for a media pipeline. class FileDataSource : public DataSource { public: - // Public method to get a filter factory for the FileDataSource. - static FilterFactory* CreateFactory() { - return new FilterFactoryImpl0<FileDataSource>(); - } + FileDataSource(); + virtual ~FileDataSource(); // Implementation of MediaFilter. virtual void Stop(FilterCallback* callback); @@ -41,9 +39,6 @@ class FileDataSource : public DataSource { FRIEND_TEST_ALL_PREFIXES(FileDataSourceTest, OpenFile); FRIEND_TEST_ALL_PREFIXES(FileDataSourceTest, ReadData); FRIEND_TEST_ALL_PREFIXES(FileDataSourceTest, Seek); - friend class FilterFactoryImpl0<FileDataSource>; - FileDataSource(); - virtual ~FileDataSource(); // File handle. NULL if not initialized or an error occurs. FILE* file_; diff --git a/media/filters/null_audio_renderer.cc b/media/filters/null_audio_renderer.cc index 55c4013..7c3c039 100644 --- a/media/filters/null_audio_renderer.cc +++ b/media/filters/null_audio_renderer.cc @@ -26,15 +26,6 @@ NullAudioRenderer::~NullAudioRenderer() { DCHECK_EQ(kNullThreadHandle, thread_); } -// static -bool NullAudioRenderer::IsMediaFormatSupported( - const MediaFormat& media_format) { - int channels; - int sample_rate; - int sample_bits; - return ParseMediaFormat(media_format, &channels, &sample_rate, &sample_bits); -} - void NullAudioRenderer::SetVolume(float volume) { // Do nothing. } diff --git a/media/filters/null_audio_renderer.h b/media/filters/null_audio_renderer.h index e6f2e85..afbb098 100644 --- a/media/filters/null_audio_renderer.h +++ b/media/filters/null_audio_renderer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 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. @@ -23,7 +23,6 @@ #include "base/platform_thread.h" #include "base/scoped_ptr.h" #include "media/base/buffers.h" -#include "media/base/factory.h" #include "media/base/filters.h" #include "media/filters/audio_renderer_base.h" @@ -31,13 +30,8 @@ namespace media { class NullAudioRenderer : public AudioRendererBase, PlatformThread::Delegate { public: - // FilterFactory provider. - static FilterFactory* CreateFilterFactory() { - return new FilterFactoryImpl0<NullAudioRenderer>(); - } - - // Compatible with any audio/x-uncompressed MediaFormat. - static bool IsMediaFormatSupported(const MediaFormat& media_format); + NullAudioRenderer(); + virtual ~NullAudioRenderer(); // AudioRenderer implementation. virtual void SetVolume(float volume); @@ -46,11 +40,6 @@ class NullAudioRenderer : public AudioRendererBase, PlatformThread::Delegate { virtual void ThreadMain(); protected: - // Only allow a factory to create this class. - friend class FilterFactoryImpl0<NullAudioRenderer>; - NullAudioRenderer(); - virtual ~NullAudioRenderer(); - // AudioRendererBase implementation. virtual bool OnInitialize(const MediaFormat& media_format); virtual void OnStop(); diff --git a/media/filters/omx_video_decoder.cc b/media/filters/omx_video_decoder.cc index ba122e5..d8fbf04 100644 --- a/media/filters/omx_video_decoder.cc +++ b/media/filters/omx_video_decoder.cc @@ -7,7 +7,6 @@ #include "base/callback.h" #include "base/message_loop.h" #include "media/base/callback.h" -#include "media/base/factory.h" #include "media/base/filter_host.h" #include "media/base/limits.h" #include "media/ffmpeg/ffmpeg_common.h" @@ -16,38 +15,9 @@ namespace media { -// static -FilterFactory* OmxVideoDecoder::CreateFactory( - VideoDecodeContext* decode_context) { - return new FilterFactoryImpl2<OmxVideoDecoder, - VideoDecodeEngine*, - VideoDecodeContext*>( - new OmxVideoDecodeEngine(), decode_context); -} - -// static -bool OmxVideoDecoder::IsMediaFormatSupported(const MediaFormat& format) { - std::string mime_type; - if (!format.GetAsString(MediaFormat::kMimeType, &mime_type) || - mime_type::kFFmpegVideo != mime_type) { - return false; - } - - // TODO(ajwong): Find a good way to white-list formats that OpenMAX can - // handle. - int codec_id; - if (format.GetAsInteger(MediaFormat::kFFmpegCodecID, &codec_id) && - codec_id == CODEC_ID_H264) { - return true; - } - - return false; -} - OmxVideoDecoder::OmxVideoDecoder( - VideoDecodeEngine* engine, VideoDecodeContext* context) - : decode_engine_(engine), + : decode_engine_(new OmxVideoDecodeEngine()), decode_context_(context), width_(0), height_(0) { DCHECK(decode_engine_.get()); diff --git a/media/filters/omx_video_decoder.h b/media/filters/omx_video_decoder.h index f025554..e5861af 100644 --- a/media/filters/omx_video_decoder.h +++ b/media/filters/omx_video_decoder.h @@ -7,7 +7,6 @@ #include <queue> -#include "media/base/factory.h" #include "media/base/filters.h" #include "media/base/media_format.h" #include "media/video/video_decode_context.h" @@ -24,13 +23,10 @@ class VideoFrame; class OmxVideoDecoder : public VideoDecoder, public VideoDecodeEngine::EventHandler { public: - static FilterFactory* CreateFactory(VideoDecodeContext* decode_context); - static bool IsMediaFormatSupported(const MediaFormat& media_format); - - OmxVideoDecoder(VideoDecodeEngine* decode_engine, - VideoDecodeContext* decode_context); + explicit OmxVideoDecoder(VideoDecodeContext* decode_context); virtual ~OmxVideoDecoder(); + // MediaFilter implementations. virtual void Initialize(DemuxerStream* stream, FilterCallback* callback); virtual void Stop(FilterCallback* callback); virtual void Flush(FilterCallback* callback); diff --git a/media/media.gyp b/media/media.gyp index 111962a..f844f12 100644 --- a/media/media.gyp +++ b/media/media.gyp @@ -76,8 +76,6 @@ 'base/data_buffer.h', 'base/djb2.cc', 'base/djb2.h', - 'base/factory.cc', - 'base/factory.h', 'base/filter_host.h', 'base/filters.cc', 'base/filters.h', diff --git a/media/tools/player_wtl/movie.cc b/media/tools/player_wtl/movie.cc index be97097..90dae4f 100644 --- a/media/tools/player_wtl/movie.cc +++ b/media/tools/player_wtl/movie.cc @@ -19,7 +19,7 @@ using media::FFmpegAudioDecoder; using media::FFmpegDemuxer; using media::FFmpegVideoDecoder; using media::FileDataSource; -using media::FilterFactoryCollection; +using media::MediaFilterCollection; using media::PipelineImpl; namespace media { @@ -53,28 +53,26 @@ bool Movie::Open(const wchar_t* url, WtlVideoRenderer* video_renderer) { Close(); } - // Create our filter factories. - scoped_refptr<FilterFactoryCollection> factories = - new FilterFactoryCollection(); - factories->AddFactory(FileDataSource::CreateFactory()); - factories->AddFactory(FFmpegAudioDecoder::CreateFactory()); - factories->AddFactory(FFmpegDemuxer::CreateFilterFactory()); - factories->AddFactory(FFmpegVideoDecoder::CreateFactory(NULL)); + // Create filter collection. + MediaFilterCollection collection; + collection.push_back(new FileDataSource()); + collection.push_back(new FFmpegAudioDecoder()); + collection.push_back(new FFmpegDemuxer()); + collection.push_back(new FFmpegVideoDecoder(NULL)); if (enable_audio_) { - factories->AddFactory(AudioRendererImpl::CreateFilterFactory()); + collection.push_back(new AudioRendererImpl()); } else { - factories->AddFactory(media::NullAudioRenderer::CreateFilterFactory()); + collection.push_back(new media::NullAudioRenderer()); } - factories->AddFactory( - new media::InstanceFilterFactory<WtlVideoRenderer>(video_renderer)); + collection.push_back(video_renderer); thread_.reset(new base::Thread("PipelineThread")); thread_->Start(); pipeline_ = new PipelineImpl(thread_->message_loop()); // Create and start our pipeline. - pipeline_->Start(factories, WideToUTF8(std::wstring(url)), NULL); + pipeline_->Start(collection, WideToUTF8(std::wstring(url)), NULL); while (true) { PlatformThread::Sleep(100); if (pipeline_->IsInitialized()) diff --git a/media/tools/player_x11/gl_video_renderer.cc b/media/tools/player_x11/gl_video_renderer.cc index 29b4f38..eef1a25 100644 --- a/media/tools/player_x11/gl_video_renderer.cc +++ b/media/tools/player_x11/gl_video_renderer.cc @@ -24,12 +24,6 @@ GlVideoRenderer::GlVideoRenderer(Display* display, Window window, GlVideoRenderer::~GlVideoRenderer() { } -// static -bool GlVideoRenderer::IsMediaFormatSupported( - const media::MediaFormat& media_format) { - return ParseMediaFormat(media_format, NULL, NULL, NULL, NULL); -} - void GlVideoRenderer::OnStop(media::FilterCallback* callback) { glXMakeCurrent(display_, 0, NULL); glXDestroyContext(display_, gl_context_); diff --git a/media/tools/player_x11/gl_video_renderer.h b/media/tools/player_x11/gl_video_renderer.h index 71f8d77..c6ce45e 100644 --- a/media/tools/player_x11/gl_video_renderer.h +++ b/media/tools/player_x11/gl_video_renderer.h @@ -8,29 +8,17 @@ #include "app/gfx/gl/gl_bindings.h" #include "base/lock.h" #include "base/scoped_ptr.h" -#include "media/base/factory.h" #include "media/base/filters.h" #include "media/filters/video_renderer_base.h" class GlVideoRenderer : public media::VideoRendererBase { public: - static media::FilterFactory* CreateFactory(Display* display, - Window window, - MessageLoop* message_loop) { - return new media::FilterFactoryImpl3< - GlVideoRenderer, Display*, Window, MessageLoop*>(display, window, - message_loop); - } - GlVideoRenderer(Display* display, Window window, MessageLoop* message_loop); // This method is called to paint the current video frame to the assigned // window. void Paint(); - // media::FilterFactoryImpl2 Implementation. - static bool IsMediaFormatSupported(const media::MediaFormat& media_format); - static GlVideoRenderer* instance() { return instance_; } MessageLoop* glx_thread_message_loop() { diff --git a/media/tools/player_x11/gles_video_renderer.cc b/media/tools/player_x11/gles_video_renderer.cc index d3b8051..8bd8b3e 100644 --- a/media/tools/player_x11/gles_video_renderer.cc +++ b/media/tools/player_x11/gles_video_renderer.cc @@ -33,12 +33,6 @@ GlesVideoRenderer::GlesVideoRenderer(Display* display, Window window, GlesVideoRenderer::~GlesVideoRenderer() { } -// static -bool GlesVideoRenderer::IsMediaFormatSupported( - const media::MediaFormat& media_format) { - return ParseMediaFormat(media_format, NULL, NULL, NULL, NULL); -} - void GlesVideoRenderer::OnStop(media::FilterCallback* callback) { if (glx_thread_message_loop()) { glx_thread_message_loop()->PostTask(FROM_HERE, diff --git a/media/tools/player_x11/gles_video_renderer.h b/media/tools/player_x11/gles_video_renderer.h index 27780b6..ead864f 100644 --- a/media/tools/player_x11/gles_video_renderer.h +++ b/media/tools/player_x11/gles_video_renderer.h @@ -12,30 +12,18 @@ #include "base/lock.h" #include "base/scoped_ptr.h" -#include "media/base/factory.h" #include "media/base/filters.h" #include "media/base/video_frame.h" #include "media/filters/video_renderer_base.h" class GlesVideoRenderer : public media::VideoRendererBase { public: - static media::FilterFactory* CreateFactory(Display* display, - Window window, - MessageLoop* message_loop) { - return new media::FilterFactoryImpl3< - GlesVideoRenderer, Display*, Window, MessageLoop*>(display, window, - message_loop); - } - GlesVideoRenderer(Display* display, Window window, MessageLoop* message_loop); // This method is called to paint the current video frame to the assigned // window. void Paint(); - // media::FilterFactoryImpl2 Implementation. - static bool IsMediaFormatSupported(const media::MediaFormat& media_format); - static GlesVideoRenderer* instance() { return instance_; } MessageLoop* glx_thread_message_loop() { diff --git a/media/tools/player_x11/player_x11.cc b/media/tools/player_x11/player_x11.cc index 11b8b5f..d1a7ffe 100644 --- a/media/tools/player_x11/player_x11.cc +++ b/media/tools/player_x11/player_x11.cc @@ -97,29 +97,26 @@ bool InitPipeline(MessageLoop* message_loop, } // Create our filter factories. - scoped_refptr<media::FilterFactoryCollection> factories = - new media::FilterFactoryCollection(); - factories->AddFactory(media::FileDataSource::CreateFactory()); - factories->AddFactory(media::FFmpegAudioDecoder::CreateFactory()); - factories->AddFactory(media::FFmpegDemuxer::CreateFilterFactory()); + media::MediaFilterCollection collection; + collection.push_back(new media::FileDataSource()); + collection.push_back(new media::FFmpegDemuxer()); + collection.push_back(new media::FFmpegAudioDecoder()); if (CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnableOpenMax)) { - factories->AddFactory(media::OmxVideoDecoder::CreateFactory(NULL)); + collection.push_back(new media::OmxVideoDecoder(NULL)); } else { - factories->AddFactory(media::FFmpegVideoDecoder::CreateFactory(NULL)); + collection.push_back(new media::FFmpegVideoDecoder(NULL)); } - factories->AddFactory(Renderer::CreateFactory(g_display, g_window, - paint_message_loop)); + collection.push_back(new Renderer(g_display, g_window, paint_message_loop)); - if (enable_audio) { - factories->AddFactory(media::AudioRendererImpl::CreateFilterFactory()); - } else { - factories->AddFactory(media::NullAudioRenderer::CreateFilterFactory()); - } + if (enable_audio) + collection.push_back(new media::AudioRendererImpl()); + else + collection.push_back(new media::NullAudioRenderer()); // Creates the pipeline and start it. *pipeline = new media::PipelineImpl(message_loop); - (*pipeline)->Start(factories, filename, NULL); + (*pipeline)->Start(collection, filename, NULL); // Wait until the pipeline is fully initialized. while (true) { diff --git a/media/tools/player_x11/x11_video_renderer.cc b/media/tools/player_x11/x11_video_renderer.cc index 6819468..2c50e50 100644 --- a/media/tools/player_x11/x11_video_renderer.cc +++ b/media/tools/player_x11/x11_video_renderer.cc @@ -67,12 +67,6 @@ X11VideoRenderer::X11VideoRenderer(Display* display, Window window, X11VideoRenderer::~X11VideoRenderer() { } -// static -bool X11VideoRenderer::IsMediaFormatSupported( - const media::MediaFormat& media_format) { - return ParseMediaFormat(media_format, NULL, NULL, NULL, NULL); -} - void X11VideoRenderer::OnStop(media::FilterCallback* callback) { if (image_) { XDestroyImage(image_); diff --git a/media/tools/player_x11/x11_video_renderer.h b/media/tools/player_x11/x11_video_renderer.h index 2bd9dc4..5076ef8 100644 --- a/media/tools/player_x11/x11_video_renderer.h +++ b/media/tools/player_x11/x11_video_renderer.h @@ -9,29 +9,17 @@ #include "base/lock.h" #include "base/scoped_ptr.h" -#include "media/base/factory.h" #include "media/base/filters.h" #include "media/filters/video_renderer_base.h" class X11VideoRenderer : public media::VideoRendererBase { public: - static media::FilterFactory* CreateFactory(Display* display, - Window window, - MessageLoop* message_loop) { - return new media::FilterFactoryImpl3< - X11VideoRenderer, Display*, Window, MessageLoop*>(display, window, - message_loop); - } - X11VideoRenderer(Display* display, Window window, MessageLoop* message_loop); // This method is called to paint the current video frame to the assigned // window. void Paint(); - // media::FilterFactoryImpl2 Implementation. - static bool IsMediaFormatSupported(const media::MediaFormat& media_format); - static X11VideoRenderer* instance() { return instance_; } MessageLoop* glx_thread_message_loop() { diff --git a/webkit/glue/media/buffered_data_source.cc b/webkit/glue/media/buffered_data_source.cc index a4e3901..43d21f7 100644 --- a/webkit/glue/media/buffered_data_source.cc +++ b/webkit/glue/media/buffered_data_source.cc @@ -522,29 +522,10 @@ void BufferedResourceLoader::NotifyNetworkEvent() { } ///////////////////////////////////////////////////////////////////////////// -// BufferedDataSource, static methods -bool BufferedDataSource::IsMediaFormatSupported( - const media::MediaFormat& media_format) { - std::string mime_type; - std::string url; - if (media_format.GetAsString(media::MediaFormat::kMimeType, &mime_type) && - media_format.GetAsString(media::MediaFormat::kURL, &url)) { - GURL gurl(url); - - // This data source doesn't support data:// protocol, so reject it - // explicitly. - if (IsProtocolSupportedForMedia(gurl) && !IsDataProtocol(gurl)) - return true; - } - return false; -} - -///////////////////////////////////////////////////////////////////////////// -// BufferedDataSource, protected +// BufferedDataSource BufferedDataSource::BufferedDataSource( MessageLoop* render_loop, - webkit_glue::MediaResourceLoaderBridgeFactory* bridge_factory, - webkit_glue::WebMediaPlayerImpl::Proxy* proxy) + webkit_glue::MediaResourceLoaderBridgeFactory* bridge_factory) : total_bytes_(kPositionNotSpecified), loaded_(false), streaming_(false), @@ -564,8 +545,6 @@ BufferedDataSource::BufferedDataSource( stopped_on_render_loop_(false), media_is_paused_(true), using_range_request_(true) { - if (proxy) - proxy->SetDataSource(this); } BufferedDataSource::~BufferedDataSource() { @@ -618,6 +597,13 @@ void BufferedDataSource::Initialize(const std::string& url, NewRunnableMethod(this, &BufferedDataSource::InitializeTask)); } +bool BufferedDataSource::IsUrlSupported(const std::string& url) { + GURL gurl(url); + + // This data source doesn't support data:// protocol so reject it. + return IsProtocolSupportedForMedia(gurl) && !IsDataProtocol(gurl); +} + void BufferedDataSource::Stop(media::FilterCallback* callback) { { AutoLock auto_lock(lock_); diff --git a/webkit/glue/media/buffered_data_source.h b/webkit/glue/media/buffered_data_source.h index 6b740c9..d6a7e24 100644 --- a/webkit/glue/media/buffered_data_source.h +++ b/webkit/glue/media/buffered_data_source.h @@ -13,7 +13,6 @@ #include "base/timer.h" #include "base/condition_variable.h" #include "googleurl/src/gurl.h" -#include "media/base/factory.h" #include "media/base/filters.h" #include "media/base/media_format.h" #include "media/base/pipeline.h" @@ -216,27 +215,16 @@ class BufferedResourceLoader : class BufferedDataSource : public WebDataSource { public: - // Methods called from pipeline thread - // Static methods for creating this class. - static media::FilterFactory* CreateFactory( - MessageLoop* message_loop, - webkit_glue::MediaResourceLoaderBridgeFactory* bridge_factory, - webkit_glue::WebMediaPlayerImpl::Proxy* proxy) { - return new media::FilterFactoryImpl3< - BufferedDataSource, - MessageLoop*, - webkit_glue::MediaResourceLoaderBridgeFactory*, - webkit_glue::WebMediaPlayerImpl::Proxy*>( - message_loop, bridge_factory, proxy); - } + BufferedDataSource( + MessageLoop* render_loop, + webkit_glue::MediaResourceLoaderBridgeFactory* bridge_factory); - // media::FilterFactoryImpl2 implementation. - static bool IsMediaFormatSupported( - const media::MediaFormat& media_format); + virtual ~BufferedDataSource(); // media::MediaFilter implementation. virtual void Initialize(const std::string& url, media::FilterCallback* callback); + virtual bool IsUrlSupported(const std::string& url); virtual void Stop(media::FilterCallback* callback); virtual void SetPlaybackRate(float playback_rate); @@ -256,11 +244,6 @@ class BufferedDataSource : public WebDataSource { virtual void Abort(); protected: - BufferedDataSource( - MessageLoop* render_loop, - webkit_glue::MediaResourceLoaderBridgeFactory* bridge_factory, - webkit_glue::WebMediaPlayerImpl::Proxy* proxy); - virtual ~BufferedDataSource(); // A factory method to create a BufferedResourceLoader based on the read // parameters. We can override this file to object a mock @@ -274,12 +257,6 @@ class BufferedDataSource : public WebDataSource { virtual base::TimeDelta GetTimeoutMilliseconds(); private: - friend class media::FilterFactoryImpl3< - BufferedDataSource, - MessageLoop*, - webkit_glue::MediaResourceLoaderBridgeFactory*, - webkit_glue::WebMediaPlayerImpl::Proxy*>; - // Posted to perform initialization on render thread and start resource // loading. void InitializeTask(); diff --git a/webkit/glue/media/buffered_data_source_unittest.cc b/webkit/glue/media/buffered_data_source_unittest.cc index 25e5192..7e6fd54 100644 --- a/webkit/glue/media/buffered_data_source_unittest.cc +++ b/webkit/glue/media/buffered_data_source_unittest.cc @@ -539,15 +539,9 @@ class MockBufferedResourceLoader : public BufferedResourceLoader { // CreateResourceLoader() method. class MockBufferedDataSource : public BufferedDataSource { public: - // Static methods for creating this class. - static media::FilterFactory* CreateFactory( - MessageLoop* message_loop, - MediaResourceLoaderBridgeFactory* bridge_factory) { - return new media::FilterFactoryImpl2< - MockBufferedDataSource, - MessageLoop*, - MediaResourceLoaderBridgeFactory*>(message_loop, - bridge_factory); + MockBufferedDataSource( + MessageLoop* message_loop, MediaResourceLoaderBridgeFactory* factory) + : BufferedDataSource(message_loop, factory) { } virtual base::TimeDelta GetTimeoutMilliseconds() { @@ -558,18 +552,7 @@ class MockBufferedDataSource : public BufferedDataSource { MOCK_METHOD2(CreateResourceLoader, BufferedResourceLoader*( int64 first_position, int64 last_position)); - protected: - MockBufferedDataSource( - MessageLoop* message_loop, MediaResourceLoaderBridgeFactory* factory) - : BufferedDataSource(message_loop, factory, NULL) { - } - private: - friend class media::FilterFactoryImpl2< - MockBufferedDataSource, - MessageLoop*, - MediaResourceLoaderBridgeFactory*>; - DISALLOW_COPY_AND_ASSIGN(MockBufferedDataSource); }; @@ -579,8 +562,6 @@ class BufferedDataSourceTest : public testing::Test { message_loop_ = MessageLoop::current(); bridge_factory_.reset( new StrictMock<MockMediaResourceLoaderBridgeFactory>()); - factory_ = MockBufferedDataSource::CreateFactory(message_loop_, - bridge_factory_.get()); // Prepare test data. for (size_t i = 0; i < sizeof(data_); ++i) { @@ -619,7 +600,8 @@ class BufferedDataSourceTest : public testing::Test { url_format.SetAsString(media::MediaFormat::kMimeType, media::mime_type::kURL); url_format.SetAsString(media::MediaFormat::kURL, url); - data_source_ = factory_->Create<MockBufferedDataSource>(url_format); + data_source_ = new MockBufferedDataSource(MessageLoop::current(), + bridge_factory_.get()); CHECK(data_source_); // There is no need to provide a message loop to data source. @@ -901,7 +883,6 @@ class BufferedDataSourceTest : public testing::Test { bridge_factory_; scoped_refptr<NiceMock<MockBufferedResourceLoader> > loader_; scoped_refptr<MockBufferedDataSource> data_source_; - scoped_refptr<media::FilterFactory> factory_; StrictMock<media::MockFilterHost> host_; GURL gurl_; diff --git a/webkit/glue/media/simple_data_source.cc b/webkit/glue/media/simple_data_source.cc index 0b09edf..256c910 100644 --- a/webkit/glue/media/simple_data_source.cc +++ b/webkit/glue/media/simple_data_source.cc @@ -28,19 +28,6 @@ bool IsDataProtocol(const GURL& url) { namespace webkit_glue { -bool SimpleDataSource::IsMediaFormatSupported( - const media::MediaFormat& media_format) { - std::string mime_type; - std::string url; - if (media_format.GetAsString(media::MediaFormat::kMimeType, &mime_type) && - media_format.GetAsString(media::MediaFormat::kURL, &url)) { - GURL gurl(url); - if (IsProtocolSupportedForMedia(gurl)) - return true; - } - return false; -} - SimpleDataSource::SimpleDataSource( MessageLoop* render_loop, webkit_glue::MediaResourceLoaderBridgeFactory* bridge_factory) diff --git a/webkit/glue/media/simple_data_source.h b/webkit/glue/media/simple_data_source.h index d649c0d..2ff851e 100644 --- a/webkit/glue/media/simple_data_source.h +++ b/webkit/glue/media/simple_data_source.h @@ -12,7 +12,6 @@ #include "base/message_loop.h" #include "base/scoped_ptr.h" -#include "media/base/factory.h" #include "media/base/filters.h" #include "webkit/glue/media/media_resource_loader_bridge_factory.h" @@ -24,19 +23,10 @@ namespace webkit_glue { class SimpleDataSource : public media::DataSource, public webkit_glue::ResourceLoaderBridge::Peer { public: - static media::FilterFactory* CreateFactory( - MessageLoop* message_loop, - webkit_glue::MediaResourceLoaderBridgeFactory* bridge_factory) { - return new media::FilterFactoryImpl2< - SimpleDataSource, - MessageLoop*, - webkit_glue::MediaResourceLoaderBridgeFactory*>(message_loop, - bridge_factory); - } - - // media::FilterFactoryImpl2 implementation. - static bool IsMediaFormatSupported( - const media::MediaFormat& media_format); + SimpleDataSource( + MessageLoop* render_loop, + webkit_glue::MediaResourceLoaderBridgeFactory* bridge_factory); + virtual ~SimpleDataSource(); // MediaFilter implementation. virtual void Stop(media::FilterCallback* callback); @@ -68,15 +58,6 @@ class SimpleDataSource : public media::DataSource, virtual GURL GetURLForDebugging() const; private: - friend class media::FilterFactoryImpl2< - SimpleDataSource, - MessageLoop*, - webkit_glue::MediaResourceLoaderBridgeFactory*>; - SimpleDataSource( - MessageLoop* render_loop, - webkit_glue::MediaResourceLoaderBridgeFactory* bridge_factory); - virtual ~SimpleDataSource(); - // Updates |url_| and |media_format_| with the given URL. void SetURL(const GURL& url); diff --git a/webkit/glue/media/simple_data_source_unittest.cc b/webkit/glue/media/simple_data_source_unittest.cc index 50c8910..537798f 100644 --- a/webkit/glue/media/simple_data_source_unittest.cc +++ b/webkit/glue/media/simple_data_source_unittest.cc @@ -42,8 +42,6 @@ class SimpleDataSourceTest : public testing::Test { bridge_factory_.reset( new NiceMock<MockMediaResourceLoaderBridgeFactory>()); bridge_.reset(new NiceMock<MockResourceLoaderBridge>()); - factory_ = SimpleDataSource::CreateFactory(MessageLoop::current(), - bridge_factory_.get()); for (int i = 0; i < kDataSize; ++i) { data_[i] = i; @@ -58,11 +56,8 @@ class SimpleDataSourceTest : public testing::Test { } void InitializeDataSource(const char* url) { - media::MediaFormat url_format; - url_format.SetAsString(media::MediaFormat::kMimeType, - media::mime_type::kURL); - url_format.SetAsString(media::MediaFormat::kURL, url); - data_source_ = factory_->Create<SimpleDataSource>(url_format); + data_source_ = new SimpleDataSource(MessageLoop::current(), + bridge_factory_.get()); CHECK(data_source_); // There is no need to provide a message loop to data source. @@ -167,7 +162,6 @@ class SimpleDataSourceTest : public testing::Test { scoped_ptr<MessageLoop> message_loop_; scoped_ptr<NiceMock<MockMediaResourceLoaderBridgeFactory> > bridge_factory_; scoped_ptr<NiceMock<MockResourceLoaderBridge> > bridge_; - scoped_refptr<media::FilterFactory> factory_; scoped_refptr<SimpleDataSource> data_source_; StrictMock<media::MockFilterHost> host_; StrictMock<media::MockFilterCallback> callback_; @@ -195,11 +189,9 @@ TEST_F(SimpleDataSourceTest, InitializeFile) { } TEST_F(SimpleDataSourceTest, InitializeData) { - media::MediaFormat url_format; - url_format.SetAsString(media::MediaFormat::kMimeType, - media::mime_type::kURL); - url_format.SetAsString(media::MediaFormat::kURL, kDataUrl); - data_source_ = factory_->Create<SimpleDataSource>(url_format); + data_source_ = new SimpleDataSource(MessageLoop::current(), + bridge_factory_.get()); + EXPECT_TRUE(data_source_->IsUrlSupported(kDataUrl)); CHECK(data_source_); // There is no need to provide a message loop to data source. @@ -217,15 +209,6 @@ TEST_F(SimpleDataSourceTest, InitializeData) { DestroyDataSource(); } -TEST_F(SimpleDataSourceTest, InitializeInvalid) { - media::MediaFormat url_format; - url_format.SetAsString(media::MediaFormat::kMimeType, - media::mime_type::kURL); - url_format.SetAsString(media::MediaFormat::kURL, kInvalidUrl); - data_source_ = factory_->Create<SimpleDataSource>(url_format); - EXPECT_FALSE(data_source_); -} - TEST_F(SimpleDataSourceTest, RequestFailed) { InitializeDataSource(kHttpUrl); RequestFailed(); diff --git a/webkit/glue/media/video_renderer_impl.cc b/webkit/glue/media/video_renderer_impl.cc index 16c9ef6..3bbd626 100644 --- a/webkit/glue/media/video_renderer_impl.cc +++ b/webkit/glue/media/video_renderer_impl.cc @@ -10,33 +10,13 @@ namespace webkit_glue { -VideoRendererImpl::VideoRendererImpl(WebMediaPlayerImpl::Proxy* proxy, - bool pts_logging) - : proxy_(proxy), - last_converted_frame_(NULL), +VideoRendererImpl::VideoRendererImpl(bool pts_logging) + : last_converted_frame_(NULL), pts_logging_(pts_logging) { - // TODO(hclam): decide whether to do the following line in this thread or - // in the render thread. - proxy_->SetVideoRenderer(this); } VideoRendererImpl::~VideoRendererImpl() {} -// static -media::FilterFactory* VideoRendererImpl::CreateFactory( - WebMediaPlayerImpl::Proxy* proxy, - bool pts_logging) { - return new media::FilterFactoryImpl2<VideoRendererImpl, - WebMediaPlayerImpl::Proxy*, - bool>(proxy, pts_logging); -} - -// static -bool VideoRendererImpl::IsMediaFormatSupported( - const media::MediaFormat& media_format) { - return ParseMediaFormat(media_format, NULL, NULL, NULL, NULL); -} - bool VideoRendererImpl::OnInitialize(media::VideoDecoder* decoder) { video_size_.SetSize(width(), height()); bitmap_.setConfig(SkBitmap::kARGB_8888_Config, width(), height()); @@ -60,6 +40,11 @@ void VideoRendererImpl::OnFrameAvailable() { proxy_->Repaint(); } +void VideoRendererImpl::SetWebMediaPlayerImplProxy( + WebMediaPlayerImpl::Proxy* proxy) { + proxy_ = proxy; +} + void VideoRendererImpl::SetRect(const gfx::Rect& rect) { } diff --git a/webkit/glue/media/video_renderer_impl.h b/webkit/glue/media/video_renderer_impl.h index 38e88514..34c67d3 100644 --- a/webkit/glue/media/video_renderer_impl.h +++ b/webkit/glue/media/video_renderer_impl.h @@ -24,39 +24,16 @@ namespace webkit_glue { class VideoRendererImpl : public WebVideoRenderer { public: + explicit VideoRendererImpl(bool pts_logging); + virtual ~VideoRendererImpl(); + // WebVideoRenderer implementation. + virtual void SetWebMediaPlayerImplProxy(WebMediaPlayerImpl::Proxy* proxy); virtual void SetRect(const gfx::Rect& rect); virtual void Paint(skia::PlatformCanvas* canvas, const gfx::Rect& dest_rect); virtual void GetCurrentFrame(scoped_refptr<media::VideoFrame>* frame_out); virtual void PutCurrentFrame(scoped_refptr<media::VideoFrame> frame); - // Static method for creating factory for this object. - static media::FilterFactory* CreateFactory(WebMediaPlayerImpl::Proxy* proxy, - bool pts_logging); - - // FilterFactoryImpl2 implementation. - static bool IsMediaFormatSupported(const media::MediaFormat& media_format); - - // TODO(scherkus): remove this mega-hack, see http://crbug.com/28207 - class FactoryFactory : public webkit_glue::WebVideoRendererFactoryFactory { - public: - FactoryFactory(bool pts_logging) - : webkit_glue::WebVideoRendererFactoryFactory(), - pts_logging_(pts_logging) { - } - - virtual media::FilterFactory* CreateFactory( - webkit_glue::WebMediaPlayerImpl::Proxy* proxy) { - return VideoRendererImpl::CreateFactory(proxy, pts_logging_); - } - - private: - // Whether we're logging video presentation timestamps (PTS). - bool pts_logging_; - - DISALLOW_COPY_AND_ASSIGN(FactoryFactory); - }; - protected: // Method called by VideoRendererBase during initialization. virtual bool OnInitialize(media::VideoDecoder* decoder); @@ -68,13 +45,6 @@ class VideoRendererImpl : public WebVideoRenderer { virtual void OnFrameAvailable(); private: - // Only the filter factories can create instances. - friend class media::FilterFactoryImpl2<VideoRendererImpl, - WebMediaPlayerImpl::Proxy*, - bool>; - VideoRendererImpl(WebMediaPlayerImpl::Proxy* proxy, bool pts_logging); - virtual ~VideoRendererImpl(); - // Determine the conditions to perform fast paint. Returns true if we can do // fast paint otherwise false. bool CanFastPaint(skia::PlatformCanvas* canvas, const gfx::Rect& dest_rect); diff --git a/webkit/glue/media/web_video_renderer.h b/webkit/glue/media/web_video_renderer.h index d8b47ad0..efd3109 100644 --- a/webkit/glue/media/web_video_renderer.h +++ b/webkit/glue/media/web_video_renderer.h @@ -7,6 +7,7 @@ #include "media/base/video_frame.h" #include "media/filters/video_renderer_base.h" +#include "webkit/glue/webmediaplayer_impl.h" namespace webkit_glue { @@ -16,6 +17,9 @@ class WebVideoRenderer : public media::VideoRendererBase { WebVideoRenderer() : media::VideoRendererBase() {} virtual ~WebVideoRenderer() {} + // Saves the reference to WebMediaPlayerImpl::Proxy. + virtual void SetWebMediaPlayerImplProxy(WebMediaPlayerImpl::Proxy* proxy) = 0; + // This method is called with the same rect as the Paint() method and could // be used by future implementations to implement an improved color space + // scale code on a separate thread. Since we always do the stretch on the diff --git a/webkit/glue/webmediaplayer_impl.cc b/webkit/glue/webmediaplayer_impl.cc index 205be78..3337c5d 100644 --- a/webkit/glue/webmediaplayer_impl.cc +++ b/webkit/glue/webmediaplayer_impl.cc @@ -88,12 +88,13 @@ void WebMediaPlayerImpl::Proxy::Repaint() { } } -void WebMediaPlayerImpl::Proxy::SetDataSource(WebDataSource* data_source) { +void WebMediaPlayerImpl::Proxy::SetDataSource( + scoped_refptr<WebDataSource> data_source) { data_source_ = data_source; } void WebMediaPlayerImpl::Proxy::SetVideoRenderer( - WebVideoRenderer* video_renderer) { + scoped_refptr<WebVideoRenderer> video_renderer) { video_renderer_ = video_renderer; } @@ -215,14 +216,15 @@ void WebMediaPlayerImpl::Proxy::PutCurrentFrame( WebMediaPlayerImpl::WebMediaPlayerImpl( WebKit::WebMediaPlayerClient* client, - media::FilterFactoryCollection* factory, - MediaResourceLoaderBridgeFactory* bridge_factory, + const media::MediaFilterCollection& collection, + MediaResourceLoaderBridgeFactory* bridge_factory_simple, + MediaResourceLoaderBridgeFactory* bridge_factory_buffered, bool use_simple_data_source, - WebVideoRendererFactoryFactory* video_renderer_factory) + scoped_refptr<WebVideoRenderer> web_video_renderer) : network_state_(WebKit::WebMediaPlayer::Empty), ready_state_(WebKit::WebMediaPlayer::HaveNothing), main_loop_(NULL), - filter_factory_(factory), + filter_collection_(collection), pipeline_thread_("PipelineThread"), paused_(true), playback_rate_(0.0f), @@ -232,10 +234,6 @@ WebMediaPlayerImpl::WebMediaPlayerImpl( DCHECK(!main_loop_); main_loop_ = MessageLoop::current(); - // Make sure this gets deleted. - scoped_ptr<WebVideoRendererFactoryFactory> - scoped_video_renderer_factory(video_renderer_factory); - // Create the pipeline and its thread. if (!pipeline_thread_.Start()) { NOTREACHED() << "Could not start PipelineThread"; @@ -249,6 +247,8 @@ WebMediaPlayerImpl::WebMediaPlayerImpl( // Creates the proxy. proxy_ = new Proxy(main_loop_, this); + web_video_renderer->SetWebMediaPlayerImplProxy(proxy_); + proxy_->SetVideoRenderer(web_video_renderer); // Set our pipeline callbacks. pipeline_->SetPipelineEndedCallback(NewCallback(proxy_.get(), @@ -259,28 +259,27 @@ WebMediaPlayerImpl::WebMediaPlayerImpl( &WebMediaPlayerImpl::Proxy::NetworkEventCallback)); // A simple data source that keeps all data in memory. - media::FilterFactory* simple_data_source_factory = - webkit_glue::SimpleDataSource::CreateFactory(MessageLoop::current(), - bridge_factory); + scoped_refptr<SimpleDataSource> simple_data_source = + new SimpleDataSource(MessageLoop::current(), bridge_factory_simple); + // A sophisticated data source that does memory caching. - media::FilterFactory* buffered_data_source_factory = - webkit_glue::BufferedDataSource::CreateFactory(MessageLoop::current(), - bridge_factory, - proxy_); + scoped_refptr<BufferedDataSource> buffered_data_source = + new BufferedDataSource(MessageLoop::current(), bridge_factory_buffered); + proxy_->SetDataSource(buffered_data_source); + if (use_simple_data_source) { - factory->AddFactory(simple_data_source_factory); - factory->AddFactory(buffered_data_source_factory); + filter_collection_.push_back(simple_data_source); + filter_collection_.push_back(buffered_data_source); } else { - factory->AddFactory(buffered_data_source_factory); - factory->AddFactory(simple_data_source_factory); + filter_collection_.push_back(buffered_data_source); + filter_collection_.push_back(simple_data_source); } // Add in the default filter factories. - filter_factory_->AddFactory(media::FFmpegDemuxer::CreateFilterFactory()); - filter_factory_->AddFactory(media::FFmpegAudioDecoder::CreateFactory()); - filter_factory_->AddFactory(media::FFmpegVideoDecoder::CreateFactory(NULL)); - filter_factory_->AddFactory(media::NullAudioRenderer::CreateFilterFactory()); - filter_factory_->AddFactory(video_renderer_factory->CreateFactory(proxy_)); + filter_collection_.push_back(new media::FFmpegDemuxer()); + filter_collection_.push_back(new media::FFmpegAudioDecoder()); + filter_collection_.push_back(new media::FFmpegVideoDecoder(NULL)); + filter_collection_.push_back(new media::NullAudioRenderer()); } WebMediaPlayerImpl::~WebMediaPlayerImpl() { @@ -304,7 +303,7 @@ void WebMediaPlayerImpl::load(const WebKit::WebURL& url) { SetNetworkState(WebKit::WebMediaPlayer::Loading); SetReadyState(WebKit::WebMediaPlayer::HaveNothing); pipeline_->Start( - filter_factory_.get(), + filter_collection_, url.spec(), NewCallback(proxy_.get(), &WebMediaPlayerImpl::Proxy::PipelineInitializationCallback)); diff --git a/webkit/glue/webmediaplayer_impl.h b/webkit/glue/webmediaplayer_impl.h index 30a8dcb..003d0b9 100644 --- a/webkit/glue/webmediaplayer_impl.h +++ b/webkit/glue/webmediaplayer_impl.h @@ -68,16 +68,11 @@ class GURL; -namespace media { -class FilterFactoryCollection; -} - namespace webkit_glue { class MediaResourceLoaderBridgeFactory; class WebDataSource; class WebVideoRenderer; -class WebVideoRendererFactoryFactory; class WebMediaPlayerImpl : public WebKit::WebMediaPlayer, public MessageLoop::DestructionObserver { @@ -97,8 +92,8 @@ class WebMediaPlayerImpl : public WebKit::WebMediaPlayer, // Public methods called from the video renderer. void Repaint(); - void SetVideoRenderer(WebVideoRenderer* video_renderer); - void SetDataSource(WebDataSource* data_source); + void SetVideoRenderer(scoped_refptr<WebVideoRenderer> video_renderer); + void SetDataSource(scoped_refptr<WebDataSource> data_source); // Public methods called from WebMediaPlayerImpl. void Paint(skia::PlatformCanvas* canvas, const gfx::Rect& dest_rect); @@ -153,9 +148,9 @@ class WebMediaPlayerImpl : public WebKit::WebMediaPlayer, }; // Construct a WebMediaPlayerImpl with reference to the client, and media - // filter factory collection. By providing the filter factory collection - // the implementor can provide more specific media filters that does resource - // loading and rendering. |factory| should contain filter factories for: + // filter collection. By providing the filter collection the implementor can + // provide more specific media filters that does resource loading and + // rendering. |collection| should contain filter factories for: // 1. Data source // 2. Audio renderer // 3. Video renderer (optional) @@ -170,16 +165,15 @@ class WebMediaPlayerImpl : public WebKit::WebMediaPlayer, // provided by WebKit to perform renderering. The simple data source does // resource loading by loading the whole resource object into memory. Null // audio renderer is a fake audio device that plays silence. Provider of the - // |factory| can override the default filters by adding extra filters to - // |factory| before calling this method. + // |collection| can override the default filters by adding extra filters to + // |collection| before calling this method. // - // |video_renderer_factory| is used to construct a factory that should create - // a subclass of WebVideoRenderer. Is deleted by WebMediaPlayerImpl. WebMediaPlayerImpl(WebKit::WebMediaPlayerClient* client, - media::FilterFactoryCollection* factory, - MediaResourceLoaderBridgeFactory* bridge_factory, + const media::MediaFilterCollection& collection, + MediaResourceLoaderBridgeFactory* bridge_factory_simple, + MediaResourceLoaderBridgeFactory* bridge_factory_buffered, bool use_simple_data_source, - WebVideoRendererFactoryFactory* video_renderer_factory); + scoped_refptr<WebVideoRenderer> web_video_renderer); virtual ~WebMediaPlayerImpl(); virtual void load(const WebKit::WebURL& url); @@ -285,8 +279,8 @@ class WebMediaPlayerImpl : public WebKit::WebMediaPlayer, // 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_; + // A collection of filters. + media::MediaFilterCollection filter_collection_; // The actual pipeline and the thread it runs on. scoped_refptr<media::PipelineImpl> pipeline_; @@ -322,29 +316,6 @@ class WebMediaPlayerImpl : public WebKit::WebMediaPlayer, DISALLOW_COPY_AND_ASSIGN(WebMediaPlayerImpl); }; -// TODO(scherkus): WebMediaPlayerImpl creates and injects its Proxy into a -// video renderer factory, so we need to (unfortunately) have a factory of a -// factory so we can receive the proxy pointer without violating the -// separation of renderer code from webkit glue code. This is part of a -// longer-term plan to rethink our FilterFactory strategy (refer to -// http://crbug.com/28207). -// -// Either that or we rethink this Proxy business as a short-term solution. -class WebVideoRendererFactoryFactory { - public: - WebVideoRendererFactoryFactory() {} - virtual ~WebVideoRendererFactoryFactory() {} - - // Creates a FilterFactory which should be capable of creating a - // WebVideoRenderer subclass. - virtual media::FilterFactory* CreateFactory( - WebMediaPlayerImpl::Proxy* proxy) = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(WebVideoRendererFactoryFactory); -}; - - } // namespace webkit_glue #endif // WEBKIT_GLUE_WEBMEDIAPLAYER_IMPL_H_ diff --git a/webkit/support/webkit_support.cc b/webkit/support/webkit_support.cc index c199cc3..6b5b9c3 100644 --- a/webkit/support/webkit_support.cc +++ b/webkit/support/webkit_support.cc @@ -265,15 +265,14 @@ WebPlugin* CreateWebPlugin(WebFrame* frame, WebKit::WebMediaPlayer* CreateMediaPlayer(WebFrame* frame, WebMediaPlayerClient* client) { - scoped_refptr<media::FilterFactoryCollection> factory = - new media::FilterFactoryCollection(); + media::MediaFilterCollection collection; appcache::WebApplicationCacheHostImpl* appcache_host = appcache::WebApplicationCacheHostImpl::FromFrame(frame); // TODO(hclam): this is the same piece of code as in RenderView, maybe they // should be grouped together. - webkit_glue::MediaResourceLoaderBridgeFactory* bridge_factory = + webkit_glue::MediaResourceLoaderBridgeFactory* bridge_factory_simple = new webkit_glue::MediaResourceLoaderBridgeFactory( GURL(), // referrer "null", // frame origin @@ -281,10 +280,22 @@ WebKit::WebMediaPlayer* CreateMediaPlayer(WebFrame* frame, base::GetCurrentProcId(), appcache_host ? appcache_host->host_id() : appcache::kNoHostId, 0); + webkit_glue::MediaResourceLoaderBridgeFactory* bridge_factory_buffered = + new webkit_glue::MediaResourceLoaderBridgeFactory( + GURL(), // referrer + "null", // frame origin + "null", // main_frame_origin + base::GetCurrentProcId(), + appcache_host ? appcache_host->host_id() : appcache::kNoHostId, + 0); + + scoped_refptr<webkit_glue::VideoRendererImpl> video_renderer = + new webkit_glue::VideoRendererImpl(false); + collection.push_back(video_renderer); return new webkit_glue::WebMediaPlayerImpl( - client, factory, bridge_factory, false, - new webkit_glue::VideoRendererImpl::FactoryFactory(false)); + client, collection, bridge_factory_simple, bridge_factory_buffered, + false, video_renderer); } WebKit::WebApplicationCacheHost* CreateApplicationCacheHost( diff --git a/webkit/tools/test_shell/test_webview_delegate.cc b/webkit/tools/test_shell/test_webview_delegate.cc index 0fb610f..8b0b4bc 100644 --- a/webkit/tools/test_shell/test_webview_delegate.cc +++ b/webkit/tools/test_shell/test_webview_delegate.cc @@ -716,15 +716,14 @@ WebWorker* TestWebViewDelegate::createWorker( WebMediaPlayer* TestWebViewDelegate::createMediaPlayer( WebFrame* frame, WebMediaPlayerClient* client) { - scoped_refptr<media::FilterFactoryCollection> factory = - new media::FilterFactoryCollection(); + media::MediaFilterCollection collection; appcache::WebApplicationCacheHostImpl* appcache_host = appcache::WebApplicationCacheHostImpl::FromFrame(frame); // TODO(hclam): this is the same piece of code as in RenderView, maybe they // should be grouped together. - webkit_glue::MediaResourceLoaderBridgeFactory* bridge_factory = + webkit_glue::MediaResourceLoaderBridgeFactory* bridge_factory_simple = new webkit_glue::MediaResourceLoaderBridgeFactory( GURL(frame->url()), // referrer "null", // frame origin @@ -732,10 +731,22 @@ WebMediaPlayer* TestWebViewDelegate::createMediaPlayer( base::GetCurrentProcId(), appcache_host ? appcache_host->host_id() : appcache::kNoHostId, 0); + webkit_glue::MediaResourceLoaderBridgeFactory* bridge_factory_buffered = + new webkit_glue::MediaResourceLoaderBridgeFactory( + GURL(frame->url()), // referrer + "null", // frame origin + "null", // main_frame_origin + base::GetCurrentProcId(), + appcache_host ? appcache_host->host_id() : appcache::kNoHostId, + 0); + + scoped_refptr<webkit_glue::VideoRendererImpl> video_renderer = + new webkit_glue::VideoRendererImpl(false); + collection.push_back(video_renderer); return new webkit_glue::WebMediaPlayerImpl( - client, factory, bridge_factory, false, - new webkit_glue::VideoRendererImpl::FactoryFactory(false)); + client, collection, bridge_factory_simple, bridge_factory_buffered, + false, video_renderer); } WebApplicationCacheHost* TestWebViewDelegate::createApplicationCacheHost( |