- add third_party src.
[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   return InsertRTPPacket(static_cast<const int8_t*>(rtp_packet),
182                          rtp_packet_length);
183 }
184
185 int ViEReceiver::ReceivedRTCPPacket(const void* rtcp_packet,
186                                     int rtcp_packet_length) {
187   return InsertRTCPPacket(static_cast<const int8_t*>(rtcp_packet),
188                           rtcp_packet_length);
189 }
190
191 int32_t ViEReceiver::OnReceivedPayloadData(
192     const uint8_t* payload_data, const uint16_t payload_size,
193     const WebRtcRTPHeader* rtp_header) {
194   if (vcm_->IncomingPacket(payload_data, payload_size, *rtp_header) != 0) {
195     // Check this...
196     return -1;
197   }
198   return 0;
199 }
200
201 bool ViEReceiver::OnRecoveredPacket(const uint8_t* rtp_packet,
202                                     int rtp_packet_length) {
203   RTPHeader header;
204   if (!rtp_header_parser_->Parse(rtp_packet, rtp_packet_length, &header)) {
205     WEBRTC_TRACE(kTraceDebug, webrtc::kTraceVideo, channel_id_,
206                  "IncomingPacket invalid RTP header");
207     return false;
208   }
209   header.payload_type_frequency = kVideoPayloadTypeFrequency;
210   return ReceivePacket(rtp_packet, rtp_packet_length, header, false);
211 }
212
213 int ViEReceiver::InsertRTPPacket(const int8_t* rtp_packet,
214                                  int rtp_packet_length) {
215   // TODO(mflodman) Change decrypt to get rid of this cast.
216   int8_t* tmp_ptr = const_cast<int8_t*>(rtp_packet);
217   unsigned char* received_packet = reinterpret_cast<unsigned char*>(tmp_ptr);
218   int received_packet_length = rtp_packet_length;
219
220   {
221     CriticalSectionScoped cs(receive_cs_.get());
222     if (!receiving_) {
223       return -1;
224     }
225
226     if (external_decryption_) {
227       int decrypted_length = kViEMaxMtu;
228       external_decryption_->decrypt(channel_id_, received_packet,
229                                     decryption_buffer_, received_packet_length,
230                                     &decrypted_length);
231       if (decrypted_length <= 0) {
232         WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, channel_id_,
233                      "RTP decryption failed");
234         return -1;
235       } else if (decrypted_length > kViEMaxMtu) {
236         WEBRTC_TRACE(webrtc::kTraceCritical, webrtc::kTraceVideo, channel_id_,
237                      "InsertRTPPacket: %d bytes is allocated as RTP decrytption"
238                      " output, external decryption used %d bytes. => memory is "
239                      " now corrupted", kViEMaxMtu, decrypted_length);
240         return -1;
241       }
242       received_packet = decryption_buffer_;
243       received_packet_length = decrypted_length;
244     }
245
246     if (rtp_dump_) {
247       rtp_dump_->DumpPacket(received_packet,
248                            static_cast<uint16_t>(received_packet_length));
249     }
250   }
251   RTPHeader header;
252   if (!rtp_header_parser_->Parse(received_packet, received_packet_length,
253                                  &header)) {
254     WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideo, channel_id_,
255                  "Incoming packet: Invalid RTP header");
256     return -1;
257   }
258   int payload_length = received_packet_length - header.headerLength;
259   remote_bitrate_estimator_->IncomingPacket(TickTime::MillisecondTimestamp(),
260                                             payload_length, header);
261   header.payload_type_frequency = kVideoPayloadTypeFrequency;
262
263   rtp_receive_statistics_->IncomingPacket(header, received_packet_length,
264                                           IsPacketRetransmitted(header));
265   rtp_payload_registry_->SetIncomingPayloadType(header);
266   return ReceivePacket(received_packet, received_packet_length, header,
267                        IsPacketInOrder(header)) ? 0 : -1;
268 }
269
270 bool ViEReceiver::ReceivePacket(const uint8_t* packet,
271                                 int packet_length,
272                                 const RTPHeader& header,
273                                 bool in_order) {
274   if (rtp_payload_registry_->IsEncapsulated(header)) {
275     return ParseAndHandleEncapsulatingHeader(packet, packet_length, header);
276   }
277   const uint8_t* payload = packet + header.headerLength;
278   int payload_length = packet_length - header.headerLength;
279   assert(payload_length >= 0);
280   PayloadUnion payload_specific;
281   if (!rtp_payload_registry_->GetPayloadSpecifics(header.payloadType,
282                                                   &payload_specific)) {
283     return false;
284   }
285   return rtp_receiver_->IncomingRtpPacket(header, payload, payload_length,
286                                           payload_specific, in_order);
287 }
288
289 bool ViEReceiver::ParseAndHandleEncapsulatingHeader(const uint8_t* packet,
290                                                     int packet_length,
291                                                     const RTPHeader& header) {
292   if (rtp_payload_registry_->IsRed(header)) {
293     if (fec_receiver_->AddReceivedRedPacket(
294         header, packet, packet_length,
295         rtp_payload_registry_->ulpfec_payload_type()) != 0) {
296       WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideo, channel_id_,
297                    "Incoming RED packet error");
298       return false;
299     }
300     return fec_receiver_->ProcessReceivedFec() == 0;
301   } else if (rtp_payload_registry_->IsRtx(header)) {
302     // Remove the RTX header and parse the original RTP header.
303     if (packet_length < header.headerLength)
304       return false;
305     if (packet_length > static_cast<int>(sizeof(restored_packet_)))
306       return false;
307     CriticalSectionScoped cs(receive_cs_.get());
308     if (restored_packet_in_use_) {
309       WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideo, channel_id_,
310                    "Multiple RTX headers detected, dropping packet");
311       return false;
312     }
313     uint8_t* restored_packet_ptr = restored_packet_;
314     if (!rtp_payload_registry_->RestoreOriginalPacket(
315         &restored_packet_ptr, packet, &packet_length, rtp_receiver_->SSRC(),
316         header)) {
317       WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideo, channel_id_,
318                    "Incoming RTX packet: invalid RTP header");
319       return false;
320     }
321     restored_packet_in_use_ = true;
322     bool ret = OnRecoveredPacket(restored_packet_ptr, packet_length);
323     restored_packet_in_use_ = false;
324     return ret;
325   }
326   return false;
327 }
328
329 int ViEReceiver::InsertRTCPPacket(const int8_t* rtcp_packet,
330                                   int rtcp_packet_length) {
331   // TODO(mflodman) Change decrypt to get rid of this cast.
332   int8_t* tmp_ptr = const_cast<int8_t*>(rtcp_packet);
333   unsigned char* received_packet = reinterpret_cast<unsigned char*>(tmp_ptr);
334   int received_packet_length = rtcp_packet_length;
335   {
336     CriticalSectionScoped cs(receive_cs_.get());
337     if (!receiving_) {
338       return -1;
339     }
340
341     if (external_decryption_) {
342       int decrypted_length = kViEMaxMtu;
343       external_decryption_->decrypt_rtcp(channel_id_, received_packet,
344                                          decryption_buffer_,
345                                          received_packet_length,
346                                          &decrypted_length);
347       if (decrypted_length <= 0) {
348         WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, channel_id_,
349                      "RTP decryption failed");
350         return -1;
351       } else if (decrypted_length > kViEMaxMtu) {
352         WEBRTC_TRACE(webrtc::kTraceCritical, webrtc::kTraceVideo, channel_id_,
353                      "InsertRTCPPacket: %d bytes is allocated as RTP "
354                      " decrytption output, external decryption used %d bytes. "
355                      " => memory is now corrupted",
356                      kViEMaxMtu, decrypted_length);
357         return -1;
358       }
359       received_packet = decryption_buffer_;
360       received_packet_length = decrypted_length;
361     }
362
363     if (rtp_dump_) {
364       rtp_dump_->DumpPacket(
365           received_packet, static_cast<uint16_t>(received_packet_length));
366     }
367   }
368   {
369     CriticalSectionScoped cs(receive_cs_.get());
370     std::list<RtpRtcp*>::iterator it = rtp_rtcp_simulcast_.begin();
371     while (it != rtp_rtcp_simulcast_.end()) {
372       RtpRtcp* rtp_rtcp = *it++;
373       rtp_rtcp->IncomingRtcpPacket(received_packet, received_packet_length);
374     }
375   }
376   assert(rtp_rtcp_);  // Should be set by owner at construction time.
377   return rtp_rtcp_->IncomingRtcpPacket(received_packet, received_packet_length);
378 }
379
380 void ViEReceiver::StartReceive() {
381   CriticalSectionScoped cs(receive_cs_.get());
382   receiving_ = true;
383 }
384
385 void ViEReceiver::StopReceive() {
386   CriticalSectionScoped cs(receive_cs_.get());
387   receiving_ = false;
388 }
389
390 int ViEReceiver::StartRTPDump(const char file_nameUTF8[1024]) {
391   CriticalSectionScoped cs(receive_cs_.get());
392   if (rtp_dump_) {
393     // Restart it if it already exists and is started
394     rtp_dump_->Stop();
395   } else {
396     rtp_dump_ = RtpDump::CreateRtpDump();
397     if (rtp_dump_ == NULL) {
398       WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, channel_id_,
399                    "StartRTPDump: Failed to create RTP dump");
400       return -1;
401     }
402   }
403   if (rtp_dump_->Start(file_nameUTF8) != 0) {
404     RtpDump::DestroyRtpDump(rtp_dump_);
405     rtp_dump_ = NULL;
406     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, channel_id_,
407                  "StartRTPDump: Failed to start RTP dump");
408     return -1;
409   }
410   return 0;
411 }
412
413 int ViEReceiver::StopRTPDump() {
414   CriticalSectionScoped cs(receive_cs_.get());
415   if (rtp_dump_) {
416     if (rtp_dump_->IsActive()) {
417       rtp_dump_->Stop();
418     } else {
419       WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, channel_id_,
420                    "StopRTPDump: Dump not active");
421     }
422     RtpDump::DestroyRtpDump(rtp_dump_);
423     rtp_dump_ = NULL;
424   } else {
425     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, channel_id_,
426                  "StopRTPDump: RTP dump not started");
427     return -1;
428   }
429   return 0;
430 }
431
432 // TODO(holmer): To be moved to ViEChannelGroup.
433 void ViEReceiver::EstimatedReceiveBandwidth(
434     unsigned int* available_bandwidth) const {
435   std::vector<unsigned int> ssrcs;
436
437   // LatestEstimate returns an error if there is no valid bitrate estimate, but
438   // ViEReceiver instead returns a zero estimate.
439   remote_bitrate_estimator_->LatestEstimate(&ssrcs, available_bandwidth);
440   if (std::find(ssrcs.begin(), ssrcs.end(), rtp_receiver_->SSRC()) !=
441       ssrcs.end()) {
442     *available_bandwidth /= ssrcs.size();
443   } else {
444     *available_bandwidth = 0;
445   }
446 }
447
448 ReceiveStatistics* ViEReceiver::GetReceiveStatistics() const {
449   return rtp_receive_statistics_.get();
450 }
451
452 bool ViEReceiver::IsPacketInOrder(const RTPHeader& header) const {
453   StreamStatistician* statistician =
454       rtp_receive_statistics_->GetStatistician(header.ssrc);
455   if (!statistician)
456     return false;
457   return statistician->IsPacketInOrder(header.sequenceNumber);
458 }
459
460 bool ViEReceiver::IsPacketRetransmitted(const RTPHeader& header) const {
461   // Retransmissions are handled separately if RTX is enabled.
462   if (rtp_payload_registry_->RtxEnabled())
463     return false;
464   StreamStatistician* statistician =
465       rtp_receive_statistics_->GetStatistician(header.ssrc);
466   if (!statistician)
467     return false;
468   // Check if this is a retransmission.
469   uint16_t min_rtt = 0;
470   rtp_rtcp_->RTT(rtp_receiver_->SSRC(), NULL, NULL, &min_rtt, NULL);
471   return !IsPacketInOrder(header) &&
472       statistician->IsRetransmitOfOldPacket(header, min_rtt);
473 }
474 }  // namespace webrtc