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
31namespace webrtc {
32
33ViEReceiver::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
58ViEReceiver::~ViEReceiver() {
59  if (rtp_dump_) {
60    rtp_dump_->Stop();
61    RtpDump::DestroyRtpDump(rtp_dump_);
62    rtp_dump_ = NULL;
63  }
64}
65
66bool 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
79bool 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
87void 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
99void ViEReceiver::SetRtxPayloadType(int payload_type) {
100  rtp_payload_registry_->SetRtxPayloadType(payload_type);
101}
102
103void ViEReceiver::SetRtxSsrc(uint32_t ssrc) {
104  rtp_payload_registry_->SetRtxSsrc(ssrc);
105}
106
107uint32_t ViEReceiver::GetRemoteSsrc() const {
108  return rtp_receiver_->SSRC();
109}
110
111int ViEReceiver::GetCsrcs(uint32_t* csrcs) const {
112  return rtp_receiver_->CSRCs(csrcs);
113}
114
115void ViEReceiver::SetRtpRtcpModule(RtpRtcp* module) {
116  rtp_rtcp_ = module;
117}
118
119RtpReceiver* ViEReceiver::GetRtpReceiver() const {
120  return rtp_receiver_.get();
121}
122
123void 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
135bool 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
145bool 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
161int 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
168int 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
174int32_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
189bool 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
200void 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
211int 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
254bool 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
273bool 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
316int 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
346void ViEReceiver::StartReceive() {
347  CriticalSectionScoped cs(receive_cs_.get());
348  receiving_ = true;
349}
350
351void ViEReceiver::StopReceive() {
352  CriticalSectionScoped cs(receive_cs_.get());
353  receiving_ = false;
354}
355
356int 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
375int 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
389void ViEReceiver::GetReceiveBandwidthEstimatorStats(
390    ReceiveBandwidthEstimatorStats* output) const {
391  remote_bitrate_estimator_->GetStats(output);
392}
393
394ReceiveStatistics* ViEReceiver::GetReceiveStatistics() const {
395  return rtp_receive_statistics_.get();
396}
397
398bool 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
406bool 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