Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / video_engine / vie_encoder.cc
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/critical_section_wrapper.h"
27 #include "webrtc/system_wrappers/interface/logging.h"
28 #include "webrtc/system_wrappers/interface/tick_util.h"
29 #include "webrtc/system_wrappers/interface/trace.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 // Pace in kbits/s until we receive first estimate.
39 static const int kInitialPace = 2000;
40
41 // Pacing-rate relative to our target send rate.
42 // Multiplicative factor that is applied to the target bitrate to calculate the
43 // number of bytes that can be transmitted per interval.
44 // Increasing this factor will result in lower delays in cases of bitrate
45 // overshoots from the encoder.
46 static const float kPaceMultiplier = 2.5f;
47
48 // Margin on when we pause the encoder when the pacing buffer overflows relative
49 // to the configured buffer delay.
50 static const float kEncoderPausePacerMargin = 2.0f;
51
52 // Don't stop the encoder unless the delay is above this configured value.
53 static const int kMinPacingDelayMs = 200;
54
55 // Allow packets to be transmitted in up to 2 times max video bitrate if the
56 // bandwidth estimate allows it.
57 // TODO(holmer): Expose transmission start, min and max bitrates in the
58 // VideoEngine API and remove the kTransmissionMaxBitrateMultiplier.
59 static const int kTransmissionMaxBitrateMultiplier = 2;
60
61 static const float kStopPaddingThresholdMs = 2000;
62
63 std::vector<uint32_t> AllocateStreamBitrates(
64     uint32_t total_bitrate,
65     const SimulcastStream* stream_configs,
66     size_t number_of_streams) {
67   if (number_of_streams == 0) {
68     std::vector<uint32_t> stream_bitrates(1, 0);
69     stream_bitrates[0] = total_bitrate;
70     return stream_bitrates;
71   }
72   std::vector<uint32_t> stream_bitrates(number_of_streams, 0);
73   uint32_t bitrate_remainder = total_bitrate;
74   for (size_t i = 0; i < stream_bitrates.size() && bitrate_remainder > 0; ++i) {
75     if (stream_configs[i].maxBitrate * 1000 > bitrate_remainder) {
76       stream_bitrates[i] = bitrate_remainder;
77     } else {
78       stream_bitrates[i] = stream_configs[i].maxBitrate * 1000;
79     }
80     bitrate_remainder -= stream_bitrates[i];
81   }
82   return stream_bitrates;
83 }
84
85 class QMVideoSettingsCallback : public VCMQMSettingsCallback {
86  public:
87   explicit QMVideoSettingsCallback(VideoProcessingModule* vpm);
88
89   ~QMVideoSettingsCallback();
90
91   // Update VPM with QM (quality modes: frame size & frame rate) settings.
92   int32_t SetVideoQMSettings(const uint32_t frame_rate,
93                              const uint32_t width,
94                              const uint32_t height);
95
96  private:
97   VideoProcessingModule* vpm_;
98 };
99
100 class ViEBitrateObserver : public BitrateObserver {
101  public:
102   explicit ViEBitrateObserver(ViEEncoder* owner)
103       : owner_(owner) {
104   }
105   virtual ~ViEBitrateObserver() {}
106   // Implements BitrateObserver.
107   virtual void OnNetworkChanged(const uint32_t bitrate_bps,
108                                 const uint8_t fraction_lost,
109                                 const uint32_t rtt) {
110     owner_->OnNetworkChanged(bitrate_bps, fraction_lost, rtt);
111   }
112  private:
113   ViEEncoder* owner_;
114 };
115
116 class ViEPacedSenderCallback : public PacedSender::Callback {
117  public:
118   explicit ViEPacedSenderCallback(ViEEncoder* owner)
119       : owner_(owner) {
120   }
121   virtual ~ViEPacedSenderCallback() {}
122   virtual bool TimeToSendPacket(uint32_t ssrc, uint16_t sequence_number,
123                                 int64_t capture_time_ms, bool retransmission) {
124     return owner_->TimeToSendPacket(ssrc, sequence_number, capture_time_ms,
125                                     retransmission);
126   }
127   virtual int TimeToSendPadding(int bytes) {
128     return owner_->TimeToSendPadding(bytes);
129   }
130  private:
131   ViEEncoder* owner_;
132 };
133
134 ViEEncoder::ViEEncoder(int32_t engine_id,
135                        int32_t channel_id,
136                        uint32_t number_of_cores,
137                        const Config& config,
138                        ProcessThread& module_process_thread,
139                        BitrateController* bitrate_controller)
140   : engine_id_(engine_id),
141     channel_id_(channel_id),
142     number_of_cores_(number_of_cores),
143     vcm_(*webrtc::VideoCodingModule::Create(ViEModuleId(engine_id,
144                                                         channel_id))),
145     vpm_(*webrtc::VideoProcessingModule::Create(ViEModuleId(engine_id,
146                                                             channel_id))),
147     callback_cs_(CriticalSectionWrapper::CreateCriticalSection()),
148     data_cs_(CriticalSectionWrapper::CreateCriticalSection()),
149     bitrate_controller_(bitrate_controller),
150     time_of_last_incoming_frame_ms_(0),
151     send_padding_(false),
152     target_delay_ms_(0),
153     network_is_transmitting_(true),
154     encoder_paused_(false),
155     encoder_paused_and_dropped_frame_(false),
156     fec_enabled_(false),
157     nack_enabled_(false),
158     codec_observer_(NULL),
159     effect_filter_(NULL),
160     module_process_thread_(module_process_thread),
161     has_received_sli_(false),
162     picture_id_sli_(0),
163     has_received_rpsi_(false),
164     picture_id_rpsi_(0),
165     qm_callback_(NULL),
166     video_suspended_(false),
167     pre_encode_callback_(NULL) {
168   WEBRTC_TRACE(webrtc::kTraceMemory, webrtc::kTraceVideo,
169                ViEId(engine_id, channel_id),
170                "%s(engine_id: %d) 0x%p - Constructor", __FUNCTION__, engine_id,
171                this);
172
173   RtpRtcp::Configuration configuration;
174   configuration.id = ViEModuleId(engine_id_, channel_id_);
175   configuration.audio = false;  // Video.
176
177   default_rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(configuration));
178   bitrate_observer_.reset(new ViEBitrateObserver(this));
179   pacing_callback_.reset(new ViEPacedSenderCallback(this));
180   paced_sender_.reset(
181       new PacedSender(pacing_callback_.get(), kInitialPace, kPaceMultiplier));
182 }
183
184 bool ViEEncoder::Init() {
185   if (vcm_.InitializeSender() != 0) {
186     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
187                  ViEId(engine_id_, channel_id_),
188                  "%s InitializeSender failure", __FUNCTION__);
189     return false;
190   }
191   vpm_.EnableTemporalDecimation(true);
192
193   // Enable/disable content analysis: off by default for now.
194   vpm_.EnableContentAnalysis(false);
195
196   if (module_process_thread_.RegisterModule(&vcm_) != 0 ||
197       module_process_thread_.RegisterModule(default_rtp_rtcp_.get()) != 0 ||
198       module_process_thread_.RegisterModule(paced_sender_.get()) != 0) {
199     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
200                  ViEId(engine_id_, channel_id_),
201                  "%s RegisterModule failure", __FUNCTION__);
202     return false;
203   }
204   if (qm_callback_) {
205     delete qm_callback_;
206   }
207   qm_callback_ = new QMVideoSettingsCallback(&vpm_);
208
209 #ifdef VIDEOCODEC_VP8
210   VideoCodec video_codec;
211   if (vcm_.Codec(webrtc::kVideoCodecVP8, &video_codec) != VCM_OK) {
212     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
213                  ViEId(engine_id_, channel_id_),
214                  "%s Codec failure", __FUNCTION__);
215     return false;
216   }
217   send_padding_ = video_codec.numberOfSimulcastStreams > 1;
218   if (vcm_.RegisterSendCodec(&video_codec, number_of_cores_,
219                              default_rtp_rtcp_->MaxDataPayloadLength()) != 0) {
220     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
221                  ViEId(engine_id_, channel_id_),
222                  "%s RegisterSendCodec failure", __FUNCTION__);
223     return false;
224   }
225   if (default_rtp_rtcp_->RegisterSendPayload(video_codec) != 0) {
226     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
227                  ViEId(engine_id_, channel_id_),
228                  "%s RegisterSendPayload failure", __FUNCTION__);
229     return false;
230   }
231 #else
232   VideoCodec video_codec;
233   if (vcm_.Codec(webrtc::kVideoCodecI420, &video_codec) == VCM_OK) {
234     send_padding_ = video_codec.numberOfSimulcastStreams > 1;
235     vcm_.RegisterSendCodec(&video_codec, number_of_cores_,
236                            default_rtp_rtcp_->MaxDataPayloadLength());
237     default_rtp_rtcp_->RegisterSendPayload(video_codec);
238   } else {
239     return false;
240   }
241 #endif
242
243   if (vcm_.RegisterTransportCallback(this) != 0) {
244     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
245                  ViEId(engine_id_, channel_id_),
246                  "ViEEncoder: VCM::RegisterTransportCallback failure");
247     return false;
248   }
249   if (vcm_.RegisterSendStatisticsCallback(this) != 0) {
250     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
251                  ViEId(engine_id_, channel_id_),
252                  "ViEEncoder: VCM::RegisterSendStatisticsCallback failure");
253     return false;
254   }
255   if (vcm_.RegisterVideoQMCallback(qm_callback_) != 0) {
256     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
257                  ViEId(engine_id_, channel_id_),
258                  "VCM::RegisterQMCallback failure");
259     return false;
260   }
261   return true;
262 }
263
264 ViEEncoder::~ViEEncoder() {
265   WEBRTC_TRACE(webrtc::kTraceMemory, webrtc::kTraceVideo,
266                ViEId(engine_id_, channel_id_),
267                "ViEEncoder Destructor 0x%p, engine_id: %d", this, engine_id_);
268   if (bitrate_controller_) {
269     bitrate_controller_->RemoveBitrateObserver(bitrate_observer_.get());
270   }
271   module_process_thread_.DeRegisterModule(&vcm_);
272   module_process_thread_.DeRegisterModule(&vpm_);
273   module_process_thread_.DeRegisterModule(default_rtp_rtcp_.get());
274   module_process_thread_.DeRegisterModule(paced_sender_.get());
275   VideoCodingModule::Destroy(&vcm_);
276   VideoProcessingModule::Destroy(&vpm_);
277   delete qm_callback_;
278 }
279
280 int ViEEncoder::Owner() const {
281   return channel_id_;
282 }
283
284 void ViEEncoder::SetNetworkTransmissionState(bool is_transmitting) {
285   WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
286                ViEId(engine_id_, channel_id_),
287                "%s(%s)", __FUNCTION__,
288                is_transmitting ? "transmitting" : "not transmitting");
289   {
290     CriticalSectionScoped cs(data_cs_.get());
291     network_is_transmitting_ = is_transmitting;
292   }
293   if (is_transmitting) {
294     paced_sender_->Resume();
295   } else {
296     paced_sender_->Pause();
297   }
298 }
299
300 void ViEEncoder::Pause() {
301   WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
302                ViEId(engine_id_, channel_id_),
303                "%s", __FUNCTION__);
304   CriticalSectionScoped cs(data_cs_.get());
305   encoder_paused_ = true;
306 }
307
308 void ViEEncoder::Restart() {
309   WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
310                ViEId(engine_id_, channel_id_),
311                "%s", __FUNCTION__);
312   CriticalSectionScoped cs(data_cs_.get());
313   encoder_paused_ = false;
314 }
315
316 uint8_t ViEEncoder::NumberOfCodecs() {
317   return vcm_.NumberOfCodecs();
318 }
319
320 int32_t ViEEncoder::GetCodec(uint8_t list_index, VideoCodec* video_codec) {
321   if (vcm_.Codec(list_index, video_codec) != 0) {
322     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
323                  ViEId(engine_id_, channel_id_), "%s: Could not get codec",
324                  __FUNCTION__);
325     return -1;
326   }
327   return 0;
328 }
329
330 int32_t ViEEncoder::RegisterExternalEncoder(webrtc::VideoEncoder* encoder,
331                                             uint8_t pl_type,
332                                             bool internal_source) {
333   WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
334                ViEId(engine_id_, channel_id_), "%s: pltype %u", __FUNCTION__,
335                pl_type);
336
337   if (encoder == NULL)
338     return -1;
339
340   if (vcm_.RegisterExternalEncoder(encoder, pl_type, internal_source) !=
341           VCM_OK) {
342     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
343                  ViEId(engine_id_, channel_id_),
344                  "Could not register external encoder");
345     return -1;
346   }
347   return 0;
348 }
349
350 int32_t ViEEncoder::DeRegisterExternalEncoder(uint8_t pl_type) {
351   WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
352                ViEId(engine_id_, channel_id_),
353                "%s: pltype %u", __FUNCTION__, pl_type);
354
355   webrtc::VideoCodec current_send_codec;
356   if (vcm_.SendCodec(&current_send_codec) == VCM_OK) {
357     uint32_t current_bitrate_bps = 0;
358     if (vcm_.Bitrate(&current_bitrate_bps) != 0) {
359       WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideo,
360                    ViEId(engine_id_, channel_id_),
361                    "Failed to get the current encoder target bitrate.");
362     }
363     current_send_codec.startBitrate = (current_bitrate_bps + 500) / 1000;
364   }
365
366   if (vcm_.RegisterExternalEncoder(NULL, pl_type) != VCM_OK) {
367     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
368                  ViEId(engine_id_, channel_id_),
369                  "Could not deregister external encoder");
370     return -1;
371   }
372
373   // If the external encoder is the current send codec, use vcm internal
374   // encoder.
375   if (current_send_codec.plType == pl_type) {
376     uint16_t max_data_payload_length =
377         default_rtp_rtcp_->MaxDataPayloadLength();
378     send_padding_ = current_send_codec.numberOfSimulcastStreams > 1;
379     if (vcm_.RegisterSendCodec(&current_send_codec, number_of_cores_,
380                                max_data_payload_length) != VCM_OK) {
381       WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
382                    ViEId(engine_id_, channel_id_),
383                    "Could not use internal encoder");
384       return -1;
385     }
386   }
387   return 0;
388 }
389
390 int32_t ViEEncoder::SetEncoder(const webrtc::VideoCodec& video_codec) {
391   WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
392                ViEId(engine_id_, channel_id_),
393                "%s: CodecType: %d, width: %u, height: %u", __FUNCTION__,
394                video_codec.codecType, video_codec.width, video_codec.height);
395   // Setting target width and height for VPM.
396   if (vpm_.SetTargetResolution(video_codec.width, video_codec.height,
397                                video_codec.maxFramerate) != VPM_OK) {
398     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
399                  ViEId(engine_id_, channel_id_),
400                  "Could not set VPM target dimensions");
401     return -1;
402   }
403
404   if (default_rtp_rtcp_->RegisterSendPayload(video_codec) != 0) {
405     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
406                  ViEId(engine_id_, channel_id_),
407                  "Could register RTP module video payload");
408     return -1;
409   }
410   // Convert from kbps to bps.
411   std::vector<uint32_t> stream_bitrates = AllocateStreamBitrates(
412       video_codec.startBitrate * 1000,
413       video_codec.simulcastStream,
414       video_codec.numberOfSimulcastStreams);
415   default_rtp_rtcp_->SetTargetSendBitrate(stream_bitrates);
416
417   uint16_t max_data_payload_length =
418       default_rtp_rtcp_->MaxDataPayloadLength();
419
420   send_padding_ = video_codec.numberOfSimulcastStreams > 1;
421   if (vcm_.RegisterSendCodec(&video_codec, number_of_cores_,
422                              max_data_payload_length) != VCM_OK) {
423     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
424                  ViEId(engine_id_, channel_id_),
425                  "Could not register send codec");
426     return -1;
427   }
428
429   // Set this module as sending right away, let the slave module in the channel
430   // start and stop sending.
431   if (default_rtp_rtcp_->Sending() == false) {
432     if (default_rtp_rtcp_->SetSendingStatus(true) != 0) {
433       WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
434                    ViEId(engine_id_, channel_id_),
435                    "Could start RTP module sending");
436       return -1;
437     }
438   }
439   bitrate_controller_->SetBitrateObserver(bitrate_observer_.get(),
440                                           video_codec.startBitrate * 1000,
441                                           video_codec.minBitrate * 1000,
442                                           kTransmissionMaxBitrateMultiplier *
443                                           video_codec.maxBitrate * 1000);
444
445   return 0;
446 }
447
448 int32_t ViEEncoder::GetEncoder(VideoCodec* video_codec) {
449   WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
450                ViEId(engine_id_, channel_id_), "%s", __FUNCTION__);
451
452   if (vcm_.SendCodec(video_codec) != 0) {
453     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
454                  ViEId(engine_id_, channel_id_),
455                  "Could not get VCM send codec");
456     return -1;
457   }
458   return 0;
459 }
460
461 int32_t ViEEncoder::GetCodecConfigParameters(
462     unsigned char config_parameters[kConfigParameterSize],
463     unsigned char& config_parameters_size) {
464   WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
465                ViEId(engine_id_, channel_id_), "%s", __FUNCTION__);
466
467   int32_t num_parameters =
468       vcm_.CodecConfigParameters(config_parameters, kConfigParameterSize);
469   if (num_parameters <= 0) {
470     config_parameters_size = 0;
471     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
472                  ViEId(engine_id_, channel_id_),
473                  "Could not get config parameters");
474     return -1;
475   }
476   config_parameters_size = static_cast<unsigned char>(num_parameters);
477   return 0;
478 }
479
480 int32_t ViEEncoder::ScaleInputImage(bool enable) {
481   WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
482                ViEId(engine_id_, channel_id_), "%s(enable %d)", __FUNCTION__,
483                enable);
484
485   VideoFrameResampling resampling_mode = kFastRescaling;
486   if (enable == true) {
487     // kInterpolation is currently not supported.
488     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
489                  ViEId(engine_id_, channel_id_), "%s not supported",
490                  __FUNCTION__, enable);
491     return -1;
492   }
493   vpm_.SetInputFrameResampleMode(resampling_mode);
494
495   return 0;
496 }
497
498 bool ViEEncoder::TimeToSendPacket(uint32_t ssrc,
499                                   uint16_t sequence_number,
500                                   int64_t capture_time_ms,
501                                   bool retransmission) {
502   return default_rtp_rtcp_->TimeToSendPacket(ssrc, sequence_number,
503                                              capture_time_ms, retransmission);
504 }
505
506 int ViEEncoder::TimeToSendPadding(int bytes) {
507   bool send_padding;
508   {
509     CriticalSectionScoped cs(data_cs_.get());
510     send_padding = send_padding_ || video_suspended_;
511   }
512   if (send_padding) {
513     return default_rtp_rtcp_->TimeToSendPadding(bytes);
514   }
515   return 0;
516 }
517
518 bool ViEEncoder::EncoderPaused() const {
519   // Pause video if paused by caller or as long as the network is down or the
520   // pacer queue has grown too large in buffered mode.
521   if (encoder_paused_) {
522     return true;
523   }
524   if (target_delay_ms_ > 0) {
525     // Buffered mode.
526     // TODO(pwestin): Workaround until nack is configured as a time and not
527     // number of packets.
528     return paced_sender_->QueueInMs() >=
529         std::max(static_cast<int>(target_delay_ms_ * kEncoderPausePacerMargin),
530                  kMinPacingDelayMs);
531   }
532   return !network_is_transmitting_;
533 }
534
535 RtpRtcp* ViEEncoder::SendRtpRtcpModule() {
536   WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
537                ViEId(engine_id_, channel_id_), "%s", __FUNCTION__);
538
539   return default_rtp_rtcp_.get();
540 }
541
542 void ViEEncoder::DeliverFrame(int id,
543                               I420VideoFrame* video_frame,
544                               int num_csrcs,
545                               const uint32_t CSRC[kRtpCsrcSize]) {
546   WEBRTC_TRACE(webrtc::kTraceStream,
547                webrtc::kTraceVideo,
548                ViEId(engine_id_, channel_id_),
549                "%s: %llu", __FUNCTION__,
550                video_frame->timestamp());
551   {
552     CriticalSectionScoped cs(data_cs_.get());
553     time_of_last_incoming_frame_ms_ = TickTime::MillisecondTimestamp();
554     if (default_rtp_rtcp_->SendingMedia() == false) {
555       // We've paused or we have no channels attached, don't encode.
556       return;
557     }
558     if (EncoderPaused()) {
559       if (!encoder_paused_and_dropped_frame_) {
560         TRACE_EVENT_ASYNC_BEGIN0("webrtc", "EncoderPaused", this);
561       }
562       encoder_paused_and_dropped_frame_ = true;
563       return;
564     }
565     if (encoder_paused_and_dropped_frame_) {
566       TRACE_EVENT_ASYNC_END0("webrtc", "EncoderPaused", this);
567     }
568     encoder_paused_and_dropped_frame_ = false;
569   }
570
571   // Convert render time, in ms, to RTP timestamp.
572   const int kMsToRtpTimestamp = 90;
573   const uint32_t time_stamp =
574       kMsToRtpTimestamp *
575       static_cast<uint32_t>(video_frame->render_time_ms());
576
577   TRACE_EVENT_ASYNC_STEP0("webrtc", "Video", video_frame->render_time_ms(),
578                           "Encode");
579   video_frame->set_timestamp(time_stamp);
580   {
581     CriticalSectionScoped cs(callback_cs_.get());
582     if (effect_filter_) {
583       unsigned int length = CalcBufferSize(kI420,
584                                            video_frame->width(),
585                                            video_frame->height());
586       scoped_array<uint8_t> video_buffer(new uint8_t[length]);
587       ExtractBuffer(*video_frame, length, video_buffer.get());
588       effect_filter_->Transform(length,
589                                 video_buffer.get(),
590                                 video_frame->timestamp(),
591                                 video_frame->width(),
592                                 video_frame->height());
593     }
594   }
595
596   // Make sure the CSRC list is correct.
597   if (num_csrcs > 0) {
598     uint32_t tempCSRC[kRtpCsrcSize];
599     for (int i = 0; i < num_csrcs; i++) {
600       if (CSRC[i] == 1) {
601         tempCSRC[i] = default_rtp_rtcp_->SSRC();
602       } else {
603         tempCSRC[i] = CSRC[i];
604       }
605     }
606     default_rtp_rtcp_->SetCSRCs(tempCSRC, (uint8_t) num_csrcs);
607   }
608   // Pass frame via preprocessor.
609   I420VideoFrame* decimated_frame = NULL;
610   const int ret = vpm_.PreprocessFrame(*video_frame, &decimated_frame);
611   if (ret == 1) {
612     // Drop this frame.
613     return;
614   }
615   if (ret != VPM_OK) {
616     WEBRTC_TRACE(webrtc::kTraceError,
617                  webrtc::kTraceVideo,
618                  ViEId(engine_id_, channel_id_),
619                  "%s: Error preprocessing frame %u", __FUNCTION__,
620                  video_frame->timestamp());
621     return;
622   }
623   // Frame was not sampled => use original.
624   if (decimated_frame == NULL)  {
625     decimated_frame = video_frame;
626   }
627
628   {
629     CriticalSectionScoped cs(callback_cs_.get());
630     if (pre_encode_callback_)
631       pre_encode_callback_->FrameCallback(decimated_frame);
632   }
633
634 #ifdef VIDEOCODEC_VP8
635   if (vcm_.SendCodec() == webrtc::kVideoCodecVP8) {
636     webrtc::CodecSpecificInfo codec_specific_info;
637     codec_specific_info.codecType = webrtc::kVideoCodecVP8;
638     codec_specific_info.codecSpecific.VP8.hasReceivedRPSI =
639         has_received_rpsi_;
640     codec_specific_info.codecSpecific.VP8.hasReceivedSLI =
641         has_received_sli_;
642     codec_specific_info.codecSpecific.VP8.pictureIdRPSI =
643         picture_id_rpsi_;
644     codec_specific_info.codecSpecific.VP8.pictureIdSLI  =
645         picture_id_sli_;
646     has_received_sli_ = false;
647     has_received_rpsi_ = false;
648
649     if (vcm_.AddVideoFrame(*decimated_frame,
650                            vpm_.ContentMetrics(),
651                            &codec_specific_info) != VCM_OK) {
652       WEBRTC_TRACE(webrtc::kTraceError,
653                    webrtc::kTraceVideo,
654                    ViEId(engine_id_, channel_id_),
655                    "%s: Error encoding frame %u", __FUNCTION__,
656                    video_frame->timestamp());
657     }
658     return;
659   }
660 #endif
661   if (vcm_.AddVideoFrame(*decimated_frame) != VCM_OK) {
662     WEBRTC_TRACE(webrtc::kTraceError,
663                  webrtc::kTraceVideo,
664                  ViEId(engine_id_, channel_id_),
665                  "%s: Error encoding frame %u", __FUNCTION__,
666                  video_frame->timestamp());
667   }
668 }
669
670 void ViEEncoder::DelayChanged(int id, int frame_delay) {
671   WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceVideo,
672                ViEId(engine_id_, channel_id_), "%s: %u", __FUNCTION__,
673                frame_delay);
674
675   default_rtp_rtcp_->SetCameraDelay(frame_delay);
676 }
677
678 int ViEEncoder::GetPreferedFrameSettings(int* width,
679                                          int* height,
680                                          int* frame_rate) {
681   WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
682                ViEId(engine_id_, channel_id_), "%s", __FUNCTION__);
683
684   webrtc::VideoCodec video_codec;
685   memset(&video_codec, 0, sizeof(video_codec));
686   if (vcm_.SendCodec(&video_codec) != VCM_OK) {
687     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
688                  ViEId(engine_id_, channel_id_),
689                  "Could not get VCM send codec");
690     return -1;
691   }
692
693   *width = video_codec.width;
694   *height = video_codec.height;
695   *frame_rate = video_codec.maxFramerate;
696   return 0;
697 }
698
699 int ViEEncoder::SendKeyFrame() {
700   WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
701                ViEId(engine_id_, channel_id_), "%s", __FUNCTION__);
702   return vcm_.IntraFrameRequest(0);
703 }
704
705 int32_t ViEEncoder::SendCodecStatistics(
706     uint32_t* num_key_frames, uint32_t* num_delta_frames) {
707   WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
708                ViEId(engine_id_, channel_id_), "%s", __FUNCTION__);
709
710   webrtc::VCMFrameCount sent_frames;
711   if (vcm_.SentFrameCount(sent_frames) != VCM_OK) {
712     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
713                  ViEId(engine_id_, channel_id_),
714                  "%s: Could not get sent frame information", __FUNCTION__);
715     return -1;
716   }
717   *num_key_frames = sent_frames.numKeyFrames;
718   *num_delta_frames = sent_frames.numDeltaFrames;
719   return 0;
720 }
721
722 int32_t ViEEncoder::EstimatedSendBandwidth(
723     uint32_t* available_bandwidth) const {
724   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
725                __FUNCTION__);
726
727   if (!bitrate_controller_->AvailableBandwidth(available_bandwidth)) {
728     return -1;
729   }
730   return 0;
731 }
732
733 int ViEEncoder::CodecTargetBitrate(uint32_t* bitrate) const {
734   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
735                __FUNCTION__);
736   if (vcm_.Bitrate(bitrate) != 0)
737     return -1;
738   return 0;
739 }
740
741 int32_t ViEEncoder::UpdateProtectionMethod(bool enable_nack) {
742   bool fec_enabled = false;
743   uint8_t dummy_ptype_red = 0;
744   uint8_t dummy_ptypeFEC = 0;
745
746   // Updated protection method to VCM to get correct packetization sizes.
747   // FEC has larger overhead than NACK -> set FEC if used.
748   int32_t error = default_rtp_rtcp_->GenericFECStatus(fec_enabled,
749                                                       dummy_ptype_red,
750                                                       dummy_ptypeFEC);
751   if (error) {
752     return -1;
753   }
754   if (fec_enabled_ == fec_enabled && nack_enabled_ == enable_nack) {
755     // No change needed, we're already in correct state.
756     return 0;
757   }
758   fec_enabled_ = fec_enabled;
759   nack_enabled_ = enable_nack;
760
761   // Set Video Protection for VCM.
762   if (fec_enabled && nack_enabled_) {
763     vcm_.SetVideoProtection(webrtc::kProtectionNackFEC, true);
764   } else {
765     vcm_.SetVideoProtection(webrtc::kProtectionFEC, fec_enabled_);
766     vcm_.SetVideoProtection(webrtc::kProtectionNackSender, nack_enabled_);
767     vcm_.SetVideoProtection(webrtc::kProtectionNackFEC, false);
768   }
769
770   if (fec_enabled_ || nack_enabled_) {
771     WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
772                  ViEId(engine_id_, channel_id_), "%s: FEC status ",
773                  __FUNCTION__, fec_enabled);
774     vcm_.RegisterProtectionCallback(this);
775     // The send codec must be registered to set correct MTU.
776     webrtc::VideoCodec codec;
777     if (vcm_.SendCodec(&codec) == 0) {
778       uint16_t max_pay_load = default_rtp_rtcp_->MaxDataPayloadLength();
779       uint32_t current_bitrate_bps = 0;
780       if (vcm_.Bitrate(&current_bitrate_bps) != 0) {
781         WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideo,
782                      ViEId(engine_id_, channel_id_),
783                      "Failed to get the current encoder target bitrate.");
784       }
785       // Convert to start bitrate in kbps.
786       codec.startBitrate = (current_bitrate_bps + 500) / 1000;
787       if (vcm_.RegisterSendCodec(&codec, number_of_cores_, max_pay_load) != 0) {
788         WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
789                      ViEId(engine_id_, channel_id_),
790                      "%s: Failed to update Sendcodec when enabling FEC",
791                      __FUNCTION__, fec_enabled);
792         return -1;
793       }
794     }
795     return 0;
796   } else {
797     // FEC and NACK are disabled.
798     vcm_.RegisterProtectionCallback(NULL);
799   }
800   return 0;
801 }
802
803 void ViEEncoder::SetSenderBufferingMode(int target_delay_ms) {
804   {
805     CriticalSectionScoped cs(data_cs_.get());
806     target_delay_ms_ = target_delay_ms;
807   }
808   if (target_delay_ms > 0) {
809     // Disable external frame-droppers.
810     vcm_.EnableFrameDropper(false);
811     vpm_.EnableTemporalDecimation(false);
812     // We don't put any limits on the pacer queue when running in buffered mode
813     // since the encoder will be paused if the queue grow too large.
814     paced_sender_->set_max_queue_length_ms(-1);
815   } else {
816     // Real-time mode - enable frame droppers.
817     vpm_.EnableTemporalDecimation(true);
818     vcm_.EnableFrameDropper(true);
819     paced_sender_->set_max_queue_length_ms(
820         PacedSender::kDefaultMaxQueueLengthMs);
821   }
822 }
823
824 int32_t ViEEncoder::SendData(
825     const FrameType frame_type,
826     const uint8_t payload_type,
827     const uint32_t time_stamp,
828     int64_t capture_time_ms,
829     const uint8_t* payload_data,
830     const uint32_t payload_size,
831     const webrtc::RTPFragmentationHeader& fragmentation_header,
832     const RTPVideoHeader* rtp_video_hdr) {
833   // New encoded data, hand over to the rtp module.
834   return default_rtp_rtcp_->SendOutgoingData(frame_type,
835                                              payload_type,
836                                              time_stamp,
837                                              capture_time_ms,
838                                              payload_data,
839                                              payload_size,
840                                              &fragmentation_header,
841                                              rtp_video_hdr);
842 }
843
844 int32_t ViEEncoder::ProtectionRequest(
845     const FecProtectionParams* delta_fec_params,
846     const FecProtectionParams* key_fec_params,
847     uint32_t* sent_video_rate_bps,
848     uint32_t* sent_nack_rate_bps,
849     uint32_t* sent_fec_rate_bps) {
850   WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceVideo,
851                ViEId(engine_id_, channel_id_),
852                "%s, deltaFECRate: %u, key_fecrate: %u, "
853                "delta_use_uep_protection: %d, key_use_uep_protection: %d, "
854                "delta_max_fec_frames: %d, key_max_fec_frames: %d, "
855                "delta_mask_type: %d, key_mask_type: %d, ",
856                __FUNCTION__,
857                delta_fec_params->fec_rate,
858                key_fec_params->fec_rate,
859                delta_fec_params->use_uep_protection,
860                key_fec_params->use_uep_protection,
861                delta_fec_params->max_fec_frames,
862                key_fec_params->max_fec_frames,
863                delta_fec_params->fec_mask_type,
864                key_fec_params->fec_mask_type);
865   if (default_rtp_rtcp_->SetFecParameters(delta_fec_params,
866                                          key_fec_params) != 0) {
867     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
868                  ViEId(engine_id_, channel_id_),
869                  "%s: Could not update FEC parameters", __FUNCTION__);
870   }
871   default_rtp_rtcp_->BitrateSent(NULL,
872                                 sent_video_rate_bps,
873                                 sent_fec_rate_bps,
874                                 sent_nack_rate_bps);
875   return 0;
876 }
877
878 int32_t ViEEncoder::SendStatistics(const uint32_t bit_rate,
879                                    const uint32_t frame_rate) {
880   CriticalSectionScoped cs(callback_cs_.get());
881   if (codec_observer_) {
882     WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
883                  ViEId(engine_id_, channel_id_), "%s: bitrate %u, framerate %u",
884                  __FUNCTION__, bit_rate, frame_rate);
885     codec_observer_->OutgoingRate(channel_id_, frame_rate, bit_rate);
886   }
887   return 0;
888 }
889
890 int32_t ViEEncoder::RegisterCodecObserver(ViEEncoderObserver* observer) {
891   CriticalSectionScoped cs(callback_cs_.get());
892   if (observer) {
893     WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
894                  ViEId(engine_id_, channel_id_), "%s: observer added",
895                  __FUNCTION__);
896     if (codec_observer_) {
897       WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
898                    ViEId(engine_id_, channel_id_), "%s: observer already set.",
899                    __FUNCTION__);
900       return -1;
901     }
902     codec_observer_ = observer;
903   } else {
904     if (codec_observer_ == NULL) {
905       WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
906                    ViEId(engine_id_, channel_id_),
907                    "%s: observer does not exist.", __FUNCTION__);
908       return -1;
909     }
910     WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
911                  ViEId(engine_id_, channel_id_), "%s: observer removed",
912                  __FUNCTION__);
913     codec_observer_ = NULL;
914   }
915   return 0;
916 }
917
918 void ViEEncoder::OnReceivedSLI(uint32_t /*ssrc*/,
919                                uint8_t picture_id) {
920   picture_id_sli_ = picture_id;
921   has_received_sli_ = true;
922 }
923
924 void ViEEncoder::OnReceivedRPSI(uint32_t /*ssrc*/,
925                                 uint64_t picture_id) {
926   picture_id_rpsi_ = picture_id;
927   has_received_rpsi_ = true;
928 }
929
930 void ViEEncoder::OnReceivedIntraFrameRequest(uint32_t ssrc) {
931   // Key frame request from remote side, signal to VCM.
932   WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceVideo,
933                ViEId(engine_id_, channel_id_), "%s", __FUNCTION__);
934   TRACE_EVENT0("webrtc", "OnKeyFrameRequest");
935
936   int idx = 0;
937   {
938     CriticalSectionScoped cs(data_cs_.get());
939     std::map<unsigned int, int>::iterator stream_it = ssrc_streams_.find(ssrc);
940     if (stream_it == ssrc_streams_.end()) {
941       LOG_F(LS_WARNING) << "ssrc not found: " << ssrc << ", map size "
942                         << ssrc_streams_.size();
943       return;
944     }
945     std::map<unsigned int, int64_t>::iterator time_it =
946         time_last_intra_request_ms_.find(ssrc);
947     if (time_it == time_last_intra_request_ms_.end()) {
948       time_last_intra_request_ms_[ssrc] = 0;
949     }
950
951     int64_t now = TickTime::MillisecondTimestamp();
952     if (time_last_intra_request_ms_[ssrc] + kViEMinKeyRequestIntervalMs > now) {
953       WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceVideo,
954                    ViEId(engine_id_, channel_id_),
955                    "%s: Not encoding new intra due to timing", __FUNCTION__);
956       return;
957     }
958     time_last_intra_request_ms_[ssrc] = now;
959     idx = stream_it->second;
960   }
961   // Release the critsect before triggering key frame.
962   vcm_.IntraFrameRequest(idx);
963 }
964
965 void ViEEncoder::OnLocalSsrcChanged(uint32_t old_ssrc, uint32_t new_ssrc) {
966   CriticalSectionScoped cs(data_cs_.get());
967   std::map<unsigned int, int>::iterator it = ssrc_streams_.find(old_ssrc);
968   if (it == ssrc_streams_.end()) {
969     return;
970   }
971
972   ssrc_streams_[new_ssrc] = it->second;
973   ssrc_streams_.erase(it);
974
975   std::map<unsigned int, int64_t>::iterator time_it =
976       time_last_intra_request_ms_.find(old_ssrc);
977   int64_t last_intra_request_ms = 0;
978   if (time_it != time_last_intra_request_ms_.end()) {
979     last_intra_request_ms = time_it->second;
980     time_last_intra_request_ms_.erase(time_it);
981   }
982   time_last_intra_request_ms_[new_ssrc] = last_intra_request_ms;
983 }
984
985 bool ViEEncoder::SetSsrcs(const std::list<unsigned int>& ssrcs) {
986   VideoCodec codec;
987   if (vcm_.SendCodec(&codec) != 0)
988     return false;
989
990   if (codec.numberOfSimulcastStreams > 0 &&
991       ssrcs.size() != codec.numberOfSimulcastStreams) {
992     return false;
993   }
994
995   CriticalSectionScoped cs(data_cs_.get());
996   ssrc_streams_.clear();
997   time_last_intra_request_ms_.clear();
998   int idx = 0;
999   for (std::list<unsigned int>::const_iterator it = ssrcs.begin();
1000        it != ssrcs.end(); ++it, ++idx) {
1001     unsigned int ssrc = *it;
1002     ssrc_streams_[ssrc] = idx;
1003   }
1004   return true;
1005 }
1006
1007 // Called from ViEBitrateObserver.
1008 void ViEEncoder::OnNetworkChanged(const uint32_t bitrate_bps,
1009                                   const uint8_t fraction_lost,
1010                                   const uint32_t round_trip_time_ms) {
1011   WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
1012                ViEId(engine_id_, channel_id_),
1013                "%s(bitrate_bps: %u, fraction_lost: %u, rtt_ms: %u",
1014                __FUNCTION__, bitrate_bps, fraction_lost, round_trip_time_ms);
1015
1016   vcm_.SetChannelParameters(bitrate_bps, fraction_lost, round_trip_time_ms);
1017   bool video_is_suspended = vcm_.VideoSuspended();
1018   int bitrate_kbps = bitrate_bps / 1000;
1019   VideoCodec send_codec;
1020   if (vcm_.SendCodec(&send_codec) != 0) {
1021     return;
1022   }
1023   SimulcastStream* stream_configs = send_codec.simulcastStream;
1024   // Allocate the bandwidth between the streams.
1025   std::vector<uint32_t> stream_bitrates = AllocateStreamBitrates(
1026       bitrate_bps,
1027       stream_configs,
1028       send_codec.numberOfSimulcastStreams);
1029   // Find the max amount of padding we can allow ourselves to send at this
1030   // point, based on which streams are currently active and what our current
1031   // available bandwidth is.
1032   int max_padding_bitrate_kbps = 0;
1033   int pad_up_to_bitrate_kbps = 0;
1034   if (send_codec.numberOfSimulcastStreams == 0) {
1035     max_padding_bitrate_kbps = send_codec.minBitrate;
1036     pad_up_to_bitrate_kbps = send_codec.minBitrate;
1037   } else {
1038     int i = send_codec.numberOfSimulcastStreams - 1;
1039     for (std::vector<uint32_t>::reverse_iterator it = stream_bitrates.rbegin();
1040         it != stream_bitrates.rend(); ++it) {
1041       if (*it > 0) {
1042         max_padding_bitrate_kbps = std::min((*it + 500) / 1000,
1043                                             stream_configs[i].minBitrate);
1044         break;
1045       }
1046       --i;
1047     }
1048     pad_up_to_bitrate_kbps =
1049         stream_configs[send_codec.numberOfSimulcastStreams - 1].minBitrate;
1050     for (int i = 0; i < send_codec.numberOfSimulcastStreams - 1; ++i) {
1051       pad_up_to_bitrate_kbps += stream_configs[i].targetBitrate;
1052     }
1053   }
1054   if (video_is_suspended || send_codec.numberOfSimulcastStreams > 1) {
1055     pad_up_to_bitrate_kbps = std::min(bitrate_kbps, pad_up_to_bitrate_kbps);
1056   } else {
1057     // Disable padding if only sending one stream and video isn't suspended.
1058     pad_up_to_bitrate_kbps = 0;
1059   }
1060
1061   {
1062     // The amount of padding should decay to zero if no frames are being
1063     // captured.
1064     CriticalSectionScoped cs(data_cs_.get());
1065     int64_t now_ms = TickTime::MillisecondTimestamp();
1066     if (now_ms - time_of_last_incoming_frame_ms_ > kStopPaddingThresholdMs)
1067       max_padding_bitrate_kbps = 0;
1068   }
1069
1070   paced_sender_->UpdateBitrate(bitrate_kbps,
1071                                max_padding_bitrate_kbps,
1072                                pad_up_to_bitrate_kbps);
1073   default_rtp_rtcp_->SetTargetSendBitrate(stream_bitrates);
1074   {
1075     CriticalSectionScoped cs(data_cs_.get());
1076     if (video_suspended_ == video_is_suspended)
1077       return;
1078     video_suspended_ = video_is_suspended;
1079   }
1080   // State changed, inform codec observer.
1081   if (codec_observer_) {
1082     WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
1083                  ViEId(engine_id_, channel_id_),
1084                  "%s: video_suspended_ changed to %i",
1085                  __FUNCTION__, video_is_suspended);
1086     codec_observer_->SuspendChange(channel_id_, video_is_suspended);
1087   }
1088 }
1089
1090 PacedSender* ViEEncoder::GetPacedSender() {
1091   return paced_sender_.get();
1092 }
1093
1094 int32_t ViEEncoder::RegisterEffectFilter(ViEEffectFilter* effect_filter) {
1095   CriticalSectionScoped cs(callback_cs_.get());
1096   if (effect_filter == NULL) {
1097     if (effect_filter_ == NULL) {
1098       WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
1099                    ViEId(engine_id_, channel_id_), "%s: no effect filter added",
1100                    __FUNCTION__);
1101       return -1;
1102     }
1103     WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
1104                  ViEId(engine_id_, channel_id_), "%s: deregister effect filter",
1105                  __FUNCTION__);
1106   } else {
1107     WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
1108                  ViEId(engine_id_, channel_id_), "%s: register effect",
1109                  __FUNCTION__);
1110     if (effect_filter_) {
1111       WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
1112                    ViEId(engine_id_, channel_id_),
1113                    "%s: effect filter already added ", __FUNCTION__);
1114       return -1;
1115     }
1116   }
1117   effect_filter_ = effect_filter;
1118   return 0;
1119 }
1120
1121 int ViEEncoder::StartDebugRecording(const char* fileNameUTF8) {
1122   return vcm_.StartDebugRecording(fileNameUTF8);
1123 }
1124
1125 int ViEEncoder::StopDebugRecording() {
1126   return vcm_.StopDebugRecording();
1127 }
1128
1129 void ViEEncoder::SuspendBelowMinBitrate() {
1130   vcm_.SuspendBelowMinBitrate();
1131   bitrate_controller_->EnforceMinBitrate(false);
1132 }
1133
1134 void ViEEncoder::RegisterPreEncodeCallback(
1135     I420FrameCallback* pre_encode_callback) {
1136   CriticalSectionScoped cs(callback_cs_.get());
1137   pre_encode_callback_ = pre_encode_callback;
1138 }
1139
1140 void ViEEncoder::DeRegisterPreEncodeCallback() {
1141   CriticalSectionScoped cs(callback_cs_.get());
1142   pre_encode_callback_ = NULL;
1143 }
1144
1145 void ViEEncoder::RegisterPostEncodeImageCallback(
1146       EncodedImageCallback* post_encode_callback) {
1147   vcm_.RegisterPostEncodeImageCallback(post_encode_callback);
1148 }
1149
1150 void ViEEncoder::DeRegisterPostEncodeImageCallback() {
1151   vcm_.RegisterPostEncodeImageCallback(NULL);
1152 }
1153
1154 QMVideoSettingsCallback::QMVideoSettingsCallback(VideoProcessingModule* vpm)
1155     : vpm_(vpm) {
1156 }
1157
1158 QMVideoSettingsCallback::~QMVideoSettingsCallback() {
1159 }
1160
1161 int32_t QMVideoSettingsCallback::SetVideoQMSettings(
1162     const uint32_t frame_rate,
1163     const uint32_t width,
1164     const uint32_t height) {
1165   return vpm_->SetTargetResolution(width, height, frame_rate);
1166 }
1167
1168 }  // namespace webrtc