Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / video_engine / vie_channel.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_channel.h"
12
13 #include <algorithm>
14 #include <vector>
15
16 #include "webrtc/common.h"
17 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
18 #include "webrtc/experiments.h"
19 #include "webrtc/modules/pacing/include/paced_sender.h"
20 #include "webrtc/modules/rtp_rtcp/interface/rtp_receiver.h"
21 #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h"
22 #include "webrtc/modules/utility/interface/process_thread.h"
23 #include "webrtc/modules/video_coding/main/interface/video_coding.h"
24 #include "webrtc/modules/video_processing/main/interface/video_processing.h"
25 #include "webrtc/modules/video_render/include/video_render_defines.h"
26 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
27 #include "webrtc/system_wrappers/interface/thread_wrapper.h"
28 #include "webrtc/system_wrappers/interface/trace.h"
29 #include "webrtc/video_engine/call_stats.h"
30 #include "webrtc/video_engine/include/vie_codec.h"
31 #include "webrtc/video_engine/include/vie_errors.h"
32 #include "webrtc/video_engine/include/vie_image_process.h"
33 #include "webrtc/video_engine/include/vie_rtp_rtcp.h"
34 #include "webrtc/frame_callback.h"
35 #include "webrtc/video_engine/vie_defines.h"
36
37 namespace webrtc {
38
39 const int kMaxDecodeWaitTimeMs = 50;
40 const int kInvalidRtpExtensionId = 0;
41 static const int kMaxTargetDelayMs = 10000;
42 static const float kMaxIncompleteTimeMultiplier = 3.5f;
43
44 // Helper class receiving statistics callbacks.
45 class ChannelStatsObserver : public CallStatsObserver {
46  public:
47   explicit ChannelStatsObserver(ViEChannel* owner) : owner_(owner) {}
48   virtual ~ChannelStatsObserver() {}
49
50   // Implements StatsObserver.
51   virtual void OnRttUpdate(uint32_t rtt) {
52     owner_->OnRttUpdate(rtt);
53   }
54
55  private:
56   ViEChannel* owner_;
57 };
58
59 ViEChannel::ViEChannel(int32_t channel_id,
60                        int32_t engine_id,
61                        uint32_t number_of_cores,
62                        const Config& config,
63                        ProcessThread& module_process_thread,
64                        RtcpIntraFrameObserver* intra_frame_observer,
65                        RtcpBandwidthObserver* bandwidth_observer,
66                        RemoteBitrateEstimator* remote_bitrate_estimator,
67                        RtcpRttStats* rtt_stats,
68                        PacedSender* paced_sender,
69                        RtpRtcp* default_rtp_rtcp,
70                        bool sender)
71     : ViEFrameProviderBase(channel_id, engine_id),
72       channel_id_(channel_id),
73       engine_id_(engine_id),
74       number_of_cores_(number_of_cores),
75       num_socket_threads_(kViESocketThreads),
76       callback_cs_(CriticalSectionWrapper::CreateCriticalSection()),
77       rtp_rtcp_cs_(CriticalSectionWrapper::CreateCriticalSection()),
78       default_rtp_rtcp_(default_rtp_rtcp),
79       vcm_(*VideoCodingModule::Create(ViEModuleId(engine_id, channel_id))),
80       vie_receiver_(channel_id, &vcm_, remote_bitrate_estimator, this),
81       vie_sender_(channel_id),
82       vie_sync_(&vcm_, this),
83       stats_observer_(new ChannelStatsObserver(this)),
84       module_process_thread_(module_process_thread),
85       codec_observer_(NULL),
86       do_key_frame_callbackRequest_(false),
87       rtp_observer_(NULL),
88       rtcp_observer_(NULL),
89       intra_frame_observer_(intra_frame_observer),
90       rtt_stats_(rtt_stats),
91       paced_sender_(paced_sender),
92       bandwidth_observer_(bandwidth_observer),
93       send_timestamp_extension_id_(kInvalidRtpExtensionId),
94       absolute_send_time_extension_id_(kInvalidRtpExtensionId),
95       external_transport_(NULL),
96       decoder_reset_(true),
97       wait_for_key_frame_(false),
98       decode_thread_(NULL),
99       effect_filter_(NULL),
100       color_enhancement_(false),
101       mtu_(0),
102       sender_(sender),
103       nack_history_size_sender_(kSendSidePacketHistorySize),
104       max_nack_reordering_threshold_(kMaxPacketAgeToNack),
105       pre_render_callback_(NULL),
106       config_(config) {
107   WEBRTC_TRACE(kTraceMemory, kTraceVideo, ViEId(engine_id, channel_id),
108                "ViEChannel::ViEChannel(channel_id: %d, engine_id: %d)",
109                channel_id, engine_id);
110
111   RtpRtcp::Configuration configuration;
112   configuration.id = ViEModuleId(engine_id, channel_id);
113   configuration.audio = false;
114   configuration.default_module = default_rtp_rtcp;
115   configuration.outgoing_transport = &vie_sender_;
116   configuration.rtcp_feedback = this;
117   configuration.intra_frame_callback = intra_frame_observer;
118   configuration.bandwidth_callback = bandwidth_observer;
119   configuration.rtt_stats = rtt_stats;
120   configuration.remote_bitrate_estimator = remote_bitrate_estimator;
121   configuration.paced_sender = paced_sender;
122   configuration.receive_statistics = vie_receiver_.GetReceiveStatistics();
123
124   rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(configuration));
125   vie_receiver_.SetRtpRtcpModule(rtp_rtcp_.get());
126   vcm_.SetNackSettings(kMaxNackListSize, max_nack_reordering_threshold_, 0);
127 }
128
129 int32_t ViEChannel::Init() {
130   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
131                "%s: channel_id: %d, engine_id: %d)", __FUNCTION__, channel_id_,
132                engine_id_);
133
134   if (module_process_thread_.RegisterModule(
135       vie_receiver_.GetReceiveStatistics()) != 0) {
136     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
137                  "%s: Failed to register receive-statistics to process thread",
138                  __FUNCTION__);
139     return -1;
140   }
141   // RTP/RTCP initialization.
142   if (rtp_rtcp_->SetSendingMediaStatus(false) != 0) {
143     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
144                  "%s: RTP::SetSendingMediaStatus failure", __FUNCTION__);
145     return -1;
146   }
147   if (module_process_thread_.RegisterModule(rtp_rtcp_.get()) != 0) {
148     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
149                  "%s: RTP::RegisterModule failure", __FUNCTION__);
150     return -1;
151   }
152   if (rtp_rtcp_->SetKeyFrameRequestMethod(kKeyFrameReqFirRtp) != 0) {
153     WEBRTC_TRACE(kTraceWarning, kTraceVideo, ViEId(engine_id_, channel_id_),
154                  "%s: RTP::SetKeyFrameRequestMethod failure", __FUNCTION__);
155   }
156   if (rtp_rtcp_->SetRTCPStatus(kRtcpCompound) != 0) {
157     WEBRTC_TRACE(kTraceWarning, kTraceVideo, ViEId(engine_id_, channel_id_),
158                  "%s: RTP::SetRTCPStatus failure", __FUNCTION__);
159   }
160   if (paced_sender_) {
161     if (rtp_rtcp_->SetStorePacketsStatus(true, nack_history_size_sender_) !=
162         0) {
163       WEBRTC_TRACE(kTraceWarning, kTraceVideo, ViEId(engine_id_, channel_id_),
164                    "%s:SetStorePacketsStatus failure", __FUNCTION__);
165     }
166   }
167   // VCM initialization
168   if (vcm_.InitializeReceiver() != 0) {
169     WEBRTC_TRACE(kTraceError, kTraceVideo,
170                  ViEId(engine_id_, channel_id_),
171                  "%s: VCM::InitializeReceiver failure", __FUNCTION__);
172     return -1;
173   }
174   if (vcm_.SetVideoProtection(kProtectionKeyOnLoss, true)) {
175     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
176                  "%s: VCM::SetVideoProtection failure", __FUNCTION__);
177     return -1;
178   }
179   if (vcm_.RegisterReceiveCallback(this) != 0) {
180     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
181                  "%s: VCM::RegisterReceiveCallback failure", __FUNCTION__);
182     return -1;
183   }
184   if (vcm_.RegisterFrameTypeCallback(this) != 0) {
185     WEBRTC_TRACE(kTraceWarning, kTraceVideo, ViEId(engine_id_, channel_id_),
186                  "%s: VCM::RegisterFrameTypeCallback failure", __FUNCTION__);
187   }
188   if (vcm_.RegisterReceiveStatisticsCallback(this) != 0) {
189     WEBRTC_TRACE(kTraceWarning, kTraceVideo, ViEId(engine_id_, channel_id_),
190                  "%s: VCM::RegisterReceiveStatisticsCallback failure",
191                  __FUNCTION__);
192   }
193   if (vcm_.RegisterDecoderTimingCallback(this) != 0) {
194     WEBRTC_TRACE(kTraceWarning, kTraceVideo, ViEId(engine_id_, channel_id_),
195                  "%s: VCM::RegisterDecoderTimingCallback failure",
196                  __FUNCTION__);
197   }
198   if (vcm_.SetRenderDelay(kViEDefaultRenderDelayMs) != 0) {
199     WEBRTC_TRACE(kTraceWarning, kTraceVideo, ViEId(engine_id_, channel_id_),
200                  "%s: VCM::SetRenderDelay failure", __FUNCTION__);
201   }
202   if (module_process_thread_.RegisterModule(&vcm_) != 0) {
203     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
204                  "%s: VCM::RegisterModule(vcm) failure", __FUNCTION__);
205     return -1;
206   }
207 #ifdef VIDEOCODEC_VP8
208   VideoCodec video_codec;
209   if (vcm_.Codec(kVideoCodecVP8, &video_codec) == VCM_OK) {
210     rtp_rtcp_->RegisterSendPayload(video_codec);
211     // TODO(holmer): Can we call SetReceiveCodec() here instead?
212     if (!vie_receiver_.RegisterPayload(video_codec)) {
213       return -1;
214     }
215     vcm_.RegisterReceiveCodec(&video_codec, number_of_cores_);
216     vcm_.RegisterSendCodec(&video_codec, number_of_cores_,
217                            rtp_rtcp_->MaxDataPayloadLength());
218   } else {
219     assert(false);
220   }
221 #endif
222
223   return 0;
224 }
225
226 ViEChannel::~ViEChannel() {
227   WEBRTC_TRACE(kTraceMemory, kTraceVideo, ViEId(engine_id_, channel_id_),
228                "ViEChannel Destructor, channel_id: %d, engine_id: %d",
229                channel_id_, engine_id_);
230
231   // Make sure we don't get more callbacks from the RTP module.
232   module_process_thread_.DeRegisterModule(vie_receiver_.GetReceiveStatistics());
233   module_process_thread_.DeRegisterModule(rtp_rtcp_.get());
234   module_process_thread_.DeRegisterModule(&vcm_);
235   module_process_thread_.DeRegisterModule(&vie_sync_);
236   while (simulcast_rtp_rtcp_.size() > 0) {
237     std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
238     RtpRtcp* rtp_rtcp = *it;
239     module_process_thread_.DeRegisterModule(rtp_rtcp);
240     delete rtp_rtcp;
241     simulcast_rtp_rtcp_.erase(it);
242   }
243   while (removed_rtp_rtcp_.size() > 0) {
244     std::list<RtpRtcp*>::iterator it = removed_rtp_rtcp_.begin();
245     delete *it;
246     removed_rtp_rtcp_.erase(it);
247   }
248   if (decode_thread_) {
249     StopDecodeThread();
250   }
251   // Release modules.
252   VideoCodingModule::Destroy(&vcm_);
253 }
254
255 int32_t ViEChannel::SetSendCodec(const VideoCodec& video_codec,
256                                  bool new_stream) {
257   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
258                "%s: codec_type: %d", __FUNCTION__, video_codec.codecType);
259
260   if (!sender_) {
261     return 0;
262   }
263   if (video_codec.codecType == kVideoCodecRED ||
264       video_codec.codecType == kVideoCodecULPFEC) {
265     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
266                  "%s: codec_type: %d is not a valid send codec.", __FUNCTION__,
267                  video_codec.codecType);
268     return -1;
269   }
270   if (kMaxSimulcastStreams < video_codec.numberOfSimulcastStreams) {
271     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
272                  "%s: Too many simulcast streams", __FUNCTION__);
273     return -1;
274   }
275   // Update the RTP module with the settings.
276   // Stop and Start the RTP module -> trigger new SSRC, if an SSRC hasn't been
277   // set explicitly.
278   bool restart_rtp = false;
279   if (rtp_rtcp_->Sending() && new_stream) {
280     restart_rtp = true;
281     rtp_rtcp_->SetSendingStatus(false);
282     for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
283          it != simulcast_rtp_rtcp_.end(); ++it) {
284       (*it)->SetSendingStatus(false);
285       (*it)->SetSendingMediaStatus(false);
286     }
287   }
288
289   bool fec_enabled = false;
290   uint8_t payload_type_red;
291   uint8_t payload_type_fec;
292   rtp_rtcp_->GenericFECStatus(fec_enabled, payload_type_red, payload_type_fec);
293
294   CriticalSectionScoped cs(rtp_rtcp_cs_.get());
295
296   if (video_codec.numberOfSimulcastStreams > 0) {
297     // Set correct bitrate to base layer.
298     // Create our simulcast RTP modules.
299     int num_modules_to_add = video_codec.numberOfSimulcastStreams -
300         simulcast_rtp_rtcp_.size() - 1;
301     if (num_modules_to_add < 0) {
302       num_modules_to_add = 0;
303     }
304
305     while (removed_rtp_rtcp_.size() > 0 && num_modules_to_add > 0) {
306       RtpRtcp* rtp_rtcp = removed_rtp_rtcp_.front();
307       removed_rtp_rtcp_.pop_front();
308       simulcast_rtp_rtcp_.push_back(rtp_rtcp);
309       rtp_rtcp->SetSendingStatus(rtp_rtcp_->Sending());
310       rtp_rtcp->SetSendingMediaStatus(rtp_rtcp_->SendingMedia());
311       module_process_thread_.RegisterModule(rtp_rtcp);
312       --num_modules_to_add;
313     }
314
315     for (int i = 0; i < num_modules_to_add; ++i) {
316       RtpRtcp::Configuration configuration;
317       configuration.id = ViEModuleId(engine_id_, channel_id_);
318       configuration.audio = false;  // Video.
319       configuration.default_module = default_rtp_rtcp_;
320       configuration.outgoing_transport = &vie_sender_;
321       configuration.intra_frame_callback = intra_frame_observer_;
322       configuration.bandwidth_callback = bandwidth_observer_.get();
323       configuration.rtt_stats = rtt_stats_;
324       configuration.paced_sender = paced_sender_;
325
326       RtpRtcp* rtp_rtcp = RtpRtcp::CreateRtpRtcp(configuration);
327
328       // Silently ignore error.
329       module_process_thread_.RegisterModule(rtp_rtcp);
330       if (rtp_rtcp->SetRTCPStatus(rtp_rtcp_->RTCP()) != 0) {
331         WEBRTC_TRACE(kTraceWarning, kTraceVideo, ViEId(engine_id_, channel_id_),
332                      "%s: RTP::SetRTCPStatus failure", __FUNCTION__);
333       }
334
335       if (rtp_rtcp_->StorePackets()) {
336         rtp_rtcp->SetStorePacketsStatus(true, nack_history_size_sender_);
337       } else if (paced_sender_) {
338         rtp_rtcp->SetStorePacketsStatus(true, nack_history_size_sender_);
339       }
340
341       if (fec_enabled) {
342         rtp_rtcp->SetGenericFECStatus(fec_enabled, payload_type_red,
343             payload_type_fec);
344       }
345       rtp_rtcp->SetSendingStatus(rtp_rtcp_->Sending());
346       rtp_rtcp->SetSendingMediaStatus(rtp_rtcp_->SendingMedia());
347       simulcast_rtp_rtcp_.push_back(rtp_rtcp);
348     }
349     // Remove last in list if we have too many.
350     for (int j = simulcast_rtp_rtcp_.size();
351          j > (video_codec.numberOfSimulcastStreams - 1);
352          j--) {
353       RtpRtcp* rtp_rtcp = simulcast_rtp_rtcp_.back();
354       module_process_thread_.DeRegisterModule(rtp_rtcp);
355       rtp_rtcp->SetSendingStatus(false);
356       rtp_rtcp->SetSendingMediaStatus(false);
357       rtp_rtcp->RegisterSendFrameCountObserver(NULL);
358       rtp_rtcp->RegisterSendChannelRtcpStatisticsCallback(NULL);
359       rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(NULL);
360       rtp_rtcp->RegisterVideoBitrateObserver(NULL);
361       simulcast_rtp_rtcp_.pop_back();
362       removed_rtp_rtcp_.push_front(rtp_rtcp);
363     }
364     uint8_t idx = 0;
365     // Configure all simulcast modules.
366     for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
367          it != simulcast_rtp_rtcp_.end();
368          it++) {
369       idx++;
370       RtpRtcp* rtp_rtcp = *it;
371       rtp_rtcp->DeRegisterSendPayload(video_codec.plType);
372       if (rtp_rtcp->RegisterSendPayload(video_codec) != 0) {
373         WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
374                      "%s: could not register payload type", __FUNCTION__);
375         return -1;
376       }
377       if (mtu_ != 0) {
378         rtp_rtcp->SetMaxTransferUnit(mtu_);
379       }
380       if (restart_rtp) {
381         rtp_rtcp->SetSendingStatus(true);
382         rtp_rtcp->SetSendingMediaStatus(true);
383       }
384       if (send_timestamp_extension_id_ != kInvalidRtpExtensionId) {
385         // Deregister in case the extension was previously enabled.
386         rtp_rtcp->DeregisterSendRtpHeaderExtension(
387             kRtpExtensionTransmissionTimeOffset);
388         if (rtp_rtcp->RegisterSendRtpHeaderExtension(
389             kRtpExtensionTransmissionTimeOffset,
390             send_timestamp_extension_id_) != 0) {
391           WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
392                        "%s: could not register transmission time extension",
393                        __FUNCTION__);
394         }
395       } else {
396         rtp_rtcp->DeregisterSendRtpHeaderExtension(
397             kRtpExtensionTransmissionTimeOffset);
398       }
399       if (absolute_send_time_extension_id_ != kInvalidRtpExtensionId) {
400         // Deregister in case the extension was previously enabled.
401         rtp_rtcp->DeregisterSendRtpHeaderExtension(
402             kRtpExtensionAbsoluteSendTime);
403         if (rtp_rtcp->RegisterSendRtpHeaderExtension(
404             kRtpExtensionAbsoluteSendTime,
405             absolute_send_time_extension_id_) != 0) {
406           WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
407                        "%s: could not register absolute send time extension",
408                        __FUNCTION__);
409         }
410       } else {
411         rtp_rtcp->DeregisterSendRtpHeaderExtension(
412             kRtpExtensionAbsoluteSendTime);
413       }
414       rtp_rtcp->RegisterSendFrameCountObserver(
415           rtp_rtcp_->GetSendFrameCountObserver());
416       rtp_rtcp->RegisterSendChannelRtcpStatisticsCallback(
417           rtp_rtcp_->GetSendChannelRtcpStatisticsCallback());
418       rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(
419           rtp_rtcp_->GetSendChannelRtpStatisticsCallback());
420       rtp_rtcp->RegisterVideoBitrateObserver(
421           rtp_rtcp_->GetVideoBitrateObserver());
422     }
423     // |RegisterSimulcastRtpRtcpModules| resets all old weak pointers and old
424     // modules can be deleted after this step.
425     vie_receiver_.RegisterSimulcastRtpRtcpModules(simulcast_rtp_rtcp_);
426   } else {
427     while (!simulcast_rtp_rtcp_.empty()) {
428       RtpRtcp* rtp_rtcp = simulcast_rtp_rtcp_.back();
429       module_process_thread_.DeRegisterModule(rtp_rtcp);
430       rtp_rtcp->SetSendingStatus(false);
431       rtp_rtcp->SetSendingMediaStatus(false);
432       rtp_rtcp->RegisterSendFrameCountObserver(NULL);
433       rtp_rtcp->RegisterSendChannelRtcpStatisticsCallback(NULL);
434       rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(NULL);
435       rtp_rtcp->RegisterVideoBitrateObserver(NULL);
436       simulcast_rtp_rtcp_.pop_back();
437       removed_rtp_rtcp_.push_front(rtp_rtcp);
438     }
439     // Clear any previous modules.
440     vie_receiver_.RegisterSimulcastRtpRtcpModules(simulcast_rtp_rtcp_);
441   }
442   // Enable this if H264 is available.
443   // This sets the wanted packetization mode.
444   // if (video_codec.plType == kVideoCodecH264) {
445   //   if (video_codec.codecSpecific.H264.packetization ==  kH264SingleMode) {
446   //     rtp_rtcp_->SetH264PacketizationMode(H264_SINGLE_NAL_MODE);
447   //   } else {
448   //     rtp_rtcp_->SetH264PacketizationMode(H264_NON_INTERLEAVED_MODE);
449   //   }
450   //   if (video_codec.codecSpecific.H264.configParametersSize > 0) {
451   //     rtp_rtcp_->SetH264SendModeNALU_PPS_SPS(true);
452   //   }
453   // }
454
455   // Don't log this error, no way to check in advance if this pl_type is
456   // registered or not...
457   rtp_rtcp_->DeRegisterSendPayload(video_codec.plType);
458   if (rtp_rtcp_->RegisterSendPayload(video_codec) != 0) {
459     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
460                  "%s: could not register payload type", __FUNCTION__);
461     return -1;
462   }
463   if (restart_rtp) {
464     rtp_rtcp_->SetSendingStatus(true);
465     for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
466          it != simulcast_rtp_rtcp_.end(); ++it) {
467       (*it)->SetSendingStatus(true);
468       (*it)->SetSendingMediaStatus(true);
469     }
470   }
471   return 0;
472 }
473
474 int32_t ViEChannel::SetReceiveCodec(const VideoCodec& video_codec) {
475   // We will not receive simulcast streams, so no need to handle that use case.
476   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
477                "%s", __FUNCTION__);
478
479   if (!vie_receiver_.SetReceiveCodec(video_codec)) {
480     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
481                  "%s: Could not register receive payload type", __FUNCTION__);
482     return -1;
483   }
484
485   if (video_codec.codecType != kVideoCodecRED &&
486       video_codec.codecType != kVideoCodecULPFEC) {
487     // Register codec type with VCM, but do not register RED or ULPFEC.
488     if (vcm_.RegisterReceiveCodec(&video_codec, number_of_cores_,
489                                   wait_for_key_frame_) != VCM_OK) {
490       WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
491                    "%s: Could not register decoder", __FUNCTION__);
492       return -1;
493     }
494   }
495   return 0;
496 }
497
498 int32_t ViEChannel::GetReceiveCodec(VideoCodec* video_codec) {
499   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
500                "%s", __FUNCTION__);
501
502   if (vcm_.ReceiveCodec(video_codec) != 0) {
503     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
504                  "%s: Could not get receive codec", __FUNCTION__);
505     return -1;
506   }
507   return 0;
508 }
509
510 int32_t ViEChannel::RegisterCodecObserver(ViEDecoderObserver* observer) {
511   CriticalSectionScoped cs(callback_cs_.get());
512   if (observer) {
513     if (codec_observer_) {
514       WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
515                    "%s: already added", __FUNCTION__);
516       return -1;
517     }
518     WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
519                  "%s: observer added", __FUNCTION__);
520     codec_observer_ = observer;
521   } else {
522     if (!codec_observer_) {
523       WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
524                    "%s: no observer added", __FUNCTION__);
525       return -1;
526     }
527     WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
528                  "%s: observer removed", __FUNCTION__);
529     codec_observer_ = NULL;
530   }
531   return 0;
532 }
533
534 int32_t ViEChannel::RegisterExternalDecoder(const uint8_t pl_type,
535                                             VideoDecoder* decoder,
536                                             bool buffered_rendering,
537                                             int32_t render_delay) {
538   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
539                "%s", __FUNCTION__);
540
541   int32_t result;
542   result = vcm_.RegisterExternalDecoder(decoder, pl_type, buffered_rendering);
543   if (result != VCM_OK) {
544     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
545                  "%s: Could not register external decoder with VCM.",
546                  __FUNCTION__);
547     return result;
548   }
549   return vcm_.SetRenderDelay(render_delay);
550 }
551
552 int32_t ViEChannel::DeRegisterExternalDecoder(
553     const uint8_t pl_type) {
554   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
555                "%s pl_type", __FUNCTION__, pl_type);
556
557   VideoCodec current_receive_codec;
558   int32_t result = 0;
559   result = vcm_.ReceiveCodec(&current_receive_codec);
560   if (vcm_.RegisterExternalDecoder(NULL, pl_type, false) != VCM_OK) {
561     return -1;
562   }
563
564   if (result == 0 && current_receive_codec.plType == pl_type) {
565     result = vcm_.RegisterReceiveCodec(&current_receive_codec, number_of_cores_,
566                                        wait_for_key_frame_);
567   }
568   return result;
569 }
570
571 int32_t ViEChannel::ReceiveCodecStatistics(
572     uint32_t* num_key_frames, uint32_t* num_delta_frames) {
573   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
574                "%s", __FUNCTION__);
575
576   VCMFrameCount received_frames;
577   if (vcm_.ReceivedFrameCount(received_frames) != VCM_OK) {
578     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
579                  "%s: Could not get received frame information", __FUNCTION__);
580     return -1;
581   }
582   *num_key_frames = received_frames.numKeyFrames;
583   *num_delta_frames = received_frames.numDeltaFrames;
584   return 0;
585 }
586
587 uint32_t ViEChannel::DiscardedPackets() const {
588   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
589                __FUNCTION__);
590   return vcm_.DiscardedPackets();
591 }
592
593 int ViEChannel::ReceiveDelay() const {
594   return vcm_.Delay();
595 }
596
597 int32_t ViEChannel::WaitForKeyFrame(bool wait) {
598   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
599                "%s(wait: %d)", __FUNCTION__, wait);
600   wait_for_key_frame_ = wait;
601   return 0;
602 }
603
604 int32_t ViEChannel::SetSignalPacketLossStatus(bool enable,
605                                               bool only_key_frames) {
606   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
607                "%s(enable: %d)", __FUNCTION__, enable);
608   if (enable) {
609     if (only_key_frames) {
610       vcm_.SetVideoProtection(kProtectionKeyOnLoss, false);
611       if (vcm_.SetVideoProtection(kProtectionKeyOnKeyLoss, true) != VCM_OK) {
612         WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
613                      "%s failed %d", __FUNCTION__, enable);
614         return -1;
615       }
616     } else {
617       vcm_.SetVideoProtection(kProtectionKeyOnKeyLoss, false);
618       if (vcm_.SetVideoProtection(kProtectionKeyOnLoss, true) != VCM_OK) {
619         WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
620                      "%s failed %d", __FUNCTION__, enable);
621         return -1;
622       }
623     }
624   } else {
625     vcm_.SetVideoProtection(kProtectionKeyOnLoss, false);
626     vcm_.SetVideoProtection(kProtectionKeyOnKeyLoss, false);
627   }
628   return 0;
629 }
630
631 int32_t ViEChannel::SetRTCPMode(const RTCPMethod rtcp_mode) {
632   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
633                "%s: %d", __FUNCTION__, rtcp_mode);
634
635   CriticalSectionScoped cs(rtp_rtcp_cs_.get());
636   for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
637        it != simulcast_rtp_rtcp_.end();
638        it++) {
639     RtpRtcp* rtp_rtcp = *it;
640     rtp_rtcp->SetRTCPStatus(rtcp_mode);
641   }
642   return rtp_rtcp_->SetRTCPStatus(rtcp_mode);
643 }
644
645 int32_t ViEChannel::GetRTCPMode(RTCPMethod* rtcp_mode) {
646   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
647                "%s", __FUNCTION__);
648   *rtcp_mode = rtp_rtcp_->RTCP();
649   return 0;
650 }
651
652 int32_t ViEChannel::SetNACKStatus(const bool enable) {
653   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
654                "%s(enable: %d)", __FUNCTION__, enable);
655
656   // Update the decoding VCM.
657   if (vcm_.SetVideoProtection(kProtectionNack, enable) != VCM_OK) {
658     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
659                  "%s: Could not set VCM NACK protection: %d", __FUNCTION__,
660                  enable);
661     return -1;
662   }
663   if (enable) {
664     // Disable possible FEC.
665     SetFECStatus(false, 0, 0);
666   }
667   // Update the decoding VCM.
668   if (vcm_.SetVideoProtection(kProtectionNack, enable) != VCM_OK) {
669     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
670                  "%s: Could not set VCM NACK protection: %d", __FUNCTION__,
671                  enable);
672     return -1;
673   }
674   return ProcessNACKRequest(enable);
675 }
676
677 int32_t ViEChannel::ProcessNACKRequest(const bool enable) {
678   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
679                "%s(enable: %d)", __FUNCTION__, enable);
680
681   if (enable) {
682     // Turn on NACK.
683     NACKMethod nackMethod = kNackRtcp;
684     if (rtp_rtcp_->RTCP() == kRtcpOff) {
685       WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
686                    "%s: Could not enable NACK, RTPC not on ", __FUNCTION__);
687       return -1;
688     }
689     vie_receiver_.SetNackStatus(true, max_nack_reordering_threshold_);
690     WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
691                  "%s: Using NACK method %d", __FUNCTION__, nackMethod);
692     rtp_rtcp_->SetStorePacketsStatus(true, nack_history_size_sender_);
693
694     vcm_.RegisterPacketRequestCallback(this);
695
696     CriticalSectionScoped cs(rtp_rtcp_cs_.get());
697
698     for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
699          it != simulcast_rtp_rtcp_.end();
700          it++) {
701       RtpRtcp* rtp_rtcp = *it;
702       rtp_rtcp->SetStorePacketsStatus(true, nack_history_size_sender_);
703     }
704     // Don't introduce errors when NACK is enabled.
705     vcm_.SetDecodeErrorMode(kNoErrors);
706   } else {
707     CriticalSectionScoped cs(rtp_rtcp_cs_.get());
708     for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
709          it != simulcast_rtp_rtcp_.end();
710          it++) {
711       RtpRtcp* rtp_rtcp = *it;
712       if (paced_sender_ == NULL) {
713         rtp_rtcp->SetStorePacketsStatus(false, 0);
714       }
715     }
716     vcm_.RegisterPacketRequestCallback(NULL);
717     if (paced_sender_ == NULL) {
718       rtp_rtcp_->SetStorePacketsStatus(false, 0);
719     }
720     vie_receiver_.SetNackStatus(false, max_nack_reordering_threshold_);
721     // When NACK is off, allow decoding with errors. Otherwise, the video
722     // will freeze, and will only recover with a complete key frame.
723     vcm_.SetDecodeErrorMode(kWithErrors);
724   }
725   return 0;
726 }
727
728 int32_t ViEChannel::SetFECStatus(const bool enable,
729                                        const unsigned char payload_typeRED,
730                                        const unsigned char payload_typeFEC) {
731   // Disable possible NACK.
732   if (enable) {
733     SetNACKStatus(false);
734   }
735
736   return ProcessFECRequest(enable, payload_typeRED, payload_typeFEC);
737 }
738
739 int32_t ViEChannel::ProcessFECRequest(
740     const bool enable,
741     const unsigned char payload_typeRED,
742     const unsigned char payload_typeFEC) {
743   WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(engine_id_, channel_id_),
744                "%s(enable: %d, payload_typeRED: %u, payload_typeFEC: %u)",
745                __FUNCTION__, enable, payload_typeRED, payload_typeFEC);
746
747   if (rtp_rtcp_->SetGenericFECStatus(enable, payload_typeRED,
748                                     payload_typeFEC) != 0) {
749     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
750                  "%s: Could not change FEC status to %d", __FUNCTION__,
751                  enable);
752     return -1;
753   }
754   CriticalSectionScoped cs(rtp_rtcp_cs_.get());
755   for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
756        it != simulcast_rtp_rtcp_.end();
757        it++) {
758     RtpRtcp* rtp_rtcp = *it;
759     rtp_rtcp->SetGenericFECStatus(enable, payload_typeRED, payload_typeFEC);
760   }
761   return 0;
762 }
763
764 int32_t ViEChannel::SetHybridNACKFECStatus(
765     const bool enable,
766     const unsigned char payload_typeRED,
767     const unsigned char payload_typeFEC) {
768   // Update the decoding VCM with hybrid mode.
769   if (vcm_.SetVideoProtection(kProtectionNackFEC, enable) != VCM_OK) {
770     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
771                  "%s: Could not set VCM NACK protection: %d", __FUNCTION__,
772                  enable);
773     return -1;
774   }
775
776   int32_t ret_val = 0;
777   ret_val = ProcessNACKRequest(enable);
778   if (ret_val < 0) {
779     return ret_val;
780   }
781   return ProcessFECRequest(enable, payload_typeRED, payload_typeFEC);
782 }
783
784 int ViEChannel::SetSenderBufferingMode(int target_delay_ms) {
785   if ((target_delay_ms < 0) || (target_delay_ms > kMaxTargetDelayMs)) {
786     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
787                  "%s: Target sender buffering delay out of bounds: %d",
788                  __FUNCTION__, target_delay_ms);
789     return -1;
790   }
791   if (target_delay_ms == 0) {
792     // Real-time mode.
793     nack_history_size_sender_ = kSendSidePacketHistorySize;
794   } else {
795     nack_history_size_sender_ = GetRequiredNackListSize(target_delay_ms);
796     // Don't allow a number lower than the default value.
797     if (nack_history_size_sender_ < kSendSidePacketHistorySize) {
798       nack_history_size_sender_ = kSendSidePacketHistorySize;
799     }
800   }
801   // Setting nack_history_size_.
802   // First disabling (forcing free) and then resetting to desired value.
803   if (rtp_rtcp_->SetStorePacketsStatus(false, 0) != 0) {
804     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
805                  "%s:SetStorePacketsStatus failure", __FUNCTION__);
806     return -1;
807   }
808   if (rtp_rtcp_->SetStorePacketsStatus(true, nack_history_size_sender_) != 0) {
809     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
810                  "%s:SetStorePacketsStatus failure", __FUNCTION__);
811     return -1;
812   }
813   return 0;
814 }
815
816 int ViEChannel::SetReceiverBufferingMode(int target_delay_ms) {
817   if ((target_delay_ms < 0) || (target_delay_ms > kMaxTargetDelayMs)) {
818     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
819                  "%s: Target receiver buffering delay out of bounds: %d",
820                  __FUNCTION__, target_delay_ms);
821     return -1;
822   }
823   int max_nack_list_size;
824   int max_incomplete_time_ms;
825   if (target_delay_ms == 0) {
826     // Real-time mode - restore default settings.
827     max_nack_reordering_threshold_ = kMaxPacketAgeToNack;
828     max_nack_list_size = kMaxNackListSize;
829     max_incomplete_time_ms = 0;
830   } else {
831     max_nack_list_size =  3 * GetRequiredNackListSize(target_delay_ms) / 4;
832     max_nack_reordering_threshold_ = max_nack_list_size;
833     // Calculate the max incomplete time and round to int.
834     max_incomplete_time_ms = static_cast<int>(kMaxIncompleteTimeMultiplier *
835         target_delay_ms + 0.5f);
836   }
837   vcm_.SetNackSettings(max_nack_list_size, max_nack_reordering_threshold_,
838                        max_incomplete_time_ms);
839   vcm_.SetMinReceiverDelay(target_delay_ms);
840   if (vie_sync_.SetTargetBufferingDelay(target_delay_ms) < 0)
841     return -1;
842   return 0;
843 }
844
845 int ViEChannel::GetRequiredNackListSize(int target_delay_ms) {
846   // The max size of the nack list should be large enough to accommodate the
847   // the number of packets (frames) resulting from the increased delay.
848   // Roughly estimating for ~40 packets per frame @ 30fps.
849   return target_delay_ms * 40 * 30 / 1000;
850 }
851
852 int32_t ViEChannel::SetKeyFrameRequestMethod(
853     const KeyFrameRequestMethod method) {
854   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
855                "%s: %d", __FUNCTION__, method);
856   return rtp_rtcp_->SetKeyFrameRequestMethod(method);
857 }
858
859 bool ViEChannel::EnableRemb(bool enable) {
860   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
861                "ViEChannel::EnableRemb: %d", enable);
862   if (rtp_rtcp_->SetREMBStatus(enable) != 0)
863     return false;
864   return true;
865 }
866
867 int ViEChannel::SetSendTimestampOffsetStatus(bool enable, int id) {
868   CriticalSectionScoped cs(rtp_rtcp_cs_.get());
869   int error = 0;
870   if (enable) {
871     // Enable the extension, but disable possible old id to avoid errors.
872     send_timestamp_extension_id_ = id;
873     rtp_rtcp_->DeregisterSendRtpHeaderExtension(
874         kRtpExtensionTransmissionTimeOffset);
875     error = rtp_rtcp_->RegisterSendRtpHeaderExtension(
876         kRtpExtensionTransmissionTimeOffset, id);
877     for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
878          it != simulcast_rtp_rtcp_.end(); it++) {
879       (*it)->DeregisterSendRtpHeaderExtension(
880           kRtpExtensionTransmissionTimeOffset);
881       error |= (*it)->RegisterSendRtpHeaderExtension(
882           kRtpExtensionTransmissionTimeOffset, id);
883     }
884   } else {
885     // Disable the extension.
886     send_timestamp_extension_id_ = kInvalidRtpExtensionId;
887     rtp_rtcp_->DeregisterSendRtpHeaderExtension(
888         kRtpExtensionTransmissionTimeOffset);
889     for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
890          it != simulcast_rtp_rtcp_.end(); it++) {
891       (*it)->DeregisterSendRtpHeaderExtension(
892           kRtpExtensionTransmissionTimeOffset);
893     }
894   }
895   return error;
896 }
897
898 int ViEChannel::SetReceiveTimestampOffsetStatus(bool enable, int id) {
899   return vie_receiver_.SetReceiveTimestampOffsetStatus(enable, id) ? 0 : -1;
900 }
901
902 int ViEChannel::SetSendAbsoluteSendTimeStatus(bool enable, int id) {
903   CriticalSectionScoped cs(rtp_rtcp_cs_.get());
904   int error = 0;
905   if (enable) {
906     // Enable the extension, but disable possible old id to avoid errors.
907     absolute_send_time_extension_id_ = id;
908     rtp_rtcp_->DeregisterSendRtpHeaderExtension(
909         kRtpExtensionAbsoluteSendTime);
910     error = rtp_rtcp_->RegisterSendRtpHeaderExtension(
911         kRtpExtensionAbsoluteSendTime, id);
912     for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
913          it != simulcast_rtp_rtcp_.end(); it++) {
914       (*it)->DeregisterSendRtpHeaderExtension(
915           kRtpExtensionAbsoluteSendTime);
916       error |= (*it)->RegisterSendRtpHeaderExtension(
917           kRtpExtensionAbsoluteSendTime, id);
918     }
919   } else {
920     // Disable the extension.
921     absolute_send_time_extension_id_ = kInvalidRtpExtensionId;
922     rtp_rtcp_->DeregisterSendRtpHeaderExtension(
923         kRtpExtensionAbsoluteSendTime);
924     for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
925          it != simulcast_rtp_rtcp_.end(); it++) {
926       (*it)->DeregisterSendRtpHeaderExtension(
927           kRtpExtensionAbsoluteSendTime);
928     }
929   }
930   return error;
931 }
932
933 int ViEChannel::SetReceiveAbsoluteSendTimeStatus(bool enable, int id) {
934   return vie_receiver_.SetReceiveAbsoluteSendTimeStatus(enable, id) ? 0 : -1;
935 }
936
937 void ViEChannel::SetRtcpXrRrtrStatus(bool enable) {
938   CriticalSectionScoped cs(rtp_rtcp_cs_.get());
939   rtp_rtcp_->SetRtcpXrRrtrStatus(enable);
940 }
941
942 void ViEChannel::SetTransmissionSmoothingStatus(bool enable) {
943   assert(paced_sender_ && "No paced sender registered.");
944   paced_sender_->SetStatus(enable);
945 }
946
947 int32_t ViEChannel::EnableTMMBR(const bool enable) {
948   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
949                "%s: %d", __FUNCTION__, enable);
950   return rtp_rtcp_->SetTMMBRStatus(enable);
951 }
952
953 int32_t ViEChannel::EnableKeyFrameRequestCallback(const bool enable) {
954   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
955                "%s: %d", __FUNCTION__, enable);
956
957   CriticalSectionScoped cs(callback_cs_.get());
958   if (enable && !codec_observer_) {
959     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
960                  "%s: No ViECodecObserver set", __FUNCTION__, enable);
961     return -1;
962   }
963   do_key_frame_callbackRequest_ = enable;
964   return 0;
965 }
966
967 int32_t ViEChannel::SetSSRC(const uint32_t SSRC,
968                             const StreamType usage,
969                             const uint8_t simulcast_idx) {
970   WEBRTC_TRACE(webrtc::kTraceInfo,
971                webrtc::kTraceVideo,
972                ViEId(engine_id_, channel_id_),
973                "%s(usage:%d, SSRC: 0x%x, idx:%u)",
974                __FUNCTION__, usage, SSRC, simulcast_idx);
975   int rtx_settings = kRtxRetransmitted;
976   if (config_.Get<PaddingStrategy>().redundant_payloads)
977     rtx_settings |= kRtxRedundantPayloads;
978   if (simulcast_idx == 0) {
979     if (usage == kViEStreamTypeRtx) {
980       return rtp_rtcp_->SetRTXSendStatus(rtx_settings, true, SSRC);
981     }
982     return rtp_rtcp_->SetSSRC(SSRC);
983   }
984   CriticalSectionScoped cs(rtp_rtcp_cs_.get());
985   if (simulcast_idx > simulcast_rtp_rtcp_.size()) {
986       return -1;
987   }
988   std::list<RtpRtcp*>::const_iterator it = simulcast_rtp_rtcp_.begin();
989   for (int i = 1; i < simulcast_idx; ++i, ++it) {
990     if (it ==  simulcast_rtp_rtcp_.end()) {
991       return -1;
992     }
993   }
994   RtpRtcp* rtp_rtcp_module = *it;
995   if (usage == kViEStreamTypeRtx) {
996     return rtp_rtcp_module->SetRTXSendStatus(rtx_settings, true, SSRC);
997   }
998   return rtp_rtcp_module->SetSSRC(SSRC);
999 }
1000
1001 int32_t ViEChannel::SetRemoteSSRCType(const StreamType usage,
1002                                       const uint32_t SSRC) {
1003   WEBRTC_TRACE(webrtc::kTraceInfo,
1004                webrtc::kTraceVideo,
1005                ViEId(engine_id_, channel_id_),
1006                "%s(usage:%d, SSRC: 0x%x)",
1007                __FUNCTION__, usage, SSRC);
1008
1009   vie_receiver_.SetRtxStatus(true, SSRC);
1010   return 0;
1011 }
1012
1013 // TODO(mflodman) Add kViEStreamTypeRtx.
1014 int32_t ViEChannel::GetLocalSSRC(uint8_t idx, unsigned int* ssrc) {
1015   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
1016                "%s", __FUNCTION__);
1017
1018   if (idx == 0) {
1019     *ssrc = rtp_rtcp_->SSRC();
1020     return 0;
1021   }
1022   CriticalSectionScoped cs(rtp_rtcp_cs_.get());
1023   if (idx > simulcast_rtp_rtcp_.size()) {
1024     return -1;
1025   }
1026   std::list<RtpRtcp*>::const_iterator it = simulcast_rtp_rtcp_.begin();
1027   for (int i = 1; i < idx; ++i, ++it) {
1028     if (it ==  simulcast_rtp_rtcp_.end()) {
1029       return -1;
1030     }
1031   }
1032   *ssrc = (*it)->SSRC();
1033   return 0;
1034 }
1035
1036 int32_t ViEChannel::GetRemoteSSRC(uint32_t* ssrc) {
1037   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
1038                __FUNCTION__);
1039
1040   *ssrc = vie_receiver_.GetRemoteSsrc();
1041   return 0;
1042 }
1043
1044 int32_t ViEChannel::GetRemoteCSRC(uint32_t CSRCs[kRtpCsrcSize]) {
1045   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
1046                __FUNCTION__);
1047
1048   uint32_t arrayCSRC[kRtpCsrcSize];
1049   memset(arrayCSRC, 0, sizeof(arrayCSRC));
1050
1051   int num_csrcs = vie_receiver_.GetCsrcs(arrayCSRC);
1052   if (num_csrcs > 0) {
1053     memcpy(CSRCs, arrayCSRC, num_csrcs * sizeof(uint32_t));
1054     for (int idx = 0; idx < num_csrcs; idx++) {
1055       WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
1056                    "\tCSRC[%d] = %lu", idx, CSRCs[idx]);
1057     }
1058   } else {
1059     WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
1060                  "%s: CSRC list is empty", __FUNCTION__);
1061   }
1062   return 0;
1063 }
1064
1065 int ViEChannel::SetRtxSendPayloadType(int payload_type) {
1066   if (rtp_rtcp_->Sending()) {
1067     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1068                "%s: already sending", __FUNCTION__);
1069     return -1;
1070   }
1071   rtp_rtcp_->SetRtxSendPayloadType(payload_type);
1072   CriticalSectionScoped cs(rtp_rtcp_cs_.get());
1073   for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
1074        it != simulcast_rtp_rtcp_.end(); it++) {
1075     (*it)->SetRtxSendPayloadType(payload_type);
1076   }
1077   return 0;
1078 }
1079
1080 void ViEChannel::SetRtxReceivePayloadType(int payload_type) {
1081   vie_receiver_.SetRtxPayloadType(payload_type);
1082 }
1083
1084 int32_t ViEChannel::SetStartSequenceNumber(uint16_t sequence_number) {
1085   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
1086                __FUNCTION__);
1087
1088   if (rtp_rtcp_->Sending()) {
1089     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1090                  "%s: already sending", __FUNCTION__);
1091     return -1;
1092   }
1093   return rtp_rtcp_->SetSequenceNumber(sequence_number);
1094 }
1095
1096 int32_t ViEChannel::SetRTCPCName(const char rtcp_cname[]) {
1097   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
1098                "%s", __FUNCTION__);
1099   if (rtp_rtcp_->Sending()) {
1100     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1101                  "%s: already sending", __FUNCTION__);
1102     return -1;
1103   }
1104   return rtp_rtcp_->SetCNAME(rtcp_cname);
1105 }
1106
1107 int32_t ViEChannel::GetRTCPCName(char rtcp_cname[]) {
1108   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
1109                "%s", __FUNCTION__);
1110   return rtp_rtcp_->CNAME(rtcp_cname);
1111 }
1112
1113 int32_t ViEChannel::GetRemoteRTCPCName(char rtcp_cname[]) {
1114   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
1115                __FUNCTION__);
1116
1117   uint32_t remoteSSRC = vie_receiver_.GetRemoteSsrc();
1118   return rtp_rtcp_->RemoteCNAME(remoteSSRC, rtcp_cname);
1119 }
1120
1121 int32_t ViEChannel::RegisterRtpObserver(ViERTPObserver* observer) {
1122   CriticalSectionScoped cs(callback_cs_.get());
1123   if (observer) {
1124     if (rtp_observer_) {
1125       WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1126                    "%s: observer alread added", __FUNCTION__);
1127       return -1;
1128     }
1129     WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
1130                  "%s: observer added", __FUNCTION__);
1131     rtp_observer_ = observer;
1132   } else {
1133     if (!rtp_observer_) {
1134       WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1135                    "%s: no observer added", __FUNCTION__);
1136       return -1;
1137     }
1138     WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
1139                  "%s: observer removed", __FUNCTION__);
1140     rtp_observer_ = NULL;
1141   }
1142   return 0;
1143 }
1144
1145 int32_t ViEChannel::RegisterRtcpObserver(ViERTCPObserver* observer) {
1146   CriticalSectionScoped cs(callback_cs_.get());
1147   if (observer) {
1148     if (rtcp_observer_) {
1149       WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1150                    "%s: observer alread added", __FUNCTION__);
1151       return -1;
1152     }
1153     WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
1154                  "%s: observer added", __FUNCTION__);
1155     rtcp_observer_ = observer;
1156   } else {
1157     if (!rtcp_observer_) {
1158       WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1159                    "%s: no observer added", __FUNCTION__);
1160       return -1;
1161     }
1162     WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
1163                  "%s: observer removed", __FUNCTION__);
1164     rtcp_observer_ = NULL;
1165   }
1166   return 0;
1167 }
1168
1169 int32_t ViEChannel::SendApplicationDefinedRTCPPacket(
1170     const uint8_t sub_type,
1171     uint32_t name,
1172     const uint8_t* data,
1173     uint16_t data_length_in_bytes) {
1174   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
1175                __FUNCTION__);
1176   if (!rtp_rtcp_->Sending()) {
1177     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1178                  "%s: not sending", __FUNCTION__);
1179     return -1;
1180   }
1181   if (!data) {
1182     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1183                  "%s: no input argument", __FUNCTION__);
1184     return -1;
1185   }
1186   if (data_length_in_bytes % 4 != 0) {
1187     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1188                  "%s: input length error", __FUNCTION__);
1189     return -1;
1190   }
1191   RTCPMethod rtcp_method = rtp_rtcp_->RTCP();
1192   if (rtcp_method == kRtcpOff) {
1193     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1194                  "%s: RTCP not enabled", __FUNCTION__);
1195     return -1;
1196   }
1197   // Create and send packet.
1198   if (rtp_rtcp_->SetRTCPApplicationSpecificData(sub_type, name, data,
1199                                                data_length_in_bytes) != 0) {
1200     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1201                  "%s: Could not send RTCP application data", __FUNCTION__);
1202     return -1;
1203   }
1204   return 0;
1205 }
1206
1207 int32_t ViEChannel::GetSendRtcpStatistics(uint16_t* fraction_lost,
1208                                           uint32_t* cumulative_lost,
1209                                           uint32_t* extended_max,
1210                                           uint32_t* jitter_samples,
1211                                           int32_t* rtt_ms) {
1212   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
1213                __FUNCTION__);
1214
1215   // TODO(pwestin) how do we do this for simulcast ? average for all
1216   // except cumulative_lost that is the sum ?
1217   // CriticalSectionScoped cs(rtp_rtcp_cs_.get());
1218
1219   // for (std::list<RtpRtcp*>::const_iterator it = simulcast_rtp_rtcp_.begin();
1220   //      it != simulcast_rtp_rtcp_.end();
1221   //      it++) {
1222   //   RtpRtcp* rtp_rtcp = *it;
1223   // }
1224   uint32_t remote_ssrc = vie_receiver_.GetRemoteSsrc();
1225
1226   // Get all RTCP receiver report blocks that have been received on this
1227   // channel. If we receive RTP packets from a remote source we know the
1228   // remote SSRC and use the report block from him.
1229   // Otherwise use the first report block.
1230   std::vector<RTCPReportBlock> remote_stats;
1231   if (rtp_rtcp_->RemoteRTCPStat(&remote_stats) != 0 || remote_stats.empty()) {
1232     WEBRTC_TRACE(kTraceWarning, kTraceVideo, ViEId(engine_id_, channel_id_),
1233                  "%s: Could not get remote stats", __FUNCTION__);
1234     return -1;
1235   }
1236   std::vector<RTCPReportBlock>::const_iterator statistics =
1237       remote_stats.begin();
1238   for (; statistics != remote_stats.end(); ++statistics) {
1239     if (statistics->remoteSSRC == remote_ssrc)
1240       break;
1241   }
1242
1243   if (statistics == remote_stats.end()) {
1244     // If we have not received any RTCP packets from this SSRC it probably means
1245     // we have not received any RTP packets.
1246     // Use the first received report block instead.
1247     statistics = remote_stats.begin();
1248     remote_ssrc = statistics->remoteSSRC;
1249   }
1250
1251   *fraction_lost = statistics->fractionLost;
1252   *cumulative_lost = statistics->cumulativeLost;
1253   *extended_max = statistics->extendedHighSeqNum;
1254   *jitter_samples = statistics->jitter;
1255
1256   uint16_t dummy;
1257   uint16_t rtt = 0;
1258   if (rtp_rtcp_->RTT(remote_ssrc, &rtt, &dummy, &dummy, &dummy) != 0) {
1259     WEBRTC_TRACE(kTraceWarning, kTraceVideo, ViEId(engine_id_, channel_id_),
1260                  "%s: Could not get RTT", __FUNCTION__);
1261     return -1;
1262   }
1263   *rtt_ms = rtt;
1264   return 0;
1265 }
1266
1267 void ViEChannel::RegisterSendChannelRtcpStatisticsCallback(
1268     RtcpStatisticsCallback* callback) {
1269   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
1270                __FUNCTION__);
1271   rtp_rtcp_->RegisterSendChannelRtcpStatisticsCallback(callback);
1272   CriticalSectionScoped cs(rtp_rtcp_cs_.get());
1273   for (std::list<RtpRtcp*>::const_iterator it = simulcast_rtp_rtcp_.begin();
1274        it != simulcast_rtp_rtcp_.end();
1275        ++it) {
1276     (*it)->RegisterSendChannelRtcpStatisticsCallback(callback);
1277   }
1278 }
1279
1280 // TODO(holmer): This is a bad function name as it implies that it returns the
1281 // received RTCP, while it actually returns the statistics which will be sent
1282 // in the RTCP.
1283 int32_t ViEChannel::GetReceivedRtcpStatistics(uint16_t* fraction_lost,
1284                                               uint32_t* cumulative_lost,
1285                                               uint32_t* extended_max,
1286                                               uint32_t* jitter_samples,
1287                                               int32_t* rtt_ms) {
1288   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
1289                "%s", __FUNCTION__);
1290
1291   uint32_t remote_ssrc = vie_receiver_.GetRemoteSsrc();
1292   StreamStatistician* statistician =
1293       vie_receiver_.GetReceiveStatistics()->GetStatistician(remote_ssrc);
1294   RtcpStatistics receive_stats;
1295   if (!statistician || !statistician->GetStatistics(
1296       &receive_stats, rtp_rtcp_->RTCP() == kRtcpOff)) {
1297     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1298                  "%s: Could not get received RTP statistics", __FUNCTION__);
1299     return -1;
1300   }
1301   *fraction_lost = receive_stats.fraction_lost;
1302   *cumulative_lost = receive_stats.cumulative_lost;
1303   *extended_max = receive_stats.extended_max_sequence_number;
1304   *jitter_samples = receive_stats.jitter;
1305
1306   uint16_t dummy = 0;
1307   uint16_t rtt = 0;
1308   if (rtp_rtcp_->RTT(remote_ssrc, &rtt, &dummy, &dummy, &dummy) != 0) {
1309     WEBRTC_TRACE(kTraceStateInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
1310                  "%s: Could not get RTT", __FUNCTION__);
1311   }
1312   *rtt_ms = rtt;
1313   return 0;
1314 }
1315
1316 void ViEChannel::RegisterReceiveChannelRtcpStatisticsCallback(
1317     RtcpStatisticsCallback* callback) {
1318   WEBRTC_TRACE(kTraceInfo,
1319                kTraceVideo,
1320                ViEId(engine_id_, channel_id_),
1321                "%s",
1322                __FUNCTION__);
1323   vie_receiver_.GetReceiveStatistics()->RegisterRtcpStatisticsCallback(
1324       callback);
1325 }
1326
1327 int32_t ViEChannel::GetRtpStatistics(uint32_t* bytes_sent,
1328                                      uint32_t* packets_sent,
1329                                      uint32_t* bytes_received,
1330                                      uint32_t* packets_received) const {
1331   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
1332                __FUNCTION__);
1333
1334   StreamStatistician* statistician = vie_receiver_.GetReceiveStatistics()->
1335       GetStatistician(vie_receiver_.GetRemoteSsrc());
1336   *bytes_received = 0;
1337   *packets_received = 0;
1338   if (statistician)
1339     statistician->GetDataCounters(bytes_received, packets_received);
1340   if (rtp_rtcp_->DataCountersRTP(bytes_sent, packets_sent) != 0) {
1341     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1342                  "%s: Could not get counters", __FUNCTION__);
1343     return -1;
1344   }
1345   CriticalSectionScoped cs(rtp_rtcp_cs_.get());
1346   for (std::list<RtpRtcp*>::const_iterator it = simulcast_rtp_rtcp_.begin();
1347        it != simulcast_rtp_rtcp_.end();
1348        it++) {
1349     uint32_t bytes_sent_temp = 0;
1350     uint32_t packets_sent_temp = 0;
1351     RtpRtcp* rtp_rtcp = *it;
1352     rtp_rtcp->DataCountersRTP(&bytes_sent_temp, &packets_sent_temp);
1353     bytes_sent += bytes_sent_temp;
1354     packets_sent += packets_sent_temp;
1355   }
1356   return 0;
1357 }
1358
1359 void ViEChannel::RegisterSendChannelRtpStatisticsCallback(
1360       StreamDataCountersCallback* callback) {
1361   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
1362                  __FUNCTION__);
1363   rtp_rtcp_->RegisterSendChannelRtpStatisticsCallback(callback);
1364   {
1365     CriticalSectionScoped cs(rtp_rtcp_cs_.get());
1366     for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
1367          it != simulcast_rtp_rtcp_.end();
1368          it++) {
1369       (*it)->RegisterSendChannelRtpStatisticsCallback(callback);
1370     }
1371   }
1372 }
1373
1374 void ViEChannel::RegisterReceiveChannelRtpStatisticsCallback(
1375     StreamDataCountersCallback* callback) {
1376   WEBRTC_TRACE(kTraceInfo,
1377                kTraceVideo,
1378                ViEId(engine_id_, channel_id_),
1379                "%s",
1380                __FUNCTION__);
1381   vie_receiver_.GetReceiveStatistics()->RegisterRtpStatisticsCallback(callback);
1382 }
1383
1384 void ViEChannel::GetBandwidthUsage(uint32_t* total_bitrate_sent,
1385                                    uint32_t* video_bitrate_sent,
1386                                    uint32_t* fec_bitrate_sent,
1387                                    uint32_t* nackBitrateSent) const {
1388   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
1389                __FUNCTION__);
1390
1391   rtp_rtcp_->BitrateSent(total_bitrate_sent, video_bitrate_sent,
1392                          fec_bitrate_sent, nackBitrateSent);
1393   CriticalSectionScoped cs(rtp_rtcp_cs_.get());
1394   for (std::list<RtpRtcp*>::const_iterator it = simulcast_rtp_rtcp_.begin();
1395        it != simulcast_rtp_rtcp_.end(); it++) {
1396     uint32_t stream_rate = 0;
1397     uint32_t video_rate = 0;
1398     uint32_t fec_rate = 0;
1399     uint32_t nackRate = 0;
1400     RtpRtcp* rtp_rtcp = *it;
1401     rtp_rtcp->BitrateSent(&stream_rate, &video_rate, &fec_rate, &nackRate);
1402     *total_bitrate_sent += stream_rate;
1403     *video_bitrate_sent += video_rate;
1404     *fec_bitrate_sent += fec_rate;
1405     *nackBitrateSent += nackRate;
1406   }
1407 }
1408
1409 bool ViEChannel::GetSendSideDelay(int* avg_send_delay,
1410                                   int* max_send_delay) const {
1411   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
1412                __FUNCTION__);
1413
1414   *avg_send_delay = 0;
1415   *max_send_delay = 0;
1416   bool valid_estimate = false;
1417   int num_send_delays = 0;
1418   if (rtp_rtcp_->GetSendSideDelay(avg_send_delay, max_send_delay)) {
1419     ++num_send_delays;
1420     valid_estimate = true;
1421   }
1422   CriticalSectionScoped cs(rtp_rtcp_cs_.get());
1423   for (std::list<RtpRtcp*>::const_iterator it = simulcast_rtp_rtcp_.begin();
1424        it != simulcast_rtp_rtcp_.end(); it++) {
1425     RtpRtcp* rtp_rtcp = *it;
1426     int sub_stream_avg_delay = 0;
1427     int sub_stream_max_delay = 0;
1428     if (rtp_rtcp->GetSendSideDelay(&sub_stream_avg_delay,
1429                                    &sub_stream_max_delay)) {
1430       *avg_send_delay += sub_stream_avg_delay;
1431       *max_send_delay = std::max(*max_send_delay, sub_stream_max_delay);
1432       ++num_send_delays;
1433     }
1434   }
1435   if (num_send_delays > 0) {
1436     valid_estimate = true;
1437     *avg_send_delay = *avg_send_delay / num_send_delays;
1438     *avg_send_delay = (*avg_send_delay + num_send_delays / 2) / num_send_delays;
1439   }
1440   return valid_estimate;
1441 }
1442
1443 void ViEChannel::RegisterSendBitrateObserver(
1444     BitrateStatisticsObserver* observer) {
1445   rtp_rtcp_->RegisterVideoBitrateObserver(observer);
1446   CriticalSectionScoped cs(rtp_rtcp_cs_.get());
1447   for (std::list<RtpRtcp*>::const_iterator it = simulcast_rtp_rtcp_.begin();
1448        it != simulcast_rtp_rtcp_.end();
1449        it++) {
1450     (*it)->RegisterVideoBitrateObserver(observer);
1451   }
1452 }
1453
1454 void ViEChannel::GetEstimatedReceiveBandwidth(
1455     uint32_t* estimated_bandwidth) const {
1456   vie_receiver_.EstimatedReceiveBandwidth(estimated_bandwidth);
1457 }
1458
1459 void ViEChannel::GetReceiveBandwidthEstimatorStats(
1460     ReceiveBandwidthEstimatorStats* output) const {
1461   vie_receiver_.GetReceiveBandwidthEstimatorStats(output);
1462 }
1463
1464 int32_t ViEChannel::StartRTPDump(const char file_nameUTF8[1024],
1465                                        RTPDirections direction) {
1466   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
1467                __FUNCTION__);
1468
1469   if (direction != kRtpIncoming && direction != kRtpOutgoing) {
1470     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1471                  "%s: invalid input", __FUNCTION__);
1472     return -1;
1473   }
1474
1475   if (direction == kRtpIncoming) {
1476     return vie_receiver_.StartRTPDump(file_nameUTF8);
1477   } else {
1478     return vie_sender_.StartRTPDump(file_nameUTF8);
1479   }
1480 }
1481
1482 int32_t ViEChannel::StopRTPDump(RTPDirections direction) {
1483   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
1484                "%s", __FUNCTION__);
1485
1486   if (direction != kRtpIncoming && direction != kRtpOutgoing) {
1487     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1488                  "%s: invalid input", __FUNCTION__);
1489     return -1;
1490   }
1491
1492   if (direction == kRtpIncoming) {
1493     return vie_receiver_.StopRTPDump();
1494   } else {
1495     return vie_sender_.StopRTPDump();
1496   }
1497 }
1498
1499 int32_t ViEChannel::StartSend() {
1500   CriticalSectionScoped cs(callback_cs_.get());
1501   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
1502                "%s", __FUNCTION__);
1503
1504   if (!external_transport_) {
1505     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1506                  "%s: send sockets not initialized", __FUNCTION__);
1507     return -1;
1508   }
1509   rtp_rtcp_->SetSendingMediaStatus(true);
1510
1511   if (rtp_rtcp_->Sending()) {
1512     // Already sending.
1513     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1514                  "%s: Already sending", __FUNCTION__);
1515     return kViEBaseAlreadySending;
1516   }
1517   if (rtp_rtcp_->SetSendingStatus(true) != 0) {
1518     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1519                  "%s: Could not start sending RTP", __FUNCTION__);
1520     return -1;
1521   }
1522   CriticalSectionScoped cs_rtp(rtp_rtcp_cs_.get());
1523   for (std::list<RtpRtcp*>::const_iterator it = simulcast_rtp_rtcp_.begin();
1524        it != simulcast_rtp_rtcp_.end();
1525        it++) {
1526     RtpRtcp* rtp_rtcp = *it;
1527     rtp_rtcp->SetSendingMediaStatus(true);
1528     rtp_rtcp->SetSendingStatus(true);
1529   }
1530   return 0;
1531 }
1532
1533 int32_t ViEChannel::StopSend() {
1534   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
1535                __FUNCTION__);
1536
1537   CriticalSectionScoped cs(rtp_rtcp_cs_.get());
1538   rtp_rtcp_->SetSendingMediaStatus(false);
1539   for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
1540        it != simulcast_rtp_rtcp_.end();
1541        it++) {
1542     RtpRtcp* rtp_rtcp = *it;
1543     rtp_rtcp->SetSendingMediaStatus(false);
1544   }
1545   if (!rtp_rtcp_->Sending()) {
1546     WEBRTC_TRACE(kTraceWarning, kTraceVideo, ViEId(engine_id_, channel_id_),
1547                  "%s: Not sending", __FUNCTION__);
1548     return kViEBaseNotSending;
1549   }
1550
1551   // Reset.
1552   rtp_rtcp_->ResetSendDataCountersRTP();
1553   if (rtp_rtcp_->SetSendingStatus(false) != 0) {
1554     WEBRTC_TRACE(kTraceWarning, kTraceVideo, ViEId(engine_id_, channel_id_),
1555                  "%s: could not stop RTP sending", __FUNCTION__);
1556     return -1;
1557   }
1558   for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
1559        it != simulcast_rtp_rtcp_.end();
1560        it++) {
1561     RtpRtcp* rtp_rtcp = *it;
1562     rtp_rtcp->ResetSendDataCountersRTP();
1563     rtp_rtcp->SetSendingStatus(false);
1564   }
1565   return 0;
1566 }
1567
1568 bool ViEChannel::Sending() {
1569   return rtp_rtcp_->Sending();
1570 }
1571
1572 int32_t ViEChannel::StartReceive() {
1573   CriticalSectionScoped cs(callback_cs_.get());
1574   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
1575                __FUNCTION__);
1576
1577   if (StartDecodeThread() != 0) {
1578     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1579                  "%s: could not start decoder thread", __FUNCTION__);
1580
1581     vie_receiver_.StopReceive();
1582     return -1;
1583   }
1584   vie_receiver_.StartReceive();
1585   return 0;
1586 }
1587
1588 int32_t ViEChannel::StopReceive() {
1589   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
1590                __FUNCTION__);
1591
1592   vie_receiver_.StopReceive();
1593   StopDecodeThread();
1594   vcm_.ResetDecoder();
1595   return 0;
1596 }
1597
1598 int32_t ViEChannel::RegisterSendTransport(Transport* transport) {
1599   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
1600                __FUNCTION__);
1601
1602   if (rtp_rtcp_->Sending()) {
1603     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1604                  "%s: Sending", __FUNCTION__);
1605     return -1;
1606   }
1607
1608   CriticalSectionScoped cs(callback_cs_.get());
1609   if (external_transport_) {
1610     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1611                  "%s: transport already registered", __FUNCTION__);
1612     return -1;
1613   }
1614   external_transport_ = transport;
1615   vie_sender_.RegisterSendTransport(transport);
1616   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
1617                "%s: Transport registered: 0x%p", __FUNCTION__,
1618                &external_transport_);
1619
1620   return 0;
1621 }
1622
1623 int32_t ViEChannel::DeregisterSendTransport() {
1624   CriticalSectionScoped cs(callback_cs_.get());
1625   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
1626                __FUNCTION__);
1627
1628   if (!external_transport_) {
1629     WEBRTC_TRACE(kTraceWarning, kTraceVideo, ViEId(engine_id_, channel_id_),
1630                  "%s: no transport registered", __FUNCTION__);
1631     return -1;
1632   }
1633   if (rtp_rtcp_->Sending()) {
1634     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1635                  "%s: Sending", __FUNCTION__);
1636     return -1;
1637   }
1638   external_transport_ = NULL;
1639   vie_sender_.DeregisterSendTransport();
1640   return 0;
1641 }
1642
1643 int32_t ViEChannel::ReceivedRTPPacket(
1644     const void* rtp_packet, const int32_t rtp_packet_length,
1645     const PacketTime& packet_time) {
1646   {
1647     CriticalSectionScoped cs(callback_cs_.get());
1648     if (!external_transport_) {
1649       return -1;
1650     }
1651   }
1652   return vie_receiver_.ReceivedRTPPacket(
1653       rtp_packet, rtp_packet_length, packet_time);
1654 }
1655
1656 int32_t ViEChannel::ReceivedRTCPPacket(
1657   const void* rtcp_packet, const int32_t rtcp_packet_length) {
1658   {
1659     CriticalSectionScoped cs(callback_cs_.get());
1660     if (!external_transport_) {
1661       return -1;
1662     }
1663   }
1664   return vie_receiver_.ReceivedRTCPPacket(rtcp_packet, rtcp_packet_length);
1665 }
1666
1667 int32_t ViEChannel::SetMTU(uint16_t mtu) {
1668   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
1669                __FUNCTION__);
1670   if (rtp_rtcp_->SetMaxTransferUnit(mtu) != 0) {
1671     // Logging done.
1672     return -1;
1673   }
1674   CriticalSectionScoped cs(rtp_rtcp_cs_.get());
1675   for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
1676        it != simulcast_rtp_rtcp_.end();
1677        it++) {
1678     RtpRtcp* rtp_rtcp = *it;
1679     rtp_rtcp->SetMaxTransferUnit(mtu);
1680   }
1681   mtu_ = mtu;
1682   return 0;
1683 }
1684
1685 uint16_t ViEChannel::MaxDataPayloadLength() const {
1686   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
1687                "%s", __FUNCTION__);
1688   return rtp_rtcp_->MaxDataPayloadLength();
1689 }
1690
1691 int32_t ViEChannel::EnableColorEnhancement(bool enable) {
1692   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
1693                "%s(enable: %d)", __FUNCTION__, enable);
1694
1695   CriticalSectionScoped cs(callback_cs_.get());
1696   color_enhancement_ = enable;
1697   return 0;
1698 }
1699
1700 RtpRtcp* ViEChannel::rtp_rtcp() {
1701   return rtp_rtcp_.get();
1702 }
1703
1704 CallStatsObserver* ViEChannel::GetStatsObserver() {
1705   return stats_observer_.get();
1706 }
1707
1708 // Do not acquire the lock of |vcm_| in this function. Decode callback won't
1709 // necessarily be called from the decoding thread. The decoding thread may have
1710 // held the lock when calling VideoDecoder::Decode, Reset, or Release. Acquiring
1711 // the same lock in the path of decode callback can deadlock.
1712 int32_t ViEChannel::FrameToRender(
1713     I420VideoFrame& video_frame) {  // NOLINT
1714   CriticalSectionScoped cs(callback_cs_.get());
1715
1716   if (decoder_reset_) {
1717     // Trigger a callback to the user if the incoming codec has changed.
1718     if (codec_observer_) {
1719       // The codec set by RegisterReceiveCodec might not be the size we're
1720       // actually decoding.
1721       receive_codec_.width = static_cast<uint16_t>(video_frame.width());
1722       receive_codec_.height = static_cast<uint16_t>(video_frame.height());
1723       codec_observer_->IncomingCodecChanged(channel_id_, receive_codec_);
1724     }
1725     decoder_reset_ = false;
1726   }
1727   // Post processing is not supported if the frame is backed by a texture.
1728   if (video_frame.native_handle() == NULL) {
1729     if (pre_render_callback_ != NULL)
1730       pre_render_callback_->FrameCallback(&video_frame);
1731     if (effect_filter_) {
1732       unsigned int length = CalcBufferSize(kI420,
1733                                            video_frame.width(),
1734                                            video_frame.height());
1735       scoped_array<uint8_t> video_buffer(new uint8_t[length]);
1736       ExtractBuffer(video_frame, length, video_buffer.get());
1737       effect_filter_->Transform(length, video_buffer.get(),
1738                                 video_frame.timestamp(), video_frame.width(),
1739                                 video_frame.height());
1740     }
1741     if (color_enhancement_) {
1742       VideoProcessingModule::ColorEnhancement(&video_frame);
1743     }
1744   }
1745
1746   uint32_t arr_ofCSRC[kRtpCsrcSize];
1747   int32_t no_of_csrcs = vie_receiver_.GetCsrcs(arr_ofCSRC);
1748   if (no_of_csrcs <= 0) {
1749     arr_ofCSRC[0] = vie_receiver_.GetRemoteSsrc();
1750     no_of_csrcs = 1;
1751   }
1752   WEBRTC_TRACE(kTraceStream, kTraceVideo, ViEId(engine_id_, channel_id_),
1753                "%s(timestamp:%u)", __FUNCTION__, video_frame.timestamp());
1754   DeliverFrame(&video_frame, no_of_csrcs, arr_ofCSRC);
1755   return 0;
1756 }
1757
1758 int32_t ViEChannel::ReceivedDecodedReferenceFrame(
1759   const uint64_t picture_id) {
1760   return rtp_rtcp_->SendRTCPReferencePictureSelection(picture_id);
1761 }
1762
1763 void ViEChannel::IncomingCodecChanged(const VideoCodec& codec) {
1764   CriticalSectionScoped cs(callback_cs_.get());
1765   receive_codec_ = codec;
1766 }
1767
1768 int32_t ViEChannel::OnReceiveStatisticsUpdate(const uint32_t bit_rate,
1769                                               const uint32_t frame_rate) {
1770   CriticalSectionScoped cs(callback_cs_.get());
1771   if (codec_observer_) {
1772     WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
1773                  "%s: bitrate %u, framerate %u", __FUNCTION__, bit_rate,
1774                  frame_rate);
1775     codec_observer_->IncomingRate(channel_id_, frame_rate, bit_rate);
1776   }
1777   return 0;
1778 }
1779
1780 void ViEChannel::OnDecoderTiming(int decode_ms,
1781                                  int max_decode_ms,
1782                                  int current_delay_ms,
1783                                  int target_delay_ms,
1784                                  int jitter_buffer_ms,
1785                                  int min_playout_delay_ms,
1786                                  int render_delay_ms) {
1787   CriticalSectionScoped cs(callback_cs_.get());
1788   if (!codec_observer_)
1789     return;
1790   codec_observer_->DecoderTiming(decode_ms,
1791                                  max_decode_ms,
1792                                  current_delay_ms,
1793                                  target_delay_ms,
1794                                  jitter_buffer_ms,
1795                                  min_playout_delay_ms,
1796                                  render_delay_ms);
1797 }
1798
1799 int32_t ViEChannel::RequestKeyFrame() {
1800   WEBRTC_TRACE(kTraceStream, kTraceVideo, ViEId(engine_id_, channel_id_),
1801                "%s", __FUNCTION__);
1802   {
1803     CriticalSectionScoped cs(callback_cs_.get());
1804     if (codec_observer_ && do_key_frame_callbackRequest_) {
1805       codec_observer_->RequestNewKeyFrame(channel_id_);
1806     }
1807   }
1808   return rtp_rtcp_->RequestKeyFrame();
1809 }
1810
1811 int32_t ViEChannel::SliceLossIndicationRequest(
1812   const uint64_t picture_id) {
1813   return rtp_rtcp_->SendRTCPSliceLossIndication((uint8_t) picture_id);
1814 }
1815
1816 int32_t ViEChannel::ResendPackets(const uint16_t* sequence_numbers,
1817                                         uint16_t length) {
1818   WEBRTC_TRACE(kTraceStream, kTraceVideo, ViEId(engine_id_, channel_id_),
1819                "%s(length: %d)", __FUNCTION__, length);
1820   return rtp_rtcp_->SendNACK(sequence_numbers, length);
1821 }
1822
1823 bool ViEChannel::ChannelDecodeThreadFunction(void* obj) {
1824   return static_cast<ViEChannel*>(obj)->ChannelDecodeProcess();
1825 }
1826
1827 bool ViEChannel::ChannelDecodeProcess() {
1828   vcm_.Decode(kMaxDecodeWaitTimeMs);
1829   return true;
1830 }
1831
1832 void ViEChannel::OnRttUpdate(uint32_t rtt) {
1833   vcm_.SetReceiveChannelParameters(rtt);
1834 }
1835
1836 int32_t ViEChannel::StartDecodeThread() {
1837   // Start the decode thread
1838   if (decode_thread_) {
1839     // Already started.
1840     return 0;
1841   }
1842   decode_thread_ = ThreadWrapper::CreateThread(ChannelDecodeThreadFunction,
1843                                                    this, kHighestPriority,
1844                                                    "DecodingThread");
1845   if (!decode_thread_) {
1846     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1847                  "%s: could not create decode thread", __FUNCTION__);
1848     return -1;
1849   }
1850
1851   unsigned int thread_id;
1852   if (decode_thread_->Start(thread_id) == false) {
1853     delete decode_thread_;
1854     decode_thread_ = NULL;
1855     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1856                  "%s: could not start decode thread", __FUNCTION__);
1857     return -1;
1858   }
1859
1860   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
1861                "%s: decode thread with id %u started", __FUNCTION__);
1862   return 0;
1863 }
1864
1865 int32_t ViEChannel::StopDecodeThread() {
1866   if (!decode_thread_) {
1867     WEBRTC_TRACE(kTraceWarning, kTraceVideo, ViEId(engine_id_, channel_id_),
1868                  "%s: decode thread not running", __FUNCTION__);
1869     return 0;
1870   }
1871
1872   decode_thread_->SetNotAlive();
1873   if (decode_thread_->Stop()) {
1874     delete decode_thread_;
1875   } else {
1876     // Couldn't stop the thread, leak instead of crash.
1877     WEBRTC_TRACE(kTraceWarning, kTraceVideo, ViEId(engine_id_, channel_id_),
1878                  "%s: could not stop decode thread", __FUNCTION__);
1879     assert(false && "could not stop decode thread");
1880   }
1881   decode_thread_ = NULL;
1882   return 0;
1883 }
1884
1885 int32_t ViEChannel::SetVoiceChannel(int32_t ve_channel_id,
1886                                           VoEVideoSync* ve_sync_interface) {
1887   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
1888                "%s, audio channel %d, video channel %d", __FUNCTION__,
1889                ve_channel_id, channel_id_);
1890
1891   if (ve_sync_interface) {
1892     // Register lip sync
1893     module_process_thread_.RegisterModule(&vie_sync_);
1894   } else {
1895     module_process_thread_.DeRegisterModule(&vie_sync_);
1896   }
1897   return vie_sync_.ConfigureSync(ve_channel_id,
1898                                  ve_sync_interface,
1899                                  rtp_rtcp_.get(),
1900                                  vie_receiver_.GetRtpReceiver());
1901 }
1902
1903 int32_t ViEChannel::VoiceChannel() {
1904   return vie_sync_.VoiceChannel();
1905 }
1906
1907 int32_t ViEChannel::RegisterEffectFilter(ViEEffectFilter* effect_filter) {
1908   CriticalSectionScoped cs(callback_cs_.get());
1909   if (!effect_filter) {
1910     if (!effect_filter_) {
1911       WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1912                    "%s: no effect filter added for channel %d",
1913                    __FUNCTION__, channel_id_);
1914       return -1;
1915     }
1916     WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
1917                  "%s: deregister effect filter for device %d", __FUNCTION__,
1918                  channel_id_);
1919   } else {
1920     WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
1921                  "%s: register effect filter for device %d", __FUNCTION__,
1922                  channel_id_);
1923     if (effect_filter_) {
1924       WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1925                    "%s: effect filter already added for channel %d",
1926                    __FUNCTION__, channel_id_);
1927       return -1;
1928     }
1929   }
1930   effect_filter_ = effect_filter;
1931   return 0;
1932 }
1933
1934 void ViEChannel::RegisterPreRenderCallback(
1935     I420FrameCallback* pre_render_callback) {
1936   CriticalSectionScoped cs(callback_cs_.get());
1937   pre_render_callback_ = pre_render_callback;
1938 }
1939
1940 void ViEChannel::RegisterPreDecodeImageCallback(
1941     EncodedImageCallback* pre_decode_callback) {
1942   CriticalSectionScoped cs(callback_cs_.get());
1943   vcm_.RegisterPreDecodeImageCallback(pre_decode_callback);
1944 }
1945
1946 void ViEChannel::OnApplicationDataReceived(const int32_t id,
1947                                            const uint8_t sub_type,
1948                                            const uint32_t name,
1949                                            const uint16_t length,
1950                                            const uint8_t* data) {
1951   if (channel_id_ != ChannelId(id)) {
1952     WEBRTC_TRACE(kTraceStream, kTraceVideo, ViEId(engine_id_, channel_id_),
1953                  "%s, incorrect id", __FUNCTION__, id);
1954     return;
1955   }
1956   CriticalSectionScoped cs(callback_cs_.get());
1957   {
1958     if (rtcp_observer_) {
1959       rtcp_observer_->OnApplicationDataReceived(
1960           channel_id_, sub_type, name, reinterpret_cast<const char*>(data),
1961           length);
1962     }
1963   }
1964 }
1965
1966 int32_t ViEChannel::OnInitializeDecoder(
1967     const int32_t id,
1968     const int8_t payload_type,
1969     const char payload_name[RTP_PAYLOAD_NAME_SIZE],
1970     const int frequency,
1971     const uint8_t channels,
1972     const uint32_t rate) {
1973   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
1974                "%s: payload_type %d, payload_name %s", __FUNCTION__,
1975                payload_type, payload_name);
1976   vcm_.ResetDecoder();
1977
1978   CriticalSectionScoped cs(callback_cs_.get());
1979   decoder_reset_ = true;
1980   return 0;
1981 }
1982
1983 void ViEChannel::OnIncomingSSRCChanged(const int32_t id, const uint32_t ssrc) {
1984   if (channel_id_ != ChannelId(id)) {
1985     assert(false);
1986     WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
1987                  "%s, incorrect id", __FUNCTION__, id);
1988     return;
1989   }
1990
1991   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
1992                "%s: %u", __FUNCTION__, ssrc);
1993
1994   rtp_rtcp_->SetRemoteSSRC(ssrc);
1995
1996   CriticalSectionScoped cs(callback_cs_.get());
1997   {
1998     if (rtp_observer_) {
1999       rtp_observer_->IncomingSSRCChanged(channel_id_, ssrc);
2000     }
2001   }
2002 }
2003
2004 void ViEChannel::OnIncomingCSRCChanged(const int32_t id,
2005                                        const uint32_t CSRC,
2006                                        const bool added) {
2007   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
2008                "%s: %u added: %d", __FUNCTION__, CSRC, added);
2009
2010   if (channel_id_ != ChannelId(id)) {
2011     assert(false);
2012     WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
2013                  "%s, incorrect id", __FUNCTION__, id);
2014     return;
2015   }
2016
2017   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
2018                "%s: %u", __FUNCTION__, CSRC);
2019
2020   CriticalSectionScoped cs(callback_cs_.get());
2021   {
2022     if (rtp_observer_) {
2023       rtp_observer_->IncomingCSRCChanged(channel_id_, CSRC, added);
2024     }
2025   }
2026 }
2027
2028 void ViEChannel::ResetStatistics(uint32_t ssrc) {
2029   StreamStatistician* statistician =
2030       vie_receiver_.GetReceiveStatistics()->GetStatistician(ssrc);
2031   if (statistician)
2032     statistician->ResetStatistics();
2033 }
2034
2035 void ViEChannel::RegisterSendFrameCountObserver(
2036     FrameCountObserver* observer) {
2037   rtp_rtcp_->RegisterSendFrameCountObserver(observer);
2038   CriticalSectionScoped cs(rtp_rtcp_cs_.get());
2039   for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
2040        it != simulcast_rtp_rtcp_.end();
2041        it++) {
2042     (*it)->RegisterSendFrameCountObserver(observer);
2043   }
2044 }
2045
2046 }  // namespace webrtc