blob: ce6bdf20e9fcddbd4587bb4e16cc754e4fe0a79e [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
leozwang@webrtc.org39e96592012-03-01 18:22:48 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
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.orgf5d4cb12013-05-17 13:44:48 +000011#include "webrtc/video_engine/vie_receiver.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
mflodman@webrtc.org4fd55272013-02-06 17:46:39 +000013#include <vector>
14
pbos@webrtc.orgf5d4cb12013-05-17 13:44:48 +000015#include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +000016#include "webrtc/modules/rtp_rtcp/interface/fec_receiver.h"
wu@webrtc.org822fbd82013-08-15 23:38:54 +000017#include "webrtc/modules/rtp_rtcp/interface/receive_statistics.h"
stefan@webrtc.orga5cb98c2013-05-29 12:12:51 +000018#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
wu@webrtc.org822fbd82013-08-15 23:38:54 +000019#include "webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h"
20#include "webrtc/modules/rtp_rtcp/interface/rtp_receiver.h"
pbos@webrtc.orgf5d4cb12013-05-17 13:44:48 +000021#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"
wu@webrtc.orgcd701192014-04-24 22:10:24 +000025#include "webrtc/system_wrappers/interface/logging.h"
pbos@webrtc.orgf5d4cb12013-05-17 13:44:48 +000026#include "webrtc/system_wrappers/interface/tick_util.h"
wu@webrtc.org66773a02014-05-07 17:09:44 +000027#include "webrtc/system_wrappers/interface/timestamp_extrapolator.h"
pbos@webrtc.orgf5d4cb12013-05-17 13:44:48 +000028#include "webrtc/system_wrappers/interface/trace.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000029
30namespace webrtc {
31
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +000032ViEReceiver::ViEReceiver(const int32_t channel_id,
stefan@webrtc.org976a7e62012-09-21 13:20:21 +000033 VideoCodingModule* module_vcm,
wu@webrtc.org822fbd82013-08-15 23:38:54 +000034 RemoteBitrateEstimator* remote_bitrate_estimator,
35 RtpFeedback* rtp_feedback)
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +000036 : receive_cs_(CriticalSectionWrapper::CreateCriticalSection()),
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +000037 channel_id_(channel_id),
stefan@webrtc.orga5cb98c2013-05-29 12:12:51 +000038 rtp_header_parser_(RtpHeaderParser::Create()),
wu@webrtc.org822fbd82013-08-15 23:38:54 +000039 rtp_payload_registry_(new RTPPayloadRegistry(
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +000040 RTPPayloadStrategy::CreateStrategy(false))),
wu@webrtc.org822fbd82013-08-15 23:38:54 +000041 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())),
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +000046 fec_receiver_(FecReceiver::Create(this)),
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +000047 rtp_rtcp_(NULL),
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +000048 vcm_(module_vcm),
stefan@webrtc.org976a7e62012-09-21 13:20:21 +000049 remote_bitrate_estimator_(remote_bitrate_estimator),
wu@webrtc.orgcd701192014-04-24 22:10:24 +000050 clock_(Clock::GetRealTimeClock()),
wu@webrtc.orged4cb562014-05-06 04:50:49 +000051 ts_extrapolator_(
wu@webrtc.org66773a02014-05-07 17:09:44 +000052 new TimestampExtrapolator(clock_->TimeInMilliseconds())),
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +000053 rtp_dump_(NULL),
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +000054 receiving_(false),
solenberg@webrtc.org3fb8f7b2014-03-24 20:28:11 +000055 restored_packet_in_use_(false),
56 receiving_ast_enabled_(false) {
stefan@webrtc.org976a7e62012-09-21 13:20:21 +000057 assert(remote_bitrate_estimator);
niklase@google.com470e71d2011-07-07 08:21:25 +000058}
59
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +000060ViEReceiver::~ViEReceiver() {
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +000061 if (rtp_dump_) {
62 rtp_dump_->Stop();
63 RtpDump::DestroyRtpDump(rtp_dump_);
64 rtp_dump_ = NULL;
65 }
niklase@google.com470e71d2011-07-07 08:21:25 +000066}
67
wu@webrtc.org822fbd82013-08-15 23:38:54 +000068bool ViEReceiver::SetReceiveCodec(const VideoCodec& video_codec) {
69 int8_t old_pltype = -1;
70 if (rtp_payload_registry_->ReceivePayloadType(video_codec.plName,
71 kVideoPayloadTypeFrequency,
72 0,
73 video_codec.maxBitrate,
74 &old_pltype) != -1) {
75 rtp_payload_registry_->DeRegisterReceivePayload(old_pltype);
76 }
77
78 return RegisterPayload(video_codec);
79}
80
81bool ViEReceiver::RegisterPayload(const VideoCodec& video_codec) {
82 return rtp_receiver_->RegisterReceivePayload(video_codec.plName,
83 video_codec.plType,
84 kVideoPayloadTypeFrequency,
85 0,
86 video_codec.maxBitrate) == 0;
87}
88
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +000089void ViEReceiver::SetNackStatus(bool enable,
wu@webrtc.org822fbd82013-08-15 23:38:54 +000090 int max_nack_reordering_threshold) {
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +000091 if (!enable) {
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;
95 }
96 rtp_receive_statistics_->SetMaxReorderingThreshold(
97 max_nack_reordering_threshold);
98 rtp_receiver_->SetNACKStatus(enable ? kNackRtcp : kNackOff);
wu@webrtc.org822fbd82013-08-15 23:38:54 +000099}
100
101void ViEReceiver::SetRtxStatus(bool enable, uint32_t ssrc) {
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000102 rtp_payload_registry_->SetRtxStatus(enable, ssrc);
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000103}
104
105void ViEReceiver::SetRtxPayloadType(uint32_t payload_type) {
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000106 rtp_payload_registry_->SetRtxPayloadType(payload_type);
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000107}
108
109uint32_t ViEReceiver::GetRemoteSsrc() const {
110 return rtp_receiver_->SSRC();
111}
112
113int ViEReceiver::GetCsrcs(uint32_t* csrcs) const {
114 return rtp_receiver_->CSRCs(csrcs);
115}
116
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000117void ViEReceiver::SetRtpRtcpModule(RtpRtcp* module) {
118 rtp_rtcp_ = module;
119}
120
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000121RtpReceiver* ViEReceiver::GetRtpReceiver() const {
122 return rtp_receiver_.get();
123}
124
pwestin@webrtc.org1da1ce02011-10-13 15:19:55 +0000125void ViEReceiver::RegisterSimulcastRtpRtcpModules(
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000126 const std::list<RtpRtcp*>& rtp_modules) {
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000127 CriticalSectionScoped cs(receive_cs_.get());
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000128 rtp_rtcp_simulcast_.clear();
129
130 if (!rtp_modules.empty()) {
131 rtp_rtcp_simulcast_.insert(rtp_rtcp_simulcast_.begin(),
132 rtp_modules.begin(),
133 rtp_modules.end());
134 }
pwestin@webrtc.org1da1ce02011-10-13 15:19:55 +0000135}
136
stefan@webrtc.org08994cc2013-05-29 13:28:21 +0000137bool ViEReceiver::SetReceiveTimestampOffsetStatus(bool enable, int id) {
stefan@webrtc.orga5cb98c2013-05-29 12:12:51 +0000138 if (enable) {
139 return rtp_header_parser_->RegisterRtpHeaderExtension(
140 kRtpExtensionTransmissionTimeOffset, id);
141 } else {
142 return rtp_header_parser_->DeregisterRtpHeaderExtension(
143 kRtpExtensionTransmissionTimeOffset);
144 }
145}
146
stefan@webrtc.org08994cc2013-05-29 13:28:21 +0000147bool ViEReceiver::SetReceiveAbsoluteSendTimeStatus(bool enable, int id) {
stefan@webrtc.orga5cb98c2013-05-29 12:12:51 +0000148 if (enable) {
solenberg@webrtc.org3fb8f7b2014-03-24 20:28:11 +0000149 if (rtp_header_parser_->RegisterRtpHeaderExtension(
150 kRtpExtensionAbsoluteSendTime, id)) {
151 receiving_ast_enabled_ = true;
152 return true;
153 } else {
154 return false;
155 }
stefan@webrtc.orga5cb98c2013-05-29 12:12:51 +0000156 } else {
solenberg@webrtc.org3fb8f7b2014-03-24 20:28:11 +0000157 receiving_ast_enabled_ = false;
stefan@webrtc.orga5cb98c2013-05-29 12:12:51 +0000158 return rtp_header_parser_->DeregisterRtpHeaderExtension(
159 kRtpExtensionAbsoluteSendTime);
160 }
161}
162
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000163int ViEReceiver::ReceivedRTPPacket(const void* rtp_packet,
wu@webrtc.orga9890802013-12-13 00:21:03 +0000164 int rtp_packet_length,
165 const PacketTime& packet_time) {
solenberg@webrtc.orgfc320462014-02-11 15:27:49 +0000166 return InsertRTPPacket(static_cast<const uint8_t*>(rtp_packet),
wu@webrtc.orga9890802013-12-13 00:21:03 +0000167 rtp_packet_length, packet_time);
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000168}
169
170int ViEReceiver::ReceivedRTCPPacket(const void* rtcp_packet,
171 int rtcp_packet_length) {
solenberg@webrtc.orgfc320462014-02-11 15:27:49 +0000172 return InsertRTCPPacket(static_cast<const uint8_t*>(rtcp_packet),
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000173 rtcp_packet_length);
174}
175
pbos@webrtc.orgb238d122013-04-09 13:41:51 +0000176int32_t ViEReceiver::OnReceivedPayloadData(
177 const uint8_t* payload_data, const uint16_t payload_size,
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000178 const WebRtcRTPHeader* rtp_header) {
wu@webrtc.orgcd701192014-04-24 22:10:24 +0000179 WebRtcRTPHeader rtp_header_with_ntp = *rtp_header;
180 CalculateCaptureNtpTime(&rtp_header_with_ntp);
181 if (vcm_->IncomingPacket(payload_data,
182 payload_size,
183 rtp_header_with_ntp) != 0) {
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000184 // Check this...
185 return -1;
186 }
187 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000188}
189
wu@webrtc.orgcd701192014-04-24 22:10:24 +0000190void ViEReceiver::CalculateCaptureNtpTime(WebRtcRTPHeader* rtp_header) {
191 if (rtcp_list_.size() < 2) {
192 // We need two RTCP SR reports to calculate NTP.
193 return;
194 }
195
196 int64_t sender_capture_ntp_ms = 0;
wu@webrtc.org66773a02014-05-07 17:09:44 +0000197 if (!RtpToNtpMs(rtp_header->header.timestamp,
198 rtcp_list_,
199 &sender_capture_ntp_ms)) {
wu@webrtc.orgcd701192014-04-24 22:10:24 +0000200 return;
201 }
202 uint32_t timestamp = sender_capture_ntp_ms * 90;
203 int64_t receiver_capture_ms =
204 ts_extrapolator_->ExtrapolateLocalTime(timestamp);
205 int64_t ntp_offset =
206 clock_->CurrentNtpInMilliseconds() - clock_->TimeInMilliseconds();
207 rtp_header->ntp_time_ms = receiver_capture_ms + ntp_offset;
208}
209
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000210bool ViEReceiver::OnRecoveredPacket(const uint8_t* rtp_packet,
211 int rtp_packet_length) {
212 RTPHeader header;
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");
216 return false;
217 }
218 header.payload_type_frequency = kVideoPayloadTypeFrequency;
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000219 return ReceivePacket(rtp_packet, rtp_packet_length, header, false);
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000220}
221
solenberg@webrtc.org3fb8f7b2014-03-24 20:28:11 +0000222void 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,
229 header);
230 }
231}
232
solenberg@webrtc.orgfc320462014-02-11 15:27:49 +0000233int ViEReceiver::InsertRTPPacket(const uint8_t* rtp_packet,
wu@webrtc.orga9890802013-12-13 00:21:03 +0000234 int rtp_packet_length,
235 const PacketTime& packet_time) {
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000236 {
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000237 CriticalSectionScoped cs(receive_cs_.get());
braveyao@webrtc.orgb6433b72013-07-26 09:02:46 +0000238 if (!receiving_) {
239 return -1;
240 }
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000241 if (rtp_dump_) {
solenberg@webrtc.orgfc320462014-02-11 15:27:49 +0000242 rtp_dump_->DumpPacket(rtp_packet,
243 static_cast<uint16_t>(rtp_packet_length));
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000244 }
245 }
solenberg@webrtc.orgfc320462014-02-11 15:27:49 +0000246
stefan@webrtc.orga5cb98c2013-05-29 12:12:51 +0000247 RTPHeader header;
solenberg@webrtc.orgfc320462014-02-11 15:27:49 +0000248 if (!rtp_header_parser_->Parse(rtp_packet, rtp_packet_length,
stefan@webrtc.orga5cb98c2013-05-29 12:12:51 +0000249 &header)) {
250 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideo, channel_id_,
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000251 "Incoming packet: Invalid RTP header");
stefan@webrtc.orga5cb98c2013-05-29 12:12:51 +0000252 return -1;
253 }
solenberg@webrtc.orgfc320462014-02-11 15:27:49 +0000254 int payload_length = rtp_packet_length - header.headerLength;
wu@webrtc.orga9890802013-12-13 00:21:03 +0000255 int64_t arrival_time_ms;
256 if (packet_time.timestamp != -1)
257 arrival_time_ms = (packet_time.timestamp + 500) / 1000;
258 else
259 arrival_time_ms = TickTime::MillisecondTimestamp();
260
261 remote_bitrate_estimator_->IncomingPacket(arrival_time_ms,
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000262 payload_length, header);
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000263 header.payload_type_frequency = kVideoPayloadTypeFrequency;
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000264
stefan@webrtc.org48df3812013-11-08 15:18:52 +0000265 bool in_order = IsPacketInOrder(header);
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000266 rtp_receive_statistics_->IncomingPacket(
solenberg@webrtc.orgfc320462014-02-11 15:27:49 +0000267 header, rtp_packet_length, IsPacketRetransmitted(header, in_order));
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000268 rtp_payload_registry_->SetIncomingPayloadType(header);
solenberg@webrtc.orgfc320462014-02-11 15:27:49 +0000269 return ReceivePacket(rtp_packet, rtp_packet_length, header, in_order)
270 ? 0
271 : -1;
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000272}
273
274bool ViEReceiver::ReceivePacket(const uint8_t* packet,
275 int packet_length,
276 const RTPHeader& header,
277 bool in_order) {
278 if (rtp_payload_registry_->IsEncapsulated(header)) {
279 return ParseAndHandleEncapsulatingHeader(packet, packet_length, header);
280 }
281 const uint8_t* payload = packet + header.headerLength;
282 int payload_length = packet_length - header.headerLength;
283 assert(payload_length >= 0);
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000284 PayloadUnion payload_specific;
285 if (!rtp_payload_registry_->GetPayloadSpecifics(header.payloadType,
286 &payload_specific)) {
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000287 return false;
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000288 }
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000289 return rtp_receiver_->IncomingRtpPacket(header, payload, payload_length,
290 payload_specific, in_order);
291}
292
293bool ViEReceiver::ParseAndHandleEncapsulatingHeader(const uint8_t* packet,
294 int packet_length,
295 const RTPHeader& header) {
296 if (rtp_payload_registry_->IsRed(header)) {
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000297 int8_t ulpfec_pt = rtp_payload_registry_->ulpfec_payload_type();
298 if (packet[header.headerLength] == ulpfec_pt)
299 rtp_receive_statistics_->FecPacketReceived(header.ssrc);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000300 if (fec_receiver_->AddReceivedRedPacket(
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000301 header, packet, packet_length, ulpfec_pt) != 0) {
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000302 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideo, channel_id_,
303 "Incoming RED packet error");
304 return false;
305 }
306 return fec_receiver_->ProcessReceivedFec() == 0;
307 } else if (rtp_payload_registry_->IsRtx(header)) {
stefan@webrtc.org7c6ff2d2014-03-19 18:14:52 +0000308 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.
311 return true;
312 }
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000313 // Remove the RTX header and parse the original RTP header.
314 if (packet_length < header.headerLength)
315 return false;
316 if (packet_length > static_cast<int>(sizeof(restored_packet_)))
317 return false;
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");
322 return false;
323 }
324 uint8_t* restored_packet_ptr = restored_packet_;
325 if (!rtp_payload_registry_->RestoreOriginalPacket(
326 &restored_packet_ptr, packet, &packet_length, rtp_receiver_->SSRC(),
327 header)) {
328 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideo, channel_id_,
329 "Incoming RTX packet: invalid RTP header");
330 return false;
331 }
332 restored_packet_in_use_ = true;
333 bool ret = OnRecoveredPacket(restored_packet_ptr, packet_length);
334 restored_packet_in_use_ = false;
335 return ret;
336 }
337 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000338}
339
solenberg@webrtc.orgfc320462014-02-11 15:27:49 +0000340int ViEReceiver::InsertRTCPPacket(const uint8_t* rtcp_packet,
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000341 int rtcp_packet_length) {
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000342 {
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000343 CriticalSectionScoped cs(receive_cs_.get());
braveyao@webrtc.orgb6433b72013-07-26 09:02:46 +0000344 if (!receiving_) {
345 return -1;
346 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000347
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000348 if (rtp_dump_) {
349 rtp_dump_->DumpPacket(
solenberg@webrtc.orgfc320462014-02-11 15:27:49 +0000350 rtcp_packet, static_cast<uint16_t>(rtcp_packet_length));
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000351 }
solenberg@webrtc.orgfc320462014-02-11 15:27:49 +0000352
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000353 std::list<RtpRtcp*>::iterator it = rtp_rtcp_simulcast_.begin();
354 while (it != rtp_rtcp_simulcast_.end()) {
355 RtpRtcp* rtp_rtcp = *it++;
solenberg@webrtc.orgfc320462014-02-11 15:27:49 +0000356 rtp_rtcp->IncomingRtcpPacket(rtcp_packet, rtcp_packet_length);
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000357 }
358 }
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000359 assert(rtp_rtcp_); // Should be set by owner at construction time.
wu@webrtc.orgcd701192014-04-24 22:10:24 +0000360 int ret = rtp_rtcp_->IncomingRtcpPacket(rtcp_packet, rtcp_packet_length);
361 if (ret != 0) {
362 return ret;
363 }
364
365 if (!GetRtcpTimestamp()) {
366 LOG(LS_WARNING) << "Failed to retrieve timestamp information from RTCP SR.";
367 }
368
369 return 0;
370}
371
372bool ViEReceiver::GetRtcpTimestamp() {
373 uint16_t rtt = 0;
374 rtp_rtcp_->RTT(rtp_receiver_->SSRC(), &rtt, NULL, NULL, NULL);
375 if (rtt == 0) {
376 // Waiting for valid rtt.
377 return true;
378 }
379
380 // Update RTCP list
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,
385 &ntp_frac,
386 NULL,
387 NULL,
388 &rtp_timestamp)) {
389 return false;
390 }
391
392 bool new_rtcp_sr = false;
wu@webrtc.org66773a02014-05-07 17:09:44 +0000393 if (!UpdateRtcpList(ntp_secs,
394 ntp_frac,
395 rtp_timestamp,
396 &rtcp_list_,
397 &new_rtcp_sr)) {
wu@webrtc.orgcd701192014-04-24 22:10:24 +0000398 return false;
399 }
400
401 if (!new_rtcp_sr) {
402 // No new RTCP SR since last time this function was called.
403 return true;
404 }
405
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);
412 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000413}
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000414
415void ViEReceiver::StartReceive() {
braveyao@webrtc.orgb6433b72013-07-26 09:02:46 +0000416 CriticalSectionScoped cs(receive_cs_.get());
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000417 receiving_ = true;
418}
419
420void ViEReceiver::StopReceive() {
braveyao@webrtc.orgb6433b72013-07-26 09:02:46 +0000421 CriticalSectionScoped cs(receive_cs_.get());
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000422 receiving_ = false;
423}
424
425int ViEReceiver::StartRTPDump(const char file_nameUTF8[1024]) {
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000426 CriticalSectionScoped cs(receive_cs_.get());
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000427 if (rtp_dump_) {
428 // Restart it if it already exists and is started
429 rtp_dump_->Stop();
430 } else {
431 rtp_dump_ = RtpDump::CreateRtpDump();
432 if (rtp_dump_ == NULL) {
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000433 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, channel_id_,
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000434 "StartRTPDump: Failed to create RTP dump");
435 return -1;
436 }
437 }
438 if (rtp_dump_->Start(file_nameUTF8) != 0) {
439 RtpDump::DestroyRtpDump(rtp_dump_);
440 rtp_dump_ = NULL;
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000441 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, channel_id_,
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000442 "StartRTPDump: Failed to start RTP dump");
443 return -1;
444 }
445 return 0;
446}
447
448int ViEReceiver::StopRTPDump() {
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000449 CriticalSectionScoped cs(receive_cs_.get());
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000450 if (rtp_dump_) {
451 if (rtp_dump_->IsActive()) {
452 rtp_dump_->Stop();
453 } else {
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000454 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, channel_id_,
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000455 "StopRTPDump: Dump not active");
456 }
457 RtpDump::DestroyRtpDump(rtp_dump_);
458 rtp_dump_ = NULL;
459 } else {
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000460 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, channel_id_,
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000461 "StopRTPDump: RTP dump not started");
462 return -1;
463 }
464 return 0;
465}
466
jiayl@webrtc.org1f64f062014-02-10 19:12:14 +0000467void ViEReceiver::GetReceiveBandwidthEstimatorStats(
468 ReceiveBandwidthEstimatorStats* output) const {
469 remote_bitrate_estimator_->GetStats(output);
470}
471
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000472ReceiveStatistics* ViEReceiver::GetReceiveStatistics() const {
473 return rtp_receive_statistics_.get();
474}
475
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000476bool ViEReceiver::IsPacketInOrder(const RTPHeader& header) const {
477 StreamStatistician* statistician =
478 rtp_receive_statistics_->GetStatistician(header.ssrc);
479 if (!statistician)
480 return false;
481 return statistician->IsPacketInOrder(header.sequenceNumber);
482}
483
stefan@webrtc.org48df3812013-11-08 15:18:52 +0000484bool ViEReceiver::IsPacketRetransmitted(const RTPHeader& header,
485 bool in_order) const {
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000486 // Retransmissions are handled separately if RTX is enabled.
487 if (rtp_payload_registry_->RtxEnabled())
488 return false;
489 StreamStatistician* statistician =
490 rtp_receive_statistics_->GetStatistician(header.ssrc);
491 if (!statistician)
492 return false;
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);
stefan@webrtc.org48df3812013-11-08 15:18:52 +0000496 return !in_order &&
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000497 statistician->IsRetransmitOfOldPacket(header, min_rtt);
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000498}
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000499} // namespace webrtc