1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*
2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Use of this source code is governed by a BSD-style license
5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  that can be found in the LICENSE file in the root of the source
6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  tree. An additional intellectual property rights grant can be found
7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  in the file PATENTS.  All contributing project authors may
8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */
10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
11281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/video_engine/vie_receiver.h"
12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
13cd1ac8b77e14f5f84a0d99f732b0aff7297baa4cmflodman@webrtc.org#include <vector>
14cd1ac8b77e14f5f84a0d99f732b0aff7297baa4cmflodman@webrtc.org
15281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
16db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org#include "webrtc/modules/rtp_rtcp/interface/fec_receiver.h"
177fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org#include "webrtc/modules/rtp_rtcp/interface/receive_statistics.h"
182fae0d1b007dd3689fd002f31391dab6f1cd6628wu@webrtc.org#include "webrtc/modules/rtp_rtcp/interface/remote_ntp_time_estimator.h"
196696fba9388a386f7d0e3e0d93df48d43f05cd95stefan@webrtc.org#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
207fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org#include "webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h"
217fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org#include "webrtc/modules/rtp_rtcp/interface/rtp_receiver.h"
22281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h"
23281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/modules/utility/interface/rtp_dump.h"
24281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/modules/video_coding/main/interface/video_coding.h"
25281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
26093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org#include "webrtc/system_wrappers/interface/logging.h"
27281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/system_wrappers/interface/tick_util.h"
28d2fb259b3bc61c68f368929510215a7ee7d00fdawu@webrtc.org#include "webrtc/system_wrappers/interface/timestamp_extrapolator.h"
292fae0d1b007dd3689fd002f31391dab6f1cd6628wu@webrtc.org#include "webrtc/system_wrappers/interface/trace.h"
30b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
31b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgnamespace webrtc {
32b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgViEReceiver::ViEReceiver(const int32_t channel_id,
34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                         VideoCodingModule* module_vcm,
357fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org                         RemoteBitrateEstimator* remote_bitrate_estimator,
367fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org                         RtpFeedback* rtp_feedback)
37b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    : receive_cs_(CriticalSectionWrapper::CreateCriticalSection()),
386696fba9388a386f7d0e3e0d93df48d43f05cd95stefan@webrtc.org      rtp_header_parser_(RtpHeaderParser::Create()),
397fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org      rtp_payload_registry_(new RTPPayloadRegistry(
4099681317b0a9dc29c1682a17908f382eac16bd2aandresp@webrtc.org          RTPPayloadStrategy::CreateStrategy(false))),
417fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org      rtp_receiver_(RtpReceiver::CreateVideoReceiver(
427fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org          channel_id, Clock::GetRealTimeClock(), this, rtp_feedback,
437fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org          rtp_payload_registry_.get())),
447fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org      rtp_receive_statistics_(ReceiveStatistics::Create(
457fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org          Clock::GetRealTimeClock())),
4699681317b0a9dc29c1682a17908f382eac16bd2aandresp@webrtc.org      fec_receiver_(FecReceiver::Create(this)),
47b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      rtp_rtcp_(NULL),
48b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      vcm_(module_vcm),
49b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      remote_bitrate_estimator_(remote_bitrate_estimator),
502fae0d1b007dd3689fd002f31391dab6f1cd6628wu@webrtc.org      ntp_estimator_(new RemoteNtpTimeEstimator(Clock::GetRealTimeClock())),
51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      rtp_dump_(NULL),
52db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org      receiving_(false),
532d3624ceb06407a4440433f816612fc150bfea42solenberg@webrtc.org      restored_packet_in_use_(false),
542d3624ceb06407a4440433f816612fc150bfea42solenberg@webrtc.org      receiving_ast_enabled_(false) {
55b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  assert(remote_bitrate_estimator);
56b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
57b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
58b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgViEReceiver::~ViEReceiver() {
59b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (rtp_dump_) {
60b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rtp_dump_->Stop();
61b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    RtpDump::DestroyRtpDump(rtp_dump_);
62b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rtp_dump_ = NULL;
63b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
64b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
65b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
667fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.orgbool ViEReceiver::SetReceiveCodec(const VideoCodec& video_codec) {
677fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org  int8_t old_pltype = -1;
687fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org  if (rtp_payload_registry_->ReceivePayloadType(video_codec.plName,
697fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org                                                kVideoPayloadTypeFrequency,
707fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org                                                0,
717fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org                                                video_codec.maxBitrate,
727fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org                                                &old_pltype) != -1) {
737fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org    rtp_payload_registry_->DeRegisterReceivePayload(old_pltype);
747fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org  }
757fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org
767fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org  return RegisterPayload(video_codec);
777fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org}
787fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org
797fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.orgbool ViEReceiver::RegisterPayload(const VideoCodec& video_codec) {
807fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org  return rtp_receiver_->RegisterReceivePayload(video_codec.plName,
817fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org                                               video_codec.plType,
827fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org                                               kVideoPayloadTypeFrequency,
837fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org                                               0,
847fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org                                               video_codec.maxBitrate) == 0;
857fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org}
867fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org
87db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.orgvoid ViEReceiver::SetNackStatus(bool enable,
887fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org                                int max_nack_reordering_threshold) {
89db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org  if (!enable) {
90db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org    // Reset the threshold back to the lower default threshold when NACK is
91db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org    // disabled since we no longer will be receiving retransmissions.
92db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org    max_nack_reordering_threshold = kDefaultMaxReorderingThreshold;
93db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org  }
94db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org  rtp_receive_statistics_->SetMaxReorderingThreshold(
95db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org      max_nack_reordering_threshold);
96db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org  rtp_receiver_->SetNACKStatus(enable ? kNackRtcp : kNackOff);
977fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org}
987fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org
99903e746cc9a73da17bfa3f6110293582fa6ee3bestefan@webrtc.orgvoid ViEReceiver::SetRtxPayloadType(int payload_type) {
100903e746cc9a73da17bfa3f6110293582fa6ee3bestefan@webrtc.org  rtp_payload_registry_->SetRtxPayloadType(payload_type);
1017fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org}
1027fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org
103903e746cc9a73da17bfa3f6110293582fa6ee3bestefan@webrtc.orgvoid ViEReceiver::SetRtxSsrc(uint32_t ssrc) {
104903e746cc9a73da17bfa3f6110293582fa6ee3bestefan@webrtc.org  rtp_payload_registry_->SetRtxSsrc(ssrc);
1057fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org}
1067fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org
1077fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.orguint32_t ViEReceiver::GetRemoteSsrc() const {
1087fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org  return rtp_receiver_->SSRC();
1097fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org}
1107fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org
1117fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.orgint ViEReceiver::GetCsrcs(uint32_t* csrcs) const {
1127fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org  return rtp_receiver_->CSRCs(csrcs);
1137fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org}
1147fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org
115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid ViEReceiver::SetRtpRtcpModule(RtpRtcp* module) {
116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  rtp_rtcp_ = module;
117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1197fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.orgRtpReceiver* ViEReceiver::GetRtpReceiver() const {
1207fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org  return rtp_receiver_.get();
1217fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org}
1227fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org
123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid ViEReceiver::RegisterSimulcastRtpRtcpModules(
124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const std::list<RtpRtcp*>& rtp_modules) {
125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CriticalSectionScoped cs(receive_cs_.get());
126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  rtp_rtcp_simulcast_.clear();
127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (!rtp_modules.empty()) {
129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rtp_rtcp_simulcast_.insert(rtp_rtcp_simulcast_.begin(),
130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                               rtp_modules.begin(),
131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                               rtp_modules.end());
132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1354e5f9831edffe845ae2474e9f7df0e5f9e35bdd5stefan@webrtc.orgbool ViEReceiver::SetReceiveTimestampOffsetStatus(bool enable, int id) {
1366696fba9388a386f7d0e3e0d93df48d43f05cd95stefan@webrtc.org  if (enable) {
1376696fba9388a386f7d0e3e0d93df48d43f05cd95stefan@webrtc.org    return rtp_header_parser_->RegisterRtpHeaderExtension(
1386696fba9388a386f7d0e3e0d93df48d43f05cd95stefan@webrtc.org        kRtpExtensionTransmissionTimeOffset, id);
1396696fba9388a386f7d0e3e0d93df48d43f05cd95stefan@webrtc.org  } else {
1406696fba9388a386f7d0e3e0d93df48d43f05cd95stefan@webrtc.org    return rtp_header_parser_->DeregisterRtpHeaderExtension(
1416696fba9388a386f7d0e3e0d93df48d43f05cd95stefan@webrtc.org        kRtpExtensionTransmissionTimeOffset);
1426696fba9388a386f7d0e3e0d93df48d43f05cd95stefan@webrtc.org  }
1436696fba9388a386f7d0e3e0d93df48d43f05cd95stefan@webrtc.org}
1446696fba9388a386f7d0e3e0d93df48d43f05cd95stefan@webrtc.org
1454e5f9831edffe845ae2474e9f7df0e5f9e35bdd5stefan@webrtc.orgbool ViEReceiver::SetReceiveAbsoluteSendTimeStatus(bool enable, int id) {
1466696fba9388a386f7d0e3e0d93df48d43f05cd95stefan@webrtc.org  if (enable) {
1472d3624ceb06407a4440433f816612fc150bfea42solenberg@webrtc.org    if (rtp_header_parser_->RegisterRtpHeaderExtension(
1482d3624ceb06407a4440433f816612fc150bfea42solenberg@webrtc.org        kRtpExtensionAbsoluteSendTime, id)) {
1492d3624ceb06407a4440433f816612fc150bfea42solenberg@webrtc.org      receiving_ast_enabled_ = true;
1502d3624ceb06407a4440433f816612fc150bfea42solenberg@webrtc.org      return true;
1512d3624ceb06407a4440433f816612fc150bfea42solenberg@webrtc.org    } else {
1522d3624ceb06407a4440433f816612fc150bfea42solenberg@webrtc.org      return false;
1532d3624ceb06407a4440433f816612fc150bfea42solenberg@webrtc.org    }
1546696fba9388a386f7d0e3e0d93df48d43f05cd95stefan@webrtc.org  } else {
1552d3624ceb06407a4440433f816612fc150bfea42solenberg@webrtc.org    receiving_ast_enabled_ = false;
1566696fba9388a386f7d0e3e0d93df48d43f05cd95stefan@webrtc.org    return rtp_header_parser_->DeregisterRtpHeaderExtension(
1576696fba9388a386f7d0e3e0d93df48d43f05cd95stefan@webrtc.org        kRtpExtensionAbsoluteSendTime);
1586696fba9388a386f7d0e3e0d93df48d43f05cd95stefan@webrtc.org  }
1596696fba9388a386f7d0e3e0d93df48d43f05cd95stefan@webrtc.org}
1606696fba9388a386f7d0e3e0d93df48d43f05cd95stefan@webrtc.org
161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint ViEReceiver::ReceivedRTPPacket(const void* rtp_packet,
162efeb8ce7e183005e557a2d107203e2057cec26a8wu@webrtc.org                                   int rtp_packet_length,
163efeb8ce7e183005e557a2d107203e2057cec26a8wu@webrtc.org                                   const PacketTime& packet_time) {
164800136d2ca86bc644a2914db8f4a11b13a21dcaasolenberg@webrtc.org  return InsertRTPPacket(static_cast<const uint8_t*>(rtp_packet),
165efeb8ce7e183005e557a2d107203e2057cec26a8wu@webrtc.org                         rtp_packet_length, packet_time);
166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint ViEReceiver::ReceivedRTCPPacket(const void* rtcp_packet,
169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                    int rtcp_packet_length) {
170800136d2ca86bc644a2914db8f4a11b13a21dcaasolenberg@webrtc.org  return InsertRTCPPacket(static_cast<const uint8_t*>(rtcp_packet),
171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                          rtcp_packet_length);
172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
17467879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.orgint32_t ViEReceiver::OnReceivedPayloadData(
17567879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org    const uint8_t* payload_data, const uint16_t payload_size,
176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const WebRtcRTPHeader* rtp_header) {
177093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org  WebRtcRTPHeader rtp_header_with_ntp = *rtp_header;
1782fae0d1b007dd3689fd002f31391dab6f1cd6628wu@webrtc.org  rtp_header_with_ntp.ntp_time_ms =
1792fae0d1b007dd3689fd002f31391dab6f1cd6628wu@webrtc.org      ntp_estimator_->Estimate(rtp_header->header.timestamp);
180093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org  if (vcm_->IncomingPacket(payload_data,
181093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org                           payload_size,
182093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org                           rtp_header_with_ntp) != 0) {
183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Check this...
184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1897fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.orgbool ViEReceiver::OnRecoveredPacket(const uint8_t* rtp_packet,
1907fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org                                    int rtp_packet_length) {
1917fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org  RTPHeader header;
1927fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org  if (!rtp_header_parser_->Parse(rtp_packet, rtp_packet_length, &header)) {
1937fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org    return false;
1947fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org  }
1957fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org  header.payload_type_frequency = kVideoPayloadTypeFrequency;
196d01c49138f5c9c49c86251094f72759ee2c4705fstefan@webrtc.org  bool in_order = IsPacketInOrder(header);
197d01c49138f5c9c49c86251094f72759ee2c4705fstefan@webrtc.org  return ReceivePacket(rtp_packet, rtp_packet_length, header, in_order);
1987fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org}
1997fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org
2002d3624ceb06407a4440433f816612fc150bfea42solenberg@webrtc.orgvoid ViEReceiver::ReceivedBWEPacket(
2012d3624ceb06407a4440433f816612fc150bfea42solenberg@webrtc.org    int64_t arrival_time_ms, int payload_size, const RTPHeader& header) {
2022d3624ceb06407a4440433f816612fc150bfea42solenberg@webrtc.org  // Only forward if the incoming packet *and* the channel are both configured
2032d3624ceb06407a4440433f816612fc150bfea42solenberg@webrtc.org  // to receive absolute sender time. RTP time stamps may have different rates
2042d3624ceb06407a4440433f816612fc150bfea42solenberg@webrtc.org  // for audio and video and shouldn't be mixed.
2052d3624ceb06407a4440433f816612fc150bfea42solenberg@webrtc.org  if (header.extension.hasAbsoluteSendTime && receiving_ast_enabled_) {
2062d3624ceb06407a4440433f816612fc150bfea42solenberg@webrtc.org    remote_bitrate_estimator_->IncomingPacket(arrival_time_ms, payload_size,
2072d3624ceb06407a4440433f816612fc150bfea42solenberg@webrtc.org                                              header);
2082d3624ceb06407a4440433f816612fc150bfea42solenberg@webrtc.org  }
2092d3624ceb06407a4440433f816612fc150bfea42solenberg@webrtc.org}
2102d3624ceb06407a4440433f816612fc150bfea42solenberg@webrtc.org
211800136d2ca86bc644a2914db8f4a11b13a21dcaasolenberg@webrtc.orgint ViEReceiver::InsertRTPPacket(const uint8_t* rtp_packet,
212efeb8ce7e183005e557a2d107203e2057cec26a8wu@webrtc.org                                 int rtp_packet_length,
213efeb8ce7e183005e557a2d107203e2057cec26a8wu@webrtc.org                                 const PacketTime& packet_time) {
214b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  {
215b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CriticalSectionScoped cs(receive_cs_.get());
216d69e2f437a136a90cb1edc42a1bd498d12f5c295braveyao@webrtc.org    if (!receiving_) {
217d69e2f437a136a90cb1edc42a1bd498d12f5c295braveyao@webrtc.org      return -1;
218d69e2f437a136a90cb1edc42a1bd498d12f5c295braveyao@webrtc.org    }
219b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (rtp_dump_) {
220800136d2ca86bc644a2914db8f4a11b13a21dcaasolenberg@webrtc.org      rtp_dump_->DumpPacket(rtp_packet,
221800136d2ca86bc644a2914db8f4a11b13a21dcaasolenberg@webrtc.org                            static_cast<uint16_t>(rtp_packet_length));
222b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
223b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
224800136d2ca86bc644a2914db8f4a11b13a21dcaasolenberg@webrtc.org
2256696fba9388a386f7d0e3e0d93df48d43f05cd95stefan@webrtc.org  RTPHeader header;
226800136d2ca86bc644a2914db8f4a11b13a21dcaasolenberg@webrtc.org  if (!rtp_header_parser_->Parse(rtp_packet, rtp_packet_length,
2276696fba9388a386f7d0e3e0d93df48d43f05cd95stefan@webrtc.org                                 &header)) {
2286696fba9388a386f7d0e3e0d93df48d43f05cd95stefan@webrtc.org    return -1;
2296696fba9388a386f7d0e3e0d93df48d43f05cd95stefan@webrtc.org  }
230800136d2ca86bc644a2914db8f4a11b13a21dcaasolenberg@webrtc.org  int payload_length = rtp_packet_length - header.headerLength;
231efeb8ce7e183005e557a2d107203e2057cec26a8wu@webrtc.org  int64_t arrival_time_ms;
232efeb8ce7e183005e557a2d107203e2057cec26a8wu@webrtc.org  if (packet_time.timestamp != -1)
233efeb8ce7e183005e557a2d107203e2057cec26a8wu@webrtc.org    arrival_time_ms = (packet_time.timestamp + 500) / 1000;
234efeb8ce7e183005e557a2d107203e2057cec26a8wu@webrtc.org  else
235efeb8ce7e183005e557a2d107203e2057cec26a8wu@webrtc.org    arrival_time_ms = TickTime::MillisecondTimestamp();
236efeb8ce7e183005e557a2d107203e2057cec26a8wu@webrtc.org
237efeb8ce7e183005e557a2d107203e2057cec26a8wu@webrtc.org  remote_bitrate_estimator_->IncomingPacket(arrival_time_ms,
238db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org                                            payload_length, header);
2397fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org  header.payload_type_frequency = kVideoPayloadTypeFrequency;
240db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org
2417e97e4c84dc21b2853f5158a03dcceb569e493adstefan@webrtc.org  bool in_order = IsPacketInOrder(header);
242db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org  rtp_payload_registry_->SetIncomingPayloadType(header);
24399153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org  int ret = ReceivePacket(rtp_packet, rtp_packet_length, header, in_order)
244800136d2ca86bc644a2914db8f4a11b13a21dcaasolenberg@webrtc.org      ? 0
245800136d2ca86bc644a2914db8f4a11b13a21dcaasolenberg@webrtc.org      : -1;
24699153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org  // Update receive statistics after ReceivePacket.
24799153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org  // Receive statistics will be reset if the payload type changes (make sure
24899153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org  // that the first packet is included in the stats).
24999153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org  rtp_receive_statistics_->IncomingPacket(
25099153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org      header, rtp_packet_length, IsPacketRetransmitted(header, in_order));
25199153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org  return ret;
252db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org}
253db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org
254db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.orgbool ViEReceiver::ReceivePacket(const uint8_t* packet,
255db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org                                int packet_length,
256db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org                                const RTPHeader& header,
257db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org                                bool in_order) {
258db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org  if (rtp_payload_registry_->IsEncapsulated(header)) {
259db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org    return ParseAndHandleEncapsulatingHeader(packet, packet_length, header);
260db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org  }
261db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org  const uint8_t* payload = packet + header.headerLength;
262db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org  int payload_length = packet_length - header.headerLength;
263db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org  assert(payload_length >= 0);
2647fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org  PayloadUnion payload_specific;
2657fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org  if (!rtp_payload_registry_->GetPayloadSpecifics(header.payloadType,
2667fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org                                                  &payload_specific)) {
267db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org    return false;
2687fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org  }
269db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org  return rtp_receiver_->IncomingRtpPacket(header, payload, payload_length,
270db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org                                          payload_specific, in_order);
271db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org}
272db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org
273db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.orgbool ViEReceiver::ParseAndHandleEncapsulatingHeader(const uint8_t* packet,
274db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org                                                    int packet_length,
275db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org                                                    const RTPHeader& header) {
276db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org  if (rtp_payload_registry_->IsRed(header)) {
2777d99cd47d8055ec6815f2862b75a0bdf53304199sprang@webrtc.org    int8_t ulpfec_pt = rtp_payload_registry_->ulpfec_payload_type();
2787d99cd47d8055ec6815f2862b75a0bdf53304199sprang@webrtc.org    if (packet[header.headerLength] == ulpfec_pt)
2797d99cd47d8055ec6815f2862b75a0bdf53304199sprang@webrtc.org      rtp_receive_statistics_->FecPacketReceived(header.ssrc);
280db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org    if (fec_receiver_->AddReceivedRedPacket(
2817d99cd47d8055ec6815f2862b75a0bdf53304199sprang@webrtc.org            header, packet, packet_length, ulpfec_pt) != 0) {
282db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org      return false;
283db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org    }
284db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org    return fec_receiver_->ProcessReceivedFec() == 0;
285db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org  } else if (rtp_payload_registry_->IsRtx(header)) {
286fbd6f47f33ba2f1f6884dbd6bb975325f6c0adc3stefan@webrtc.org    if (header.headerLength + header.paddingLength == packet_length) {
287fbd6f47f33ba2f1f6884dbd6bb975325f6c0adc3stefan@webrtc.org      // This is an empty packet and should be silently dropped before trying to
288fbd6f47f33ba2f1f6884dbd6bb975325f6c0adc3stefan@webrtc.org      // parse the RTX header.
289fbd6f47f33ba2f1f6884dbd6bb975325f6c0adc3stefan@webrtc.org      return true;
290fbd6f47f33ba2f1f6884dbd6bb975325f6c0adc3stefan@webrtc.org    }
291db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org    // Remove the RTX header and parse the original RTP header.
292db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org    if (packet_length < header.headerLength)
293db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org      return false;
294db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org    if (packet_length > static_cast<int>(sizeof(restored_packet_)))
295db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org      return false;
296db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org    CriticalSectionScoped cs(receive_cs_.get());
297db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org    if (restored_packet_in_use_) {
2983468f20608200e23fa0ad7435490260419cf70c5pbos@webrtc.org      LOG(LS_WARNING) << "Multiple RTX headers detected, dropping packet.";
299db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org      return false;
300db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org    }
301db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org    uint8_t* restored_packet_ptr = restored_packet_;
302db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org    if (!rtp_payload_registry_->RestoreOriginalPacket(
303db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org        &restored_packet_ptr, packet, &packet_length, rtp_receiver_->SSRC(),
304db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org        header)) {
3053468f20608200e23fa0ad7435490260419cf70c5pbos@webrtc.org      LOG(LS_WARNING) << "Incoming RTX packet: Invalid RTP header";
306db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org      return false;
307db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org    }
308db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org    restored_packet_in_use_ = true;
309db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org    bool ret = OnRecoveredPacket(restored_packet_ptr, packet_length);
310db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org    restored_packet_in_use_ = false;
311db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org    return ret;
312db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org  }
313db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org  return false;
314b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
315b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
316800136d2ca86bc644a2914db8f4a11b13a21dcaasolenberg@webrtc.orgint ViEReceiver::InsertRTCPPacket(const uint8_t* rtcp_packet,
317b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                  int rtcp_packet_length) {
318b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  {
319b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CriticalSectionScoped cs(receive_cs_.get());
320d69e2f437a136a90cb1edc42a1bd498d12f5c295braveyao@webrtc.org    if (!receiving_) {
321d69e2f437a136a90cb1edc42a1bd498d12f5c295braveyao@webrtc.org      return -1;
322d69e2f437a136a90cb1edc42a1bd498d12f5c295braveyao@webrtc.org    }
323b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
324b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (rtp_dump_) {
325b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      rtp_dump_->DumpPacket(
326800136d2ca86bc644a2914db8f4a11b13a21dcaasolenberg@webrtc.org          rtcp_packet, static_cast<uint16_t>(rtcp_packet_length));
327b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
328800136d2ca86bc644a2914db8f4a11b13a21dcaasolenberg@webrtc.org
329b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    std::list<RtpRtcp*>::iterator it = rtp_rtcp_simulcast_.begin();
330b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    while (it != rtp_rtcp_simulcast_.end()) {
331b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      RtpRtcp* rtp_rtcp = *it++;
332800136d2ca86bc644a2914db8f4a11b13a21dcaasolenberg@webrtc.org      rtp_rtcp->IncomingRtcpPacket(rtcp_packet, rtcp_packet_length);
333b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
334b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
335b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  assert(rtp_rtcp_);  // Should be set by owner at construction time.
336093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org  int ret = rtp_rtcp_->IncomingRtcpPacket(rtcp_packet, rtcp_packet_length);
337093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org  if (ret != 0) {
338093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org    return ret;
339093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org  }
340093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org
341dd0f8b2a5f7fde0d8a515ea90bcf32fcad7ad230wu@webrtc.org  ntp_estimator_->UpdateRtcpTimestamp(rtp_receiver_->SSRC(), rtp_rtcp_);
342093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org
343093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org  return 0;
344093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org}
345093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org
346b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid ViEReceiver::StartReceive() {
347d69e2f437a136a90cb1edc42a1bd498d12f5c295braveyao@webrtc.org  CriticalSectionScoped cs(receive_cs_.get());
348b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  receiving_ = true;
349b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
350b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
351b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid ViEReceiver::StopReceive() {
352d69e2f437a136a90cb1edc42a1bd498d12f5c295braveyao@webrtc.org  CriticalSectionScoped cs(receive_cs_.get());
353b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  receiving_ = false;
354b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
355b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
356b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint ViEReceiver::StartRTPDump(const char file_nameUTF8[1024]) {
357b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CriticalSectionScoped cs(receive_cs_.get());
358b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (rtp_dump_) {
359b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Restart it if it already exists and is started
360b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rtp_dump_->Stop();
361b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else {
362b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rtp_dump_ = RtpDump::CreateRtpDump();
363b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (rtp_dump_ == NULL) {
364b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return -1;
365b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
366b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
367b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (rtp_dump_->Start(file_nameUTF8) != 0) {
368b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    RtpDump::DestroyRtpDump(rtp_dump_);
369b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rtp_dump_ = NULL;
370b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
371b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
372b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
373b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
374b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
375b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint ViEReceiver::StopRTPDump() {
376b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CriticalSectionScoped cs(receive_cs_.get());
377b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (rtp_dump_) {
378b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (rtp_dump_->IsActive()) {
379b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      rtp_dump_->Stop();
380b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
381b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    RtpDump::DestroyRtpDump(rtp_dump_);
382b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rtp_dump_ = NULL;
383b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else {
384b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
385b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
386b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
387b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
388b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
389d1e7facca966ca4b7632940d71f62deea5094083jiayl@webrtc.orgvoid ViEReceiver::GetReceiveBandwidthEstimatorStats(
390d1e7facca966ca4b7632940d71f62deea5094083jiayl@webrtc.org    ReceiveBandwidthEstimatorStats* output) const {
391d1e7facca966ca4b7632940d71f62deea5094083jiayl@webrtc.org  remote_bitrate_estimator_->GetStats(output);
392d1e7facca966ca4b7632940d71f62deea5094083jiayl@webrtc.org}
393d1e7facca966ca4b7632940d71f62deea5094083jiayl@webrtc.org
3947fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.orgReceiveStatistics* ViEReceiver::GetReceiveStatistics() const {
3957fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org  return rtp_receive_statistics_.get();
3967fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org}
3977fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org
398db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.orgbool ViEReceiver::IsPacketInOrder(const RTPHeader& header) const {
399db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org  StreamStatistician* statistician =
400db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org      rtp_receive_statistics_->GetStatistician(header.ssrc);
401db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org  if (!statistician)
402db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org    return false;
403db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org  return statistician->IsPacketInOrder(header.sequenceNumber);
404db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org}
405db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org
4067e97e4c84dc21b2853f5158a03dcceb569e493adstefan@webrtc.orgbool ViEReceiver::IsPacketRetransmitted(const RTPHeader& header,
4077e97e4c84dc21b2853f5158a03dcceb569e493adstefan@webrtc.org                                        bool in_order) const {
408db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org  // Retransmissions are handled separately if RTX is enabled.
409db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org  if (rtp_payload_registry_->RtxEnabled())
410db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org    return false;
411db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org  StreamStatistician* statistician =
412db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org      rtp_receive_statistics_->GetStatistician(header.ssrc);
413db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org  if (!statistician)
414db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org    return false;
415db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org  // Check if this is a retransmission.
416db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org  uint16_t min_rtt = 0;
417db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org  rtp_rtcp_->RTT(rtp_receiver_->SSRC(), NULL, NULL, &min_rtt, NULL);
4187e97e4c84dc21b2853f5158a03dcceb569e493adstefan@webrtc.org  return !in_order &&
419db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org      statistician->IsRetransmitOfOldPacket(header, min_rtt);
4207fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org}
421b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}  // namespace webrtc
422