Home | History | Annotate | Download | only in video_engine
      1 /*
      2  *  Copyright (c) 2012 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/video_engine/vie_encoder.h"
     12 
     13 #include <assert.h>
     14 
     15 #include <algorithm>
     16 
     17 #include "webrtc/common_video/interface/video_image.h"
     18 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
     19 #include "webrtc/modules/pacing/include/paced_sender.h"
     20 #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h"
     21 #include "webrtc/modules/utility/interface/process_thread.h"
     22 #include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h"
     23 #include "webrtc/modules/video_coding/main/interface/video_coding.h"
     24 #include "webrtc/modules/video_coding/main/interface/video_coding_defines.h"
     25 #include "webrtc/modules/video_coding/main/source/encoded_frame.h"
     26 #include "webrtc/system_wrappers/interface/clock.h"
     27 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
     28 #include "webrtc/system_wrappers/interface/logging.h"
     29 #include "webrtc/system_wrappers/interface/tick_util.h"
     30 #include "webrtc/system_wrappers/interface/trace_event.h"
     31 #include "webrtc/video_engine/include/vie_codec.h"
     32 #include "webrtc/video_engine/include/vie_image_process.h"
     33 #include "webrtc/frame_callback.h"
     34 #include "webrtc/video_engine/vie_defines.h"
     35 
     36 namespace webrtc {
     37 
     38 // Margin on when we pause the encoder when the pacing buffer overflows relative
     39 // to the configured buffer delay.
     40 static const float kEncoderPausePacerMargin = 2.0f;
     41 
     42 // Don't stop the encoder unless the delay is above this configured value.
     43 static const int kMinPacingDelayMs = 200;
     44 
     45 // Allow packets to be transmitted in up to 2 times max video bitrate if the
     46 // bandwidth estimate allows it.
     47 // TODO(holmer): Expose transmission start, min and max bitrates in the
     48 // VideoEngine API and remove the kTransmissionMaxBitrateMultiplier.
     49 static const int kTransmissionMaxBitrateMultiplier = 2;
     50 
     51 static const float kStopPaddingThresholdMs = 2000;
     52 
     53 std::vector<uint32_t> AllocateStreamBitrates(
     54     uint32_t total_bitrate,
     55     const SimulcastStream* stream_configs,
     56     size_t number_of_streams) {
     57   if (number_of_streams == 0) {
     58     std::vector<uint32_t> stream_bitrates(1, 0);
     59     stream_bitrates[0] = total_bitrate;
     60     return stream_bitrates;
     61   }
     62   std::vector<uint32_t> stream_bitrates(number_of_streams, 0);
     63   uint32_t bitrate_remainder = total_bitrate;
     64   for (size_t i = 0; i < stream_bitrates.size() && bitrate_remainder > 0; ++i) {
     65     if (stream_configs[i].maxBitrate * 1000 > bitrate_remainder) {
     66       stream_bitrates[i] = bitrate_remainder;
     67     } else {
     68       stream_bitrates[i] = stream_configs[i].maxBitrate * 1000;
     69     }
     70     bitrate_remainder -= stream_bitrates[i];
     71   }
     72   return stream_bitrates;
     73 }
     74 
     75 class QMVideoSettingsCallback : public VCMQMSettingsCallback {
     76  public:
     77   explicit QMVideoSettingsCallback(VideoProcessingModule* vpm);
     78 
     79   ~QMVideoSettingsCallback();
     80 
     81   // Update VPM with QM (quality modes: frame size & frame rate) settings.
     82   int32_t SetVideoQMSettings(const uint32_t frame_rate,
     83                              const uint32_t width,
     84                              const uint32_t height);
     85 
     86  private:
     87   VideoProcessingModule* vpm_;
     88 };
     89 
     90 class ViEBitrateObserver : public BitrateObserver {
     91  public:
     92   explicit ViEBitrateObserver(ViEEncoder* owner)
     93       : owner_(owner) {
     94   }
     95   virtual ~ViEBitrateObserver() {}
     96   // Implements BitrateObserver.
     97   virtual void OnNetworkChanged(const uint32_t bitrate_bps,
     98                                 const uint8_t fraction_lost,
     99                                 const uint32_t rtt) {
    100     owner_->OnNetworkChanged(bitrate_bps, fraction_lost, rtt);
    101   }
    102  private:
    103   ViEEncoder* owner_;
    104 };
    105 
    106 class ViEPacedSenderCallback : public PacedSender::Callback {
    107  public:
    108   explicit ViEPacedSenderCallback(ViEEncoder* owner)
    109       : owner_(owner) {
    110   }
    111   virtual ~ViEPacedSenderCallback() {}
    112   virtual bool TimeToSendPacket(uint32_t ssrc, uint16_t sequence_number,
    113                                 int64_t capture_time_ms, bool retransmission) {
    114     return owner_->TimeToSendPacket(ssrc, sequence_number, capture_time_ms,
    115                                     retransmission);
    116   }
    117   virtual int TimeToSendPadding(int bytes) {
    118     return owner_->TimeToSendPadding(bytes);
    119   }
    120  private:
    121   ViEEncoder* owner_;
    122 };
    123 
    124 ViEEncoder::ViEEncoder(int32_t engine_id,
    125                        int32_t channel_id,
    126                        uint32_t number_of_cores,
    127                        const Config& config,
    128                        ProcessThread& module_process_thread,
    129                        BitrateController* bitrate_controller)
    130   : engine_id_(engine_id),
    131     channel_id_(channel_id),
    132     number_of_cores_(number_of_cores),
    133     vcm_(*webrtc::VideoCodingModule::Create()),
    134     vpm_(*webrtc::VideoProcessingModule::Create(ViEModuleId(engine_id,
    135                                                             channel_id))),
    136     callback_cs_(CriticalSectionWrapper::CreateCriticalSection()),
    137     data_cs_(CriticalSectionWrapper::CreateCriticalSection()),
    138     bitrate_controller_(bitrate_controller),
    139     time_of_last_incoming_frame_ms_(0),
    140     send_padding_(false),
    141     min_transmit_bitrate_kbps_(0),
    142     target_delay_ms_(0),
    143     network_is_transmitting_(true),
    144     encoder_paused_(false),
    145     encoder_paused_and_dropped_frame_(false),
    146     fec_enabled_(false),
    147     nack_enabled_(false),
    148     codec_observer_(NULL),
    149     effect_filter_(NULL),
    150     module_process_thread_(module_process_thread),
    151     has_received_sli_(false),
    152     picture_id_sli_(0),
    153     has_received_rpsi_(false),
    154     picture_id_rpsi_(0),
    155     qm_callback_(NULL),
    156     video_suspended_(false),
    157     pre_encode_callback_(NULL) {
    158   RtpRtcp::Configuration configuration;
    159   configuration.id = ViEModuleId(engine_id_, channel_id_);
    160   configuration.audio = false;  // Video.
    161 
    162   default_rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(configuration));
    163   bitrate_observer_.reset(new ViEBitrateObserver(this));
    164   pacing_callback_.reset(new ViEPacedSenderCallback(this));
    165   paced_sender_.reset(
    166       new PacedSender(Clock::GetRealTimeClock(), pacing_callback_.get(),
    167                       PacedSender::kDefaultInitialPaceKbps, 0));
    168 }
    169 
    170 bool ViEEncoder::Init() {
    171   if (vcm_.InitializeSender() != 0) {
    172     return false;
    173   }
    174   vpm_.EnableTemporalDecimation(true);
    175 
    176   // Enable/disable content analysis: off by default for now.
    177   vpm_.EnableContentAnalysis(false);
    178 
    179   if (module_process_thread_.RegisterModule(&vcm_) != 0 ||
    180       module_process_thread_.RegisterModule(default_rtp_rtcp_.get()) != 0 ||
    181       module_process_thread_.RegisterModule(paced_sender_.get()) != 0) {
    182     return false;
    183   }
    184   if (qm_callback_) {
    185     delete qm_callback_;
    186   }
    187   qm_callback_ = new QMVideoSettingsCallback(&vpm_);
    188 
    189 #ifdef VIDEOCODEC_VP8
    190   VideoCodecType codec_type = webrtc::kVideoCodecVP8;
    191 #else
    192   VideoCodecType codec_type = webrtc::kVideoCodecI420;
    193 #endif
    194 
    195   VideoCodec video_codec;
    196   if (vcm_.Codec(codec_type, &video_codec) != VCM_OK) {
    197     return false;
    198   }
    199   {
    200     CriticalSectionScoped cs(data_cs_.get());
    201     send_padding_ = video_codec.numberOfSimulcastStreams > 1;
    202   }
    203   if (vcm_.RegisterSendCodec(&video_codec, number_of_cores_,
    204                              default_rtp_rtcp_->MaxDataPayloadLength()) != 0) {
    205     return false;
    206   }
    207   if (default_rtp_rtcp_->RegisterSendPayload(video_codec) != 0) {
    208     return false;
    209   }
    210   if (vcm_.RegisterTransportCallback(this) != 0) {
    211     return false;
    212   }
    213   if (vcm_.RegisterSendStatisticsCallback(this) != 0) {
    214     return false;
    215   }
    216   if (vcm_.RegisterVideoQMCallback(qm_callback_) != 0) {
    217     return false;
    218   }
    219   return true;
    220 }
    221 
    222 ViEEncoder::~ViEEncoder() {
    223   if (bitrate_controller_) {
    224     bitrate_controller_->RemoveBitrateObserver(bitrate_observer_.get());
    225   }
    226   module_process_thread_.DeRegisterModule(&vcm_);
    227   module_process_thread_.DeRegisterModule(&vpm_);
    228   module_process_thread_.DeRegisterModule(default_rtp_rtcp_.get());
    229   module_process_thread_.DeRegisterModule(paced_sender_.get());
    230   VideoCodingModule::Destroy(&vcm_);
    231   VideoProcessingModule::Destroy(&vpm_);
    232   delete qm_callback_;
    233 }
    234 
    235 int ViEEncoder::Owner() const {
    236   return channel_id_;
    237 }
    238 
    239 void ViEEncoder::SetNetworkTransmissionState(bool is_transmitting) {
    240   {
    241     CriticalSectionScoped cs(data_cs_.get());
    242     network_is_transmitting_ = is_transmitting;
    243   }
    244   if (is_transmitting) {
    245     paced_sender_->Resume();
    246   } else {
    247     paced_sender_->Pause();
    248   }
    249 }
    250 
    251 void ViEEncoder::Pause() {
    252   CriticalSectionScoped cs(data_cs_.get());
    253   encoder_paused_ = true;
    254 }
    255 
    256 void ViEEncoder::Restart() {
    257   CriticalSectionScoped cs(data_cs_.get());
    258   encoder_paused_ = false;
    259 }
    260 
    261 uint8_t ViEEncoder::NumberOfCodecs() {
    262   return vcm_.NumberOfCodecs();
    263 }
    264 
    265 int32_t ViEEncoder::GetCodec(uint8_t list_index, VideoCodec* video_codec) {
    266   if (vcm_.Codec(list_index, video_codec) != 0) {
    267     return -1;
    268   }
    269   return 0;
    270 }
    271 
    272 int32_t ViEEncoder::RegisterExternalEncoder(webrtc::VideoEncoder* encoder,
    273                                             uint8_t pl_type,
    274                                             bool internal_source) {
    275   if (encoder == NULL)
    276     return -1;
    277 
    278   if (vcm_.RegisterExternalEncoder(encoder, pl_type, internal_source) !=
    279       VCM_OK) {
    280     return -1;
    281   }
    282   return 0;
    283 }
    284 
    285 int32_t ViEEncoder::DeRegisterExternalEncoder(uint8_t pl_type) {
    286   webrtc::VideoCodec current_send_codec;
    287   if (vcm_.SendCodec(&current_send_codec) == VCM_OK) {
    288     uint32_t current_bitrate_bps = 0;
    289     if (vcm_.Bitrate(&current_bitrate_bps) != 0) {
    290       LOG(LS_WARNING) << "Failed to get the current encoder target bitrate.";
    291     }
    292     current_send_codec.startBitrate = (current_bitrate_bps + 500) / 1000;
    293   }
    294 
    295   if (vcm_.RegisterExternalEncoder(NULL, pl_type) != VCM_OK) {
    296     return -1;
    297   }
    298 
    299   // If the external encoder is the current send codec, use vcm internal
    300   // encoder.
    301   if (current_send_codec.plType == pl_type) {
    302     uint16_t max_data_payload_length =
    303         default_rtp_rtcp_->MaxDataPayloadLength();
    304     {
    305       CriticalSectionScoped cs(data_cs_.get());
    306       send_padding_ = current_send_codec.numberOfSimulcastStreams > 1;
    307     }
    308     // TODO(mflodman): Unfortunately the VideoCodec that VCM has cached a
    309     // raw pointer to an |extra_options| that's long gone.  Clearing it here is
    310     // a hack to prevent the following code from crashing.  This should be fixed
    311     // for realz.  https://code.google.com/p/chromium/issues/detail?id=348222
    312     current_send_codec.extra_options = NULL;
    313     if (vcm_.RegisterSendCodec(&current_send_codec, number_of_cores_,
    314                                max_data_payload_length) != VCM_OK) {
    315       LOG(LS_INFO) << "De-registered the currently used external encoder ("
    316                    << static_cast<int>(pl_type) << ") and therefore tried to "
    317                    << "register the corresponding internal encoder, but none "
    318                    << "was supported.";
    319     }
    320   }
    321   return 0;
    322 }
    323 
    324 int32_t ViEEncoder::SetEncoder(const webrtc::VideoCodec& video_codec) {
    325   // Setting target width and height for VPM.
    326   if (vpm_.SetTargetResolution(video_codec.width, video_codec.height,
    327                                video_codec.maxFramerate) != VPM_OK) {
    328     return -1;
    329   }
    330 
    331   if (default_rtp_rtcp_->RegisterSendPayload(video_codec) != 0) {
    332     return -1;
    333   }
    334   // Convert from kbps to bps.
    335   std::vector<uint32_t> stream_bitrates = AllocateStreamBitrates(
    336       video_codec.startBitrate * 1000,
    337       video_codec.simulcastStream,
    338       video_codec.numberOfSimulcastStreams);
    339   default_rtp_rtcp_->SetTargetSendBitrate(stream_bitrates);
    340 
    341   uint16_t max_data_payload_length =
    342       default_rtp_rtcp_->MaxDataPayloadLength();
    343 
    344   {
    345     CriticalSectionScoped cs(data_cs_.get());
    346     send_padding_ = video_codec.numberOfSimulcastStreams > 1;
    347   }
    348   if (vcm_.RegisterSendCodec(&video_codec, number_of_cores_,
    349                              max_data_payload_length) != VCM_OK) {
    350     return -1;
    351   }
    352 
    353   // Set this module as sending right away, let the slave module in the channel
    354   // start and stop sending.
    355   if (default_rtp_rtcp_->SetSendingStatus(true) != 0) {
    356     return -1;
    357   }
    358 
    359   bitrate_controller_->SetBitrateObserver(bitrate_observer_.get(),
    360                                           video_codec.startBitrate * 1000,
    361                                           video_codec.minBitrate * 1000,
    362                                           kTransmissionMaxBitrateMultiplier *
    363                                           video_codec.maxBitrate * 1000);
    364 
    365   CriticalSectionScoped crit(data_cs_.get());
    366   int pad_up_to_bitrate_kbps = video_codec.startBitrate;
    367   if (pad_up_to_bitrate_kbps < min_transmit_bitrate_kbps_)
    368     pad_up_to_bitrate_kbps = min_transmit_bitrate_kbps_;
    369 
    370   paced_sender_->UpdateBitrate(
    371       PacedSender::kDefaultPaceMultiplier * video_codec.startBitrate,
    372       pad_up_to_bitrate_kbps);
    373 
    374   return 0;
    375 }
    376 
    377 int32_t ViEEncoder::GetEncoder(VideoCodec* video_codec) {
    378   if (vcm_.SendCodec(video_codec) != 0) {
    379     return -1;
    380   }
    381   return 0;
    382 }
    383 
    384 int32_t ViEEncoder::GetCodecConfigParameters(
    385     unsigned char config_parameters[kConfigParameterSize],
    386     unsigned char& config_parameters_size) {
    387   int32_t num_parameters =
    388       vcm_.CodecConfigParameters(config_parameters, kConfigParameterSize);
    389   if (num_parameters <= 0) {
    390     config_parameters_size = 0;
    391     return -1;
    392   }
    393   config_parameters_size = static_cast<unsigned char>(num_parameters);
    394   return 0;
    395 }
    396 
    397 int32_t ViEEncoder::ScaleInputImage(bool enable) {
    398   VideoFrameResampling resampling_mode = kFastRescaling;
    399   // TODO(mflodman) What?
    400   if (enable) {
    401     // kInterpolation is currently not supported.
    402     LOG_F(LS_ERROR) << "Not supported.";
    403     return -1;
    404   }
    405   vpm_.SetInputFrameResampleMode(resampling_mode);
    406 
    407   return 0;
    408 }
    409 
    410 bool ViEEncoder::TimeToSendPacket(uint32_t ssrc,
    411                                   uint16_t sequence_number,
    412                                   int64_t capture_time_ms,
    413                                   bool retransmission) {
    414   return default_rtp_rtcp_->TimeToSendPacket(ssrc, sequence_number,
    415                                              capture_time_ms, retransmission);
    416 }
    417 
    418 int ViEEncoder::TimeToSendPadding(int bytes) {
    419   bool send_padding;
    420   {
    421     CriticalSectionScoped cs(data_cs_.get());
    422     send_padding =
    423         send_padding_ || video_suspended_ || min_transmit_bitrate_kbps_ > 0;
    424   }
    425   if (send_padding) {
    426     return default_rtp_rtcp_->TimeToSendPadding(bytes);
    427   }
    428   return 0;
    429 }
    430 
    431 bool ViEEncoder::EncoderPaused() const {
    432   // Pause video if paused by caller or as long as the network is down or the
    433   // pacer queue has grown too large in buffered mode.
    434   if (encoder_paused_) {
    435     return true;
    436   }
    437   if (target_delay_ms_ > 0) {
    438     // Buffered mode.
    439     // TODO(pwestin): Workaround until nack is configured as a time and not
    440     // number of packets.
    441     return paced_sender_->QueueInMs() >=
    442         std::max(static_cast<int>(target_delay_ms_ * kEncoderPausePacerMargin),
    443                  kMinPacingDelayMs);
    444   }
    445   return !network_is_transmitting_;
    446 }
    447 
    448 RtpRtcp* ViEEncoder::SendRtpRtcpModule() {
    449   return default_rtp_rtcp_.get();
    450 }
    451 
    452 void ViEEncoder::DeliverFrame(int id,
    453                               I420VideoFrame* video_frame,
    454                               int num_csrcs,
    455                               const uint32_t CSRC[kRtpCsrcSize]) {
    456   if (default_rtp_rtcp_->SendingMedia() == false) {
    457     // We've paused or we have no channels attached, don't encode.
    458     return;
    459   }
    460   {
    461     CriticalSectionScoped cs(data_cs_.get());
    462     time_of_last_incoming_frame_ms_ = TickTime::MillisecondTimestamp();
    463     if (EncoderPaused()) {
    464       if (!encoder_paused_and_dropped_frame_) {
    465         TRACE_EVENT_ASYNC_BEGIN0("webrtc", "EncoderPaused", this);
    466       }
    467       encoder_paused_and_dropped_frame_ = true;
    468       return;
    469     }
    470     if (encoder_paused_and_dropped_frame_) {
    471       TRACE_EVENT_ASYNC_END0("webrtc", "EncoderPaused", this);
    472     }
    473     encoder_paused_and_dropped_frame_ = false;
    474   }
    475 
    476   // Convert render time, in ms, to RTP timestamp.
    477   const int kMsToRtpTimestamp = 90;
    478   const uint32_t time_stamp =
    479       kMsToRtpTimestamp *
    480       static_cast<uint32_t>(video_frame->render_time_ms());
    481 
    482   TRACE_EVENT_ASYNC_STEP0("webrtc", "Video", video_frame->render_time_ms(),
    483                           "Encode");
    484   video_frame->set_timestamp(time_stamp);
    485 
    486   // Make sure the CSRC list is correct.
    487   if (num_csrcs > 0) {
    488     uint32_t tempCSRC[kRtpCsrcSize];
    489     for (int i = 0; i < num_csrcs; i++) {
    490       if (CSRC[i] == 1) {
    491         tempCSRC[i] = default_rtp_rtcp_->SSRC();
    492       } else {
    493         tempCSRC[i] = CSRC[i];
    494       }
    495     }
    496     default_rtp_rtcp_->SetCSRCs(tempCSRC, (uint8_t) num_csrcs);
    497   }
    498 
    499   I420VideoFrame* decimated_frame = NULL;
    500   // TODO(wuchengli): support texture frames.
    501   if (video_frame->native_handle() == NULL) {
    502     {
    503       CriticalSectionScoped cs(callback_cs_.get());
    504       if (effect_filter_) {
    505         unsigned int length =
    506             CalcBufferSize(kI420, video_frame->width(), video_frame->height());
    507         scoped_ptr<uint8_t[]> video_buffer(new uint8_t[length]);
    508         ExtractBuffer(*video_frame, length, video_buffer.get());
    509         effect_filter_->Transform(length,
    510                                   video_buffer.get(),
    511                                   video_frame->ntp_time_ms(),
    512                                   video_frame->timestamp(),
    513                                   video_frame->width(),
    514                                   video_frame->height());
    515       }
    516     }
    517 
    518     // Pass frame via preprocessor.
    519     const int ret = vpm_.PreprocessFrame(*video_frame, &decimated_frame);
    520     if (ret == 1) {
    521       // Drop this frame.
    522       return;
    523     }
    524     if (ret != VPM_OK) {
    525       return;
    526     }
    527   }
    528   // If the frame was not resampled or scaled => use original.
    529   if (decimated_frame == NULL)  {
    530     decimated_frame = video_frame;
    531   }
    532 
    533   {
    534     CriticalSectionScoped cs(callback_cs_.get());
    535     if (pre_encode_callback_)
    536       pre_encode_callback_->FrameCallback(decimated_frame);
    537   }
    538 
    539   if (video_frame->native_handle() != NULL) {
    540     // TODO(wuchengli): add texture support. http://crbug.com/362437
    541     return;
    542   }
    543 
    544 #ifdef VIDEOCODEC_VP8
    545   if (vcm_.SendCodec() == webrtc::kVideoCodecVP8) {
    546     webrtc::CodecSpecificInfo codec_specific_info;
    547     codec_specific_info.codecType = webrtc::kVideoCodecVP8;
    548     {
    549       CriticalSectionScoped cs(data_cs_.get());
    550       codec_specific_info.codecSpecific.VP8.hasReceivedRPSI =
    551           has_received_rpsi_;
    552       codec_specific_info.codecSpecific.VP8.hasReceivedSLI =
    553           has_received_sli_;
    554       codec_specific_info.codecSpecific.VP8.pictureIdRPSI =
    555           picture_id_rpsi_;
    556       codec_specific_info.codecSpecific.VP8.pictureIdSLI  =
    557           picture_id_sli_;
    558       has_received_sli_ = false;
    559       has_received_rpsi_ = false;
    560     }
    561 
    562     vcm_.AddVideoFrame(*decimated_frame, vpm_.ContentMetrics(),
    563                        &codec_specific_info);
    564     return;
    565   }
    566 #endif
    567   vcm_.AddVideoFrame(*decimated_frame);
    568 }
    569 
    570 void ViEEncoder::DelayChanged(int id, int frame_delay) {
    571   default_rtp_rtcp_->SetCameraDelay(frame_delay);
    572 }
    573 
    574 int ViEEncoder::GetPreferedFrameSettings(int* width,
    575                                          int* height,
    576                                          int* frame_rate) {
    577   webrtc::VideoCodec video_codec;
    578   memset(&video_codec, 0, sizeof(video_codec));
    579   if (vcm_.SendCodec(&video_codec) != VCM_OK) {
    580     return -1;
    581   }
    582 
    583   *width = video_codec.width;
    584   *height = video_codec.height;
    585   *frame_rate = video_codec.maxFramerate;
    586   return 0;
    587 }
    588 
    589 int ViEEncoder::SendKeyFrame() {
    590   return vcm_.IntraFrameRequest(0);
    591 }
    592 
    593 int32_t ViEEncoder::SendCodecStatistics(
    594     uint32_t* num_key_frames, uint32_t* num_delta_frames) {
    595   webrtc::VCMFrameCount sent_frames;
    596   if (vcm_.SentFrameCount(sent_frames) != VCM_OK) {
    597     return -1;
    598   }
    599   *num_key_frames = sent_frames.numKeyFrames;
    600   *num_delta_frames = sent_frames.numDeltaFrames;
    601   return 0;
    602 }
    603 
    604 int32_t ViEEncoder::PacerQueuingDelayMs() const {
    605   return paced_sender_->QueueInMs();
    606 }
    607 
    608 int ViEEncoder::CodecTargetBitrate(uint32_t* bitrate) const {
    609   if (vcm_.Bitrate(bitrate) != 0)
    610     return -1;
    611   return 0;
    612 }
    613 
    614 int32_t ViEEncoder::UpdateProtectionMethod(bool enable_nack) {
    615   bool fec_enabled = false;
    616   uint8_t dummy_ptype_red = 0;
    617   uint8_t dummy_ptypeFEC = 0;
    618 
    619   // Updated protection method to VCM to get correct packetization sizes.
    620   // FEC has larger overhead than NACK -> set FEC if used.
    621   int32_t error = default_rtp_rtcp_->GenericFECStatus(fec_enabled,
    622                                                       dummy_ptype_red,
    623                                                       dummy_ptypeFEC);
    624   if (error) {
    625     return -1;
    626   }
    627   if (fec_enabled_ == fec_enabled && nack_enabled_ == enable_nack) {
    628     // No change needed, we're already in correct state.
    629     return 0;
    630   }
    631   fec_enabled_ = fec_enabled;
    632   nack_enabled_ = enable_nack;
    633 
    634   // Set Video Protection for VCM.
    635   if (fec_enabled && nack_enabled_) {
    636     vcm_.SetVideoProtection(webrtc::kProtectionNackFEC, true);
    637   } else {
    638     vcm_.SetVideoProtection(webrtc::kProtectionFEC, fec_enabled_);
    639     vcm_.SetVideoProtection(webrtc::kProtectionNackSender, nack_enabled_);
    640     vcm_.SetVideoProtection(webrtc::kProtectionNackFEC, false);
    641   }
    642 
    643   if (fec_enabled_ || nack_enabled_) {
    644     vcm_.RegisterProtectionCallback(this);
    645     // The send codec must be registered to set correct MTU.
    646     webrtc::VideoCodec codec;
    647     if (vcm_.SendCodec(&codec) == 0) {
    648       uint16_t max_pay_load = default_rtp_rtcp_->MaxDataPayloadLength();
    649       uint32_t current_bitrate_bps = 0;
    650       if (vcm_.Bitrate(&current_bitrate_bps) != 0) {
    651         LOG_F(LS_WARNING) <<
    652             "Failed to get the current encoder target bitrate.";
    653       }
    654       // Convert to start bitrate in kbps.
    655       codec.startBitrate = (current_bitrate_bps + 500) / 1000;
    656       if (vcm_.RegisterSendCodec(&codec, number_of_cores_, max_pay_load) != 0) {
    657         return -1;
    658       }
    659     }
    660     return 0;
    661   } else {
    662     // FEC and NACK are disabled.
    663     vcm_.RegisterProtectionCallback(NULL);
    664   }
    665   return 0;
    666 }
    667 
    668 void ViEEncoder::SetSenderBufferingMode(int target_delay_ms) {
    669   {
    670     CriticalSectionScoped cs(data_cs_.get());
    671     target_delay_ms_ = target_delay_ms;
    672   }
    673   if (target_delay_ms > 0) {
    674     // Disable external frame-droppers.
    675     vcm_.EnableFrameDropper(false);
    676     vpm_.EnableTemporalDecimation(false);
    677     // We don't put any limits on the pacer queue when running in buffered mode
    678     // since the encoder will be paused if the queue grow too large.
    679     paced_sender_->set_max_queue_length_ms(-1);
    680   } else {
    681     // Real-time mode - enable frame droppers.
    682     vpm_.EnableTemporalDecimation(true);
    683     vcm_.EnableFrameDropper(true);
    684     paced_sender_->set_max_queue_length_ms(
    685         PacedSender::kDefaultMaxQueueLengthMs);
    686   }
    687 }
    688 
    689 int32_t ViEEncoder::SendData(
    690     const FrameType frame_type,
    691     const uint8_t payload_type,
    692     const uint32_t time_stamp,
    693     int64_t capture_time_ms,
    694     const uint8_t* payload_data,
    695     const uint32_t payload_size,
    696     const webrtc::RTPFragmentationHeader& fragmentation_header,
    697     const RTPVideoHeader* rtp_video_hdr) {
    698   // New encoded data, hand over to the rtp module.
    699   return default_rtp_rtcp_->SendOutgoingData(frame_type,
    700                                              payload_type,
    701                                              time_stamp,
    702                                              capture_time_ms,
    703                                              payload_data,
    704                                              payload_size,
    705                                              &fragmentation_header,
    706                                              rtp_video_hdr);
    707 }
    708 
    709 int32_t ViEEncoder::ProtectionRequest(
    710     const FecProtectionParams* delta_fec_params,
    711     const FecProtectionParams* key_fec_params,
    712     uint32_t* sent_video_rate_bps,
    713     uint32_t* sent_nack_rate_bps,
    714     uint32_t* sent_fec_rate_bps) {
    715   default_rtp_rtcp_->SetFecParameters(delta_fec_params, key_fec_params);
    716   default_rtp_rtcp_->BitrateSent(NULL, sent_video_rate_bps, sent_fec_rate_bps,
    717                                 sent_nack_rate_bps);
    718   return 0;
    719 }
    720 
    721 int32_t ViEEncoder::SendStatistics(const uint32_t bit_rate,
    722                                    const uint32_t frame_rate) {
    723   CriticalSectionScoped cs(callback_cs_.get());
    724   if (codec_observer_) {
    725     codec_observer_->OutgoingRate(channel_id_, frame_rate, bit_rate);
    726   }
    727   return 0;
    728 }
    729 
    730 int32_t ViEEncoder::RegisterCodecObserver(ViEEncoderObserver* observer) {
    731   CriticalSectionScoped cs(callback_cs_.get());
    732   if (observer && codec_observer_) {
    733     LOG_F(LS_ERROR) << "Observer already set.";
    734     return -1;
    735   }
    736   codec_observer_ = observer;
    737   return 0;
    738 }
    739 
    740 void ViEEncoder::OnReceivedSLI(uint32_t /*ssrc*/,
    741                                uint8_t picture_id) {
    742   CriticalSectionScoped cs(data_cs_.get());
    743   picture_id_sli_ = picture_id;
    744   has_received_sli_ = true;
    745 }
    746 
    747 void ViEEncoder::OnReceivedRPSI(uint32_t /*ssrc*/,
    748                                 uint64_t picture_id) {
    749   CriticalSectionScoped cs(data_cs_.get());
    750   picture_id_rpsi_ = picture_id;
    751   has_received_rpsi_ = true;
    752 }
    753 
    754 void ViEEncoder::OnReceivedIntraFrameRequest(uint32_t ssrc) {
    755   // Key frame request from remote side, signal to VCM.
    756   TRACE_EVENT0("webrtc", "OnKeyFrameRequest");
    757 
    758   int idx = 0;
    759   {
    760     CriticalSectionScoped cs(data_cs_.get());
    761     std::map<unsigned int, int>::iterator stream_it = ssrc_streams_.find(ssrc);
    762     if (stream_it == ssrc_streams_.end()) {
    763       LOG_F(LS_WARNING) << "ssrc not found: " << ssrc << ", map size "
    764                         << ssrc_streams_.size();
    765       return;
    766     }
    767     std::map<unsigned int, int64_t>::iterator time_it =
    768         time_last_intra_request_ms_.find(ssrc);
    769     if (time_it == time_last_intra_request_ms_.end()) {
    770       time_last_intra_request_ms_[ssrc] = 0;
    771     }
    772 
    773     int64_t now = TickTime::MillisecondTimestamp();
    774     if (time_last_intra_request_ms_[ssrc] + kViEMinKeyRequestIntervalMs > now) {
    775       return;
    776     }
    777     time_last_intra_request_ms_[ssrc] = now;
    778     idx = stream_it->second;
    779   }
    780   // Release the critsect before triggering key frame.
    781   vcm_.IntraFrameRequest(idx);
    782 }
    783 
    784 void ViEEncoder::OnLocalSsrcChanged(uint32_t old_ssrc, uint32_t new_ssrc) {
    785   CriticalSectionScoped cs(data_cs_.get());
    786   std::map<unsigned int, int>::iterator it = ssrc_streams_.find(old_ssrc);
    787   if (it == ssrc_streams_.end()) {
    788     return;
    789   }
    790 
    791   ssrc_streams_[new_ssrc] = it->second;
    792   ssrc_streams_.erase(it);
    793 
    794   std::map<unsigned int, int64_t>::iterator time_it =
    795       time_last_intra_request_ms_.find(old_ssrc);
    796   int64_t last_intra_request_ms = 0;
    797   if (time_it != time_last_intra_request_ms_.end()) {
    798     last_intra_request_ms = time_it->second;
    799     time_last_intra_request_ms_.erase(time_it);
    800   }
    801   time_last_intra_request_ms_[new_ssrc] = last_intra_request_ms;
    802 }
    803 
    804 bool ViEEncoder::SetSsrcs(const std::list<unsigned int>& ssrcs) {
    805   VideoCodec codec;
    806   if (vcm_.SendCodec(&codec) != 0)
    807     return false;
    808 
    809   if (codec.numberOfSimulcastStreams > 0 &&
    810       ssrcs.size() != codec.numberOfSimulcastStreams) {
    811     return false;
    812   }
    813 
    814   CriticalSectionScoped cs(data_cs_.get());
    815   ssrc_streams_.clear();
    816   time_last_intra_request_ms_.clear();
    817   int idx = 0;
    818   for (std::list<unsigned int>::const_iterator it = ssrcs.begin();
    819        it != ssrcs.end(); ++it, ++idx) {
    820     unsigned int ssrc = *it;
    821     ssrc_streams_[ssrc] = idx;
    822   }
    823   return true;
    824 }
    825 
    826 void ViEEncoder::SetMinTransmitBitrate(int min_transmit_bitrate_kbps) {
    827   assert(min_transmit_bitrate_kbps >= 0);
    828   CriticalSectionScoped crit(data_cs_.get());
    829   min_transmit_bitrate_kbps_ = min_transmit_bitrate_kbps;
    830 }
    831 
    832 // Called from ViEBitrateObserver.
    833 void ViEEncoder::OnNetworkChanged(const uint32_t bitrate_bps,
    834                                   const uint8_t fraction_lost,
    835                                   const uint32_t round_trip_time_ms) {
    836   LOG(LS_VERBOSE) << "OnNetworkChanged, bitrate" << bitrate_bps
    837                   << " packet loss " << fraction_lost
    838                   << " rtt " << round_trip_time_ms;
    839   vcm_.SetChannelParameters(bitrate_bps, fraction_lost, round_trip_time_ms);
    840   bool video_is_suspended = vcm_.VideoSuspended();
    841   int bitrate_kbps = bitrate_bps / 1000;
    842   VideoCodec send_codec;
    843   if (vcm_.SendCodec(&send_codec) != 0) {
    844     return;
    845   }
    846   SimulcastStream* stream_configs = send_codec.simulcastStream;
    847   // Allocate the bandwidth between the streams.
    848   std::vector<uint32_t> stream_bitrates = AllocateStreamBitrates(
    849       bitrate_bps,
    850       stream_configs,
    851       send_codec.numberOfSimulcastStreams);
    852   // Find the max amount of padding we can allow ourselves to send at this
    853   // point, based on which streams are currently active and what our current
    854   // available bandwidth is.
    855   int pad_up_to_bitrate_kbps = 0;
    856   if (send_codec.numberOfSimulcastStreams == 0) {
    857     pad_up_to_bitrate_kbps = send_codec.minBitrate;
    858   } else {
    859     pad_up_to_bitrate_kbps =
    860         stream_configs[send_codec.numberOfSimulcastStreams - 1].minBitrate;
    861     for (int i = 0; i < send_codec.numberOfSimulcastStreams - 1; ++i) {
    862       pad_up_to_bitrate_kbps += stream_configs[i].targetBitrate;
    863     }
    864   }
    865 
    866   // Disable padding if only sending one stream and video isn't suspended and
    867   // min-transmit bitrate isn't used (applied later).
    868   if (!video_is_suspended && send_codec.numberOfSimulcastStreams <= 1)
    869     pad_up_to_bitrate_kbps = 0;
    870 
    871   {
    872     CriticalSectionScoped cs(data_cs_.get());
    873     // The amount of padding should decay to zero if no frames are being
    874     // captured unless a min-transmit bitrate is used.
    875     int64_t now_ms = TickTime::MillisecondTimestamp();
    876     if (now_ms - time_of_last_incoming_frame_ms_ > kStopPaddingThresholdMs)
    877       pad_up_to_bitrate_kbps = 0;
    878 
    879     // Pad up to min bitrate.
    880     if (pad_up_to_bitrate_kbps < min_transmit_bitrate_kbps_)
    881       pad_up_to_bitrate_kbps = min_transmit_bitrate_kbps_;
    882 
    883     // Padding may never exceed bitrate estimate.
    884     if (pad_up_to_bitrate_kbps > bitrate_kbps)
    885       pad_up_to_bitrate_kbps = bitrate_kbps;
    886 
    887     paced_sender_->UpdateBitrate(
    888         PacedSender::kDefaultPaceMultiplier * bitrate_kbps,
    889         pad_up_to_bitrate_kbps);
    890     default_rtp_rtcp_->SetTargetSendBitrate(stream_bitrates);
    891     if (video_suspended_ == video_is_suspended)
    892       return;
    893     video_suspended_ = video_is_suspended;
    894   }
    895 
    896   // Video suspend-state changed, inform codec observer.
    897   CriticalSectionScoped crit(callback_cs_.get());
    898   if (codec_observer_) {
    899     LOG(LS_INFO) << "Video suspended " << video_is_suspended
    900                  << " for channel " << channel_id_;
    901     codec_observer_->SuspendChange(channel_id_, video_is_suspended);
    902   }
    903 }
    904 
    905 PacedSender* ViEEncoder::GetPacedSender() {
    906   return paced_sender_.get();
    907 }
    908 
    909 int32_t ViEEncoder::RegisterEffectFilter(ViEEffectFilter* effect_filter) {
    910   CriticalSectionScoped cs(callback_cs_.get());
    911   if (effect_filter != NULL && effect_filter_ != NULL) {
    912     LOG_F(LS_ERROR) << "Filter already set.";
    913     return -1;
    914   }
    915   effect_filter_ = effect_filter;
    916   return 0;
    917 }
    918 
    919 int ViEEncoder::StartDebugRecording(const char* fileNameUTF8) {
    920   return vcm_.StartDebugRecording(fileNameUTF8);
    921 }
    922 
    923 int ViEEncoder::StopDebugRecording() {
    924   return vcm_.StopDebugRecording();
    925 }
    926 
    927 void ViEEncoder::SuspendBelowMinBitrate() {
    928   vcm_.SuspendBelowMinBitrate();
    929   bitrate_controller_->EnforceMinBitrate(false);
    930 }
    931 
    932 void ViEEncoder::RegisterPreEncodeCallback(
    933     I420FrameCallback* pre_encode_callback) {
    934   CriticalSectionScoped cs(callback_cs_.get());
    935   pre_encode_callback_ = pre_encode_callback;
    936 }
    937 
    938 void ViEEncoder::DeRegisterPreEncodeCallback() {
    939   CriticalSectionScoped cs(callback_cs_.get());
    940   pre_encode_callback_ = NULL;
    941 }
    942 
    943 void ViEEncoder::RegisterPostEncodeImageCallback(
    944       EncodedImageCallback* post_encode_callback) {
    945   vcm_.RegisterPostEncodeImageCallback(post_encode_callback);
    946 }
    947 
    948 void ViEEncoder::DeRegisterPostEncodeImageCallback() {
    949   vcm_.RegisterPostEncodeImageCallback(NULL);
    950 }
    951 
    952 QMVideoSettingsCallback::QMVideoSettingsCallback(VideoProcessingModule* vpm)
    953     : vpm_(vpm) {
    954 }
    955 
    956 QMVideoSettingsCallback::~QMVideoSettingsCallback() {
    957 }
    958 
    959 int32_t QMVideoSettingsCallback::SetVideoQMSettings(
    960     const uint32_t frame_rate,
    961     const uint32_t width,
    962     const uint32_t height) {
    963   return vpm_->SetTargetResolution(width, height, frame_rate);
    964 }
    965 
    966 }  // namespace webrtc
    967