Upstream version 5.34.104.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       rtp_dump_(NULL),
49       receiving_(false),
50       restored_packet_in_use_(false) {
51   assert(remote_bitrate_estimator);
52 }
53
54 ViEReceiver::~ViEReceiver() {
55   if (rtp_dump_) {
56     rtp_dump_->Stop();
57     RtpDump::DestroyRtpDump(rtp_dump_);
58     rtp_dump_ = NULL;
59   }
60 }
61
62 bool ViEReceiver::SetReceiveCodec(const VideoCodec& video_codec) {
63   int8_t old_pltype = -1;
64   if (rtp_payload_registry_->ReceivePayloadType(video_codec.plName,
65                                                 kVideoPayloadTypeFrequency,
66                                                 0,
67                                                 video_codec.maxBitrate,
68                                                 &old_pltype) != -1) {
69     rtp_payload_registry_->DeRegisterReceivePayload(old_pltype);
70   }
71
72   return RegisterPayload(video_codec);
73 }
74
75 bool ViEReceiver::RegisterPayload(const VideoCodec& video_codec) {
76   return rtp_receiver_->RegisterReceivePayload(video_codec.plName,
77                                                video_codec.plType,
78                                                kVideoPayloadTypeFrequency,
79                                                0,
80                                                video_codec.maxBitrate) == 0;
81 }
82
83 void ViEReceiver::SetNackStatus(bool enable,
84                                 int max_nack_reordering_threshold) {
85   if (!enable) {
86     // Reset the threshold back to the lower default threshold when NACK is
87     // disabled since we no longer will be receiving retransmissions.
88     max_nack_reordering_threshold = kDefaultMaxReorderingThreshold;
89   }
90   rtp_receive_statistics_->SetMaxReorderingThreshold(
91       max_nack_reordering_threshold);
92   rtp_receiver_->SetNACKStatus(enable ? kNackRtcp : kNackOff);
93 }
94
95 void ViEReceiver::SetRtxStatus(bool enable, uint32_t ssrc) {
96   rtp_payload_registry_->SetRtxStatus(enable, ssrc);
97 }
98
99 void ViEReceiver::SetRtxPayloadType(uint32_t payload_type) {
100   rtp_payload_registry_->SetRtxPayloadType(payload_type);
101 }
102
103 uint32_t ViEReceiver::GetRemoteSsrc() const {
104   return rtp_receiver_->SSRC();
105 }
106
107 int ViEReceiver::GetCsrcs(uint32_t* csrcs) const {
108   return rtp_receiver_->CSRCs(csrcs);
109 }
110
111 void ViEReceiver::SetRtpRtcpModule(RtpRtcp* module) {
112   rtp_rtcp_ = module;
113 }
114
115 RtpReceiver* ViEReceiver::GetRtpReceiver() const {
116   return rtp_receiver_.get();
117 }
118
119 void ViEReceiver::RegisterSimulcastRtpRtcpModules(
120     const std::list<RtpRtcp*>& rtp_modules) {
121   CriticalSectionScoped cs(receive_cs_.get());
122   rtp_rtcp_simulcast_.clear();
123
124   if (!rtp_modules.empty()) {
125     rtp_rtcp_simulcast_.insert(rtp_rtcp_simulcast_.begin(),
126                                rtp_modules.begin(),
127                                rtp_modules.end());
128   }
129 }
130
131 bool ViEReceiver::SetReceiveTimestampOffsetStatus(bool enable, int id) {
132   if (enable) {
133     return rtp_header_parser_->RegisterRtpHeaderExtension(
134         kRtpExtensionTransmissionTimeOffset, id);
135   } else {
136     return rtp_header_parser_->DeregisterRtpHeaderExtension(
137         kRtpExtensionTransmissionTimeOffset);
138   }
139 }
140
141 bool ViEReceiver::SetReceiveAbsoluteSendTimeStatus(bool enable, int id) {
142   if (enable) {
143     return rtp_header_parser_->RegisterRtpHeaderExtension(
144         kRtpExtensionAbsoluteSendTime, id);
145   } else {
146     return rtp_header_parser_->DeregisterRtpHeaderExtension(
147         kRtpExtensionAbsoluteSendTime);
148   }
149 }
150
151 int ViEReceiver::ReceivedRTPPacket(const void* rtp_packet,
152                                    int rtp_packet_length,
153                                    const PacketTime& packet_time) {
154   return InsertRTPPacket(static_cast<const uint8_t*>(rtp_packet),
155                          rtp_packet_length, packet_time);
156 }
157
158 int ViEReceiver::ReceivedRTCPPacket(const void* rtcp_packet,
159                                     int rtcp_packet_length) {
160   return InsertRTCPPacket(static_cast<const uint8_t*>(rtcp_packet),
161                           rtcp_packet_length);
162 }
163
164 int32_t ViEReceiver::OnReceivedPayloadData(
165     const uint8_t* payload_data, const uint16_t payload_size,
166     const WebRtcRTPHeader* rtp_header) {
167   if (vcm_->IncomingPacket(payload_data, payload_size, *rtp_header) != 0) {
168     // Check this...
169     return -1;
170   }
171   return 0;
172 }
173
174 bool ViEReceiver::OnRecoveredPacket(const uint8_t* rtp_packet,
175                                     int rtp_packet_length) {
176   RTPHeader header;
177   if (!rtp_header_parser_->Parse(rtp_packet, rtp_packet_length, &header)) {
178     WEBRTC_TRACE(kTraceDebug, webrtc::kTraceVideo, channel_id_,
179                  "IncomingPacket invalid RTP header");
180     return false;
181   }
182   header.payload_type_frequency = kVideoPayloadTypeFrequency;
183   return ReceivePacket(rtp_packet, rtp_packet_length, header, false);
184 }
185
186 int ViEReceiver::InsertRTPPacket(const uint8_t* rtp_packet,
187                                  int rtp_packet_length,
188                                  const PacketTime& packet_time) {
189   {
190     CriticalSectionScoped cs(receive_cs_.get());
191     if (!receiving_) {
192       return -1;
193     }
194     if (rtp_dump_) {
195       rtp_dump_->DumpPacket(rtp_packet,
196                             static_cast<uint16_t>(rtp_packet_length));
197     }
198   }
199
200   RTPHeader header;
201   if (!rtp_header_parser_->Parse(rtp_packet, rtp_packet_length,
202                                  &header)) {
203     WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideo, channel_id_,
204                  "Incoming packet: Invalid RTP header");
205     return -1;
206   }
207   int payload_length = rtp_packet_length - header.headerLength;
208   int64_t arrival_time_ms;
209   if (packet_time.timestamp != -1)
210     arrival_time_ms = (packet_time.timestamp + 500) / 1000;
211   else
212     arrival_time_ms = TickTime::MillisecondTimestamp();
213
214   remote_bitrate_estimator_->IncomingPacket(arrival_time_ms,
215                                             payload_length, header);
216   header.payload_type_frequency = kVideoPayloadTypeFrequency;
217
218   bool in_order = IsPacketInOrder(header);
219   rtp_receive_statistics_->IncomingPacket(
220       header, rtp_packet_length, IsPacketRetransmitted(header, in_order));
221   rtp_payload_registry_->SetIncomingPayloadType(header);
222   return ReceivePacket(rtp_packet, rtp_packet_length, header, in_order)
223       ? 0
224       : -1;
225 }
226
227 bool ViEReceiver::ReceivePacket(const uint8_t* packet,
228                                 int packet_length,
229                                 const RTPHeader& header,
230                                 bool in_order) {
231   if (rtp_payload_registry_->IsEncapsulated(header)) {
232     return ParseAndHandleEncapsulatingHeader(packet, packet_length, header);
233   }
234   const uint8_t* payload = packet + header.headerLength;
235   int payload_length = packet_length - header.headerLength;
236   assert(payload_length >= 0);
237   PayloadUnion payload_specific;
238   if (!rtp_payload_registry_->GetPayloadSpecifics(header.payloadType,
239                                                   &payload_specific)) {
240     return false;
241   }
242   return rtp_receiver_->IncomingRtpPacket(header, payload, payload_length,
243                                           payload_specific, in_order);
244 }
245
246 bool ViEReceiver::ParseAndHandleEncapsulatingHeader(const uint8_t* packet,
247                                                     int packet_length,
248                                                     const RTPHeader& header) {
249   if (rtp_payload_registry_->IsRed(header)) {
250     int8_t ulpfec_pt = rtp_payload_registry_->ulpfec_payload_type();
251     if (packet[header.headerLength] == ulpfec_pt)
252       rtp_receive_statistics_->FecPacketReceived(header.ssrc);
253     if (fec_receiver_->AddReceivedRedPacket(
254             header, packet, packet_length, ulpfec_pt) != 0) {
255       WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideo, channel_id_,
256                    "Incoming RED packet error");
257       return false;
258     }
259     return fec_receiver_->ProcessReceivedFec() == 0;
260   } else if (rtp_payload_registry_->IsRtx(header)) {
261     // Remove the RTX header and parse the original RTP header.
262     if (packet_length < header.headerLength)
263       return false;
264     if (packet_length > static_cast<int>(sizeof(restored_packet_)))
265       return false;
266     CriticalSectionScoped cs(receive_cs_.get());
267     if (restored_packet_in_use_) {
268       WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideo, channel_id_,
269                    "Multiple RTX headers detected, dropping packet");
270       return false;
271     }
272     uint8_t* restored_packet_ptr = restored_packet_;
273     if (!rtp_payload_registry_->RestoreOriginalPacket(
274         &restored_packet_ptr, packet, &packet_length, rtp_receiver_->SSRC(),
275         header)) {
276       WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideo, channel_id_,
277                    "Incoming RTX packet: invalid RTP header");
278       return false;
279     }
280     restored_packet_in_use_ = true;
281     bool ret = OnRecoveredPacket(restored_packet_ptr, packet_length);
282     restored_packet_in_use_ = false;
283     return ret;
284   }
285   return false;
286 }
287
288 int ViEReceiver::InsertRTCPPacket(const uint8_t* rtcp_packet,
289                                   int rtcp_packet_length) {
290   {
291     CriticalSectionScoped cs(receive_cs_.get());
292     if (!receiving_) {
293       return -1;
294     }
295
296     if (rtp_dump_) {
297       rtp_dump_->DumpPacket(
298           rtcp_packet, static_cast<uint16_t>(rtcp_packet_length));
299     }
300
301     std::list<RtpRtcp*>::iterator it = rtp_rtcp_simulcast_.begin();
302     while (it != rtp_rtcp_simulcast_.end()) {
303       RtpRtcp* rtp_rtcp = *it++;
304       rtp_rtcp->IncomingRtcpPacket(rtcp_packet, rtcp_packet_length);
305     }
306   }
307   assert(rtp_rtcp_);  // Should be set by owner at construction time.
308   return rtp_rtcp_->IncomingRtcpPacket(rtcp_packet, rtcp_packet_length);
309 }
310
311 void ViEReceiver::StartReceive() {
312   CriticalSectionScoped cs(receive_cs_.get());
313   receiving_ = true;
314 }
315
316 void ViEReceiver::StopReceive() {
317   CriticalSectionScoped cs(receive_cs_.get());
318   receiving_ = false;
319 }
320
321 int ViEReceiver::StartRTPDump(const char file_nameUTF8[1024]) {
322   CriticalSectionScoped cs(receive_cs_.get());
323   if (rtp_dump_) {
324     // Restart it if it already exists and is started
325     rtp_dump_->Stop();
326   } else {
327     rtp_dump_ = RtpDump::CreateRtpDump();
328     if (rtp_dump_ == NULL) {
329       WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, channel_id_,
330                    "StartRTPDump: Failed to create RTP dump");
331       return -1;
332     }
333   }
334   if (rtp_dump_->Start(file_nameUTF8) != 0) {
335     RtpDump::DestroyRtpDump(rtp_dump_);
336     rtp_dump_ = NULL;
337     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, channel_id_,
338                  "StartRTPDump: Failed to start RTP dump");
339     return -1;
340   }
341   return 0;
342 }
343
344 int ViEReceiver::StopRTPDump() {
345   CriticalSectionScoped cs(receive_cs_.get());
346   if (rtp_dump_) {
347     if (rtp_dump_->IsActive()) {
348       rtp_dump_->Stop();
349     } else {
350       WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, channel_id_,
351                    "StopRTPDump: Dump not active");
352     }
353     RtpDump::DestroyRtpDump(rtp_dump_);
354     rtp_dump_ = NULL;
355   } else {
356     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, channel_id_,
357                  "StopRTPDump: RTP dump not started");
358     return -1;
359   }
360   return 0;
361 }
362
363 // TODO(holmer): To be moved to ViEChannelGroup.
364 void ViEReceiver::EstimatedReceiveBandwidth(
365     unsigned int* available_bandwidth) const {
366   std::vector<unsigned int> ssrcs;
367
368   // LatestEstimate returns an error if there is no valid bitrate estimate, but
369   // ViEReceiver instead returns a zero estimate.
370   remote_bitrate_estimator_->LatestEstimate(&ssrcs, available_bandwidth);
371   if (std::find(ssrcs.begin(), ssrcs.end(), rtp_receiver_->SSRC()) !=
372       ssrcs.end()) {
373     *available_bandwidth /= ssrcs.size();
374   } else {
375     *available_bandwidth = 0;
376   }
377 }
378
379 void ViEReceiver::GetReceiveBandwidthEstimatorStats(
380     ReceiveBandwidthEstimatorStats* output) const {
381   remote_bitrate_estimator_->GetStats(output);
382 }
383
384 ReceiveStatistics* ViEReceiver::GetReceiveStatistics() const {
385   return rtp_receive_statistics_.get();
386 }
387
388 bool ViEReceiver::IsPacketInOrder(const RTPHeader& header) const {
389   StreamStatistician* statistician =
390       rtp_receive_statistics_->GetStatistician(header.ssrc);
391   if (!statistician)
392     return false;
393   return statistician->IsPacketInOrder(header.sequenceNumber);
394 }
395
396 bool ViEReceiver::IsPacketRetransmitted(const RTPHeader& header,
397                                         bool in_order) const {
398   // Retransmissions are handled separately if RTX is enabled.
399   if (rtp_payload_registry_->RtxEnabled())
400     return false;
401   StreamStatistician* statistician =
402       rtp_receive_statistics_->GetStatistician(header.ssrc);
403   if (!statistician)
404     return false;
405   // Check if this is a retransmission.
406   uint16_t min_rtt = 0;
407   rtp_rtcp_->RTT(rtp_receiver_->SSRC(), NULL, NULL, &min_rtt, NULL);
408   return !in_order &&
409       statistician->IsRetransmitOfOldPacket(header, min_rtt);
410 }
411 }  // namespace webrtc