2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
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.
11 #include "webrtc/video_engine/vie_channel.h"
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"
39 const int kMaxDecodeWaitTimeMs = 50;
40 const int kInvalidRtpExtensionId = 0;
41 static const int kMaxTargetDelayMs = 10000;
42 static const float kMaxIncompleteTimeMultiplier = 3.5f;
44 // Helper class receiving statistics callbacks.
45 class ChannelStatsObserver : public CallStatsObserver {
47 explicit ChannelStatsObserver(ViEChannel* owner) : owner_(owner) {}
48 virtual ~ChannelStatsObserver() {}
50 // Implements StatsObserver.
51 virtual void OnRttUpdate(uint32_t rtt) {
52 owner_->OnRttUpdate(rtt);
59 ViEChannel::ViEChannel(int32_t channel_id,
61 uint32_t number_of_cores,
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,
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),
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),
97 wait_for_key_frame_(false),
100 color_enhancement_(false),
103 nack_history_size_sender_(kSendSidePacketHistorySize),
104 max_nack_reordering_threshold_(kMaxPacketAgeToNack),
105 pre_render_callback_(NULL),
107 WEBRTC_TRACE(kTraceMemory, kTraceVideo, ViEId(engine_id, channel_id),
108 "ViEChannel::ViEChannel(channel_id: %d, engine_id: %d)",
109 channel_id, engine_id);
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();
124 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(configuration));
125 vie_receiver_.SetRtpRtcpModule(rtp_rtcp_.get());
126 vcm_.SetNackSettings(kMaxNackListSize, max_nack_reordering_threshold_, 0);
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_,
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",
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__);
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__);
152 if (rtp_rtcp_->SetKeyFrameRequestMethod(kKeyFrameReqFirRtp) != 0) {
153 WEBRTC_TRACE(kTraceWarning, kTraceVideo, ViEId(engine_id_, channel_id_),
154 "%s: RTP::SetKeyFrameRequestMethod failure", __FUNCTION__);
156 if (rtp_rtcp_->SetRTCPStatus(kRtcpCompound) != 0) {
157 WEBRTC_TRACE(kTraceWarning, kTraceVideo, ViEId(engine_id_, channel_id_),
158 "%s: RTP::SetRTCPStatus failure", __FUNCTION__);
161 if (rtp_rtcp_->SetStorePacketsStatus(true, nack_history_size_sender_) !=
163 WEBRTC_TRACE(kTraceWarning, kTraceVideo, ViEId(engine_id_, channel_id_),
164 "%s:SetStorePacketsStatus failure", __FUNCTION__);
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__);
174 if (vcm_.SetVideoProtection(kProtectionKeyOnLoss, true)) {
175 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
176 "%s: VCM::SetVideoProtection failure", __FUNCTION__);
179 if (vcm_.RegisterReceiveCallback(this) != 0) {
180 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
181 "%s: VCM::RegisterReceiveCallback failure", __FUNCTION__);
184 if (vcm_.RegisterFrameTypeCallback(this) != 0) {
185 WEBRTC_TRACE(kTraceWarning, kTraceVideo, ViEId(engine_id_, channel_id_),
186 "%s: VCM::RegisterFrameTypeCallback failure", __FUNCTION__);
188 if (vcm_.RegisterReceiveStatisticsCallback(this) != 0) {
189 WEBRTC_TRACE(kTraceWarning, kTraceVideo, ViEId(engine_id_, channel_id_),
190 "%s: VCM::RegisterReceiveStatisticsCallback failure",
193 if (vcm_.RegisterDecoderTimingCallback(this) != 0) {
194 WEBRTC_TRACE(kTraceWarning, kTraceVideo, ViEId(engine_id_, channel_id_),
195 "%s: VCM::RegisterDecoderTimingCallback failure",
198 if (vcm_.SetRenderDelay(kViEDefaultRenderDelayMs) != 0) {
199 WEBRTC_TRACE(kTraceWarning, kTraceVideo, ViEId(engine_id_, channel_id_),
200 "%s: VCM::SetRenderDelay failure", __FUNCTION__);
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__);
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)) {
215 vcm_.RegisterReceiveCodec(&video_codec, number_of_cores_);
216 vcm_.RegisterSendCodec(&video_codec, number_of_cores_,
217 rtp_rtcp_->MaxDataPayloadLength());
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_);
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);
241 simulcast_rtp_rtcp_.erase(it);
243 while (removed_rtp_rtcp_.size() > 0) {
244 std::list<RtpRtcp*>::iterator it = removed_rtp_rtcp_.begin();
246 removed_rtp_rtcp_.erase(it);
248 if (decode_thread_) {
252 VideoCodingModule::Destroy(&vcm_);
255 int32_t ViEChannel::SetSendCodec(const VideoCodec& video_codec,
257 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
258 "%s: codec_type: %d", __FUNCTION__, video_codec.codecType);
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);
270 if (kMaxSimulcastStreams < video_codec.numberOfSimulcastStreams) {
271 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
272 "%s: Too many simulcast streams", __FUNCTION__);
275 // Update the RTP module with the settings.
276 // Stop and Start the RTP module -> trigger new SSRC, if an SSRC hasn't been
278 bool restart_rtp = false;
279 if (rtp_rtcp_->Sending() && new_stream) {
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);
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);
294 CriticalSectionScoped cs(rtp_rtcp_cs_.get());
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;
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;
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_;
326 RtpRtcp* rtp_rtcp = RtpRtcp::CreateRtpRtcp(configuration);
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__);
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_);
342 rtp_rtcp->SetGenericFECStatus(fec_enabled, payload_type_red,
345 rtp_rtcp->SetSendingStatus(rtp_rtcp_->Sending());
346 rtp_rtcp->SetSendingMediaStatus(rtp_rtcp_->SendingMedia());
347 simulcast_rtp_rtcp_.push_back(rtp_rtcp);
349 // Remove last in list if we have too many.
350 for (int j = simulcast_rtp_rtcp_.size();
351 j > (video_codec.numberOfSimulcastStreams - 1);
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);
365 // Configure all simulcast modules.
366 for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
367 it != simulcast_rtp_rtcp_.end();
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__);
378 rtp_rtcp->SetMaxTransferUnit(mtu_);
381 rtp_rtcp->SetSendingStatus(true);
382 rtp_rtcp->SetSendingMediaStatus(true);
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",
396 rtp_rtcp->DeregisterSendRtpHeaderExtension(
397 kRtpExtensionTransmissionTimeOffset);
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",
411 rtp_rtcp->DeregisterSendRtpHeaderExtension(
412 kRtpExtensionAbsoluteSendTime);
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());
423 // |RegisterSimulcastRtpRtcpModules| resets all old weak pointers and old
424 // modules can be deleted after this step.
425 vie_receiver_.RegisterSimulcastRtpRtcpModules(simulcast_rtp_rtcp_);
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);
439 // Clear any previous modules.
440 vie_receiver_.RegisterSimulcastRtpRtcpModules(simulcast_rtp_rtcp_);
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);
448 // rtp_rtcp_->SetH264PacketizationMode(H264_NON_INTERLEAVED_MODE);
450 // if (video_codec.codecSpecific.H264.configParametersSize > 0) {
451 // rtp_rtcp_->SetH264SendModeNALU_PPS_SPS(true);
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__);
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);
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_),
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__);
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__);
498 int32_t ViEChannel::GetReceiveCodec(VideoCodec* video_codec) {
499 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
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__);
510 int32_t ViEChannel::RegisterCodecObserver(ViEDecoderObserver* observer) {
511 CriticalSectionScoped cs(callback_cs_.get());
513 if (codec_observer_) {
514 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
515 "%s: already added", __FUNCTION__);
518 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
519 "%s: observer added", __FUNCTION__);
520 codec_observer_ = observer;
522 if (!codec_observer_) {
523 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
524 "%s: no observer added", __FUNCTION__);
527 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
528 "%s: observer removed", __FUNCTION__);
529 codec_observer_ = NULL;
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_),
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.",
549 return vcm_.SetRenderDelay(render_delay);
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);
557 VideoCodec current_receive_codec;
559 result = vcm_.ReceiveCodec(¤t_receive_codec);
560 if (vcm_.RegisterExternalDecoder(NULL, pl_type, false) != VCM_OK) {
564 if (result == 0 && current_receive_codec.plType == pl_type) {
565 result = vcm_.RegisterReceiveCodec(¤t_receive_codec, number_of_cores_,
566 wait_for_key_frame_);
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_),
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__);
582 *num_key_frames = received_frames.numKeyFrames;
583 *num_delta_frames = received_frames.numDeltaFrames;
587 uint32_t ViEChannel::DiscardedPackets() const {
588 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
590 return vcm_.DiscardedPackets();
593 int ViEChannel::ReceiveDelay() const {
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;
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);
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);
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);
625 vcm_.SetVideoProtection(kProtectionKeyOnLoss, false);
626 vcm_.SetVideoProtection(kProtectionKeyOnKeyLoss, false);
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);
635 CriticalSectionScoped cs(rtp_rtcp_cs_.get());
636 for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
637 it != simulcast_rtp_rtcp_.end();
639 RtpRtcp* rtp_rtcp = *it;
640 rtp_rtcp->SetRTCPStatus(rtcp_mode);
642 return rtp_rtcp_->SetRTCPStatus(rtcp_mode);
645 int32_t ViEChannel::GetRTCPMode(RTCPMethod* rtcp_mode) {
646 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
648 *rtcp_mode = rtp_rtcp_->RTCP();
652 int32_t ViEChannel::SetNACKStatus(const bool enable) {
653 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
654 "%s(enable: %d)", __FUNCTION__, enable);
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__,
664 // Disable possible FEC.
665 SetFECStatus(false, 0, 0);
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__,
674 return ProcessNACKRequest(enable);
677 int32_t ViEChannel::ProcessNACKRequest(const bool enable) {
678 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
679 "%s(enable: %d)", __FUNCTION__, enable);
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__);
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_);
694 vcm_.RegisterPacketRequestCallback(this);
696 CriticalSectionScoped cs(rtp_rtcp_cs_.get());
698 for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
699 it != simulcast_rtp_rtcp_.end();
701 RtpRtcp* rtp_rtcp = *it;
702 rtp_rtcp->SetStorePacketsStatus(true, nack_history_size_sender_);
704 // Don't introduce errors when NACK is enabled.
705 vcm_.SetDecodeErrorMode(kNoErrors);
707 CriticalSectionScoped cs(rtp_rtcp_cs_.get());
708 for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
709 it != simulcast_rtp_rtcp_.end();
711 RtpRtcp* rtp_rtcp = *it;
712 if (paced_sender_ == NULL) {
713 rtp_rtcp->SetStorePacketsStatus(false, 0);
716 vcm_.RegisterPacketRequestCallback(NULL);
717 if (paced_sender_ == NULL) {
718 rtp_rtcp_->SetStorePacketsStatus(false, 0);
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);
728 int32_t ViEChannel::SetFECStatus(const bool enable,
729 const unsigned char payload_typeRED,
730 const unsigned char payload_typeFEC) {
731 // Disable possible NACK.
733 SetNACKStatus(false);
736 return ProcessFECRequest(enable, payload_typeRED, payload_typeFEC);
739 int32_t ViEChannel::ProcessFECRequest(
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);
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__,
754 CriticalSectionScoped cs(rtp_rtcp_cs_.get());
755 for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
756 it != simulcast_rtp_rtcp_.end();
758 RtpRtcp* rtp_rtcp = *it;
759 rtp_rtcp->SetGenericFECStatus(enable, payload_typeRED, payload_typeFEC);
764 int32_t ViEChannel::SetHybridNACKFECStatus(
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__,
777 ret_val = ProcessNACKRequest(enable);
781 return ProcessFECRequest(enable, payload_typeRED, payload_typeFEC);
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);
791 if (target_delay_ms == 0) {
793 nack_history_size_sender_ = kSendSidePacketHistorySize;
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;
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__);
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__);
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);
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;
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);
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)
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;
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);
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)
867 int ViEChannel::SetSendTimestampOffsetStatus(bool enable, int id) {
868 CriticalSectionScoped cs(rtp_rtcp_cs_.get());
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);
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);
898 int ViEChannel::SetReceiveTimestampOffsetStatus(bool enable, int id) {
899 return vie_receiver_.SetReceiveTimestampOffsetStatus(enable, id) ? 0 : -1;
902 int ViEChannel::SetSendAbsoluteSendTimeStatus(bool enable, int id) {
903 CriticalSectionScoped cs(rtp_rtcp_cs_.get());
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);
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);
933 int ViEChannel::SetReceiveAbsoluteSendTimeStatus(bool enable, int id) {
934 return vie_receiver_.SetReceiveAbsoluteSendTimeStatus(enable, id) ? 0 : -1;
937 void ViEChannel::SetRtcpXrRrtrStatus(bool enable) {
938 CriticalSectionScoped cs(rtp_rtcp_cs_.get());
939 rtp_rtcp_->SetRtcpXrRrtrStatus(enable);
942 void ViEChannel::SetTransmissionSmoothingStatus(bool enable) {
943 assert(paced_sender_ && "No paced sender registered.");
944 paced_sender_->SetStatus(enable);
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);
953 int32_t ViEChannel::EnableKeyFrameRequestCallback(const bool enable) {
954 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
955 "%s: %d", __FUNCTION__, enable);
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);
963 do_key_frame_callbackRequest_ = enable;
967 int32_t ViEChannel::SetSSRC(const uint32_t SSRC,
968 const StreamType usage,
969 const uint8_t simulcast_idx) {
970 WEBRTC_TRACE(webrtc::kTraceInfo,
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);
982 return rtp_rtcp_->SetSSRC(SSRC);
984 CriticalSectionScoped cs(rtp_rtcp_cs_.get());
985 if (simulcast_idx > simulcast_rtp_rtcp_.size()) {
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()) {
994 RtpRtcp* rtp_rtcp_module = *it;
995 if (usage == kViEStreamTypeRtx) {
996 return rtp_rtcp_module->SetRTXSendStatus(rtx_settings, true, SSRC);
998 return rtp_rtcp_module->SetSSRC(SSRC);
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);
1009 vie_receiver_.SetRtxStatus(true, SSRC);
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__);
1019 *ssrc = rtp_rtcp_->SSRC();
1022 CriticalSectionScoped cs(rtp_rtcp_cs_.get());
1023 if (idx > simulcast_rtp_rtcp_.size()) {
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()) {
1032 *ssrc = (*it)->SSRC();
1036 int32_t ViEChannel::GetRemoteSSRC(uint32_t* ssrc) {
1037 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
1040 *ssrc = vie_receiver_.GetRemoteSsrc();
1044 int32_t ViEChannel::GetRemoteCSRC(uint32_t CSRCs[kRtpCsrcSize]) {
1045 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
1048 uint32_t arrayCSRC[kRtpCsrcSize];
1049 memset(arrayCSRC, 0, sizeof(arrayCSRC));
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]);
1059 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
1060 "%s: CSRC list is empty", __FUNCTION__);
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__);
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);
1080 void ViEChannel::SetRtxReceivePayloadType(int payload_type) {
1081 vie_receiver_.SetRtxPayloadType(payload_type);
1084 int32_t ViEChannel::SetStartSequenceNumber(uint16_t sequence_number) {
1085 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
1088 if (rtp_rtcp_->Sending()) {
1089 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1090 "%s: already sending", __FUNCTION__);
1093 return rtp_rtcp_->SetSequenceNumber(sequence_number);
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__);
1104 return rtp_rtcp_->SetCNAME(rtcp_cname);
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);
1113 int32_t ViEChannel::GetRemoteRTCPCName(char rtcp_cname[]) {
1114 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
1117 uint32_t remoteSSRC = vie_receiver_.GetRemoteSsrc();
1118 return rtp_rtcp_->RemoteCNAME(remoteSSRC, rtcp_cname);
1121 int32_t ViEChannel::RegisterRtpObserver(ViERTPObserver* observer) {
1122 CriticalSectionScoped cs(callback_cs_.get());
1124 if (rtp_observer_) {
1125 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1126 "%s: observer alread added", __FUNCTION__);
1129 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
1130 "%s: observer added", __FUNCTION__);
1131 rtp_observer_ = observer;
1133 if (!rtp_observer_) {
1134 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1135 "%s: no observer added", __FUNCTION__);
1138 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
1139 "%s: observer removed", __FUNCTION__);
1140 rtp_observer_ = NULL;
1145 int32_t ViEChannel::RegisterRtcpObserver(ViERTCPObserver* observer) {
1146 CriticalSectionScoped cs(callback_cs_.get());
1148 if (rtcp_observer_) {
1149 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1150 "%s: observer alread added", __FUNCTION__);
1153 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
1154 "%s: observer added", __FUNCTION__);
1155 rtcp_observer_ = observer;
1157 if (!rtcp_observer_) {
1158 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1159 "%s: no observer added", __FUNCTION__);
1162 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
1163 "%s: observer removed", __FUNCTION__);
1164 rtcp_observer_ = NULL;
1169 int32_t ViEChannel::SendApplicationDefinedRTCPPacket(
1170 const uint8_t sub_type,
1172 const uint8_t* data,
1173 uint16_t data_length_in_bytes) {
1174 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
1176 if (!rtp_rtcp_->Sending()) {
1177 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1178 "%s: not sending", __FUNCTION__);
1182 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1183 "%s: no input argument", __FUNCTION__);
1186 if (data_length_in_bytes % 4 != 0) {
1187 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1188 "%s: input length error", __FUNCTION__);
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__);
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__);
1207 int32_t ViEChannel::GetSendRtcpStatistics(uint16_t* fraction_lost,
1208 uint32_t* cumulative_lost,
1209 uint32_t* extended_max,
1210 uint32_t* jitter_samples,
1212 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
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());
1219 // for (std::list<RtpRtcp*>::const_iterator it = simulcast_rtp_rtcp_.begin();
1220 // it != simulcast_rtp_rtcp_.end();
1222 // RtpRtcp* rtp_rtcp = *it;
1224 uint32_t remote_ssrc = vie_receiver_.GetRemoteSsrc();
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__);
1236 std::vector<RTCPReportBlock>::const_iterator statistics =
1237 remote_stats.begin();
1238 for (; statistics != remote_stats.end(); ++statistics) {
1239 if (statistics->remoteSSRC == remote_ssrc)
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;
1251 *fraction_lost = statistics->fractionLost;
1252 *cumulative_lost = statistics->cumulativeLost;
1253 *extended_max = statistics->extendedHighSeqNum;
1254 *jitter_samples = statistics->jitter;
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__);
1267 void ViEChannel::RegisterSendChannelRtcpStatisticsCallback(
1268 RtcpStatisticsCallback* callback) {
1269 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
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();
1276 (*it)->RegisterSendChannelRtcpStatisticsCallback(callback);
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
1283 int32_t ViEChannel::GetReceivedRtcpStatistics(uint16_t* fraction_lost,
1284 uint32_t* cumulative_lost,
1285 uint32_t* extended_max,
1286 uint32_t* jitter_samples,
1288 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
1289 "%s", __FUNCTION__);
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__);
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;
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__);
1316 void ViEChannel::RegisterReceiveChannelRtcpStatisticsCallback(
1317 RtcpStatisticsCallback* callback) {
1318 WEBRTC_TRACE(kTraceInfo,
1320 ViEId(engine_id_, channel_id_),
1323 vie_receiver_.GetReceiveStatistics()->RegisterRtcpStatisticsCallback(
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",
1334 StreamStatistician* statistician = vie_receiver_.GetReceiveStatistics()->
1335 GetStatistician(vie_receiver_.GetRemoteSsrc());
1336 *bytes_received = 0;
1337 *packets_received = 0;
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__);
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();
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;
1359 void ViEChannel::RegisterSendChannelRtpStatisticsCallback(
1360 StreamDataCountersCallback* callback) {
1361 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
1363 rtp_rtcp_->RegisterSendChannelRtpStatisticsCallback(callback);
1365 CriticalSectionScoped cs(rtp_rtcp_cs_.get());
1366 for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
1367 it != simulcast_rtp_rtcp_.end();
1369 (*it)->RegisterSendChannelRtpStatisticsCallback(callback);
1374 void ViEChannel::RegisterReceiveChannelRtpStatisticsCallback(
1375 StreamDataCountersCallback* callback) {
1376 WEBRTC_TRACE(kTraceInfo,
1378 ViEId(engine_id_, channel_id_),
1381 vie_receiver_.GetReceiveStatistics()->RegisterRtpStatisticsCallback(callback);
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",
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;
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",
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)) {
1420 valid_estimate = true;
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);
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;
1440 return valid_estimate;
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();
1450 (*it)->RegisterVideoBitrateObserver(observer);
1454 void ViEChannel::GetEstimatedReceiveBandwidth(
1455 uint32_t* estimated_bandwidth) const {
1456 vie_receiver_.EstimatedReceiveBandwidth(estimated_bandwidth);
1459 void ViEChannel::GetReceiveBandwidthEstimatorStats(
1460 ReceiveBandwidthEstimatorStats* output) const {
1461 vie_receiver_.GetReceiveBandwidthEstimatorStats(output);
1464 int32_t ViEChannel::StartRTPDump(const char file_nameUTF8[1024],
1465 RTPDirections direction) {
1466 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
1469 if (direction != kRtpIncoming && direction != kRtpOutgoing) {
1470 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1471 "%s: invalid input", __FUNCTION__);
1475 if (direction == kRtpIncoming) {
1476 return vie_receiver_.StartRTPDump(file_nameUTF8);
1478 return vie_sender_.StartRTPDump(file_nameUTF8);
1482 int32_t ViEChannel::StopRTPDump(RTPDirections direction) {
1483 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
1484 "%s", __FUNCTION__);
1486 if (direction != kRtpIncoming && direction != kRtpOutgoing) {
1487 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1488 "%s: invalid input", __FUNCTION__);
1492 if (direction == kRtpIncoming) {
1493 return vie_receiver_.StopRTPDump();
1495 return vie_sender_.StopRTPDump();
1499 int32_t ViEChannel::StartSend() {
1500 CriticalSectionScoped cs(callback_cs_.get());
1501 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
1502 "%s", __FUNCTION__);
1504 if (!external_transport_) {
1505 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1506 "%s: send sockets not initialized", __FUNCTION__);
1509 rtp_rtcp_->SetSendingMediaStatus(true);
1511 if (rtp_rtcp_->Sending()) {
1513 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1514 "%s: Already sending", __FUNCTION__);
1515 return kViEBaseAlreadySending;
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__);
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();
1526 RtpRtcp* rtp_rtcp = *it;
1527 rtp_rtcp->SetSendingMediaStatus(true);
1528 rtp_rtcp->SetSendingStatus(true);
1533 int32_t ViEChannel::StopSend() {
1534 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
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();
1542 RtpRtcp* rtp_rtcp = *it;
1543 rtp_rtcp->SetSendingMediaStatus(false);
1545 if (!rtp_rtcp_->Sending()) {
1546 WEBRTC_TRACE(kTraceWarning, kTraceVideo, ViEId(engine_id_, channel_id_),
1547 "%s: Not sending", __FUNCTION__);
1548 return kViEBaseNotSending;
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__);
1558 for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
1559 it != simulcast_rtp_rtcp_.end();
1561 RtpRtcp* rtp_rtcp = *it;
1562 rtp_rtcp->ResetSendDataCountersRTP();
1563 rtp_rtcp->SetSendingStatus(false);
1568 bool ViEChannel::Sending() {
1569 return rtp_rtcp_->Sending();
1572 int32_t ViEChannel::StartReceive() {
1573 CriticalSectionScoped cs(callback_cs_.get());
1574 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
1577 if (StartDecodeThread() != 0) {
1578 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1579 "%s: could not start decoder thread", __FUNCTION__);
1581 vie_receiver_.StopReceive();
1584 vie_receiver_.StartReceive();
1588 int32_t ViEChannel::StopReceive() {
1589 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
1592 vie_receiver_.StopReceive();
1594 vcm_.ResetDecoder();
1598 int32_t ViEChannel::RegisterSendTransport(Transport* transport) {
1599 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
1602 if (rtp_rtcp_->Sending()) {
1603 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1604 "%s: Sending", __FUNCTION__);
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__);
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_);
1623 int32_t ViEChannel::DeregisterSendTransport() {
1624 CriticalSectionScoped cs(callback_cs_.get());
1625 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
1628 if (!external_transport_) {
1629 WEBRTC_TRACE(kTraceWarning, kTraceVideo, ViEId(engine_id_, channel_id_),
1630 "%s: no transport registered", __FUNCTION__);
1633 if (rtp_rtcp_->Sending()) {
1634 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1635 "%s: Sending", __FUNCTION__);
1638 external_transport_ = NULL;
1639 vie_sender_.DeregisterSendTransport();
1643 int32_t ViEChannel::ReceivedRTPPacket(
1644 const void* rtp_packet, const int32_t rtp_packet_length,
1645 const PacketTime& packet_time) {
1647 CriticalSectionScoped cs(callback_cs_.get());
1648 if (!external_transport_) {
1652 return vie_receiver_.ReceivedRTPPacket(
1653 rtp_packet, rtp_packet_length, packet_time);
1656 int32_t ViEChannel::ReceivedRTCPPacket(
1657 const void* rtcp_packet, const int32_t rtcp_packet_length) {
1659 CriticalSectionScoped cs(callback_cs_.get());
1660 if (!external_transport_) {
1664 return vie_receiver_.ReceivedRTCPPacket(rtcp_packet, rtcp_packet_length);
1667 int32_t ViEChannel::SetMTU(uint16_t mtu) {
1668 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
1670 if (rtp_rtcp_->SetMaxTransferUnit(mtu) != 0) {
1674 CriticalSectionScoped cs(rtp_rtcp_cs_.get());
1675 for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
1676 it != simulcast_rtp_rtcp_.end();
1678 RtpRtcp* rtp_rtcp = *it;
1679 rtp_rtcp->SetMaxTransferUnit(mtu);
1685 uint16_t ViEChannel::MaxDataPayloadLength() const {
1686 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
1687 "%s", __FUNCTION__);
1688 return rtp_rtcp_->MaxDataPayloadLength();
1691 int32_t ViEChannel::EnableColorEnhancement(bool enable) {
1692 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
1693 "%s(enable: %d)", __FUNCTION__, enable);
1695 CriticalSectionScoped cs(callback_cs_.get());
1696 color_enhancement_ = enable;
1700 RtpRtcp* ViEChannel::rtp_rtcp() {
1701 return rtp_rtcp_.get();
1704 CallStatsObserver* ViEChannel::GetStatsObserver() {
1705 return stats_observer_.get();
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());
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_);
1725 decoder_reset_ = false;
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());
1741 if (color_enhancement_) {
1742 VideoProcessingModule::ColorEnhancement(&video_frame);
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();
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);
1758 int32_t ViEChannel::ReceivedDecodedReferenceFrame(
1759 const uint64_t picture_id) {
1760 return rtp_rtcp_->SendRTCPReferencePictureSelection(picture_id);
1763 void ViEChannel::IncomingCodecChanged(const VideoCodec& codec) {
1764 CriticalSectionScoped cs(callback_cs_.get());
1765 receive_codec_ = codec;
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,
1775 codec_observer_->IncomingRate(channel_id_, frame_rate, bit_rate);
1780 void ViEChannel::OnDecoderTiming(int 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_)
1790 codec_observer_->DecoderTiming(decode_ms,
1795 min_playout_delay_ms,
1799 int32_t ViEChannel::RequestKeyFrame() {
1800 WEBRTC_TRACE(kTraceStream, kTraceVideo, ViEId(engine_id_, channel_id_),
1801 "%s", __FUNCTION__);
1803 CriticalSectionScoped cs(callback_cs_.get());
1804 if (codec_observer_ && do_key_frame_callbackRequest_) {
1805 codec_observer_->RequestNewKeyFrame(channel_id_);
1808 return rtp_rtcp_->RequestKeyFrame();
1811 int32_t ViEChannel::SliceLossIndicationRequest(
1812 const uint64_t picture_id) {
1813 return rtp_rtcp_->SendRTCPSliceLossIndication((uint8_t) picture_id);
1816 int32_t ViEChannel::ResendPackets(const uint16_t* sequence_numbers,
1818 WEBRTC_TRACE(kTraceStream, kTraceVideo, ViEId(engine_id_, channel_id_),
1819 "%s(length: %d)", __FUNCTION__, length);
1820 return rtp_rtcp_->SendNACK(sequence_numbers, length);
1823 bool ViEChannel::ChannelDecodeThreadFunction(void* obj) {
1824 return static_cast<ViEChannel*>(obj)->ChannelDecodeProcess();
1827 bool ViEChannel::ChannelDecodeProcess() {
1828 vcm_.Decode(kMaxDecodeWaitTimeMs);
1832 void ViEChannel::OnRttUpdate(uint32_t rtt) {
1833 vcm_.SetReceiveChannelParameters(rtt);
1836 int32_t ViEChannel::StartDecodeThread() {
1837 // Start the decode thread
1838 if (decode_thread_) {
1842 decode_thread_ = ThreadWrapper::CreateThread(ChannelDecodeThreadFunction,
1843 this, kHighestPriority,
1845 if (!decode_thread_) {
1846 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
1847 "%s: could not create decode thread", __FUNCTION__);
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__);
1860 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
1861 "%s: decode thread with id %u started", __FUNCTION__);
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__);
1872 decode_thread_->SetNotAlive();
1873 if (decode_thread_->Stop()) {
1874 delete decode_thread_;
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");
1881 decode_thread_ = NULL;
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_);
1891 if (ve_sync_interface) {
1892 // Register lip sync
1893 module_process_thread_.RegisterModule(&vie_sync_);
1895 module_process_thread_.DeRegisterModule(&vie_sync_);
1897 return vie_sync_.ConfigureSync(ve_channel_id,
1900 vie_receiver_.GetRtpReceiver());
1903 int32_t ViEChannel::VoiceChannel() {
1904 return vie_sync_.VoiceChannel();
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_);
1916 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
1917 "%s: deregister effect filter for device %d", __FUNCTION__,
1920 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
1921 "%s: register effect filter for device %d", __FUNCTION__,
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_);
1930 effect_filter_ = effect_filter;
1934 void ViEChannel::RegisterPreRenderCallback(
1935 I420FrameCallback* pre_render_callback) {
1936 CriticalSectionScoped cs(callback_cs_.get());
1937 pre_render_callback_ = pre_render_callback;
1940 void ViEChannel::RegisterPreDecodeImageCallback(
1941 EncodedImageCallback* pre_decode_callback) {
1942 CriticalSectionScoped cs(callback_cs_.get());
1943 vcm_.RegisterPreDecodeImageCallback(pre_decode_callback);
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);
1956 CriticalSectionScoped cs(callback_cs_.get());
1958 if (rtcp_observer_) {
1959 rtcp_observer_->OnApplicationDataReceived(
1960 channel_id_, sub_type, name, reinterpret_cast<const char*>(data),
1966 int32_t ViEChannel::OnInitializeDecoder(
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();
1978 CriticalSectionScoped cs(callback_cs_.get());
1979 decoder_reset_ = true;
1983 void ViEChannel::OnIncomingSSRCChanged(const int32_t id, const uint32_t ssrc) {
1984 if (channel_id_ != ChannelId(id)) {
1986 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
1987 "%s, incorrect id", __FUNCTION__, id);
1991 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
1992 "%s: %u", __FUNCTION__, ssrc);
1994 rtp_rtcp_->SetRemoteSSRC(ssrc);
1996 CriticalSectionScoped cs(callback_cs_.get());
1998 if (rtp_observer_) {
1999 rtp_observer_->IncomingSSRCChanged(channel_id_, ssrc);
2004 void ViEChannel::OnIncomingCSRCChanged(const int32_t id,
2005 const uint32_t CSRC,
2007 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
2008 "%s: %u added: %d", __FUNCTION__, CSRC, added);
2010 if (channel_id_ != ChannelId(id)) {
2012 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
2013 "%s, incorrect id", __FUNCTION__, id);
2017 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
2018 "%s: %u", __FUNCTION__, CSRC);
2020 CriticalSectionScoped cs(callback_cs_.get());
2022 if (rtp_observer_) {
2023 rtp_observer_->IncomingCSRCChanged(channel_id_, CSRC, added);
2028 void ViEChannel::ResetStatistics(uint32_t ssrc) {
2029 StreamStatistician* statistician =
2030 vie_receiver_.GetReceiveStatistics()->GetStatistician(ssrc);
2032 statistician->ResetStatistics();
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();
2042 (*it)->RegisterSendFrameCountObserver(observer);
2046 } // namespace webrtc