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_receiver.h"
15 #include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
16 #include "webrtc/modules/rtp_rtcp/interface/fec_receiver.h"
17 #include "webrtc/modules/rtp_rtcp/interface/receive_statistics.h"
18 #include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
19 #include "webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.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/rtp_dump.h"
23 #include "webrtc/modules/video_coding/main/interface/video_coding.h"
24 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
25 #include "webrtc/system_wrappers/interface/logging.h"
26 #include "webrtc/system_wrappers/interface/tick_util.h"
27 #include "webrtc/system_wrappers/interface/timestamp_extrapolator.h"
28 #include "webrtc/system_wrappers/interface/trace.h"
32 ViEReceiver::ViEReceiver(const int32_t channel_id,
33 VideoCodingModule* module_vcm,
34 RemoteBitrateEstimator* remote_bitrate_estimator,
35 RtpFeedback* rtp_feedback)
36 : receive_cs_(CriticalSectionWrapper::CreateCriticalSection()),
37 channel_id_(channel_id),
38 rtp_header_parser_(RtpHeaderParser::Create()),
39 rtp_payload_registry_(new RTPPayloadRegistry(
40 RTPPayloadStrategy::CreateStrategy(false))),
41 rtp_receiver_(RtpReceiver::CreateVideoReceiver(
42 channel_id, Clock::GetRealTimeClock(), this, rtp_feedback,
43 rtp_payload_registry_.get())),
44 rtp_receive_statistics_(ReceiveStatistics::Create(
45 Clock::GetRealTimeClock())),
46 fec_receiver_(FecReceiver::Create(this)),
49 remote_bitrate_estimator_(remote_bitrate_estimator),
50 clock_(Clock::GetRealTimeClock()),
52 new TimestampExtrapolator(clock_->TimeInMilliseconds())),
55 restored_packet_in_use_(false),
56 receiving_ast_enabled_(false) {
57 assert(remote_bitrate_estimator);
60 ViEReceiver::~ViEReceiver() {
63 RtpDump::DestroyRtpDump(rtp_dump_);
68 bool ViEReceiver::SetReceiveCodec(const VideoCodec& video_codec) {
69 int8_t old_pltype = -1;
70 if (rtp_payload_registry_->ReceivePayloadType(video_codec.plName,
71 kVideoPayloadTypeFrequency,
73 video_codec.maxBitrate,
75 rtp_payload_registry_->DeRegisterReceivePayload(old_pltype);
78 return RegisterPayload(video_codec);
81 bool ViEReceiver::RegisterPayload(const VideoCodec& video_codec) {
82 return rtp_receiver_->RegisterReceivePayload(video_codec.plName,
84 kVideoPayloadTypeFrequency,
86 video_codec.maxBitrate) == 0;
89 void ViEReceiver::SetNackStatus(bool enable,
90 int max_nack_reordering_threshold) {
92 // Reset the threshold back to the lower default threshold when NACK is
93 // disabled since we no longer will be receiving retransmissions.
94 max_nack_reordering_threshold = kDefaultMaxReorderingThreshold;
96 rtp_receive_statistics_->SetMaxReorderingThreshold(
97 max_nack_reordering_threshold);
98 rtp_receiver_->SetNACKStatus(enable ? kNackRtcp : kNackOff);
101 void ViEReceiver::SetRtxStatus(bool enable, uint32_t ssrc) {
102 rtp_payload_registry_->SetRtxStatus(enable, ssrc);
105 void ViEReceiver::SetRtxPayloadType(uint32_t payload_type) {
106 rtp_payload_registry_->SetRtxPayloadType(payload_type);
109 uint32_t ViEReceiver::GetRemoteSsrc() const {
110 return rtp_receiver_->SSRC();
113 int ViEReceiver::GetCsrcs(uint32_t* csrcs) const {
114 return rtp_receiver_->CSRCs(csrcs);
117 void ViEReceiver::SetRtpRtcpModule(RtpRtcp* module) {
121 RtpReceiver* ViEReceiver::GetRtpReceiver() const {
122 return rtp_receiver_.get();
125 void ViEReceiver::RegisterSimulcastRtpRtcpModules(
126 const std::list<RtpRtcp*>& rtp_modules) {
127 CriticalSectionScoped cs(receive_cs_.get());
128 rtp_rtcp_simulcast_.clear();
130 if (!rtp_modules.empty()) {
131 rtp_rtcp_simulcast_.insert(rtp_rtcp_simulcast_.begin(),
137 bool ViEReceiver::SetReceiveTimestampOffsetStatus(bool enable, int id) {
139 return rtp_header_parser_->RegisterRtpHeaderExtension(
140 kRtpExtensionTransmissionTimeOffset, id);
142 return rtp_header_parser_->DeregisterRtpHeaderExtension(
143 kRtpExtensionTransmissionTimeOffset);
147 bool ViEReceiver::SetReceiveAbsoluteSendTimeStatus(bool enable, int id) {
149 if (rtp_header_parser_->RegisterRtpHeaderExtension(
150 kRtpExtensionAbsoluteSendTime, id)) {
151 receiving_ast_enabled_ = true;
157 receiving_ast_enabled_ = false;
158 return rtp_header_parser_->DeregisterRtpHeaderExtension(
159 kRtpExtensionAbsoluteSendTime);
163 int ViEReceiver::ReceivedRTPPacket(const void* rtp_packet,
164 int rtp_packet_length,
165 const PacketTime& packet_time) {
166 return InsertRTPPacket(static_cast<const uint8_t*>(rtp_packet),
167 rtp_packet_length, packet_time);
170 int ViEReceiver::ReceivedRTCPPacket(const void* rtcp_packet,
171 int rtcp_packet_length) {
172 return InsertRTCPPacket(static_cast<const uint8_t*>(rtcp_packet),
176 int32_t ViEReceiver::OnReceivedPayloadData(
177 const uint8_t* payload_data, const uint16_t payload_size,
178 const WebRtcRTPHeader* rtp_header) {
179 WebRtcRTPHeader rtp_header_with_ntp = *rtp_header;
180 CalculateCaptureNtpTime(&rtp_header_with_ntp);
181 if (vcm_->IncomingPacket(payload_data,
183 rtp_header_with_ntp) != 0) {
190 void ViEReceiver::CalculateCaptureNtpTime(WebRtcRTPHeader* rtp_header) {
191 if (rtcp_list_.size() < 2) {
192 // We need two RTCP SR reports to calculate NTP.
196 int64_t sender_capture_ntp_ms = 0;
197 if (!RtpToNtpMs(rtp_header->header.timestamp,
199 &sender_capture_ntp_ms)) {
202 uint32_t timestamp = sender_capture_ntp_ms * 90;
203 int64_t receiver_capture_ms =
204 ts_extrapolator_->ExtrapolateLocalTime(timestamp);
206 clock_->CurrentNtpInMilliseconds() - clock_->TimeInMilliseconds();
207 rtp_header->ntp_time_ms = receiver_capture_ms + ntp_offset;
210 bool ViEReceiver::OnRecoveredPacket(const uint8_t* rtp_packet,
211 int rtp_packet_length) {
213 if (!rtp_header_parser_->Parse(rtp_packet, rtp_packet_length, &header)) {
214 WEBRTC_TRACE(kTraceDebug, webrtc::kTraceVideo, channel_id_,
215 "IncomingPacket invalid RTP header");
218 header.payload_type_frequency = kVideoPayloadTypeFrequency;
219 return ReceivePacket(rtp_packet, rtp_packet_length, header, false);
222 void ViEReceiver::ReceivedBWEPacket(
223 int64_t arrival_time_ms, int payload_size, const RTPHeader& header) {
224 // Only forward if the incoming packet *and* the channel are both configured
225 // to receive absolute sender time. RTP time stamps may have different rates
226 // for audio and video and shouldn't be mixed.
227 if (header.extension.hasAbsoluteSendTime && receiving_ast_enabled_) {
228 remote_bitrate_estimator_->IncomingPacket(arrival_time_ms, payload_size,
233 int ViEReceiver::InsertRTPPacket(const uint8_t* rtp_packet,
234 int rtp_packet_length,
235 const PacketTime& packet_time) {
237 CriticalSectionScoped cs(receive_cs_.get());
242 rtp_dump_->DumpPacket(rtp_packet,
243 static_cast<uint16_t>(rtp_packet_length));
248 if (!rtp_header_parser_->Parse(rtp_packet, rtp_packet_length,
250 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideo, channel_id_,
251 "Incoming packet: Invalid RTP header");
254 int payload_length = rtp_packet_length - header.headerLength;
255 int64_t arrival_time_ms;
256 if (packet_time.timestamp != -1)
257 arrival_time_ms = (packet_time.timestamp + 500) / 1000;
259 arrival_time_ms = TickTime::MillisecondTimestamp();
261 remote_bitrate_estimator_->IncomingPacket(arrival_time_ms,
262 payload_length, header);
263 header.payload_type_frequency = kVideoPayloadTypeFrequency;
265 bool in_order = IsPacketInOrder(header);
266 rtp_receive_statistics_->IncomingPacket(
267 header, rtp_packet_length, IsPacketRetransmitted(header, in_order));
268 rtp_payload_registry_->SetIncomingPayloadType(header);
269 return ReceivePacket(rtp_packet, rtp_packet_length, header, in_order)
274 bool ViEReceiver::ReceivePacket(const uint8_t* packet,
276 const RTPHeader& header,
278 if (rtp_payload_registry_->IsEncapsulated(header)) {
279 return ParseAndHandleEncapsulatingHeader(packet, packet_length, header);
281 const uint8_t* payload = packet + header.headerLength;
282 int payload_length = packet_length - header.headerLength;
283 assert(payload_length >= 0);
284 PayloadUnion payload_specific;
285 if (!rtp_payload_registry_->GetPayloadSpecifics(header.payloadType,
286 &payload_specific)) {
289 return rtp_receiver_->IncomingRtpPacket(header, payload, payload_length,
290 payload_specific, in_order);
293 bool ViEReceiver::ParseAndHandleEncapsulatingHeader(const uint8_t* packet,
295 const RTPHeader& header) {
296 if (rtp_payload_registry_->IsRed(header)) {
297 int8_t ulpfec_pt = rtp_payload_registry_->ulpfec_payload_type();
298 if (packet[header.headerLength] == ulpfec_pt)
299 rtp_receive_statistics_->FecPacketReceived(header.ssrc);
300 if (fec_receiver_->AddReceivedRedPacket(
301 header, packet, packet_length, ulpfec_pt) != 0) {
302 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideo, channel_id_,
303 "Incoming RED packet error");
306 return fec_receiver_->ProcessReceivedFec() == 0;
307 } else if (rtp_payload_registry_->IsRtx(header)) {
308 if (header.headerLength + header.paddingLength == packet_length) {
309 // This is an empty packet and should be silently dropped before trying to
310 // parse the RTX header.
313 // Remove the RTX header and parse the original RTP header.
314 if (packet_length < header.headerLength)
316 if (packet_length > static_cast<int>(sizeof(restored_packet_)))
318 CriticalSectionScoped cs(receive_cs_.get());
319 if (restored_packet_in_use_) {
320 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideo, channel_id_,
321 "Multiple RTX headers detected, dropping packet");
324 uint8_t* restored_packet_ptr = restored_packet_;
325 if (!rtp_payload_registry_->RestoreOriginalPacket(
326 &restored_packet_ptr, packet, &packet_length, rtp_receiver_->SSRC(),
328 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideo, channel_id_,
329 "Incoming RTX packet: invalid RTP header");
332 restored_packet_in_use_ = true;
333 bool ret = OnRecoveredPacket(restored_packet_ptr, packet_length);
334 restored_packet_in_use_ = false;
340 int ViEReceiver::InsertRTCPPacket(const uint8_t* rtcp_packet,
341 int rtcp_packet_length) {
343 CriticalSectionScoped cs(receive_cs_.get());
349 rtp_dump_->DumpPacket(
350 rtcp_packet, static_cast<uint16_t>(rtcp_packet_length));
353 std::list<RtpRtcp*>::iterator it = rtp_rtcp_simulcast_.begin();
354 while (it != rtp_rtcp_simulcast_.end()) {
355 RtpRtcp* rtp_rtcp = *it++;
356 rtp_rtcp->IncomingRtcpPacket(rtcp_packet, rtcp_packet_length);
359 assert(rtp_rtcp_); // Should be set by owner at construction time.
360 int ret = rtp_rtcp_->IncomingRtcpPacket(rtcp_packet, rtcp_packet_length);
365 if (!GetRtcpTimestamp()) {
366 LOG(LS_WARNING) << "Failed to retrieve timestamp information from RTCP SR.";
372 bool ViEReceiver::GetRtcpTimestamp() {
374 rtp_rtcp_->RTT(rtp_receiver_->SSRC(), &rtt, NULL, NULL, NULL);
376 // Waiting for valid rtt.
381 uint32_t ntp_secs = 0;
382 uint32_t ntp_frac = 0;
383 uint32_t rtp_timestamp = 0;
384 if (0 != rtp_rtcp_->RemoteNTP(&ntp_secs,
392 bool new_rtcp_sr = false;
393 if (!UpdateRtcpList(ntp_secs,
402 // No new RTCP SR since last time this function was called.
406 // Update extrapolator with the new arrival time.
407 // The extrapolator assumes the TimeInMilliseconds time.
408 int64_t receiver_arrival_time = clock_->TimeInMilliseconds();
409 int64_t sender_send_time_ms = Clock::NtpToMs(ntp_secs, ntp_frac);
410 int64_t sender_arrival_time_90k = (sender_send_time_ms + rtt / 2) * 90;
411 ts_extrapolator_->Update(receiver_arrival_time, sender_arrival_time_90k);
415 void ViEReceiver::StartReceive() {
416 CriticalSectionScoped cs(receive_cs_.get());
420 void ViEReceiver::StopReceive() {
421 CriticalSectionScoped cs(receive_cs_.get());
425 int ViEReceiver::StartRTPDump(const char file_nameUTF8[1024]) {
426 CriticalSectionScoped cs(receive_cs_.get());
428 // Restart it if it already exists and is started
431 rtp_dump_ = RtpDump::CreateRtpDump();
432 if (rtp_dump_ == NULL) {
433 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, channel_id_,
434 "StartRTPDump: Failed to create RTP dump");
438 if (rtp_dump_->Start(file_nameUTF8) != 0) {
439 RtpDump::DestroyRtpDump(rtp_dump_);
441 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, channel_id_,
442 "StartRTPDump: Failed to start RTP dump");
448 int ViEReceiver::StopRTPDump() {
449 CriticalSectionScoped cs(receive_cs_.get());
451 if (rtp_dump_->IsActive()) {
454 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, channel_id_,
455 "StopRTPDump: Dump not active");
457 RtpDump::DestroyRtpDump(rtp_dump_);
460 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, channel_id_,
461 "StopRTPDump: RTP dump not started");
467 void ViEReceiver::GetReceiveBandwidthEstimatorStats(
468 ReceiveBandwidthEstimatorStats* output) const {
469 remote_bitrate_estimator_->GetStats(output);
472 ReceiveStatistics* ViEReceiver::GetReceiveStatistics() const {
473 return rtp_receive_statistics_.get();
476 bool ViEReceiver::IsPacketInOrder(const RTPHeader& header) const {
477 StreamStatistician* statistician =
478 rtp_receive_statistics_->GetStatistician(header.ssrc);
481 return statistician->IsPacketInOrder(header.sequenceNumber);
484 bool ViEReceiver::IsPacketRetransmitted(const RTPHeader& header,
485 bool in_order) const {
486 // Retransmissions are handled separately if RTX is enabled.
487 if (rtp_payload_registry_->RtxEnabled())
489 StreamStatistician* statistician =
490 rtp_receive_statistics_->GetStatistician(header.ssrc);
493 // Check if this is a retransmission.
494 uint16_t min_rtt = 0;
495 rtp_rtcp_->RTT(rtp_receiver_->SSRC(), NULL, NULL, &min_rtt, NULL);
497 statistician->IsRetransmitOfOldPacket(header, min_rtt);
499 } // namespace webrtc