| /* | 
 |  *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. | 
 |  * | 
 |  *  Use of this source code is governed by a BSD-style license | 
 |  *  that can be found in the LICENSE file in the root of the source | 
 |  *  tree. An additional intellectual property rights grant can be found | 
 |  *  in the file PATENTS.  All contributing project authors may | 
 |  *  be found in the AUTHORS file in the root of the source tree. | 
 |  */ | 
 |  | 
 | #include "webrtc/modules/audio_coding/neteq/decision_logic_fax.h" | 
 |  | 
 | #include <assert.h> | 
 |  | 
 | #include <algorithm> | 
 |  | 
 | #include "webrtc/modules/audio_coding/neteq/decoder_database.h" | 
 | #include "webrtc/modules/audio_coding/neteq/sync_buffer.h" | 
 |  | 
 | namespace webrtc { | 
 |  | 
 | Operations DecisionLogicFax::GetDecisionSpecialized( | 
 |     const SyncBuffer& sync_buffer, | 
 |     const Expand& expand, | 
 |     size_t decoder_frame_length, | 
 |     const RTPHeader* packet_header, | 
 |     Modes prev_mode, | 
 |     bool play_dtmf, | 
 |     bool* reset_decoder) { | 
 |   assert(playout_mode_ == kPlayoutFax || playout_mode_ == kPlayoutOff); | 
 |   uint32_t target_timestamp = sync_buffer.end_timestamp(); | 
 |   uint32_t available_timestamp = 0; | 
 |   int is_cng_packet = 0; | 
 |   if (packet_header) { | 
 |     available_timestamp = packet_header->timestamp; | 
 |     is_cng_packet = | 
 |         decoder_database_->IsComfortNoise(packet_header->payloadType); | 
 |   } | 
 |   if (is_cng_packet) { | 
 |     if (static_cast<int32_t>((generated_noise_samples_ + target_timestamp) | 
 |         - available_timestamp) >= 0) { | 
 |       // Time to play this packet now. | 
 |       return kRfc3389Cng; | 
 |     } else { | 
 |       // Wait before playing this packet. | 
 |       return kRfc3389CngNoPacket; | 
 |     } | 
 |   } | 
 |   if (!packet_header) { | 
 |     // No packet. If in CNG mode, play as usual. Otherwise, use other method to | 
 |     // generate data. | 
 |     if (cng_state_ == kCngRfc3389On) { | 
 |       // Continue playing comfort noise. | 
 |       return kRfc3389CngNoPacket; | 
 |     } else if (cng_state_ == kCngInternalOn) { | 
 |       // Continue playing codec-internal comfort noise. | 
 |       return kCodecInternalCng; | 
 |     } else { | 
 |       // Nothing to play. Generate some data to play out. | 
 |       switch (playout_mode_) { | 
 |         case kPlayoutOff: | 
 |           return kAlternativePlc; | 
 |         case kPlayoutFax: | 
 |           return kAudioRepetition; | 
 |         default: | 
 |           assert(false); | 
 |           return kUndefined; | 
 |       } | 
 |     } | 
 |   } else if (target_timestamp == available_timestamp) { | 
 |     return kNormal; | 
 |   } else { | 
 |     if (static_cast<int32_t>((generated_noise_samples_ + target_timestamp) | 
 |         - available_timestamp) >= 0) { | 
 |       return kNormal; | 
 |     } else { | 
 |       // If currently playing comfort noise, continue with that. Do not | 
 |       // increase the timestamp counter since generated_noise_samples_ will | 
 |       // be increased. | 
 |       if (cng_state_ == kCngRfc3389On) { | 
 |         return kRfc3389CngNoPacket; | 
 |       } else if (cng_state_ == kCngInternalOn) { | 
 |         return kCodecInternalCng; | 
 |       } else { | 
 |         // Otherwise, do packet-loss concealment and increase the | 
 |         // timestamp while waiting for the time to play this packet. | 
 |         switch (playout_mode_) { | 
 |           case kPlayoutOff: | 
 |             return kAlternativePlcIncreaseTimestamp; | 
 |           case kPlayoutFax: | 
 |             return kAudioRepetitionIncreaseTimestamp; | 
 |           default: | 
 |             assert(0); | 
 |             return kUndefined; | 
 |         } | 
 |       } | 
 |     } | 
 |   } | 
 | } | 
 |  | 
 |  | 
 | }  // namespace webrtc |