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 WEBRTC_MODULES_AUDIO_CODING_NETEQ_DECISION_LOGIC_H_
12 #define WEBRTC_MODULES_AUDIO_CODING_NETEQ_DECISION_LOGIC_H_
13 
14 #include "webrtc/base/constructormagic.h"
15 #include "webrtc/modules/audio_coding/neteq/defines.h"
16 #include "webrtc/modules/audio_coding/neteq/include/neteq.h"
17 #include "webrtc/typedefs.h"
18 
19 namespace webrtc {
20 
21 // Forward declarations.
22 class BufferLevelFilter;
23 class DecoderDatabase;
24 class DelayManager;
25 class Expand;
26 class PacketBuffer;
27 class SyncBuffer;
28 struct RTPHeader;
29 
30 // This is the base class for the decision tree implementations. Derived classes
31 // must implement the method GetDecisionSpecialized().
32 class DecisionLogic {
33  public:
34   // Static factory function which creates different types of objects depending
35   // on the |playout_mode|.
36   static DecisionLogic* Create(int fs_hz,
37                                size_t output_size_samples,
38                                NetEqPlayoutMode playout_mode,
39                                DecoderDatabase* decoder_database,
40                                const PacketBuffer& packet_buffer,
41                                DelayManager* delay_manager,
42                                BufferLevelFilter* buffer_level_filter);
43 
44   // Constructor.
45   DecisionLogic(int fs_hz,
46                 size_t output_size_samples,
47                 NetEqPlayoutMode playout_mode,
48                 DecoderDatabase* decoder_database,
49                 const PacketBuffer& packet_buffer,
50                 DelayManager* delay_manager,
51                 BufferLevelFilter* buffer_level_filter);
52 
53   // Destructor.
~DecisionLogic()54   virtual ~DecisionLogic() {}
55 
56   // Resets object to a clean state.
57   void Reset();
58 
59   // Resets parts of the state. Typically done when switching codecs.
60   void SoftReset();
61 
62   // Sets the sample rate and the output block size.
63   void SetSampleRate(int fs_hz, size_t output_size_samples);
64 
65   // Returns the operation that should be done next. |sync_buffer| and |expand|
66   // are provided for reference. |decoder_frame_length| is the number of samples
67   // obtained from the last decoded frame. If there is a packet available, the
68   // packet header should be supplied in |packet_header|; otherwise it should
69   // be NULL. The mode resulting form the last call to NetEqImpl::GetAudio is
70   // supplied in |prev_mode|. If there is a DTMF event to play, |play_dtmf|
71   // should be set to true. The output variable |reset_decoder| will be set to
72   // true if a reset is required; otherwise it is left unchanged (i.e., it can
73   // remain true if it was true before the call).
74   // This method end with calling GetDecisionSpecialized to get the actual
75   // return value.
76   Operations GetDecision(const SyncBuffer& sync_buffer,
77                          const Expand& expand,
78                          size_t decoder_frame_length,
79                          const RTPHeader* packet_header,
80                          Modes prev_mode,
81                          bool play_dtmf,
82                          bool* reset_decoder);
83 
84   // These methods test the |cng_state_| for different conditions.
CngRfc3389On()85   bool CngRfc3389On() const { return cng_state_ == kCngRfc3389On; }
CngOff()86   bool CngOff() const { return cng_state_ == kCngOff; }
87 
88   // Resets the |cng_state_| to kCngOff.
SetCngOff()89   void SetCngOff() { cng_state_ = kCngOff; }
90 
91   // Reports back to DecisionLogic whether the decision to do expand remains or
92   // not. Note that this is necessary, since an expand decision can be changed
93   // to kNormal in NetEqImpl::GetDecision if there is still enough data in the
94   // sync buffer.
95   virtual void ExpandDecision(Operations operation);
96 
97   // Adds |value| to |sample_memory_|.
AddSampleMemory(int32_t value)98   void AddSampleMemory(int32_t value) {
99     sample_memory_ += value;
100   }
101 
102   // Accessors and mutators.
set_sample_memory(int32_t value)103   void set_sample_memory(int32_t value) { sample_memory_ = value; }
generated_noise_samples()104   size_t generated_noise_samples() const { return generated_noise_samples_; }
set_generated_noise_samples(size_t value)105   void set_generated_noise_samples(size_t value) {
106     generated_noise_samples_ = value;
107   }
packet_length_samples()108   size_t packet_length_samples() const { return packet_length_samples_; }
set_packet_length_samples(size_t value)109   void set_packet_length_samples(size_t value) {
110     packet_length_samples_ = value;
111   }
set_prev_time_scale(bool value)112   void set_prev_time_scale(bool value) { prev_time_scale_ = value; }
playout_mode()113   NetEqPlayoutMode playout_mode() const { return playout_mode_; }
114 
115  protected:
116   // The value 6 sets maximum time-stretch rate to about 100 ms/s.
117   static const int kMinTimescaleInterval = 6;
118 
119   enum CngState {
120     kCngOff,
121     kCngRfc3389On,
122     kCngInternalOn
123   };
124 
125   // Returns the operation that should be done next. |sync_buffer| and |expand|
126   // are provided for reference. |decoder_frame_length| is the number of samples
127   // obtained from the last decoded frame. If there is a packet available, the
128   // packet header should be supplied in |packet_header|; otherwise it should
129   // be NULL. The mode resulting form the last call to NetEqImpl::GetAudio is
130   // supplied in |prev_mode|. If there is a DTMF event to play, |play_dtmf|
131   // should be set to true. The output variable |reset_decoder| will be set to
132   // true if a reset is required; otherwise it is left unchanged (i.e., it can
133   // remain true if it was true before the call).
134   // Should be implemented by derived classes.
135   virtual Operations GetDecisionSpecialized(const SyncBuffer& sync_buffer,
136                                             const Expand& expand,
137                                             size_t decoder_frame_length,
138                                             const RTPHeader* packet_header,
139                                             Modes prev_mode,
140                                             bool play_dtmf,
141                                             bool* reset_decoder) = 0;
142 
143   // Updates the |buffer_level_filter_| with the current buffer level
144   // |buffer_size_packets|.
145   void FilterBufferLevel(size_t buffer_size_packets, Modes prev_mode);
146 
147   DecoderDatabase* decoder_database_;
148   const PacketBuffer& packet_buffer_;
149   DelayManager* delay_manager_;
150   BufferLevelFilter* buffer_level_filter_;
151   int fs_mult_;
152   size_t output_size_samples_;
153   CngState cng_state_;  // Remember if comfort noise is interrupted by other
154                         // event (e.g., DTMF).
155   size_t generated_noise_samples_;
156   size_t packet_length_samples_;
157   int sample_memory_;
158   bool prev_time_scale_;
159   int timescale_hold_off_;
160   int num_consecutive_expands_;
161   const NetEqPlayoutMode playout_mode_;
162 
163  private:
164   RTC_DISALLOW_COPY_AND_ASSIGN(DecisionLogic);
165 };
166 
167 }  // namespace webrtc
168 #endif  // WEBRTC_MODULES_AUDIO_CODING_NETEQ_DECISION_LOGIC_H_
169