blob: b8f900273cf046f88b2936de5c37a4d2eebc52d0 [file] [log] [blame]
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001/*
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
pbos@webrtc.org281cff82013-05-17 13:44:48 +000011#include "webrtc/video_engine/vie_channel.h"
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000012
13#include <algorithm>
14#include <vector>
15
stefan@webrtc.org47f0c412013-12-04 10:24:26 +000016#include "webrtc/common.h"
pbos@webrtc.org281cff82013-05-17 13:44:48 +000017#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
stefan@webrtc.org47f0c412013-12-04 10:24:26 +000018#include "webrtc/experiments.h"
pbos@webrtc.org281cff82013-05-17 13:44:48 +000019#include "webrtc/modules/pacing/include/paced_sender.h"
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +000020#include "webrtc/modules/rtp_rtcp/interface/rtp_receiver.h"
pbos@webrtc.org281cff82013-05-17 13:44:48 +000021#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"
andrew@webrtc.org07e96da2012-10-31 05:22:11 +000025#include "webrtc/modules/video_render/include/video_render_defines.h"
pbos@webrtc.org281cff82013-05-17 13:44:48 +000026#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
mflodman@webrtc.org022615b2014-04-07 10:56:31 +000027#include "webrtc/system_wrappers/interface/logging.h"
pbos@webrtc.org281cff82013-05-17 13:44:48 +000028#include "webrtc/system_wrappers/interface/thread_wrapper.h"
pbos@webrtc.org281cff82013-05-17 13:44:48 +000029#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"
pbos@webrtc.org24e20892013-10-28 16:32:01 +000034#include "webrtc/frame_callback.h"
pbos@webrtc.org281cff82013-05-17 13:44:48 +000035#include "webrtc/video_engine/vie_defines.h"
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000036
37namespace webrtc {
38
39const int kMaxDecodeWaitTimeMs = 50;
40const int kInvalidRtpExtensionId = 0;
mikhal@webrtc.org16196642013-02-01 19:33:21 +000041static const int kMaxTargetDelayMs = 10000;
stefan@webrtc.org06ad3842013-05-07 19:16:33 +000042static const float kMaxIncompleteTimeMultiplier = 3.5f;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000043
stefan@webrtc.orgd1d198b2014-08-14 15:10:49 +000044namespace {
45
46RTCPReportBlock AggregateReportBlocks(
47 const std::vector<RTCPReportBlock>& report_blocks,
48 std::map<uint32_t, RTCPReportBlock>* prev_report_blocks) {
49 int fraction_lost_sum = 0;
50 int fl_seq_num_sum = 0;
51 int jitter_sum = 0;
52 int number_of_report_blocks = 0;
53 RTCPReportBlock aggregate;
54 std::vector<RTCPReportBlock>::const_iterator report_block =
55 report_blocks.begin();
56 for (; report_block != report_blocks.end(); ++report_block) {
57 aggregate.cumulativeLost += report_block->cumulativeLost;
58 std::map<uint32_t, RTCPReportBlock>::iterator prev_report_block =
59 prev_report_blocks->find(report_block->sourceSSRC);
60 if (prev_report_block != prev_report_blocks->end()) {
61 // Skip the first report block since we won't be able to get a correct
62 // weight for it.
63 int seq_num_diff = report_block->extendedHighSeqNum -
64 prev_report_block->second.extendedHighSeqNum;
65 if (seq_num_diff > 0) {
66 fraction_lost_sum += report_block->fractionLost * seq_num_diff;
67 fl_seq_num_sum += seq_num_diff;
68 }
69 }
70 jitter_sum += report_block->jitter;
71 ++number_of_report_blocks;
72 (*prev_report_blocks)[report_block->sourceSSRC] = *report_block;
73 }
74 if (fl_seq_num_sum > 0) {
75 aggregate.fractionLost =
76 (fraction_lost_sum + fl_seq_num_sum / 2) / fl_seq_num_sum;
77 }
78 if (number_of_report_blocks > 0) {
79 aggregate.jitter =
80 (jitter_sum + number_of_report_blocks / 2) / number_of_report_blocks;
81 }
82 // Not well defined for aggregated report blocks.
83 aggregate.extendedHighSeqNum = 0;
84 return aggregate;
85}
86} // namespace
87
mflodman@webrtc.org78696d32012-11-26 12:40:15 +000088// Helper class receiving statistics callbacks.
fischman@webrtc.org0329e592013-02-19 22:09:36 +000089class ChannelStatsObserver : public CallStatsObserver {
mflodman@webrtc.org78696d32012-11-26 12:40:15 +000090 public:
91 explicit ChannelStatsObserver(ViEChannel* owner) : owner_(owner) {}
92 virtual ~ChannelStatsObserver() {}
93
94 // Implements StatsObserver.
95 virtual void OnRttUpdate(uint32_t rtt) {
96 owner_->OnRttUpdate(rtt);
97 }
98
99 private:
100 ViEChannel* owner_;
101};
102
pbos@webrtc.org67879bc2013-04-09 13:41:51 +0000103ViEChannel::ViEChannel(int32_t channel_id,
104 int32_t engine_id,
105 uint32_t number_of_cores,
andresp@webrtc.orgac6d9192013-05-13 10:50:50 +0000106 const Config& config,
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000107 ProcessThread& module_process_thread,
108 RtcpIntraFrameObserver* intra_frame_observer,
109 RtcpBandwidthObserver* bandwidth_observer,
110 RemoteBitrateEstimator* remote_bitrate_estimator,
asapersson@webrtc.orgc4af4cf2013-11-20 12:46:11 +0000111 RtcpRttStats* rtt_stats,
pwestin@webrtc.org5e87b5f2012-11-13 21:12:39 +0000112 PacedSender* paced_sender,
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000113 RtpRtcp* default_rtp_rtcp,
114 bool sender)
115 : ViEFrameProviderBase(channel_id, engine_id),
116 channel_id_(channel_id),
117 engine_id_(engine_id),
118 number_of_cores_(number_of_cores),
119 num_socket_threads_(kViESocketThreads),
120 callback_cs_(CriticalSectionWrapper::CreateCriticalSection()),
121 rtp_rtcp_cs_(CriticalSectionWrapper::CreateCriticalSection()),
122 default_rtp_rtcp_(default_rtp_rtcp),
pbos@webrtc.org7f545612014-05-23 09:41:07 +0000123 vcm_(VideoCodingModule::Create()),
124 vie_receiver_(channel_id, vcm_, remote_bitrate_estimator, this),
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000125 vie_sender_(channel_id),
pbos@webrtc.org7f545612014-05-23 09:41:07 +0000126 vie_sync_(vcm_, this),
mflodman@webrtc.org78696d32012-11-26 12:40:15 +0000127 stats_observer_(new ChannelStatsObserver(this)),
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000128 module_process_thread_(module_process_thread),
129 codec_observer_(NULL),
130 do_key_frame_callbackRequest_(false),
131 rtp_observer_(NULL),
132 rtcp_observer_(NULL),
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000133 intra_frame_observer_(intra_frame_observer),
asapersson@webrtc.orgc4af4cf2013-11-20 12:46:11 +0000134 rtt_stats_(rtt_stats),
pwestin@webrtc.org5e87b5f2012-11-13 21:12:39 +0000135 paced_sender_(paced_sender),
stefan@webrtc.org6845de72014-06-11 13:41:36 +0000136 pad_with_redundant_payloads_(false),
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000137 bandwidth_observer_(bandwidth_observer),
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000138 send_timestamp_extension_id_(kInvalidRtpExtensionId),
solenberg@webrtc.org453f9c02013-05-20 12:00:23 +0000139 absolute_send_time_extension_id_(kInvalidRtpExtensionId),
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000140 external_transport_(NULL),
141 decoder_reset_(true),
142 wait_for_key_frame_(false),
143 decode_thread_(NULL),
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000144 effect_filter_(NULL),
145 color_enhancement_(false),
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000146 mtu_(0),
mikhal@webrtc.org16196642013-02-01 19:33:21 +0000147 sender_(sender),
mikhal@webrtc.org9d6fcb32013-02-15 23:22:18 +0000148 nack_history_size_sender_(kSendSidePacketHistorySize),
pbos@webrtc.org63301bd2013-10-21 10:34:43 +0000149 max_nack_reordering_threshold_(kMaxPacketAgeToNack),
stefan@webrtc.org6845de72014-06-11 13:41:36 +0000150 pre_render_callback_(NULL) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000151 RtpRtcp::Configuration configuration;
152 configuration.id = ViEModuleId(engine_id, channel_id);
153 configuration.audio = false;
154 configuration.default_module = default_rtp_rtcp;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000155 configuration.outgoing_transport = &vie_sender_;
156 configuration.rtcp_feedback = this;
157 configuration.intra_frame_callback = intra_frame_observer;
158 configuration.bandwidth_callback = bandwidth_observer;
asapersson@webrtc.orgc4af4cf2013-11-20 12:46:11 +0000159 configuration.rtt_stats = rtt_stats;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000160 configuration.remote_bitrate_estimator = remote_bitrate_estimator;
pwestin@webrtc.org5e87b5f2012-11-13 21:12:39 +0000161 configuration.paced_sender = paced_sender;
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +0000162 configuration.receive_statistics = vie_receiver_.GetReceiveStatistics();
andresp@webrtc.orgf8ec08e2014-07-08 14:32:58 +0000163 configuration.send_bitrate_observer = &send_bitrate_observer_;
andresp@webrtc.org8c95e832014-07-10 09:39:23 +0000164 configuration.send_frame_count_observer = &send_frame_count_observer_;
stefan@webrtc.org55b0f2e2014-07-11 13:44:02 +0000165 configuration.send_side_delay_observer = &send_side_delay_observer_;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000166
167 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(configuration));
168 vie_receiver_.SetRtpRtcpModule(rtp_rtcp_.get());
pbos@webrtc.org7f545612014-05-23 09:41:07 +0000169 vcm_->SetNackSettings(kMaxNackListSize, max_nack_reordering_threshold_, 0);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000170}
171
pbos@webrtc.org67879bc2013-04-09 13:41:51 +0000172int32_t ViEChannel::Init() {
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +0000173 if (module_process_thread_.RegisterModule(
174 vie_receiver_.GetReceiveStatistics()) != 0) {
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +0000175 return -1;
176 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000177 // RTP/RTCP initialization.
178 if (rtp_rtcp_->SetSendingMediaStatus(false) != 0) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000179 return -1;
180 }
181 if (module_process_thread_.RegisterModule(rtp_rtcp_.get()) != 0) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000182 return -1;
183 }
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000184 rtp_rtcp_->SetKeyFrameRequestMethod(kKeyFrameReqFirRtp);
185 rtp_rtcp_->SetRTCPStatus(kRtcpCompound);
pwestin@webrtc.org5e87b5f2012-11-13 21:12:39 +0000186 if (paced_sender_) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000187 rtp_rtcp_->SetStorePacketsStatus(true, nack_history_size_sender_);
pwestin@webrtc.org5e87b5f2012-11-13 21:12:39 +0000188 }
pbos@webrtc.org7f545612014-05-23 09:41:07 +0000189 if (vcm_->InitializeReceiver() != 0) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000190 return -1;
191 }
pbos@webrtc.org7f545612014-05-23 09:41:07 +0000192 if (vcm_->SetVideoProtection(kProtectionKeyOnLoss, true)) {
mflodman@webrtc.orgb4c89a42013-06-10 15:50:12 +0000193 return -1;
194 }
pbos@webrtc.org7f545612014-05-23 09:41:07 +0000195 if (vcm_->RegisterReceiveCallback(this) != 0) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000196 return -1;
197 }
pbos@webrtc.org7f545612014-05-23 09:41:07 +0000198 vcm_->RegisterFrameTypeCallback(this);
199 vcm_->RegisterReceiveStatisticsCallback(this);
200 vcm_->RegisterDecoderTimingCallback(this);
201 vcm_->SetRenderDelay(kViEDefaultRenderDelayMs);
202 if (module_process_thread_.RegisterModule(vcm_) != 0) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000203 return -1;
204 }
205#ifdef VIDEOCODEC_VP8
206 VideoCodec video_codec;
pbos@webrtc.org7f545612014-05-23 09:41:07 +0000207 if (vcm_->Codec(kVideoCodecVP8, &video_codec) == VCM_OK) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000208 rtp_rtcp_->RegisterSendPayload(video_codec);
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +0000209 // TODO(holmer): Can we call SetReceiveCodec() here instead?
210 if (!vie_receiver_.RegisterPayload(video_codec)) {
211 return -1;
212 }
pbos@webrtc.org7f545612014-05-23 09:41:07 +0000213 vcm_->RegisterReceiveCodec(&video_codec, number_of_cores_);
214 vcm_->RegisterSendCodec(&video_codec, number_of_cores_,
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000215 rtp_rtcp_->MaxDataPayloadLength());
216 } else {
217 assert(false);
218 }
219#endif
220
221 return 0;
222}
223
224ViEChannel::~ViEChannel() {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000225 // Make sure we don't get more callbacks from the RTP module.
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +0000226 module_process_thread_.DeRegisterModule(vie_receiver_.GetReceiveStatistics());
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000227 module_process_thread_.DeRegisterModule(rtp_rtcp_.get());
pbos@webrtc.org7f545612014-05-23 09:41:07 +0000228 module_process_thread_.DeRegisterModule(vcm_);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000229 module_process_thread_.DeRegisterModule(&vie_sync_);
230 while (simulcast_rtp_rtcp_.size() > 0) {
231 std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
232 RtpRtcp* rtp_rtcp = *it;
233 module_process_thread_.DeRegisterModule(rtp_rtcp);
234 delete rtp_rtcp;
235 simulcast_rtp_rtcp_.erase(it);
236 }
mflodman@webrtc.org55e6f582013-02-20 16:00:27 +0000237 while (removed_rtp_rtcp_.size() > 0) {
238 std::list<RtpRtcp*>::iterator it = removed_rtp_rtcp_.begin();
239 delete *it;
240 removed_rtp_rtcp_.erase(it);
241 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000242 if (decode_thread_) {
243 StopDecodeThread();
244 }
pwestin@webrtc.org912b7f72013-03-13 23:20:57 +0000245 // Release modules.
pbos@webrtc.org7f545612014-05-23 09:41:07 +0000246 VideoCodingModule::Destroy(vcm_);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000247}
248
pbos@webrtc.org67879bc2013-04-09 13:41:51 +0000249int32_t ViEChannel::SetSendCodec(const VideoCodec& video_codec,
250 bool new_stream) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000251 if (!sender_) {
252 return 0;
253 }
254 if (video_codec.codecType == kVideoCodecRED ||
255 video_codec.codecType == kVideoCodecULPFEC) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000256 LOG_F(LS_ERROR) << "Not a valid send codec " << video_codec.codecType;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000257 return -1;
258 }
259 if (kMaxSimulcastStreams < video_codec.numberOfSimulcastStreams) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000260 LOG_F(LS_ERROR) << "Incorrect config "
261 << video_codec.numberOfSimulcastStreams;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000262 return -1;
263 }
264 // Update the RTP module with the settings.
265 // Stop and Start the RTP module -> trigger new SSRC, if an SSRC hasn't been
266 // set explicitly.
267 bool restart_rtp = false;
268 if (rtp_rtcp_->Sending() && new_stream) {
269 restart_rtp = true;
270 rtp_rtcp_->SetSendingStatus(false);
mflodman@webrtc.org55e6f582013-02-20 16:00:27 +0000271 for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
272 it != simulcast_rtp_rtcp_.end(); ++it) {
273 (*it)->SetSendingStatus(false);
274 (*it)->SetSendingMediaStatus(false);
275 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000276 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000277
278 bool fec_enabled = false;
pbos@webrtc.org67879bc2013-04-09 13:41:51 +0000279 uint8_t payload_type_red;
280 uint8_t payload_type_fec;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000281 rtp_rtcp_->GenericFECStatus(fec_enabled, payload_type_red, payload_type_fec);
282
283 CriticalSectionScoped cs(rtp_rtcp_cs_.get());
284
285 if (video_codec.numberOfSimulcastStreams > 0) {
286 // Set correct bitrate to base layer.
287 // Create our simulcast RTP modules.
mflodman@webrtc.org55e6f582013-02-20 16:00:27 +0000288 int num_modules_to_add = video_codec.numberOfSimulcastStreams -
289 simulcast_rtp_rtcp_.size() - 1;
290 if (num_modules_to_add < 0) {
291 num_modules_to_add = 0;
292 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000293
pbos@webrtc.org88b558f2014-06-30 13:19:09 +0000294 // Add back removed rtp modules. Order is important (allocate from front of
295 // removed modules) to preserve RTP settings such as SSRCs for simulcast
296 // streams.
297 std::list<RtpRtcp*> new_rtp_modules;
298 for (; removed_rtp_rtcp_.size() > 0 && num_modules_to_add > 0;
299 --num_modules_to_add) {
300 new_rtp_modules.push_back(removed_rtp_rtcp_.front());
mflodman@webrtc.org55e6f582013-02-20 16:00:27 +0000301 removed_rtp_rtcp_.pop_front();
mflodman@webrtc.org55e6f582013-02-20 16:00:27 +0000302 }
303
pbos@webrtc.org88b558f2014-06-30 13:19:09 +0000304 for (int i = 0; i < num_modules_to_add; ++i)
305 new_rtp_modules.push_back(CreateRtpRtcpModule());
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000306
pbos@webrtc.org88b558f2014-06-30 13:19:09 +0000307 // Initialize newly added modules.
308 for (std::list<RtpRtcp*>::iterator it = new_rtp_modules.begin();
309 it != new_rtp_modules.end();
310 ++it) {
311 RtpRtcp* rtp_rtcp = *it;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000312
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000313 rtp_rtcp->SetRTCPStatus(rtp_rtcp_->RTCP());
stefan@webrtc.orga20e2d42013-08-21 20:58:21 +0000314
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +0000315 if (rtp_rtcp_->StorePackets()) {
tnakamura@webrtc.org0ba496b2013-07-16 19:25:04 +0000316 rtp_rtcp->SetStorePacketsStatus(true, nack_history_size_sender_);
tnakamura@webrtc.org0ba496b2013-07-16 19:25:04 +0000317 } else if (paced_sender_) {
318 rtp_rtcp->SetStorePacketsStatus(true, nack_history_size_sender_);
319 }
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +0000320
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000321 if (fec_enabled) {
pbos@webrtc.org88b558f2014-06-30 13:19:09 +0000322 rtp_rtcp->SetGenericFECStatus(
323 fec_enabled, payload_type_red, payload_type_fec);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000324 }
asapersson@webrtc.orgf4def772013-11-06 10:45:58 +0000325 rtp_rtcp->SetSendingStatus(rtp_rtcp_->Sending());
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000326 rtp_rtcp->SetSendingMediaStatus(rtp_rtcp_->SendingMedia());
pbos@webrtc.org88b558f2014-06-30 13:19:09 +0000327
pbos@webrtc.org65afbf32014-07-04 10:58:12 +0000328 int mode;
329 uint32_t ssrc;
330 int payload_type;
331 rtp_rtcp_->RTXSendStatus(&mode, &ssrc, &payload_type);
332 rtp_rtcp->SetRTXSendStatus(mode);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000333 simulcast_rtp_rtcp_.push_back(rtp_rtcp);
pbos@webrtc.org88b558f2014-06-30 13:19:09 +0000334
335 // Silently ignore error.
336 module_process_thread_.RegisterModule(rtp_rtcp);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000337 }
pbos@webrtc.org88b558f2014-06-30 13:19:09 +0000338
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000339 // Remove last in list if we have too many.
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000340 for (int j = simulcast_rtp_rtcp_.size();
341 j > (video_codec.numberOfSimulcastStreams - 1);
342 j--) {
343 RtpRtcp* rtp_rtcp = simulcast_rtp_rtcp_.back();
344 module_process_thread_.DeRegisterModule(rtp_rtcp);
mflodman@webrtc.org55e6f582013-02-20 16:00:27 +0000345 rtp_rtcp->SetSendingStatus(false);
346 rtp_rtcp->SetSendingMediaStatus(false);
sprang@webrtc.org9b30fd32013-12-05 09:48:44 +0000347 rtp_rtcp->RegisterSendChannelRtcpStatisticsCallback(NULL);
sprang@webrtc.orgb1139812013-12-05 14:29:02 +0000348 rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(NULL);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000349 simulcast_rtp_rtcp_.pop_back();
mflodman@webrtc.org55e6f582013-02-20 16:00:27 +0000350 removed_rtp_rtcp_.push_front(rtp_rtcp);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000351 }
pbos@webrtc.org67879bc2013-04-09 13:41:51 +0000352 uint8_t idx = 0;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000353 // Configure all simulcast modules.
354 for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
355 it != simulcast_rtp_rtcp_.end();
356 it++) {
357 idx++;
358 RtpRtcp* rtp_rtcp = *it;
359 rtp_rtcp->DeRegisterSendPayload(video_codec.plType);
360 if (rtp_rtcp->RegisterSendPayload(video_codec) != 0) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000361 return -1;
362 }
363 if (mtu_ != 0) {
364 rtp_rtcp->SetMaxTransferUnit(mtu_);
365 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000366 if (restart_rtp) {
367 rtp_rtcp->SetSendingStatus(true);
mflodman@webrtc.org55e6f582013-02-20 16:00:27 +0000368 rtp_rtcp->SetSendingMediaStatus(true);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000369 }
370 if (send_timestamp_extension_id_ != kInvalidRtpExtensionId) {
371 // Deregister in case the extension was previously enabled.
372 rtp_rtcp->DeregisterSendRtpHeaderExtension(
373 kRtpExtensionTransmissionTimeOffset);
374 if (rtp_rtcp->RegisterSendRtpHeaderExtension(
375 kRtpExtensionTransmissionTimeOffset,
376 send_timestamp_extension_id_) != 0) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000377 }
378 } else {
379 rtp_rtcp->DeregisterSendRtpHeaderExtension(
380 kRtpExtensionTransmissionTimeOffset);
381 }
solenberg@webrtc.org453f9c02013-05-20 12:00:23 +0000382 if (absolute_send_time_extension_id_ != kInvalidRtpExtensionId) {
383 // Deregister in case the extension was previously enabled.
384 rtp_rtcp->DeregisterSendRtpHeaderExtension(
385 kRtpExtensionAbsoluteSendTime);
386 if (rtp_rtcp->RegisterSendRtpHeaderExtension(
387 kRtpExtensionAbsoluteSendTime,
388 absolute_send_time_extension_id_) != 0) {
solenberg@webrtc.org453f9c02013-05-20 12:00:23 +0000389 }
390 } else {
391 rtp_rtcp->DeregisterSendRtpHeaderExtension(
392 kRtpExtensionAbsoluteSendTime);
393 }
sprang@webrtc.org9b30fd32013-12-05 09:48:44 +0000394 rtp_rtcp->RegisterSendChannelRtcpStatisticsCallback(
395 rtp_rtcp_->GetSendChannelRtcpStatisticsCallback());
sprang@webrtc.orgb1139812013-12-05 14:29:02 +0000396 rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(
397 rtp_rtcp_->GetSendChannelRtpStatisticsCallback());
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000398 }
399 // |RegisterSimulcastRtpRtcpModules| resets all old weak pointers and old
400 // modules can be deleted after this step.
401 vie_receiver_.RegisterSimulcastRtpRtcpModules(simulcast_rtp_rtcp_);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000402 } else {
mflodman@webrtc.org55e6f582013-02-20 16:00:27 +0000403 while (!simulcast_rtp_rtcp_.empty()) {
404 RtpRtcp* rtp_rtcp = simulcast_rtp_rtcp_.back();
405 module_process_thread_.DeRegisterModule(rtp_rtcp);
406 rtp_rtcp->SetSendingStatus(false);
407 rtp_rtcp->SetSendingMediaStatus(false);
sprang@webrtc.org9b30fd32013-12-05 09:48:44 +0000408 rtp_rtcp->RegisterSendChannelRtcpStatisticsCallback(NULL);
sprang@webrtc.orgb1139812013-12-05 14:29:02 +0000409 rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(NULL);
mflodman@webrtc.org55e6f582013-02-20 16:00:27 +0000410 simulcast_rtp_rtcp_.pop_back();
411 removed_rtp_rtcp_.push_front(rtp_rtcp);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000412 }
413 // Clear any previous modules.
414 vie_receiver_.RegisterSimulcastRtpRtcpModules(simulcast_rtp_rtcp_);
415 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000416
417 // Don't log this error, no way to check in advance if this pl_type is
418 // registered or not...
419 rtp_rtcp_->DeRegisterSendPayload(video_codec.plType);
420 if (rtp_rtcp_->RegisterSendPayload(video_codec) != 0) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000421 return -1;
422 }
423 if (restart_rtp) {
424 rtp_rtcp_->SetSendingStatus(true);
mflodman@webrtc.org55e6f582013-02-20 16:00:27 +0000425 for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
426 it != simulcast_rtp_rtcp_.end(); ++it) {
427 (*it)->SetSendingStatus(true);
428 (*it)->SetSendingMediaStatus(true);
429 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000430 }
431 return 0;
432}
433
pbos@webrtc.org67879bc2013-04-09 13:41:51 +0000434int32_t ViEChannel::SetReceiveCodec(const VideoCodec& video_codec) {
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +0000435 if (!vie_receiver_.SetReceiveCodec(video_codec)) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000436 return -1;
437 }
438
439 if (video_codec.codecType != kVideoCodecRED &&
440 video_codec.codecType != kVideoCodecULPFEC) {
441 // Register codec type with VCM, but do not register RED or ULPFEC.
pbos@webrtc.org7f545612014-05-23 09:41:07 +0000442 if (vcm_->RegisterReceiveCodec(&video_codec, number_of_cores_,
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000443 wait_for_key_frame_) != VCM_OK) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000444 return -1;
445 }
446 }
447 return 0;
448}
449
pbos@webrtc.org67879bc2013-04-09 13:41:51 +0000450int32_t ViEChannel::GetReceiveCodec(VideoCodec* video_codec) {
pbos@webrtc.org7f545612014-05-23 09:41:07 +0000451 if (vcm_->ReceiveCodec(video_codec) != 0) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000452 return -1;
453 }
454 return 0;
455}
456
pbos@webrtc.org67879bc2013-04-09 13:41:51 +0000457int32_t ViEChannel::RegisterCodecObserver(ViEDecoderObserver* observer) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000458 CriticalSectionScoped cs(callback_cs_.get());
459 if (observer) {
460 if (codec_observer_) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000461 LOG_F(LS_ERROR) << "Observer already registered.";
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000462 return -1;
463 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000464 codec_observer_ = observer;
465 } else {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000466 codec_observer_ = NULL;
467 }
468 return 0;
469}
470
pbos@webrtc.org67879bc2013-04-09 13:41:51 +0000471int32_t ViEChannel::RegisterExternalDecoder(const uint8_t pl_type,
472 VideoDecoder* decoder,
473 bool buffered_rendering,
474 int32_t render_delay) {
pbos@webrtc.org67879bc2013-04-09 13:41:51 +0000475 int32_t result;
pbos@webrtc.org7f545612014-05-23 09:41:07 +0000476 result = vcm_->RegisterExternalDecoder(decoder, pl_type, buffered_rendering);
pbos@webrtc.org208a6482013-04-09 00:34:42 +0000477 if (result != VCM_OK) {
pbos@webrtc.org208a6482013-04-09 00:34:42 +0000478 return result;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000479 }
pbos@webrtc.org7f545612014-05-23 09:41:07 +0000480 return vcm_->SetRenderDelay(render_delay);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000481}
482
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000483int32_t ViEChannel::DeRegisterExternalDecoder(const uint8_t pl_type) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000484 VideoCodec current_receive_codec;
pbos@webrtc.org67879bc2013-04-09 13:41:51 +0000485 int32_t result = 0;
pbos@webrtc.org7f545612014-05-23 09:41:07 +0000486 result = vcm_->ReceiveCodec(&current_receive_codec);
487 if (vcm_->RegisterExternalDecoder(NULL, pl_type, false) != VCM_OK) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000488 return -1;
489 }
490
491 if (result == 0 && current_receive_codec.plType == pl_type) {
pbos@webrtc.org7f545612014-05-23 09:41:07 +0000492 result = vcm_->RegisterReceiveCodec(
493 &current_receive_codec, number_of_cores_, wait_for_key_frame_);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000494 }
495 return result;
496}
497
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000498int32_t ViEChannel::ReceiveCodecStatistics(uint32_t* num_key_frames,
499 uint32_t* num_delta_frames) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000500 VCMFrameCount received_frames;
pbos@webrtc.org7f545612014-05-23 09:41:07 +0000501 if (vcm_->ReceivedFrameCount(received_frames) != VCM_OK) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000502 return -1;
503 }
504 *num_key_frames = received_frames.numKeyFrames;
505 *num_delta_frames = received_frames.numDeltaFrames;
506 return 0;
507}
508
pbos@webrtc.org67879bc2013-04-09 13:41:51 +0000509uint32_t ViEChannel::DiscardedPackets() const {
pbos@webrtc.org7f545612014-05-23 09:41:07 +0000510 return vcm_->DiscardedPackets();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000511}
512
mflodman@webrtc.orgf314c802012-12-14 14:02:10 +0000513int ViEChannel::ReceiveDelay() const {
pbos@webrtc.org7f545612014-05-23 09:41:07 +0000514 return vcm_->Delay();
mflodman@webrtc.orgf314c802012-12-14 14:02:10 +0000515}
516
pbos@webrtc.org67879bc2013-04-09 13:41:51 +0000517int32_t ViEChannel::WaitForKeyFrame(bool wait) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000518 wait_for_key_frame_ = wait;
519 return 0;
520}
521
pbos@webrtc.org67879bc2013-04-09 13:41:51 +0000522int32_t ViEChannel::SetSignalPacketLossStatus(bool enable,
mikhal@webrtc.orge9151742013-08-08 22:45:33 +0000523 bool only_key_frames) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000524 if (enable) {
525 if (only_key_frames) {
pbos@webrtc.org7f545612014-05-23 09:41:07 +0000526 vcm_->SetVideoProtection(kProtectionKeyOnLoss, false);
527 if (vcm_->SetVideoProtection(kProtectionKeyOnKeyLoss, true) != VCM_OK) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000528 return -1;
529 }
530 } else {
pbos@webrtc.org7f545612014-05-23 09:41:07 +0000531 vcm_->SetVideoProtection(kProtectionKeyOnKeyLoss, false);
532 if (vcm_->SetVideoProtection(kProtectionKeyOnLoss, true) != VCM_OK) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000533 return -1;
534 }
535 }
536 } else {
pbos@webrtc.org7f545612014-05-23 09:41:07 +0000537 vcm_->SetVideoProtection(kProtectionKeyOnLoss, false);
538 vcm_->SetVideoProtection(kProtectionKeyOnKeyLoss, false);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000539 }
540 return 0;
541}
542
pbos@webrtc.org67879bc2013-04-09 13:41:51 +0000543int32_t ViEChannel::SetRTCPMode(const RTCPMethod rtcp_mode) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000544 CriticalSectionScoped cs(rtp_rtcp_cs_.get());
545 for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
546 it != simulcast_rtp_rtcp_.end();
547 it++) {
548 RtpRtcp* rtp_rtcp = *it;
549 rtp_rtcp->SetRTCPStatus(rtcp_mode);
550 }
551 return rtp_rtcp_->SetRTCPStatus(rtcp_mode);
552}
553
pbos@webrtc.org67879bc2013-04-09 13:41:51 +0000554int32_t ViEChannel::GetRTCPMode(RTCPMethod* rtcp_mode) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000555 *rtcp_mode = rtp_rtcp_->RTCP();
556 return 0;
557}
558
pbos@webrtc.org67879bc2013-04-09 13:41:51 +0000559int32_t ViEChannel::SetNACKStatus(const bool enable) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000560 // Update the decoding VCM.
pbos@webrtc.org7f545612014-05-23 09:41:07 +0000561 if (vcm_->SetVideoProtection(kProtectionNack, enable) != VCM_OK) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000562 return -1;
563 }
564 if (enable) {
565 // Disable possible FEC.
566 SetFECStatus(false, 0, 0);
567 }
568 // Update the decoding VCM.
pbos@webrtc.org7f545612014-05-23 09:41:07 +0000569 if (vcm_->SetVideoProtection(kProtectionNack, enable) != VCM_OK) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000570 return -1;
571 }
572 return ProcessNACKRequest(enable);
573}
574
pbos@webrtc.org67879bc2013-04-09 13:41:51 +0000575int32_t ViEChannel::ProcessNACKRequest(const bool enable) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000576 if (enable) {
577 // Turn on NACK.
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000578 if (rtp_rtcp_->RTCP() == kRtcpOff) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000579 return -1;
580 }
stefan@webrtc.orgdb74c612013-09-06 13:40:11 +0000581 vie_receiver_.SetNackStatus(true, max_nack_reordering_threshold_);
mikhal@webrtc.org16196642013-02-01 19:33:21 +0000582 rtp_rtcp_->SetStorePacketsStatus(true, nack_history_size_sender_);
pbos@webrtc.org7f545612014-05-23 09:41:07 +0000583 vcm_->RegisterPacketRequestCallback(this);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000584
585 CriticalSectionScoped cs(rtp_rtcp_cs_.get());
586
587 for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
588 it != simulcast_rtp_rtcp_.end();
589 it++) {
590 RtpRtcp* rtp_rtcp = *it;
mikhal@webrtc.org16196642013-02-01 19:33:21 +0000591 rtp_rtcp->SetStorePacketsStatus(true, nack_history_size_sender_);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000592 }
mikhal@webrtc.orge9151742013-08-08 22:45:33 +0000593 // Don't introduce errors when NACK is enabled.
pbos@webrtc.org7f545612014-05-23 09:41:07 +0000594 vcm_->SetDecodeErrorMode(kNoErrors);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000595 } else {
596 CriticalSectionScoped cs(rtp_rtcp_cs_.get());
597 for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
598 it != simulcast_rtp_rtcp_.end();
599 it++) {
600 RtpRtcp* rtp_rtcp = *it;
pwestin@webrtc.org5e87b5f2012-11-13 21:12:39 +0000601 if (paced_sender_ == NULL) {
602 rtp_rtcp->SetStorePacketsStatus(false, 0);
603 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000604 }
pbos@webrtc.org7f545612014-05-23 09:41:07 +0000605 vcm_->RegisterPacketRequestCallback(NULL);
pwestin@webrtc.org5e87b5f2012-11-13 21:12:39 +0000606 if (paced_sender_ == NULL) {
607 rtp_rtcp_->SetStorePacketsStatus(false, 0);
608 }
stefan@webrtc.orgdb74c612013-09-06 13:40:11 +0000609 vie_receiver_.SetNackStatus(false, max_nack_reordering_threshold_);
mikhal@webrtc.orge9151742013-08-08 22:45:33 +0000610 // When NACK is off, allow decoding with errors. Otherwise, the video
611 // will freeze, and will only recover with a complete key frame.
pbos@webrtc.org7f545612014-05-23 09:41:07 +0000612 vcm_->SetDecodeErrorMode(kWithErrors);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000613 }
614 return 0;
615}
616
pbos@webrtc.org67879bc2013-04-09 13:41:51 +0000617int32_t ViEChannel::SetFECStatus(const bool enable,
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000618 const unsigned char payload_typeRED,
619 const unsigned char payload_typeFEC) {
620 // Disable possible NACK.
621 if (enable) {
622 SetNACKStatus(false);
623 }
624
625 return ProcessFECRequest(enable, payload_typeRED, payload_typeFEC);
626}
627
pbos@webrtc.org67879bc2013-04-09 13:41:51 +0000628int32_t ViEChannel::ProcessFECRequest(
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000629 const bool enable,
630 const unsigned char payload_typeRED,
631 const unsigned char payload_typeFEC) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000632 if (rtp_rtcp_->SetGenericFECStatus(enable, payload_typeRED,
633 payload_typeFEC) != 0) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000634 return -1;
635 }
636 CriticalSectionScoped cs(rtp_rtcp_cs_.get());
637 for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
638 it != simulcast_rtp_rtcp_.end();
639 it++) {
640 RtpRtcp* rtp_rtcp = *it;
641 rtp_rtcp->SetGenericFECStatus(enable, payload_typeRED, payload_typeFEC);
642 }
643 return 0;
644}
645
pbos@webrtc.org67879bc2013-04-09 13:41:51 +0000646int32_t ViEChannel::SetHybridNACKFECStatus(
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000647 const bool enable,
648 const unsigned char payload_typeRED,
649 const unsigned char payload_typeFEC) {
pbos@webrtc.org7f545612014-05-23 09:41:07 +0000650 if (vcm_->SetVideoProtection(kProtectionNackFEC, enable) != VCM_OK) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000651 return -1;
652 }
653
pbos@webrtc.org67879bc2013-04-09 13:41:51 +0000654 int32_t ret_val = 0;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000655 ret_val = ProcessNACKRequest(enable);
656 if (ret_val < 0) {
657 return ret_val;
658 }
659 return ProcessFECRequest(enable, payload_typeRED, payload_typeFEC);
660}
661
mikhal@webrtc.org9d6fcb32013-02-15 23:22:18 +0000662int ViEChannel::SetSenderBufferingMode(int target_delay_ms) {
mikhal@webrtc.org16196642013-02-01 19:33:21 +0000663 if ((target_delay_ms < 0) || (target_delay_ms > kMaxTargetDelayMs)) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000664 LOG(LS_ERROR) << "Invalid send buffer value.";
mikhal@webrtc.org16196642013-02-01 19:33:21 +0000665 return -1;
666 }
667 if (target_delay_ms == 0) {
668 // Real-time mode.
669 nack_history_size_sender_ = kSendSidePacketHistorySize;
mikhal@webrtc.org16196642013-02-01 19:33:21 +0000670 } else {
mikhal@webrtc.org9d6fcb32013-02-15 23:22:18 +0000671 nack_history_size_sender_ = GetRequiredNackListSize(target_delay_ms);
mikhal@webrtc.org16196642013-02-01 19:33:21 +0000672 // Don't allow a number lower than the default value.
673 if (nack_history_size_sender_ < kSendSidePacketHistorySize) {
674 nack_history_size_sender_ = kSendSidePacketHistorySize;
675 }
mikhal@webrtc.org16196642013-02-01 19:33:21 +0000676 }
mikhal@webrtc.org16196642013-02-01 19:33:21 +0000677 if (rtp_rtcp_->SetStorePacketsStatus(true, nack_history_size_sender_) != 0) {
mikhal@webrtc.org16196642013-02-01 19:33:21 +0000678 return -1;
679 }
680 return 0;
681}
682
mikhal@webrtc.org9d6fcb32013-02-15 23:22:18 +0000683int ViEChannel::SetReceiverBufferingMode(int target_delay_ms) {
684 if ((target_delay_ms < 0) || (target_delay_ms > kMaxTargetDelayMs)) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000685 LOG(LS_ERROR) << "Invalid receive buffer delay value.";
mikhal@webrtc.org9d6fcb32013-02-15 23:22:18 +0000686 return -1;
687 }
688 int max_nack_list_size;
stefan@webrtc.org06ad3842013-05-07 19:16:33 +0000689 int max_incomplete_time_ms;
mikhal@webrtc.org9d6fcb32013-02-15 23:22:18 +0000690 if (target_delay_ms == 0) {
691 // Real-time mode - restore default settings.
692 max_nack_reordering_threshold_ = kMaxPacketAgeToNack;
693 max_nack_list_size = kMaxNackListSize;
stefan@webrtc.org06ad3842013-05-07 19:16:33 +0000694 max_incomplete_time_ms = 0;
mikhal@webrtc.org9d6fcb32013-02-15 23:22:18 +0000695 } else {
mikhal@webrtc.org08998cd2013-02-19 19:42:35 +0000696 max_nack_list_size = 3 * GetRequiredNackListSize(target_delay_ms) / 4;
mikhal@webrtc.org9d6fcb32013-02-15 23:22:18 +0000697 max_nack_reordering_threshold_ = max_nack_list_size;
stefan@webrtc.org06ad3842013-05-07 19:16:33 +0000698 // Calculate the max incomplete time and round to int.
699 max_incomplete_time_ms = static_cast<int>(kMaxIncompleteTimeMultiplier *
700 target_delay_ms + 0.5f);
mikhal@webrtc.org9d6fcb32013-02-15 23:22:18 +0000701 }
pbos@webrtc.org7f545612014-05-23 09:41:07 +0000702 vcm_->SetNackSettings(max_nack_list_size, max_nack_reordering_threshold_,
stefan@webrtc.org06ad3842013-05-07 19:16:33 +0000703 max_incomplete_time_ms);
pbos@webrtc.org7f545612014-05-23 09:41:07 +0000704 vcm_->SetMinReceiverDelay(target_delay_ms);
mikhal@webrtc.org78e450f2013-03-06 23:29:33 +0000705 if (vie_sync_.SetTargetBufferingDelay(target_delay_ms) < 0)
706 return -1;
mikhal@webrtc.org9d6fcb32013-02-15 23:22:18 +0000707 return 0;
708}
709
710int ViEChannel::GetRequiredNackListSize(int target_delay_ms) {
711 // The max size of the nack list should be large enough to accommodate the
712 // the number of packets (frames) resulting from the increased delay.
mikhal@webrtc.orgb793abe2013-03-13 20:52:49 +0000713 // Roughly estimating for ~40 packets per frame @ 30fps.
714 return target_delay_ms * 40 * 30 / 1000;
mikhal@webrtc.org9d6fcb32013-02-15 23:22:18 +0000715}
716
pbos@webrtc.org67879bc2013-04-09 13:41:51 +0000717int32_t ViEChannel::SetKeyFrameRequestMethod(
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000718 const KeyFrameRequestMethod method) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000719 return rtp_rtcp_->SetKeyFrameRequestMethod(method);
720}
721
722bool ViEChannel::EnableRemb(bool enable) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000723 if (rtp_rtcp_->SetREMBStatus(enable) != 0)
724 return false;
725 return true;
726}
727
728int ViEChannel::SetSendTimestampOffsetStatus(bool enable, int id) {
729 CriticalSectionScoped cs(rtp_rtcp_cs_.get());
730 int error = 0;
731 if (enable) {
732 // Enable the extension, but disable possible old id to avoid errors.
733 send_timestamp_extension_id_ = id;
734 rtp_rtcp_->DeregisterSendRtpHeaderExtension(
735 kRtpExtensionTransmissionTimeOffset);
736 error = rtp_rtcp_->RegisterSendRtpHeaderExtension(
737 kRtpExtensionTransmissionTimeOffset, id);
738 for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
739 it != simulcast_rtp_rtcp_.end(); it++) {
740 (*it)->DeregisterSendRtpHeaderExtension(
741 kRtpExtensionTransmissionTimeOffset);
742 error |= (*it)->RegisterSendRtpHeaderExtension(
743 kRtpExtensionTransmissionTimeOffset, id);
744 }
745 } else {
746 // Disable the extension.
747 send_timestamp_extension_id_ = kInvalidRtpExtensionId;
748 rtp_rtcp_->DeregisterSendRtpHeaderExtension(
749 kRtpExtensionTransmissionTimeOffset);
750 for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
751 it != simulcast_rtp_rtcp_.end(); it++) {
752 (*it)->DeregisterSendRtpHeaderExtension(
753 kRtpExtensionTransmissionTimeOffset);
754 }
755 }
756 return error;
757}
758
759int ViEChannel::SetReceiveTimestampOffsetStatus(bool enable, int id) {
stefan@webrtc.org4e5f9832013-05-29 13:28:21 +0000760 return vie_receiver_.SetReceiveTimestampOffsetStatus(enable, id) ? 0 : -1;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000761}
762
solenberg@webrtc.org453f9c02013-05-20 12:00:23 +0000763int ViEChannel::SetSendAbsoluteSendTimeStatus(bool enable, int id) {
764 CriticalSectionScoped cs(rtp_rtcp_cs_.get());
765 int error = 0;
766 if (enable) {
767 // Enable the extension, but disable possible old id to avoid errors.
768 absolute_send_time_extension_id_ = id;
769 rtp_rtcp_->DeregisterSendRtpHeaderExtension(
770 kRtpExtensionAbsoluteSendTime);
771 error = rtp_rtcp_->RegisterSendRtpHeaderExtension(
772 kRtpExtensionAbsoluteSendTime, id);
773 for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
774 it != simulcast_rtp_rtcp_.end(); it++) {
775 (*it)->DeregisterSendRtpHeaderExtension(
776 kRtpExtensionAbsoluteSendTime);
777 error |= (*it)->RegisterSendRtpHeaderExtension(
778 kRtpExtensionAbsoluteSendTime, id);
779 }
780 } else {
781 // Disable the extension.
782 absolute_send_time_extension_id_ = kInvalidRtpExtensionId;
783 rtp_rtcp_->DeregisterSendRtpHeaderExtension(
784 kRtpExtensionAbsoluteSendTime);
785 for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
786 it != simulcast_rtp_rtcp_.end(); it++) {
787 (*it)->DeregisterSendRtpHeaderExtension(
788 kRtpExtensionAbsoluteSendTime);
789 }
790 }
791 return error;
792}
793
794int ViEChannel::SetReceiveAbsoluteSendTimeStatus(bool enable, int id) {
stefan@webrtc.org4e5f9832013-05-29 13:28:21 +0000795 return vie_receiver_.SetReceiveAbsoluteSendTimeStatus(enable, id) ? 0 : -1;
solenberg@webrtc.orgf40e9b62013-05-27 16:02:56 +0000796}
797
asapersson@webrtc.org3dc7ff32013-11-21 08:57:04 +0000798void ViEChannel::SetRtcpXrRrtrStatus(bool enable) {
799 CriticalSectionScoped cs(rtp_rtcp_cs_.get());
800 rtp_rtcp_->SetRtcpXrRrtrStatus(enable);
asapersson@webrtc.org3dc7ff32013-11-21 08:57:04 +0000801}
802
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000803void ViEChannel::SetTransmissionSmoothingStatus(bool enable) {
pwestin@webrtc.org5e87b5f2012-11-13 21:12:39 +0000804 assert(paced_sender_ && "No paced sender registered.");
805 paced_sender_->SetStatus(enable);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000806}
807
pbos@webrtc.org67879bc2013-04-09 13:41:51 +0000808int32_t ViEChannel::EnableTMMBR(const bool enable) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000809 return rtp_rtcp_->SetTMMBRStatus(enable);
810}
811
pbos@webrtc.org67879bc2013-04-09 13:41:51 +0000812int32_t ViEChannel::EnableKeyFrameRequestCallback(const bool enable) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000813
814 CriticalSectionScoped cs(callback_cs_.get());
815 if (enable && !codec_observer_) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000816 LOG(LS_ERROR) << "No ViECodecObserver set.";
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000817 return -1;
818 }
819 do_key_frame_callbackRequest_ = enable;
820 return 0;
821}
822
pbos@webrtc.org67879bc2013-04-09 13:41:51 +0000823int32_t ViEChannel::SetSSRC(const uint32_t SSRC,
stefan@webrtc.org695ff2a2013-06-04 09:36:56 +0000824 const StreamType usage,
825 const uint8_t simulcast_idx) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000826 CriticalSectionScoped cs(rtp_rtcp_cs_.get());
pbos@webrtc.org88b558f2014-06-30 13:19:09 +0000827 ReserveRtpRtcpModules(simulcast_idx + 1);
828 RtpRtcp* rtp_rtcp = GetRtpRtcpModule(simulcast_idx);
829 if (rtp_rtcp == NULL)
830 return -1;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000831 if (usage == kViEStreamTypeRtx) {
pbos@webrtc.org88b558f2014-06-30 13:19:09 +0000832 rtp_rtcp->SetRtxSsrc(SSRC);
stefan@webrtc.org903e7462014-06-05 08:25:29 +0000833 } else {
pbos@webrtc.org88b558f2014-06-30 13:19:09 +0000834 rtp_rtcp->SetSSRC(SSRC);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000835 }
stefan@webrtc.org903e7462014-06-05 08:25:29 +0000836 return 0;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000837}
838
pbos@webrtc.org67879bc2013-04-09 13:41:51 +0000839int32_t ViEChannel::SetRemoteSSRCType(const StreamType usage,
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +0000840 const uint32_t SSRC) {
stefan@webrtc.org903e7462014-06-05 08:25:29 +0000841 vie_receiver_.SetRtxSsrc(SSRC);
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +0000842 return 0;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000843}
844
pbos@webrtc.org67879bc2013-04-09 13:41:51 +0000845int32_t ViEChannel::GetLocalSSRC(uint8_t idx, unsigned int* ssrc) {
mflodman@webrtc.orgb6d9cfc2012-10-25 11:30:29 +0000846 CriticalSectionScoped cs(rtp_rtcp_cs_.get());
pbos@webrtc.org88b558f2014-06-30 13:19:09 +0000847 RtpRtcp* rtp_rtcp = GetRtpRtcpModule(idx);
848 if (rtp_rtcp == NULL)
mflodman@webrtc.orgb6d9cfc2012-10-25 11:30:29 +0000849 return -1;
pbos@webrtc.org88b558f2014-06-30 13:19:09 +0000850 *ssrc = rtp_rtcp->SSRC();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000851 return 0;
852}
853
pbos@webrtc.org67879bc2013-04-09 13:41:51 +0000854int32_t ViEChannel::GetRemoteSSRC(uint32_t* ssrc) {
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +0000855 *ssrc = vie_receiver_.GetRemoteSsrc();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000856 return 0;
857}
858
pbos@webrtc.org67879bc2013-04-09 13:41:51 +0000859int32_t ViEChannel::GetRemoteCSRC(uint32_t CSRCs[kRtpCsrcSize]) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000860 uint32_t arrayCSRC[kRtpCsrcSize];
861 memset(arrayCSRC, 0, sizeof(arrayCSRC));
862
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +0000863 int num_csrcs = vie_receiver_.GetCsrcs(arrayCSRC);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000864 if (num_csrcs > 0) {
pbos@webrtc.org67879bc2013-04-09 13:41:51 +0000865 memcpy(CSRCs, arrayCSRC, num_csrcs * sizeof(uint32_t));
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000866 }
867 return 0;
868}
869
stefan@webrtc.org6845de72014-06-11 13:41:36 +0000870void ViEChannel::SetPadWithRedundantPayloads(bool enable) {
871 {
872 CriticalSectionScoped cs(callback_cs_.get());
873 pad_with_redundant_payloads_ = enable;
874 }
875 int mode;
876 uint32_t ssrc;
877 int payload_type;
878 rtp_rtcp_->RTXSendStatus(&mode, &ssrc, &payload_type);
879 if (mode != kRtxOff) {
880 // Since RTX was already enabled we have to reset it with payload-based
881 // padding on.
882 SetRtxSendStatus(true);
883 }
884}
885
mflodman@webrtc.org7bc7e022013-04-12 14:55:46 +0000886int ViEChannel::SetRtxSendPayloadType(int payload_type) {
mflodman@webrtc.org7bc7e022013-04-12 14:55:46 +0000887 rtp_rtcp_->SetRtxSendPayloadType(payload_type);
stefan@webrtc.org6845de72014-06-11 13:41:36 +0000888 for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
889 it != simulcast_rtp_rtcp_.end(); it++) {
890 (*it)->SetRtxSendPayloadType(payload_type);
891 }
892 SetRtxSendStatus(true);
893 return 0;
894}
895
896void ViEChannel::SetRtxSendStatus(bool enable) {
897 int rtx_settings = kRtxOff;
898 if (enable) {
899 CriticalSectionScoped cs(callback_cs_.get());
900 rtx_settings = kRtxRetransmitted;
901 if (pad_with_redundant_payloads_)
902 rtx_settings |= kRtxRedundantPayloads;
903 }
stefan@webrtc.org903e7462014-06-05 08:25:29 +0000904 rtp_rtcp_->SetRTXSendStatus(rtx_settings);
mflodman@webrtc.org7bc7e022013-04-12 14:55:46 +0000905 CriticalSectionScoped cs(rtp_rtcp_cs_.get());
906 for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
907 it != simulcast_rtp_rtcp_.end(); it++) {
stefan@webrtc.org903e7462014-06-05 08:25:29 +0000908 (*it)->SetRTXSendStatus(rtx_settings);
mflodman@webrtc.org7bc7e022013-04-12 14:55:46 +0000909 }
mflodman@webrtc.org7bc7e022013-04-12 14:55:46 +0000910}
911
912void ViEChannel::SetRtxReceivePayloadType(int payload_type) {
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +0000913 vie_receiver_.SetRtxPayloadType(payload_type);
mflodman@webrtc.org7bc7e022013-04-12 14:55:46 +0000914}
915
916int32_t ViEChannel::SetStartSequenceNumber(uint16_t sequence_number) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000917 if (rtp_rtcp_->Sending()) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000918 return -1;
919 }
920 return rtp_rtcp_->SetSequenceNumber(sequence_number);
921}
922
pbos@webrtc.org2fd91bd2014-07-07 13:06:48 +0000923void ViEChannel::SetRtpStateForSsrc(uint32_t ssrc, const RtpState& rtp_state) {
924 assert(!rtp_rtcp_->Sending());
925 default_rtp_rtcp_->SetRtpStateForSsrc(ssrc, rtp_state);
926}
927
928RtpState ViEChannel::GetRtpStateForSsrc(uint32_t ssrc) {
929 assert(!rtp_rtcp_->Sending());
930
931 RtpState rtp_state;
932 if (!default_rtp_rtcp_->GetRtpStateForSsrc(ssrc, &rtp_state)) {
933 LOG(LS_ERROR) << "Couldn't get RTP state for ssrc: " << ssrc;
934 }
935 return rtp_state;
936}
937
pbos@webrtc.org67879bc2013-04-09 13:41:51 +0000938int32_t ViEChannel::SetRTCPCName(const char rtcp_cname[]) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000939 if (rtp_rtcp_->Sending()) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000940 return -1;
941 }
942 return rtp_rtcp_->SetCNAME(rtcp_cname);
943}
944
pbos@webrtc.org67879bc2013-04-09 13:41:51 +0000945int32_t ViEChannel::GetRemoteRTCPCName(char rtcp_cname[]) {
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +0000946 uint32_t remoteSSRC = vie_receiver_.GetRemoteSsrc();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000947 return rtp_rtcp_->RemoteCNAME(remoteSSRC, rtcp_cname);
948}
949
pbos@webrtc.org67879bc2013-04-09 13:41:51 +0000950int32_t ViEChannel::RegisterRtpObserver(ViERTPObserver* observer) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000951 CriticalSectionScoped cs(callback_cs_.get());
952 if (observer) {
953 if (rtp_observer_) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000954 LOG_F(LS_ERROR) << "Observer already registered.";
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000955 return -1;
956 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000957 rtp_observer_ = observer;
958 } else {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000959 rtp_observer_ = NULL;
960 }
961 return 0;
962}
963
pbos@webrtc.org67879bc2013-04-09 13:41:51 +0000964int32_t ViEChannel::RegisterRtcpObserver(ViERTCPObserver* observer) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000965 CriticalSectionScoped cs(callback_cs_.get());
966 if (observer) {
967 if (rtcp_observer_) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000968 LOG_F(LS_ERROR) << "Observer already registered.";
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000969 return -1;
970 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000971 rtcp_observer_ = observer;
972 } else {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000973 rtcp_observer_ = NULL;
974 }
975 return 0;
976}
977
pbos@webrtc.org67879bc2013-04-09 13:41:51 +0000978int32_t ViEChannel::SendApplicationDefinedRTCPPacket(
979 const uint8_t sub_type,
980 uint32_t name,
981 const uint8_t* data,
982 uint16_t data_length_in_bytes) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000983 if (!rtp_rtcp_->Sending()) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000984 return -1;
985 }
986 if (!data) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000987 LOG_F(LS_ERROR) << "Invalid input.";
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000988 return -1;
989 }
990 if (data_length_in_bytes % 4 != 0) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000991 LOG(LS_ERROR) << "Invalid input length.";
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000992 return -1;
993 }
994 RTCPMethod rtcp_method = rtp_rtcp_->RTCP();
995 if (rtcp_method == kRtcpOff) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000996 LOG_F(LS_ERROR) << "RTCP not enable.";
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000997 return -1;
998 }
999 // Create and send packet.
1000 if (rtp_rtcp_->SetRTCPApplicationSpecificData(sub_type, name, data,
1001 data_length_in_bytes) != 0) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001002 return -1;
1003 }
1004 return 0;
1005}
1006
pbos@webrtc.org67879bc2013-04-09 13:41:51 +00001007int32_t ViEChannel::GetSendRtcpStatistics(uint16_t* fraction_lost,
stefan@webrtc.orgdb74c612013-09-06 13:40:11 +00001008 uint32_t* cumulative_lost,
1009 uint32_t* extended_max,
1010 uint32_t* jitter_samples,
1011 int32_t* rtt_ms) {
stefan@webrtc.orgd1d198b2014-08-14 15:10:49 +00001012 // Aggregate the report blocks associated with streams sent on this channel.
1013 std::vector<RTCPReportBlock> report_blocks;
1014 rtp_rtcp_->RemoteRTCPStat(&report_blocks);
1015 for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
1016 it != simulcast_rtp_rtcp_.end();
1017 ++it) {
1018 (*it)->RemoteRTCPStat(&report_blocks);
1019 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001020
stefan@webrtc.orgd1d198b2014-08-14 15:10:49 +00001021 if (report_blocks.empty())
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001022 return -1;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001023
stefan@webrtc.orgd1d198b2014-08-14 15:10:49 +00001024 RTCPReportBlock report;
1025 if (report_blocks.size() > 1)
1026 report = AggregateReportBlocks(report_blocks, &prev_report_blocks_);
1027 else
1028 report = report_blocks[0];
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001029
stefan@webrtc.orgd1d198b2014-08-14 15:10:49 +00001030 *fraction_lost = report.fractionLost;
1031 *cumulative_lost = report.cumulativeLost;
1032 *extended_max = report.extendedHighSeqNum;
1033 *jitter_samples = report.jitter;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001034
pbos@webrtc.org67879bc2013-04-09 13:41:51 +00001035 uint16_t dummy;
1036 uint16_t rtt = 0;
stefan@webrtc.orgd1d198b2014-08-14 15:10:49 +00001037 if (rtp_rtcp_->RTT(
1038 vie_receiver_.GetRemoteSsrc(), &rtt, &dummy, &dummy, &dummy) != 0) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001039 return -1;
1040 }
1041 *rtt_ms = rtt;
1042 return 0;
1043}
1044
sprang@webrtc.org9b30fd32013-12-05 09:48:44 +00001045void ViEChannel::RegisterSendChannelRtcpStatisticsCallback(
1046 RtcpStatisticsCallback* callback) {
sprang@webrtc.org9b30fd32013-12-05 09:48:44 +00001047 rtp_rtcp_->RegisterSendChannelRtcpStatisticsCallback(callback);
1048 CriticalSectionScoped cs(rtp_rtcp_cs_.get());
1049 for (std::list<RtpRtcp*>::const_iterator it = simulcast_rtp_rtcp_.begin();
1050 it != simulcast_rtp_rtcp_.end();
1051 ++it) {
1052 (*it)->RegisterSendChannelRtcpStatisticsCallback(callback);
1053 }
1054}
1055
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00001056// TODO(holmer): This is a bad function name as it implies that it returns the
1057// received RTCP, while it actually returns the statistics which will be sent
1058// in the RTCP.
pbos@webrtc.org67879bc2013-04-09 13:41:51 +00001059int32_t ViEChannel::GetReceivedRtcpStatistics(uint16_t* fraction_lost,
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00001060 uint32_t* cumulative_lost,
1061 uint32_t* extended_max,
1062 uint32_t* jitter_samples,
1063 int32_t* rtt_ms) {
stefan@webrtc.orga20e2d42013-08-21 20:58:21 +00001064 uint32_t remote_ssrc = vie_receiver_.GetRemoteSsrc();
stefan@webrtc.orga20e2d42013-08-21 20:58:21 +00001065 StreamStatistician* statistician =
1066 vie_receiver_.GetReceiveStatistics()->GetStatistician(remote_ssrc);
sprang@webrtc.org4f1f5fa2013-12-19 13:26:02 +00001067 RtcpStatistics receive_stats;
stefan@webrtc.orga20e2d42013-08-21 20:58:21 +00001068 if (!statistician || !statistician->GetStatistics(
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00001069 &receive_stats, rtp_rtcp_->RTCP() == kRtcpOff)) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001070 return -1;
1071 }
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00001072 *fraction_lost = receive_stats.fraction_lost;
1073 *cumulative_lost = receive_stats.cumulative_lost;
1074 *extended_max = receive_stats.extended_max_sequence_number;
1075 *jitter_samples = receive_stats.jitter;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001076
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001077 uint16_t dummy = 0;
1078 uint16_t rtt = 0;
mflodman@webrtc.org022615b2014-04-07 10:56:31 +00001079 rtp_rtcp_->RTT(remote_ssrc, &rtt, &dummy, &dummy, &dummy);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001080 *rtt_ms = rtt;
1081 return 0;
1082}
1083
sprang@webrtc.org4f1f5fa2013-12-19 13:26:02 +00001084void ViEChannel::RegisterReceiveChannelRtcpStatisticsCallback(
1085 RtcpStatisticsCallback* callback) {
sprang@webrtc.org4f1f5fa2013-12-19 13:26:02 +00001086 vie_receiver_.GetReceiveStatistics()->RegisterRtcpStatisticsCallback(
1087 callback);
1088}
1089
pbos@webrtc.org67879bc2013-04-09 13:41:51 +00001090int32_t ViEChannel::GetRtpStatistics(uint32_t* bytes_sent,
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00001091 uint32_t* packets_sent,
1092 uint32_t* bytes_received,
1093 uint32_t* packets_received) const {
stefan@webrtc.orga20e2d42013-08-21 20:58:21 +00001094 StreamStatistician* statistician = vie_receiver_.GetReceiveStatistics()->
1095 GetStatistician(vie_receiver_.GetRemoteSsrc());
1096 *bytes_received = 0;
1097 *packets_received = 0;
1098 if (statistician)
1099 statistician->GetDataCounters(bytes_received, packets_received);
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00001100 if (rtp_rtcp_->DataCountersRTP(bytes_sent, packets_sent) != 0) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001101 return -1;
1102 }
1103 CriticalSectionScoped cs(rtp_rtcp_cs_.get());
1104 for (std::list<RtpRtcp*>::const_iterator it = simulcast_rtp_rtcp_.begin();
1105 it != simulcast_rtp_rtcp_.end();
1106 it++) {
1107 uint32_t bytes_sent_temp = 0;
1108 uint32_t packets_sent_temp = 0;
1109 RtpRtcp* rtp_rtcp = *it;
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00001110 rtp_rtcp->DataCountersRTP(&bytes_sent_temp, &packets_sent_temp);
asapersson@webrtc.orgd8851092014-05-02 13:24:42 +00001111 *bytes_sent += bytes_sent_temp;
1112 *packets_sent += packets_sent_temp;
1113 }
1114 for (std::list<RtpRtcp*>::const_iterator it = removed_rtp_rtcp_.begin();
1115 it != removed_rtp_rtcp_.end(); ++it) {
1116 uint32_t bytes_sent_temp = 0;
1117 uint32_t packets_sent_temp = 0;
1118 RtpRtcp* rtp_rtcp = *it;
1119 rtp_rtcp->DataCountersRTP(&bytes_sent_temp, &packets_sent_temp);
1120 *bytes_sent += bytes_sent_temp;
1121 *packets_sent += packets_sent_temp;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001122 }
1123 return 0;
1124}
1125
sprang@webrtc.orgb1139812013-12-05 14:29:02 +00001126void ViEChannel::RegisterSendChannelRtpStatisticsCallback(
1127 StreamDataCountersCallback* callback) {
sprang@webrtc.orgb1139812013-12-05 14:29:02 +00001128 rtp_rtcp_->RegisterSendChannelRtpStatisticsCallback(callback);
1129 {
1130 CriticalSectionScoped cs(rtp_rtcp_cs_.get());
1131 for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
1132 it != simulcast_rtp_rtcp_.end();
1133 it++) {
1134 (*it)->RegisterSendChannelRtpStatisticsCallback(callback);
1135 }
1136 }
1137}
1138
sprang@webrtc.org7d99cd42014-01-23 10:00:39 +00001139void ViEChannel::RegisterReceiveChannelRtpStatisticsCallback(
1140 StreamDataCountersCallback* callback) {
sprang@webrtc.org7d99cd42014-01-23 10:00:39 +00001141 vie_receiver_.GetReceiveStatistics()->RegisterRtpStatisticsCallback(callback);
1142}
1143
asapersson@webrtc.org4a155602014-02-19 11:59:02 +00001144void ViEChannel::GetRtcpPacketTypeCounters(
1145 RtcpPacketTypeCounter* packets_sent,
1146 RtcpPacketTypeCounter* packets_received) const {
1147 rtp_rtcp_->GetRtcpPacketTypeCounters(packets_sent, packets_received);
1148
1149 CriticalSectionScoped cs(rtp_rtcp_cs_.get());
1150 for (std::list<RtpRtcp*>::const_iterator it = simulcast_rtp_rtcp_.begin();
1151 it != simulcast_rtp_rtcp_.end(); ++it) {
1152 RtcpPacketTypeCounter sent;
1153 RtcpPacketTypeCounter received;
1154 (*it)->GetRtcpPacketTypeCounters(&sent, &received);
1155 packets_sent->Add(sent);
1156 packets_received->Add(received);
1157 }
asapersson@webrtc.org9aef2252014-02-24 09:27:38 +00001158 for (std::list<RtpRtcp*>::const_iterator it = removed_rtp_rtcp_.begin();
1159 it != removed_rtp_rtcp_.end(); ++it) {
1160 RtcpPacketTypeCounter sent;
1161 RtcpPacketTypeCounter received;
1162 (*it)->GetRtcpPacketTypeCounters(&sent, &received);
1163 packets_sent->Add(sent);
1164 packets_received->Add(received);
1165 }
asapersson@webrtc.org4a155602014-02-19 11:59:02 +00001166}
1167
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001168void ViEChannel::GetBandwidthUsage(uint32_t* total_bitrate_sent,
1169 uint32_t* video_bitrate_sent,
1170 uint32_t* fec_bitrate_sent,
1171 uint32_t* nackBitrateSent) const {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001172 rtp_rtcp_->BitrateSent(total_bitrate_sent, video_bitrate_sent,
1173 fec_bitrate_sent, nackBitrateSent);
1174 CriticalSectionScoped cs(rtp_rtcp_cs_.get());
1175 for (std::list<RtpRtcp*>::const_iterator it = simulcast_rtp_rtcp_.begin();
1176 it != simulcast_rtp_rtcp_.end(); it++) {
1177 uint32_t stream_rate = 0;
1178 uint32_t video_rate = 0;
1179 uint32_t fec_rate = 0;
1180 uint32_t nackRate = 0;
1181 RtpRtcp* rtp_rtcp = *it;
1182 rtp_rtcp->BitrateSent(&stream_rate, &video_rate, &fec_rate, &nackRate);
1183 *total_bitrate_sent += stream_rate;
sprang@webrtc.org6646abd2013-10-31 09:49:03 +00001184 *video_bitrate_sent += video_rate;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001185 *fec_bitrate_sent += fec_rate;
1186 *nackBitrateSent += nackRate;
1187 }
1188}
1189
stefan@webrtc.orgee234be2013-12-05 14:05:07 +00001190bool ViEChannel::GetSendSideDelay(int* avg_send_delay,
1191 int* max_send_delay) const {
stefan@webrtc.orgee234be2013-12-05 14:05:07 +00001192 *avg_send_delay = 0;
1193 *max_send_delay = 0;
1194 bool valid_estimate = false;
1195 int num_send_delays = 0;
1196 if (rtp_rtcp_->GetSendSideDelay(avg_send_delay, max_send_delay)) {
1197 ++num_send_delays;
1198 valid_estimate = true;
1199 }
1200 CriticalSectionScoped cs(rtp_rtcp_cs_.get());
1201 for (std::list<RtpRtcp*>::const_iterator it = simulcast_rtp_rtcp_.begin();
1202 it != simulcast_rtp_rtcp_.end(); it++) {
1203 RtpRtcp* rtp_rtcp = *it;
1204 int sub_stream_avg_delay = 0;
1205 int sub_stream_max_delay = 0;
1206 if (rtp_rtcp->GetSendSideDelay(&sub_stream_avg_delay,
1207 &sub_stream_max_delay)) {
1208 *avg_send_delay += sub_stream_avg_delay;
1209 *max_send_delay = std::max(*max_send_delay, sub_stream_max_delay);
1210 ++num_send_delays;
1211 }
1212 }
1213 if (num_send_delays > 0) {
1214 valid_estimate = true;
1215 *avg_send_delay = *avg_send_delay / num_send_delays;
1216 *avg_send_delay = (*avg_send_delay + num_send_delays / 2) / num_send_delays;
1217 }
1218 return valid_estimate;
1219}
1220
stefan@webrtc.org55b0f2e2014-07-11 13:44:02 +00001221void ViEChannel::RegisterSendSideDelayObserver(
1222 SendSideDelayObserver* observer) {
1223 send_side_delay_observer_.Set(observer);
1224}
1225
sprang@webrtc.orgb70db6d2013-12-13 09:46:59 +00001226void ViEChannel::RegisterSendBitrateObserver(
1227 BitrateStatisticsObserver* observer) {
andresp@webrtc.orgf8ec08e2014-07-08 14:32:58 +00001228 send_bitrate_observer_.Set(observer);
sprang@webrtc.orgb70db6d2013-12-13 09:46:59 +00001229}
1230
jiayl@webrtc.orgd1e7fac2014-02-10 19:12:14 +00001231void ViEChannel::GetReceiveBandwidthEstimatorStats(
1232 ReceiveBandwidthEstimatorStats* output) const {
1233 vie_receiver_.GetReceiveBandwidthEstimatorStats(output);
1234}
1235
pbos@webrtc.org67879bc2013-04-09 13:41:51 +00001236int32_t ViEChannel::StartRTPDump(const char file_nameUTF8[1024],
mflodman@webrtc.org022615b2014-04-07 10:56:31 +00001237 RTPDirections direction) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001238 if (direction == kRtpIncoming) {
1239 return vie_receiver_.StartRTPDump(file_nameUTF8);
1240 } else {
1241 return vie_sender_.StartRTPDump(file_nameUTF8);
1242 }
1243}
1244
pbos@webrtc.org67879bc2013-04-09 13:41:51 +00001245int32_t ViEChannel::StopRTPDump(RTPDirections direction) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001246 if (direction == kRtpIncoming) {
1247 return vie_receiver_.StopRTPDump();
1248 } else {
1249 return vie_sender_.StopRTPDump();
1250 }
1251}
1252
pbos@webrtc.org67879bc2013-04-09 13:41:51 +00001253int32_t ViEChannel::StartSend() {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001254 CriticalSectionScoped cs(callback_cs_.get());
pwestin@webrtc.org912b7f72013-03-13 23:20:57 +00001255 if (!external_transport_) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +00001256 LOG(LS_ERROR) << "No transport set.";
pwestin@webrtc.org065b64d2013-04-02 20:37:14 +00001257 return -1;
pwestin@webrtc.org912b7f72013-03-13 23:20:57 +00001258 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001259 rtp_rtcp_->SetSendingMediaStatus(true);
1260
1261 if (rtp_rtcp_->Sending()) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001262 return kViEBaseAlreadySending;
1263 }
1264 if (rtp_rtcp_->SetSendingStatus(true) != 0) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001265 return -1;
1266 }
1267 CriticalSectionScoped cs_rtp(rtp_rtcp_cs_.get());
1268 for (std::list<RtpRtcp*>::const_iterator it = simulcast_rtp_rtcp_.begin();
1269 it != simulcast_rtp_rtcp_.end();
1270 it++) {
1271 RtpRtcp* rtp_rtcp = *it;
1272 rtp_rtcp->SetSendingMediaStatus(true);
1273 rtp_rtcp->SetSendingStatus(true);
1274 }
1275 return 0;
1276}
1277
pbos@webrtc.org67879bc2013-04-09 13:41:51 +00001278int32_t ViEChannel::StopSend() {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001279 CriticalSectionScoped cs(rtp_rtcp_cs_.get());
1280 rtp_rtcp_->SetSendingMediaStatus(false);
1281 for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
1282 it != simulcast_rtp_rtcp_.end();
1283 it++) {
1284 RtpRtcp* rtp_rtcp = *it;
1285 rtp_rtcp->SetSendingMediaStatus(false);
1286 }
1287 if (!rtp_rtcp_->Sending()) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001288 return kViEBaseNotSending;
1289 }
1290
1291 // Reset.
1292 rtp_rtcp_->ResetSendDataCountersRTP();
1293 if (rtp_rtcp_->SetSendingStatus(false) != 0) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001294 return -1;
1295 }
1296 for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
1297 it != simulcast_rtp_rtcp_.end();
1298 it++) {
1299 RtpRtcp* rtp_rtcp = *it;
1300 rtp_rtcp->ResetSendDataCountersRTP();
1301 rtp_rtcp->SetSendingStatus(false);
1302 }
1303 return 0;
1304}
1305
1306bool ViEChannel::Sending() {
1307 return rtp_rtcp_->Sending();
1308}
1309
pbos@webrtc.org67879bc2013-04-09 13:41:51 +00001310int32_t ViEChannel::StartReceive() {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001311 CriticalSectionScoped cs(callback_cs_.get());
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001312 if (StartDecodeThread() != 0) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001313 vie_receiver_.StopReceive();
1314 return -1;
1315 }
1316 vie_receiver_.StartReceive();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001317 return 0;
1318}
1319
pbos@webrtc.org67879bc2013-04-09 13:41:51 +00001320int32_t ViEChannel::StopReceive() {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001321 vie_receiver_.StopReceive();
1322 StopDecodeThread();
pbos@webrtc.org7f545612014-05-23 09:41:07 +00001323 vcm_->ResetDecoder();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001324 return 0;
1325}
1326
pbos@webrtc.org67879bc2013-04-09 13:41:51 +00001327int32_t ViEChannel::RegisterSendTransport(Transport* transport) {
pwestin@webrtc.org912b7f72013-03-13 23:20:57 +00001328 if (rtp_rtcp_->Sending()) {
pwestin@webrtc.org912b7f72013-03-13 23:20:57 +00001329 return -1;
1330 }
1331
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001332 CriticalSectionScoped cs(callback_cs_.get());
1333 if (external_transport_) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +00001334 LOG_F(LS_ERROR) << "Transport already registered.";
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001335 return -1;
1336 }
1337 external_transport_ = transport;
1338 vie_sender_.RegisterSendTransport(transport);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001339 return 0;
1340}
1341
pbos@webrtc.org67879bc2013-04-09 13:41:51 +00001342int32_t ViEChannel::DeregisterSendTransport() {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001343 CriticalSectionScoped cs(callback_cs_.get());
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001344 if (!external_transport_) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +00001345 return 0;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001346 }
1347 if (rtp_rtcp_->Sending()) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +00001348 LOG_F(LS_ERROR) << "Can't deregister transport when sending.";
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001349 return -1;
1350 }
1351 external_transport_ = NULL;
1352 vie_sender_.DeregisterSendTransport();
1353 return 0;
1354}
1355
pbos@webrtc.org67879bc2013-04-09 13:41:51 +00001356int32_t ViEChannel::ReceivedRTPPacket(
wu@webrtc.orgefeb8ce2013-12-13 00:21:03 +00001357 const void* rtp_packet, const int32_t rtp_packet_length,
1358 const PacketTime& packet_time) {
pwestin@webrtc.org912b7f72013-03-13 23:20:57 +00001359 {
1360 CriticalSectionScoped cs(callback_cs_.get());
1361 if (!external_transport_) {
1362 return -1;
1363 }
1364 }
wu@webrtc.orgefeb8ce2013-12-13 00:21:03 +00001365 return vie_receiver_.ReceivedRTPPacket(
1366 rtp_packet, rtp_packet_length, packet_time);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001367}
1368
pbos@webrtc.org67879bc2013-04-09 13:41:51 +00001369int32_t ViEChannel::ReceivedRTCPPacket(
1370 const void* rtcp_packet, const int32_t rtcp_packet_length) {
pwestin@webrtc.org912b7f72013-03-13 23:20:57 +00001371 {
1372 CriticalSectionScoped cs(callback_cs_.get());
1373 if (!external_transport_) {
1374 return -1;
1375 }
1376 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001377 return vie_receiver_.ReceivedRTCPPacket(rtcp_packet, rtcp_packet_length);
1378}
1379
pbos@webrtc.org67879bc2013-04-09 13:41:51 +00001380int32_t ViEChannel::SetMTU(uint16_t mtu) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001381 if (rtp_rtcp_->SetMaxTransferUnit(mtu) != 0) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001382 return -1;
1383 }
1384 CriticalSectionScoped cs(rtp_rtcp_cs_.get());
1385 for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
1386 it != simulcast_rtp_rtcp_.end();
1387 it++) {
1388 RtpRtcp* rtp_rtcp = *it;
1389 rtp_rtcp->SetMaxTransferUnit(mtu);
1390 }
1391 mtu_ = mtu;
1392 return 0;
1393}
1394
pbos@webrtc.org67879bc2013-04-09 13:41:51 +00001395uint16_t ViEChannel::MaxDataPayloadLength() const {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001396 return rtp_rtcp_->MaxDataPayloadLength();
1397}
1398
pbos@webrtc.org67879bc2013-04-09 13:41:51 +00001399int32_t ViEChannel::EnableColorEnhancement(bool enable) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001400 CriticalSectionScoped cs(callback_cs_.get());
1401 color_enhancement_ = enable;
1402 return 0;
1403}
1404
1405RtpRtcp* ViEChannel::rtp_rtcp() {
1406 return rtp_rtcp_.get();
1407}
1408
fischman@webrtc.org0329e592013-02-19 22:09:36 +00001409CallStatsObserver* ViEChannel::GetStatsObserver() {
mflodman@webrtc.org78696d32012-11-26 12:40:15 +00001410 return stats_observer_.get();
1411}
1412
wuchengli@chromium.orgd893b3f2013-08-12 14:20:49 +00001413// Do not acquire the lock of |vcm_| in this function. Decode callback won't
1414// necessarily be called from the decoding thread. The decoding thread may have
1415// held the lock when calling VideoDecoder::Decode, Reset, or Release. Acquiring
1416// the same lock in the path of decode callback can deadlock.
pbos@webrtc.org67879bc2013-04-09 13:41:51 +00001417int32_t ViEChannel::FrameToRender(
mikhal@webrtc.org3bbed742012-10-24 18:33:04 +00001418 I420VideoFrame& video_frame) { // NOLINT
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001419 CriticalSectionScoped cs(callback_cs_.get());
1420
1421 if (decoder_reset_) {
1422 // Trigger a callback to the user if the incoming codec has changed.
1423 if (codec_observer_) {
wuchengli@chromium.orgd893b3f2013-08-12 14:20:49 +00001424 // The codec set by RegisterReceiveCodec might not be the size we're
1425 // actually decoding.
1426 receive_codec_.width = static_cast<uint16_t>(video_frame.width());
1427 receive_codec_.height = static_cast<uint16_t>(video_frame.height());
1428 codec_observer_->IncomingCodecChanged(channel_id_, receive_codec_);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001429 }
1430 decoder_reset_ = false;
1431 }
wu@webrtc.orgea7b33e2013-08-05 20:36:57 +00001432 // Post processing is not supported if the frame is backed by a texture.
1433 if (video_frame.native_handle() == NULL) {
pbos@webrtc.org63301bd2013-10-21 10:34:43 +00001434 if (pre_render_callback_ != NULL)
1435 pre_render_callback_->FrameCallback(&video_frame);
wu@webrtc.orgea7b33e2013-08-05 20:36:57 +00001436 if (effect_filter_) {
1437 unsigned int length = CalcBufferSize(kI420,
1438 video_frame.width(),
1439 video_frame.height());
andrew@webrtc.orgba476162014-04-25 23:10:28 +00001440 scoped_ptr<uint8_t[]> video_buffer(new uint8_t[length]);
wu@webrtc.orgea7b33e2013-08-05 20:36:57 +00001441 ExtractBuffer(video_frame, length, video_buffer.get());
wu@webrtc.org9d107692014-04-15 17:46:33 +00001442 effect_filter_->Transform(length,
1443 video_buffer.get(),
1444 video_frame.ntp_time_ms(),
1445 video_frame.timestamp(),
1446 video_frame.width(),
wu@webrtc.orgea7b33e2013-08-05 20:36:57 +00001447 video_frame.height());
1448 }
1449 if (color_enhancement_) {
1450 VideoProcessingModule::ColorEnhancement(&video_frame);
1451 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001452 }
1453
pbos@webrtc.org67879bc2013-04-09 13:41:51 +00001454 uint32_t arr_ofCSRC[kRtpCsrcSize];
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00001455 int32_t no_of_csrcs = vie_receiver_.GetCsrcs(arr_ofCSRC);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001456 if (no_of_csrcs <= 0) {
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00001457 arr_ofCSRC[0] = vie_receiver_.GetRemoteSsrc();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001458 no_of_csrcs = 1;
1459 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001460 DeliverFrame(&video_frame, no_of_csrcs, arr_ofCSRC);
1461 return 0;
1462}
1463
pbos@webrtc.org67879bc2013-04-09 13:41:51 +00001464int32_t ViEChannel::ReceivedDecodedReferenceFrame(
1465 const uint64_t picture_id) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001466 return rtp_rtcp_->SendRTCPReferencePictureSelection(picture_id);
1467}
1468
wuchengli@chromium.orgd893b3f2013-08-12 14:20:49 +00001469void ViEChannel::IncomingCodecChanged(const VideoCodec& codec) {
1470 CriticalSectionScoped cs(callback_cs_.get());
1471 receive_codec_ = codec;
1472}
1473
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00001474int32_t ViEChannel::OnReceiveStatisticsUpdate(const uint32_t bit_rate,
1475 const uint32_t frame_rate) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001476 CriticalSectionScoped cs(callback_cs_.get());
1477 if (codec_observer_) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001478 codec_observer_->IncomingRate(channel_id_, frame_rate, bit_rate);
1479 }
1480 return 0;
1481}
1482
fischman@webrtc.orgecfef192013-10-23 23:59:45 +00001483void ViEChannel::OnDecoderTiming(int decode_ms,
1484 int max_decode_ms,
1485 int current_delay_ms,
1486 int target_delay_ms,
1487 int jitter_buffer_ms,
1488 int min_playout_delay_ms,
1489 int render_delay_ms) {
1490 CriticalSectionScoped cs(callback_cs_.get());
1491 if (!codec_observer_)
1492 return;
1493 codec_observer_->DecoderTiming(decode_ms,
1494 max_decode_ms,
1495 current_delay_ms,
1496 target_delay_ms,
1497 jitter_buffer_ms,
1498 min_playout_delay_ms,
1499 render_delay_ms);
1500}
1501
pbos@webrtc.org67879bc2013-04-09 13:41:51 +00001502int32_t ViEChannel::RequestKeyFrame() {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001503 {
1504 CriticalSectionScoped cs(callback_cs_.get());
1505 if (codec_observer_ && do_key_frame_callbackRequest_) {
1506 codec_observer_->RequestNewKeyFrame(channel_id_);
1507 }
1508 }
1509 return rtp_rtcp_->RequestKeyFrame();
1510}
1511
pbos@webrtc.org67879bc2013-04-09 13:41:51 +00001512int32_t ViEChannel::SliceLossIndicationRequest(
1513 const uint64_t picture_id) {
1514 return rtp_rtcp_->SendRTCPSliceLossIndication((uint8_t) picture_id);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001515}
1516
pbos@webrtc.org67879bc2013-04-09 13:41:51 +00001517int32_t ViEChannel::ResendPackets(const uint16_t* sequence_numbers,
1518 uint16_t length) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001519 return rtp_rtcp_->SendNACK(sequence_numbers, length);
1520}
1521
1522bool ViEChannel::ChannelDecodeThreadFunction(void* obj) {
1523 return static_cast<ViEChannel*>(obj)->ChannelDecodeProcess();
1524}
1525
1526bool ViEChannel::ChannelDecodeProcess() {
pbos@webrtc.org7f545612014-05-23 09:41:07 +00001527 vcm_->Decode(kMaxDecodeWaitTimeMs);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001528 return true;
1529}
1530
mflodman@webrtc.org78696d32012-11-26 12:40:15 +00001531void ViEChannel::OnRttUpdate(uint32_t rtt) {
pbos@webrtc.org7f545612014-05-23 09:41:07 +00001532 vcm_->SetReceiveChannelParameters(rtt);
mflodman@webrtc.org78696d32012-11-26 12:40:15 +00001533}
1534
pbos@webrtc.org88b558f2014-06-30 13:19:09 +00001535void ViEChannel::ReserveRtpRtcpModules(size_t num_modules) {
1536 for (size_t total_modules =
1537 1 + simulcast_rtp_rtcp_.size() + removed_rtp_rtcp_.size();
1538 total_modules < num_modules;
1539 ++total_modules) {
1540 RtpRtcp* rtp_rtcp = CreateRtpRtcpModule();
1541 rtp_rtcp->SetSendingStatus(false);
1542 rtp_rtcp->SetSendingMediaStatus(false);
pbos@webrtc.org88b558f2014-06-30 13:19:09 +00001543 rtp_rtcp->RegisterSendChannelRtcpStatisticsCallback(NULL);
1544 rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(NULL);
pbos@webrtc.org88b558f2014-06-30 13:19:09 +00001545 removed_rtp_rtcp_.push_back(rtp_rtcp);
1546 }
1547}
1548
1549RtpRtcp* ViEChannel::GetRtpRtcpModule(size_t index) const {
1550 if (index == 0)
1551 return rtp_rtcp_.get();
1552 if (index <= simulcast_rtp_rtcp_.size()) {
1553 std::list<RtpRtcp*>::const_iterator it = simulcast_rtp_rtcp_.begin();
1554 for (size_t i = 1; i < index; ++i) {
1555 ++it;
1556 }
1557 return *it;
1558 }
1559
1560 // If the requested module exists it must be in the removed list. Index
1561 // translation to this list must remove the default module as well as all
1562 // active simulcast modules.
1563 size_t removed_idx = index - simulcast_rtp_rtcp_.size() - 1;
1564 if (removed_idx >= removed_rtp_rtcp_.size())
1565 return NULL;
1566
1567 std::list<RtpRtcp*>::const_iterator it = removed_rtp_rtcp_.begin();
1568 while (removed_idx-- > 0)
1569 ++it;
1570
1571 return *it;
1572}
1573
1574RtpRtcp* ViEChannel::CreateRtpRtcpModule() {
1575 RtpRtcp::Configuration configuration;
1576 configuration.id = ViEModuleId(engine_id_, channel_id_);
1577 configuration.audio = false; // Video.
1578 configuration.default_module = default_rtp_rtcp_;
1579 configuration.outgoing_transport = &vie_sender_;
1580 configuration.intra_frame_callback = intra_frame_observer_;
1581 configuration.bandwidth_callback = bandwidth_observer_.get();
1582 configuration.rtt_stats = rtt_stats_;
1583 configuration.paced_sender = paced_sender_;
stefan@webrtc.org55b0f2e2014-07-11 13:44:02 +00001584 configuration.send_side_delay_observer = &send_side_delay_observer_;
pbos@webrtc.org88b558f2014-06-30 13:19:09 +00001585
1586 return RtpRtcp::CreateRtpRtcp(configuration);
1587}
1588
pbos@webrtc.org67879bc2013-04-09 13:41:51 +00001589int32_t ViEChannel::StartDecodeThread() {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001590 // Start the decode thread
1591 if (decode_thread_) {
1592 // Already started.
1593 return 0;
1594 }
1595 decode_thread_ = ThreadWrapper::CreateThread(ChannelDecodeThreadFunction,
1596 this, kHighestPriority,
1597 "DecodingThread");
1598 if (!decode_thread_) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001599 return -1;
1600 }
1601
1602 unsigned int thread_id;
1603 if (decode_thread_->Start(thread_id) == false) {
1604 delete decode_thread_;
1605 decode_thread_ = NULL;
mflodman@webrtc.org022615b2014-04-07 10:56:31 +00001606 LOG(LS_ERROR) << "Could not start decode thread.";
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001607 return -1;
1608 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001609 return 0;
1610}
1611
pbos@webrtc.org67879bc2013-04-09 13:41:51 +00001612int32_t ViEChannel::StopDecodeThread() {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001613 if (!decode_thread_) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001614 return 0;
1615 }
1616
1617 decode_thread_->SetNotAlive();
1618 if (decode_thread_->Stop()) {
1619 delete decode_thread_;
1620 } else {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001621 assert(false && "could not stop decode thread");
1622 }
1623 decode_thread_ = NULL;
1624 return 0;
1625}
1626
pbos@webrtc.org67879bc2013-04-09 13:41:51 +00001627int32_t ViEChannel::SetVoiceChannel(int32_t ve_channel_id,
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001628 VoEVideoSync* ve_sync_interface) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001629 if (ve_sync_interface) {
1630 // Register lip sync
1631 module_process_thread_.RegisterModule(&vie_sync_);
1632 } else {
1633 module_process_thread_.DeRegisterModule(&vie_sync_);
1634 }
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00001635 return vie_sync_.ConfigureSync(ve_channel_id,
1636 ve_sync_interface,
1637 rtp_rtcp_.get(),
1638 vie_receiver_.GetRtpReceiver());
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001639}
1640
pbos@webrtc.org67879bc2013-04-09 13:41:51 +00001641int32_t ViEChannel::VoiceChannel() {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001642 return vie_sync_.VoiceChannel();
1643}
1644
pbos@webrtc.org67879bc2013-04-09 13:41:51 +00001645int32_t ViEChannel::RegisterEffectFilter(ViEEffectFilter* effect_filter) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001646 CriticalSectionScoped cs(callback_cs_.get());
mflodman@webrtc.org022615b2014-04-07 10:56:31 +00001647 if (effect_filter && effect_filter_) {
1648 LOG(LS_ERROR) << "Effect filter already registered.";
1649 return -1;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001650 }
1651 effect_filter_ = effect_filter;
1652 return 0;
1653}
1654
pbos@webrtc.org63301bd2013-10-21 10:34:43 +00001655void ViEChannel::RegisterPreRenderCallback(
1656 I420FrameCallback* pre_render_callback) {
1657 CriticalSectionScoped cs(callback_cs_.get());
1658 pre_render_callback_ = pre_render_callback;
1659}
1660
sprang@webrtc.org2e98d452013-11-26 11:41:59 +00001661void ViEChannel::RegisterPreDecodeImageCallback(
1662 EncodedImageCallback* pre_decode_callback) {
pbos@webrtc.org7f545612014-05-23 09:41:07 +00001663 vcm_->RegisterPreDecodeImageCallback(pre_decode_callback);
sprang@webrtc.org2e98d452013-11-26 11:41:59 +00001664}
1665
pbos@webrtc.org67879bc2013-04-09 13:41:51 +00001666void ViEChannel::OnApplicationDataReceived(const int32_t id,
1667 const uint8_t sub_type,
1668 const uint32_t name,
1669 const uint16_t length,
1670 const uint8_t* data) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001671 if (channel_id_ != ChannelId(id)) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001672 return;
1673 }
1674 CriticalSectionScoped cs(callback_cs_.get());
1675 {
1676 if (rtcp_observer_) {
1677 rtcp_observer_->OnApplicationDataReceived(
1678 channel_id_, sub_type, name, reinterpret_cast<const char*>(data),
1679 length);
1680 }
1681 }
1682}
1683
pbos@webrtc.org67879bc2013-04-09 13:41:51 +00001684int32_t ViEChannel::OnInitializeDecoder(
1685 const int32_t id,
1686 const int8_t payload_type,
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001687 const char payload_name[RTP_PAYLOAD_NAME_SIZE],
1688 const int frequency,
pbos@webrtc.org67879bc2013-04-09 13:41:51 +00001689 const uint8_t channels,
1690 const uint32_t rate) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +00001691 LOG(LS_INFO) << "OnInitializeDecoder " << payload_type << " "
1692 << payload_name;
pbos@webrtc.org7f545612014-05-23 09:41:07 +00001693 vcm_->ResetDecoder();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001694
wuchengli@chromium.orgd893b3f2013-08-12 14:20:49 +00001695 CriticalSectionScoped cs(callback_cs_.get());
wuchengli@chromium.orgf43029b2013-08-09 04:42:51 +00001696 decoder_reset_ = true;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001697 return 0;
1698}
1699
stefan@webrtc.orga20e2d42013-08-21 20:58:21 +00001700void ViEChannel::OnIncomingSSRCChanged(const int32_t id, const uint32_t ssrc) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +00001701 assert(channel_id_ == ChannelId(id));
stefan@webrtc.orga20e2d42013-08-21 20:58:21 +00001702 rtp_rtcp_->SetRemoteSSRC(ssrc);
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00001703
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001704 CriticalSectionScoped cs(callback_cs_.get());
1705 {
1706 if (rtp_observer_) {
stefan@webrtc.orga20e2d42013-08-21 20:58:21 +00001707 rtp_observer_->IncomingSSRCChanged(channel_id_, ssrc);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001708 }
1709 }
1710}
1711
pbos@webrtc.org67879bc2013-04-09 13:41:51 +00001712void ViEChannel::OnIncomingCSRCChanged(const int32_t id,
1713 const uint32_t CSRC,
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001714 const bool added) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +00001715 assert(channel_id_ == ChannelId(id));
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001716 CriticalSectionScoped cs(callback_cs_.get());
1717 {
1718 if (rtp_observer_) {
1719 rtp_observer_->IncomingCSRCChanged(channel_id_, CSRC, added);
1720 }
1721 }
1722}
1723
stefan@webrtc.orga20e2d42013-08-21 20:58:21 +00001724void ViEChannel::ResetStatistics(uint32_t ssrc) {
1725 StreamStatistician* statistician =
1726 vie_receiver_.GetReceiveStatistics()->GetStatistician(ssrc);
1727 if (statistician)
1728 statistician->ResetStatistics();
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00001729}
1730
sprang@webrtc.org5fdd10a2013-12-04 15:09:27 +00001731void ViEChannel::RegisterSendFrameCountObserver(
1732 FrameCountObserver* observer) {
andresp@webrtc.org8c95e832014-07-10 09:39:23 +00001733 send_frame_count_observer_.Set(observer);
sprang@webrtc.org5fdd10a2013-12-04 15:09:27 +00001734}
1735
solenberg@webrtc.org2d3624c2014-03-24 20:28:11 +00001736void ViEChannel::ReceivedBWEPacket(int64_t arrival_time_ms,
1737 int payload_size, const RTPHeader& header) {
1738 vie_receiver_.ReceivedBWEPacket(arrival_time_ms, payload_size, header);
1739}
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001740} // namespace webrtc