diff options
Diffstat (limited to 'media/base/factory.h')
-rw-r--r-- | media/base/factory.h | 136 |
1 files changed, 136 insertions, 0 deletions
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<YourAudioDecoder>()); +// filter_factory->AddFactory(new TypeFilterFactory<YourAudioRenderer>()); +// etc... +// AudioDecoderInterface* filter; +// if (filter_factory->Create<AudioDecoderInterface>(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/ref_counted.h" +#include "media/base/filters.h" + +namespace media { + +class FilterFactoryCollection; + +class FilterFactory : base::RefCountedThreadSafe<FilterFactory> { + 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<AudioDecoderInterface>(media_format, &filter); + template <class T> + bool Create(const MediaFormat* media_format, T** filter_out) { + return Create(T::kFilterType, media_format, + reinterpret_cast<MediaFilterInterface**>(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<FilterFactory>; + 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<YourFilterType>() +template <class T> +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<FilterFactory> > FactoryVector; + FactoryVector factories_; + + DISALLOW_COPY_AND_ASSIGN(FilterFactoryCollection); +}; + +} // namespace media + +#endif // MEDIA_BASE_FACTORY_H_ |