1 /*
2  *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #ifndef MODULES_AUDIO_PROCESSING_INCLUDE_CONFIG_H_
12 #define MODULES_AUDIO_PROCESSING_INCLUDE_CONFIG_H_
13 
14 #include <map>
15 
16 #include "rtc_base/basictypes.h"
17 #include "rtc_base/constructormagic.h"
18 
19 namespace webrtc {
20 
21 // Only add new values to the end of the enumeration and never remove (only
22 // deprecate) to maintain binary compatibility.
23 enum class ConfigOptionID {
24   kMyExperimentForTest,
25   kAlgo1CostFunctionForTest,
26   kTemporalLayersFactory,  // Deprecated
27   kNetEqCapacityConfig,    // Deprecated
28   kNetEqFastAccelerate,    // Deprecated
29   kVoicePacing,            // Deprecated
30   kExtendedFilter,
31   kDelayAgnostic,
32   kExperimentalAgc,
33   kExperimentalNs,
34   kBeamforming,
35   kIntelligibility,
36   kEchoCanceller3,  // Deprecated
37   kAecRefinedAdaptiveFilter,
38   kLevelControl,
39   kCaptureDeviceInfo
40 };
41 
42 // Class Config is designed to ease passing a set of options across webrtc code.
43 // Options are identified by typename in order to avoid incorrect casts.
44 //
45 // Usage:
46 // * declaring an option:
47 //    struct Algo1_CostFunction {
48 //      virtual float cost(int x) const { return x; }
49 //      virtual ~Algo1_CostFunction() {}
50 //    };
51 //
52 // * accessing an option:
53 //    config.Get<Algo1_CostFunction>().cost(value);
54 //
55 // * setting an option:
56 //    struct SqrCost : Algo1_CostFunction {
57 //      virtual float cost(int x) const { return x*x; }
58 //    };
59 //    config.Set<Algo1_CostFunction>(new SqrCost());
60 //
61 // Note: This class is thread-compatible (like STL containers).
62 class Config {
63  public:
64   // Returns the option if set or a default constructed one.
65   // Callers that access options too often are encouraged to cache the result.
66   // Returned references are owned by this.
67   //
68   // Requires std::is_default_constructible<T>
69   template<typename T> const T& Get() const;
70 
71   // Set the option, deleting any previous instance of the same.
72   // This instance gets ownership of the newly set value.
73   template<typename T> void Set(T* value);
74 
75   Config();
76   ~Config();
77 
78  private:
79   struct BaseOption {
~BaseOptionBaseOption80     virtual ~BaseOption() {}
81   };
82 
83   template<typename T>
84   struct Option : BaseOption {
OptionOption85     explicit Option(T* v): value(v) {}
~OptionOption86     ~Option() {
87       delete value;
88     }
89     T* value;
90   };
91 
92   template<typename T>
identifier()93   static ConfigOptionID identifier() {
94     return T::identifier;
95   }
96 
97   // Used to instantiate a default constructed object that doesn't needs to be
98   // owned. This allows Get<T> to be implemented without requiring explicitly
99   // locks.
100   template<typename T>
default_value()101   static const T& default_value() {
102     RTC_DEFINE_STATIC_LOCAL(const T, def, ());
103     return def;
104   }
105 
106   typedef std::map<ConfigOptionID, BaseOption*> OptionMap;
107   OptionMap options_;
108 
109   // RTC_DISALLOW_COPY_AND_ASSIGN
110   Config(const Config&);
111   void operator=(const Config&);
112 };
113 
114 template<typename T>
Get()115 const T& Config::Get() const {
116   OptionMap::const_iterator it = options_.find(identifier<T>());
117   if (it != options_.end()) {
118     const T* t = static_cast<Option<T>*>(it->second)->value;
119     if (t) {
120       return *t;
121     }
122   }
123   return default_value<T>();
124 }
125 
126 template<typename T>
Set(T * value)127 void Config::Set(T* value) {
128   BaseOption*& it = options_[identifier<T>()];
129   delete it;
130   it = new Option<T>(value);
131 }
132 }  // namespace webrtc
133 
134 #endif  // MODULES_AUDIO_PROCESSING_INCLUDE_CONFIG_H_
135