text: /*
   *  Copyright (c) 2012 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.
   */
  
  #ifndef WEBRTC_MODULES_AUDIO_CODING_ACM2_AUDIO_CODING_MODULE_IMPL_H_
  #define WEBRTC_MODULES_AUDIO_CODING_ACM2_AUDIO_CODING_MODULE_IMPL_H_
  
  #include <memory>
  #include <string>
  #include <vector>
  
  #include "webrtc/base/buffer.h"
  #include "webrtc/base/criticalsection.h"
  #include "webrtc/base/thread_annotations.h"
  #include "webrtc/common_types.h"
  #include "webrtc/engine_configurations.h"
  #include "webrtc/modules/audio_coding/acm2/acm_receiver.h"
  #include "webrtc/modules/audio_coding/acm2/acm_resampler.h"
  #include "webrtc/modules/audio_coding/acm2/codec_manager.h"
  
  namespace webrtc {
  
  class AudioCodingImpl;
  
  namespace acm2 {
  
  class AudioCodingModuleImpl final : public AudioCodingModule {
   public:
    friend webrtc::AudioCodingImpl;
  
    explicit AudioCodingModuleImpl(const AudioCodingModule::Config& config);
    ~AudioCodingModuleImpl() override;
  
    /////////////////////////////////////////
    //   Sender
    //
  
    // Can be called multiple times for Codec, CNG, RED.
    int RegisterSendCodec(const CodecInst& send_codec) override;
  
    void RegisterExternalSendCodec(
        AudioEncoder* external_speech_encoder) override;
  
    // Get current send codec.
    rtc::Optional<CodecInst> SendCodec() const override;
  
    // Get current send frequency.
    int SendFrequency() const override;
  
    // Sets the bitrate to the specified value in bits/sec. In case the codec does
    // not support the requested value it will choose an appropriate value
    // instead.
    void SetBitRate(int bitrate_bps) override;
  
    // Register a transport callback which will be
    // called to deliver the encoded buffers.
    int RegisterTransportCallback(AudioPacketizationCallback* transport) override;
  
    // Add 10 ms of raw (PCM) audio data to the encoder.
    int Add10MsData(const AudioFrame& audio_frame) override;
  
    /////////////////////////////////////////
    // (RED) Redundant Coding
    //
  
    // Configure RED status i.e. on/off.
    int SetREDStatus(bool enable_red) override;
  
    // Get RED status.
    bool REDStatus() const override;
  
    /////////////////////////////////////////
    // (FEC) Forward Error Correction (codec internal)
    //
  
    // Configure FEC status i.e. on/off.
    int SetCodecFEC(bool enabled_codec_fec) override;
  
    // Get FEC status.
    bool CodecFEC() const override;
  
    // Set target packet loss rate
    int SetPacketLossRate(int loss_rate) override;
  
    /////////////////////////////////////////
    //   (VAD) Voice Activity Detection
    //   and
    //   (CNG) Comfort Noise Generation
    //
  
    int SetVAD(bool enable_dtx = true,
               bool enable_vad = false,
               ACMVADMode mode = VADNormal) override;
  
    int VAD(bool* dtx_enabled,
            bool* vad_enabled,
            ACMVADMode* mode) const override;
  
    int RegisterVADCallback(ACMVADCallback* vad_callback) override;
  
    /////////////////////////////////////////
    //   Receiver
    //
  
    // Initialize receiver, resets codec database etc.
    int InitializeReceiver() override;
  
    // Get current receive frequency.
    int ReceiveFrequency() const override;
  
    // Get current playout frequency.
    int PlayoutFrequency() const override;
  
    // Register possible receive codecs, can be called multiple times,
    // for codecs, CNG, DTMF, RED.
    int RegisterReceiveCodec(const CodecInst& receive_codec) override;
  
    int RegisterExternalReceiveCodec(int rtp_payload_type,
                                     AudioDecoder* external_decoder,
                                     int sample_rate_hz,
                                     int num_channels,
                                     const std::string& name) override;
  
    // Get current received codec.
    int ReceiveCodec(CodecInst* current_codec) const override;
  
    // Incoming packet from network parsed and ready for decode.
    int IncomingPacket(const uint8_t* incoming_payload,
                       const size_t payload_length,
                       const WebRtcRTPHeader& rtp_info) override;
  
    // Incoming payloads, without rtp-info, the rtp-info will be created in ACM.
    // One usage for this API is when pre-encoded files are pushed in ACM.
    int IncomingPayload(const uint8_t* incoming_payload,
                        const size_t payload_length,
                        uint8_t payload_type,
                        uint32_t timestamp) override;
  
    // Minimum playout delay.
    int SetMinimumPlayoutDelay(int time_ms) override;
  
    // Maximum playout delay.
    int SetMaximumPlayoutDelay(int time_ms) override;
  
    // Smallest latency NetEq will maintain.
    int LeastRequiredDelayMs() const override;
  
    // Get playout timestamp.
    int PlayoutTimestamp(uint32_t* timestamp) override;
  
    // Get 10 milliseconds of raw audio data to play out, and
    // automatic resample to the requested frequency if > 0.
    int PlayoutData10Ms(int desired_freq_hz, AudioFrame* audio_frame) override;
  
    /////////////////////////////////////////
    //   Statistics
    //
  
    int GetNetworkStatistics(NetworkStatistics* statistics) override;
  
    int SetOpusApplication(OpusApplicationMode application) override;
  
    // If current send codec is Opus, informs it about the maximum playback rate
    // the receiver will render.
    int SetOpusMaxPlaybackRate(int frequency_hz) override;
  
    int EnableOpusDtx() override;
  
    int DisableOpusDtx() override;
  
    int UnregisterReceiveCodec(uint8_t payload_type) override;
  
    int EnableNack(size_t max_nack_list_size) override;
  
    void DisableNack() override;
  
    std::vector<uint16_t> GetNackList(int64_t round_trip_time_ms) const override;
  
    void GetDecodingCallStatistics(AudioDecodingCallStats* stats) const override;
  
   private:
    struct InputData {
      uint32_t input_timestamp;
      const int16_t* audio;
      size_t length_per_channel;
      size_t audio_channel;
      // If a re-mix is required (up or down), this buffer will store a re-mixed
      // version of the input.
      int16_t buffer[WEBRTC_10MS_PCM_AUDIO];
    };
  
    // This member class writes values to the named UMA histogram, but only if
    // the value has changed since the last time (and always for the first call).
    class ChangeLogger {
     public:
      explicit ChangeLogger(const std::string& histogram_name)
          : histogram_name_(histogram_name) {}
      // Logs the new value if it is different from the last logged value, or if
      // this is the first call.
      void MaybeLog(int value);
  
     private:
      int last_value_ = 0;
      int first_time_ = true;
      const std::string histogram_name_;
    };
  
    int Add10MsDataInternal(const AudioFrame& audio_frame, InputData* input_data)
        EXCLUSIVE_LOCKS_REQUIRED(acm_crit_sect_);
    int Encode(const InputData& input_data)
        EXCLUSIVE_LOCKS_REQUIRED(acm_crit_sect_);
  
    int InitializeReceiverSafe() EXCLUSIVE_LOCKS_REQUIRED(acm_crit_sect_);
  
    bool HaveValidEncoder(const char* caller_name) const
        EXCLUSIVE_LOCKS_REQUIRED(acm_crit_sect_);
  
    // Preprocessing of input audio, including resampling and down-mixing if
    // required, before pushing audio into encoder's buffer.
    //
    // in_frame: input audio-frame
    // ptr_out: pointer to output audio_frame. If no preprocessing is required
    //          |ptr_out| will be pointing to |in_frame|, otherwise pointing to
    //          |preprocess_frame_|.
    //
    // Return value:
    //   -1: if encountering an error.
    //    0: otherwise.
    int PreprocessToAddData(const AudioFrame& in_frame,
                            const AudioFrame** ptr_out)
        EXCLUSIVE_LOCKS_REQUIRED(acm_crit_sect_);
  
    // Change required states after starting to receive the codec corresponding
    // to |index|.
    int UpdateUponReceivingCodec(int index);
  
    rtc::CriticalSection acm_crit_sect_;
    rtc::Buffer encode_buffer_ GUARDED_BY(acm_crit_sect_);
    int id_;  // TODO(henrik.lundin) Make const.
    uint32_t expected_codec_ts_ GUARDED_BY(acm_crit_sect_);
    uint32_t expected_in_ts_ GUARDED_BY(acm_crit_sect_);
    ACMResampler resampler_ GUARDED_BY(acm_crit_sect_);
    AcmReceiver receiver_;  // AcmReceiver has it's own internal lock.
    ChangeLogger bitrate_logger_ GUARDED_BY(acm_crit_sect_);
  
    struct EncoderFactory {
      CodecManager codec_manager;
      RentACodec rent_a_codec;
    };
    std::unique_ptr<EncoderFactory> encoder_factory_ GUARDED_BY(acm_crit_sect_);
  
    // Current encoder stack, either obtained from
    // encoder_factory_->rent_a_codec.RentEncoderStack or provided by a call to
    // RegisterEncoder.
    AudioEncoder* encoder_stack_ GUARDED_BY(acm_crit_sect_);
  
    // This is to keep track of CN instances where we can send DTMFs.
    uint8_t previous_pltype_ GUARDED_BY(acm_crit_sect_);
  
    // Used when payloads are pushed into ACM without any RTP info
    // One example is when pre-encoded bit-stream is pushed from
    // a file.
    // IMPORTANT: this variable is only used in IncomingPayload(), therefore,
    // no lock acquired when interacting with this variable. If it is going to
    // be used in other methods, locks need to be taken.
    std::unique_ptr<WebRtcRTPHeader> aux_rtp_header_;
  
    bool receiver_initialized_ GUARDED_BY(acm_crit_sect_);
  
    AudioFrame preprocess_frame_ GUARDED_BY(acm_crit_sect_);
    bool first_10ms_data_ GUARDED_BY(acm_crit_sect_);
  
    bool first_frame_ GUARDED_BY(acm_crit_sect_);
    uint32_t last_timestamp_ GUARDED_BY(acm_crit_sect_);
    uint32_t last_rtp_timestamp_ GUARDED_BY(acm_crit_sect_);
  
    rtc::CriticalSection callback_crit_sect_;
    AudioPacketizationCallback* packetization_callback_
        GUARDED_BY(callback_crit_sect_);
    ACMVADCallback* vad_callback_ GUARDED_BY(callback_crit_sect_);
  };
  
  }  // namespace acm2
  }  // namespace webrtc
  
  #endif  // WEBRTC_MODULES_AUDIO_CODING_ACM2_AUDIO_CODING_MODULE_IMPL_H_
  