xref: /aosp_15_r20/external/webrtc/video/rtp_video_stream_receiver2.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker 
11*d9f75844SAndroid Build Coastguard Worker #include "video/rtp_video_stream_receiver2.h"
12*d9f75844SAndroid Build Coastguard Worker 
13*d9f75844SAndroid Build Coastguard Worker #include <algorithm>
14*d9f75844SAndroid Build Coastguard Worker #include <limits>
15*d9f75844SAndroid Build Coastguard Worker #include <memory>
16*d9f75844SAndroid Build Coastguard Worker #include <utility>
17*d9f75844SAndroid Build Coastguard Worker #include <vector>
18*d9f75844SAndroid Build Coastguard Worker 
19*d9f75844SAndroid Build Coastguard Worker #include "absl/algorithm/container.h"
20*d9f75844SAndroid Build Coastguard Worker #include "absl/memory/memory.h"
21*d9f75844SAndroid Build Coastguard Worker #include "absl/types/optional.h"
22*d9f75844SAndroid Build Coastguard Worker #include "api/video/video_codec_type.h"
23*d9f75844SAndroid Build Coastguard Worker #include "media/base/media_constants.h"
24*d9f75844SAndroid Build Coastguard Worker #include "modules/pacing/packet_router.h"
25*d9f75844SAndroid Build Coastguard Worker #include "modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
26*d9f75844SAndroid Build Coastguard Worker #include "modules/rtp_rtcp/include/receive_statistics.h"
27*d9f75844SAndroid Build Coastguard Worker #include "modules/rtp_rtcp/include/rtp_cvo.h"
28*d9f75844SAndroid Build Coastguard Worker #include "modules/rtp_rtcp/source/create_video_rtp_depacketizer.h"
29*d9f75844SAndroid Build Coastguard Worker #include "modules/rtp_rtcp/source/rtp_dependency_descriptor_extension.h"
30*d9f75844SAndroid Build Coastguard Worker #include "modules/rtp_rtcp/source/rtp_format.h"
31*d9f75844SAndroid Build Coastguard Worker #include "modules/rtp_rtcp/source/rtp_generic_frame_descriptor.h"
32*d9f75844SAndroid Build Coastguard Worker #include "modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension.h"
33*d9f75844SAndroid Build Coastguard Worker #include "modules/rtp_rtcp/source/rtp_header_extensions.h"
34*d9f75844SAndroid Build Coastguard Worker #include "modules/rtp_rtcp/source/rtp_packet_received.h"
35*d9f75844SAndroid Build Coastguard Worker #include "modules/rtp_rtcp/source/rtp_rtcp_config.h"
36*d9f75844SAndroid Build Coastguard Worker #include "modules/rtp_rtcp/source/ulpfec_receiver.h"
37*d9f75844SAndroid Build Coastguard Worker #include "modules/rtp_rtcp/source/video_rtp_depacketizer.h"
38*d9f75844SAndroid Build Coastguard Worker #include "modules/rtp_rtcp/source/video_rtp_depacketizer_raw.h"
39*d9f75844SAndroid Build Coastguard Worker #include "modules/video_coding/frame_object.h"
40*d9f75844SAndroid Build Coastguard Worker #include "modules/video_coding/h264_sprop_parameter_sets.h"
41*d9f75844SAndroid Build Coastguard Worker #include "modules/video_coding/h264_sps_pps_tracker.h"
42*d9f75844SAndroid Build Coastguard Worker #include "modules/video_coding/nack_requester.h"
43*d9f75844SAndroid Build Coastguard Worker #include "modules/video_coding/packet_buffer.h"
44*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
45*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
46*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/strings/string_builder.h"
47*d9f75844SAndroid Build Coastguard Worker #include "system_wrappers/include/metrics.h"
48*d9f75844SAndroid Build Coastguard Worker #include "system_wrappers/include/ntp_time.h"
49*d9f75844SAndroid Build Coastguard Worker 
50*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
51*d9f75844SAndroid Build Coastguard Worker 
52*d9f75844SAndroid Build Coastguard Worker namespace {
53*d9f75844SAndroid Build Coastguard Worker // TODO(philipel): Change kPacketBufferStartSize back to 32 in M63 see:
54*d9f75844SAndroid Build Coastguard Worker //                 crbug.com/752886
55*d9f75844SAndroid Build Coastguard Worker constexpr int kPacketBufferStartSize = 512;
56*d9f75844SAndroid Build Coastguard Worker constexpr int kPacketBufferMaxSize = 2048;
57*d9f75844SAndroid Build Coastguard Worker 
58*d9f75844SAndroid Build Coastguard Worker constexpr int kMaxPacketAgeToNack = 450;
59*d9f75844SAndroid Build Coastguard Worker 
PacketBufferMaxSize(const FieldTrialsView & field_trials)60*d9f75844SAndroid Build Coastguard Worker int PacketBufferMaxSize(const FieldTrialsView& field_trials) {
61*d9f75844SAndroid Build Coastguard Worker   // The group here must be a positive power of 2, in which case that is used as
62*d9f75844SAndroid Build Coastguard Worker   // size. All other values shall result in the default value being used.
63*d9f75844SAndroid Build Coastguard Worker   const std::string group_name =
64*d9f75844SAndroid Build Coastguard Worker       field_trials.Lookup("WebRTC-PacketBufferMaxSize");
65*d9f75844SAndroid Build Coastguard Worker   int packet_buffer_max_size = kPacketBufferMaxSize;
66*d9f75844SAndroid Build Coastguard Worker   if (!group_name.empty() &&
67*d9f75844SAndroid Build Coastguard Worker       (sscanf(group_name.c_str(), "%d", &packet_buffer_max_size) != 1 ||
68*d9f75844SAndroid Build Coastguard Worker        packet_buffer_max_size <= 0 ||
69*d9f75844SAndroid Build Coastguard Worker        // Verify that the number is a positive power of 2.
70*d9f75844SAndroid Build Coastguard Worker        (packet_buffer_max_size & (packet_buffer_max_size - 1)) != 0)) {
71*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << "Invalid packet buffer max size: " << group_name;
72*d9f75844SAndroid Build Coastguard Worker     packet_buffer_max_size = kPacketBufferMaxSize;
73*d9f75844SAndroid Build Coastguard Worker   }
74*d9f75844SAndroid Build Coastguard Worker   return packet_buffer_max_size;
75*d9f75844SAndroid Build Coastguard Worker }
76*d9f75844SAndroid Build Coastguard Worker 
CreateRtpRtcpModule(Clock * clock,ReceiveStatistics * receive_statistics,Transport * outgoing_transport,RtcpRttStats * rtt_stats,RtcpPacketTypeCounterObserver * rtcp_packet_type_counter_observer,RtcpCnameCallback * rtcp_cname_callback,bool non_sender_rtt_measurement,uint32_t local_ssrc,RtcEventLog * rtc_event_log)77*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<ModuleRtpRtcpImpl2> CreateRtpRtcpModule(
78*d9f75844SAndroid Build Coastguard Worker     Clock* clock,
79*d9f75844SAndroid Build Coastguard Worker     ReceiveStatistics* receive_statistics,
80*d9f75844SAndroid Build Coastguard Worker     Transport* outgoing_transport,
81*d9f75844SAndroid Build Coastguard Worker     RtcpRttStats* rtt_stats,
82*d9f75844SAndroid Build Coastguard Worker     RtcpPacketTypeCounterObserver* rtcp_packet_type_counter_observer,
83*d9f75844SAndroid Build Coastguard Worker     RtcpCnameCallback* rtcp_cname_callback,
84*d9f75844SAndroid Build Coastguard Worker     bool non_sender_rtt_measurement,
85*d9f75844SAndroid Build Coastguard Worker     uint32_t local_ssrc,
86*d9f75844SAndroid Build Coastguard Worker     RtcEventLog* rtc_event_log) {
87*d9f75844SAndroid Build Coastguard Worker   RtpRtcpInterface::Configuration configuration;
88*d9f75844SAndroid Build Coastguard Worker   configuration.clock = clock;
89*d9f75844SAndroid Build Coastguard Worker   configuration.audio = false;
90*d9f75844SAndroid Build Coastguard Worker   configuration.receiver_only = true;
91*d9f75844SAndroid Build Coastguard Worker   configuration.receive_statistics = receive_statistics;
92*d9f75844SAndroid Build Coastguard Worker   configuration.outgoing_transport = outgoing_transport;
93*d9f75844SAndroid Build Coastguard Worker   configuration.rtt_stats = rtt_stats;
94*d9f75844SAndroid Build Coastguard Worker   configuration.rtcp_packet_type_counter_observer =
95*d9f75844SAndroid Build Coastguard Worker       rtcp_packet_type_counter_observer;
96*d9f75844SAndroid Build Coastguard Worker   configuration.rtcp_cname_callback = rtcp_cname_callback;
97*d9f75844SAndroid Build Coastguard Worker   configuration.local_media_ssrc = local_ssrc;
98*d9f75844SAndroid Build Coastguard Worker   configuration.non_sender_rtt_measurement = non_sender_rtt_measurement;
99*d9f75844SAndroid Build Coastguard Worker   configuration.event_log = rtc_event_log;
100*d9f75844SAndroid Build Coastguard Worker 
101*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<ModuleRtpRtcpImpl2> rtp_rtcp =
102*d9f75844SAndroid Build Coastguard Worker       ModuleRtpRtcpImpl2::Create(configuration);
103*d9f75844SAndroid Build Coastguard Worker   rtp_rtcp->SetRTCPStatus(RtcpMode::kCompound);
104*d9f75844SAndroid Build Coastguard Worker 
105*d9f75844SAndroid Build Coastguard Worker   return rtp_rtcp;
106*d9f75844SAndroid Build Coastguard Worker }
107*d9f75844SAndroid Build Coastguard Worker 
MaybeConstructNackModule(TaskQueueBase * current_queue,NackPeriodicProcessor * nack_periodic_processor,const NackConfig & nack,Clock * clock,NackSender * nack_sender,KeyFrameRequestSender * keyframe_request_sender,const FieldTrialsView & field_trials)108*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<NackRequester> MaybeConstructNackModule(
109*d9f75844SAndroid Build Coastguard Worker     TaskQueueBase* current_queue,
110*d9f75844SAndroid Build Coastguard Worker     NackPeriodicProcessor* nack_periodic_processor,
111*d9f75844SAndroid Build Coastguard Worker     const NackConfig& nack,
112*d9f75844SAndroid Build Coastguard Worker     Clock* clock,
113*d9f75844SAndroid Build Coastguard Worker     NackSender* nack_sender,
114*d9f75844SAndroid Build Coastguard Worker     KeyFrameRequestSender* keyframe_request_sender,
115*d9f75844SAndroid Build Coastguard Worker     const FieldTrialsView& field_trials) {
116*d9f75844SAndroid Build Coastguard Worker   if (nack.rtp_history_ms == 0)
117*d9f75844SAndroid Build Coastguard Worker     return nullptr;
118*d9f75844SAndroid Build Coastguard Worker 
119*d9f75844SAndroid Build Coastguard Worker   // TODO(bugs.webrtc.org/12420): pass rtp_history_ms to the nack module.
120*d9f75844SAndroid Build Coastguard Worker   return std::make_unique<NackRequester>(current_queue, nack_periodic_processor,
121*d9f75844SAndroid Build Coastguard Worker                                          clock, nack_sender,
122*d9f75844SAndroid Build Coastguard Worker                                          keyframe_request_sender, field_trials);
123*d9f75844SAndroid Build Coastguard Worker }
124*d9f75844SAndroid Build Coastguard Worker 
MaybeConstructUlpfecReceiver(uint32_t remote_ssrc,int red_payload_type,int ulpfec_payload_type,rtc::ArrayView<const RtpExtension> extensions,RecoveredPacketReceiver * callback,Clock * clock)125*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<UlpfecReceiver> MaybeConstructUlpfecReceiver(
126*d9f75844SAndroid Build Coastguard Worker     uint32_t remote_ssrc,
127*d9f75844SAndroid Build Coastguard Worker     int red_payload_type,
128*d9f75844SAndroid Build Coastguard Worker     int ulpfec_payload_type,
129*d9f75844SAndroid Build Coastguard Worker     rtc::ArrayView<const RtpExtension> extensions,
130*d9f75844SAndroid Build Coastguard Worker     RecoveredPacketReceiver* callback,
131*d9f75844SAndroid Build Coastguard Worker     Clock* clock) {
132*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_GE(red_payload_type, -1);
133*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_GE(ulpfec_payload_type, -1);
134*d9f75844SAndroid Build Coastguard Worker   if (red_payload_type == -1)
135*d9f75844SAndroid Build Coastguard Worker     return nullptr;
136*d9f75844SAndroid Build Coastguard Worker 
137*d9f75844SAndroid Build Coastguard Worker   // TODO(tommi, brandtr): Consider including this check too once
138*d9f75844SAndroid Build Coastguard Worker   // `UlpfecReceiver` has been updated to not consider both red and ulpfec
139*d9f75844SAndroid Build Coastguard Worker   // payload ids.
140*d9f75844SAndroid Build Coastguard Worker   //  if (ulpfec_payload_type == -1)
141*d9f75844SAndroid Build Coastguard Worker   //    return nullptr;
142*d9f75844SAndroid Build Coastguard Worker 
143*d9f75844SAndroid Build Coastguard Worker   return std::make_unique<UlpfecReceiver>(remote_ssrc, ulpfec_payload_type,
144*d9f75844SAndroid Build Coastguard Worker                                           callback, extensions, clock);
145*d9f75844SAndroid Build Coastguard Worker }
146*d9f75844SAndroid Build Coastguard Worker 
147*d9f75844SAndroid Build Coastguard Worker static const int kPacketLogIntervalMs = 10000;
148*d9f75844SAndroid Build Coastguard Worker 
149*d9f75844SAndroid Build Coastguard Worker }  // namespace
150*d9f75844SAndroid Build Coastguard Worker 
RtcpFeedbackBuffer(KeyFrameRequestSender * key_frame_request_sender,NackSender * nack_sender,LossNotificationSender * loss_notification_sender)151*d9f75844SAndroid Build Coastguard Worker RtpVideoStreamReceiver2::RtcpFeedbackBuffer::RtcpFeedbackBuffer(
152*d9f75844SAndroid Build Coastguard Worker     KeyFrameRequestSender* key_frame_request_sender,
153*d9f75844SAndroid Build Coastguard Worker     NackSender* nack_sender,
154*d9f75844SAndroid Build Coastguard Worker     LossNotificationSender* loss_notification_sender)
155*d9f75844SAndroid Build Coastguard Worker     : key_frame_request_sender_(key_frame_request_sender),
156*d9f75844SAndroid Build Coastguard Worker       nack_sender_(nack_sender),
157*d9f75844SAndroid Build Coastguard Worker       loss_notification_sender_(loss_notification_sender),
158*d9f75844SAndroid Build Coastguard Worker       request_key_frame_(false) {
159*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(key_frame_request_sender_);
160*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(nack_sender_);
161*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(loss_notification_sender_);
162*d9f75844SAndroid Build Coastguard Worker   packet_sequence_checker_.Detach();
163*d9f75844SAndroid Build Coastguard Worker }
164*d9f75844SAndroid Build Coastguard Worker 
RequestKeyFrame()165*d9f75844SAndroid Build Coastguard Worker void RtpVideoStreamReceiver2::RtcpFeedbackBuffer::RequestKeyFrame() {
166*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
167*d9f75844SAndroid Build Coastguard Worker   request_key_frame_ = true;
168*d9f75844SAndroid Build Coastguard Worker }
169*d9f75844SAndroid Build Coastguard Worker 
SendNack(const std::vector<uint16_t> & sequence_numbers,bool buffering_allowed)170*d9f75844SAndroid Build Coastguard Worker void RtpVideoStreamReceiver2::RtcpFeedbackBuffer::SendNack(
171*d9f75844SAndroid Build Coastguard Worker     const std::vector<uint16_t>& sequence_numbers,
172*d9f75844SAndroid Build Coastguard Worker     bool buffering_allowed) {
173*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
174*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(!sequence_numbers.empty());
175*d9f75844SAndroid Build Coastguard Worker   nack_sequence_numbers_.insert(nack_sequence_numbers_.end(),
176*d9f75844SAndroid Build Coastguard Worker                                 sequence_numbers.cbegin(),
177*d9f75844SAndroid Build Coastguard Worker                                 sequence_numbers.cend());
178*d9f75844SAndroid Build Coastguard Worker   if (!buffering_allowed) {
179*d9f75844SAndroid Build Coastguard Worker     // Note that while *buffering* is not allowed, *batching* is, meaning that
180*d9f75844SAndroid Build Coastguard Worker     // previously buffered messages may be sent along with the current message.
181*d9f75844SAndroid Build Coastguard Worker     SendBufferedRtcpFeedback();
182*d9f75844SAndroid Build Coastguard Worker   }
183*d9f75844SAndroid Build Coastguard Worker }
184*d9f75844SAndroid Build Coastguard Worker 
SendLossNotification(uint16_t last_decoded_seq_num,uint16_t last_received_seq_num,bool decodability_flag,bool buffering_allowed)185*d9f75844SAndroid Build Coastguard Worker void RtpVideoStreamReceiver2::RtcpFeedbackBuffer::SendLossNotification(
186*d9f75844SAndroid Build Coastguard Worker     uint16_t last_decoded_seq_num,
187*d9f75844SAndroid Build Coastguard Worker     uint16_t last_received_seq_num,
188*d9f75844SAndroid Build Coastguard Worker     bool decodability_flag,
189*d9f75844SAndroid Build Coastguard Worker     bool buffering_allowed) {
190*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
191*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(buffering_allowed);
192*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(!lntf_state_)
193*d9f75844SAndroid Build Coastguard Worker       << "SendLossNotification() called twice in a row with no call to "
194*d9f75844SAndroid Build Coastguard Worker          "SendBufferedRtcpFeedback() in between.";
195*d9f75844SAndroid Build Coastguard Worker   lntf_state_ = absl::make_optional<LossNotificationState>(
196*d9f75844SAndroid Build Coastguard Worker       last_decoded_seq_num, last_received_seq_num, decodability_flag);
197*d9f75844SAndroid Build Coastguard Worker }
198*d9f75844SAndroid Build Coastguard Worker 
SendBufferedRtcpFeedback()199*d9f75844SAndroid Build Coastguard Worker void RtpVideoStreamReceiver2::RtcpFeedbackBuffer::SendBufferedRtcpFeedback() {
200*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
201*d9f75844SAndroid Build Coastguard Worker 
202*d9f75844SAndroid Build Coastguard Worker   bool request_key_frame = false;
203*d9f75844SAndroid Build Coastguard Worker   std::vector<uint16_t> nack_sequence_numbers;
204*d9f75844SAndroid Build Coastguard Worker   absl::optional<LossNotificationState> lntf_state;
205*d9f75844SAndroid Build Coastguard Worker 
206*d9f75844SAndroid Build Coastguard Worker   std::swap(request_key_frame, request_key_frame_);
207*d9f75844SAndroid Build Coastguard Worker   std::swap(nack_sequence_numbers, nack_sequence_numbers_);
208*d9f75844SAndroid Build Coastguard Worker   std::swap(lntf_state, lntf_state_);
209*d9f75844SAndroid Build Coastguard Worker 
210*d9f75844SAndroid Build Coastguard Worker   if (lntf_state) {
211*d9f75844SAndroid Build Coastguard Worker     // If either a NACK or a key frame request is sent, we should buffer
212*d9f75844SAndroid Build Coastguard Worker     // the LNTF and wait for them (NACK or key frame request) to trigger
213*d9f75844SAndroid Build Coastguard Worker     // the compound feedback message.
214*d9f75844SAndroid Build Coastguard Worker     // Otherwise, the LNTF should be sent out immediately.
215*d9f75844SAndroid Build Coastguard Worker     const bool buffering_allowed =
216*d9f75844SAndroid Build Coastguard Worker         request_key_frame || !nack_sequence_numbers.empty();
217*d9f75844SAndroid Build Coastguard Worker 
218*d9f75844SAndroid Build Coastguard Worker     loss_notification_sender_->SendLossNotification(
219*d9f75844SAndroid Build Coastguard Worker         lntf_state->last_decoded_seq_num, lntf_state->last_received_seq_num,
220*d9f75844SAndroid Build Coastguard Worker         lntf_state->decodability_flag, buffering_allowed);
221*d9f75844SAndroid Build Coastguard Worker   }
222*d9f75844SAndroid Build Coastguard Worker 
223*d9f75844SAndroid Build Coastguard Worker   if (request_key_frame) {
224*d9f75844SAndroid Build Coastguard Worker     key_frame_request_sender_->RequestKeyFrame();
225*d9f75844SAndroid Build Coastguard Worker   } else if (!nack_sequence_numbers.empty()) {
226*d9f75844SAndroid Build Coastguard Worker     nack_sender_->SendNack(nack_sequence_numbers, true);
227*d9f75844SAndroid Build Coastguard Worker   }
228*d9f75844SAndroid Build Coastguard Worker }
229*d9f75844SAndroid Build Coastguard Worker 
ClearLossNotificationState()230*d9f75844SAndroid Build Coastguard Worker void RtpVideoStreamReceiver2::RtcpFeedbackBuffer::ClearLossNotificationState() {
231*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
232*d9f75844SAndroid Build Coastguard Worker   lntf_state_.reset();
233*d9f75844SAndroid Build Coastguard Worker }
234*d9f75844SAndroid Build Coastguard Worker 
RtpVideoStreamReceiver2(TaskQueueBase * current_queue,Clock * clock,Transport * transport,RtcpRttStats * rtt_stats,PacketRouter * packet_router,const VideoReceiveStreamInterface::Config * config,ReceiveStatistics * rtp_receive_statistics,RtcpPacketTypeCounterObserver * rtcp_packet_type_counter_observer,RtcpCnameCallback * rtcp_cname_callback,NackPeriodicProcessor * nack_periodic_processor,OnCompleteFrameCallback * complete_frame_callback,rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor,rtc::scoped_refptr<FrameTransformerInterface> frame_transformer,const FieldTrialsView & field_trials,RtcEventLog * event_log)235*d9f75844SAndroid Build Coastguard Worker RtpVideoStreamReceiver2::RtpVideoStreamReceiver2(
236*d9f75844SAndroid Build Coastguard Worker     TaskQueueBase* current_queue,
237*d9f75844SAndroid Build Coastguard Worker     Clock* clock,
238*d9f75844SAndroid Build Coastguard Worker     Transport* transport,
239*d9f75844SAndroid Build Coastguard Worker     RtcpRttStats* rtt_stats,
240*d9f75844SAndroid Build Coastguard Worker     PacketRouter* packet_router,
241*d9f75844SAndroid Build Coastguard Worker     const VideoReceiveStreamInterface::Config* config,
242*d9f75844SAndroid Build Coastguard Worker     ReceiveStatistics* rtp_receive_statistics,
243*d9f75844SAndroid Build Coastguard Worker     RtcpPacketTypeCounterObserver* rtcp_packet_type_counter_observer,
244*d9f75844SAndroid Build Coastguard Worker     RtcpCnameCallback* rtcp_cname_callback,
245*d9f75844SAndroid Build Coastguard Worker     NackPeriodicProcessor* nack_periodic_processor,
246*d9f75844SAndroid Build Coastguard Worker     OnCompleteFrameCallback* complete_frame_callback,
247*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor,
248*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<FrameTransformerInterface> frame_transformer,
249*d9f75844SAndroid Build Coastguard Worker     const FieldTrialsView& field_trials,
250*d9f75844SAndroid Build Coastguard Worker     RtcEventLog* event_log)
251*d9f75844SAndroid Build Coastguard Worker     : field_trials_(field_trials),
252*d9f75844SAndroid Build Coastguard Worker       worker_queue_(current_queue),
253*d9f75844SAndroid Build Coastguard Worker       clock_(clock),
254*d9f75844SAndroid Build Coastguard Worker       config_(*config),
255*d9f75844SAndroid Build Coastguard Worker       packet_router_(packet_router),
256*d9f75844SAndroid Build Coastguard Worker       ntp_estimator_(clock),
257*d9f75844SAndroid Build Coastguard Worker       rtp_header_extensions_(config_.rtp.extensions),
258*d9f75844SAndroid Build Coastguard Worker       forced_playout_delay_max_ms_("max_ms", absl::nullopt),
259*d9f75844SAndroid Build Coastguard Worker       forced_playout_delay_min_ms_("min_ms", absl::nullopt),
260*d9f75844SAndroid Build Coastguard Worker       rtp_receive_statistics_(rtp_receive_statistics),
261*d9f75844SAndroid Build Coastguard Worker       ulpfec_receiver_(
262*d9f75844SAndroid Build Coastguard Worker           MaybeConstructUlpfecReceiver(config->rtp.remote_ssrc,
263*d9f75844SAndroid Build Coastguard Worker                                        config->rtp.red_payload_type,
264*d9f75844SAndroid Build Coastguard Worker                                        config->rtp.ulpfec_payload_type,
265*d9f75844SAndroid Build Coastguard Worker                                        config->rtp.extensions,
266*d9f75844SAndroid Build Coastguard Worker                                        this,
267*d9f75844SAndroid Build Coastguard Worker                                        clock_)),
268*d9f75844SAndroid Build Coastguard Worker       red_payload_type_(config_.rtp.red_payload_type),
269*d9f75844SAndroid Build Coastguard Worker       packet_sink_(config->rtp.packet_sink_),
270*d9f75844SAndroid Build Coastguard Worker       receiving_(false),
271*d9f75844SAndroid Build Coastguard Worker       last_packet_log_ms_(-1),
272*d9f75844SAndroid Build Coastguard Worker       rtp_rtcp_(CreateRtpRtcpModule(
273*d9f75844SAndroid Build Coastguard Worker           clock,
274*d9f75844SAndroid Build Coastguard Worker           rtp_receive_statistics_,
275*d9f75844SAndroid Build Coastguard Worker           transport,
276*d9f75844SAndroid Build Coastguard Worker           rtt_stats,
277*d9f75844SAndroid Build Coastguard Worker           rtcp_packet_type_counter_observer,
278*d9f75844SAndroid Build Coastguard Worker           rtcp_cname_callback,
279*d9f75844SAndroid Build Coastguard Worker           config_.rtp.rtcp_xr.receiver_reference_time_report,
280*d9f75844SAndroid Build Coastguard Worker           config_.rtp.local_ssrc,
281*d9f75844SAndroid Build Coastguard Worker           event_log)),
282*d9f75844SAndroid Build Coastguard Worker       nack_periodic_processor_(nack_periodic_processor),
283*d9f75844SAndroid Build Coastguard Worker       complete_frame_callback_(complete_frame_callback),
284*d9f75844SAndroid Build Coastguard Worker       keyframe_request_method_(config_.rtp.keyframe_method),
285*d9f75844SAndroid Build Coastguard Worker       // TODO(bugs.webrtc.org/10336): Let `rtcp_feedback_buffer_` communicate
286*d9f75844SAndroid Build Coastguard Worker       // directly with `rtp_rtcp_`.
287*d9f75844SAndroid Build Coastguard Worker       rtcp_feedback_buffer_(this, this, this),
288*d9f75844SAndroid Build Coastguard Worker       nack_module_(MaybeConstructNackModule(current_queue,
289*d9f75844SAndroid Build Coastguard Worker                                             nack_periodic_processor,
290*d9f75844SAndroid Build Coastguard Worker                                             config_.rtp.nack,
291*d9f75844SAndroid Build Coastguard Worker                                             clock_,
292*d9f75844SAndroid Build Coastguard Worker                                             &rtcp_feedback_buffer_,
293*d9f75844SAndroid Build Coastguard Worker                                             &rtcp_feedback_buffer_,
294*d9f75844SAndroid Build Coastguard Worker                                             field_trials_)),
295*d9f75844SAndroid Build Coastguard Worker       packet_buffer_(kPacketBufferStartSize,
296*d9f75844SAndroid Build Coastguard Worker                      PacketBufferMaxSize(field_trials_)),
297*d9f75844SAndroid Build Coastguard Worker       reference_finder_(std::make_unique<RtpFrameReferenceFinder>()),
298*d9f75844SAndroid Build Coastguard Worker       has_received_frame_(false),
299*d9f75844SAndroid Build Coastguard Worker       frames_decryptable_(false),
300*d9f75844SAndroid Build Coastguard Worker       absolute_capture_time_interpolator_(clock) {
301*d9f75844SAndroid Build Coastguard Worker   packet_sequence_checker_.Detach();
302*d9f75844SAndroid Build Coastguard Worker   constexpr bool remb_candidate = true;
303*d9f75844SAndroid Build Coastguard Worker   if (packet_router_)
304*d9f75844SAndroid Build Coastguard Worker     packet_router_->AddReceiveRtpModule(rtp_rtcp_.get(), remb_candidate);
305*d9f75844SAndroid Build Coastguard Worker 
306*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(config_.rtp.rtcp_mode != RtcpMode::kOff)
307*d9f75844SAndroid Build Coastguard Worker       << "A stream should not be configured with RTCP disabled. This value is "
308*d9f75844SAndroid Build Coastguard Worker          "reserved for internal usage.";
309*d9f75844SAndroid Build Coastguard Worker   // TODO(pbos): What's an appropriate local_ssrc for receive-only streams?
310*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(config_.rtp.local_ssrc != 0);
311*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(config_.rtp.remote_ssrc != config_.rtp.local_ssrc);
312*d9f75844SAndroid Build Coastguard Worker 
313*d9f75844SAndroid Build Coastguard Worker   rtp_rtcp_->SetRTCPStatus(config_.rtp.rtcp_mode);
314*d9f75844SAndroid Build Coastguard Worker   rtp_rtcp_->SetRemoteSSRC(config_.rtp.remote_ssrc);
315*d9f75844SAndroid Build Coastguard Worker 
316*d9f75844SAndroid Build Coastguard Worker   if (config_.rtp.nack.rtp_history_ms > 0) {
317*d9f75844SAndroid Build Coastguard Worker     rtp_receive_statistics_->SetMaxReorderingThreshold(config_.rtp.remote_ssrc,
318*d9f75844SAndroid Build Coastguard Worker                                                        kMaxPacketAgeToNack);
319*d9f75844SAndroid Build Coastguard Worker   }
320*d9f75844SAndroid Build Coastguard Worker   ParseFieldTrial(
321*d9f75844SAndroid Build Coastguard Worker       {&forced_playout_delay_max_ms_, &forced_playout_delay_min_ms_},
322*d9f75844SAndroid Build Coastguard Worker       field_trials_.Lookup("WebRTC-ForcePlayoutDelay"));
323*d9f75844SAndroid Build Coastguard Worker 
324*d9f75844SAndroid Build Coastguard Worker   if (config_.rtp.lntf.enabled) {
325*d9f75844SAndroid Build Coastguard Worker     loss_notification_controller_ =
326*d9f75844SAndroid Build Coastguard Worker         std::make_unique<LossNotificationController>(&rtcp_feedback_buffer_,
327*d9f75844SAndroid Build Coastguard Worker                                                      &rtcp_feedback_buffer_);
328*d9f75844SAndroid Build Coastguard Worker   }
329*d9f75844SAndroid Build Coastguard Worker 
330*d9f75844SAndroid Build Coastguard Worker   // Only construct the encrypted receiver if frame encryption is enabled.
331*d9f75844SAndroid Build Coastguard Worker   if (config_.crypto_options.sframe.require_frame_encryption) {
332*d9f75844SAndroid Build Coastguard Worker     buffered_frame_decryptor_ =
333*d9f75844SAndroid Build Coastguard Worker         std::make_unique<BufferedFrameDecryptor>(this, this, field_trials_);
334*d9f75844SAndroid Build Coastguard Worker     if (frame_decryptor != nullptr) {
335*d9f75844SAndroid Build Coastguard Worker       buffered_frame_decryptor_->SetFrameDecryptor(std::move(frame_decryptor));
336*d9f75844SAndroid Build Coastguard Worker     }
337*d9f75844SAndroid Build Coastguard Worker   }
338*d9f75844SAndroid Build Coastguard Worker 
339*d9f75844SAndroid Build Coastguard Worker   if (frame_transformer) {
340*d9f75844SAndroid Build Coastguard Worker     frame_transformer_delegate_ =
341*d9f75844SAndroid Build Coastguard Worker         rtc::make_ref_counted<RtpVideoStreamReceiverFrameTransformerDelegate>(
342*d9f75844SAndroid Build Coastguard Worker             this, std::move(frame_transformer), rtc::Thread::Current(),
343*d9f75844SAndroid Build Coastguard Worker             config_.rtp.remote_ssrc);
344*d9f75844SAndroid Build Coastguard Worker     frame_transformer_delegate_->Init();
345*d9f75844SAndroid Build Coastguard Worker   }
346*d9f75844SAndroid Build Coastguard Worker }
347*d9f75844SAndroid Build Coastguard Worker 
~RtpVideoStreamReceiver2()348*d9f75844SAndroid Build Coastguard Worker RtpVideoStreamReceiver2::~RtpVideoStreamReceiver2() {
349*d9f75844SAndroid Build Coastguard Worker   if (packet_router_)
350*d9f75844SAndroid Build Coastguard Worker     packet_router_->RemoveReceiveRtpModule(rtp_rtcp_.get());
351*d9f75844SAndroid Build Coastguard Worker   ulpfec_receiver_.reset();
352*d9f75844SAndroid Build Coastguard Worker   if (frame_transformer_delegate_)
353*d9f75844SAndroid Build Coastguard Worker     frame_transformer_delegate_->Reset();
354*d9f75844SAndroid Build Coastguard Worker }
355*d9f75844SAndroid Build Coastguard Worker 
AddReceiveCodec(uint8_t payload_type,VideoCodecType video_codec,const std::map<std::string,std::string> & codec_params,bool raw_payload)356*d9f75844SAndroid Build Coastguard Worker void RtpVideoStreamReceiver2::AddReceiveCodec(
357*d9f75844SAndroid Build Coastguard Worker     uint8_t payload_type,
358*d9f75844SAndroid Build Coastguard Worker     VideoCodecType video_codec,
359*d9f75844SAndroid Build Coastguard Worker     const std::map<std::string, std::string>& codec_params,
360*d9f75844SAndroid Build Coastguard Worker     bool raw_payload) {
361*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
362*d9f75844SAndroid Build Coastguard Worker   if (codec_params.count(cricket::kH264FmtpSpsPpsIdrInKeyframe) > 0 ||
363*d9f75844SAndroid Build Coastguard Worker       field_trials_.IsEnabled("WebRTC-SpsPpsIdrIsH264Keyframe")) {
364*d9f75844SAndroid Build Coastguard Worker     packet_buffer_.ForceSpsPpsIdrIsH264Keyframe();
365*d9f75844SAndroid Build Coastguard Worker   }
366*d9f75844SAndroid Build Coastguard Worker   payload_type_map_.emplace(
367*d9f75844SAndroid Build Coastguard Worker       payload_type, raw_payload ? std::make_unique<VideoRtpDepacketizerRaw>()
368*d9f75844SAndroid Build Coastguard Worker                                 : CreateVideoRtpDepacketizer(video_codec));
369*d9f75844SAndroid Build Coastguard Worker   pt_codec_params_.emplace(payload_type, codec_params);
370*d9f75844SAndroid Build Coastguard Worker }
371*d9f75844SAndroid Build Coastguard Worker 
RemoveReceiveCodec(uint8_t payload_type)372*d9f75844SAndroid Build Coastguard Worker void RtpVideoStreamReceiver2::RemoveReceiveCodec(uint8_t payload_type) {
373*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
374*d9f75844SAndroid Build Coastguard Worker   auto codec_params_it = pt_codec_params_.find(payload_type);
375*d9f75844SAndroid Build Coastguard Worker   if (codec_params_it == pt_codec_params_.end())
376*d9f75844SAndroid Build Coastguard Worker     return;
377*d9f75844SAndroid Build Coastguard Worker 
378*d9f75844SAndroid Build Coastguard Worker   const bool sps_pps_idr_in_key_frame =
379*d9f75844SAndroid Build Coastguard Worker       codec_params_it->second.count(cricket::kH264FmtpSpsPpsIdrInKeyframe) > 0;
380*d9f75844SAndroid Build Coastguard Worker 
381*d9f75844SAndroid Build Coastguard Worker   pt_codec_params_.erase(codec_params_it);
382*d9f75844SAndroid Build Coastguard Worker   payload_type_map_.erase(payload_type);
383*d9f75844SAndroid Build Coastguard Worker 
384*d9f75844SAndroid Build Coastguard Worker   if (sps_pps_idr_in_key_frame) {
385*d9f75844SAndroid Build Coastguard Worker     bool reset_setting = true;
386*d9f75844SAndroid Build Coastguard Worker     for (auto& [unused, codec_params] : pt_codec_params_) {
387*d9f75844SAndroid Build Coastguard Worker       if (codec_params.count(cricket::kH264FmtpSpsPpsIdrInKeyframe) > 0) {
388*d9f75844SAndroid Build Coastguard Worker         reset_setting = false;
389*d9f75844SAndroid Build Coastguard Worker         break;
390*d9f75844SAndroid Build Coastguard Worker       }
391*d9f75844SAndroid Build Coastguard Worker     }
392*d9f75844SAndroid Build Coastguard Worker 
393*d9f75844SAndroid Build Coastguard Worker     if (reset_setting) {
394*d9f75844SAndroid Build Coastguard Worker       packet_buffer_.ResetSpsPpsIdrIsH264Keyframe();
395*d9f75844SAndroid Build Coastguard Worker     }
396*d9f75844SAndroid Build Coastguard Worker   }
397*d9f75844SAndroid Build Coastguard Worker }
398*d9f75844SAndroid Build Coastguard Worker 
RemoveReceiveCodecs()399*d9f75844SAndroid Build Coastguard Worker void RtpVideoStreamReceiver2::RemoveReceiveCodecs() {
400*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
401*d9f75844SAndroid Build Coastguard Worker 
402*d9f75844SAndroid Build Coastguard Worker   pt_codec_params_.clear();
403*d9f75844SAndroid Build Coastguard Worker   payload_type_map_.clear();
404*d9f75844SAndroid Build Coastguard Worker   packet_buffer_.ResetSpsPpsIdrIsH264Keyframe();
405*d9f75844SAndroid Build Coastguard Worker }
406*d9f75844SAndroid Build Coastguard Worker 
GetSyncInfo() const407*d9f75844SAndroid Build Coastguard Worker absl::optional<Syncable::Info> RtpVideoStreamReceiver2::GetSyncInfo() const {
408*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
409*d9f75844SAndroid Build Coastguard Worker   Syncable::Info info;
410*d9f75844SAndroid Build Coastguard Worker   if (rtp_rtcp_->RemoteNTP(&info.capture_time_ntp_secs,
411*d9f75844SAndroid Build Coastguard Worker                            &info.capture_time_ntp_frac,
412*d9f75844SAndroid Build Coastguard Worker                            /*rtcp_arrival_time_secs=*/nullptr,
413*d9f75844SAndroid Build Coastguard Worker                            /*rtcp_arrival_time_frac=*/nullptr,
414*d9f75844SAndroid Build Coastguard Worker                            &info.capture_time_source_clock) != 0) {
415*d9f75844SAndroid Build Coastguard Worker     return absl::nullopt;
416*d9f75844SAndroid Build Coastguard Worker   }
417*d9f75844SAndroid Build Coastguard Worker 
418*d9f75844SAndroid Build Coastguard Worker   if (!last_received_rtp_timestamp_ || !last_received_rtp_system_time_) {
419*d9f75844SAndroid Build Coastguard Worker     return absl::nullopt;
420*d9f75844SAndroid Build Coastguard Worker   }
421*d9f75844SAndroid Build Coastguard Worker   info.latest_received_capture_timestamp = *last_received_rtp_timestamp_;
422*d9f75844SAndroid Build Coastguard Worker   info.latest_receive_time_ms = last_received_rtp_system_time_->ms();
423*d9f75844SAndroid Build Coastguard Worker 
424*d9f75844SAndroid Build Coastguard Worker   // Leaves info.current_delay_ms uninitialized.
425*d9f75844SAndroid Build Coastguard Worker   return info;
426*d9f75844SAndroid Build Coastguard Worker }
427*d9f75844SAndroid Build Coastguard Worker 
428*d9f75844SAndroid Build Coastguard Worker RtpVideoStreamReceiver2::ParseGenericDependenciesResult
ParseGenericDependenciesExtension(const RtpPacketReceived & rtp_packet,RTPVideoHeader * video_header)429*d9f75844SAndroid Build Coastguard Worker RtpVideoStreamReceiver2::ParseGenericDependenciesExtension(
430*d9f75844SAndroid Build Coastguard Worker     const RtpPacketReceived& rtp_packet,
431*d9f75844SAndroid Build Coastguard Worker     RTPVideoHeader* video_header) {
432*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
433*d9f75844SAndroid Build Coastguard Worker   if (rtp_packet.HasExtension<RtpDependencyDescriptorExtension>()) {
434*d9f75844SAndroid Build Coastguard Worker     webrtc::DependencyDescriptor dependency_descriptor;
435*d9f75844SAndroid Build Coastguard Worker     if (!rtp_packet.GetExtension<RtpDependencyDescriptorExtension>(
436*d9f75844SAndroid Build Coastguard Worker             video_structure_.get(), &dependency_descriptor)) {
437*d9f75844SAndroid Build Coastguard Worker       // Descriptor is there, but failed to parse. Either it is invalid,
438*d9f75844SAndroid Build Coastguard Worker       // or too old packet (after relevant video_structure_ changed),
439*d9f75844SAndroid Build Coastguard Worker       // or too new packet (before relevant video_structure_ arrived).
440*d9f75844SAndroid Build Coastguard Worker       // Drop such packet to be on the safe side.
441*d9f75844SAndroid Build Coastguard Worker       // TODO(bugs.webrtc.org/10342): Stash too new packet.
442*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_WARNING) << "ssrc: " << rtp_packet.Ssrc()
443*d9f75844SAndroid Build Coastguard Worker                           << " Failed to parse dependency descriptor.";
444*d9f75844SAndroid Build Coastguard Worker       return kDropPacket;
445*d9f75844SAndroid Build Coastguard Worker     }
446*d9f75844SAndroid Build Coastguard Worker     if (dependency_descriptor.attached_structure != nullptr &&
447*d9f75844SAndroid Build Coastguard Worker         !dependency_descriptor.first_packet_in_frame) {
448*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_WARNING) << "ssrc: " << rtp_packet.Ssrc()
449*d9f75844SAndroid Build Coastguard Worker                           << "Invalid dependency descriptor: structure "
450*d9f75844SAndroid Build Coastguard Worker                              "attached to non first packet of a frame.";
451*d9f75844SAndroid Build Coastguard Worker       return kDropPacket;
452*d9f75844SAndroid Build Coastguard Worker     }
453*d9f75844SAndroid Build Coastguard Worker     video_header->is_first_packet_in_frame =
454*d9f75844SAndroid Build Coastguard Worker         dependency_descriptor.first_packet_in_frame;
455*d9f75844SAndroid Build Coastguard Worker     video_header->is_last_packet_in_frame =
456*d9f75844SAndroid Build Coastguard Worker         dependency_descriptor.last_packet_in_frame;
457*d9f75844SAndroid Build Coastguard Worker 
458*d9f75844SAndroid Build Coastguard Worker     int64_t frame_id =
459*d9f75844SAndroid Build Coastguard Worker         frame_id_unwrapper_.Unwrap(dependency_descriptor.frame_number);
460*d9f75844SAndroid Build Coastguard Worker     auto& generic_descriptor_info = video_header->generic.emplace();
461*d9f75844SAndroid Build Coastguard Worker     generic_descriptor_info.frame_id = frame_id;
462*d9f75844SAndroid Build Coastguard Worker     generic_descriptor_info.spatial_index =
463*d9f75844SAndroid Build Coastguard Worker         dependency_descriptor.frame_dependencies.spatial_id;
464*d9f75844SAndroid Build Coastguard Worker     generic_descriptor_info.temporal_index =
465*d9f75844SAndroid Build Coastguard Worker         dependency_descriptor.frame_dependencies.temporal_id;
466*d9f75844SAndroid Build Coastguard Worker     for (int fdiff : dependency_descriptor.frame_dependencies.frame_diffs) {
467*d9f75844SAndroid Build Coastguard Worker       generic_descriptor_info.dependencies.push_back(frame_id - fdiff);
468*d9f75844SAndroid Build Coastguard Worker     }
469*d9f75844SAndroid Build Coastguard Worker     generic_descriptor_info.decode_target_indications =
470*d9f75844SAndroid Build Coastguard Worker         dependency_descriptor.frame_dependencies.decode_target_indications;
471*d9f75844SAndroid Build Coastguard Worker     if (dependency_descriptor.resolution) {
472*d9f75844SAndroid Build Coastguard Worker       video_header->width = dependency_descriptor.resolution->Width();
473*d9f75844SAndroid Build Coastguard Worker       video_header->height = dependency_descriptor.resolution->Height();
474*d9f75844SAndroid Build Coastguard Worker     }
475*d9f75844SAndroid Build Coastguard Worker 
476*d9f75844SAndroid Build Coastguard Worker     // FrameDependencyStructure is sent in dependency descriptor of the first
477*d9f75844SAndroid Build Coastguard Worker     // packet of a key frame and required for parsed dependency descriptor in
478*d9f75844SAndroid Build Coastguard Worker     // all the following packets until next key frame.
479*d9f75844SAndroid Build Coastguard Worker     // Save it if there is a (potentially) new structure.
480*d9f75844SAndroid Build Coastguard Worker     if (dependency_descriptor.attached_structure) {
481*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK(dependency_descriptor.first_packet_in_frame);
482*d9f75844SAndroid Build Coastguard Worker       if (video_structure_frame_id_ > frame_id) {
483*d9f75844SAndroid Build Coastguard Worker         RTC_LOG(LS_WARNING)
484*d9f75844SAndroid Build Coastguard Worker             << "Arrived key frame with id " << frame_id << " and structure id "
485*d9f75844SAndroid Build Coastguard Worker             << dependency_descriptor.attached_structure->structure_id
486*d9f75844SAndroid Build Coastguard Worker             << " is older than the latest received key frame with id "
487*d9f75844SAndroid Build Coastguard Worker             << *video_structure_frame_id_ << " and structure id "
488*d9f75844SAndroid Build Coastguard Worker             << video_structure_->structure_id;
489*d9f75844SAndroid Build Coastguard Worker         return kDropPacket;
490*d9f75844SAndroid Build Coastguard Worker       }
491*d9f75844SAndroid Build Coastguard Worker       video_structure_ = std::move(dependency_descriptor.attached_structure);
492*d9f75844SAndroid Build Coastguard Worker       video_structure_frame_id_ = frame_id;
493*d9f75844SAndroid Build Coastguard Worker       video_header->frame_type = VideoFrameType::kVideoFrameKey;
494*d9f75844SAndroid Build Coastguard Worker     } else {
495*d9f75844SAndroid Build Coastguard Worker       video_header->frame_type = VideoFrameType::kVideoFrameDelta;
496*d9f75844SAndroid Build Coastguard Worker     }
497*d9f75844SAndroid Build Coastguard Worker     return kHasGenericDescriptor;
498*d9f75844SAndroid Build Coastguard Worker   }
499*d9f75844SAndroid Build Coastguard Worker 
500*d9f75844SAndroid Build Coastguard Worker   RtpGenericFrameDescriptor generic_frame_descriptor;
501*d9f75844SAndroid Build Coastguard Worker   if (!rtp_packet.GetExtension<RtpGenericFrameDescriptorExtension00>(
502*d9f75844SAndroid Build Coastguard Worker           &generic_frame_descriptor)) {
503*d9f75844SAndroid Build Coastguard Worker     return kNoGenericDescriptor;
504*d9f75844SAndroid Build Coastguard Worker   }
505*d9f75844SAndroid Build Coastguard Worker 
506*d9f75844SAndroid Build Coastguard Worker   video_header->is_first_packet_in_frame =
507*d9f75844SAndroid Build Coastguard Worker       generic_frame_descriptor.FirstPacketInSubFrame();
508*d9f75844SAndroid Build Coastguard Worker   video_header->is_last_packet_in_frame =
509*d9f75844SAndroid Build Coastguard Worker       generic_frame_descriptor.LastPacketInSubFrame();
510*d9f75844SAndroid Build Coastguard Worker 
511*d9f75844SAndroid Build Coastguard Worker   if (generic_frame_descriptor.FirstPacketInSubFrame()) {
512*d9f75844SAndroid Build Coastguard Worker     video_header->frame_type =
513*d9f75844SAndroid Build Coastguard Worker         generic_frame_descriptor.FrameDependenciesDiffs().empty()
514*d9f75844SAndroid Build Coastguard Worker             ? VideoFrameType::kVideoFrameKey
515*d9f75844SAndroid Build Coastguard Worker             : VideoFrameType::kVideoFrameDelta;
516*d9f75844SAndroid Build Coastguard Worker 
517*d9f75844SAndroid Build Coastguard Worker     auto& generic_descriptor_info = video_header->generic.emplace();
518*d9f75844SAndroid Build Coastguard Worker     int64_t frame_id =
519*d9f75844SAndroid Build Coastguard Worker         frame_id_unwrapper_.Unwrap(generic_frame_descriptor.FrameId());
520*d9f75844SAndroid Build Coastguard Worker     generic_descriptor_info.frame_id = frame_id;
521*d9f75844SAndroid Build Coastguard Worker     generic_descriptor_info.spatial_index =
522*d9f75844SAndroid Build Coastguard Worker         generic_frame_descriptor.SpatialLayer();
523*d9f75844SAndroid Build Coastguard Worker     generic_descriptor_info.temporal_index =
524*d9f75844SAndroid Build Coastguard Worker         generic_frame_descriptor.TemporalLayer();
525*d9f75844SAndroid Build Coastguard Worker     for (uint16_t fdiff : generic_frame_descriptor.FrameDependenciesDiffs()) {
526*d9f75844SAndroid Build Coastguard Worker       generic_descriptor_info.dependencies.push_back(frame_id - fdiff);
527*d9f75844SAndroid Build Coastguard Worker     }
528*d9f75844SAndroid Build Coastguard Worker   }
529*d9f75844SAndroid Build Coastguard Worker   video_header->width = generic_frame_descriptor.Width();
530*d9f75844SAndroid Build Coastguard Worker   video_header->height = generic_frame_descriptor.Height();
531*d9f75844SAndroid Build Coastguard Worker   return kHasGenericDescriptor;
532*d9f75844SAndroid Build Coastguard Worker }
533*d9f75844SAndroid Build Coastguard Worker 
OnReceivedPayloadData(rtc::CopyOnWriteBuffer codec_payload,const RtpPacketReceived & rtp_packet,const RTPVideoHeader & video)534*d9f75844SAndroid Build Coastguard Worker void RtpVideoStreamReceiver2::OnReceivedPayloadData(
535*d9f75844SAndroid Build Coastguard Worker     rtc::CopyOnWriteBuffer codec_payload,
536*d9f75844SAndroid Build Coastguard Worker     const RtpPacketReceived& rtp_packet,
537*d9f75844SAndroid Build Coastguard Worker     const RTPVideoHeader& video) {
538*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
539*d9f75844SAndroid Build Coastguard Worker 
540*d9f75844SAndroid Build Coastguard Worker   auto packet =
541*d9f75844SAndroid Build Coastguard Worker       std::make_unique<video_coding::PacketBuffer::Packet>(rtp_packet, video);
542*d9f75844SAndroid Build Coastguard Worker 
543*d9f75844SAndroid Build Coastguard Worker   int64_t unwrapped_rtp_seq_num =
544*d9f75844SAndroid Build Coastguard Worker       rtp_seq_num_unwrapper_.Unwrap(rtp_packet.SequenceNumber());
545*d9f75844SAndroid Build Coastguard Worker 
546*d9f75844SAndroid Build Coastguard Worker   RtpPacketInfo& packet_info =
547*d9f75844SAndroid Build Coastguard Worker       packet_infos_
548*d9f75844SAndroid Build Coastguard Worker           .emplace(unwrapped_rtp_seq_num,
549*d9f75844SAndroid Build Coastguard Worker                    RtpPacketInfo(rtp_packet.Ssrc(), rtp_packet.Csrcs(),
550*d9f75844SAndroid Build Coastguard Worker                                  rtp_packet.Timestamp(),
551*d9f75844SAndroid Build Coastguard Worker                                  /*receive_time_ms=*/clock_->CurrentTime()))
552*d9f75844SAndroid Build Coastguard Worker           .first->second;
553*d9f75844SAndroid Build Coastguard Worker 
554*d9f75844SAndroid Build Coastguard Worker   // Try to extrapolate absolute capture time if it is missing.
555*d9f75844SAndroid Build Coastguard Worker   packet_info.set_absolute_capture_time(
556*d9f75844SAndroid Build Coastguard Worker       absolute_capture_time_interpolator_.OnReceivePacket(
557*d9f75844SAndroid Build Coastguard Worker           AbsoluteCaptureTimeInterpolator::GetSource(packet_info.ssrc(),
558*d9f75844SAndroid Build Coastguard Worker                                                      packet_info.csrcs()),
559*d9f75844SAndroid Build Coastguard Worker           packet_info.rtp_timestamp(),
560*d9f75844SAndroid Build Coastguard Worker           // Assume frequency is the same one for all video frames.
561*d9f75844SAndroid Build Coastguard Worker           kVideoPayloadTypeFrequency,
562*d9f75844SAndroid Build Coastguard Worker           rtp_packet.GetExtension<AbsoluteCaptureTimeExtension>()));
563*d9f75844SAndroid Build Coastguard Worker 
564*d9f75844SAndroid Build Coastguard Worker   RTPVideoHeader& video_header = packet->video_header;
565*d9f75844SAndroid Build Coastguard Worker   video_header.rotation = kVideoRotation_0;
566*d9f75844SAndroid Build Coastguard Worker   video_header.content_type = VideoContentType::UNSPECIFIED;
567*d9f75844SAndroid Build Coastguard Worker   video_header.video_timing.flags = VideoSendTiming::kInvalid;
568*d9f75844SAndroid Build Coastguard Worker   video_header.is_last_packet_in_frame |= rtp_packet.Marker();
569*d9f75844SAndroid Build Coastguard Worker 
570*d9f75844SAndroid Build Coastguard Worker   rtp_packet.GetExtension<VideoOrientation>(&video_header.rotation);
571*d9f75844SAndroid Build Coastguard Worker   rtp_packet.GetExtension<VideoContentTypeExtension>(
572*d9f75844SAndroid Build Coastguard Worker       &video_header.content_type);
573*d9f75844SAndroid Build Coastguard Worker   rtp_packet.GetExtension<VideoTimingExtension>(&video_header.video_timing);
574*d9f75844SAndroid Build Coastguard Worker   if (forced_playout_delay_max_ms_ && forced_playout_delay_min_ms_) {
575*d9f75844SAndroid Build Coastguard Worker     video_header.playout_delay.max_ms = *forced_playout_delay_max_ms_;
576*d9f75844SAndroid Build Coastguard Worker     video_header.playout_delay.min_ms = *forced_playout_delay_min_ms_;
577*d9f75844SAndroid Build Coastguard Worker   } else {
578*d9f75844SAndroid Build Coastguard Worker     rtp_packet.GetExtension<PlayoutDelayLimits>(&video_header.playout_delay);
579*d9f75844SAndroid Build Coastguard Worker   }
580*d9f75844SAndroid Build Coastguard Worker 
581*d9f75844SAndroid Build Coastguard Worker   ParseGenericDependenciesResult generic_descriptor_state =
582*d9f75844SAndroid Build Coastguard Worker       ParseGenericDependenciesExtension(rtp_packet, &video_header);
583*d9f75844SAndroid Build Coastguard Worker 
584*d9f75844SAndroid Build Coastguard Worker   if (!rtp_packet.recovered()) {
585*d9f75844SAndroid Build Coastguard Worker     UpdatePacketReceiveTimestamps(
586*d9f75844SAndroid Build Coastguard Worker         rtp_packet, video_header.frame_type == VideoFrameType::kVideoFrameKey);
587*d9f75844SAndroid Build Coastguard Worker   }
588*d9f75844SAndroid Build Coastguard Worker 
589*d9f75844SAndroid Build Coastguard Worker   if (generic_descriptor_state == kDropPacket) {
590*d9f75844SAndroid Build Coastguard Worker     Timestamp now = clock_->CurrentTime();
591*d9f75844SAndroid Build Coastguard Worker     if (video_structure_ == nullptr &&
592*d9f75844SAndroid Build Coastguard Worker         next_keyframe_request_for_missing_video_structure_ < now) {
593*d9f75844SAndroid Build Coastguard Worker       // No video structure received yet, most likely part of the initial
594*d9f75844SAndroid Build Coastguard Worker       // keyframe was lost.
595*d9f75844SAndroid Build Coastguard Worker       RequestKeyFrame();
596*d9f75844SAndroid Build Coastguard Worker       next_keyframe_request_for_missing_video_structure_ =
597*d9f75844SAndroid Build Coastguard Worker           now + TimeDelta::Seconds(1);
598*d9f75844SAndroid Build Coastguard Worker     }
599*d9f75844SAndroid Build Coastguard Worker     return;
600*d9f75844SAndroid Build Coastguard Worker   }
601*d9f75844SAndroid Build Coastguard Worker 
602*d9f75844SAndroid Build Coastguard Worker   // Color space should only be transmitted in the last packet of a frame,
603*d9f75844SAndroid Build Coastguard Worker   // therefore, neglect it otherwise so that last_color_space_ is not reset by
604*d9f75844SAndroid Build Coastguard Worker   // mistake.
605*d9f75844SAndroid Build Coastguard Worker   if (video_header.is_last_packet_in_frame) {
606*d9f75844SAndroid Build Coastguard Worker     video_header.color_space = rtp_packet.GetExtension<ColorSpaceExtension>();
607*d9f75844SAndroid Build Coastguard Worker     if (video_header.color_space ||
608*d9f75844SAndroid Build Coastguard Worker         video_header.frame_type == VideoFrameType::kVideoFrameKey) {
609*d9f75844SAndroid Build Coastguard Worker       // Store color space since it's only transmitted when changed or for key
610*d9f75844SAndroid Build Coastguard Worker       // frames. Color space will be cleared if a key frame is transmitted
611*d9f75844SAndroid Build Coastguard Worker       // without color space information.
612*d9f75844SAndroid Build Coastguard Worker       last_color_space_ = video_header.color_space;
613*d9f75844SAndroid Build Coastguard Worker     } else if (last_color_space_) {
614*d9f75844SAndroid Build Coastguard Worker       video_header.color_space = last_color_space_;
615*d9f75844SAndroid Build Coastguard Worker     }
616*d9f75844SAndroid Build Coastguard Worker   }
617*d9f75844SAndroid Build Coastguard Worker   video_header.video_frame_tracking_id =
618*d9f75844SAndroid Build Coastguard Worker       rtp_packet.GetExtension<VideoFrameTrackingIdExtension>();
619*d9f75844SAndroid Build Coastguard Worker 
620*d9f75844SAndroid Build Coastguard Worker   if (loss_notification_controller_) {
621*d9f75844SAndroid Build Coastguard Worker     if (rtp_packet.recovered()) {
622*d9f75844SAndroid Build Coastguard Worker       // TODO(bugs.webrtc.org/10336): Implement support for reordering.
623*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_INFO)
624*d9f75844SAndroid Build Coastguard Worker           << "LossNotificationController does not support reordering.";
625*d9f75844SAndroid Build Coastguard Worker     } else if (generic_descriptor_state == kNoGenericDescriptor) {
626*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_WARNING) << "LossNotificationController requires generic "
627*d9f75844SAndroid Build Coastguard Worker                              "frame descriptor, but it is missing.";
628*d9f75844SAndroid Build Coastguard Worker     } else {
629*d9f75844SAndroid Build Coastguard Worker       if (video_header.is_first_packet_in_frame) {
630*d9f75844SAndroid Build Coastguard Worker         RTC_DCHECK(video_header.generic);
631*d9f75844SAndroid Build Coastguard Worker         LossNotificationController::FrameDetails frame;
632*d9f75844SAndroid Build Coastguard Worker         frame.is_keyframe =
633*d9f75844SAndroid Build Coastguard Worker             video_header.frame_type == VideoFrameType::kVideoFrameKey;
634*d9f75844SAndroid Build Coastguard Worker         frame.frame_id = video_header.generic->frame_id;
635*d9f75844SAndroid Build Coastguard Worker         frame.frame_dependencies = video_header.generic->dependencies;
636*d9f75844SAndroid Build Coastguard Worker         loss_notification_controller_->OnReceivedPacket(
637*d9f75844SAndroid Build Coastguard Worker             rtp_packet.SequenceNumber(), &frame);
638*d9f75844SAndroid Build Coastguard Worker       } else {
639*d9f75844SAndroid Build Coastguard Worker         loss_notification_controller_->OnReceivedPacket(
640*d9f75844SAndroid Build Coastguard Worker             rtp_packet.SequenceNumber(), nullptr);
641*d9f75844SAndroid Build Coastguard Worker       }
642*d9f75844SAndroid Build Coastguard Worker     }
643*d9f75844SAndroid Build Coastguard Worker   }
644*d9f75844SAndroid Build Coastguard Worker 
645*d9f75844SAndroid Build Coastguard Worker   if (nack_module_) {
646*d9f75844SAndroid Build Coastguard Worker     const bool is_keyframe =
647*d9f75844SAndroid Build Coastguard Worker         video_header.is_first_packet_in_frame &&
648*d9f75844SAndroid Build Coastguard Worker         video_header.frame_type == VideoFrameType::kVideoFrameKey;
649*d9f75844SAndroid Build Coastguard Worker 
650*d9f75844SAndroid Build Coastguard Worker     packet->times_nacked = nack_module_->OnReceivedPacket(
651*d9f75844SAndroid Build Coastguard Worker         rtp_packet.SequenceNumber(), is_keyframe, rtp_packet.recovered());
652*d9f75844SAndroid Build Coastguard Worker   } else {
653*d9f75844SAndroid Build Coastguard Worker     packet->times_nacked = -1;
654*d9f75844SAndroid Build Coastguard Worker   }
655*d9f75844SAndroid Build Coastguard Worker 
656*d9f75844SAndroid Build Coastguard Worker   if (codec_payload.size() == 0) {
657*d9f75844SAndroid Build Coastguard Worker     NotifyReceiverOfEmptyPacket(packet->seq_num);
658*d9f75844SAndroid Build Coastguard Worker     rtcp_feedback_buffer_.SendBufferedRtcpFeedback();
659*d9f75844SAndroid Build Coastguard Worker     return;
660*d9f75844SAndroid Build Coastguard Worker   }
661*d9f75844SAndroid Build Coastguard Worker 
662*d9f75844SAndroid Build Coastguard Worker   if (packet->codec() == kVideoCodecH264) {
663*d9f75844SAndroid Build Coastguard Worker     // Only when we start to receive packets will we know what payload type
664*d9f75844SAndroid Build Coastguard Worker     // that will be used. When we know the payload type insert the correct
665*d9f75844SAndroid Build Coastguard Worker     // sps/pps into the tracker.
666*d9f75844SAndroid Build Coastguard Worker     if (packet->payload_type != last_payload_type_) {
667*d9f75844SAndroid Build Coastguard Worker       last_payload_type_ = packet->payload_type;
668*d9f75844SAndroid Build Coastguard Worker       InsertSpsPpsIntoTracker(packet->payload_type);
669*d9f75844SAndroid Build Coastguard Worker     }
670*d9f75844SAndroid Build Coastguard Worker 
671*d9f75844SAndroid Build Coastguard Worker     video_coding::H264SpsPpsTracker::FixedBitstream fixed =
672*d9f75844SAndroid Build Coastguard Worker         tracker_.CopyAndFixBitstream(
673*d9f75844SAndroid Build Coastguard Worker             rtc::MakeArrayView(codec_payload.cdata(), codec_payload.size()),
674*d9f75844SAndroid Build Coastguard Worker             &packet->video_header);
675*d9f75844SAndroid Build Coastguard Worker 
676*d9f75844SAndroid Build Coastguard Worker     switch (fixed.action) {
677*d9f75844SAndroid Build Coastguard Worker       case video_coding::H264SpsPpsTracker::kRequestKeyframe:
678*d9f75844SAndroid Build Coastguard Worker         rtcp_feedback_buffer_.RequestKeyFrame();
679*d9f75844SAndroid Build Coastguard Worker         rtcp_feedback_buffer_.SendBufferedRtcpFeedback();
680*d9f75844SAndroid Build Coastguard Worker         [[fallthrough]];
681*d9f75844SAndroid Build Coastguard Worker       case video_coding::H264SpsPpsTracker::kDrop:
682*d9f75844SAndroid Build Coastguard Worker         return;
683*d9f75844SAndroid Build Coastguard Worker       case video_coding::H264SpsPpsTracker::kInsert:
684*d9f75844SAndroid Build Coastguard Worker         packet->video_payload = std::move(fixed.bitstream);
685*d9f75844SAndroid Build Coastguard Worker         break;
686*d9f75844SAndroid Build Coastguard Worker     }
687*d9f75844SAndroid Build Coastguard Worker 
688*d9f75844SAndroid Build Coastguard Worker   } else {
689*d9f75844SAndroid Build Coastguard Worker     packet->video_payload = std::move(codec_payload);
690*d9f75844SAndroid Build Coastguard Worker   }
691*d9f75844SAndroid Build Coastguard Worker 
692*d9f75844SAndroid Build Coastguard Worker   rtcp_feedback_buffer_.SendBufferedRtcpFeedback();
693*d9f75844SAndroid Build Coastguard Worker   frame_counter_.Add(packet->timestamp);
694*d9f75844SAndroid Build Coastguard Worker   OnInsertedPacket(packet_buffer_.InsertPacket(std::move(packet)));
695*d9f75844SAndroid Build Coastguard Worker }
696*d9f75844SAndroid Build Coastguard Worker 
OnRecoveredPacket(const uint8_t * rtp_packet,size_t rtp_packet_length)697*d9f75844SAndroid Build Coastguard Worker void RtpVideoStreamReceiver2::OnRecoveredPacket(const uint8_t* rtp_packet,
698*d9f75844SAndroid Build Coastguard Worker                                                 size_t rtp_packet_length) {
699*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
700*d9f75844SAndroid Build Coastguard Worker 
701*d9f75844SAndroid Build Coastguard Worker   RtpPacketReceived packet;
702*d9f75844SAndroid Build Coastguard Worker   if (!packet.Parse(rtp_packet, rtp_packet_length))
703*d9f75844SAndroid Build Coastguard Worker     return;
704*d9f75844SAndroid Build Coastguard Worker   if (packet.PayloadType() == red_payload_type_) {
705*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << "Discarding recovered packet with RED encapsulation";
706*d9f75844SAndroid Build Coastguard Worker     return;
707*d9f75844SAndroid Build Coastguard Worker   }
708*d9f75844SAndroid Build Coastguard Worker 
709*d9f75844SAndroid Build Coastguard Worker   packet.IdentifyExtensions(rtp_header_extensions_);
710*d9f75844SAndroid Build Coastguard Worker   packet.set_payload_type_frequency(kVideoPayloadTypeFrequency);
711*d9f75844SAndroid Build Coastguard Worker   // TODO(bugs.webrtc.org/7135): UlpfecReceiverImpl::ProcessReceivedFec passes
712*d9f75844SAndroid Build Coastguard Worker   // both original (decapsulated) media packets and recovered packets to this
713*d9f75844SAndroid Build Coastguard Worker   // callback. We need a way to distinguish, for setting packet.recovered()
714*d9f75844SAndroid Build Coastguard Worker   // correctly. Ideally, move RED decapsulation out of the Ulpfec
715*d9f75844SAndroid Build Coastguard Worker   // implementation.
716*d9f75844SAndroid Build Coastguard Worker 
717*d9f75844SAndroid Build Coastguard Worker   ReceivePacket(packet);
718*d9f75844SAndroid Build Coastguard Worker }
719*d9f75844SAndroid Build Coastguard Worker 
720*d9f75844SAndroid Build Coastguard Worker // This method handles both regular RTP packets and packets recovered
721*d9f75844SAndroid Build Coastguard Worker // via FlexFEC.
OnRtpPacket(const RtpPacketReceived & packet)722*d9f75844SAndroid Build Coastguard Worker void RtpVideoStreamReceiver2::OnRtpPacket(const RtpPacketReceived& packet) {
723*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
724*d9f75844SAndroid Build Coastguard Worker 
725*d9f75844SAndroid Build Coastguard Worker   if (!receiving_)
726*d9f75844SAndroid Build Coastguard Worker     return;
727*d9f75844SAndroid Build Coastguard Worker 
728*d9f75844SAndroid Build Coastguard Worker   ReceivePacket(packet);
729*d9f75844SAndroid Build Coastguard Worker 
730*d9f75844SAndroid Build Coastguard Worker   // Update receive statistics after ReceivePacket.
731*d9f75844SAndroid Build Coastguard Worker   // Receive statistics will be reset if the payload type changes (make sure
732*d9f75844SAndroid Build Coastguard Worker   // that the first packet is included in the stats).
733*d9f75844SAndroid Build Coastguard Worker   if (!packet.recovered()) {
734*d9f75844SAndroid Build Coastguard Worker     rtp_receive_statistics_->OnRtpPacket(packet);
735*d9f75844SAndroid Build Coastguard Worker   }
736*d9f75844SAndroid Build Coastguard Worker 
737*d9f75844SAndroid Build Coastguard Worker   if (packet_sink_) {
738*d9f75844SAndroid Build Coastguard Worker     packet_sink_->OnRtpPacket(packet);
739*d9f75844SAndroid Build Coastguard Worker   }
740*d9f75844SAndroid Build Coastguard Worker }
741*d9f75844SAndroid Build Coastguard Worker 
RequestKeyFrame()742*d9f75844SAndroid Build Coastguard Worker void RtpVideoStreamReceiver2::RequestKeyFrame() {
743*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&worker_task_checker_);
744*d9f75844SAndroid Build Coastguard Worker   // TODO(bugs.webrtc.org/10336): Allow the sender to ignore key frame requests
745*d9f75844SAndroid Build Coastguard Worker   // issued by anything other than the LossNotificationController if it (the
746*d9f75844SAndroid Build Coastguard Worker   // sender) is relying on LNTF alone.
747*d9f75844SAndroid Build Coastguard Worker   if (keyframe_request_method_ == KeyFrameReqMethod::kPliRtcp) {
748*d9f75844SAndroid Build Coastguard Worker     rtp_rtcp_->SendPictureLossIndication();
749*d9f75844SAndroid Build Coastguard Worker   } else if (keyframe_request_method_ == KeyFrameReqMethod::kFirRtcp) {
750*d9f75844SAndroid Build Coastguard Worker     rtp_rtcp_->SendFullIntraRequest();
751*d9f75844SAndroid Build Coastguard Worker   }
752*d9f75844SAndroid Build Coastguard Worker }
753*d9f75844SAndroid Build Coastguard Worker 
SendNack(const std::vector<uint16_t> & sequence_numbers,bool)754*d9f75844SAndroid Build Coastguard Worker void RtpVideoStreamReceiver2::SendNack(
755*d9f75844SAndroid Build Coastguard Worker     const std::vector<uint16_t>& sequence_numbers,
756*d9f75844SAndroid Build Coastguard Worker     bool /*buffering_allowed*/) {
757*d9f75844SAndroid Build Coastguard Worker   rtp_rtcp_->SendNack(sequence_numbers);
758*d9f75844SAndroid Build Coastguard Worker }
759*d9f75844SAndroid Build Coastguard Worker 
SendLossNotification(uint16_t last_decoded_seq_num,uint16_t last_received_seq_num,bool decodability_flag,bool buffering_allowed)760*d9f75844SAndroid Build Coastguard Worker void RtpVideoStreamReceiver2::SendLossNotification(
761*d9f75844SAndroid Build Coastguard Worker     uint16_t last_decoded_seq_num,
762*d9f75844SAndroid Build Coastguard Worker     uint16_t last_received_seq_num,
763*d9f75844SAndroid Build Coastguard Worker     bool decodability_flag,
764*d9f75844SAndroid Build Coastguard Worker     bool buffering_allowed) {
765*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(config_.rtp.lntf.enabled);
766*d9f75844SAndroid Build Coastguard Worker   rtp_rtcp_->SendLossNotification(last_decoded_seq_num, last_received_seq_num,
767*d9f75844SAndroid Build Coastguard Worker                                   decodability_flag, buffering_allowed);
768*d9f75844SAndroid Build Coastguard Worker }
769*d9f75844SAndroid Build Coastguard Worker 
IsDecryptable() const770*d9f75844SAndroid Build Coastguard Worker bool RtpVideoStreamReceiver2::IsDecryptable() const {
771*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&worker_task_checker_);
772*d9f75844SAndroid Build Coastguard Worker   return frames_decryptable_;
773*d9f75844SAndroid Build Coastguard Worker }
774*d9f75844SAndroid Build Coastguard Worker 
OnInsertedPacket(video_coding::PacketBuffer::InsertResult result)775*d9f75844SAndroid Build Coastguard Worker void RtpVideoStreamReceiver2::OnInsertedPacket(
776*d9f75844SAndroid Build Coastguard Worker     video_coding::PacketBuffer::InsertResult result) {
777*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
778*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&worker_task_checker_);
779*d9f75844SAndroid Build Coastguard Worker   video_coding::PacketBuffer::Packet* first_packet = nullptr;
780*d9f75844SAndroid Build Coastguard Worker   int max_nack_count;
781*d9f75844SAndroid Build Coastguard Worker   int64_t min_recv_time;
782*d9f75844SAndroid Build Coastguard Worker   int64_t max_recv_time;
783*d9f75844SAndroid Build Coastguard Worker   std::vector<rtc::ArrayView<const uint8_t>> payloads;
784*d9f75844SAndroid Build Coastguard Worker   RtpPacketInfos::vector_type packet_infos;
785*d9f75844SAndroid Build Coastguard Worker 
786*d9f75844SAndroid Build Coastguard Worker   bool frame_boundary = true;
787*d9f75844SAndroid Build Coastguard Worker   for (auto& packet : result.packets) {
788*d9f75844SAndroid Build Coastguard Worker     // PacketBuffer promisses frame boundaries are correctly set on each
789*d9f75844SAndroid Build Coastguard Worker     // packet. Document that assumption with the DCHECKs.
790*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK_EQ(frame_boundary, packet->is_first_packet_in_frame());
791*d9f75844SAndroid Build Coastguard Worker     int64_t unwrapped_rtp_seq_num =
792*d9f75844SAndroid Build Coastguard Worker         rtp_seq_num_unwrapper_.Unwrap(packet->seq_num);
793*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK_GT(packet_infos_.count(unwrapped_rtp_seq_num), 0);
794*d9f75844SAndroid Build Coastguard Worker     RtpPacketInfo& packet_info = packet_infos_[unwrapped_rtp_seq_num];
795*d9f75844SAndroid Build Coastguard Worker     if (packet->is_first_packet_in_frame()) {
796*d9f75844SAndroid Build Coastguard Worker       first_packet = packet.get();
797*d9f75844SAndroid Build Coastguard Worker       max_nack_count = packet->times_nacked;
798*d9f75844SAndroid Build Coastguard Worker       min_recv_time = packet_info.receive_time().ms();
799*d9f75844SAndroid Build Coastguard Worker       max_recv_time = packet_info.receive_time().ms();
800*d9f75844SAndroid Build Coastguard Worker     } else {
801*d9f75844SAndroid Build Coastguard Worker       max_nack_count = std::max(max_nack_count, packet->times_nacked);
802*d9f75844SAndroid Build Coastguard Worker       min_recv_time = std::min(min_recv_time, packet_info.receive_time().ms());
803*d9f75844SAndroid Build Coastguard Worker       max_recv_time = std::max(max_recv_time, packet_info.receive_time().ms());
804*d9f75844SAndroid Build Coastguard Worker     }
805*d9f75844SAndroid Build Coastguard Worker     payloads.emplace_back(packet->video_payload);
806*d9f75844SAndroid Build Coastguard Worker     packet_infos.push_back(packet_info);
807*d9f75844SAndroid Build Coastguard Worker 
808*d9f75844SAndroid Build Coastguard Worker     frame_boundary = packet->is_last_packet_in_frame();
809*d9f75844SAndroid Build Coastguard Worker     if (packet->is_last_packet_in_frame()) {
810*d9f75844SAndroid Build Coastguard Worker       auto depacketizer_it = payload_type_map_.find(first_packet->payload_type);
811*d9f75844SAndroid Build Coastguard Worker       RTC_CHECK(depacketizer_it != payload_type_map_.end());
812*d9f75844SAndroid Build Coastguard Worker 
813*d9f75844SAndroid Build Coastguard Worker       rtc::scoped_refptr<EncodedImageBuffer> bitstream =
814*d9f75844SAndroid Build Coastguard Worker           depacketizer_it->second->AssembleFrame(payloads);
815*d9f75844SAndroid Build Coastguard Worker       if (!bitstream) {
816*d9f75844SAndroid Build Coastguard Worker         // Failed to assemble a frame. Discard and continue.
817*d9f75844SAndroid Build Coastguard Worker         continue;
818*d9f75844SAndroid Build Coastguard Worker       }
819*d9f75844SAndroid Build Coastguard Worker 
820*d9f75844SAndroid Build Coastguard Worker       const video_coding::PacketBuffer::Packet& last_packet = *packet;
821*d9f75844SAndroid Build Coastguard Worker       OnAssembledFrame(std::make_unique<RtpFrameObject>(
822*d9f75844SAndroid Build Coastguard Worker           first_packet->seq_num,                             //
823*d9f75844SAndroid Build Coastguard Worker           last_packet.seq_num,                               //
824*d9f75844SAndroid Build Coastguard Worker           last_packet.marker_bit,                            //
825*d9f75844SAndroid Build Coastguard Worker           max_nack_count,                                    //
826*d9f75844SAndroid Build Coastguard Worker           min_recv_time,                                     //
827*d9f75844SAndroid Build Coastguard Worker           max_recv_time,                                     //
828*d9f75844SAndroid Build Coastguard Worker           first_packet->timestamp,                           //
829*d9f75844SAndroid Build Coastguard Worker           ntp_estimator_.Estimate(first_packet->timestamp),  //
830*d9f75844SAndroid Build Coastguard Worker           last_packet.video_header.video_timing,             //
831*d9f75844SAndroid Build Coastguard Worker           first_packet->payload_type,                        //
832*d9f75844SAndroid Build Coastguard Worker           first_packet->codec(),                             //
833*d9f75844SAndroid Build Coastguard Worker           last_packet.video_header.rotation,                 //
834*d9f75844SAndroid Build Coastguard Worker           last_packet.video_header.content_type,             //
835*d9f75844SAndroid Build Coastguard Worker           first_packet->video_header,                        //
836*d9f75844SAndroid Build Coastguard Worker           last_packet.video_header.color_space,              //
837*d9f75844SAndroid Build Coastguard Worker           RtpPacketInfos(std::move(packet_infos)),           //
838*d9f75844SAndroid Build Coastguard Worker           std::move(bitstream)));
839*d9f75844SAndroid Build Coastguard Worker       payloads.clear();
840*d9f75844SAndroid Build Coastguard Worker       packet_infos.clear();
841*d9f75844SAndroid Build Coastguard Worker     }
842*d9f75844SAndroid Build Coastguard Worker   }
843*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(frame_boundary);
844*d9f75844SAndroid Build Coastguard Worker   if (result.buffer_cleared) {
845*d9f75844SAndroid Build Coastguard Worker     last_received_rtp_system_time_.reset();
846*d9f75844SAndroid Build Coastguard Worker     last_received_keyframe_rtp_system_time_.reset();
847*d9f75844SAndroid Build Coastguard Worker     last_received_keyframe_rtp_timestamp_.reset();
848*d9f75844SAndroid Build Coastguard Worker     packet_infos_.clear();
849*d9f75844SAndroid Build Coastguard Worker     RequestKeyFrame();
850*d9f75844SAndroid Build Coastguard Worker   }
851*d9f75844SAndroid Build Coastguard Worker }
852*d9f75844SAndroid Build Coastguard Worker 
OnAssembledFrame(std::unique_ptr<RtpFrameObject> frame)853*d9f75844SAndroid Build Coastguard Worker void RtpVideoStreamReceiver2::OnAssembledFrame(
854*d9f75844SAndroid Build Coastguard Worker     std::unique_ptr<RtpFrameObject> frame) {
855*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
856*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(frame);
857*d9f75844SAndroid Build Coastguard Worker 
858*d9f75844SAndroid Build Coastguard Worker   const absl::optional<RTPVideoHeader::GenericDescriptorInfo>& descriptor =
859*d9f75844SAndroid Build Coastguard Worker       frame->GetRtpVideoHeader().generic;
860*d9f75844SAndroid Build Coastguard Worker 
861*d9f75844SAndroid Build Coastguard Worker   if (loss_notification_controller_ && descriptor) {
862*d9f75844SAndroid Build Coastguard Worker     loss_notification_controller_->OnAssembledFrame(
863*d9f75844SAndroid Build Coastguard Worker         frame->first_seq_num(), descriptor->frame_id,
864*d9f75844SAndroid Build Coastguard Worker         absl::c_linear_search(descriptor->decode_target_indications,
865*d9f75844SAndroid Build Coastguard Worker                               DecodeTargetIndication::kDiscardable),
866*d9f75844SAndroid Build Coastguard Worker         descriptor->dependencies);
867*d9f75844SAndroid Build Coastguard Worker   }
868*d9f75844SAndroid Build Coastguard Worker 
869*d9f75844SAndroid Build Coastguard Worker   // If frames arrive before a key frame, they would not be decodable.
870*d9f75844SAndroid Build Coastguard Worker   // In that case, request a key frame ASAP.
871*d9f75844SAndroid Build Coastguard Worker   if (!has_received_frame_) {
872*d9f75844SAndroid Build Coastguard Worker     if (frame->FrameType() != VideoFrameType::kVideoFrameKey) {
873*d9f75844SAndroid Build Coastguard Worker       // `loss_notification_controller_`, if present, would have already
874*d9f75844SAndroid Build Coastguard Worker       // requested a key frame when the first packet for the non-key frame
875*d9f75844SAndroid Build Coastguard Worker       // had arrived, so no need to replicate the request.
876*d9f75844SAndroid Build Coastguard Worker       if (!loss_notification_controller_) {
877*d9f75844SAndroid Build Coastguard Worker         RequestKeyFrame();
878*d9f75844SAndroid Build Coastguard Worker       }
879*d9f75844SAndroid Build Coastguard Worker     }
880*d9f75844SAndroid Build Coastguard Worker     has_received_frame_ = true;
881*d9f75844SAndroid Build Coastguard Worker   }
882*d9f75844SAndroid Build Coastguard Worker 
883*d9f75844SAndroid Build Coastguard Worker   // Reset `reference_finder_` if `frame` is new and the codec have changed.
884*d9f75844SAndroid Build Coastguard Worker   if (current_codec_) {
885*d9f75844SAndroid Build Coastguard Worker     bool frame_is_newer =
886*d9f75844SAndroid Build Coastguard Worker         AheadOf(frame->Timestamp(), last_assembled_frame_rtp_timestamp_);
887*d9f75844SAndroid Build Coastguard Worker 
888*d9f75844SAndroid Build Coastguard Worker     if (frame->codec_type() != current_codec_) {
889*d9f75844SAndroid Build Coastguard Worker       if (frame_is_newer) {
890*d9f75844SAndroid Build Coastguard Worker         // When we reset the `reference_finder_` we don't want new picture ids
891*d9f75844SAndroid Build Coastguard Worker         // to overlap with old picture ids. To ensure that doesn't happen we
892*d9f75844SAndroid Build Coastguard Worker         // start from the `last_completed_picture_id_` and add an offset in case
893*d9f75844SAndroid Build Coastguard Worker         // of reordering.
894*d9f75844SAndroid Build Coastguard Worker         reference_finder_ = std::make_unique<RtpFrameReferenceFinder>(
895*d9f75844SAndroid Build Coastguard Worker             last_completed_picture_id_ + std::numeric_limits<uint16_t>::max());
896*d9f75844SAndroid Build Coastguard Worker         current_codec_ = frame->codec_type();
897*d9f75844SAndroid Build Coastguard Worker       } else {
898*d9f75844SAndroid Build Coastguard Worker         // Old frame from before the codec switch, discard it.
899*d9f75844SAndroid Build Coastguard Worker         return;
900*d9f75844SAndroid Build Coastguard Worker       }
901*d9f75844SAndroid Build Coastguard Worker     }
902*d9f75844SAndroid Build Coastguard Worker 
903*d9f75844SAndroid Build Coastguard Worker     if (frame_is_newer) {
904*d9f75844SAndroid Build Coastguard Worker       last_assembled_frame_rtp_timestamp_ = frame->Timestamp();
905*d9f75844SAndroid Build Coastguard Worker     }
906*d9f75844SAndroid Build Coastguard Worker   } else {
907*d9f75844SAndroid Build Coastguard Worker     current_codec_ = frame->codec_type();
908*d9f75844SAndroid Build Coastguard Worker     last_assembled_frame_rtp_timestamp_ = frame->Timestamp();
909*d9f75844SAndroid Build Coastguard Worker   }
910*d9f75844SAndroid Build Coastguard Worker 
911*d9f75844SAndroid Build Coastguard Worker   if (buffered_frame_decryptor_ != nullptr) {
912*d9f75844SAndroid Build Coastguard Worker     buffered_frame_decryptor_->ManageEncryptedFrame(std::move(frame));
913*d9f75844SAndroid Build Coastguard Worker   } else if (frame_transformer_delegate_) {
914*d9f75844SAndroid Build Coastguard Worker     frame_transformer_delegate_->TransformFrame(std::move(frame));
915*d9f75844SAndroid Build Coastguard Worker   } else {
916*d9f75844SAndroid Build Coastguard Worker     OnCompleteFrames(reference_finder_->ManageFrame(std::move(frame)));
917*d9f75844SAndroid Build Coastguard Worker   }
918*d9f75844SAndroid Build Coastguard Worker }
919*d9f75844SAndroid Build Coastguard Worker 
OnCompleteFrames(RtpFrameReferenceFinder::ReturnVector frames)920*d9f75844SAndroid Build Coastguard Worker void RtpVideoStreamReceiver2::OnCompleteFrames(
921*d9f75844SAndroid Build Coastguard Worker     RtpFrameReferenceFinder::ReturnVector frames) {
922*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
923*d9f75844SAndroid Build Coastguard Worker   for (auto& frame : frames) {
924*d9f75844SAndroid Build Coastguard Worker     last_seq_num_for_pic_id_[frame->Id()] = frame->last_seq_num();
925*d9f75844SAndroid Build Coastguard Worker 
926*d9f75844SAndroid Build Coastguard Worker     last_completed_picture_id_ =
927*d9f75844SAndroid Build Coastguard Worker         std::max(last_completed_picture_id_, frame->Id());
928*d9f75844SAndroid Build Coastguard Worker     complete_frame_callback_->OnCompleteFrame(std::move(frame));
929*d9f75844SAndroid Build Coastguard Worker   }
930*d9f75844SAndroid Build Coastguard Worker }
931*d9f75844SAndroid Build Coastguard Worker 
OnDecryptedFrame(std::unique_ptr<RtpFrameObject> frame)932*d9f75844SAndroid Build Coastguard Worker void RtpVideoStreamReceiver2::OnDecryptedFrame(
933*d9f75844SAndroid Build Coastguard Worker     std::unique_ptr<RtpFrameObject> frame) {
934*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
935*d9f75844SAndroid Build Coastguard Worker   OnCompleteFrames(reference_finder_->ManageFrame(std::move(frame)));
936*d9f75844SAndroid Build Coastguard Worker }
937*d9f75844SAndroid Build Coastguard Worker 
OnDecryptionStatusChange(FrameDecryptorInterface::Status status)938*d9f75844SAndroid Build Coastguard Worker void RtpVideoStreamReceiver2::OnDecryptionStatusChange(
939*d9f75844SAndroid Build Coastguard Worker     FrameDecryptorInterface::Status status) {
940*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&worker_task_checker_);
941*d9f75844SAndroid Build Coastguard Worker   // Called from BufferedFrameDecryptor::DecryptFrame.
942*d9f75844SAndroid Build Coastguard Worker   frames_decryptable_ =
943*d9f75844SAndroid Build Coastguard Worker       (status == FrameDecryptorInterface::Status::kOk) ||
944*d9f75844SAndroid Build Coastguard Worker       (status == FrameDecryptorInterface::Status::kRecoverable);
945*d9f75844SAndroid Build Coastguard Worker }
946*d9f75844SAndroid Build Coastguard Worker 
SetFrameDecryptor(rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor)947*d9f75844SAndroid Build Coastguard Worker void RtpVideoStreamReceiver2::SetFrameDecryptor(
948*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor) {
949*d9f75844SAndroid Build Coastguard Worker   // TODO(bugs.webrtc.org/11993): Update callers or post the operation over to
950*d9f75844SAndroid Build Coastguard Worker   // the network thread.
951*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
952*d9f75844SAndroid Build Coastguard Worker   if (buffered_frame_decryptor_ == nullptr) {
953*d9f75844SAndroid Build Coastguard Worker     buffered_frame_decryptor_ =
954*d9f75844SAndroid Build Coastguard Worker         std::make_unique<BufferedFrameDecryptor>(this, this, field_trials_);
955*d9f75844SAndroid Build Coastguard Worker   }
956*d9f75844SAndroid Build Coastguard Worker   buffered_frame_decryptor_->SetFrameDecryptor(std::move(frame_decryptor));
957*d9f75844SAndroid Build Coastguard Worker }
958*d9f75844SAndroid Build Coastguard Worker 
SetDepacketizerToDecoderFrameTransformer(rtc::scoped_refptr<FrameTransformerInterface> frame_transformer)959*d9f75844SAndroid Build Coastguard Worker void RtpVideoStreamReceiver2::SetDepacketizerToDecoderFrameTransformer(
960*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<FrameTransformerInterface> frame_transformer) {
961*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&worker_task_checker_);
962*d9f75844SAndroid Build Coastguard Worker   frame_transformer_delegate_ =
963*d9f75844SAndroid Build Coastguard Worker       rtc::make_ref_counted<RtpVideoStreamReceiverFrameTransformerDelegate>(
964*d9f75844SAndroid Build Coastguard Worker           this, std::move(frame_transformer), rtc::Thread::Current(),
965*d9f75844SAndroid Build Coastguard Worker           config_.rtp.remote_ssrc);
966*d9f75844SAndroid Build Coastguard Worker   frame_transformer_delegate_->Init();
967*d9f75844SAndroid Build Coastguard Worker }
968*d9f75844SAndroid Build Coastguard Worker 
SetRtpExtensions(const std::vector<RtpExtension> & extensions)969*d9f75844SAndroid Build Coastguard Worker void RtpVideoStreamReceiver2::SetRtpExtensions(
970*d9f75844SAndroid Build Coastguard Worker     const std::vector<RtpExtension>& extensions) {
971*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
972*d9f75844SAndroid Build Coastguard Worker   rtp_header_extensions_.Reset(extensions);
973*d9f75844SAndroid Build Coastguard Worker }
974*d9f75844SAndroid Build Coastguard Worker 
GetRtpExtensions() const975*d9f75844SAndroid Build Coastguard Worker const RtpHeaderExtensionMap& RtpVideoStreamReceiver2::GetRtpExtensions() const {
976*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
977*d9f75844SAndroid Build Coastguard Worker   return rtp_header_extensions_;
978*d9f75844SAndroid Build Coastguard Worker }
979*d9f75844SAndroid Build Coastguard Worker 
UpdateRtt(int64_t max_rtt_ms)980*d9f75844SAndroid Build Coastguard Worker void RtpVideoStreamReceiver2::UpdateRtt(int64_t max_rtt_ms) {
981*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
982*d9f75844SAndroid Build Coastguard Worker   if (nack_module_)
983*d9f75844SAndroid Build Coastguard Worker     nack_module_->UpdateRtt(max_rtt_ms);
984*d9f75844SAndroid Build Coastguard Worker }
985*d9f75844SAndroid Build Coastguard Worker 
OnLocalSsrcChange(uint32_t local_ssrc)986*d9f75844SAndroid Build Coastguard Worker void RtpVideoStreamReceiver2::OnLocalSsrcChange(uint32_t local_ssrc) {
987*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
988*d9f75844SAndroid Build Coastguard Worker   rtp_rtcp_->SetLocalSsrc(local_ssrc);
989*d9f75844SAndroid Build Coastguard Worker }
990*d9f75844SAndroid Build Coastguard Worker 
SetRtcpMode(RtcpMode mode)991*d9f75844SAndroid Build Coastguard Worker void RtpVideoStreamReceiver2::SetRtcpMode(RtcpMode mode) {
992*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
993*d9f75844SAndroid Build Coastguard Worker   rtp_rtcp_->SetRTCPStatus(mode);
994*d9f75844SAndroid Build Coastguard Worker }
995*d9f75844SAndroid Build Coastguard Worker 
SetReferenceTimeReport(bool enabled)996*d9f75844SAndroid Build Coastguard Worker void RtpVideoStreamReceiver2::SetReferenceTimeReport(bool enabled) {
997*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
998*d9f75844SAndroid Build Coastguard Worker   rtp_rtcp_->SetNonSenderRttMeasurement(enabled);
999*d9f75844SAndroid Build Coastguard Worker }
1000*d9f75844SAndroid Build Coastguard Worker 
SetPacketSink(RtpPacketSinkInterface * packet_sink)1001*d9f75844SAndroid Build Coastguard Worker void RtpVideoStreamReceiver2::SetPacketSink(
1002*d9f75844SAndroid Build Coastguard Worker     RtpPacketSinkInterface* packet_sink) {
1003*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
1004*d9f75844SAndroid Build Coastguard Worker   packet_sink_ = packet_sink;
1005*d9f75844SAndroid Build Coastguard Worker }
1006*d9f75844SAndroid Build Coastguard Worker 
SetLossNotificationEnabled(bool enabled)1007*d9f75844SAndroid Build Coastguard Worker void RtpVideoStreamReceiver2::SetLossNotificationEnabled(bool enabled) {
1008*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
1009*d9f75844SAndroid Build Coastguard Worker   if (enabled && !loss_notification_controller_) {
1010*d9f75844SAndroid Build Coastguard Worker     loss_notification_controller_ =
1011*d9f75844SAndroid Build Coastguard Worker         std::make_unique<LossNotificationController>(&rtcp_feedback_buffer_,
1012*d9f75844SAndroid Build Coastguard Worker                                                      &rtcp_feedback_buffer_);
1013*d9f75844SAndroid Build Coastguard Worker   } else if (!enabled && loss_notification_controller_) {
1014*d9f75844SAndroid Build Coastguard Worker     loss_notification_controller_.reset();
1015*d9f75844SAndroid Build Coastguard Worker     rtcp_feedback_buffer_.ClearLossNotificationState();
1016*d9f75844SAndroid Build Coastguard Worker   }
1017*d9f75844SAndroid Build Coastguard Worker }
1018*d9f75844SAndroid Build Coastguard Worker 
SetNackHistory(TimeDelta history)1019*d9f75844SAndroid Build Coastguard Worker void RtpVideoStreamReceiver2::SetNackHistory(TimeDelta history) {
1020*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
1021*d9f75844SAndroid Build Coastguard Worker   if (history.ms() == 0) {
1022*d9f75844SAndroid Build Coastguard Worker     nack_module_.reset();
1023*d9f75844SAndroid Build Coastguard Worker   } else if (!nack_module_) {
1024*d9f75844SAndroid Build Coastguard Worker     nack_module_ = std::make_unique<NackRequester>(
1025*d9f75844SAndroid Build Coastguard Worker         worker_queue_, nack_periodic_processor_, clock_, &rtcp_feedback_buffer_,
1026*d9f75844SAndroid Build Coastguard Worker         &rtcp_feedback_buffer_, field_trials_);
1027*d9f75844SAndroid Build Coastguard Worker   }
1028*d9f75844SAndroid Build Coastguard Worker 
1029*d9f75844SAndroid Build Coastguard Worker   rtp_receive_statistics_->SetMaxReorderingThreshold(
1030*d9f75844SAndroid Build Coastguard Worker       config_.rtp.remote_ssrc,
1031*d9f75844SAndroid Build Coastguard Worker       history.ms() > 0 ? kMaxPacketAgeToNack : kDefaultMaxReorderingThreshold);
1032*d9f75844SAndroid Build Coastguard Worker }
1033*d9f75844SAndroid Build Coastguard Worker 
ulpfec_payload_type() const1034*d9f75844SAndroid Build Coastguard Worker int RtpVideoStreamReceiver2::ulpfec_payload_type() const {
1035*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
1036*d9f75844SAndroid Build Coastguard Worker   return ulpfec_receiver_ ? ulpfec_receiver_->ulpfec_payload_type() : -1;
1037*d9f75844SAndroid Build Coastguard Worker }
1038*d9f75844SAndroid Build Coastguard Worker 
red_payload_type() const1039*d9f75844SAndroid Build Coastguard Worker int RtpVideoStreamReceiver2::red_payload_type() const {
1040*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
1041*d9f75844SAndroid Build Coastguard Worker   return red_payload_type_;
1042*d9f75844SAndroid Build Coastguard Worker }
1043*d9f75844SAndroid Build Coastguard Worker 
SetProtectionPayloadTypes(int red_payload_type,int ulpfec_payload_type)1044*d9f75844SAndroid Build Coastguard Worker void RtpVideoStreamReceiver2::SetProtectionPayloadTypes(
1045*d9f75844SAndroid Build Coastguard Worker     int red_payload_type,
1046*d9f75844SAndroid Build Coastguard Worker     int ulpfec_payload_type) {
1047*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
1048*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(red_payload_type >= -1 && red_payload_type < 0x80);
1049*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(ulpfec_payload_type >= -1 && ulpfec_payload_type < 0x80);
1050*d9f75844SAndroid Build Coastguard Worker   red_payload_type_ = red_payload_type;
1051*d9f75844SAndroid Build Coastguard Worker   ulpfec_receiver_ = MaybeConstructUlpfecReceiver(
1052*d9f75844SAndroid Build Coastguard Worker       config_.rtp.remote_ssrc, red_payload_type, ulpfec_payload_type,
1053*d9f75844SAndroid Build Coastguard Worker       config_.rtp.extensions, this, clock_);
1054*d9f75844SAndroid Build Coastguard Worker }
1055*d9f75844SAndroid Build Coastguard Worker 
LastReceivedPacketMs() const1056*d9f75844SAndroid Build Coastguard Worker absl::optional<int64_t> RtpVideoStreamReceiver2::LastReceivedPacketMs() const {
1057*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
1058*d9f75844SAndroid Build Coastguard Worker   if (last_received_rtp_system_time_) {
1059*d9f75844SAndroid Build Coastguard Worker     return absl::optional<int64_t>(last_received_rtp_system_time_->ms());
1060*d9f75844SAndroid Build Coastguard Worker   }
1061*d9f75844SAndroid Build Coastguard Worker   return absl::nullopt;
1062*d9f75844SAndroid Build Coastguard Worker }
1063*d9f75844SAndroid Build Coastguard Worker 
LastReceivedKeyframePacketMs() const1064*d9f75844SAndroid Build Coastguard Worker absl::optional<int64_t> RtpVideoStreamReceiver2::LastReceivedKeyframePacketMs()
1065*d9f75844SAndroid Build Coastguard Worker     const {
1066*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
1067*d9f75844SAndroid Build Coastguard Worker   if (last_received_keyframe_rtp_system_time_) {
1068*d9f75844SAndroid Build Coastguard Worker     return absl::optional<int64_t>(
1069*d9f75844SAndroid Build Coastguard Worker         last_received_keyframe_rtp_system_time_->ms());
1070*d9f75844SAndroid Build Coastguard Worker   }
1071*d9f75844SAndroid Build Coastguard Worker   return absl::nullopt;
1072*d9f75844SAndroid Build Coastguard Worker }
1073*d9f75844SAndroid Build Coastguard Worker 
ManageFrame(std::unique_ptr<RtpFrameObject> frame)1074*d9f75844SAndroid Build Coastguard Worker void RtpVideoStreamReceiver2::ManageFrame(
1075*d9f75844SAndroid Build Coastguard Worker     std::unique_ptr<RtpFrameObject> frame) {
1076*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
1077*d9f75844SAndroid Build Coastguard Worker   OnCompleteFrames(reference_finder_->ManageFrame(std::move(frame)));
1078*d9f75844SAndroid Build Coastguard Worker }
1079*d9f75844SAndroid Build Coastguard Worker 
ReceivePacket(const RtpPacketReceived & packet)1080*d9f75844SAndroid Build Coastguard Worker void RtpVideoStreamReceiver2::ReceivePacket(const RtpPacketReceived& packet) {
1081*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
1082*d9f75844SAndroid Build Coastguard Worker 
1083*d9f75844SAndroid Build Coastguard Worker   if (packet.payload_size() == 0) {
1084*d9f75844SAndroid Build Coastguard Worker     // Padding or keep-alive packet.
1085*d9f75844SAndroid Build Coastguard Worker     // TODO(nisse): Could drop empty packets earlier, but need to figure out how
1086*d9f75844SAndroid Build Coastguard Worker     // they should be counted in stats.
1087*d9f75844SAndroid Build Coastguard Worker     NotifyReceiverOfEmptyPacket(packet.SequenceNumber());
1088*d9f75844SAndroid Build Coastguard Worker     return;
1089*d9f75844SAndroid Build Coastguard Worker   }
1090*d9f75844SAndroid Build Coastguard Worker   if (packet.PayloadType() == red_payload_type_) {
1091*d9f75844SAndroid Build Coastguard Worker     ParseAndHandleEncapsulatingHeader(packet);
1092*d9f75844SAndroid Build Coastguard Worker     return;
1093*d9f75844SAndroid Build Coastguard Worker   }
1094*d9f75844SAndroid Build Coastguard Worker 
1095*d9f75844SAndroid Build Coastguard Worker   const auto type_it = payload_type_map_.find(packet.PayloadType());
1096*d9f75844SAndroid Build Coastguard Worker   if (type_it == payload_type_map_.end()) {
1097*d9f75844SAndroid Build Coastguard Worker     return;
1098*d9f75844SAndroid Build Coastguard Worker   }
1099*d9f75844SAndroid Build Coastguard Worker   absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed_payload =
1100*d9f75844SAndroid Build Coastguard Worker       type_it->second->Parse(packet.PayloadBuffer());
1101*d9f75844SAndroid Build Coastguard Worker   if (parsed_payload == absl::nullopt) {
1102*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << "Failed parsing payload.";
1103*d9f75844SAndroid Build Coastguard Worker     return;
1104*d9f75844SAndroid Build Coastguard Worker   }
1105*d9f75844SAndroid Build Coastguard Worker 
1106*d9f75844SAndroid Build Coastguard Worker   OnReceivedPayloadData(std::move(parsed_payload->video_payload), packet,
1107*d9f75844SAndroid Build Coastguard Worker                         parsed_payload->video_header);
1108*d9f75844SAndroid Build Coastguard Worker }
1109*d9f75844SAndroid Build Coastguard Worker 
ParseAndHandleEncapsulatingHeader(const RtpPacketReceived & packet)1110*d9f75844SAndroid Build Coastguard Worker void RtpVideoStreamReceiver2::ParseAndHandleEncapsulatingHeader(
1111*d9f75844SAndroid Build Coastguard Worker     const RtpPacketReceived& packet) {
1112*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
1113*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_EQ(packet.PayloadType(), red_payload_type_);
1114*d9f75844SAndroid Build Coastguard Worker 
1115*d9f75844SAndroid Build Coastguard Worker   if (!ulpfec_receiver_ || packet.payload_size() == 0U)
1116*d9f75844SAndroid Build Coastguard Worker     return;
1117*d9f75844SAndroid Build Coastguard Worker 
1118*d9f75844SAndroid Build Coastguard Worker   if (packet.payload()[0] == ulpfec_receiver_->ulpfec_payload_type()) {
1119*d9f75844SAndroid Build Coastguard Worker     // Notify video_receiver about received FEC packets to avoid NACKing these
1120*d9f75844SAndroid Build Coastguard Worker     // packets.
1121*d9f75844SAndroid Build Coastguard Worker     NotifyReceiverOfEmptyPacket(packet.SequenceNumber());
1122*d9f75844SAndroid Build Coastguard Worker   }
1123*d9f75844SAndroid Build Coastguard Worker   if (ulpfec_receiver_->AddReceivedRedPacket(packet)) {
1124*d9f75844SAndroid Build Coastguard Worker     ulpfec_receiver_->ProcessReceivedFec();
1125*d9f75844SAndroid Build Coastguard Worker   }
1126*d9f75844SAndroid Build Coastguard Worker }
1127*d9f75844SAndroid Build Coastguard Worker 
1128*d9f75844SAndroid Build Coastguard Worker // In the case of a video stream without picture ids and no rtx the
1129*d9f75844SAndroid Build Coastguard Worker // RtpFrameReferenceFinder will need to know about padding to
1130*d9f75844SAndroid Build Coastguard Worker // correctly calculate frame references.
NotifyReceiverOfEmptyPacket(uint16_t seq_num)1131*d9f75844SAndroid Build Coastguard Worker void RtpVideoStreamReceiver2::NotifyReceiverOfEmptyPacket(uint16_t seq_num) {
1132*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
1133*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&worker_task_checker_);
1134*d9f75844SAndroid Build Coastguard Worker 
1135*d9f75844SAndroid Build Coastguard Worker   OnCompleteFrames(reference_finder_->PaddingReceived(seq_num));
1136*d9f75844SAndroid Build Coastguard Worker 
1137*d9f75844SAndroid Build Coastguard Worker   OnInsertedPacket(packet_buffer_.InsertPadding(seq_num));
1138*d9f75844SAndroid Build Coastguard Worker   if (nack_module_) {
1139*d9f75844SAndroid Build Coastguard Worker     nack_module_->OnReceivedPacket(seq_num, /* is_keyframe = */ false,
1140*d9f75844SAndroid Build Coastguard Worker                                    /* is _recovered = */ false);
1141*d9f75844SAndroid Build Coastguard Worker   }
1142*d9f75844SAndroid Build Coastguard Worker   if (loss_notification_controller_) {
1143*d9f75844SAndroid Build Coastguard Worker     // TODO(bugs.webrtc.org/10336): Handle empty packets.
1144*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING)
1145*d9f75844SAndroid Build Coastguard Worker         << "LossNotificationController does not expect empty packets.";
1146*d9f75844SAndroid Build Coastguard Worker   }
1147*d9f75844SAndroid Build Coastguard Worker }
1148*d9f75844SAndroid Build Coastguard Worker 
DeliverRtcp(const uint8_t * rtcp_packet,size_t rtcp_packet_length)1149*d9f75844SAndroid Build Coastguard Worker bool RtpVideoStreamReceiver2::DeliverRtcp(const uint8_t* rtcp_packet,
1150*d9f75844SAndroid Build Coastguard Worker                                           size_t rtcp_packet_length) {
1151*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
1152*d9f75844SAndroid Build Coastguard Worker 
1153*d9f75844SAndroid Build Coastguard Worker   if (!receiving_) {
1154*d9f75844SAndroid Build Coastguard Worker     return false;
1155*d9f75844SAndroid Build Coastguard Worker   }
1156*d9f75844SAndroid Build Coastguard Worker 
1157*d9f75844SAndroid Build Coastguard Worker   rtp_rtcp_->IncomingRtcpPacket(rtcp_packet, rtcp_packet_length);
1158*d9f75844SAndroid Build Coastguard Worker 
1159*d9f75844SAndroid Build Coastguard Worker   int64_t rtt = 0;
1160*d9f75844SAndroid Build Coastguard Worker   rtp_rtcp_->RTT(config_.rtp.remote_ssrc, &rtt, nullptr, nullptr, nullptr);
1161*d9f75844SAndroid Build Coastguard Worker   if (rtt == 0) {
1162*d9f75844SAndroid Build Coastguard Worker     // Waiting for valid rtt.
1163*d9f75844SAndroid Build Coastguard Worker     return true;
1164*d9f75844SAndroid Build Coastguard Worker   }
1165*d9f75844SAndroid Build Coastguard Worker   uint32_t ntp_secs = 0;
1166*d9f75844SAndroid Build Coastguard Worker   uint32_t ntp_frac = 0;
1167*d9f75844SAndroid Build Coastguard Worker   uint32_t rtp_timestamp = 0;
1168*d9f75844SAndroid Build Coastguard Worker   uint32_t received_ntp_secs = 0;
1169*d9f75844SAndroid Build Coastguard Worker   uint32_t received_ntp_frac = 0;
1170*d9f75844SAndroid Build Coastguard Worker   if (rtp_rtcp_->RemoteNTP(&ntp_secs, &ntp_frac, &received_ntp_secs,
1171*d9f75844SAndroid Build Coastguard Worker                            &received_ntp_frac, &rtp_timestamp) != 0) {
1172*d9f75844SAndroid Build Coastguard Worker     // Waiting for RTCP.
1173*d9f75844SAndroid Build Coastguard Worker     return true;
1174*d9f75844SAndroid Build Coastguard Worker   }
1175*d9f75844SAndroid Build Coastguard Worker   NtpTime received_ntp(received_ntp_secs, received_ntp_frac);
1176*d9f75844SAndroid Build Coastguard Worker   int64_t time_since_received =
1177*d9f75844SAndroid Build Coastguard Worker       clock_->CurrentNtpInMilliseconds() - received_ntp.ToMs();
1178*d9f75844SAndroid Build Coastguard Worker   // Don't use old SRs to estimate time.
1179*d9f75844SAndroid Build Coastguard Worker   if (time_since_received <= 1) {
1180*d9f75844SAndroid Build Coastguard Worker     ntp_estimator_.UpdateRtcpTimestamp(
1181*d9f75844SAndroid Build Coastguard Worker         TimeDelta::Millis(rtt), NtpTime(ntp_secs, ntp_frac), rtp_timestamp);
1182*d9f75844SAndroid Build Coastguard Worker     absl::optional<int64_t> remote_to_local_clock_offset =
1183*d9f75844SAndroid Build Coastguard Worker         ntp_estimator_.EstimateRemoteToLocalClockOffset();
1184*d9f75844SAndroid Build Coastguard Worker     if (remote_to_local_clock_offset.has_value()) {
1185*d9f75844SAndroid Build Coastguard Worker       capture_clock_offset_updater_.SetRemoteToLocalClockOffset(
1186*d9f75844SAndroid Build Coastguard Worker           *remote_to_local_clock_offset);
1187*d9f75844SAndroid Build Coastguard Worker     }
1188*d9f75844SAndroid Build Coastguard Worker   }
1189*d9f75844SAndroid Build Coastguard Worker 
1190*d9f75844SAndroid Build Coastguard Worker   return true;
1191*d9f75844SAndroid Build Coastguard Worker }
1192*d9f75844SAndroid Build Coastguard Worker 
FrameContinuous(int64_t picture_id)1193*d9f75844SAndroid Build Coastguard Worker void RtpVideoStreamReceiver2::FrameContinuous(int64_t picture_id) {
1194*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
1195*d9f75844SAndroid Build Coastguard Worker   if (!nack_module_)
1196*d9f75844SAndroid Build Coastguard Worker     return;
1197*d9f75844SAndroid Build Coastguard Worker 
1198*d9f75844SAndroid Build Coastguard Worker   int seq_num = -1;
1199*d9f75844SAndroid Build Coastguard Worker   auto seq_num_it = last_seq_num_for_pic_id_.find(picture_id);
1200*d9f75844SAndroid Build Coastguard Worker   if (seq_num_it != last_seq_num_for_pic_id_.end())
1201*d9f75844SAndroid Build Coastguard Worker     seq_num = seq_num_it->second;
1202*d9f75844SAndroid Build Coastguard Worker   if (seq_num != -1)
1203*d9f75844SAndroid Build Coastguard Worker     nack_module_->ClearUpTo(seq_num);
1204*d9f75844SAndroid Build Coastguard Worker }
1205*d9f75844SAndroid Build Coastguard Worker 
FrameDecoded(int64_t picture_id)1206*d9f75844SAndroid Build Coastguard Worker void RtpVideoStreamReceiver2::FrameDecoded(int64_t picture_id) {
1207*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
1208*d9f75844SAndroid Build Coastguard Worker   int seq_num = -1;
1209*d9f75844SAndroid Build Coastguard Worker   auto seq_num_it = last_seq_num_for_pic_id_.find(picture_id);
1210*d9f75844SAndroid Build Coastguard Worker   if (seq_num_it != last_seq_num_for_pic_id_.end()) {
1211*d9f75844SAndroid Build Coastguard Worker     seq_num = seq_num_it->second;
1212*d9f75844SAndroid Build Coastguard Worker     last_seq_num_for_pic_id_.erase(last_seq_num_for_pic_id_.begin(),
1213*d9f75844SAndroid Build Coastguard Worker                                    ++seq_num_it);
1214*d9f75844SAndroid Build Coastguard Worker   }
1215*d9f75844SAndroid Build Coastguard Worker 
1216*d9f75844SAndroid Build Coastguard Worker   if (seq_num != -1) {
1217*d9f75844SAndroid Build Coastguard Worker     int64_t unwrapped_rtp_seq_num = rtp_seq_num_unwrapper_.Unwrap(seq_num);
1218*d9f75844SAndroid Build Coastguard Worker     packet_infos_.erase(packet_infos_.begin(),
1219*d9f75844SAndroid Build Coastguard Worker                         packet_infos_.upper_bound(unwrapped_rtp_seq_num));
1220*d9f75844SAndroid Build Coastguard Worker     packet_buffer_.ClearTo(seq_num);
1221*d9f75844SAndroid Build Coastguard Worker     reference_finder_->ClearTo(seq_num);
1222*d9f75844SAndroid Build Coastguard Worker   }
1223*d9f75844SAndroid Build Coastguard Worker }
1224*d9f75844SAndroid Build Coastguard Worker 
SignalNetworkState(NetworkState state)1225*d9f75844SAndroid Build Coastguard Worker void RtpVideoStreamReceiver2::SignalNetworkState(NetworkState state) {
1226*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&worker_task_checker_);
1227*d9f75844SAndroid Build Coastguard Worker   rtp_rtcp_->SetRTCPStatus(state == kNetworkUp ? config_.rtp.rtcp_mode
1228*d9f75844SAndroid Build Coastguard Worker                                                : RtcpMode::kOff);
1229*d9f75844SAndroid Build Coastguard Worker }
1230*d9f75844SAndroid Build Coastguard Worker 
StartReceive()1231*d9f75844SAndroid Build Coastguard Worker void RtpVideoStreamReceiver2::StartReceive() {
1232*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
1233*d9f75844SAndroid Build Coastguard Worker   receiving_ = true;
1234*d9f75844SAndroid Build Coastguard Worker }
1235*d9f75844SAndroid Build Coastguard Worker 
StopReceive()1236*d9f75844SAndroid Build Coastguard Worker void RtpVideoStreamReceiver2::StopReceive() {
1237*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
1238*d9f75844SAndroid Build Coastguard Worker   receiving_ = false;
1239*d9f75844SAndroid Build Coastguard Worker }
1240*d9f75844SAndroid Build Coastguard Worker 
InsertSpsPpsIntoTracker(uint8_t payload_type)1241*d9f75844SAndroid Build Coastguard Worker void RtpVideoStreamReceiver2::InsertSpsPpsIntoTracker(uint8_t payload_type) {
1242*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
1243*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&worker_task_checker_);
1244*d9f75844SAndroid Build Coastguard Worker 
1245*d9f75844SAndroid Build Coastguard Worker   auto codec_params_it = pt_codec_params_.find(payload_type);
1246*d9f75844SAndroid Build Coastguard Worker   if (codec_params_it == pt_codec_params_.end())
1247*d9f75844SAndroid Build Coastguard Worker     return;
1248*d9f75844SAndroid Build Coastguard Worker 
1249*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_INFO) << "Found out of band supplied codec parameters for"
1250*d9f75844SAndroid Build Coastguard Worker                       " payload type: "
1251*d9f75844SAndroid Build Coastguard Worker                    << static_cast<int>(payload_type);
1252*d9f75844SAndroid Build Coastguard Worker 
1253*d9f75844SAndroid Build Coastguard Worker   H264SpropParameterSets sprop_decoder;
1254*d9f75844SAndroid Build Coastguard Worker   auto sprop_base64_it =
1255*d9f75844SAndroid Build Coastguard Worker       codec_params_it->second.find(cricket::kH264FmtpSpropParameterSets);
1256*d9f75844SAndroid Build Coastguard Worker 
1257*d9f75844SAndroid Build Coastguard Worker   if (sprop_base64_it == codec_params_it->second.end())
1258*d9f75844SAndroid Build Coastguard Worker     return;
1259*d9f75844SAndroid Build Coastguard Worker 
1260*d9f75844SAndroid Build Coastguard Worker   if (!sprop_decoder.DecodeSprop(sprop_base64_it->second.c_str()))
1261*d9f75844SAndroid Build Coastguard Worker     return;
1262*d9f75844SAndroid Build Coastguard Worker 
1263*d9f75844SAndroid Build Coastguard Worker   tracker_.InsertSpsPpsNalus(sprop_decoder.sps_nalu(),
1264*d9f75844SAndroid Build Coastguard Worker                              sprop_decoder.pps_nalu());
1265*d9f75844SAndroid Build Coastguard Worker }
1266*d9f75844SAndroid Build Coastguard Worker 
UpdatePacketReceiveTimestamps(const RtpPacketReceived & packet,bool is_keyframe)1267*d9f75844SAndroid Build Coastguard Worker void RtpVideoStreamReceiver2::UpdatePacketReceiveTimestamps(
1268*d9f75844SAndroid Build Coastguard Worker     const RtpPacketReceived& packet,
1269*d9f75844SAndroid Build Coastguard Worker     bool is_keyframe) {
1270*d9f75844SAndroid Build Coastguard Worker   Timestamp now = clock_->CurrentTime();
1271*d9f75844SAndroid Build Coastguard Worker   if (is_keyframe ||
1272*d9f75844SAndroid Build Coastguard Worker       last_received_keyframe_rtp_timestamp_ == packet.Timestamp()) {
1273*d9f75844SAndroid Build Coastguard Worker     last_received_keyframe_rtp_timestamp_ = packet.Timestamp();
1274*d9f75844SAndroid Build Coastguard Worker     last_received_keyframe_rtp_system_time_ = now;
1275*d9f75844SAndroid Build Coastguard Worker   }
1276*d9f75844SAndroid Build Coastguard Worker   last_received_rtp_system_time_ = now;
1277*d9f75844SAndroid Build Coastguard Worker   last_received_rtp_timestamp_ = packet.Timestamp();
1278*d9f75844SAndroid Build Coastguard Worker 
1279*d9f75844SAndroid Build Coastguard Worker   // Periodically log the RTP header of incoming packets.
1280*d9f75844SAndroid Build Coastguard Worker   if (now.ms() - last_packet_log_ms_ > kPacketLogIntervalMs) {
1281*d9f75844SAndroid Build Coastguard Worker     rtc::StringBuilder ss;
1282*d9f75844SAndroid Build Coastguard Worker     ss << "Packet received on SSRC: " << packet.Ssrc()
1283*d9f75844SAndroid Build Coastguard Worker        << " with payload type: " << static_cast<int>(packet.PayloadType())
1284*d9f75844SAndroid Build Coastguard Worker        << ", timestamp: " << packet.Timestamp()
1285*d9f75844SAndroid Build Coastguard Worker        << ", sequence number: " << packet.SequenceNumber()
1286*d9f75844SAndroid Build Coastguard Worker        << ", arrival time: " << ToString(packet.arrival_time());
1287*d9f75844SAndroid Build Coastguard Worker     int32_t time_offset;
1288*d9f75844SAndroid Build Coastguard Worker     if (packet.GetExtension<TransmissionOffset>(&time_offset)) {
1289*d9f75844SAndroid Build Coastguard Worker       ss << ", toffset: " << time_offset;
1290*d9f75844SAndroid Build Coastguard Worker     }
1291*d9f75844SAndroid Build Coastguard Worker     uint32_t send_time;
1292*d9f75844SAndroid Build Coastguard Worker     if (packet.GetExtension<AbsoluteSendTime>(&send_time)) {
1293*d9f75844SAndroid Build Coastguard Worker       ss << ", abs send time: " << send_time;
1294*d9f75844SAndroid Build Coastguard Worker     }
1295*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_INFO) << ss.str();
1296*d9f75844SAndroid Build Coastguard Worker     last_packet_log_ms_ = now.ms();
1297*d9f75844SAndroid Build Coastguard Worker   }
1298*d9f75844SAndroid Build Coastguard Worker }
1299*d9f75844SAndroid Build Coastguard Worker 
1300*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
1301