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