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
20namespace webrtc {
21
22Operations 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