Line data Source code
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/neteq/decision_logic_normal.h"
12 :
13 : #include <assert.h>
14 :
15 : #include <algorithm>
16 :
17 : #include "webrtc/modules/audio_coding/neteq/buffer_level_filter.h"
18 : #include "webrtc/modules/audio_coding/neteq/decoder_database.h"
19 : #include "webrtc/modules/audio_coding/neteq/delay_manager.h"
20 : #include "webrtc/modules/audio_coding/neteq/expand.h"
21 : #include "webrtc/modules/audio_coding/neteq/packet_buffer.h"
22 : #include "webrtc/modules/audio_coding/neteq/sync_buffer.h"
23 : #include "webrtc/modules/include/module_common_types.h"
24 :
25 : namespace webrtc {
26 :
27 0 : Operations DecisionLogicNormal::GetDecisionSpecialized(
28 : const SyncBuffer& sync_buffer,
29 : const Expand& expand,
30 : size_t decoder_frame_length,
31 : const Packet* next_packet,
32 : Modes prev_mode,
33 : bool play_dtmf,
34 : bool* reset_decoder,
35 : size_t generated_noise_samples) {
36 0 : assert(playout_mode_ == kPlayoutOn || playout_mode_ == kPlayoutStreaming);
37 : // Guard for errors, to avoid getting stuck in error mode.
38 0 : if (prev_mode == kModeError) {
39 0 : if (!next_packet) {
40 0 : return kExpand;
41 : } else {
42 0 : return kUndefined; // Use kUndefined to flag for a reset.
43 : }
44 : }
45 :
46 0 : uint32_t target_timestamp = sync_buffer.end_timestamp();
47 0 : uint32_t available_timestamp = 0;
48 0 : bool is_cng_packet = false;
49 0 : if (next_packet) {
50 0 : available_timestamp = next_packet->timestamp;
51 : is_cng_packet =
52 0 : decoder_database_->IsComfortNoise(next_packet->payload_type);
53 : }
54 :
55 0 : if (is_cng_packet) {
56 : return CngOperation(prev_mode, target_timestamp, available_timestamp,
57 0 : generated_noise_samples);
58 : }
59 :
60 : // Handle the case with no packet at all available (except maybe DTMF).
61 0 : if (!next_packet) {
62 0 : return NoPacket(play_dtmf);
63 : }
64 :
65 : // If the expand period was very long, reset NetEQ since it is likely that the
66 : // sender was restarted.
67 0 : if (num_consecutive_expands_ > kReinitAfterExpands) {
68 0 : *reset_decoder = true;
69 0 : return kNormal;
70 : }
71 :
72 : const uint32_t five_seconds_samples =
73 0 : static_cast<uint32_t>(5 * 8000 * fs_mult_);
74 : // Check if the required packet is available.
75 0 : if (target_timestamp == available_timestamp) {
76 0 : return ExpectedPacketAvailable(prev_mode, play_dtmf);
77 0 : } else if (!PacketBuffer::IsObsoleteTimestamp(
78 : available_timestamp, target_timestamp, five_seconds_samples)) {
79 0 : return FuturePacketAvailable(sync_buffer, expand, decoder_frame_length,
80 : prev_mode, target_timestamp,
81 : available_timestamp, play_dtmf,
82 0 : generated_noise_samples);
83 : } else {
84 : // This implies that available_timestamp < target_timestamp, which can
85 : // happen when a new stream or codec is received. Signal for a reset.
86 0 : return kUndefined;
87 : }
88 : }
89 :
90 0 : Operations DecisionLogicNormal::CngOperation(Modes prev_mode,
91 : uint32_t target_timestamp,
92 : uint32_t available_timestamp,
93 : size_t generated_noise_samples) {
94 : // Signed difference between target and available timestamp.
95 : int32_t timestamp_diff = static_cast<int32_t>(
96 0 : static_cast<uint32_t>(generated_noise_samples + target_timestamp) -
97 0 : available_timestamp);
98 : int32_t optimal_level_samp = static_cast<int32_t>(
99 0 : (delay_manager_->TargetLevel() * packet_length_samples_) >> 8);
100 0 : int32_t excess_waiting_time_samp = -timestamp_diff - optimal_level_samp;
101 :
102 0 : if (excess_waiting_time_samp > optimal_level_samp / 2) {
103 : // The waiting time for this packet will be longer than 1.5
104 : // times the wanted buffer delay. Apply fast-forward to cut the
105 : // waiting time down to the optimal.
106 0 : noise_fast_forward_ += excess_waiting_time_samp;
107 0 : timestamp_diff += excess_waiting_time_samp;
108 : }
109 :
110 0 : if (timestamp_diff < 0 && prev_mode == kModeRfc3389Cng) {
111 : // Not time to play this packet yet. Wait another round before using this
112 : // packet. Keep on playing CNG from previous CNG parameters.
113 0 : return kRfc3389CngNoPacket;
114 : } else {
115 : // Otherwise, go for the CNG packet now.
116 0 : noise_fast_forward_ = 0;
117 0 : return kRfc3389Cng;
118 : }
119 : }
120 :
121 0 : Operations DecisionLogicNormal::NoPacket(bool play_dtmf) {
122 0 : if (cng_state_ == kCngRfc3389On) {
123 : // Keep on playing comfort noise.
124 0 : return kRfc3389CngNoPacket;
125 0 : } else if (cng_state_ == kCngInternalOn) {
126 : // Keep on playing codec internal comfort noise.
127 0 : return kCodecInternalCng;
128 0 : } else if (play_dtmf) {
129 0 : return kDtmf;
130 : } else {
131 : // Nothing to play, do expand.
132 0 : return kExpand;
133 : }
134 : }
135 :
136 0 : Operations DecisionLogicNormal::ExpectedPacketAvailable(Modes prev_mode,
137 : bool play_dtmf) {
138 0 : if (prev_mode != kModeExpand && !play_dtmf) {
139 : // Check criterion for time-stretching.
140 : int low_limit, high_limit;
141 0 : delay_manager_->BufferLimits(&low_limit, &high_limit);
142 0 : if (buffer_level_filter_->filtered_current_level() >= high_limit << 2)
143 0 : return kFastAccelerate;
144 0 : if (TimescaleAllowed()) {
145 0 : if (buffer_level_filter_->filtered_current_level() >= high_limit)
146 0 : return kAccelerate;
147 0 : if (buffer_level_filter_->filtered_current_level() < low_limit)
148 0 : return kPreemptiveExpand;
149 : }
150 : }
151 0 : return kNormal;
152 : }
153 :
154 0 : Operations DecisionLogicNormal::FuturePacketAvailable(
155 : const SyncBuffer& sync_buffer,
156 : const Expand& expand,
157 : size_t decoder_frame_length,
158 : Modes prev_mode,
159 : uint32_t target_timestamp,
160 : uint32_t available_timestamp,
161 : bool play_dtmf,
162 : size_t generated_noise_samples) {
163 : // Required packet is not available, but a future packet is.
164 : // Check if we should continue with an ongoing expand because the new packet
165 : // is too far into the future.
166 0 : uint32_t timestamp_leap = available_timestamp - target_timestamp;
167 0 : if ((prev_mode == kModeExpand) &&
168 0 : !ReinitAfterExpands(timestamp_leap) &&
169 0 : !MaxWaitForPacket() &&
170 0 : PacketTooEarly(timestamp_leap) &&
171 0 : UnderTargetLevel()) {
172 0 : if (play_dtmf) {
173 : // Still have DTMF to play, so do not do expand.
174 0 : return kDtmf;
175 : } else {
176 : // Nothing to play.
177 0 : return kExpand;
178 : }
179 : }
180 :
181 : const size_t samples_left =
182 0 : sync_buffer.FutureLength() - expand.overlap_length();
183 : const size_t cur_size_samples = samples_left +
184 0 : packet_buffer_.NumPacketsInBuffer() * decoder_frame_length;
185 :
186 : // If previous was comfort noise, then no merge is needed.
187 0 : if (prev_mode == kModeRfc3389Cng ||
188 : prev_mode == kModeCodecInternalCng) {
189 : // Keep the same delay as before the CNG (or maximum 70 ms in buffer as
190 : // safety precaution), but make sure that the number of samples in buffer
191 : // is no higher than 4 times the optimal level. (Note that TargetLevel()
192 : // is in Q8.)
193 0 : if (static_cast<uint32_t>(generated_noise_samples + target_timestamp) >=
194 0 : available_timestamp ||
195 : cur_size_samples >
196 0 : ((delay_manager_->TargetLevel() * packet_length_samples_) >> 8) *
197 : 4) {
198 : // Time to play this new packet.
199 0 : return kNormal;
200 : } else {
201 : // Too early to play this new packet; keep on playing comfort noise.
202 0 : if (prev_mode == kModeRfc3389Cng) {
203 0 : return kRfc3389CngNoPacket;
204 : } else { // prevPlayMode == kModeCodecInternalCng.
205 0 : return kCodecInternalCng;
206 : }
207 : }
208 : }
209 : // Do not merge unless we have done an expand before.
210 0 : if (prev_mode == kModeExpand) {
211 0 : return kMerge;
212 0 : } else if (play_dtmf) {
213 : // Play DTMF instead of expand.
214 0 : return kDtmf;
215 : } else {
216 0 : return kExpand;
217 : }
218 : }
219 :
220 0 : bool DecisionLogicNormal::UnderTargetLevel() const {
221 0 : return buffer_level_filter_->filtered_current_level() <=
222 0 : delay_manager_->TargetLevel();
223 : }
224 :
225 0 : bool DecisionLogicNormal::ReinitAfterExpands(uint32_t timestamp_leap) const {
226 0 : return timestamp_leap >=
227 0 : static_cast<uint32_t>(output_size_samples_ * kReinitAfterExpands);
228 : }
229 :
230 0 : bool DecisionLogicNormal::PacketTooEarly(uint32_t timestamp_leap) const {
231 0 : return timestamp_leap >
232 0 : static_cast<uint32_t>(output_size_samples_ * num_consecutive_expands_);
233 : }
234 :
235 0 : bool DecisionLogicNormal::MaxWaitForPacket() const {
236 0 : return num_consecutive_expands_ >= kMaxWaitForPacket;
237 : }
238 :
239 : } // namespace webrtc
|