/*
 *  Copyright (c) 2011 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 "vie_encoder.h"

#include <cassert>

#include "critical_section_wrapper.h"
#include "process_thread.h"
#include "rtp_rtcp.h"
#include "tick_util.h"
#include "trace.h"
#include "video_codec_interface.h"
#include "video_coding.h"
#include "video_coding_defines.h"
#include "vie_codec.h"
#include "vie_defines.h"
#include "vie_image_process.h"

namespace webrtc {

class QMTestVideoSettingsCallback : public VCMQMSettingsCallback {
 public:
  QMTestVideoSettingsCallback(VideoProcessingModule* vpm,
                              VideoCodingModule* vcm,
                              WebRtc_Word32 num_of_cores,
                              WebRtc_Word32 max_payload_length);
  ~QMTestVideoSettingsCallback();

  // Update VPM with QM (quality modes: frame size & frame rate) settings.
  WebRtc_Word32 SetVideoQMSettings(const WebRtc_UWord32 frame_rate,
                                   const WebRtc_UWord32 width,
                                   const WebRtc_UWord32 height);

  void SetMaxPayloadLength(WebRtc_Word32 max_payload_length);

 private:
  VideoProcessingModule* vpm_;
  VideoCodingModule* vcm_;
  WebRtc_Word32 num_cores_;
  WebRtc_Word32 max_payload_length_;
};


ViEEncoder::ViEEncoder(WebRtc_Word32 engine_id, WebRtc_Word32 channel_id,
                       WebRtc_UWord32 number_of_cores,
                       ProcessThread& module_process_thread)
  : engine_id_(engine_id),
    channel_id_(channel_id),
    number_of_cores_(number_of_cores),
    vcm_(*webrtc::VideoCodingModule::Create(ViEModuleId(engine_id,
                                                        channel_id))),
    vpm_(*webrtc::VideoProcessingModule::Create(ViEModuleId(engine_id,
                                                            channel_id))),
    default_rtp_rtcp_(*RtpRtcp::CreateRtpRtcp(
        ViEModuleId(engine_id, channel_id), false)),
    callback_cs_(CriticalSectionWrapper::CreateCriticalSection()),
    data_cs_(CriticalSectionWrapper::CreateCriticalSection()),
    paused_(false),
    channels_dropping_delta_frames_(0),
    drop_next_frame_(false),
    fec_enabled_(false),
    nack_enabled_(false),
    codec_observer_(NULL),
    effect_filter_(NULL),
    module_process_thread_(module_process_thread),
    has_received_sli_(false),
    picture_id_sli_(0),
    has_received_rpsi_(false),
    picture_id_rpsi_(0),
    file_recorder_(channel_id) {
  WEBRTC_TRACE(webrtc::kTraceMemory, webrtc::kTraceVideo,
               ViEId(engine_id, channel_id),
               "%s(engine_id: %d) 0x%p - Constructor", __FUNCTION__, engine_id,
               this);
  for (int i = 0; i < kMaxSimulcastStreams; i++) {
    time_last_intra_request_ms_[i] = 0;
  }
  vcm_.InitializeSender();
  vpm_.EnableTemporalDecimation(true);

  // Enable/disable content analysis: off by default for now.
  vpm_.EnableContentAnalysis(false);

  module_process_thread_.RegisterModule(&vcm_);
  if (default_rtp_rtcp_.InitSender() != 0) {
    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
                 ViEId(engine_id_, channel_id_),
                 "ViEEncoder: RTP::InitSender failure");
    assert(false);
  }
  default_rtp_rtcp_.RegisterIncomingVideoCallback(this);
  default_rtp_rtcp_.RegisterIncomingRTCPCallback(this);
  module_process_thread_.RegisterModule(&default_rtp_rtcp_);

  qm_callback_ = new QMTestVideoSettingsCallback(
      &vpm_, &vcm_, number_of_cores, default_rtp_rtcp_.MaxDataPayloadLength());

#ifdef VIDEOCODEC_VP8
  VideoCodec video_codec;
  if (vcm_.Codec(webrtc::kVideoCodecVP8, &video_codec) == VCM_OK) {
    vcm_.RegisterSendCodec(&video_codec, number_of_cores_,
                           default_rtp_rtcp_.MaxDataPayloadLength());
    default_rtp_rtcp_.RegisterSendPayload(video_codec);
  } else {
    assert(false);
  }
#else
  VideoCodec video_codec;
  if (vcm_.Codec(webrtc::kVideoCodecI420, &video_codec) == VCM_OK) {
    vcm_.RegisterSendCodec(&video_codec, number_of_cores_,
                           default_rtp_rtcp_.MaxDataPayloadLength());
    default_rtp_rtcp_.RegisterSendPayload(video_codec);
  } else {
    assert(false);
  }
#endif

  if (vcm_.RegisterTransportCallback(this) != 0) {
    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
                 ViEId(engine_id_, channel_id_),
                 "ViEEncoder: VCM::RegisterTransportCallback failure");
  }
  if (vcm_.RegisterSendStatisticsCallback(this) != 0) {
    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
                 ViEId(engine_id_, channel_id_),
                 "ViEEncoder: VCM::RegisterSendStatisticsCallback failure");
  }

  if (vcm_.RegisterVideoQMCallback(qm_callback_) != 0) {
    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
                 ViEId(engine_id_, channel_id_),
                 "VCM::RegisterQMCallback failure");
  }
}

ViEEncoder::~ViEEncoder() {
  WEBRTC_TRACE(webrtc::kTraceMemory, webrtc::kTraceVideo,
               ViEId(engine_id_, channel_id_),
               "ViEEncoder Destructor 0x%p, engine_id: %d", this, engine_id_);

  if (default_rtp_rtcp_.NumberChildModules() > 0) {
    assert(false);
    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
                 ViEId(engine_id_, channel_id_),
                 "Channels still attached %d, leaking memory",
                 default_rtp_rtcp_.NumberChildModules());
    return;
  }
  module_process_thread_.DeRegisterModule(&vcm_);
  module_process_thread_.DeRegisterModule(&vpm_);
  module_process_thread_.DeRegisterModule(&default_rtp_rtcp_);
  delete &vcm_;
  delete &vpm_;
  delete &default_rtp_rtcp_;
  delete qm_callback_;
}

void ViEEncoder::Pause() {
  WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
               ViEId(engine_id_, channel_id_),
               "%s", __FUNCTION__);
  CriticalSectionScoped cs(data_cs_.get());
  paused_ = true;
}

void ViEEncoder::Restart() {
  WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
               ViEId(engine_id_, channel_id_),
               "%s", __FUNCTION__);
  CriticalSectionScoped cs(data_cs_.get());
  paused_ = false;
}

WebRtc_Word32 ViEEncoder::DropDeltaAfterKey(bool enable) {
  WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
               ViEId(engine_id_, channel_id_),
               "%s(%d)", __FUNCTION__, enable);
  CriticalSectionScoped cs(data_cs_.get());

  if (enable) {
    channels_dropping_delta_frames_++;
  } else {
    channels_dropping_delta_frames_--;
    if (channels_dropping_delta_frames_ < 0) {
      channels_dropping_delta_frames_ = 0;
      WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
                   ViEId(engine_id_, channel_id_),
                   "%s: Called too many times", __FUNCTION__);
      return -1;
    }
  }
  return 0;
}

WebRtc_UWord8 ViEEncoder::NumberOfCodecs() {
  return vcm_.NumberOfCodecs();
}

WebRtc_Word32 ViEEncoder::GetCodec(WebRtc_UWord8 list_index,
                                   webrtc::VideoCodec& video_codec) {
  if (vcm_.Codec(list_index, &video_codec) != 0) {
    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
                 ViEId(engine_id_, channel_id_), "%s: Could not get codec",
                 __FUNCTION__);
    return -1;
  }
  return 0;
}

WebRtc_Word32 ViEEncoder::RegisterExternalEncoder(webrtc::VideoEncoder* encoder,
                                                  WebRtc_UWord8 pl_type) {
  WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
               ViEId(engine_id_, channel_id_), "%s: pltype %u", __FUNCTION__,
               pl_type);

  if (encoder == NULL)
    return -1;

  if (vcm_.RegisterExternalEncoder(encoder, pl_type) != VCM_OK) {
    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
                 ViEId(engine_id_, channel_id_),
                 "Could not register external encoder");
    return -1;
  }
  return 0;
}

WebRtc_Word32 ViEEncoder::DeRegisterExternalEncoder(WebRtc_UWord8 pl_type) {
  WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
               ViEId(engine_id_, channel_id_),
               "%s: pltype %u", __FUNCTION__, pl_type);

  webrtc::VideoCodec current_send_codec;
  if (vcm_.SendCodec(&current_send_codec) == VCM_OK) {
    current_send_codec.startBitrate = vcm_.Bitrate();
  }

  if (vcm_.RegisterExternalEncoder(NULL, pl_type) != VCM_OK) {
    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
                 ViEId(engine_id_, channel_id_),
                 "Could not deregister external encoder");
    return -1;
  }

  // If the external encoder is the current send codeci, use vcm internal
  // encoder.
  if (current_send_codec.plType == pl_type) {
    WebRtc_UWord16 max_data_payload_length =
        default_rtp_rtcp_.MaxDataPayloadLength();
    if (vcm_.RegisterSendCodec(&current_send_codec, number_of_cores_,
                               max_data_payload_length) != VCM_OK) {
      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
                   ViEId(engine_id_, channel_id_),
                   "Could not use internal encoder");
      return -1;
    }
  }
  return 0;
}

WebRtc_Word32 ViEEncoder::SetEncoder(const webrtc::VideoCodec& video_codec) {
  WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
               ViEId(engine_id_, channel_id_),
               "%s: CodecType: %d, width: %u, height: %u", __FUNCTION__,
               video_codec.codecType, video_codec.width, video_codec.height);

  // Convert from kbps to bps.
  if (default_rtp_rtcp_.SetSendBitrate(video_codec.startBitrate * 1000,
                                       video_codec.minBitrate,
                                       video_codec.maxBitrate) != 0) {
    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
                 ViEId(engine_id_, channel_id_),
                 "Could not set RTP module bitrates");
    return -1;
  }

  // Setting target width and height for VPM.
  if (vpm_.SetTargetResolution(video_codec.width, video_codec.height,
                               video_codec.maxFramerate) != VPM_OK) {
    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
                 ViEId(engine_id_, channel_id_),
                 "Could not set VPM target dimensions");
    return -1;
  }

  if (default_rtp_rtcp_.RegisterSendPayload(video_codec) != 0) {
    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
                 ViEId(engine_id_, channel_id_),
                 "Could register RTP module video payload");
    return -1;
  }

  WebRtc_UWord16 max_data_payload_length =
      default_rtp_rtcp_.MaxDataPayloadLength();

  qm_callback_->SetMaxPayloadLength(max_data_payload_length);

  if (vcm_.RegisterSendCodec(&video_codec, number_of_cores_,
                             max_data_payload_length) != VCM_OK) {
    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
                 ViEId(engine_id_, channel_id_),
                 "Could not register send codec");
    return -1;
  }

  data_cs_->Enter();
  memcpy(&send_codec_, &video_codec, sizeof(send_codec_));
  data_cs_->Leave();

  // Set this module as sending right away, let the slave module in the channel
  // start and stop sending.
  if (default_rtp_rtcp_.Sending() == false) {
    if (default_rtp_rtcp_.SetSendingStatus(true) != 0) {
      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
                   ViEId(engine_id_, channel_id_),
                   "Could start RTP module sending");
      return -1;
    }
  }
  return 0;
}

WebRtc_Word32 ViEEncoder::GetEncoder(webrtc::VideoCodec& video_codec) {
  WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
               ViEId(engine_id_, channel_id_), "%s", __FUNCTION__);

  if (vcm_.SendCodec(&video_codec) != 0) {
    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
                 ViEId(engine_id_, channel_id_),
                 "Could not get VCM send codec");
    return -1;
  }
  return 0;
}

WebRtc_Word32 ViEEncoder::GetCodecConfigParameters(
    unsigned char config_parameters[kConfigParameterSize],
    unsigned char& config_parameters_size) {
  WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
               ViEId(engine_id_, channel_id_), "%s", __FUNCTION__);

  WebRtc_Word32 num_parameters =
      vcm_.CodecConfigParameters(config_parameters, kConfigParameterSize);
  if (num_parameters <= 0) {
    config_parameters_size = 0;
    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
                 ViEId(engine_id_, channel_id_),
                 "Could not get config parameters");
    return -1;
  }
  config_parameters_size = static_cast<unsigned char>(num_parameters);
  return 0;
}

WebRtc_Word32 ViEEncoder::ScaleInputImage(bool enable) {
  WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
               ViEId(engine_id_, channel_id_), "%s(enable %d)", __FUNCTION__,
               enable);

  VideoFrameResampling resampling_mode = kFastRescaling;
  if (enable == true) {
    // kInterpolation is currently not supported.
    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
                 ViEId(engine_id_, channel_id_), "%s not supported",
                 __FUNCTION__, enable);
    return -1;
  }
  vpm_.SetInputFrameResampleMode(resampling_mode);

  return 0;
}

RtpRtcp* ViEEncoder::SendRtpRtcpModule() {
  WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
               ViEId(engine_id_, channel_id_), "%s", __FUNCTION__);

  return &default_rtp_rtcp_;
}

void ViEEncoder::DeliverFrame(int id, webrtc::VideoFrame& video_frame,
                              int num_csrcs,
                              const WebRtc_UWord32 CSRC[kRtpCsrcSize]) {
  WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceVideo,
               ViEId(engine_id_, channel_id_), "%s: %llu", __FUNCTION__,
               video_frame.TimeStamp());

  {
    CriticalSectionScoped cs(data_cs_.get());
    if (paused_ || default_rtp_rtcp_.SendingMedia() == false) {
      // We've paused or we have no channels attached, don't encode.
      return;
    }
    if (drop_next_frame_) {
      // Drop this frame.
      WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceVideo,
                   ViEId(engine_id_, channel_id_),
                   "%s: Dropping frame %llu after a key fame", __FUNCTION__,
                   video_frame.TimeStamp());
      drop_next_frame_ = false;
      return;
    }
  }

  // Convert render time, in ms, to RTP timestamp.
  const WebRtc_UWord32 time_stamp =
      90 * static_cast<WebRtc_UWord32>(video_frame.RenderTimeMs());
  video_frame.SetTimeStamp(time_stamp);
  {
    CriticalSectionScoped cs(callback_cs_.get());
    if (effect_filter_) {
      effect_filter_->Transform(video_frame.Length(), video_frame.Buffer(),
                                video_frame.TimeStamp(),
                                video_frame.Width(), video_frame.Height());
    }
  }
  // Record raw frame.
  file_recorder_.RecordVideoFrame(video_frame);

  // Make sure the CSRC list is correct.
  if (num_csrcs > 0) {
    WebRtc_UWord32 tempCSRC[kRtpCsrcSize];
    for (int i = 0; i < num_csrcs; i++) {
      if (CSRC[i] == 1) {
        tempCSRC[i] = default_rtp_rtcp_.SSRC();
      } else {
        tempCSRC[i] = CSRC[i];
      }
    }
    default_rtp_rtcp_.SetCSRCs(tempCSRC, (WebRtc_UWord8) num_csrcs);
  }

#ifdef VIDEOCODEC_VP8
  if (vcm_.SendCodec() == webrtc::kVideoCodecVP8) {
    webrtc::CodecSpecificInfo codec_specific_info;
    codec_specific_info.codecType = webrtc::kVideoCodecVP8;
    if (has_received_sli_ || has_received_rpsi_) {
      {
        codec_specific_info.codecSpecific.VP8.hasReceivedRPSI =
          has_received_rpsi_;
        codec_specific_info.codecSpecific.VP8.hasReceivedSLI =
          has_received_sli_;
        codec_specific_info.codecSpecific.VP8.pictureIdRPSI =
          picture_id_rpsi_;
        codec_specific_info.codecSpecific.VP8.pictureIdSLI  =
          picture_id_sli_;
      }
      has_received_sli_ = false;
      has_received_rpsi_ = false;
    }
    VideoFrame* decimated_frame = NULL;
    const int ret = vpm_.PreprocessFrame(&video_frame, &decimated_frame);
    if (ret == 1) {
      // Drop this frame.
      return;
    } else if (ret != VPM_OK) {
      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
                   ViEId(engine_id_, channel_id_),
                   "%s: Error preprocessing frame %u", __FUNCTION__,
                   video_frame.TimeStamp());
      return;
    }

    VideoContentMetrics* content_metrics = NULL;
    content_metrics = vpm_.ContentMetrics();

    // Frame was not re-sampled => use original.
    if (decimated_frame == NULL)  {
      decimated_frame = &video_frame;
    }

    if (vcm_.AddVideoFrame(*decimated_frame, content_metrics,
                           &codec_specific_info) != VCM_OK) {
      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
                   ViEId(engine_id_, channel_id_),
                   "%s: Error encoding frame %u", __FUNCTION__,
                   video_frame.TimeStamp());
    }
    return;
  }
#endif
  // TODO(mflodman) Rewrite this to use code common to VP8 case.
  // Pass frame via preprocessor.
  VideoFrame* decimated_frame = NULL;
  const int ret = vpm_.PreprocessFrame(&video_frame, &decimated_frame);
  if (ret == 1) {
    // Drop this frame.
    return;
  } else if (ret != VPM_OK) {
    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
                 ViEId(engine_id_, channel_id_),
                 "%s: Error preprocessing frame %u", __FUNCTION__,
                 video_frame.TimeStamp());
    return;
  }

  // Frame was not sampled => use original.
  if (decimated_frame == NULL)  {
    decimated_frame = &video_frame;
  }
  if (vcm_.AddVideoFrame(*decimated_frame) != VCM_OK) {
    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
                 ViEId(engine_id_, channel_id_), "%s: Error encoding frame %u",
                 __FUNCTION__, video_frame.TimeStamp());
  }
}

void ViEEncoder::DelayChanged(int id, int frame_delay) {
  WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceVideo,
               ViEId(engine_id_, channel_id_), "%s: %u", __FUNCTION__,
               frame_delay);

  default_rtp_rtcp_.SetCameraDelay(frame_delay);
  file_recorder_.SetFrameDelay(frame_delay);
}

int ViEEncoder::GetPreferedFrameSettings(int& width,
                                         int& height,
                                         int& frame_rate) {
  WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
               ViEId(engine_id_, channel_id_), "%s", __FUNCTION__);

  webrtc::VideoCodec video_codec;
  memset(&video_codec, 0, sizeof(video_codec));
  if (vcm_.SendCodec(&video_codec) != VCM_OK) {
    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
                 ViEId(engine_id_, channel_id_),
                 "Could not get VCM send codec");
    return -1;
  }

  width = video_codec.width;
  height = video_codec.height;
  frame_rate = video_codec.maxFramerate;
  return 0;
}

WebRtc_Word32 ViEEncoder::SendKeyFrame() {
  WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
               ViEId(engine_id_, channel_id_), "%s", __FUNCTION__);
  return vcm_.FrameTypeRequest(kVideoFrameKey, 0);  // Simulcast idx = 0.
}

WebRtc_Word32 ViEEncoder::SendCodecStatistics(
    WebRtc_UWord32& num_key_frames, WebRtc_UWord32& num_delta_frames) {
  WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
               ViEId(engine_id_, channel_id_), "%s", __FUNCTION__);

  webrtc::VCMFrameCount sent_frames;
  if (vcm_.SentFrameCount(sent_frames) != VCM_OK) {
    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
                 ViEId(engine_id_, channel_id_),
                 "%s: Could not get sent frame information", __FUNCTION__);
    return -1;
  }
  num_key_frames = sent_frames.numKeyFrames;
  num_delta_frames = sent_frames.numDeltaFrames;
  return 0;
}

WebRtc_Word32 ViEEncoder::UpdateProtectionMethod() {
  bool fec_enabled = false;
  WebRtc_UWord8 dummy_ptype_red = 0;
  WebRtc_UWord8 dummy_ptypeFEC = 0;

  // Updated protection method to VCM to get correct packetization sizes.
  // FEC has larger overhead than NACK -> set FEC if used.
  WebRtc_Word32 error = default_rtp_rtcp_.GenericFECStatus(fec_enabled,
                                                           dummy_ptype_red,
                                                           dummy_ptypeFEC);
  if (error) {
    return -1;
  }

  bool nack_enabled = (default_rtp_rtcp_.NACK() == kNackOff) ? false : true;
  if (fec_enabled_ == fec_enabled && nack_enabled_ == nack_enabled) {
    // No change needed, we're already in correct state.
    return 0;
  }
  fec_enabled_ = fec_enabled;
  nack_enabled_ = nack_enabled;

  // Set Video Protection for VCM.
  if (fec_enabled && nack_enabled) {
    vcm_.SetVideoProtection(webrtc::kProtectionNackFEC, true);
  } else {
    vcm_.SetVideoProtection(webrtc::kProtectionFEC, fec_enabled_);
    vcm_.SetVideoProtection(webrtc::kProtectionNack, nack_enabled_);
    vcm_.SetVideoProtection(webrtc::kProtectionNackFEC, false);
  }

  if (fec_enabled || nack_enabled) {
    WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
                 ViEId(engine_id_, channel_id_), "%s: FEC status ",
                 __FUNCTION__, fec_enabled);
    vcm_.RegisterProtectionCallback(this);
    // The send codec must be registered to set correct MTU.
    webrtc::VideoCodec codec;
    if (vcm_.SendCodec(&codec) == 0) {
      WebRtc_UWord16 max_pay_load = default_rtp_rtcp_.MaxDataPayloadLength();
      codec.startBitrate = vcm_.Bitrate();
      if (vcm_.RegisterSendCodec(&codec, number_of_cores_, max_pay_load) != 0) {
        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
                     ViEId(engine_id_, channel_id_),
                     "%s: Failed to update Sendcodec when enabling FEC",
                     __FUNCTION__, fec_enabled);
        return -1;
      }
    }
    return 0;
  } else {
    // FEC and NACK are disabled.
    vcm_.RegisterProtectionCallback(NULL);
  }
  return 0;
}

WebRtc_Word32 ViEEncoder::SendData(
    const FrameType frame_type,
    const WebRtc_UWord8 payload_type,
    const WebRtc_UWord32 time_stamp,
    const WebRtc_UWord8* payload_data,
    const WebRtc_UWord32 payload_size,
    const webrtc::RTPFragmentationHeader& fragmentation_header,
    const RTPVideoHeader* rtp_video_hdr) {
  {
    CriticalSectionScoped cs(data_cs_.get());
    if (paused_) {
      // Paused, don't send this packet.
      return 0;
    }
    if (channels_dropping_delta_frames_ &&
        frame_type == webrtc::kVideoFrameKey) {
      WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceVideo,
                   ViEId(engine_id_, channel_id_),
                   "%s: Sending key frame, drop next frame", __FUNCTION__);
      drop_next_frame_ = true;
    }
  }

  // New encoded data, hand over to the rtp module.
  return default_rtp_rtcp_.SendOutgoingData(frame_type, payload_type,
                                            time_stamp, payload_data,
                                            payload_size, &fragmentation_header,
                                            rtp_video_hdr);
}

WebRtc_Word32 ViEEncoder::ProtectionRequest(
    WebRtc_UWord8 delta_fecrate,
    WebRtc_UWord8 key_fecrate,
    bool delta_use_uep_protection,
    bool key_use_uep_protection,
    bool nack_enabled,
    WebRtc_UWord32* sent_video_rate_bps,
    WebRtc_UWord32* sent_nack_rate_bps,
    WebRtc_UWord32* sent_fec_rate_bps) {
  WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceVideo,
               ViEId(engine_id_, channel_id_),
               "%s, deltaFECRate: %u, key_fecrate: %u, "
               "delta_use_uep_protection: %d, key_use_uep_protection: %d, ",
               __FUNCTION__, delta_fecrate, key_fecrate,
               delta_use_uep_protection, key_use_uep_protection);

  if (default_rtp_rtcp_.SetFECCodeRate(key_fecrate, delta_fecrate) != 0) {
    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
                 ViEId(engine_id_, channel_id_),
                 "%s: Could not update FEC code rate", __FUNCTION__);
  }
  if (default_rtp_rtcp_.SetFECUepProtection(key_use_uep_protection,
                                            delta_use_uep_protection) != 0) {
    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
                 ViEId(engine_id_, channel_id_),
                 "%s: Could not update FEC-UEP protection", __FUNCTION__);
  }
  default_rtp_rtcp_.BitrateSent(NULL,
                                sent_video_rate_bps,
                                sent_fec_rate_bps,
                                sent_nack_rate_bps);
  return 0;
}

WebRtc_Word32 ViEEncoder::SendStatistics(const WebRtc_UWord32 bit_rate,
                                         const WebRtc_UWord32 frame_rate) {
  CriticalSectionScoped cs(callback_cs_.get());
  if (codec_observer_) {
    WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
                 ViEId(engine_id_, channel_id_), "%s: bitrate %u, framerate %u",
                 __FUNCTION__, bit_rate, frame_rate);
    codec_observer_->OutgoingRate(channel_id_, frame_rate, bit_rate);
  }
  return 0;
}

WebRtc_Word32 ViEEncoder::RegisterCodecObserver(ViEEncoderObserver* observer) {
  CriticalSectionScoped cs(callback_cs_.get());
  if (observer) {
    WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
                 ViEId(engine_id_, channel_id_), "%s: observer added",
                 __FUNCTION__);
    if (codec_observer_) {
      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
                   ViEId(engine_id_, channel_id_), "%s: observer already set.",
                   __FUNCTION__);
      return -1;
    }
    codec_observer_ = observer;
  } else {
    if (codec_observer_ == NULL) {
      WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
                   ViEId(engine_id_, channel_id_),
                   "%s: observer does not exist.", __FUNCTION__);
      return -1;
    }
    WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
                 ViEId(engine_id_, channel_id_), "%s: observer removed",
                 __FUNCTION__);
    codec_observer_ = NULL;
  }
  return 0;
}

void ViEEncoder::OnSLIReceived(const WebRtc_Word32 id,
                               const WebRtc_UWord8 picture_id) {
  picture_id_sli_ = picture_id;
  has_received_sli_ = true;
}

void ViEEncoder::OnRPSIReceived(const WebRtc_Word32 id,
                                const WebRtc_UWord64 picture_id) {
  picture_id_rpsi_ = picture_id;
  has_received_rpsi_ = true;
}

void ViEEncoder::OnReceivedIntraFrameRequest(const WebRtc_Word32 id,
                                             const FrameType type,
                                             const WebRtc_UWord8 stream_idx) {
  assert(stream_idx < kMaxSimulcastStreams);

  // Key frame request from remote side, signal to VCM.
  WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceVideo,
               ViEId(engine_id_, channel_id_), "%s", __FUNCTION__);

  WebRtc_Word64 now = TickTime::MillisecondTimestamp();
  if (time_last_intra_request_ms_[stream_idx] + kViEMinKeyRequestIntervalMs >
      now) {
    WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceVideo,
                 ViEId(engine_id_, channel_id_),
                 "%s: Not not encoding new intra due to timing", __FUNCTION__);
    return;
  }
  vcm_.FrameTypeRequest(type, stream_idx);
  time_last_intra_request_ms_[stream_idx] = now;
}

void ViEEncoder::OnNetworkChanged(const WebRtc_Word32 id,
                                  const WebRtc_UWord32 bitrate_bps,
                                  const WebRtc_UWord8 fraction_lost,
                                  const WebRtc_UWord16 round_trip_time_ms) {
  WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
               ViEId(engine_id_, channel_id_),
               "%s(bitrate_bps: %u, fraction_lost: %u, rtt_ms: %u",
               __FUNCTION__, bitrate_bps, fraction_lost, round_trip_time_ms);

  vcm_.SetChannelParameters(bitrate_bps / 1000, fraction_lost,
                            round_trip_time_ms);
}

WebRtc_Word32 ViEEncoder::RegisterEffectFilter(ViEEffectFilter* effect_filter) {
  CriticalSectionScoped cs(callback_cs_.get());
  if (effect_filter == NULL) {
    if (effect_filter_ == NULL) {
      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
                   ViEId(engine_id_, channel_id_), "%s: no effect filter added",
                   __FUNCTION__);
      return -1;
    }
    WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
                 ViEId(engine_id_, channel_id_), "%s: deregister effect filter",
                 __FUNCTION__);
  } else {
    WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
                 ViEId(engine_id_, channel_id_), "%s: register effect",
                 __FUNCTION__);
    if (effect_filter_) {
      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
                   ViEId(engine_id_, channel_id_),
                   "%s: effect filter already added ", __FUNCTION__);
      return -1;
    }
  }
  effect_filter_ = effect_filter;
  return 0;
}

ViEFileRecorder& ViEEncoder::GetOutgoingFileRecorder() {
  return file_recorder_;
}

QMTestVideoSettingsCallback::QMTestVideoSettingsCallback(
    VideoProcessingModule* vpm,
    VideoCodingModule* vcm,
    WebRtc_Word32 num_cores,
    WebRtc_Word32 max_payload_length)
    : vpm_(vpm),
      vcm_(vcm),
      num_cores_(num_cores),
      max_payload_length_(max_payload_length) {
}

QMTestVideoSettingsCallback::~QMTestVideoSettingsCallback() {
}

WebRtc_Word32 QMTestVideoSettingsCallback::SetVideoQMSettings(
    const WebRtc_UWord32 frame_rate,
    const WebRtc_UWord32 width,
    const WebRtc_UWord32 height) {
  WebRtc_Word32 ret_val = 0;
  ret_val = vpm_->SetTargetResolution(width, height, frame_rate);

  if (!ret_val) {
    // Get current settings.
    VideoCodec current_codec;
    vcm_->SendCodec(&current_codec);
    WebRtc_UWord32 current_bit_rate = vcm_->Bitrate();

    // Set the new calues.
    current_codec.height = static_cast<WebRtc_UWord16>(height);
    current_codec.width = static_cast<WebRtc_UWord16>(width);
    current_codec.maxFramerate = static_cast<WebRtc_UWord8>(frame_rate);
    current_codec.startBitrate = current_bit_rate;

    // Re-register encoder with the updated settings.
    ret_val = vcm_->RegisterSendCodec(&current_codec, num_cores_,
                                      max_payload_length_);
  }
  return ret_val;
}

void QMTestVideoSettingsCallback::SetMaxPayloadLength(
    WebRtc_Word32 max_payload_length) {
  max_payload_length_ = max_payload_length;
}

}  // namespace webrtc
