• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "webrtc/video_engine/vie_receiver.h"
12 
13 #include <vector>
14 
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/remote_ntp_time_estimator.h"
19 #include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
20 #include "webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h"
21 #include "webrtc/modules/rtp_rtcp/interface/rtp_receiver.h"
22 #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h"
23 #include "webrtc/modules/utility/interface/rtp_dump.h"
24 #include "webrtc/modules/video_coding/main/interface/video_coding.h"
25 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
26 #include "webrtc/system_wrappers/interface/logging.h"
27 #include "webrtc/system_wrappers/interface/tick_util.h"
28 #include "webrtc/system_wrappers/interface/timestamp_extrapolator.h"
29 #include "webrtc/system_wrappers/interface/trace.h"
30 
31 namespace webrtc {
32 
ViEReceiver(const int32_t channel_id,VideoCodingModule * module_vcm,RemoteBitrateEstimator * remote_bitrate_estimator,RtpFeedback * rtp_feedback)33 ViEReceiver::ViEReceiver(const int32_t channel_id,
34                          VideoCodingModule* module_vcm,
35                          RemoteBitrateEstimator* remote_bitrate_estimator,
36                          RtpFeedback* rtp_feedback)
37     : receive_cs_(CriticalSectionWrapper::CreateCriticalSection()),
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)),
47       rtp_rtcp_(NULL),
48       vcm_(module_vcm),
49       remote_bitrate_estimator_(remote_bitrate_estimator),
50       ntp_estimator_(new RemoteNtpTimeEstimator(Clock::GetRealTimeClock())),
51       rtp_dump_(NULL),
52       receiving_(false),
53       restored_packet_in_use_(false),
54       receiving_ast_enabled_(false) {
55   assert(remote_bitrate_estimator);
56 }
57 
~ViEReceiver()58 ViEReceiver::~ViEReceiver() {
59   if (rtp_dump_) {
60     rtp_dump_->Stop();
61     RtpDump::DestroyRtpDump(rtp_dump_);
62     rtp_dump_ = NULL;
63   }
64 }
65 
SetReceiveCodec(const VideoCodec & video_codec)66 bool ViEReceiver::SetReceiveCodec(const VideoCodec& video_codec) {
67   int8_t old_pltype = -1;
68   if (rtp_payload_registry_->ReceivePayloadType(video_codec.plName,
69                                                 kVideoPayloadTypeFrequency,
70                                                 0,
71                                                 video_codec.maxBitrate,
72                                                 &old_pltype) != -1) {
73     rtp_payload_registry_->DeRegisterReceivePayload(old_pltype);
74   }
75 
76   return RegisterPayload(video_codec);
77 }
78 
RegisterPayload(const VideoCodec & video_codec)79 bool ViEReceiver::RegisterPayload(const VideoCodec& video_codec) {
80   return rtp_receiver_->RegisterReceivePayload(video_codec.plName,
81                                                video_codec.plType,
82                                                kVideoPayloadTypeFrequency,
83                                                0,
84                                                video_codec.maxBitrate) == 0;
85 }
86 
SetNackStatus(bool enable,int max_nack_reordering_threshold)87 void ViEReceiver::SetNackStatus(bool enable,
88                                 int max_nack_reordering_threshold) {
89   if (!enable) {
90     // Reset the threshold back to the lower default threshold when NACK is
91     // disabled since we no longer will be receiving retransmissions.
92     max_nack_reordering_threshold = kDefaultMaxReorderingThreshold;
93   }
94   rtp_receive_statistics_->SetMaxReorderingThreshold(
95       max_nack_reordering_threshold);
96   rtp_receiver_->SetNACKStatus(enable ? kNackRtcp : kNackOff);
97 }
98 
SetRtxPayloadType(int payload_type)99 void ViEReceiver::SetRtxPayloadType(int payload_type) {
100   rtp_payload_registry_->SetRtxPayloadType(payload_type);
101 }
102 
SetRtxSsrc(uint32_t ssrc)103 void ViEReceiver::SetRtxSsrc(uint32_t ssrc) {
104   rtp_payload_registry_->SetRtxSsrc(ssrc);
105 }
106 
GetRemoteSsrc() const107 uint32_t ViEReceiver::GetRemoteSsrc() const {
108   return rtp_receiver_->SSRC();
109 }
110 
GetCsrcs(uint32_t * csrcs) const111 int ViEReceiver::GetCsrcs(uint32_t* csrcs) const {
112   return rtp_receiver_->CSRCs(csrcs);
113 }
114 
SetRtpRtcpModule(RtpRtcp * module)115 void ViEReceiver::SetRtpRtcpModule(RtpRtcp* module) {
116   rtp_rtcp_ = module;
117 }
118 
GetRtpReceiver() const119 RtpReceiver* ViEReceiver::GetRtpReceiver() const {
120   return rtp_receiver_.get();
121 }
122 
RegisterSimulcastRtpRtcpModules(const std::list<RtpRtcp * > & rtp_modules)123 void ViEReceiver::RegisterSimulcastRtpRtcpModules(
124     const std::list<RtpRtcp*>& rtp_modules) {
125   CriticalSectionScoped cs(receive_cs_.get());
126   rtp_rtcp_simulcast_.clear();
127 
128   if (!rtp_modules.empty()) {
129     rtp_rtcp_simulcast_.insert(rtp_rtcp_simulcast_.begin(),
130                                rtp_modules.begin(),
131                                rtp_modules.end());
132   }
133 }
134 
SetReceiveTimestampOffsetStatus(bool enable,int id)135 bool ViEReceiver::SetReceiveTimestampOffsetStatus(bool enable, int id) {
136   if (enable) {
137     return rtp_header_parser_->RegisterRtpHeaderExtension(
138         kRtpExtensionTransmissionTimeOffset, id);
139   } else {
140     return rtp_header_parser_->DeregisterRtpHeaderExtension(
141         kRtpExtensionTransmissionTimeOffset);
142   }
143 }
144 
SetReceiveAbsoluteSendTimeStatus(bool enable,int id)145 bool ViEReceiver::SetReceiveAbsoluteSendTimeStatus(bool enable, int id) {
146   if (enable) {
147     if (rtp_header_parser_->RegisterRtpHeaderExtension(
148         kRtpExtensionAbsoluteSendTime, id)) {
149       receiving_ast_enabled_ = true;
150       return true;
151     } else {
152       return false;
153     }
154   } else {
155     receiving_ast_enabled_ = false;
156     return rtp_header_parser_->DeregisterRtpHeaderExtension(
157         kRtpExtensionAbsoluteSendTime);
158   }
159 }
160 
ReceivedRTPPacket(const void * rtp_packet,int rtp_packet_length,const PacketTime & packet_time)161 int ViEReceiver::ReceivedRTPPacket(const void* rtp_packet,
162                                    int rtp_packet_length,
163                                    const PacketTime& packet_time) {
164   return InsertRTPPacket(static_cast<const uint8_t*>(rtp_packet),
165                          rtp_packet_length, packet_time);
166 }
167 
ReceivedRTCPPacket(const void * rtcp_packet,int rtcp_packet_length)168 int ViEReceiver::ReceivedRTCPPacket(const void* rtcp_packet,
169                                     int rtcp_packet_length) {
170   return InsertRTCPPacket(static_cast<const uint8_t*>(rtcp_packet),
171                           rtcp_packet_length);
172 }
173 
OnReceivedPayloadData(const uint8_t * payload_data,const uint16_t payload_size,const WebRtcRTPHeader * rtp_header)174 int32_t ViEReceiver::OnReceivedPayloadData(
175     const uint8_t* payload_data, const uint16_t payload_size,
176     const WebRtcRTPHeader* rtp_header) {
177   WebRtcRTPHeader rtp_header_with_ntp = *rtp_header;
178   rtp_header_with_ntp.ntp_time_ms =
179       ntp_estimator_->Estimate(rtp_header->header.timestamp);
180   if (vcm_->IncomingPacket(payload_data,
181                            payload_size,
182                            rtp_header_with_ntp) != 0) {
183     // Check this...
184     return -1;
185   }
186   return 0;
187 }
188 
OnRecoveredPacket(const uint8_t * rtp_packet,int rtp_packet_length)189 bool ViEReceiver::OnRecoveredPacket(const uint8_t* rtp_packet,
190                                     int rtp_packet_length) {
191   RTPHeader header;
192   if (!rtp_header_parser_->Parse(rtp_packet, rtp_packet_length, &header)) {
193     return false;
194   }
195   header.payload_type_frequency = kVideoPayloadTypeFrequency;
196   bool in_order = IsPacketInOrder(header);
197   return ReceivePacket(rtp_packet, rtp_packet_length, header, in_order);
198 }
199 
ReceivedBWEPacket(int64_t arrival_time_ms,int payload_size,const RTPHeader & header)200 void ViEReceiver::ReceivedBWEPacket(
201     int64_t arrival_time_ms, int payload_size, const RTPHeader& header) {
202   // Only forward if the incoming packet *and* the channel are both configured
203   // to receive absolute sender time. RTP time stamps may have different rates
204   // for audio and video and shouldn't be mixed.
205   if (header.extension.hasAbsoluteSendTime && receiving_ast_enabled_) {
206     remote_bitrate_estimator_->IncomingPacket(arrival_time_ms, payload_size,
207                                               header);
208   }
209 }
210 
InsertRTPPacket(const uint8_t * rtp_packet,int rtp_packet_length,const PacketTime & packet_time)211 int ViEReceiver::InsertRTPPacket(const uint8_t* rtp_packet,
212                                  int rtp_packet_length,
213                                  const PacketTime& packet_time) {
214   {
215     CriticalSectionScoped cs(receive_cs_.get());
216     if (!receiving_) {
217       return -1;
218     }
219     if (rtp_dump_) {
220       rtp_dump_->DumpPacket(rtp_packet,
221                             static_cast<uint16_t>(rtp_packet_length));
222     }
223   }
224 
225   RTPHeader header;
226   if (!rtp_header_parser_->Parse(rtp_packet, rtp_packet_length,
227                                  &header)) {
228     return -1;
229   }
230   int payload_length = rtp_packet_length - header.headerLength;
231   int64_t arrival_time_ms;
232   if (packet_time.timestamp != -1)
233     arrival_time_ms = (packet_time.timestamp + 500) / 1000;
234   else
235     arrival_time_ms = TickTime::MillisecondTimestamp();
236 
237   remote_bitrate_estimator_->IncomingPacket(arrival_time_ms,
238                                             payload_length, header);
239   header.payload_type_frequency = kVideoPayloadTypeFrequency;
240 
241   bool in_order = IsPacketInOrder(header);
242   rtp_payload_registry_->SetIncomingPayloadType(header);
243   int ret = ReceivePacket(rtp_packet, rtp_packet_length, header, in_order)
244       ? 0
245       : -1;
246   // Update receive statistics after ReceivePacket.
247   // Receive statistics will be reset if the payload type changes (make sure
248   // that the first packet is included in the stats).
249   rtp_receive_statistics_->IncomingPacket(
250       header, rtp_packet_length, IsPacketRetransmitted(header, in_order));
251   return ret;
252 }
253 
ReceivePacket(const uint8_t * packet,int packet_length,const RTPHeader & header,bool in_order)254 bool ViEReceiver::ReceivePacket(const uint8_t* packet,
255                                 int packet_length,
256                                 const RTPHeader& header,
257                                 bool in_order) {
258   if (rtp_payload_registry_->IsEncapsulated(header)) {
259     return ParseAndHandleEncapsulatingHeader(packet, packet_length, header);
260   }
261   const uint8_t* payload = packet + header.headerLength;
262   int payload_length = packet_length - header.headerLength;
263   assert(payload_length >= 0);
264   PayloadUnion payload_specific;
265   if (!rtp_payload_registry_->GetPayloadSpecifics(header.payloadType,
266                                                   &payload_specific)) {
267     return false;
268   }
269   return rtp_receiver_->IncomingRtpPacket(header, payload, payload_length,
270                                           payload_specific, in_order);
271 }
272 
ParseAndHandleEncapsulatingHeader(const uint8_t * packet,int packet_length,const RTPHeader & header)273 bool ViEReceiver::ParseAndHandleEncapsulatingHeader(const uint8_t* packet,
274                                                     int packet_length,
275                                                     const RTPHeader& header) {
276   if (rtp_payload_registry_->IsRed(header)) {
277     int8_t ulpfec_pt = rtp_payload_registry_->ulpfec_payload_type();
278     if (packet[header.headerLength] == ulpfec_pt)
279       rtp_receive_statistics_->FecPacketReceived(header.ssrc);
280     if (fec_receiver_->AddReceivedRedPacket(
281             header, packet, packet_length, ulpfec_pt) != 0) {
282       return false;
283     }
284     return fec_receiver_->ProcessReceivedFec() == 0;
285   } else if (rtp_payload_registry_->IsRtx(header)) {
286     if (header.headerLength + header.paddingLength == packet_length) {
287       // This is an empty packet and should be silently dropped before trying to
288       // parse the RTX header.
289       return true;
290     }
291     // Remove the RTX header and parse the original RTP header.
292     if (packet_length < header.headerLength)
293       return false;
294     if (packet_length > static_cast<int>(sizeof(restored_packet_)))
295       return false;
296     CriticalSectionScoped cs(receive_cs_.get());
297     if (restored_packet_in_use_) {
298       LOG(LS_WARNING) << "Multiple RTX headers detected, dropping packet.";
299       return false;
300     }
301     uint8_t* restored_packet_ptr = restored_packet_;
302     if (!rtp_payload_registry_->RestoreOriginalPacket(
303         &restored_packet_ptr, packet, &packet_length, rtp_receiver_->SSRC(),
304         header)) {
305       LOG(LS_WARNING) << "Incoming RTX packet: Invalid RTP header";
306       return false;
307     }
308     restored_packet_in_use_ = true;
309     bool ret = OnRecoveredPacket(restored_packet_ptr, packet_length);
310     restored_packet_in_use_ = false;
311     return ret;
312   }
313   return false;
314 }
315 
InsertRTCPPacket(const uint8_t * rtcp_packet,int rtcp_packet_length)316 int ViEReceiver::InsertRTCPPacket(const uint8_t* rtcp_packet,
317                                   int rtcp_packet_length) {
318   {
319     CriticalSectionScoped cs(receive_cs_.get());
320     if (!receiving_) {
321       return -1;
322     }
323 
324     if (rtp_dump_) {
325       rtp_dump_->DumpPacket(
326           rtcp_packet, static_cast<uint16_t>(rtcp_packet_length));
327     }
328 
329     std::list<RtpRtcp*>::iterator it = rtp_rtcp_simulcast_.begin();
330     while (it != rtp_rtcp_simulcast_.end()) {
331       RtpRtcp* rtp_rtcp = *it++;
332       rtp_rtcp->IncomingRtcpPacket(rtcp_packet, rtcp_packet_length);
333     }
334   }
335   assert(rtp_rtcp_);  // Should be set by owner at construction time.
336   int ret = rtp_rtcp_->IncomingRtcpPacket(rtcp_packet, rtcp_packet_length);
337   if (ret != 0) {
338     return ret;
339   }
340 
341   ntp_estimator_->UpdateRtcpTimestamp(rtp_receiver_->SSRC(), rtp_rtcp_);
342 
343   return 0;
344 }
345 
StartReceive()346 void ViEReceiver::StartReceive() {
347   CriticalSectionScoped cs(receive_cs_.get());
348   receiving_ = true;
349 }
350 
StopReceive()351 void ViEReceiver::StopReceive() {
352   CriticalSectionScoped cs(receive_cs_.get());
353   receiving_ = false;
354 }
355 
StartRTPDump(const char file_nameUTF8[1024])356 int ViEReceiver::StartRTPDump(const char file_nameUTF8[1024]) {
357   CriticalSectionScoped cs(receive_cs_.get());
358   if (rtp_dump_) {
359     // Restart it if it already exists and is started
360     rtp_dump_->Stop();
361   } else {
362     rtp_dump_ = RtpDump::CreateRtpDump();
363     if (rtp_dump_ == NULL) {
364       return -1;
365     }
366   }
367   if (rtp_dump_->Start(file_nameUTF8) != 0) {
368     RtpDump::DestroyRtpDump(rtp_dump_);
369     rtp_dump_ = NULL;
370     return -1;
371   }
372   return 0;
373 }
374 
StopRTPDump()375 int ViEReceiver::StopRTPDump() {
376   CriticalSectionScoped cs(receive_cs_.get());
377   if (rtp_dump_) {
378     if (rtp_dump_->IsActive()) {
379       rtp_dump_->Stop();
380     }
381     RtpDump::DestroyRtpDump(rtp_dump_);
382     rtp_dump_ = NULL;
383   } else {
384     return -1;
385   }
386   return 0;
387 }
388 
GetReceiveBandwidthEstimatorStats(ReceiveBandwidthEstimatorStats * output) const389 void ViEReceiver::GetReceiveBandwidthEstimatorStats(
390     ReceiveBandwidthEstimatorStats* output) const {
391   remote_bitrate_estimator_->GetStats(output);
392 }
393 
GetReceiveStatistics() const394 ReceiveStatistics* ViEReceiver::GetReceiveStatistics() const {
395   return rtp_receive_statistics_.get();
396 }
397 
IsPacketInOrder(const RTPHeader & header) const398 bool ViEReceiver::IsPacketInOrder(const RTPHeader& header) const {
399   StreamStatistician* statistician =
400       rtp_receive_statistics_->GetStatistician(header.ssrc);
401   if (!statistician)
402     return false;
403   return statistician->IsPacketInOrder(header.sequenceNumber);
404 }
405 
IsPacketRetransmitted(const RTPHeader & header,bool in_order) const406 bool ViEReceiver::IsPacketRetransmitted(const RTPHeader& header,
407                                         bool in_order) const {
408   // Retransmissions are handled separately if RTX is enabled.
409   if (rtp_payload_registry_->RtxEnabled())
410     return false;
411   StreamStatistician* statistician =
412       rtp_receive_statistics_->GetStatistician(header.ssrc);
413   if (!statistician)
414     return false;
415   // Check if this is a retransmission.
416   uint16_t min_rtt = 0;
417   rtp_rtcp_->RTT(rtp_receiver_->SSRC(), NULL, NULL, &min_rtt, NULL);
418   return !in_order &&
419       statistician->IsRetransmitOfOldPacket(header, min_rtt);
420 }
421 }  // namespace webrtc
422