• 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   return ReceivePacket(rtp_packet, rtp_packet_length, header, false);
197 }
198 
ReceivedBWEPacket(int64_t arrival_time_ms,int payload_size,const RTPHeader & header)199 void ViEReceiver::ReceivedBWEPacket(
200     int64_t arrival_time_ms, int payload_size, const RTPHeader& header) {
201   // Only forward if the incoming packet *and* the channel are both configured
202   // to receive absolute sender time. RTP time stamps may have different rates
203   // for audio and video and shouldn't be mixed.
204   if (header.extension.hasAbsoluteSendTime && receiving_ast_enabled_) {
205     remote_bitrate_estimator_->IncomingPacket(arrival_time_ms, payload_size,
206                                               header);
207   }
208 }
209 
InsertRTPPacket(const uint8_t * rtp_packet,int rtp_packet_length,const PacketTime & packet_time)210 int ViEReceiver::InsertRTPPacket(const uint8_t* rtp_packet,
211                                  int rtp_packet_length,
212                                  const PacketTime& packet_time) {
213   {
214     CriticalSectionScoped cs(receive_cs_.get());
215     if (!receiving_) {
216       return -1;
217     }
218     if (rtp_dump_) {
219       rtp_dump_->DumpPacket(rtp_packet,
220                             static_cast<uint16_t>(rtp_packet_length));
221     }
222   }
223 
224   RTPHeader header;
225   if (!rtp_header_parser_->Parse(rtp_packet, rtp_packet_length,
226                                  &header)) {
227     return -1;
228   }
229   int payload_length = rtp_packet_length - header.headerLength;
230   int64_t arrival_time_ms;
231   if (packet_time.timestamp != -1)
232     arrival_time_ms = (packet_time.timestamp + 500) / 1000;
233   else
234     arrival_time_ms = TickTime::MillisecondTimestamp();
235 
236   remote_bitrate_estimator_->IncomingPacket(arrival_time_ms,
237                                             payload_length, header);
238   header.payload_type_frequency = kVideoPayloadTypeFrequency;
239 
240   bool in_order = IsPacketInOrder(header);
241   rtp_payload_registry_->SetIncomingPayloadType(header);
242   int ret = ReceivePacket(rtp_packet, rtp_packet_length, header, in_order)
243       ? 0
244       : -1;
245   // Update receive statistics after ReceivePacket.
246   // Receive statistics will be reset if the payload type changes (make sure
247   // that the first packet is included in the stats).
248   rtp_receive_statistics_->IncomingPacket(
249       header, rtp_packet_length, IsPacketRetransmitted(header, in_order));
250   return ret;
251 }
252 
ReceivePacket(const uint8_t * packet,int packet_length,const RTPHeader & header,bool in_order)253 bool ViEReceiver::ReceivePacket(const uint8_t* packet,
254                                 int packet_length,
255                                 const RTPHeader& header,
256                                 bool in_order) {
257   if (rtp_payload_registry_->IsEncapsulated(header)) {
258     return ParseAndHandleEncapsulatingHeader(packet, packet_length, header);
259   }
260   const uint8_t* payload = packet + header.headerLength;
261   int payload_length = packet_length - header.headerLength;
262   assert(payload_length >= 0);
263   PayloadUnion payload_specific;
264   if (!rtp_payload_registry_->GetPayloadSpecifics(header.payloadType,
265                                                   &payload_specific)) {
266     return false;
267   }
268   return rtp_receiver_->IncomingRtpPacket(header, payload, payload_length,
269                                           payload_specific, in_order);
270 }
271 
ParseAndHandleEncapsulatingHeader(const uint8_t * packet,int packet_length,const RTPHeader & header)272 bool ViEReceiver::ParseAndHandleEncapsulatingHeader(const uint8_t* packet,
273                                                     int packet_length,
274                                                     const RTPHeader& header) {
275   if (rtp_payload_registry_->IsRed(header)) {
276     int8_t ulpfec_pt = rtp_payload_registry_->ulpfec_payload_type();
277     if (packet[header.headerLength] == ulpfec_pt)
278       rtp_receive_statistics_->FecPacketReceived(header.ssrc);
279     if (fec_receiver_->AddReceivedRedPacket(
280             header, packet, packet_length, ulpfec_pt) != 0) {
281       return false;
282     }
283     return fec_receiver_->ProcessReceivedFec() == 0;
284   } else if (rtp_payload_registry_->IsRtx(header)) {
285     if (header.headerLength + header.paddingLength == packet_length) {
286       // This is an empty packet and should be silently dropped before trying to
287       // parse the RTX header.
288       return true;
289     }
290     // Remove the RTX header and parse the original RTP header.
291     if (packet_length < header.headerLength)
292       return false;
293     if (packet_length > static_cast<int>(sizeof(restored_packet_)))
294       return false;
295     CriticalSectionScoped cs(receive_cs_.get());
296     if (restored_packet_in_use_) {
297       LOG(LS_WARNING) << "Multiple RTX headers detected, dropping packet.";
298       return false;
299     }
300     uint8_t* restored_packet_ptr = restored_packet_;
301     if (!rtp_payload_registry_->RestoreOriginalPacket(
302         &restored_packet_ptr, packet, &packet_length, rtp_receiver_->SSRC(),
303         header)) {
304       LOG(LS_WARNING) << "Incoming RTX packet: Invalid RTP header";
305       return false;
306     }
307     restored_packet_in_use_ = true;
308     bool ret = OnRecoveredPacket(restored_packet_ptr, packet_length);
309     restored_packet_in_use_ = false;
310     return ret;
311   }
312   return false;
313 }
314 
InsertRTCPPacket(const uint8_t * rtcp_packet,int rtcp_packet_length)315 int ViEReceiver::InsertRTCPPacket(const uint8_t* rtcp_packet,
316                                   int rtcp_packet_length) {
317   {
318     CriticalSectionScoped cs(receive_cs_.get());
319     if (!receiving_) {
320       return -1;
321     }
322 
323     if (rtp_dump_) {
324       rtp_dump_->DumpPacket(
325           rtcp_packet, static_cast<uint16_t>(rtcp_packet_length));
326     }
327 
328     std::list<RtpRtcp*>::iterator it = rtp_rtcp_simulcast_.begin();
329     while (it != rtp_rtcp_simulcast_.end()) {
330       RtpRtcp* rtp_rtcp = *it++;
331       rtp_rtcp->IncomingRtcpPacket(rtcp_packet, rtcp_packet_length);
332     }
333   }
334   assert(rtp_rtcp_);  // Should be set by owner at construction time.
335   int ret = rtp_rtcp_->IncomingRtcpPacket(rtcp_packet, rtcp_packet_length);
336   if (ret != 0) {
337     return ret;
338   }
339 
340   ntp_estimator_->UpdateRtcpTimestamp(rtp_receiver_->SSRC(), rtp_rtcp_);
341 
342   return 0;
343 }
344 
StartReceive()345 void ViEReceiver::StartReceive() {
346   CriticalSectionScoped cs(receive_cs_.get());
347   receiving_ = true;
348 }
349 
StopReceive()350 void ViEReceiver::StopReceive() {
351   CriticalSectionScoped cs(receive_cs_.get());
352   receiving_ = false;
353 }
354 
StartRTPDump(const char file_nameUTF8[1024])355 int ViEReceiver::StartRTPDump(const char file_nameUTF8[1024]) {
356   CriticalSectionScoped cs(receive_cs_.get());
357   if (rtp_dump_) {
358     // Restart it if it already exists and is started
359     rtp_dump_->Stop();
360   } else {
361     rtp_dump_ = RtpDump::CreateRtpDump();
362     if (rtp_dump_ == NULL) {
363       return -1;
364     }
365   }
366   if (rtp_dump_->Start(file_nameUTF8) != 0) {
367     RtpDump::DestroyRtpDump(rtp_dump_);
368     rtp_dump_ = NULL;
369     return -1;
370   }
371   return 0;
372 }
373 
StopRTPDump()374 int ViEReceiver::StopRTPDump() {
375   CriticalSectionScoped cs(receive_cs_.get());
376   if (rtp_dump_) {
377     if (rtp_dump_->IsActive()) {
378       rtp_dump_->Stop();
379     }
380     RtpDump::DestroyRtpDump(rtp_dump_);
381     rtp_dump_ = NULL;
382   } else {
383     return -1;
384   }
385   return 0;
386 }
387 
GetReceiveBandwidthEstimatorStats(ReceiveBandwidthEstimatorStats * output) const388 void ViEReceiver::GetReceiveBandwidthEstimatorStats(
389     ReceiveBandwidthEstimatorStats* output) const {
390   remote_bitrate_estimator_->GetStats(output);
391 }
392 
GetReceiveStatistics() const393 ReceiveStatistics* ViEReceiver::GetReceiveStatistics() const {
394   return rtp_receive_statistics_.get();
395 }
396 
IsPacketInOrder(const RTPHeader & header) const397 bool ViEReceiver::IsPacketInOrder(const RTPHeader& header) const {
398   StreamStatistician* statistician =
399       rtp_receive_statistics_->GetStatistician(header.ssrc);
400   if (!statistician)
401     return false;
402   return statistician->IsPacketInOrder(header.sequenceNumber);
403 }
404 
IsPacketRetransmitted(const RTPHeader & header,bool in_order) const405 bool ViEReceiver::IsPacketRetransmitted(const RTPHeader& header,
406                                         bool in_order) const {
407   // Retransmissions are handled separately if RTX is enabled.
408   if (rtp_payload_registry_->RtxEnabled())
409     return false;
410   StreamStatistician* statistician =
411       rtp_receive_statistics_->GetStatistician(header.ssrc);
412   if (!statistician)
413     return false;
414   // Check if this is a retransmission.
415   uint16_t min_rtt = 0;
416   rtp_rtcp_->RTT(rtp_receiver_->SSRC(), NULL, NULL, &min_rtt, NULL);
417   return !in_order &&
418       statistician->IsRetransmitOfOldPacket(header, min_rtt);
419 }
420 }  // namespace webrtc
421