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/constructor_magic.h"
17 #include "rtc_base/system/rtc_export.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,         // Deprecated
31   kDelayAgnostic,          // Deprecated
32   kExperimentalAgc,
33   kExperimentalNs,
34   kBeamforming,               // Deprecated
35   kIntelligibility,           // Deprecated
36   kEchoCanceller3,            // Deprecated
37   kAecRefinedAdaptiveFilter,  // Deprecated
38   kLevelControl               // Deprecated
39 };
40 
41 // Class Config is designed to ease passing a set of options across webrtc code.
42 // Options are identified by typename in order to avoid incorrect casts.
43 //
44 // Usage:
45 // * declaring an option:
46 //    struct Algo1_CostFunction {
47 //      virtual float cost(int x) const { return x; }
48 //      virtual ~Algo1_CostFunction() {}
49 //    };
50 //
51 // * accessing an option:
52 //    config.Get<Algo1_CostFunction>().cost(value);
53 //
54 // * setting an option:
55 //    struct SqrCost : Algo1_CostFunction {
56 //      virtual float cost(int x) const { return x*x; }
57 //    };
58 //    config.Set<Algo1_CostFunction>(new SqrCost());
59 //
60 // Note: This class is thread-compatible (like STL containers).
61 class RTC_EXPORT Config {
62  public:
63   // Returns the option if set or a default constructed one.
64   // Callers that access options too often are encouraged to cache the result.
65   // Returned references are owned by this.
66   //
67   // Requires std::is_default_constructible<T>
68   template <typename T>
69   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>
74   void Set(T* value);
75 
76   Config();
77   ~Config();
78 
79  private:
80   struct BaseOption {
~BaseOptionBaseOption81     virtual ~BaseOption() {}
82   };
83 
84   template <typename T>
85   struct Option : BaseOption {
OptionOption86     explicit Option(T* v) : value(v) {}
~OptionOption87     ~Option() { delete value; }
88     T* value;
89   };
90 
91   template <typename T>
identifier()92   static ConfigOptionID identifier() {
93     return T::identifier;
94   }
95 
96   // Used to instantiate a default constructed object that doesn't needs to be
97   // owned. This allows Get<T> to be implemented without requiring explicitly
98   // locks.
99   template <typename T>
default_value()100   static const T& default_value() {
101     static const T* const def = new T();
102     return *def;
103   }
104 
105   typedef std::map<ConfigOptionID, BaseOption*> OptionMap;
106   OptionMap options_;
107 
108   // RTC_DISALLOW_COPY_AND_ASSIGN
109   Config(const Config&);
110   void operator=(const Config&);
111 };
112 
113 template <typename T>
Get()114 const T& Config::Get() const {
115   OptionMap::const_iterator it = options_.find(identifier<T>());
116   if (it != options_.end()) {
117     const T* t = static_cast<Option<T>*>(it->second)->value;
118     if (t) {
119       return *t;
120     }
121   }
122   return default_value<T>();
123 }
124 
125 template <typename T>
Set(T * value)126 void Config::Set(T* value) {
127   BaseOption*& it = options_[identifier<T>()];
128   delete it;
129   it = new Option<T>(value);
130 }
131 }  // namespace webrtc
132 
133 #endif  // MODULES_AUDIO_PROCESSING_INCLUDE_CONFIG_H_
134