1470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/*
239e9659fc6a70f9416205c942d21deea060a8997leozwang@webrtc.org *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *
4470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  Use of this source code is governed by a BSD-style license
5470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  that can be found in the LICENSE file in the root of the source
6470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  tree. An additional intellectual property rights grant can be found
7470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  in the file PATENTS.  All contributing project authors may
8470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  be found in the AUTHORS file in the root of the source tree.
9470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com */
10470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
117623ce4aeb9130c937ba5836490cbb3a35679e79Peter Boström#include "webrtc/video/vie_receiver.h"
12470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
134fd5527ab1ba986e94671eacc96ad56f26d282bcmflodman@webrtc.org#include <vector>
144fd5527ab1ba986e94671eacc96ad56f26d282bcmflodman@webrtc.org
15415d2cd7454d93b3727fce9147090a24e4c3ccbaPeter Boström#include "webrtc/base/logging.h"
16f5d4cb19589f0b0a3736e4f653dc5a75b9df1cebpbos@webrtc.org#include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
17ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander#include "webrtc/modules/rtp_rtcp/include/fec_receiver.h"
18ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander#include "webrtc/modules/rtp_rtcp/include/receive_statistics.h"
19ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander#include "webrtc/modules/rtp_rtcp/include/remote_ntp_time_estimator.h"
20ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander#include "webrtc/modules/rtp_rtcp/include/rtp_cvo.h"
21ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander#include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h"
22ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander#include "webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h"
23ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander#include "webrtc/modules/rtp_rtcp/include/rtp_receiver.h"
24ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
252557b86e7648ffebc5781df9f093ca5a84efc219Henrik Kjellander#include "webrtc/modules/video_coding/include/video_coding.h"
2698f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
2798f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/metrics.h"
2898f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/tick_util.h"
2998f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/timestamp_extrapolator.h"
3098f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/trace.h"
31470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
32470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comnamespace webrtc {
33470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
34eb24b04f1631aeee670230aa6600d28ae23890d0stefan@webrtc.orgstatic const int kPacketLogIntervalMs = 10000;
35eb24b04f1631aeee670230aa6600d28ae23890d0stefan@webrtc.org
36ac547a653862744d0aae560713f8418ad2852085Peter BoströmViEReceiver::ViEReceiver(VideoCodingModule* module_vcm,
37822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org                         RemoteBitrateEstimator* remote_bitrate_estimator,
38822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org                         RtpFeedback* rtp_feedback)
39d32c44738a034977b659bb4a2e76a97f027555e4mflodman@webrtc.org    : receive_cs_(CriticalSectionWrapper::CreateCriticalSection()),
40eb24b04f1631aeee670230aa6600d28ae23890d0stefan@webrtc.org      clock_(Clock::GetRealTimeClock()),
41a5cb98cbbd11e93cb6d0a6232387814aac168c7dstefan@webrtc.org      rtp_header_parser_(RtpHeaderParser::Create()),
42eb24b04f1631aeee670230aa6600d28ae23890d0stefan@webrtc.org      rtp_payload_registry_(
43eb24b04f1631aeee670230aa6600d28ae23890d0stefan@webrtc.org          new RTPPayloadRegistry(RTPPayloadStrategy::CreateStrategy(false))),
44eb24b04f1631aeee670230aa6600d28ae23890d0stefan@webrtc.org      rtp_receiver_(
45ac547a653862744d0aae560713f8418ad2852085Peter Boström          RtpReceiver::CreateVideoReceiver(clock_,
46eb24b04f1631aeee670230aa6600d28ae23890d0stefan@webrtc.org                                           this,
47eb24b04f1631aeee670230aa6600d28ae23890d0stefan@webrtc.org                                           rtp_feedback,
48eb24b04f1631aeee670230aa6600d28ae23890d0stefan@webrtc.org                                           rtp_payload_registry_.get())),
49eb24b04f1631aeee670230aa6600d28ae23890d0stefan@webrtc.org      rtp_receive_statistics_(ReceiveStatistics::Create(clock_)),
50dc80bae2a62a1bdbe0d342b3260a7e5b2cb958dfandresp@webrtc.org      fec_receiver_(FecReceiver::Create(this)),
512853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org      rtp_rtcp_(NULL),
52ad4ee3659e4298d9b006d00399e9a77e18d2eae1mflodman@webrtc.org      vcm_(module_vcm),
53976a7e61c17047fdc27401a015a1be55749cc914stefan@webrtc.org      remote_bitrate_estimator_(remote_bitrate_estimator),
54eb24b04f1631aeee670230aa6600d28ae23890d0stefan@webrtc.org      ntp_estimator_(new RemoteNtpTimeEstimator(clock_)),
557bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org      receiving_(false),
563fb8f7bbb0c5e074d0744c57905c5f49bb7d8304solenberg@webrtc.org      restored_packet_in_use_(false),
57eb24b04f1631aeee670230aa6600d28ae23890d0stefan@webrtc.org      receiving_ast_enabled_(false),
58fdd10579496123c9a7fdc0bf185e2a26a12ed340guoweis@webrtc.org      receiving_cvo_enabled_(false),
59867fb5224e1ba6a1c2cd523c005499a93ed61a08sprang      receiving_tsn_enabled_(false),
60eb24b04f1631aeee670230aa6600d28ae23890d0stefan@webrtc.org      last_packet_log_ms_(-1) {
61976a7e61c17047fdc27401a015a1be55749cc914stefan@webrtc.org  assert(remote_bitrate_estimator);
62470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
63470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
64ad4ee3659e4298d9b006d00399e9a77e18d2eae1mflodman@webrtc.orgViEReceiver::~ViEReceiver() {
650800db74b991dec8ef750c428eb611360a1286f4asapersson@webrtc.org  UpdateHistograms();
66470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
67470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
680800db74b991dec8ef750c428eb611360a1286f4asapersson@webrtc.orgvoid ViEReceiver::UpdateHistograms() {
690800db74b991dec8ef750c428eb611360a1286f4asapersson@webrtc.org  FecPacketCounter counter = fec_receiver_->GetPacketCounter();
700800db74b991dec8ef750c428eb611360a1286f4asapersson@webrtc.org  if (counter.num_packets > 0) {
7153805324c0fa904d796cc0b333868c591f2c5f2casapersson    RTC_HISTOGRAM_PERCENTAGE_SPARSE(
72ae37abbf6aa6a660e89256cc86143d6143a0139dPeter Boström        "WebRTC.Video.ReceivedFecPacketsInPercent",
73ae37abbf6aa6a660e89256cc86143d6143a0139dPeter Boström        static_cast<int>(counter.num_fec_packets * 100 / counter.num_packets));
740800db74b991dec8ef750c428eb611360a1286f4asapersson@webrtc.org  }
750800db74b991dec8ef750c428eb611360a1286f4asapersson@webrtc.org  if (counter.num_fec_packets > 0) {
7653805324c0fa904d796cc0b333868c591f2c5f2casapersson    RTC_HISTOGRAM_PERCENTAGE_SPARSE(
7753805324c0fa904d796cc0b333868c591f2c5f2casapersson        "WebRTC.Video.RecoveredMediaPacketsInPercentOfFec",
7853805324c0fa904d796cc0b333868c591f2c5f2casapersson        static_cast<int>(counter.num_recovered_packets * 100 /
7953805324c0fa904d796cc0b333868c591f2c5f2casapersson                         counter.num_fec_packets));
800800db74b991dec8ef750c428eb611360a1286f4asapersson@webrtc.org  }
810800db74b991dec8ef750c428eb611360a1286f4asapersson@webrtc.org}
820800db74b991dec8ef750c428eb611360a1286f4asapersson@webrtc.org
83822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.orgbool ViEReceiver::SetReceiveCodec(const VideoCodec& video_codec) {
84822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org  int8_t old_pltype = -1;
85822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org  if (rtp_payload_registry_->ReceivePayloadType(video_codec.plName,
86822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org                                                kVideoPayloadTypeFrequency,
87822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org                                                0,
88822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org                                                video_codec.maxBitrate,
89822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org                                                &old_pltype) != -1) {
90822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org    rtp_payload_registry_->DeRegisterReceivePayload(old_pltype);
91822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org  }
92822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org
93822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org  return RegisterPayload(video_codec);
94822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org}
95822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org
96822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.orgbool ViEReceiver::RegisterPayload(const VideoCodec& video_codec) {
97822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org  return rtp_receiver_->RegisterReceivePayload(video_codec.plName,
98822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org                                               video_codec.plType,
99822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org                                               kVideoPayloadTypeFrequency,
100822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org                                               0,
101822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org                                               video_codec.maxBitrate) == 0;
102822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org}
103822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org
1047bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.orgvoid ViEReceiver::SetNackStatus(bool enable,
105822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org                                int max_nack_reordering_threshold) {
1067bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  if (!enable) {
1077bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org    // Reset the threshold back to the lower default threshold when NACK is
1087bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org    // disabled since we no longer will be receiving retransmissions.
1097bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org    max_nack_reordering_threshold = kDefaultMaxReorderingThreshold;
1107bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  }
1117bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  rtp_receive_statistics_->SetMaxReorderingThreshold(
1127bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org      max_nack_reordering_threshold);
1137bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  rtp_receiver_->SetNACKStatus(enable ? kNackRtcp : kNackOff);
114822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org}
115822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org
116e62202fedf57b74cc263246c0586ee353978caf8Shao Changbinvoid ViEReceiver::SetRtxPayloadType(int payload_type,
117e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin                                    int associated_payload_type) {
118e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin  rtp_payload_registry_->SetRtxPayloadType(payload_type,
119e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin                                           associated_payload_type);
120822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org}
121822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org
12265220a70a38ffe252b587775c5e9104606ab7c2cnoahricvoid ViEReceiver::SetUseRtxPayloadMappingOnRestore(bool val) {
12365220a70a38ffe252b587775c5e9104606ab7c2cnoahric  rtp_payload_registry_->set_use_rtx_payload_mapping_on_restore(val);
12465220a70a38ffe252b587775c5e9104606ab7c2cnoahric}
12565220a70a38ffe252b587775c5e9104606ab7c2cnoahric
126ef92755780253c6a7940c89598a206e58e05b810stefan@webrtc.orgvoid ViEReceiver::SetRtxSsrc(uint32_t ssrc) {
127ef92755780253c6a7940c89598a206e58e05b810stefan@webrtc.org  rtp_payload_registry_->SetRtxSsrc(ssrc);
128822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org}
129822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org
130d952c40c7e31c1603988c1f09ebfba9f17c6a866asapersson@webrtc.orgbool ViEReceiver::GetRtxSsrc(uint32_t* ssrc) const {
131d952c40c7e31c1603988c1f09ebfba9f17c6a866asapersson@webrtc.org  return rtp_payload_registry_->GetRtxSsrc(ssrc);
132d952c40c7e31c1603988c1f09ebfba9f17c6a866asapersson@webrtc.org}
133d952c40c7e31c1603988c1f09ebfba9f17c6a866asapersson@webrtc.org
134273fbbb921e61273c3d83eb494d0a68db7834d3dasapersson@webrtc.orgbool ViEReceiver::IsFecEnabled() const {
135273fbbb921e61273c3d83eb494d0a68db7834d3dasapersson@webrtc.org  return rtp_payload_registry_->ulpfec_payload_type() > -1;
136273fbbb921e61273c3d83eb494d0a68db7834d3dasapersson@webrtc.org}
137273fbbb921e61273c3d83eb494d0a68db7834d3dasapersson@webrtc.org
138822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.orguint32_t ViEReceiver::GetRemoteSsrc() const {
139822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org  return rtp_receiver_->SSRC();
140822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org}
141822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org
142822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.orgint ViEReceiver::GetCsrcs(uint32_t* csrcs) const {
143822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org  return rtp_receiver_->CSRCs(csrcs);
144822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org}
145822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org
1462853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.orgvoid ViEReceiver::SetRtpRtcpModule(RtpRtcp* module) {
1472853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org  rtp_rtcp_ = module;
1482853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org}
1492853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org
150822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.orgRtpReceiver* ViEReceiver::GetRtpReceiver() const {
151822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org  return rtp_receiver_.get();
152822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org}
153822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org
154d6f1a38165455d743fbe61f6980f22be6a3c4de9Peter Boströmvoid ViEReceiver::RegisterRtpRtcpModules(
155d6f1a38165455d743fbe61f6980f22be6a3c4de9Peter Boström    const std::vector<RtpRtcp*>& rtp_modules) {
1566cff9cf8a3562f76b1dfe4584f447dd66c2d05f2Peter Boström  CriticalSectionScoped cs(receive_cs_.get());
157d6f1a38165455d743fbe61f6980f22be6a3c4de9Peter Boström  // Only change the "simulcast" modules, the base module can be accessed
158d6f1a38165455d743fbe61f6980f22be6a3c4de9Peter Boström  // without a lock whereas the simulcast modules require locking as they can be
159d6f1a38165455d743fbe61f6980f22be6a3c4de9Peter Boström  // changed in runtime.
160d6f1a38165455d743fbe61f6980f22be6a3c4de9Peter Boström  rtp_rtcp_simulcast_ =
161d6f1a38165455d743fbe61f6980f22be6a3c4de9Peter Boström      std::vector<RtpRtcp*>(rtp_modules.begin() + 1, rtp_modules.end());
1626cff9cf8a3562f76b1dfe4584f447dd66c2d05f2Peter Boström}
1636cff9cf8a3562f76b1dfe4584f447dd66c2d05f2Peter Boström
16408994cc525110d7cef1e3990aef7f2d6fa0a8f2cstefan@webrtc.orgbool ViEReceiver::SetReceiveTimestampOffsetStatus(bool enable, int id) {
165a5cb98cbbd11e93cb6d0a6232387814aac168c7dstefan@webrtc.org  if (enable) {
166a5cb98cbbd11e93cb6d0a6232387814aac168c7dstefan@webrtc.org    return rtp_header_parser_->RegisterRtpHeaderExtension(
167a5cb98cbbd11e93cb6d0a6232387814aac168c7dstefan@webrtc.org        kRtpExtensionTransmissionTimeOffset, id);
168a5cb98cbbd11e93cb6d0a6232387814aac168c7dstefan@webrtc.org  } else {
169a5cb98cbbd11e93cb6d0a6232387814aac168c7dstefan@webrtc.org    return rtp_header_parser_->DeregisterRtpHeaderExtension(
170a5cb98cbbd11e93cb6d0a6232387814aac168c7dstefan@webrtc.org        kRtpExtensionTransmissionTimeOffset);
171a5cb98cbbd11e93cb6d0a6232387814aac168c7dstefan@webrtc.org  }
172a5cb98cbbd11e93cb6d0a6232387814aac168c7dstefan@webrtc.org}
173a5cb98cbbd11e93cb6d0a6232387814aac168c7dstefan@webrtc.org
17408994cc525110d7cef1e3990aef7f2d6fa0a8f2cstefan@webrtc.orgbool ViEReceiver::SetReceiveAbsoluteSendTimeStatus(bool enable, int id) {
175a5cb98cbbd11e93cb6d0a6232387814aac168c7dstefan@webrtc.org  if (enable) {
1763fb8f7bbb0c5e074d0744c57905c5f49bb7d8304solenberg@webrtc.org    if (rtp_header_parser_->RegisterRtpHeaderExtension(
1773fb8f7bbb0c5e074d0744c57905c5f49bb7d8304solenberg@webrtc.org        kRtpExtensionAbsoluteSendTime, id)) {
1783fb8f7bbb0c5e074d0744c57905c5f49bb7d8304solenberg@webrtc.org      receiving_ast_enabled_ = true;
1793fb8f7bbb0c5e074d0744c57905c5f49bb7d8304solenberg@webrtc.org      return true;
1803fb8f7bbb0c5e074d0744c57905c5f49bb7d8304solenberg@webrtc.org    } else {
1813fb8f7bbb0c5e074d0744c57905c5f49bb7d8304solenberg@webrtc.org      return false;
1823fb8f7bbb0c5e074d0744c57905c5f49bb7d8304solenberg@webrtc.org    }
183a5cb98cbbd11e93cb6d0a6232387814aac168c7dstefan@webrtc.org  } else {
1843fb8f7bbb0c5e074d0744c57905c5f49bb7d8304solenberg@webrtc.org    receiving_ast_enabled_ = false;
185a5cb98cbbd11e93cb6d0a6232387814aac168c7dstefan@webrtc.org    return rtp_header_parser_->DeregisterRtpHeaderExtension(
186a5cb98cbbd11e93cb6d0a6232387814aac168c7dstefan@webrtc.org        kRtpExtensionAbsoluteSendTime);
187a5cb98cbbd11e93cb6d0a6232387814aac168c7dstefan@webrtc.org  }
188a5cb98cbbd11e93cb6d0a6232387814aac168c7dstefan@webrtc.org}
189a5cb98cbbd11e93cb6d0a6232387814aac168c7dstefan@webrtc.org
190fdd10579496123c9a7fdc0bf185e2a26a12ed340guoweis@webrtc.orgbool ViEReceiver::SetReceiveVideoRotationStatus(bool enable, int id) {
191fdd10579496123c9a7fdc0bf185e2a26a12ed340guoweis@webrtc.org  if (enable) {
192fdd10579496123c9a7fdc0bf185e2a26a12ed340guoweis@webrtc.org    if (rtp_header_parser_->RegisterRtpHeaderExtension(
193fdd10579496123c9a7fdc0bf185e2a26a12ed340guoweis@webrtc.org            kRtpExtensionVideoRotation, id)) {
194fdd10579496123c9a7fdc0bf185e2a26a12ed340guoweis@webrtc.org      receiving_cvo_enabled_ = true;
195fdd10579496123c9a7fdc0bf185e2a26a12ed340guoweis@webrtc.org      return true;
196fdd10579496123c9a7fdc0bf185e2a26a12ed340guoweis@webrtc.org    } else {
197fdd10579496123c9a7fdc0bf185e2a26a12ed340guoweis@webrtc.org      return false;
198fdd10579496123c9a7fdc0bf185e2a26a12ed340guoweis@webrtc.org    }
199fdd10579496123c9a7fdc0bf185e2a26a12ed340guoweis@webrtc.org  } else {
200fdd10579496123c9a7fdc0bf185e2a26a12ed340guoweis@webrtc.org    receiving_cvo_enabled_ = false;
201fdd10579496123c9a7fdc0bf185e2a26a12ed340guoweis@webrtc.org    return rtp_header_parser_->DeregisterRtpHeaderExtension(
202fdd10579496123c9a7fdc0bf185e2a26a12ed340guoweis@webrtc.org        kRtpExtensionVideoRotation);
203fdd10579496123c9a7fdc0bf185e2a26a12ed340guoweis@webrtc.org  }
204fdd10579496123c9a7fdc0bf185e2a26a12ed340guoweis@webrtc.org}
205fdd10579496123c9a7fdc0bf185e2a26a12ed340guoweis@webrtc.org
206867fb5224e1ba6a1c2cd523c005499a93ed61a08sprangbool ViEReceiver::SetReceiveTransportSequenceNumber(bool enable, int id) {
207867fb5224e1ba6a1c2cd523c005499a93ed61a08sprang  if (enable) {
208867fb5224e1ba6a1c2cd523c005499a93ed61a08sprang    if (rtp_header_parser_->RegisterRtpHeaderExtension(
209867fb5224e1ba6a1c2cd523c005499a93ed61a08sprang            kRtpExtensionTransportSequenceNumber, id)) {
210867fb5224e1ba6a1c2cd523c005499a93ed61a08sprang      receiving_tsn_enabled_ = true;
211867fb5224e1ba6a1c2cd523c005499a93ed61a08sprang      return true;
212867fb5224e1ba6a1c2cd523c005499a93ed61a08sprang    } else {
213867fb5224e1ba6a1c2cd523c005499a93ed61a08sprang      return false;
214867fb5224e1ba6a1c2cd523c005499a93ed61a08sprang    }
215867fb5224e1ba6a1c2cd523c005499a93ed61a08sprang  } else {
216867fb5224e1ba6a1c2cd523c005499a93ed61a08sprang    receiving_tsn_enabled_ = false;
217867fb5224e1ba6a1c2cd523c005499a93ed61a08sprang    return rtp_header_parser_->DeregisterRtpHeaderExtension(
218867fb5224e1ba6a1c2cd523c005499a93ed61a08sprang        kRtpExtensionTransportSequenceNumber);
219867fb5224e1ba6a1c2cd523c005499a93ed61a08sprang  }
220867fb5224e1ba6a1c2cd523c005499a93ed61a08sprang}
221867fb5224e1ba6a1c2cd523c005499a93ed61a08sprang
222ad4ee3659e4298d9b006d00399e9a77e18d2eae1mflodman@webrtc.orgint ViEReceiver::ReceivedRTPPacket(const void* rtp_packet,
2234591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org                                   size_t rtp_packet_length,
224a9890800e078105f21f0a21358ee59a0b3736af6wu@webrtc.org                                   const PacketTime& packet_time) {
225fc320466d12e16c1e80f57b8cff864627f2766f6solenberg@webrtc.org  return InsertRTPPacket(static_cast<const uint8_t*>(rtp_packet),
226a9890800e078105f21f0a21358ee59a0b3736af6wu@webrtc.org                         rtp_packet_length, packet_time);
227470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
228470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
229ad4ee3659e4298d9b006d00399e9a77e18d2eae1mflodman@webrtc.orgint ViEReceiver::ReceivedRTCPPacket(const void* rtcp_packet,
2304591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org                                    size_t rtcp_packet_length) {
231fc320466d12e16c1e80f57b8cff864627f2766f6solenberg@webrtc.org  return InsertRTCPPacket(static_cast<const uint8_t*>(rtcp_packet),
232ad4ee3659e4298d9b006d00399e9a77e18d2eae1mflodman@webrtc.org                          rtcp_packet_length);
233470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
234470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2354591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.orgint32_t ViEReceiver::OnReceivedPayloadData(const uint8_t* payload_data,
2364591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org                                           const size_t payload_size,
2374591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org                                           const WebRtcRTPHeader* rtp_header) {
238cd70119a106e42ab7eac58050d067bc050610739wu@webrtc.org  WebRtcRTPHeader rtp_header_with_ntp = *rtp_header;
23988abf11cadc0eb8986561a942ecc13ad9a324f16wu@webrtc.org  rtp_header_with_ntp.ntp_time_ms =
24088abf11cadc0eb8986561a942ecc13ad9a324f16wu@webrtc.org      ntp_estimator_->Estimate(rtp_header->header.timestamp);
241cd70119a106e42ab7eac58050d067bc050610739wu@webrtc.org  if (vcm_->IncomingPacket(payload_data,
242cd70119a106e42ab7eac58050d067bc050610739wu@webrtc.org                           payload_size,
243cd70119a106e42ab7eac58050d067bc050610739wu@webrtc.org                           rtp_header_with_ntp) != 0) {
244ad4ee3659e4298d9b006d00399e9a77e18d2eae1mflodman@webrtc.org    // Check this...
245ad4ee3659e4298d9b006d00399e9a77e18d2eae1mflodman@webrtc.org    return -1;
246ad4ee3659e4298d9b006d00399e9a77e18d2eae1mflodman@webrtc.org  }
247ad4ee3659e4298d9b006d00399e9a77e18d2eae1mflodman@webrtc.org  return 0;
248470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
249470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
250822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.orgbool ViEReceiver::OnRecoveredPacket(const uint8_t* rtp_packet,
2514591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org                                    size_t rtp_packet_length) {
252822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org  RTPHeader header;
253822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org  if (!rtp_header_parser_->Parse(rtp_packet, rtp_packet_length, &header)) {
254822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org    return false;
255822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org  }
256822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org  header.payload_type_frequency = kVideoPayloadTypeFrequency;
25701581da71145d4b9504d12cfad0c988d1fc68654stefan@webrtc.org  bool in_order = IsPacketInOrder(header);
25801581da71145d4b9504d12cfad0c988d1fc68654stefan@webrtc.org  return ReceivePacket(rtp_packet, rtp_packet_length, header, in_order);
259822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org}
260822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org
261fc320466d12e16c1e80f57b8cff864627f2766f6solenberg@webrtc.orgint ViEReceiver::InsertRTPPacket(const uint8_t* rtp_packet,
2624591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org                                 size_t rtp_packet_length,
263a9890800e078105f21f0a21358ee59a0b3736af6wu@webrtc.org                                 const PacketTime& packet_time) {
264ad4ee3659e4298d9b006d00399e9a77e18d2eae1mflodman@webrtc.org  {
265d32c44738a034977b659bb4a2e76a97f027555e4mflodman@webrtc.org    CriticalSectionScoped cs(receive_cs_.get());
266b6433b7a1e0771aea3701279f6745543070b0589braveyao@webrtc.org    if (!receiving_) {
267b6433b7a1e0771aea3701279f6745543070b0589braveyao@webrtc.org      return -1;
268b6433b7a1e0771aea3701279f6745543070b0589braveyao@webrtc.org    }
269ad4ee3659e4298d9b006d00399e9a77e18d2eae1mflodman@webrtc.org  }
270fc320466d12e16c1e80f57b8cff864627f2766f6solenberg@webrtc.org
271a5cb98cbbd11e93cb6d0a6232387814aac168c7dstefan@webrtc.org  RTPHeader header;
272fc320466d12e16c1e80f57b8cff864627f2766f6solenberg@webrtc.org  if (!rtp_header_parser_->Parse(rtp_packet, rtp_packet_length,
273a5cb98cbbd11e93cb6d0a6232387814aac168c7dstefan@webrtc.org                                 &header)) {
274a5cb98cbbd11e93cb6d0a6232387814aac168c7dstefan@webrtc.org    return -1;
275a5cb98cbbd11e93cb6d0a6232387814aac168c7dstefan@webrtc.org  }
2764591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org  size_t payload_length = rtp_packet_length - header.headerLength;
277a9890800e078105f21f0a21358ee59a0b3736af6wu@webrtc.org  int64_t arrival_time_ms;
278eb24b04f1631aeee670230aa6600d28ae23890d0stefan@webrtc.org  int64_t now_ms = clock_->TimeInMilliseconds();
279a9890800e078105f21f0a21358ee59a0b3736af6wu@webrtc.org  if (packet_time.timestamp != -1)
280a9890800e078105f21f0a21358ee59a0b3736af6wu@webrtc.org    arrival_time_ms = (packet_time.timestamp + 500) / 1000;
281a9890800e078105f21f0a21358ee59a0b3736af6wu@webrtc.org  else
282eb24b04f1631aeee670230aa6600d28ae23890d0stefan@webrtc.org    arrival_time_ms = now_ms;
283eb24b04f1631aeee670230aa6600d28ae23890d0stefan@webrtc.org
284eb24b04f1631aeee670230aa6600d28ae23890d0stefan@webrtc.org  {
285eb24b04f1631aeee670230aa6600d28ae23890d0stefan@webrtc.org    // Periodically log the RTP header of incoming packets.
286eb24b04f1631aeee670230aa6600d28ae23890d0stefan@webrtc.org    CriticalSectionScoped cs(receive_cs_.get());
287eb24b04f1631aeee670230aa6600d28ae23890d0stefan@webrtc.org    if (now_ms - last_packet_log_ms_ > kPacketLogIntervalMs) {
288eb24b04f1631aeee670230aa6600d28ae23890d0stefan@webrtc.org      std::stringstream ss;
289eb24b04f1631aeee670230aa6600d28ae23890d0stefan@webrtc.org      ss << "Packet received on SSRC: " << header.ssrc << " with payload type: "
290eb24b04f1631aeee670230aa6600d28ae23890d0stefan@webrtc.org         << static_cast<int>(header.payloadType) << ", timestamp: "
291eb24b04f1631aeee670230aa6600d28ae23890d0stefan@webrtc.org         << header.timestamp << ", sequence number: " << header.sequenceNumber
292eb24b04f1631aeee670230aa6600d28ae23890d0stefan@webrtc.org         << ", arrival time: " << arrival_time_ms;
293eb24b04f1631aeee670230aa6600d28ae23890d0stefan@webrtc.org      if (header.extension.hasTransmissionTimeOffset)
294eb24b04f1631aeee670230aa6600d28ae23890d0stefan@webrtc.org        ss << ", toffset: " << header.extension.transmissionTimeOffset;
295eb24b04f1631aeee670230aa6600d28ae23890d0stefan@webrtc.org      if (header.extension.hasAbsoluteSendTime)
296eb24b04f1631aeee670230aa6600d28ae23890d0stefan@webrtc.org        ss << ", abs send time: " << header.extension.absoluteSendTime;
297eb24b04f1631aeee670230aa6600d28ae23890d0stefan@webrtc.org      LOG(LS_INFO) << ss.str();
298eb24b04f1631aeee670230aa6600d28ae23890d0stefan@webrtc.org      last_packet_log_ms_ = now_ms;
299eb24b04f1631aeee670230aa6600d28ae23890d0stefan@webrtc.org    }
300eb24b04f1631aeee670230aa6600d28ae23890d0stefan@webrtc.org  }
301a9890800e078105f21f0a21358ee59a0b3736af6wu@webrtc.org
302ff4ea9310e981da6292fb044cff9eeefd986cf2bStefan Holmer  remote_bitrate_estimator_->IncomingPacket(arrival_time_ms, payload_length,
303ff4ea9310e981da6292fb044cff9eeefd986cf2bStefan Holmer                                            header, true);
304822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org  header.payload_type_frequency = kVideoPayloadTypeFrequency;
3057bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org
30648df38114d9502f4b4ad700c011190c608a702d5stefan@webrtc.org  bool in_order = IsPacketInOrder(header);
3077bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  rtp_payload_registry_->SetIncomingPayloadType(header);
3081457b4737a82cc3624daf3a997f6257d13a3f974asapersson@webrtc.org  int ret = ReceivePacket(rtp_packet, rtp_packet_length, header, in_order)
309fc320466d12e16c1e80f57b8cff864627f2766f6solenberg@webrtc.org      ? 0
310fc320466d12e16c1e80f57b8cff864627f2766f6solenberg@webrtc.org      : -1;
3111457b4737a82cc3624daf3a997f6257d13a3f974asapersson@webrtc.org  // Update receive statistics after ReceivePacket.
3121457b4737a82cc3624daf3a997f6257d13a3f974asapersson@webrtc.org  // Receive statistics will be reset if the payload type changes (make sure
3131457b4737a82cc3624daf3a997f6257d13a3f974asapersson@webrtc.org  // that the first packet is included in the stats).
3141457b4737a82cc3624daf3a997f6257d13a3f974asapersson@webrtc.org  rtp_receive_statistics_->IncomingPacket(
3151457b4737a82cc3624daf3a997f6257d13a3f974asapersson@webrtc.org      header, rtp_packet_length, IsPacketRetransmitted(header, in_order));
3161457b4737a82cc3624daf3a997f6257d13a3f974asapersson@webrtc.org  return ret;
3177bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org}
3187bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org
3197bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.orgbool ViEReceiver::ReceivePacket(const uint8_t* packet,
3204591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org                                size_t packet_length,
3217bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org                                const RTPHeader& header,
3227bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org                                bool in_order) {
3237bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  if (rtp_payload_registry_->IsEncapsulated(header)) {
3247bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org    return ParseAndHandleEncapsulatingHeader(packet, packet_length, header);
3257bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  }
3267bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  const uint8_t* payload = packet + header.headerLength;
3274591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org  assert(packet_length >= header.headerLength);
3284591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org  size_t payload_length = packet_length - header.headerLength;
329822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org  PayloadUnion payload_specific;
330822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org  if (!rtp_payload_registry_->GetPayloadSpecifics(header.payloadType,
331822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org                                                  &payload_specific)) {
3327bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org    return false;
333822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org  }
3347bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  return rtp_receiver_->IncomingRtpPacket(header, payload, payload_length,
3357bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org                                          payload_specific, in_order);
3367bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org}
3377bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org
3387bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.orgbool ViEReceiver::ParseAndHandleEncapsulatingHeader(const uint8_t* packet,
3394591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org                                                    size_t packet_length,
3407bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org                                                    const RTPHeader& header) {
3417bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  if (rtp_payload_registry_->IsRed(header)) {
3420e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org    int8_t ulpfec_pt = rtp_payload_registry_->ulpfec_payload_type();
34337c0559c1edd108b345abcce1939f9b8d78d02a3asapersson@webrtc.org    if (packet[header.headerLength] == ulpfec_pt) {
344273fbbb921e61273c3d83eb494d0a68db7834d3dasapersson@webrtc.org      rtp_receive_statistics_->FecPacketReceived(header, packet_length);
34537c0559c1edd108b345abcce1939f9b8d78d02a3asapersson@webrtc.org      // Notify vcm about received FEC packets to avoid NACKing these packets.
34637c0559c1edd108b345abcce1939f9b8d78d02a3asapersson@webrtc.org      NotifyReceiverOfFecPacket(header);
34737c0559c1edd108b345abcce1939f9b8d78d02a3asapersson@webrtc.org    }
3487bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org    if (fec_receiver_->AddReceivedRedPacket(
3490e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org            header, packet, packet_length, ulpfec_pt) != 0) {
3507bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org      return false;
3517bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org    }
3527bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org    return fec_receiver_->ProcessReceivedFec() == 0;
3537bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  } else if (rtp_payload_registry_->IsRtx(header)) {
3547c6ff2da261699628e7253d9d10068bc531fe0f8stefan@webrtc.org    if (header.headerLength + header.paddingLength == packet_length) {
3557c6ff2da261699628e7253d9d10068bc531fe0f8stefan@webrtc.org      // This is an empty packet and should be silently dropped before trying to
3567c6ff2da261699628e7253d9d10068bc531fe0f8stefan@webrtc.org      // parse the RTX header.
3577c6ff2da261699628e7253d9d10068bc531fe0f8stefan@webrtc.org      return true;
3587c6ff2da261699628e7253d9d10068bc531fe0f8stefan@webrtc.org    }
3597bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org    // Remove the RTX header and parse the original RTP header.
3607bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org    if (packet_length < header.headerLength)
3617bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org      return false;
3624591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org    if (packet_length > sizeof(restored_packet_))
3637bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org      return false;
3647bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org    CriticalSectionScoped cs(receive_cs_.get());
3657bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org    if (restored_packet_in_use_) {
3664e2806d85fb1a526732ba4c046cbc935bc47bf1apbos@webrtc.org      LOG(LS_WARNING) << "Multiple RTX headers detected, dropping packet.";
3677bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org      return false;
3687bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org    }
3697bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org    if (!rtp_payload_registry_->RestoreOriginalPacket(
37065220a70a38ffe252b587775c5e9104606ab7c2cnoahric            restored_packet_, packet, &packet_length, rtp_receiver_->SSRC(),
37165220a70a38ffe252b587775c5e9104606ab7c2cnoahric            header)) {
3724e2806d85fb1a526732ba4c046cbc935bc47bf1apbos@webrtc.org      LOG(LS_WARNING) << "Incoming RTX packet: Invalid RTP header";
3737bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org      return false;
3747bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org    }
3757bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org    restored_packet_in_use_ = true;
37665220a70a38ffe252b587775c5e9104606ab7c2cnoahric    bool ret = OnRecoveredPacket(restored_packet_, packet_length);
3777bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org    restored_packet_in_use_ = false;
3787bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org    return ret;
3797bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  }
3807bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  return false;
381470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
382470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
38337c0559c1edd108b345abcce1939f9b8d78d02a3asapersson@webrtc.orgvoid ViEReceiver::NotifyReceiverOfFecPacket(const RTPHeader& header) {
38437c0559c1edd108b345abcce1939f9b8d78d02a3asapersson@webrtc.org  int8_t last_media_payload_type =
38537c0559c1edd108b345abcce1939f9b8d78d02a3asapersson@webrtc.org      rtp_payload_registry_->last_received_media_payload_type();
38637c0559c1edd108b345abcce1939f9b8d78d02a3asapersson@webrtc.org  if (last_media_payload_type < 0) {
38737c0559c1edd108b345abcce1939f9b8d78d02a3asapersson@webrtc.org    LOG(LS_WARNING) << "Failed to get last media payload type.";
38837c0559c1edd108b345abcce1939f9b8d78d02a3asapersson@webrtc.org    return;
38937c0559c1edd108b345abcce1939f9b8d78d02a3asapersson@webrtc.org  }
39037c0559c1edd108b345abcce1939f9b8d78d02a3asapersson@webrtc.org  // Fake an empty media packet.
39137c0559c1edd108b345abcce1939f9b8d78d02a3asapersson@webrtc.org  WebRtcRTPHeader rtp_header = {};
39237c0559c1edd108b345abcce1939f9b8d78d02a3asapersson@webrtc.org  rtp_header.header = header;
39337c0559c1edd108b345abcce1939f9b8d78d02a3asapersson@webrtc.org  rtp_header.header.payloadType = last_media_payload_type;
39437c0559c1edd108b345abcce1939f9b8d78d02a3asapersson@webrtc.org  rtp_header.header.paddingLength = 0;
39537c0559c1edd108b345abcce1939f9b8d78d02a3asapersson@webrtc.org  PayloadUnion payload_specific;
39637c0559c1edd108b345abcce1939f9b8d78d02a3asapersson@webrtc.org  if (!rtp_payload_registry_->GetPayloadSpecifics(last_media_payload_type,
39737c0559c1edd108b345abcce1939f9b8d78d02a3asapersson@webrtc.org                                                  &payload_specific)) {
39837c0559c1edd108b345abcce1939f9b8d78d02a3asapersson@webrtc.org    LOG(LS_WARNING) << "Failed to get payload specifics.";
39937c0559c1edd108b345abcce1939f9b8d78d02a3asapersson@webrtc.org    return;
40037c0559c1edd108b345abcce1939f9b8d78d02a3asapersson@webrtc.org  }
40137c0559c1edd108b345abcce1939f9b8d78d02a3asapersson@webrtc.org  rtp_header.type.Video.codec = payload_specific.Video.videoCodecType;
402fdd10579496123c9a7fdc0bf185e2a26a12ed340guoweis@webrtc.org  rtp_header.type.Video.rotation = kVideoRotation_0;
403fdd10579496123c9a7fdc0bf185e2a26a12ed340guoweis@webrtc.org  if (header.extension.hasVideoRotation) {
404fdd10579496123c9a7fdc0bf185e2a26a12ed340guoweis@webrtc.org    rtp_header.type.Video.rotation =
405fdd10579496123c9a7fdc0bf185e2a26a12ed340guoweis@webrtc.org        ConvertCVOByteToVideoRotation(header.extension.videoRotation);
406fdd10579496123c9a7fdc0bf185e2a26a12ed340guoweis@webrtc.org  }
40737c0559c1edd108b345abcce1939f9b8d78d02a3asapersson@webrtc.org  OnReceivedPayloadData(NULL, 0, &rtp_header);
40837c0559c1edd108b345abcce1939f9b8d78d02a3asapersson@webrtc.org}
40937c0559c1edd108b345abcce1939f9b8d78d02a3asapersson@webrtc.org
410fc320466d12e16c1e80f57b8cff864627f2766f6solenberg@webrtc.orgint ViEReceiver::InsertRTCPPacket(const uint8_t* rtcp_packet,
4114591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org                                  size_t rtcp_packet_length) {
412ad4ee3659e4298d9b006d00399e9a77e18d2eae1mflodman@webrtc.org  {
413d32c44738a034977b659bb4a2e76a97f027555e4mflodman@webrtc.org    CriticalSectionScoped cs(receive_cs_.get());
414b6433b7a1e0771aea3701279f6745543070b0589braveyao@webrtc.org    if (!receiving_) {
415b6433b7a1e0771aea3701279f6745543070b0589braveyao@webrtc.org      return -1;
416b6433b7a1e0771aea3701279f6745543070b0589braveyao@webrtc.org    }
417ad4ee3659e4298d9b006d00399e9a77e18d2eae1mflodman@webrtc.org
418d6f1a38165455d743fbe61f6980f22be6a3c4de9Peter Boström    for (RtpRtcp* rtp_rtcp : rtp_rtcp_simulcast_)
4196cff9cf8a3562f76b1dfe4584f447dd66c2d05f2Peter Boström      rtp_rtcp->IncomingRtcpPacket(rtcp_packet, rtcp_packet_length);
420ad4ee3659e4298d9b006d00399e9a77e18d2eae1mflodman@webrtc.org  }
4212853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org  assert(rtp_rtcp_);  // Should be set by owner at construction time.
422cd70119a106e42ab7eac58050d067bc050610739wu@webrtc.org  int ret = rtp_rtcp_->IncomingRtcpPacket(rtcp_packet, rtcp_packet_length);
423cd70119a106e42ab7eac58050d067bc050610739wu@webrtc.org  if (ret != 0) {
424cd70119a106e42ab7eac58050d067bc050610739wu@webrtc.org    return ret;
425cd70119a106e42ab7eac58050d067bc050610739wu@webrtc.org  }
426cd70119a106e42ab7eac58050d067bc050610739wu@webrtc.org
42716825b1a828bb4ff40f7682040e43a239b7b8ca3pkasting@chromium.org  int64_t rtt = 0;
4282c0cdbce226137a8f755ae0fb51c28a335b2ea5dminyue@webrtc.org  rtp_rtcp_->RTT(rtp_receiver_->SSRC(), &rtt, NULL, NULL, NULL);
4292c0cdbce226137a8f755ae0fb51c28a335b2ea5dminyue@webrtc.org  if (rtt == 0) {
4302c0cdbce226137a8f755ae0fb51c28a335b2ea5dminyue@webrtc.org    // Waiting for valid rtt.
4312c0cdbce226137a8f755ae0fb51c28a335b2ea5dminyue@webrtc.org    return 0;
4322c0cdbce226137a8f755ae0fb51c28a335b2ea5dminyue@webrtc.org  }
4332c0cdbce226137a8f755ae0fb51c28a335b2ea5dminyue@webrtc.org  uint32_t ntp_secs = 0;
4342c0cdbce226137a8f755ae0fb51c28a335b2ea5dminyue@webrtc.org  uint32_t ntp_frac = 0;
4352c0cdbce226137a8f755ae0fb51c28a335b2ea5dminyue@webrtc.org  uint32_t rtp_timestamp = 0;
4362c0cdbce226137a8f755ae0fb51c28a335b2ea5dminyue@webrtc.org  if (0 != rtp_rtcp_->RemoteNTP(&ntp_secs, &ntp_frac, NULL, NULL,
4372c0cdbce226137a8f755ae0fb51c28a335b2ea5dminyue@webrtc.org                                &rtp_timestamp)) {
4382c0cdbce226137a8f755ae0fb51c28a335b2ea5dminyue@webrtc.org    // Waiting for RTCP.
4392c0cdbce226137a8f755ae0fb51c28a335b2ea5dminyue@webrtc.org    return 0;
4402c0cdbce226137a8f755ae0fb51c28a335b2ea5dminyue@webrtc.org  }
4412c0cdbce226137a8f755ae0fb51c28a335b2ea5dminyue@webrtc.org  ntp_estimator_->UpdateRtcpTimestamp(rtt, ntp_secs, ntp_frac, rtp_timestamp);
442cd70119a106e42ab7eac58050d067bc050610739wu@webrtc.org
443cd70119a106e42ab7eac58050d067bc050610739wu@webrtc.org  return 0;
444cd70119a106e42ab7eac58050d067bc050610739wu@webrtc.org}
445cd70119a106e42ab7eac58050d067bc050610739wu@webrtc.org
446ad4ee3659e4298d9b006d00399e9a77e18d2eae1mflodman@webrtc.orgvoid ViEReceiver::StartReceive() {
447b6433b7a1e0771aea3701279f6745543070b0589braveyao@webrtc.org  CriticalSectionScoped cs(receive_cs_.get());
448ad4ee3659e4298d9b006d00399e9a77e18d2eae1mflodman@webrtc.org  receiving_ = true;
449470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
450470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
451ad4ee3659e4298d9b006d00399e9a77e18d2eae1mflodman@webrtc.orgvoid ViEReceiver::StopReceive() {
452b6433b7a1e0771aea3701279f6745543070b0589braveyao@webrtc.org  CriticalSectionScoped cs(receive_cs_.get());
453ad4ee3659e4298d9b006d00399e9a77e18d2eae1mflodman@webrtc.org  receiving_ = false;
454470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
455470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
456822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.orgReceiveStatistics* ViEReceiver::GetReceiveStatistics() const {
457822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org  return rtp_receive_statistics_.get();
458822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org}
459822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org
4607bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.orgbool ViEReceiver::IsPacketInOrder(const RTPHeader& header) const {
4617bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  StreamStatistician* statistician =
4627bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org      rtp_receive_statistics_->GetStatistician(header.ssrc);
4637bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  if (!statistician)
4647bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org    return false;
4657bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  return statistician->IsPacketInOrder(header.sequenceNumber);
4667bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org}
4677bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org
46848df38114d9502f4b4ad700c011190c608a702d5stefan@webrtc.orgbool ViEReceiver::IsPacketRetransmitted(const RTPHeader& header,
46948df38114d9502f4b4ad700c011190c608a702d5stefan@webrtc.org                                        bool in_order) const {
4707bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  // Retransmissions are handled separately if RTX is enabled.
4717bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  if (rtp_payload_registry_->RtxEnabled())
4727bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org    return false;
4737bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  StreamStatistician* statistician =
4747bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org      rtp_receive_statistics_->GetStatistician(header.ssrc);
4757bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  if (!statistician)
4767bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org    return false;
4777bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  // Check if this is a retransmission.
47816825b1a828bb4ff40f7682040e43a239b7b8ca3pkasting@chromium.org  int64_t min_rtt = 0;
4797bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  rtp_rtcp_->RTT(rtp_receiver_->SSRC(), NULL, NULL, &min_rtt, NULL);
48048df38114d9502f4b4ad700c011190c608a702d5stefan@webrtc.org  return !in_order &&
4817bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org      statistician->IsRetransmitOfOldPacket(header, min_rtt);
482822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org}
483ad4ee3659e4298d9b006d00399e9a77e18d2eae1mflodman@webrtc.org}  // namespace webrtc
484