From cd5d1ee7279537830a95169766f81fec69b6bd1b Mon Sep 17 00:00:00 2001 From: "scherkus@chromium.org" Date: Thu, 15 Jan 2009 02:07:51 +0000 Subject: Checking in filter factory code. Read the comments in media/base/factory.h for details. Review URL: http://codereview.chromium.org/17257 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@8071 0039d316-1c4b-4281-b951-d872f2087c98 --- media/base/factory.h | 136 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 media/base/factory.h (limited to 'media/base/factory.h') diff --git a/media/base/factory.h b/media/base/factory.h new file mode 100644 index 0000000..f735fe1 --- /dev/null +++ b/media/base/factory.h @@ -0,0 +1,136 @@ +// Copyright (c) 2006-2008 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()); +// filter_factory->AddFactory(new TypeFilterFactory()); +// etc... +// AudioDecoderInterface* filter; +// if (filter_factory->Create(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 + +#include "base/ref_counted.h" +#include "media/base/filters.h" + +namespace media { + +class FilterFactoryCollection; + +class FilterFactory : base::RefCountedThreadSafe { + public: + // Creates a filter implementing the specified interface. Hides the casting + // and FilterType constants from the callers and produces cleaner code: + // AudioDecoderInterface* filter = NULL; + // bool success = Create(media_format, &filter); + template + bool Create(const MediaFormat* media_format, T** filter_out) { + return Create(T::kFilterType, media_format, + reinterpret_cast(filter_out)); + } + + 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 assigned to |filter_out| + // and the method returns true. If the filter cannot be created for any + // reason, |filter_out| is assigned NULL and false it returned. + // + // It is assumed that |filter_out| can be safely casted to the corresponding + // interface type (i.e., FILTER_AUDIO_DECODER -> AudioDecoderInterface). + virtual bool Create(FilterType filter_type, const MediaFormat* media_format, + MediaFilterInterface** filter_out) = 0; + + friend class base::RefCountedThreadSafe; + virtual ~FilterFactory() {} +}; + + +// Helper template class for implementing trivial filter factories. If your +// filter does not require any special handling during creation, you can create +// a factory for it using this class. It requires the following static method: +// bool Create(MediaFormat* media_format, YourFilterType** filter_out) +// +// You can create the filter factory like so: +// new TypeFilterFactory() +template +class TypeFilterFactory : public FilterFactory { + public: + TypeFilterFactory() {} + + protected: + // Attempts to create a filter of the template type. Assumes a static method + // Create is declared. + virtual bool Create(FilterType filter_type, const MediaFormat* media_format, + MediaFilterInterface** filter_out) { + T* typed_out; + if (T::kFilterType == filter_type && T::Create(media_format, &typed_out)) { + *filter_out = typed_out; + return true; + } + return false; + } + + private: + DISALLOW_COPY_AND_ASSIGN(TypeFilterFactory); +}; + + +// Maintains a collection of FilterFactories. +class FilterFactoryCollection : public FilterFactory { + public: + FilterFactoryCollection() {} + + // Adds a factory to the end of the collection. + void AddFactory(FilterFactory* factory) { + factories_.push_back(factory); + } + + protected: + // Attempts to create a filter by walking down the list of filter factories. + bool Create(FilterType filter_type, const MediaFormat* media_format, + MediaFilterInterface** filter_out) { + for (FactoryVector::iterator factory = factories_.begin(); + factory != factories_.end(); + ++factory) { + if ((*factory)->Create(filter_type, media_format, filter_out)) { + return true; + } + } + return false; + } + + private: + typedef std::vector< scoped_refptr > FactoryVector; + FactoryVector factories_; + + DISALLOW_COPY_AND_ASSIGN(FilterFactoryCollection); +}; + +} // namespace media + +#endif // MEDIA_BASE_FACTORY_H_ -- cgit v1.1