Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / video_engine / vie_receiver.cc
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/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/tick_util.h"
26 #include "webrtc/system_wrappers/interface/trace.h"
27
28 namespace webrtc {
29
30 ViEReceiver::ViEReceiver(const int32_t channel_id,
31                          VideoCodingModule* module_vcm,
32                          RemoteBitrateEstimator* remote_bitrate_estimator,
33                          RtpFeedback* rtp_feedback)
34     : receive_cs_(CriticalSectionWrapper::CreateCriticalSection()),
35       channel_id_(channel_id),
36       rtp_header_parser_(RtpHeaderParser::Create()),
37       rtp_payload_registry_(new RTPPayloadRegistry(
38           channel_id, RTPPayloadStrategy::CreateStrategy(false))),
39       rtp_receiver_(RtpReceiver::CreateVideoReceiver(
40           channel_id, Clock::GetRealTimeClock(), this, rtp_feedback,
41           rtp_payload_registry_.get())),
42       rtp_receive_statistics_(ReceiveStatistics::Create(
43           Clock::GetRealTimeClock())),
44       fec_receiver_(FecReceiver::Create(channel_id, this)),
45       rtp_rtcp_(NULL),
46       vcm_(module_vcm),
47       remote_bitrate_estimator_(remote_bitrate_estimator),
48       external_decryption_(NULL),
49       decryption_buffer_(NULL),
50       rtp_dump_(NULL),
51       receiving_(false),
52       restored_packet_in_use_(false) {
53   assert(remote_bitrate_estimator);
54 }
55
56 ViEReceiver::~ViEReceiver() {
57   if (decryption_buffer_) {
58     delete[] decryption_buffer_;
59     decryption_buffer_ = NULL;
60   }
61   if (rtp_dump_) {
62     rtp_dump_->Stop();
63     RtpDump::DestroyRtpDump(rtp_dump_);
64     rtp_dump_ = NULL;
65   }
66 }
67
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,
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
81 bool 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
89 void ViEReceiver::SetNackStatus(bool enable,
90                                 int max_nack_reordering_threshold) {
91   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);
99 }
100
101 void ViEReceiver::SetRtxStatus(bool enable, uint32_t ssrc) {
102   rtp_payload_registry_->SetRtxStatus(enable, ssrc);
103 }
104
105 void ViEReceiver::SetRtxPayloadType(uint32_t payload_type) {
106   rtp_payload_registry_->SetRtxPayloadType(payload_type);
107 }
108
109 uint32_t ViEReceiver::GetRemoteSsrc() const {
110   return rtp_receiver_->SSRC();
111 }
112
113 int ViEReceiver::GetCsrcs(uint32_t* csrcs) const {
114   return rtp_receiver_->CSRCs(csrcs);
115 }
116
117 int ViEReceiver::RegisterExternalDecryption(Encryption* decryption) {
118   CriticalSectionScoped cs(receive_cs_.get());
119   if (external_decryption_) {
120     return -1;
121   }
122   decryption_buffer_ = new uint8_t[kViEMaxMtu];
123   if (decryption_buffer_ == NULL) {
124     return -1;
125   }
126   external_decryption_ = decryption;
127   return 0;
128 }
129
130 int ViEReceiver::DeregisterExternalDecryption() {
131   CriticalSectionScoped cs(receive_cs_.get());
132   if (external_decryption_ == NULL) {
133     return -1;
134   }
135   external_decryption_ = NULL;
136   return 0;
137 }
138
139 void ViEReceiver::SetRtpRtcpModule(RtpRtcp* module) {
140   rtp_rtcp_ = module;
141 }
142
143 RtpReceiver* ViEReceiver::GetRtpReceiver() const {
144   return rtp_receiver_.get();
145 }
146
147 void ViEReceiver::RegisterSimulcastRtpRtcpModules(
148     const std::list<RtpRtcp*>& rtp_modules) {
149   CriticalSectionScoped cs(receive_cs_.get());
150   rtp_rtcp_simulcast_.clear();
151
152   if (!rtp_modules.empty()) {
153     rtp_rtcp_simulcast_.insert(rtp_rtcp_simulcast_.begin(),
154                                rtp_modules.begin(),
155                                rtp_modules.end());
156   }
157 }
158
159 bool ViEReceiver::SetReceiveTimestampOffsetStatus(bool enable, int id) {
160   if (enable) {
161     return rtp_header_parser_->RegisterRtpHeaderExtension(
162         kRtpExtensionTransmissionTimeOffset, id);
163   } else {
164     return rtp_header_parser_->DeregisterRtpHeaderExtension(
165         kRtpExtensionTransmissionTimeOffset);
166   }
167 }
168
169 bool ViEReceiver::SetReceiveAbsoluteSendTimeStatus(bool enable, int id) {
170   if (enable) {
171     return rtp_header_parser_->RegisterRtpHeaderExtension(
172         kRtpExtensionAbsoluteSendTime, id);
173   } else {
174     return rtp_header_parser_->DeregisterRtpHeaderExtension(
175         kRtpExtensionAbsoluteSendTime);
176   }
177 }
178
179 int ViEReceiver::ReceivedRTPPacket(const void* rtp_packet,
180                                    int rtp_packet_length,
181                                    const PacketTime& packet_time) {
182   return InsertRTPPacket(static_cast<const int8_t*>(rtp_packet),
183                          rtp_packet_length, packet_time);
184 }
185
186 int ViEReceiver::ReceivedRTCPPacket(const void* rtcp_packet,
187                                     int rtcp_packet_length) {
188   return InsertRTCPPacket(static_cast<const int8_t*>(rtcp_packet),
189                           rtcp_packet_length);
190 }
191
192 int32_t ViEReceiver::OnReceivedPayloadData(
193     const uint8_t* payload_data, const uint16_t payload_size,
194     const WebRtcRTPHeader* rtp_header) {
195   if (vcm_->IncomingPacket(payload_data, payload_size, *rtp_header) != 0) {
196     // Check this...
197     return -1;
198   }
199   return 0;
200 }
201
202 bool ViEReceiver::OnRecoveredPacket(const uint8_t* rtp_packet,
203                                     int rtp_packet_length) {
204   RTPHeader header;
205   if (!rtp_header_parser_->Parse(rtp_packet, rtp_packet_length, &header)) {
206     WEBRTC_TRACE(kTraceDebug, webrtc::kTraceVideo, channel_id_,
207                  "IncomingPacket invalid RTP header");
208     return false;
209   }
210   header.payload_type_frequency = kVideoPayloadTypeFrequency;
211   return ReceivePacket(rtp_packet, rtp_packet_length, header, false);
212 }
213
214 int ViEReceiver::InsertRTPPacket(const int8_t* rtp_packet,
215                                  int rtp_packet_length,
216                                  const PacketTime& packet_time) {
217   // TODO(mflodman) Change decrypt to get rid of this cast.
218   int8_t* tmp_ptr = const_cast<int8_t*>(rtp_packet);
219   unsigned char* received_packet = reinterpret_cast<unsigned char*>(tmp_ptr);
220   int received_packet_length = rtp_packet_length;
221
222   {
223     CriticalSectionScoped cs(receive_cs_.get());
224     if (!receiving_) {
225       return -1;
226     }
227
228     if (external_decryption_) {
229       int decrypted_length = kViEMaxMtu;
230       external_decryption_->decrypt(channel_id_, received_packet,
231                                     decryption_buffer_, received_packet_length,
232                                     &decrypted_length);
233       if (decrypted_length <= 0) {
234         WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, channel_id_,
235                      "RTP decryption failed");
236         return -1;
237       } else if (decrypted_length > kViEMaxMtu) {
238         WEBRTC_TRACE(webrtc::kTraceCritical, webrtc::kTraceVideo, channel_id_,
239                      "InsertRTPPacket: %d bytes is allocated as RTP decrytption"
240                      " output, external decryption used %d bytes. => memory is "
241                      " now corrupted", kViEMaxMtu, decrypted_length);
242         return -1;
243       }
244       received_packet = decryption_buffer_;
245       received_packet_length = decrypted_length;
246     }
247
248     if (rtp_dump_) {
249       rtp_dump_->DumpPacket(received_packet,
250                            static_cast<uint16_t>(received_packet_length));
251     }
252   }
253   RTPHeader header;
254   if (!rtp_header_parser_->Parse(received_packet, received_packet_length,
255                                  &header)) {
256     WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideo, channel_id_,
257                  "Incoming packet: Invalid RTP header");
258     return -1;
259   }
260   int payload_length = received_packet_length - header.headerLength;
261   int64_t arrival_time_ms;
262   if (packet_time.timestamp != -1)
263     arrival_time_ms = (packet_time.timestamp + 500) / 1000;
264   else
265     arrival_time_ms = TickTime::MillisecondTimestamp();
266
267   remote_bitrate_estimator_->IncomingPacket(arrival_time_ms,
268                                             payload_length, header);
269   header.payload_type_frequency = kVideoPayloadTypeFrequency;
270
271   bool in_order = IsPacketInOrder(header);
272   rtp_receive_statistics_->IncomingPacket(
273       header, received_packet_length, IsPacketRetransmitted(header, in_order));
274   rtp_payload_registry_->SetIncomingPayloadType(header);
275   return ReceivePacket(
276              received_packet, received_packet_length, header, in_order)
277              ? 0
278              : -1;
279 }
280
281 bool ViEReceiver::ReceivePacket(const uint8_t* packet,
282                                 int packet_length,
283                                 const RTPHeader& header,
284                                 bool in_order) {
285   if (rtp_payload_registry_->IsEncapsulated(header)) {
286     return ParseAndHandleEncapsulatingHeader(packet, packet_length, header);
287   }
288   const uint8_t* payload = packet + header.headerLength;
289   int payload_length = packet_length - header.headerLength;
290   assert(payload_length >= 0);
291   PayloadUnion payload_specific;
292   if (!rtp_payload_registry_->GetPayloadSpecifics(header.payloadType,
293                                                   &payload_specific)) {
294     return false;
295   }
296   return rtp_receiver_->IncomingRtpPacket(header, payload, payload_length,
297                                           payload_specific, in_order);
298 }
299
300 bool ViEReceiver::ParseAndHandleEncapsulatingHeader(const uint8_t* packet,
301                                                     int packet_length,
302                                                     const RTPHeader& header) {
303   if (rtp_payload_registry_->IsRed(header)) {
304     int8_t ulpfec_pt = rtp_payload_registry_->ulpfec_payload_type();
305     if (packet[header.headerLength] == ulpfec_pt)
306       rtp_receive_statistics_->FecPacketReceived(header.ssrc);
307     if (fec_receiver_->AddReceivedRedPacket(
308             header, packet, packet_length, ulpfec_pt) != 0) {
309       WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideo, channel_id_,
310                    "Incoming RED packet error");
311       return false;
312     }
313     return fec_receiver_->ProcessReceivedFec() == 0;
314   } else if (rtp_payload_registry_->IsRtx(header)) {
315     // Remove the RTX header and parse the original RTP header.
316     if (packet_length < header.headerLength)
317       return false;
318     if (packet_length > static_cast<int>(sizeof(restored_packet_)))
319       return false;
320     CriticalSectionScoped cs(receive_cs_.get());
321     if (restored_packet_in_use_) {
322       WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideo, channel_id_,
323                    "Multiple RTX headers detected, dropping packet");
324       return false;
325     }
326     uint8_t* restored_packet_ptr = restored_packet_;
327     if (!rtp_payload_registry_->RestoreOriginalPacket(
328         &restored_packet_ptr, packet, &packet_length, rtp_receiver_->SSRC(),
329         header)) {
330       WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideo, channel_id_,
331                    "Incoming RTX packet: invalid RTP header");
332       return false;
333     }
334     restored_packet_in_use_ = true;
335     bool ret = OnRecoveredPacket(restored_packet_ptr, packet_length);
336     restored_packet_in_use_ = false;
337     return ret;
338   }
339   return false;
340 }
341
342 int ViEReceiver::InsertRTCPPacket(const int8_t* rtcp_packet,
343                                   int rtcp_packet_length) {
344   // TODO(mflodman) Change decrypt to get rid of this cast.
345   int8_t* tmp_ptr = const_cast<int8_t*>(rtcp_packet);
346   unsigned char* received_packet = reinterpret_cast<unsigned char*>(tmp_ptr);
347   int received_packet_length = rtcp_packet_length;
348   {
349     CriticalSectionScoped cs(receive_cs_.get());
350     if (!receiving_) {
351       return -1;
352     }
353
354     if (external_decryption_) {
355       int decrypted_length = kViEMaxMtu;
356       external_decryption_->decrypt_rtcp(channel_id_, received_packet,
357                                          decryption_buffer_,
358                                          received_packet_length,
359                                          &decrypted_length);
360       if (decrypted_length <= 0) {
361         WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, channel_id_,
362                      "RTP decryption failed");
363         return -1;
364       } else if (decrypted_length > kViEMaxMtu) {
365         WEBRTC_TRACE(webrtc::kTraceCritical, webrtc::kTraceVideo, channel_id_,
366                      "InsertRTCPPacket: %d bytes is allocated as RTP "
367                      " decrytption output, external decryption used %d bytes. "
368                      " => memory is now corrupted",
369                      kViEMaxMtu, decrypted_length);
370         return -1;
371       }
372       received_packet = decryption_buffer_;
373       received_packet_length = decrypted_length;
374     }
375
376     if (rtp_dump_) {
377       rtp_dump_->DumpPacket(
378           received_packet, static_cast<uint16_t>(received_packet_length));
379     }
380   }
381   {
382     CriticalSectionScoped cs(receive_cs_.get());
383     std::list<RtpRtcp*>::iterator it = rtp_rtcp_simulcast_.begin();
384     while (it != rtp_rtcp_simulcast_.end()) {
385       RtpRtcp* rtp_rtcp = *it++;
386       rtp_rtcp->IncomingRtcpPacket(received_packet, received_packet_length);
387     }
388   }
389   assert(rtp_rtcp_);  // Should be set by owner at construction time.
390   return rtp_rtcp_->IncomingRtcpPacket(received_packet, received_packet_length);
391 }
392
393 void ViEReceiver::StartReceive() {
394   CriticalSectionScoped cs(receive_cs_.get());
395   receiving_ = true;
396 }
397
398 void ViEReceiver::StopReceive() {
399   CriticalSectionScoped cs(receive_cs_.get());
400   receiving_ = false;
401 }
402
403 int ViEReceiver::StartRTPDump(const char file_nameUTF8[1024]) {
404   CriticalSectionScoped cs(receive_cs_.get());
405   if (rtp_dump_) {
406     // Restart it if it already exists and is started
407     rtp_dump_->Stop();
408   } else {
409     rtp_dump_ = RtpDump::CreateRtpDump();
410     if (rtp_dump_ == NULL) {
411       WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, channel_id_,
412                    "StartRTPDump: Failed to create RTP dump");
413       return -1;
414     }
415   }
416   if (rtp_dump_->Start(file_nameUTF8) != 0) {
417     RtpDump::DestroyRtpDump(rtp_dump_);
418     rtp_dump_ = NULL;
419     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, channel_id_,
420                  "StartRTPDump: Failed to start RTP dump");
421     return -1;
422   }
423   return 0;
424 }
425
426 int ViEReceiver::StopRTPDump() {
427   CriticalSectionScoped cs(receive_cs_.get());
428   if (rtp_dump_) {
429     if (rtp_dump_->IsActive()) {
430       rtp_dump_->Stop();
431     } else {
432       WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, channel_id_,
433                    "StopRTPDump: Dump not active");
434     }
435     RtpDump::DestroyRtpDump(rtp_dump_);
436     rtp_dump_ = NULL;
437   } else {
438     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, channel_id_,
439                  "StopRTPDump: RTP dump not started");
440     return -1;
441   }
442   return 0;
443 }
444
445 // TODO(holmer): To be moved to ViEChannelGroup.
446 void ViEReceiver::EstimatedReceiveBandwidth(
447     unsigned int* available_bandwidth) const {
448   std::vector<unsigned int> ssrcs;
449
450   // LatestEstimate returns an error if there is no valid bitrate estimate, but
451   // ViEReceiver instead returns a zero estimate.
452   remote_bitrate_estimator_->LatestEstimate(&ssrcs, available_bandwidth);
453   if (std::find(ssrcs.begin(), ssrcs.end(), rtp_receiver_->SSRC()) !=
454       ssrcs.end()) {
455     *available_bandwidth /= ssrcs.size();
456   } else {
457     *available_bandwidth = 0;
458   }
459 }
460
461 ReceiveStatistics* ViEReceiver::GetReceiveStatistics() const {
462   return rtp_receive_statistics_.get();
463 }
464
465 bool ViEReceiver::IsPacketInOrder(const RTPHeader& header) const {
466   StreamStatistician* statistician =
467       rtp_receive_statistics_->GetStatistician(header.ssrc);
468   if (!statistician)
469     return false;
470   return statistician->IsPacketInOrder(header.sequenceNumber);
471 }
472
473 bool ViEReceiver::IsPacketRetransmitted(const RTPHeader& header,
474                                         bool in_order) const {
475   // Retransmissions are handled separately if RTX is enabled.
476   if (rtp_payload_registry_->RtxEnabled())
477     return false;
478   StreamStatistician* statistician =
479       rtp_receive_statistics_->GetStatistician(header.ssrc);
480   if (!statistician)
481     return false;
482   // Check if this is a retransmission.
483   uint16_t min_rtt = 0;
484   rtp_rtcp_->RTT(rtp_receiver_->SSRC(), NULL, NULL, &min_rtt, NULL);
485   return !in_order &&
486       statistician->IsRetransmitOfOldPacket(header, min_rtt);
487 }
488 }  // namespace webrtc