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