summaryrefslogtreecommitdiffstats
path: root/media/base/factory.h
blob: f735fe1b8c3dabe57612b497decea8cc36a67ecd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
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_