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_fax.h"
12
13 #include <assert.h>
14
15 #include <algorithm>
16
17 #include "webrtc/modules/audio_coding/neteq/decoder_database.h"
18 #include "webrtc/modules/audio_coding/neteq/sync_buffer.h"
19
20 namespace webrtc {
21
GetDecisionSpecialized(const SyncBuffer & sync_buffer,const Expand & expand,int decoder_frame_length,const RTPHeader * packet_header,Modes prev_mode,bool play_dtmf,bool * reset_decoder)22 Operations DecisionLogicFax::GetDecisionSpecialized(
23 const SyncBuffer& sync_buffer,
24 const Expand& expand,
25 int decoder_frame_length,
26 const RTPHeader* packet_header,
27 Modes prev_mode,
28 bool play_dtmf,
29 bool* reset_decoder) {
30 assert(playout_mode_ == kPlayoutFax || playout_mode_ == kPlayoutOff);
31 uint32_t target_timestamp = sync_buffer.end_timestamp();
32 uint32_t available_timestamp = 0;
33 int is_cng_packet = 0;
34 if (packet_header) {
35 available_timestamp = packet_header->timestamp;
36 is_cng_packet =
37 decoder_database_->IsComfortNoise(packet_header->payloadType);
38 }
39 if (is_cng_packet) {
40 if (static_cast<int32_t>((generated_noise_samples_ + target_timestamp)
41 - available_timestamp) >= 0) {
42 // Time to play this packet now.
43 return kRfc3389Cng;
44 } else {
45 // Wait before playing this packet.
46 return kRfc3389CngNoPacket;
47 }
48 }
49 if (!packet_header) {
50 // No packet. If in CNG mode, play as usual. Otherwise, use other method to
51 // generate data.
52 if (cng_state_ == kCngRfc3389On) {
53 // Continue playing comfort noise.
54 return kRfc3389CngNoPacket;
55 } else if (cng_state_ == kCngInternalOn) {
56 // Continue playing codec-internal comfort noise.
57 return kCodecInternalCng;
58 } else {
59 // Nothing to play. Generate some data to play out.
60 switch (playout_mode_) {
61 case kPlayoutOff:
62 return kAlternativePlc;
63 case kPlayoutFax:
64 return kAudioRepetition;
65 default:
66 assert(false);
67 return kUndefined;
68 }
69 }
70 } else if (target_timestamp == available_timestamp) {
71 return kNormal;
72 } else {
73 if (static_cast<int32_t>((generated_noise_samples_ + target_timestamp)
74 - available_timestamp) >= 0) {
75 return kNormal;
76 } else {
77 // If currently playing comfort noise, continue with that. Do not
78 // increase the timestamp counter since generated_noise_samples_ will
79 // be increased.
80 if (cng_state_ == kCngRfc3389On) {
81 return kRfc3389CngNoPacket;
82 } else if (cng_state_ == kCngInternalOn) {
83 return kCodecInternalCng;
84 } else {
85 // Otherwise, do packet-loss concealment and increase the
86 // timestamp while waiting for the time to play this packet.
87 switch (playout_mode_) {
88 case kPlayoutOff:
89 return kAlternativePlcIncreaseTimestamp;
90 case kPlayoutFax:
91 return kAudioRepetitionIncreaseTimestamp;
92 default:
93 assert(0);
94 return kUndefined;
95 }
96 }
97 }
98 }
99 }
100
101
102 } // namespace webrtc
103