85edbb4dc7e5da507768cfc73c7ff7aab1541900
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / modules / audio_coding / neteq4 / decision_logic.cc
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 #include "webrtc/modules/audio_coding/neteq4/decision_logic.h"
12
13 #include <algorithm>
14
15 #include "webrtc/modules/audio_coding/neteq4/buffer_level_filter.h"
16 #include "webrtc/modules/audio_coding/neteq4/decision_logic_fax.h"
17 #include "webrtc/modules/audio_coding/neteq4/decision_logic_normal.h"
18 #include "webrtc/modules/audio_coding/neteq4/delay_manager.h"
19 #include "webrtc/modules/audio_coding/neteq4/expand.h"
20 #include "webrtc/modules/audio_coding/neteq4/packet_buffer.h"
21 #include "webrtc/modules/audio_coding/neteq4/sync_buffer.h"
22 #include "webrtc/system_wrappers/interface/logging.h"
23
24 namespace webrtc {
25
26 DecisionLogic* DecisionLogic::Create(int fs_hz,
27                                      int output_size_samples,
28                                      NetEqPlayoutMode playout_mode,
29                                      DecoderDatabase* decoder_database,
30                                      const PacketBuffer& packet_buffer,
31                                      DelayManager* delay_manager,
32                                      BufferLevelFilter* buffer_level_filter) {
33   switch (playout_mode) {
34     case kPlayoutOn:
35     case kPlayoutStreaming:
36       return new DecisionLogicNormal(fs_hz,
37                                      output_size_samples,
38                                      playout_mode,
39                                      decoder_database,
40                                      packet_buffer,
41                                      delay_manager,
42                                      buffer_level_filter);
43     case kPlayoutFax:
44     case kPlayoutOff:
45       return new DecisionLogicFax(fs_hz,
46                                   output_size_samples,
47                                   playout_mode,
48                                   decoder_database,
49                                   packet_buffer,
50                                   delay_manager,
51                                   buffer_level_filter);
52   }
53   // This line cannot be reached, but must be here to avoid compiler errors.
54   assert(false);
55   return NULL;
56 }
57
58 DecisionLogic::DecisionLogic(int fs_hz,
59                              int output_size_samples,
60                              NetEqPlayoutMode playout_mode,
61                              DecoderDatabase* decoder_database,
62                              const PacketBuffer& packet_buffer,
63                              DelayManager* delay_manager,
64                              BufferLevelFilter* buffer_level_filter)
65     : decoder_database_(decoder_database),
66       packet_buffer_(packet_buffer),
67       delay_manager_(delay_manager),
68       buffer_level_filter_(buffer_level_filter),
69       cng_state_(kCngOff),
70       generated_noise_samples_(0),
71       packet_length_samples_(0),
72       sample_memory_(0),
73       prev_time_scale_(false),
74       timescale_hold_off_(kMinTimescaleInterval),
75       num_consecutive_expands_(0),
76       playout_mode_(playout_mode) {
77   delay_manager_->set_streaming_mode(playout_mode_ == kPlayoutStreaming);
78   SetSampleRate(fs_hz, output_size_samples);
79 }
80
81 void DecisionLogic::Reset() {
82   cng_state_ = kCngOff;
83   generated_noise_samples_ = 0;
84   packet_length_samples_ = 0;
85   sample_memory_ = 0;
86   prev_time_scale_ = false;
87   timescale_hold_off_ = 0;
88   num_consecutive_expands_ = 0;
89 }
90
91 void DecisionLogic::SoftReset() {
92   packet_length_samples_ = 0;
93   sample_memory_ = 0;
94   prev_time_scale_ = false;
95   timescale_hold_off_ = kMinTimescaleInterval;
96 }
97
98 void DecisionLogic::SetSampleRate(int fs_hz, int output_size_samples) {
99   // TODO(hlundin): Change to an enumerator and skip assert.
100   assert(fs_hz == 8000 || fs_hz == 16000 || fs_hz ==  32000 || fs_hz == 48000);
101   fs_mult_ = fs_hz / 8000;
102   output_size_samples_ = output_size_samples;
103 }
104
105 Operations DecisionLogic::GetDecision(const SyncBuffer& sync_buffer,
106                                       const Expand& expand,
107                                       int decoder_frame_length,
108                                       const RTPHeader* packet_header,
109                                       Modes prev_mode,
110                                       bool play_dtmf, bool* reset_decoder) {
111   if (prev_mode == kModeRfc3389Cng ||
112       prev_mode == kModeCodecInternalCng ||
113       prev_mode == kModeExpand) {
114     // If last mode was CNG (or Expand, since this could be covering up for
115     // a lost CNG packet), increase the |generated_noise_samples_| counter.
116     generated_noise_samples_ += output_size_samples_;
117     // Remember that CNG is on. This is needed if comfort noise is interrupted
118     // by DTMF.
119     if (prev_mode == kModeRfc3389Cng) {
120       cng_state_ = kCngRfc3389On;
121     } else if (prev_mode == kModeCodecInternalCng) {
122       cng_state_ = kCngInternalOn;
123     }
124   }
125
126   const int samples_left = static_cast<int>(
127       sync_buffer.FutureLength() - expand.overlap_length());
128   const int cur_size_samples =
129       samples_left + packet_buffer_.NumSamplesInBuffer(decoder_database_,
130                                                        decoder_frame_length);
131   LOG(LS_VERBOSE) << "Buffers: " << packet_buffer_.NumPacketsInBuffer() <<
132       " packets * " << decoder_frame_length << " samples/packet + " <<
133       samples_left << " samples in sync buffer = " << cur_size_samples;
134
135   prev_time_scale_ = prev_time_scale_ &&
136       (prev_mode == kModeAccelerateSuccess ||
137           prev_mode == kModeAccelerateLowEnergy ||
138           prev_mode == kModePreemptiveExpandSuccess ||
139           prev_mode == kModePreemptiveExpandLowEnergy);
140
141   FilterBufferLevel(cur_size_samples, prev_mode);
142
143   return GetDecisionSpecialized(sync_buffer, expand, decoder_frame_length,
144                                 packet_header, prev_mode, play_dtmf,
145                                 reset_decoder);
146 }
147
148 void DecisionLogic::ExpandDecision(Operations operation) {
149   if (operation == kExpand) {
150     num_consecutive_expands_++;
151   } else {
152     num_consecutive_expands_ = 0;
153   }
154 }
155
156 void DecisionLogic::FilterBufferLevel(int buffer_size_samples,
157                                       Modes prev_mode) {
158   const int elapsed_time_ms = output_size_samples_ / (8 * fs_mult_);
159   delay_manager_->UpdateCounters(elapsed_time_ms);
160
161   // Do not update buffer history if currently playing CNG since it will bias
162   // the filtered buffer level.
163   if ((prev_mode != kModeRfc3389Cng) && (prev_mode != kModeCodecInternalCng)) {
164     buffer_level_filter_->SetTargetBufferLevel(
165         delay_manager_->base_target_level());
166
167     int buffer_size_packets = 0;
168     if (packet_length_samples_ > 0) {
169       // Calculate size in packets.
170       buffer_size_packets = buffer_size_samples / packet_length_samples_;
171     }
172     int sample_memory_local = 0;
173     if (prev_time_scale_) {
174       sample_memory_local = sample_memory_;
175       timescale_hold_off_ = kMinTimescaleInterval;
176     }
177     buffer_level_filter_->Update(buffer_size_packets, sample_memory_local,
178                                  packet_length_samples_);
179     prev_time_scale_ = false;
180   }
181
182   timescale_hold_off_ = std::max(timescale_hold_off_ - 1, 0);
183 }
184
185 }  // namespace webrtc