blob: 64141e671c0a52b25a7f15d2e53026e852de7577 [file] [log] [blame]
Tommid3807da2020-05-22 15:36:361/*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "video/rtp_video_stream_receiver2.h"
12
13#include <algorithm>
14#include <limits>
15#include <memory>
16#include <utility>
17#include <vector>
18
19#include "absl/algorithm/container.h"
Tommid3807da2020-05-22 15:36:3620#include "absl/memory/memory.h"
21#include "absl/types/optional.h"
Danil Chapovalov5653c952021-08-10 14:57:5622#include "api/video/video_codec_type.h"
Tommid3807da2020-05-22 15:36:3623#include "media/base/media_constants.h"
24#include "modules/pacing/packet_router.h"
25#include "modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
26#include "modules/rtp_rtcp/include/receive_statistics.h"
27#include "modules/rtp_rtcp/include/rtp_cvo.h"
Tommid3807da2020-05-22 15:36:3628#include "modules/rtp_rtcp/source/create_video_rtp_depacketizer.h"
Tony Herrebe9b5762023-02-03 11:29:0429#include "modules/rtp_rtcp/source/frame_object.h"
Tommid3807da2020-05-22 15:36:3630#include "modules/rtp_rtcp/source/rtp_dependency_descriptor_extension.h"
31#include "modules/rtp_rtcp/source/rtp_format.h"
32#include "modules/rtp_rtcp/source/rtp_generic_frame_descriptor.h"
33#include "modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension.h"
34#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
35#include "modules/rtp_rtcp/source/rtp_packet_received.h"
36#include "modules/rtp_rtcp/source/rtp_rtcp_config.h"
Tommie488a872022-08-09 15:50:4537#include "modules/rtp_rtcp/source/ulpfec_receiver.h"
Tommid3807da2020-05-22 15:36:3638#include "modules/rtp_rtcp/source/video_rtp_depacketizer.h"
39#include "modules/rtp_rtcp/source/video_rtp_depacketizer_raw.h"
Tommid3807da2020-05-22 15:36:3640#include "modules/video_coding/h264_sprop_parameter_sets.h"
41#include "modules/video_coding/h264_sps_pps_tracker.h"
Markus Handell06a2bf02021-07-22 13:09:3942#include "modules/video_coding/nack_requester.h"
Tommid3807da2020-05-22 15:36:3643#include "modules/video_coding/packet_buffer.h"
44#include "rtc_base/checks.h"
Tommid3807da2020-05-22 15:36:3645#include "rtc_base/logging.h"
46#include "rtc_base/strings/string_builder.h"
Tommid3807da2020-05-22 15:36:3647#include "system_wrappers/include/metrics.h"
48#include "system_wrappers/include/ntp_time.h"
Tommid3807da2020-05-22 15:36:3649
50namespace webrtc {
51
52namespace {
53// TODO(philipel): Change kPacketBufferStartSize back to 32 in M63 see:
54// crbug.com/752886
55constexpr int kPacketBufferStartSize = 512;
56constexpr int kPacketBufferMaxSize = 2048;
57
Tommi3900f212022-08-05 14:21:5458constexpr int kMaxPacketAgeToNack = 450;
59
Jonas Orelande62c2f22022-03-29 09:04:4860int PacketBufferMaxSize(const FieldTrialsView& field_trials) {
Tommid3807da2020-05-22 15:36:3661 // The group here must be a positive power of 2, in which case that is used as
62 // size. All other values shall result in the default value being used.
63 const std::string group_name =
Jonas Oreland8ca06132022-03-14 11:52:4864 field_trials.Lookup("WebRTC-PacketBufferMaxSize");
Tommid3807da2020-05-22 15:36:3665 int packet_buffer_max_size = kPacketBufferMaxSize;
66 if (!group_name.empty() &&
67 (sscanf(group_name.c_str(), "%d", &packet_buffer_max_size) != 1 ||
68 packet_buffer_max_size <= 0 ||
69 // Verify that the number is a positive power of 2.
70 (packet_buffer_max_size & (packet_buffer_max_size - 1)) != 0)) {
71 RTC_LOG(LS_WARNING) << "Invalid packet buffer max size: " << group_name;
72 packet_buffer_max_size = kPacketBufferMaxSize;
73 }
74 return packet_buffer_max_size;
75}
76
Tomas Gunnarssonf25761d2020-06-03 20:55:3377std::unique_ptr<ModuleRtpRtcpImpl2> CreateRtpRtcpModule(
Tommid3807da2020-05-22 15:36:3678 Clock* clock,
79 ReceiveStatistics* receive_statistics,
80 Transport* outgoing_transport,
81 RtcpRttStats* rtt_stats,
82 RtcpPacketTypeCounterObserver* rtcp_packet_type_counter_observer,
83 RtcpCnameCallback* rtcp_cname_callback,
Niels Möllerbe810cba2020-12-02 13:25:0384 bool non_sender_rtt_measurement,
Brett Heberte04d0fa2022-08-09 18:25:0485 uint32_t local_ssrc,
86 RtcEventLog* rtc_event_log) {
Tomas Gunnarssonf25761d2020-06-03 20:55:3387 RtpRtcpInterface::Configuration configuration;
Tommid3807da2020-05-22 15:36:3688 configuration.clock = clock;
89 configuration.audio = false;
90 configuration.receiver_only = true;
91 configuration.receive_statistics = receive_statistics;
92 configuration.outgoing_transport = outgoing_transport;
93 configuration.rtt_stats = rtt_stats;
94 configuration.rtcp_packet_type_counter_observer =
95 rtcp_packet_type_counter_observer;
96 configuration.rtcp_cname_callback = rtcp_cname_callback;
97 configuration.local_media_ssrc = local_ssrc;
Niels Möllerbe810cba2020-12-02 13:25:0398 configuration.non_sender_rtt_measurement = non_sender_rtt_measurement;
Brett Heberte04d0fa2022-08-09 18:25:0499 configuration.event_log = rtc_event_log;
Niels Moller2accc7d2021-01-12 15:54:16100
101 std::unique_ptr<ModuleRtpRtcpImpl2> rtp_rtcp =
102 ModuleRtpRtcpImpl2::Create(configuration);
Tommid3807da2020-05-22 15:36:36103 rtp_rtcp->SetRTCPStatus(RtcpMode::kCompound);
104
105 return rtp_rtcp;
106}
107
Markus Handell06a2bf02021-07-22 13:09:39108std::unique_ptr<NackRequester> MaybeConstructNackModule(
Tommi63673fe2020-05-27 10:55:38109 TaskQueueBase* current_queue,
Markus Handell0e62f7a2021-07-20 11:32:02110 NackPeriodicProcessor* nack_periodic_processor,
Tommi3900f212022-08-05 14:21:54111 const NackConfig& nack,
Tommi63673fe2020-05-27 10:55:38112 Clock* clock,
113 NackSender* nack_sender,
Jonas Orelande02f9ee2022-03-25 11:43:14114 KeyFrameRequestSender* keyframe_request_sender,
Jonas Orelande62c2f22022-03-29 09:04:48115 const FieldTrialsView& field_trials) {
Tommi3900f212022-08-05 14:21:54116 if (nack.rtp_history_ms == 0)
Tommi63673fe2020-05-27 10:55:38117 return nullptr;
118
Philipp Hancke006206d2021-03-24 16:49:02119 // TODO(bugs.webrtc.org/12420): pass rtp_history_ms to the nack module.
Markus Handell06a2bf02021-07-22 13:09:39120 return std::make_unique<NackRequester>(current_queue, nack_periodic_processor,
121 clock, nack_sender,
Jonas Orelande02f9ee2022-03-25 11:43:14122 keyframe_request_sender, field_trials);
Tommi63673fe2020-05-27 10:55:38123}
124
Tommib69b8192022-08-12 09:03:34125std::unique_ptr<UlpfecReceiver> MaybeConstructUlpfecReceiver(
Tommi66d20c42022-08-12 13:05:17126 uint32_t remote_ssrc,
127 int red_payload_type,
128 int ulpfec_payload_type,
Tommib69b8192022-08-12 09:03:34129 RecoveredPacketReceiver* callback,
130 Clock* clock) {
Tommi66d20c42022-08-12 13:05:17131 RTC_DCHECK_GE(red_payload_type, -1);
132 RTC_DCHECK_GE(ulpfec_payload_type, -1);
133 if (red_payload_type == -1)
Tommib69b8192022-08-12 09:03:34134 return nullptr;
135
136 // TODO(tommi, brandtr): Consider including this check too once
137 // `UlpfecReceiver` has been updated to not consider both red and ulpfec
138 // payload ids.
Tommi66d20c42022-08-12 13:05:17139 // if (ulpfec_payload_type == -1)
Tommib69b8192022-08-12 09:03:34140 // return nullptr;
141
Tommi66d20c42022-08-12 13:05:17142 return std::make_unique<UlpfecReceiver>(remote_ssrc, ulpfec_payload_type,
Per K5e5d0172022-12-22 12:43:41143 callback, clock);
Tommib69b8192022-08-12 09:03:34144}
145
Tommid3807da2020-05-22 15:36:36146static const int kPacketLogIntervalMs = 10000;
Tommi63673fe2020-05-27 10:55:38147
Tommid3807da2020-05-22 15:36:36148} // namespace
149
150RtpVideoStreamReceiver2::RtcpFeedbackBuffer::RtcpFeedbackBuffer(
151 KeyFrameRequestSender* key_frame_request_sender,
152 NackSender* nack_sender,
153 LossNotificationSender* loss_notification_sender)
154 : key_frame_request_sender_(key_frame_request_sender),
155 nack_sender_(nack_sender),
156 loss_notification_sender_(loss_notification_sender),
157 request_key_frame_(false) {
158 RTC_DCHECK(key_frame_request_sender_);
159 RTC_DCHECK(nack_sender_);
160 RTC_DCHECK(loss_notification_sender_);
Tommi376cf072021-05-31 17:14:38161 packet_sequence_checker_.Detach();
Tommid3807da2020-05-22 15:36:36162}
163
164void RtpVideoStreamReceiver2::RtcpFeedbackBuffer::RequestKeyFrame() {
Tommi376cf072021-05-31 17:14:38165 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
Tommid3807da2020-05-22 15:36:36166 request_key_frame_ = true;
167}
168
169void RtpVideoStreamReceiver2::RtcpFeedbackBuffer::SendNack(
170 const std::vector<uint16_t>& sequence_numbers,
171 bool buffering_allowed) {
Tommi376cf072021-05-31 17:14:38172 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
Tommid3807da2020-05-22 15:36:36173 RTC_DCHECK(!sequence_numbers.empty());
Tommid3807da2020-05-22 15:36:36174 nack_sequence_numbers_.insert(nack_sequence_numbers_.end(),
175 sequence_numbers.cbegin(),
176 sequence_numbers.cend());
177 if (!buffering_allowed) {
178 // Note that while *buffering* is not allowed, *batching* is, meaning that
179 // previously buffered messages may be sent along with the current message.
Tommi63673fe2020-05-27 10:55:38180 SendBufferedRtcpFeedback();
Tommid3807da2020-05-22 15:36:36181 }
182}
183
184void RtpVideoStreamReceiver2::RtcpFeedbackBuffer::SendLossNotification(
185 uint16_t last_decoded_seq_num,
186 uint16_t last_received_seq_num,
187 bool decodability_flag,
188 bool buffering_allowed) {
Tommi376cf072021-05-31 17:14:38189 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
Tommid3807da2020-05-22 15:36:36190 RTC_DCHECK(buffering_allowed);
Tommid3807da2020-05-22 15:36:36191 RTC_DCHECK(!lntf_state_)
192 << "SendLossNotification() called twice in a row with no call to "
193 "SendBufferedRtcpFeedback() in between.";
194 lntf_state_ = absl::make_optional<LossNotificationState>(
195 last_decoded_seq_num, last_received_seq_num, decodability_flag);
196}
197
198void RtpVideoStreamReceiver2::RtcpFeedbackBuffer::SendBufferedRtcpFeedback() {
Tommi376cf072021-05-31 17:14:38199 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
Tommid3807da2020-05-22 15:36:36200
Tommi63673fe2020-05-27 10:55:38201 bool request_key_frame = false;
202 std::vector<uint16_t> nack_sequence_numbers;
203 absl::optional<LossNotificationState> lntf_state;
Tommid3807da2020-05-22 15:36:36204
Tommi63673fe2020-05-27 10:55:38205 std::swap(request_key_frame, request_key_frame_);
206 std::swap(nack_sequence_numbers, nack_sequence_numbers_);
207 std::swap(lntf_state, lntf_state_);
Tommid3807da2020-05-22 15:36:36208
Tommi63673fe2020-05-27 10:55:38209 if (lntf_state) {
Tommid3807da2020-05-22 15:36:36210 // If either a NACK or a key frame request is sent, we should buffer
211 // the LNTF and wait for them (NACK or key frame request) to trigger
212 // the compound feedback message.
213 // Otherwise, the LNTF should be sent out immediately.
214 const bool buffering_allowed =
Tommi63673fe2020-05-27 10:55:38215 request_key_frame || !nack_sequence_numbers.empty();
Tommid3807da2020-05-22 15:36:36216
217 loss_notification_sender_->SendLossNotification(
Tommi63673fe2020-05-27 10:55:38218 lntf_state->last_decoded_seq_num, lntf_state->last_received_seq_num,
219 lntf_state->decodability_flag, buffering_allowed);
Tommid3807da2020-05-22 15:36:36220 }
221
Tommi63673fe2020-05-27 10:55:38222 if (request_key_frame) {
Tommid3807da2020-05-22 15:36:36223 key_frame_request_sender_->RequestKeyFrame();
Tommi63673fe2020-05-27 10:55:38224 } else if (!nack_sequence_numbers.empty()) {
225 nack_sender_->SendNack(nack_sequence_numbers, true);
Tommid3807da2020-05-22 15:36:36226 }
227}
228
Tommie644a4b2022-08-03 14:13:53229void RtpVideoStreamReceiver2::RtcpFeedbackBuffer::ClearLossNotificationState() {
230 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
231 lntf_state_.reset();
232}
233
Tommid3807da2020-05-22 15:36:36234RtpVideoStreamReceiver2::RtpVideoStreamReceiver2(
Tommi63673fe2020-05-27 10:55:38235 TaskQueueBase* current_queue,
Tommid3807da2020-05-22 15:36:36236 Clock* clock,
237 Transport* transport,
238 RtcpRttStats* rtt_stats,
239 PacketRouter* packet_router,
Tommif6f45432022-05-20 13:21:20240 const VideoReceiveStreamInterface::Config* config,
Tommid3807da2020-05-22 15:36:36241 ReceiveStatistics* rtp_receive_statistics,
242 RtcpPacketTypeCounterObserver* rtcp_packet_type_counter_observer,
243 RtcpCnameCallback* rtcp_cname_callback,
Markus Handell0e62f7a2021-07-20 11:32:02244 NackPeriodicProcessor* nack_periodic_processor,
philipel6a671502021-03-22 13:17:09245 OnCompleteFrameCallback* complete_frame_callback,
Tommid3807da2020-05-22 15:36:36246 rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor,
Jonas Oreland8ca06132022-03-14 11:52:48247 rtc::scoped_refptr<FrameTransformerInterface> frame_transformer,
Brett Heberte04d0fa2022-08-09 18:25:04248 const FieldTrialsView& field_trials,
249 RtcEventLog* event_log)
Jonas Oreland8ca06132022-03-14 11:52:48250 : field_trials_(field_trials),
Tommi3900f212022-08-05 14:21:54251 worker_queue_(current_queue),
Jonas Oreland8ca06132022-03-14 11:52:48252 clock_(clock),
Tommid3807da2020-05-22 15:36:36253 config_(*config),
254 packet_router_(packet_router),
Tommid3807da2020-05-22 15:36:36255 ntp_estimator_(clock),
Tommid3807da2020-05-22 15:36:36256 forced_playout_delay_max_ms_("max_ms", absl::nullopt),
257 forced_playout_delay_min_ms_("min_ms", absl::nullopt),
258 rtp_receive_statistics_(rtp_receive_statistics),
Tommi66d20c42022-08-12 13:05:17259 ulpfec_receiver_(
260 MaybeConstructUlpfecReceiver(config->rtp.remote_ssrc,
261 config->rtp.red_payload_type,
262 config->rtp.ulpfec_payload_type,
Tommi66d20c42022-08-12 13:05:17263 this,
264 clock_)),
Tommi1c5f3172022-08-13 08:43:59265 red_payload_type_(config_.rtp.red_payload_type),
Tommi185f10c2022-08-02 09:51:20266 packet_sink_(config->rtp.packet_sink_),
Tommid3807da2020-05-22 15:36:36267 receiving_(false),
268 last_packet_log_ms_(-1),
Niels Möllerbe810cba2020-12-02 13:25:03269 rtp_rtcp_(CreateRtpRtcpModule(
270 clock,
271 rtp_receive_statistics_,
272 transport,
273 rtt_stats,
274 rtcp_packet_type_counter_observer,
275 rtcp_cname_callback,
276 config_.rtp.rtcp_xr.receiver_reference_time_report,
Brett Heberte04d0fa2022-08-09 18:25:04277 config_.rtp.local_ssrc,
278 event_log)),
Tommi3900f212022-08-05 14:21:54279 nack_periodic_processor_(nack_periodic_processor),
Tommid3807da2020-05-22 15:36:36280 complete_frame_callback_(complete_frame_callback),
Nico Grunbauma36f10b2021-12-09 04:59:31281 keyframe_request_method_(config_.rtp.keyframe_method),
Artem Titovab30d722021-07-27 14:22:11282 // TODO(bugs.webrtc.org/10336): Let `rtcp_feedback_buffer_` communicate
283 // directly with `rtp_rtcp_`.
philipelb9813942022-07-05 09:31:36284 rtcp_feedback_buffer_(this, this, this),
Tommi63673fe2020-05-27 10:55:38285 nack_module_(MaybeConstructNackModule(current_queue,
Markus Handell0e62f7a2021-07-20 11:32:02286 nack_periodic_processor,
Tommi3900f212022-08-05 14:21:54287 config_.rtp.nack,
Tommi63673fe2020-05-27 10:55:38288 clock_,
289 &rtcp_feedback_buffer_,
Jonas Orelande02f9ee2022-03-25 11:43:14290 &rtcp_feedback_buffer_,
291 field_trials_)),
Jonas Oreland8ca06132022-03-14 11:52:48292 packet_buffer_(kPacketBufferStartSize,
293 PacketBufferMaxSize(field_trials_)),
philipel21820962021-05-25 13:35:57294 reference_finder_(std::make_unique<RtpFrameReferenceFinder>()),
Tommid3807da2020-05-22 15:36:36295 has_received_frame_(false),
Artem Titarenko3c2359c2022-05-05 10:29:51296 frames_decryptable_(false),
Minyue Li63b30952021-05-19 12:38:25297 absolute_capture_time_interpolator_(clock) {
Tommi376cf072021-05-31 17:14:38298 packet_sequence_checker_.Detach();
Tommid3807da2020-05-22 15:36:36299 constexpr bool remb_candidate = true;
300 if (packet_router_)
301 packet_router_->AddReceiveRtpModule(rtp_rtcp_.get(), remb_candidate);
302
303 RTC_DCHECK(config_.rtp.rtcp_mode != RtcpMode::kOff)
304 << "A stream should not be configured with RTCP disabled. This value is "
305 "reserved for internal usage.";
306 // TODO(pbos): What's an appropriate local_ssrc for receive-only streams?
307 RTC_DCHECK(config_.rtp.local_ssrc != 0);
308 RTC_DCHECK(config_.rtp.remote_ssrc != config_.rtp.local_ssrc);
309
310 rtp_rtcp_->SetRTCPStatus(config_.rtp.rtcp_mode);
311 rtp_rtcp_->SetRemoteSSRC(config_.rtp.remote_ssrc);
312
Niels Möller761072f2022-07-20 12:06:05313 if (config_.rtp.nack.rtp_history_ms > 0) {
Niels Möller761072f2022-07-20 12:06:05314 rtp_receive_statistics_->SetMaxReorderingThreshold(config_.rtp.remote_ssrc,
315 kMaxPacketAgeToNack);
Tommid3807da2020-05-22 15:36:36316 }
Tommid3807da2020-05-22 15:36:36317 ParseFieldTrial(
318 {&forced_playout_delay_max_ms_, &forced_playout_delay_min_ms_},
Jonas Oreland8ca06132022-03-14 11:52:48319 field_trials_.Lookup("WebRTC-ForcePlayoutDelay"));
Tommid3807da2020-05-22 15:36:36320
Tommid3807da2020-05-22 15:36:36321 if (config_.rtp.lntf.enabled) {
322 loss_notification_controller_ =
323 std::make_unique<LossNotificationController>(&rtcp_feedback_buffer_,
324 &rtcp_feedback_buffer_);
325 }
326
Tommid3807da2020-05-22 15:36:36327 // Only construct the encrypted receiver if frame encryption is enabled.
328 if (config_.crypto_options.sframe.require_frame_encryption) {
329 buffered_frame_decryptor_ =
Jonas Oreland8ca06132022-03-14 11:52:48330 std::make_unique<BufferedFrameDecryptor>(this, this, field_trials_);
Tommid3807da2020-05-22 15:36:36331 if (frame_decryptor != nullptr) {
332 buffered_frame_decryptor_->SetFrameDecryptor(std::move(frame_decryptor));
333 }
334 }
335
336 if (frame_transformer) {
Tomas Gunnarssonc1d58912021-04-22 17:21:43337 frame_transformer_delegate_ =
338 rtc::make_ref_counted<RtpVideoStreamReceiverFrameTransformerDelegate>(
Tony Herre9d677f42023-07-11 12:41:06339 this, clock_, std::move(frame_transformer), rtc::Thread::Current(),
Tomas Gunnarssonc1d58912021-04-22 17:21:43340 config_.rtp.remote_ssrc);
Tommid3807da2020-05-22 15:36:36341 frame_transformer_delegate_->Init();
342 }
343}
344
345RtpVideoStreamReceiver2::~RtpVideoStreamReceiver2() {
Tommid3807da2020-05-22 15:36:36346 if (packet_router_)
347 packet_router_->RemoveReceiveRtpModule(rtp_rtcp_.get());
Tommi7fbab872022-08-10 05:45:43348 ulpfec_receiver_.reset();
Tommid3807da2020-05-22 15:36:36349 if (frame_transformer_delegate_)
350 frame_transformer_delegate_->Reset();
351}
352
353void RtpVideoStreamReceiver2::AddReceiveCodec(
Niels Möller5401bad2020-08-11 10:17:42354 uint8_t payload_type,
Danil Chapovalov5653c952021-08-10 14:57:56355 VideoCodecType video_codec,
Tommid3807da2020-05-22 15:36:36356 const std::map<std::string, std::string>& codec_params,
357 bool raw_payload) {
Tommi376cf072021-05-31 17:14:38358 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
Tommi96c1a9b2022-09-29 10:24:02359 if (codec_params.count(cricket::kH264FmtpSpsPpsIdrInKeyframe) > 0 ||
Erik Språngeb3307f2022-08-22 09:06:06360 field_trials_.IsEnabled("WebRTC-SpsPpsIdrIsH264Keyframe")) {
Andrew Johnsonf288f5b2020-09-19 05:35:59361 packet_buffer_.ForceSpsPpsIdrIsH264Keyframe();
362 }
Tommid3807da2020-05-22 15:36:36363 payload_type_map_.emplace(
Danil Chapovalov5653c952021-08-10 14:57:56364 payload_type, raw_payload ? std::make_unique<VideoRtpDepacketizerRaw>()
365 : CreateVideoRtpDepacketizer(video_codec));
Niels Möller5401bad2020-08-11 10:17:42366 pt_codec_params_.emplace(payload_type, codec_params);
Tommid3807da2020-05-22 15:36:36367}
368
Tommi96c1a9b2022-09-29 10:24:02369void RtpVideoStreamReceiver2::RemoveReceiveCodec(uint8_t payload_type) {
370 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
371 auto codec_params_it = pt_codec_params_.find(payload_type);
372 if (codec_params_it == pt_codec_params_.end())
373 return;
374
375 const bool sps_pps_idr_in_key_frame =
376 codec_params_it->second.count(cricket::kH264FmtpSpsPpsIdrInKeyframe) > 0;
377
378 pt_codec_params_.erase(codec_params_it);
379 payload_type_map_.erase(payload_type);
380
381 if (sps_pps_idr_in_key_frame) {
382 bool reset_setting = true;
383 for (auto& [unused, codec_params] : pt_codec_params_) {
384 if (codec_params.count(cricket::kH264FmtpSpsPpsIdrInKeyframe) > 0) {
385 reset_setting = false;
386 break;
387 }
388 }
389
390 if (reset_setting) {
391 packet_buffer_.ResetSpsPpsIdrIsH264Keyframe();
392 }
393 }
394}
395
396void RtpVideoStreamReceiver2::RemoveReceiveCodecs() {
397 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
398
399 pt_codec_params_.clear();
400 payload_type_map_.clear();
401 packet_buffer_.ResetSpsPpsIdrIsH264Keyframe();
402}
403
Tommid3807da2020-05-22 15:36:36404absl::optional<Syncable::Info> RtpVideoStreamReceiver2::GetSyncInfo() const {
Tommi376cf072021-05-31 17:14:38405 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
Tommid3807da2020-05-22 15:36:36406 Syncable::Info info;
Danil Chapovalov9f397212023-02-27 18:49:31407 absl::optional<RtpRtcpInterface::SenderReportStats> last_sr =
408 rtp_rtcp_->GetSenderReportStats();
409 if (!last_sr.has_value()) {
Tommid3807da2020-05-22 15:36:36410 return absl::nullopt;
411 }
Danil Chapovalov9f397212023-02-27 18:49:31412 info.capture_time_ntp_secs = last_sr->last_remote_timestamp.seconds();
413 info.capture_time_ntp_frac = last_sr->last_remote_timestamp.fractions();
414 info.capture_time_source_clock = last_sr->last_remote_rtp_timestamp;
Tommi63673fe2020-05-27 10:55:38415
philipelce423ce2021-04-12 11:42:03416 if (!last_received_rtp_timestamp_ || !last_received_rtp_system_time_) {
Tommi63673fe2020-05-27 10:55:38417 return absl::nullopt;
Tommid3807da2020-05-22 15:36:36418 }
Tommi63673fe2020-05-27 10:55:38419 info.latest_received_capture_timestamp = *last_received_rtp_timestamp_;
philipelce423ce2021-04-12 11:42:03420 info.latest_receive_time_ms = last_received_rtp_system_time_->ms();
Tommid3807da2020-05-22 15:36:36421
422 // Leaves info.current_delay_ms uninitialized.
423 return info;
424}
425
426RtpVideoStreamReceiver2::ParseGenericDependenciesResult
427RtpVideoStreamReceiver2::ParseGenericDependenciesExtension(
428 const RtpPacketReceived& rtp_packet,
429 RTPVideoHeader* video_header) {
Danil Chapovalov6e7c2682022-07-25 13:58:28430 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
Tommid3807da2020-05-22 15:36:36431 if (rtp_packet.HasExtension<RtpDependencyDescriptorExtension>()) {
432 webrtc::DependencyDescriptor dependency_descriptor;
433 if (!rtp_packet.GetExtension<RtpDependencyDescriptorExtension>(
434 video_structure_.get(), &dependency_descriptor)) {
435 // Descriptor is there, but failed to parse. Either it is invalid,
436 // or too old packet (after relevant video_structure_ changed),
437 // or too new packet (before relevant video_structure_ arrived).
438 // Drop such packet to be on the safe side.
439 // TODO(bugs.webrtc.org/10342): Stash too new packet.
philipelc4ea5ae2023-01-20 12:13:01440 Timestamp now = clock_->CurrentTime();
441 if (now - last_logged_failed_to_parse_dd_ > TimeDelta::Seconds(1)) {
442 last_logged_failed_to_parse_dd_ = now;
443 RTC_LOG(LS_WARNING) << "ssrc: " << rtp_packet.Ssrc()
444 << " Failed to parse dependency descriptor.";
445 }
Tommid3807da2020-05-22 15:36:36446 return kDropPacket;
447 }
448 if (dependency_descriptor.attached_structure != nullptr &&
449 !dependency_descriptor.first_packet_in_frame) {
450 RTC_LOG(LS_WARNING) << "ssrc: " << rtp_packet.Ssrc()
451 << "Invalid dependency descriptor: structure "
452 "attached to non first packet of a frame.";
453 return kDropPacket;
454 }
455 video_header->is_first_packet_in_frame =
456 dependency_descriptor.first_packet_in_frame;
457 video_header->is_last_packet_in_frame =
458 dependency_descriptor.last_packet_in_frame;
459
460 int64_t frame_id =
461 frame_id_unwrapper_.Unwrap(dependency_descriptor.frame_number);
462 auto& generic_descriptor_info = video_header->generic.emplace();
463 generic_descriptor_info.frame_id = frame_id;
464 generic_descriptor_info.spatial_index =
465 dependency_descriptor.frame_dependencies.spatial_id;
466 generic_descriptor_info.temporal_index =
467 dependency_descriptor.frame_dependencies.temporal_id;
468 for (int fdiff : dependency_descriptor.frame_dependencies.frame_diffs) {
469 generic_descriptor_info.dependencies.push_back(frame_id - fdiff);
470 }
471 generic_descriptor_info.decode_target_indications =
472 dependency_descriptor.frame_dependencies.decode_target_indications;
473 if (dependency_descriptor.resolution) {
474 video_header->width = dependency_descriptor.resolution->Width();
475 video_header->height = dependency_descriptor.resolution->Height();
476 }
477
478 // FrameDependencyStructure is sent in dependency descriptor of the first
479 // packet of a key frame and required for parsed dependency descriptor in
480 // all the following packets until next key frame.
481 // Save it if there is a (potentially) new structure.
482 if (dependency_descriptor.attached_structure) {
483 RTC_DCHECK(dependency_descriptor.first_packet_in_frame);
484 if (video_structure_frame_id_ > frame_id) {
485 RTC_LOG(LS_WARNING)
486 << "Arrived key frame with id " << frame_id << " and structure id "
487 << dependency_descriptor.attached_structure->structure_id
488 << " is older than the latest received key frame with id "
489 << *video_structure_frame_id_ << " and structure id "
490 << video_structure_->structure_id;
491 return kDropPacket;
492 }
493 video_structure_ = std::move(dependency_descriptor.attached_structure);
494 video_structure_frame_id_ = frame_id;
495 video_header->frame_type = VideoFrameType::kVideoFrameKey;
496 } else {
497 video_header->frame_type = VideoFrameType::kVideoFrameDelta;
498 }
499 return kHasGenericDescriptor;
500 }
501
502 RtpGenericFrameDescriptor generic_frame_descriptor;
503 if (!rtp_packet.GetExtension<RtpGenericFrameDescriptorExtension00>(
504 &generic_frame_descriptor)) {
505 return kNoGenericDescriptor;
506 }
507
508 video_header->is_first_packet_in_frame =
509 generic_frame_descriptor.FirstPacketInSubFrame();
510 video_header->is_last_packet_in_frame =
511 generic_frame_descriptor.LastPacketInSubFrame();
512
513 if (generic_frame_descriptor.FirstPacketInSubFrame()) {
514 video_header->frame_type =
515 generic_frame_descriptor.FrameDependenciesDiffs().empty()
516 ? VideoFrameType::kVideoFrameKey
517 : VideoFrameType::kVideoFrameDelta;
518
519 auto& generic_descriptor_info = video_header->generic.emplace();
520 int64_t frame_id =
521 frame_id_unwrapper_.Unwrap(generic_frame_descriptor.FrameId());
522 generic_descriptor_info.frame_id = frame_id;
523 generic_descriptor_info.spatial_index =
524 generic_frame_descriptor.SpatialLayer();
525 generic_descriptor_info.temporal_index =
526 generic_frame_descriptor.TemporalLayer();
527 for (uint16_t fdiff : generic_frame_descriptor.FrameDependenciesDiffs()) {
528 generic_descriptor_info.dependencies.push_back(frame_id - fdiff);
529 }
530 }
531 video_header->width = generic_frame_descriptor.Width();
532 video_header->height = generic_frame_descriptor.Height();
533 return kHasGenericDescriptor;
534}
535
536void RtpVideoStreamReceiver2::OnReceivedPayloadData(
537 rtc::CopyOnWriteBuffer codec_payload,
538 const RtpPacketReceived& rtp_packet,
539 const RTPVideoHeader& video) {
Tommi376cf072021-05-31 17:14:38540 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
philipel9599b3c2021-05-11 09:30:52541
542 auto packet =
543 std::make_unique<video_coding::PacketBuffer::Packet>(rtp_packet, video);
544
545 int64_t unwrapped_rtp_seq_num =
546 rtp_seq_num_unwrapper_.Unwrap(rtp_packet.SequenceNumber());
Alessio Bazzicaa1d03562022-09-19 16:05:29547
548 RtpPacketInfo& packet_info =
philipel9599b3c2021-05-11 09:30:52549 packet_infos_
Alessio Bazzicaa1d03562022-09-19 16:05:29550 .emplace(unwrapped_rtp_seq_num,
551 RtpPacketInfo(rtp_packet.Ssrc(), rtp_packet.Csrcs(),
552 rtp_packet.Timestamp(),
553 /*receive_time_ms=*/clock_->CurrentTime()))
philipel9599b3c2021-05-11 09:30:52554 .first->second;
Tommid3807da2020-05-22 15:36:36555
556 // Try to extrapolate absolute capture time if it is missing.
philipel9599b3c2021-05-11 09:30:52557 packet_info.set_absolute_capture_time(
Minyue Li63b30952021-05-19 12:38:25558 absolute_capture_time_interpolator_.OnReceivePacket(
559 AbsoluteCaptureTimeInterpolator::GetSource(packet_info.ssrc(),
560 packet_info.csrcs()),
philipel9599b3c2021-05-11 09:30:52561 packet_info.rtp_timestamp(),
Tommid3807da2020-05-22 15:36:36562 // Assume frequency is the same one for all video frames.
Alessio Bazzicaa1d03562022-09-19 16:05:29563 kVideoPayloadTypeFrequency,
564 rtp_packet.GetExtension<AbsoluteCaptureTimeExtension>()));
Tommid3807da2020-05-22 15:36:36565
566 RTPVideoHeader& video_header = packet->video_header;
567 video_header.rotation = kVideoRotation_0;
568 video_header.content_type = VideoContentType::UNSPECIFIED;
569 video_header.video_timing.flags = VideoSendTiming::kInvalid;
570 video_header.is_last_packet_in_frame |= rtp_packet.Marker();
Tommid3807da2020-05-22 15:36:36571
Tommid3807da2020-05-22 15:36:36572 rtp_packet.GetExtension<VideoOrientation>(&video_header.rotation);
573 rtp_packet.GetExtension<VideoContentTypeExtension>(
574 &video_header.content_type);
575 rtp_packet.GetExtension<VideoTimingExtension>(&video_header.video_timing);
576 if (forced_playout_delay_max_ms_ && forced_playout_delay_min_ms_) {
577 video_header.playout_delay.max_ms = *forced_playout_delay_max_ms_;
578 video_header.playout_delay.min_ms = *forced_playout_delay_min_ms_;
579 } else {
580 rtp_packet.GetExtension<PlayoutDelayLimits>(&video_header.playout_delay);
581 }
Tommid3807da2020-05-22 15:36:36582
583 ParseGenericDependenciesResult generic_descriptor_state =
584 ParseGenericDependenciesExtension(rtp_packet, &video_header);
philipelce423ce2021-04-12 11:42:03585
586 if (!rtp_packet.recovered()) {
587 UpdatePacketReceiveTimestamps(
588 rtp_packet, video_header.frame_type == VideoFrameType::kVideoFrameKey);
589 }
590
philipel17093412022-06-13 11:14:43591 if (generic_descriptor_state == kDropPacket) {
592 Timestamp now = clock_->CurrentTime();
593 if (video_structure_ == nullptr &&
594 next_keyframe_request_for_missing_video_structure_ < now) {
595 // No video structure received yet, most likely part of the initial
596 // keyframe was lost.
597 RequestKeyFrame();
598 next_keyframe_request_for_missing_video_structure_ =
599 now + TimeDelta::Seconds(1);
600 }
Tommid3807da2020-05-22 15:36:36601 return;
philipel17093412022-06-13 11:14:43602 }
Tommid3807da2020-05-22 15:36:36603
604 // Color space should only be transmitted in the last packet of a frame,
605 // therefore, neglect it otherwise so that last_color_space_ is not reset by
606 // mistake.
607 if (video_header.is_last_packet_in_frame) {
608 video_header.color_space = rtp_packet.GetExtension<ColorSpaceExtension>();
609 if (video_header.color_space ||
610 video_header.frame_type == VideoFrameType::kVideoFrameKey) {
611 // Store color space since it's only transmitted when changed or for key
612 // frames. Color space will be cleared if a key frame is transmitted
613 // without color space information.
614 last_color_space_ = video_header.color_space;
615 } else if (last_color_space_) {
616 video_header.color_space = last_color_space_;
617 }
618 }
Jeremy Leconteb258c562021-03-18 12:50:42619 video_header.video_frame_tracking_id =
620 rtp_packet.GetExtension<VideoFrameTrackingIdExtension>();
Tommid3807da2020-05-22 15:36:36621
622 if (loss_notification_controller_) {
623 if (rtp_packet.recovered()) {
624 // TODO(bugs.webrtc.org/10336): Implement support for reordering.
625 RTC_LOG(LS_INFO)
626 << "LossNotificationController does not support reordering.";
627 } else if (generic_descriptor_state == kNoGenericDescriptor) {
628 RTC_LOG(LS_WARNING) << "LossNotificationController requires generic "
629 "frame descriptor, but it is missing.";
630 } else {
631 if (video_header.is_first_packet_in_frame) {
632 RTC_DCHECK(video_header.generic);
633 LossNotificationController::FrameDetails frame;
634 frame.is_keyframe =
635 video_header.frame_type == VideoFrameType::kVideoFrameKey;
636 frame.frame_id = video_header.generic->frame_id;
637 frame.frame_dependencies = video_header.generic->dependencies;
638 loss_notification_controller_->OnReceivedPacket(
639 rtp_packet.SequenceNumber(), &frame);
640 } else {
641 loss_notification_controller_->OnReceivedPacket(
642 rtp_packet.SequenceNumber(), nullptr);
643 }
644 }
645 }
646
647 if (nack_module_) {
648 const bool is_keyframe =
649 video_header.is_first_packet_in_frame &&
650 video_header.frame_type == VideoFrameType::kVideoFrameKey;
651
652 packet->times_nacked = nack_module_->OnReceivedPacket(
653 rtp_packet.SequenceNumber(), is_keyframe, rtp_packet.recovered());
654 } else {
655 packet->times_nacked = -1;
656 }
657
658 if (codec_payload.size() == 0) {
659 NotifyReceiverOfEmptyPacket(packet->seq_num);
660 rtcp_feedback_buffer_.SendBufferedRtcpFeedback();
661 return;
662 }
663
664 if (packet->codec() == kVideoCodecH264) {
665 // Only when we start to receive packets will we know what payload type
666 // that will be used. When we know the payload type insert the correct
667 // sps/pps into the tracker.
668 if (packet->payload_type != last_payload_type_) {
669 last_payload_type_ = packet->payload_type;
670 InsertSpsPpsIntoTracker(packet->payload_type);
671 }
672
673 video_coding::H264SpsPpsTracker::FixedBitstream fixed =
674 tracker_.CopyAndFixBitstream(
675 rtc::MakeArrayView(codec_payload.cdata(), codec_payload.size()),
676 &packet->video_header);
677
678 switch (fixed.action) {
679 case video_coding::H264SpsPpsTracker::kRequestKeyframe:
680 rtcp_feedback_buffer_.RequestKeyFrame();
681 rtcp_feedback_buffer_.SendBufferedRtcpFeedback();
Danil Chapovalov46cc32d2022-01-17 13:41:13682 [[fallthrough]];
Tommid3807da2020-05-22 15:36:36683 case video_coding::H264SpsPpsTracker::kDrop:
684 return;
685 case video_coding::H264SpsPpsTracker::kInsert:
686 packet->video_payload = std::move(fixed.bitstream);
687 break;
688 }
689
690 } else {
691 packet->video_payload = std::move(codec_payload);
692 }
693
694 rtcp_feedback_buffer_.SendBufferedRtcpFeedback();
695 frame_counter_.Add(packet->timestamp);
696 OnInsertedPacket(packet_buffer_.InsertPacket(std::move(packet)));
697}
698
Per K5e5d0172022-12-22 12:43:41699void RtpVideoStreamReceiver2::OnRecoveredPacket(
700 const RtpPacketReceived& packet) {
Tommi376cf072021-05-31 17:14:38701 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
Tommi1c5f3172022-08-13 08:43:59702 if (packet.PayloadType() == red_payload_type_) {
Tommid3807da2020-05-22 15:36:36703 RTC_LOG(LS_WARNING) << "Discarding recovered packet with RED encapsulation";
704 return;
705 }
Tommid3807da2020-05-22 15:36:36706 ReceivePacket(packet);
707}
708
709// This method handles both regular RTP packets and packets recovered
710// via FlexFEC.
711void RtpVideoStreamReceiver2::OnRtpPacket(const RtpPacketReceived& packet) {
Tommi376cf072021-05-31 17:14:38712 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
Tommid3807da2020-05-22 15:36:36713
Tommi376cf072021-05-31 17:14:38714 if (!receiving_)
Tommid3807da2020-05-22 15:36:36715 return;
Tommid3807da2020-05-22 15:36:36716
Tommid3807da2020-05-22 15:36:36717 ReceivePacket(packet);
718
719 // Update receive statistics after ReceivePacket.
720 // Receive statistics will be reset if the payload type changes (make sure
721 // that the first packet is included in the stats).
722 if (!packet.recovered()) {
723 rtp_receive_statistics_->OnRtpPacket(packet);
724 }
725
Tommi185f10c2022-08-02 09:51:20726 if (packet_sink_) {
727 packet_sink_->OnRtpPacket(packet);
Tommid3807da2020-05-22 15:36:36728 }
729}
730
731void RtpVideoStreamReceiver2::RequestKeyFrame() {
Tommi63673fe2020-05-27 10:55:38732 RTC_DCHECK_RUN_ON(&worker_task_checker_);
Tommid3807da2020-05-22 15:36:36733 // TODO(bugs.webrtc.org/10336): Allow the sender to ignore key frame requests
734 // issued by anything other than the LossNotificationController if it (the
735 // sender) is relying on LNTF alone.
philipel27b35a72022-07-05 07:59:55736 if (keyframe_request_method_ == KeyFrameReqMethod::kPliRtcp) {
Tommid3807da2020-05-22 15:36:36737 rtp_rtcp_->SendPictureLossIndication();
Nico Grunbauma36f10b2021-12-09 04:59:31738 } else if (keyframe_request_method_ == KeyFrameReqMethod::kFirRtcp) {
739 rtp_rtcp_->SendFullIntraRequest();
Tommid3807da2020-05-22 15:36:36740 }
741}
742
philipelb9813942022-07-05 09:31:36743void RtpVideoStreamReceiver2::SendNack(
744 const std::vector<uint16_t>& sequence_numbers,
745 bool /*buffering_allowed*/) {
746 rtp_rtcp_->SendNack(sequence_numbers);
747}
748
Tommid3807da2020-05-22 15:36:36749void RtpVideoStreamReceiver2::SendLossNotification(
750 uint16_t last_decoded_seq_num,
751 uint16_t last_received_seq_num,
752 bool decodability_flag,
753 bool buffering_allowed) {
754 RTC_DCHECK(config_.rtp.lntf.enabled);
755 rtp_rtcp_->SendLossNotification(last_decoded_seq_num, last_received_seq_num,
756 decodability_flag, buffering_allowed);
757}
758
Tommid3807da2020-05-22 15:36:36759bool RtpVideoStreamReceiver2::IsDecryptable() const {
Tommi63673fe2020-05-27 10:55:38760 RTC_DCHECK_RUN_ON(&worker_task_checker_);
761 return frames_decryptable_;
Tommid3807da2020-05-22 15:36:36762}
763
764void RtpVideoStreamReceiver2::OnInsertedPacket(
765 video_coding::PacketBuffer::InsertResult result) {
Danil Chapovalov6e7c2682022-07-25 13:58:28766 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
Tommi31b56492021-06-01 07:50:26767 RTC_DCHECK_RUN_ON(&worker_task_checker_);
Tommid3807da2020-05-22 15:36:36768 video_coding::PacketBuffer::Packet* first_packet = nullptr;
769 int max_nack_count;
770 int64_t min_recv_time;
771 int64_t max_recv_time;
772 std::vector<rtc::ArrayView<const uint8_t>> payloads;
773 RtpPacketInfos::vector_type packet_infos;
774
775 bool frame_boundary = true;
776 for (auto& packet : result.packets) {
777 // PacketBuffer promisses frame boundaries are correctly set on each
778 // packet. Document that assumption with the DCHECKs.
779 RTC_DCHECK_EQ(frame_boundary, packet->is_first_packet_in_frame());
philipel9599b3c2021-05-11 09:30:52780 int64_t unwrapped_rtp_seq_num =
781 rtp_seq_num_unwrapper_.Unwrap(packet->seq_num);
Tommi96c1a9b2022-09-29 10:24:02782 RTC_DCHECK_GT(packet_infos_.count(unwrapped_rtp_seq_num), 0);
philipel9599b3c2021-05-11 09:30:52783 RtpPacketInfo& packet_info = packet_infos_[unwrapped_rtp_seq_num];
Tommid3807da2020-05-22 15:36:36784 if (packet->is_first_packet_in_frame()) {
785 first_packet = packet.get();
786 max_nack_count = packet->times_nacked;
philipel9599b3c2021-05-11 09:30:52787 min_recv_time = packet_info.receive_time().ms();
788 max_recv_time = packet_info.receive_time().ms();
Tommid3807da2020-05-22 15:36:36789 } else {
790 max_nack_count = std::max(max_nack_count, packet->times_nacked);
philipel9599b3c2021-05-11 09:30:52791 min_recv_time = std::min(min_recv_time, packet_info.receive_time().ms());
792 max_recv_time = std::max(max_recv_time, packet_info.receive_time().ms());
Tommid3807da2020-05-22 15:36:36793 }
794 payloads.emplace_back(packet->video_payload);
philipel9599b3c2021-05-11 09:30:52795 packet_infos.push_back(packet_info);
Tommid3807da2020-05-22 15:36:36796
797 frame_boundary = packet->is_last_packet_in_frame();
798 if (packet->is_last_packet_in_frame()) {
799 auto depacketizer_it = payload_type_map_.find(first_packet->payload_type);
800 RTC_CHECK(depacketizer_it != payload_type_map_.end());
801
802 rtc::scoped_refptr<EncodedImageBuffer> bitstream =
803 depacketizer_it->second->AssembleFrame(payloads);
804 if (!bitstream) {
805 // Failed to assemble a frame. Discard and continue.
806 continue;
807 }
808
809 const video_coding::PacketBuffer::Packet& last_packet = *packet;
philipelca188092021-03-23 11:00:49810 OnAssembledFrame(std::make_unique<RtpFrameObject>(
philipel7c7885c2021-03-12 13:33:46811 first_packet->seq_num, //
812 last_packet.seq_num, //
813 last_packet.marker_bit, //
814 max_nack_count, //
815 min_recv_time, //
816 max_recv_time, //
817 first_packet->timestamp, //
818 ntp_estimator_.Estimate(first_packet->timestamp), //
819 last_packet.video_header.video_timing, //
820 first_packet->payload_type, //
821 first_packet->codec(), //
822 last_packet.video_header.rotation, //
823 last_packet.video_header.content_type, //
824 first_packet->video_header, //
825 last_packet.video_header.color_space, //
826 RtpPacketInfos(std::move(packet_infos)), //
Tommid3807da2020-05-22 15:36:36827 std::move(bitstream)));
Emil Lundmarkaf5ca5a2021-11-30 09:37:25828 payloads.clear();
829 packet_infos.clear();
Tommid3807da2020-05-22 15:36:36830 }
831 }
832 RTC_DCHECK(frame_boundary);
833 if (result.buffer_cleared) {
philipelb8493112021-04-16 10:10:22834 last_received_rtp_system_time_.reset();
835 last_received_keyframe_rtp_system_time_.reset();
836 last_received_keyframe_rtp_timestamp_.reset();
philipel9599b3c2021-05-11 09:30:52837 packet_infos_.clear();
Tommid3807da2020-05-22 15:36:36838 RequestKeyFrame();
839 }
840}
841
842void RtpVideoStreamReceiver2::OnAssembledFrame(
philipelca188092021-03-23 11:00:49843 std::unique_ptr<RtpFrameObject> frame) {
Danil Chapovalov6e7c2682022-07-25 13:58:28844 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
Tommid3807da2020-05-22 15:36:36845 RTC_DCHECK(frame);
846
847 const absl::optional<RTPVideoHeader::GenericDescriptorInfo>& descriptor =
848 frame->GetRtpVideoHeader().generic;
849
850 if (loss_notification_controller_ && descriptor) {
851 loss_notification_controller_->OnAssembledFrame(
852 frame->first_seq_num(), descriptor->frame_id,
853 absl::c_linear_search(descriptor->decode_target_indications,
854 DecodeTargetIndication::kDiscardable),
855 descriptor->dependencies);
856 }
857
858 // If frames arrive before a key frame, they would not be decodable.
859 // In that case, request a key frame ASAP.
860 if (!has_received_frame_) {
861 if (frame->FrameType() != VideoFrameType::kVideoFrameKey) {
Artem Titovab30d722021-07-27 14:22:11862 // `loss_notification_controller_`, if present, would have already
Tommid3807da2020-05-22 15:36:36863 // requested a key frame when the first packet for the non-key frame
864 // had arrived, so no need to replicate the request.
865 if (!loss_notification_controller_) {
866 RequestKeyFrame();
867 }
868 }
869 has_received_frame_ = true;
870 }
871
Artem Titovab30d722021-07-27 14:22:11872 // Reset `reference_finder_` if `frame` is new and the codec have changed.
Tommid3807da2020-05-22 15:36:36873 if (current_codec_) {
874 bool frame_is_newer =
875 AheadOf(frame->Timestamp(), last_assembled_frame_rtp_timestamp_);
876
877 if (frame->codec_type() != current_codec_) {
878 if (frame_is_newer) {
Artem Titovab30d722021-07-27 14:22:11879 // When we reset the `reference_finder_` we don't want new picture ids
Tommid3807da2020-05-22 15:36:36880 // to overlap with old picture ids. To ensure that doesn't happen we
Artem Titovab30d722021-07-27 14:22:11881 // start from the `last_completed_picture_id_` and add an offset in case
Tommid3807da2020-05-22 15:36:36882 // of reordering.
philipel6a671502021-03-22 13:17:09883 reference_finder_ = std::make_unique<RtpFrameReferenceFinder>(
philipel6a671502021-03-22 13:17:09884 last_completed_picture_id_ + std::numeric_limits<uint16_t>::max());
Tommid3807da2020-05-22 15:36:36885 current_codec_ = frame->codec_type();
886 } else {
887 // Old frame from before the codec switch, discard it.
888 return;
889 }
890 }
891
892 if (frame_is_newer) {
893 last_assembled_frame_rtp_timestamp_ = frame->Timestamp();
894 }
895 } else {
896 current_codec_ = frame->codec_type();
897 last_assembled_frame_rtp_timestamp_ = frame->Timestamp();
898 }
899
900 if (buffered_frame_decryptor_ != nullptr) {
901 buffered_frame_decryptor_->ManageEncryptedFrame(std::move(frame));
902 } else if (frame_transformer_delegate_) {
903 frame_transformer_delegate_->TransformFrame(std::move(frame));
904 } else {
philipel21820962021-05-25 13:35:57905 OnCompleteFrames(reference_finder_->ManageFrame(std::move(frame)));
Tommid3807da2020-05-22 15:36:36906 }
907}
908
philipel21820962021-05-25 13:35:57909void RtpVideoStreamReceiver2::OnCompleteFrames(
910 RtpFrameReferenceFinder::ReturnVector frames) {
Danil Chapovalov6e7c2682022-07-25 13:58:28911 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
philipel21820962021-05-25 13:35:57912 for (auto& frame : frames) {
Evan Shrubsolea43ffb32021-09-10 15:09:51913 last_seq_num_for_pic_id_[frame->Id()] = frame->last_seq_num();
Tommi63673fe2020-05-27 10:55:38914
philipel21820962021-05-25 13:35:57915 last_completed_picture_id_ =
916 std::max(last_completed_picture_id_, frame->Id());
917 complete_frame_callback_->OnCompleteFrame(std::move(frame));
918 }
Tommid3807da2020-05-22 15:36:36919}
920
921void RtpVideoStreamReceiver2::OnDecryptedFrame(
philipelca188092021-03-23 11:00:49922 std::unique_ptr<RtpFrameObject> frame) {
Tommi376cf072021-05-31 17:14:38923 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
philipel21820962021-05-25 13:35:57924 OnCompleteFrames(reference_finder_->ManageFrame(std::move(frame)));
Tommid3807da2020-05-22 15:36:36925}
926
927void RtpVideoStreamReceiver2::OnDecryptionStatusChange(
928 FrameDecryptorInterface::Status status) {
Tommi63673fe2020-05-27 10:55:38929 RTC_DCHECK_RUN_ON(&worker_task_checker_);
930 // Called from BufferedFrameDecryptor::DecryptFrame.
931 frames_decryptable_ =
Tommid3807da2020-05-22 15:36:36932 (status == FrameDecryptorInterface::Status::kOk) ||
Tommi63673fe2020-05-27 10:55:38933 (status == FrameDecryptorInterface::Status::kRecoverable);
Tommid3807da2020-05-22 15:36:36934}
935
936void RtpVideoStreamReceiver2::SetFrameDecryptor(
937 rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor) {
Tommi376cf072021-05-31 17:14:38938 // TODO(bugs.webrtc.org/11993): Update callers or post the operation over to
939 // the network thread.
940 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
Tommid3807da2020-05-22 15:36:36941 if (buffered_frame_decryptor_ == nullptr) {
942 buffered_frame_decryptor_ =
Jonas Oreland8ca06132022-03-14 11:52:48943 std::make_unique<BufferedFrameDecryptor>(this, this, field_trials_);
Tommid3807da2020-05-22 15:36:36944 }
945 buffered_frame_decryptor_->SetFrameDecryptor(std::move(frame_decryptor));
946}
947
948void RtpVideoStreamReceiver2::SetDepacketizerToDecoderFrameTransformer(
949 rtc::scoped_refptr<FrameTransformerInterface> frame_transformer) {
Tommi63673fe2020-05-27 10:55:38950 RTC_DCHECK_RUN_ON(&worker_task_checker_);
Tommid3807da2020-05-22 15:36:36951 frame_transformer_delegate_ =
Tomas Gunnarssonc1d58912021-04-22 17:21:43952 rtc::make_ref_counted<RtpVideoStreamReceiverFrameTransformerDelegate>(
Tony Herre9d677f42023-07-11 12:41:06953 this, clock_, std::move(frame_transformer), rtc::Thread::Current(),
Tommid3807da2020-05-22 15:36:36954 config_.rtp.remote_ssrc);
955 frame_transformer_delegate_->Init();
956}
957
958void RtpVideoStreamReceiver2::UpdateRtt(int64_t max_rtt_ms) {
Tommi3900f212022-08-05 14:21:54959 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
Tommid3807da2020-05-22 15:36:36960 if (nack_module_)
961 nack_module_->UpdateRtt(max_rtt_ms);
962}
963
Tommi1331c182022-05-17 08:13:52964void RtpVideoStreamReceiver2::OnLocalSsrcChange(uint32_t local_ssrc) {
965 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
966 rtp_rtcp_->SetLocalSsrc(local_ssrc);
967}
968
Tommiaeb44122022-07-14 16:33:42969void RtpVideoStreamReceiver2::SetRtcpMode(RtcpMode mode) {
970 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
971 rtp_rtcp_->SetRTCPStatus(mode);
972}
973
Tommi2e809362022-08-12 20:06:20974void RtpVideoStreamReceiver2::SetReferenceTimeReport(bool enabled) {
975 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
976 rtp_rtcp_->SetNonSenderRttMeasurement(enabled);
977}
978
Tommi185f10c2022-08-02 09:51:20979void RtpVideoStreamReceiver2::SetPacketSink(
980 RtpPacketSinkInterface* packet_sink) {
981 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
982 packet_sink_ = packet_sink;
983}
984
Tommie644a4b2022-08-03 14:13:53985void RtpVideoStreamReceiver2::SetLossNotificationEnabled(bool enabled) {
986 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
987 if (enabled && !loss_notification_controller_) {
988 loss_notification_controller_ =
989 std::make_unique<LossNotificationController>(&rtcp_feedback_buffer_,
990 &rtcp_feedback_buffer_);
991 } else if (!enabled && loss_notification_controller_) {
992 loss_notification_controller_.reset();
993 rtcp_feedback_buffer_.ClearLossNotificationState();
994 }
995}
996
Tommi3900f212022-08-05 14:21:54997void RtpVideoStreamReceiver2::SetNackHistory(TimeDelta history) {
998 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
999 if (history.ms() == 0) {
1000 nack_module_.reset();
1001 } else if (!nack_module_) {
1002 nack_module_ = std::make_unique<NackRequester>(
1003 worker_queue_, nack_periodic_processor_, clock_, &rtcp_feedback_buffer_,
1004 &rtcp_feedback_buffer_, field_trials_);
1005 }
1006
1007 rtp_receive_statistics_->SetMaxReorderingThreshold(
1008 config_.rtp.remote_ssrc,
1009 history.ms() > 0 ? kMaxPacketAgeToNack : kDefaultMaxReorderingThreshold);
1010}
1011
Tommi66d20c42022-08-12 13:05:171012int RtpVideoStreamReceiver2::ulpfec_payload_type() const {
1013 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
1014 return ulpfec_receiver_ ? ulpfec_receiver_->ulpfec_payload_type() : -1;
1015}
1016
Tommi1c5f3172022-08-13 08:43:591017int RtpVideoStreamReceiver2::red_payload_type() const {
1018 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
1019 return red_payload_type_;
1020}
1021
Tommie1bd8332022-08-13 08:44:101022void RtpVideoStreamReceiver2::SetProtectionPayloadTypes(
1023 int red_payload_type,
1024 int ulpfec_payload_type) {
Tommi1c5f3172022-08-13 08:43:591025 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
Tommie1bd8332022-08-13 08:44:101026 RTC_DCHECK(red_payload_type >= -1 && red_payload_type < 0x80);
1027 RTC_DCHECK(ulpfec_payload_type >= -1 && ulpfec_payload_type < 0x80);
Sergey Silkin1cb3cde2022-11-01 08:56:591028 red_payload_type_ = red_payload_type;
Per K5e5d0172022-12-22 12:43:411029 ulpfec_receiver_ =
1030 MaybeConstructUlpfecReceiver(config_.rtp.remote_ssrc, red_payload_type,
1031 ulpfec_payload_type, this, clock_);
Tommi66d20c42022-08-12 13:05:171032}
1033
Tommid3807da2020-05-22 15:36:361034absl::optional<int64_t> RtpVideoStreamReceiver2::LastReceivedPacketMs() const {
Tommi376cf072021-05-31 17:14:381035 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
philipelce423ce2021-04-12 11:42:031036 if (last_received_rtp_system_time_) {
1037 return absl::optional<int64_t>(last_received_rtp_system_time_->ms());
1038 }
1039 return absl::nullopt;
Tommid3807da2020-05-22 15:36:361040}
1041
Philipp Hancke5f4a7e02023-07-03 09:18:371042absl::optional<uint32_t>
1043RtpVideoStreamReceiver2::LastReceivedFrameRtpTimestamp() const {
1044 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
1045 return last_received_rtp_timestamp_;
1046}
1047
Tommid3807da2020-05-22 15:36:361048absl::optional<int64_t> RtpVideoStreamReceiver2::LastReceivedKeyframePacketMs()
1049 const {
Tommi376cf072021-05-31 17:14:381050 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
philipelce423ce2021-04-12 11:42:031051 if (last_received_keyframe_rtp_system_time_) {
1052 return absl::optional<int64_t>(
1053 last_received_keyframe_rtp_system_time_->ms());
1054 }
1055 return absl::nullopt;
Tommid3807da2020-05-22 15:36:361056}
1057
Tommid3807da2020-05-22 15:36:361058void RtpVideoStreamReceiver2::ManageFrame(
philipelca188092021-03-23 11:00:491059 std::unique_ptr<RtpFrameObject> frame) {
Tommi376cf072021-05-31 17:14:381060 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
philipel21820962021-05-25 13:35:571061 OnCompleteFrames(reference_finder_->ManageFrame(std::move(frame)));
Tommid3807da2020-05-22 15:36:361062}
1063
1064void RtpVideoStreamReceiver2::ReceivePacket(const RtpPacketReceived& packet) {
Danil Chapovalov6e7c2682022-07-25 13:58:281065 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
Tommi3900f212022-08-05 14:21:541066
Tommid3807da2020-05-22 15:36:361067 if (packet.payload_size() == 0) {
1068 // Padding or keep-alive packet.
1069 // TODO(nisse): Could drop empty packets earlier, but need to figure out how
1070 // they should be counted in stats.
1071 NotifyReceiverOfEmptyPacket(packet.SequenceNumber());
1072 return;
1073 }
Tommi1c5f3172022-08-13 08:43:591074 if (packet.PayloadType() == red_payload_type_) {
Tommid3807da2020-05-22 15:36:361075 ParseAndHandleEncapsulatingHeader(packet);
1076 return;
1077 }
1078
1079 const auto type_it = payload_type_map_.find(packet.PayloadType());
1080 if (type_it == payload_type_map_.end()) {
1081 return;
1082 }
1083 absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed_payload =
1084 type_it->second->Parse(packet.PayloadBuffer());
1085 if (parsed_payload == absl::nullopt) {
1086 RTC_LOG(LS_WARNING) << "Failed parsing payload.";
1087 return;
1088 }
1089
1090 OnReceivedPayloadData(std::move(parsed_payload->video_payload), packet,
1091 parsed_payload->video_header);
1092}
1093
1094void RtpVideoStreamReceiver2::ParseAndHandleEncapsulatingHeader(
1095 const RtpPacketReceived& packet) {
Danil Chapovalov6e7c2682022-07-25 13:58:281096 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
Tommi1c5f3172022-08-13 08:43:591097 RTC_DCHECK_EQ(packet.PayloadType(), red_payload_type_);
Tommi66d20c42022-08-12 13:05:171098
1099 if (!ulpfec_receiver_ || packet.payload_size() == 0U)
1100 return;
1101
1102 if (packet.payload()[0] == ulpfec_receiver_->ulpfec_payload_type()) {
1103 // Notify video_receiver about received FEC packets to avoid NACKing these
1104 // packets.
1105 NotifyReceiverOfEmptyPacket(packet.SequenceNumber());
1106 }
1107 if (ulpfec_receiver_->AddReceivedRedPacket(packet)) {
1108 ulpfec_receiver_->ProcessReceivedFec();
Tommid3807da2020-05-22 15:36:361109 }
1110}
1111
1112// In the case of a video stream without picture ids and no rtx the
1113// RtpFrameReferenceFinder will need to know about padding to
1114// correctly calculate frame references.
1115void RtpVideoStreamReceiver2::NotifyReceiverOfEmptyPacket(uint16_t seq_num) {
Danil Chapovalov6e7c2682022-07-25 13:58:281116 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
Tommi31b56492021-06-01 07:50:261117 RTC_DCHECK_RUN_ON(&worker_task_checker_);
1118
philipel21820962021-05-25 13:35:571119 OnCompleteFrames(reference_finder_->PaddingReceived(seq_num));
Tommi63673fe2020-05-27 10:55:381120
Tommid3807da2020-05-22 15:36:361121 OnInsertedPacket(packet_buffer_.InsertPadding(seq_num));
1122 if (nack_module_) {
1123 nack_module_->OnReceivedPacket(seq_num, /* is_keyframe = */ false,
1124 /* is _recovered = */ false);
1125 }
1126 if (loss_notification_controller_) {
1127 // TODO(bugs.webrtc.org/10336): Handle empty packets.
1128 RTC_LOG(LS_WARNING)
1129 << "LossNotificationController does not expect empty packets.";
1130 }
1131}
1132
1133bool RtpVideoStreamReceiver2::DeliverRtcp(const uint8_t* rtcp_packet,
1134 size_t rtcp_packet_length) {
Tommi376cf072021-05-31 17:14:381135 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
Tommid3807da2020-05-22 15:36:361136
1137 if (!receiving_) {
1138 return false;
1139 }
1140
Harald Alvestrand1f206b82023-02-01 11:12:461141 rtp_rtcp_->IncomingRtcpPacket(
1142 rtc::MakeArrayView(rtcp_packet, rtcp_packet_length));
Tommid3807da2020-05-22 15:36:361143
Danil Chapovalov8095d022023-05-09 07:59:461144 absl::optional<TimeDelta> rtt = rtp_rtcp_->LastRtt();
1145 if (!rtt.has_value()) {
Tommid3807da2020-05-22 15:36:361146 // Waiting for valid rtt.
1147 return true;
1148 }
Danil Chapovalov9f397212023-02-27 18:49:311149
1150 absl::optional<RtpRtcpInterface::SenderReportStats> last_sr =
1151 rtp_rtcp_->GetSenderReportStats();
1152 if (!last_sr.has_value()) {
Tommid3807da2020-05-22 15:36:361153 // Waiting for RTCP.
1154 return true;
1155 }
Danil Chapovalov9f397212023-02-27 18:49:311156 int64_t time_since_received = clock_->CurrentNtpInMilliseconds() -
1157 last_sr->last_arrival_timestamp.ToMs();
Tommid3807da2020-05-22 15:36:361158 // Don't use old SRs to estimate time.
Niels Möllerbe74b802022-03-18 13:10:151159 if (time_since_received <= 1) {
Danil Chapovalov8095d022023-05-09 07:59:461160 ntp_estimator_.UpdateRtcpTimestamp(*rtt, last_sr->last_remote_timestamp,
Danil Chapovalov9f397212023-02-27 18:49:311161 last_sr->last_remote_rtp_timestamp);
Danil Chapovalovedcb25b2022-05-10 09:33:201162 absl::optional<int64_t> remote_to_local_clock_offset =
1163 ntp_estimator_.EstimateRemoteToLocalClockOffset();
1164 if (remote_to_local_clock_offset.has_value()) {
Minyue Li63b30952021-05-19 12:38:251165 capture_clock_offset_updater_.SetRemoteToLocalClockOffset(
Danil Chapovalovedcb25b2022-05-10 09:33:201166 *remote_to_local_clock_offset);
Tommid3807da2020-05-22 15:36:361167 }
1168 }
1169
1170 return true;
1171}
1172
1173void RtpVideoStreamReceiver2::FrameContinuous(int64_t picture_id) {
Tommi376cf072021-05-31 17:14:381174 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
Tommid3807da2020-05-22 15:36:361175 if (!nack_module_)
1176 return;
1177
1178 int seq_num = -1;
Tommi63673fe2020-05-27 10:55:381179 auto seq_num_it = last_seq_num_for_pic_id_.find(picture_id);
1180 if (seq_num_it != last_seq_num_for_pic_id_.end())
1181 seq_num = seq_num_it->second;
Tommid3807da2020-05-22 15:36:361182 if (seq_num != -1)
1183 nack_module_->ClearUpTo(seq_num);
1184}
1185
1186void RtpVideoStreamReceiver2::FrameDecoded(int64_t picture_id) {
Tommi376cf072021-05-31 17:14:381187 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
Tommid3807da2020-05-22 15:36:361188 int seq_num = -1;
Tommi63673fe2020-05-27 10:55:381189 auto seq_num_it = last_seq_num_for_pic_id_.find(picture_id);
1190 if (seq_num_it != last_seq_num_for_pic_id_.end()) {
1191 seq_num = seq_num_it->second;
1192 last_seq_num_for_pic_id_.erase(last_seq_num_for_pic_id_.begin(),
1193 ++seq_num_it);
Tommid3807da2020-05-22 15:36:361194 }
Tommi63673fe2020-05-27 10:55:381195
Tommid3807da2020-05-22 15:36:361196 if (seq_num != -1) {
philipel9599b3c2021-05-11 09:30:521197 int64_t unwrapped_rtp_seq_num = rtp_seq_num_unwrapper_.Unwrap(seq_num);
1198 packet_infos_.erase(packet_infos_.begin(),
1199 packet_infos_.upper_bound(unwrapped_rtp_seq_num));
Tommid3807da2020-05-22 15:36:361200 packet_buffer_.ClearTo(seq_num);
Tommid3807da2020-05-22 15:36:361201 reference_finder_->ClearTo(seq_num);
1202 }
1203}
1204
1205void RtpVideoStreamReceiver2::SignalNetworkState(NetworkState state) {
Tommi63673fe2020-05-27 10:55:381206 RTC_DCHECK_RUN_ON(&worker_task_checker_);
Tommid3807da2020-05-22 15:36:361207 rtp_rtcp_->SetRTCPStatus(state == kNetworkUp ? config_.rtp.rtcp_mode
1208 : RtcpMode::kOff);
1209}
1210
1211void RtpVideoStreamReceiver2::StartReceive() {
Tommi376cf072021-05-31 17:14:381212 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
Tommid3807da2020-05-22 15:36:361213 receiving_ = true;
1214}
1215
1216void RtpVideoStreamReceiver2::StopReceive() {
Tommi376cf072021-05-31 17:14:381217 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
Tommid3807da2020-05-22 15:36:361218 receiving_ = false;
1219}
1220
Tommid3807da2020-05-22 15:36:361221void RtpVideoStreamReceiver2::InsertSpsPpsIntoTracker(uint8_t payload_type) {
Danil Chapovalov6e7c2682022-07-25 13:58:281222 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
Tommi31b56492021-06-01 07:50:261223 RTC_DCHECK_RUN_ON(&worker_task_checker_);
1224
Tommid3807da2020-05-22 15:36:361225 auto codec_params_it = pt_codec_params_.find(payload_type);
1226 if (codec_params_it == pt_codec_params_.end())
1227 return;
1228
1229 RTC_LOG(LS_INFO) << "Found out of band supplied codec parameters for"
1230 " payload type: "
1231 << static_cast<int>(payload_type);
1232
1233 H264SpropParameterSets sprop_decoder;
1234 auto sprop_base64_it =
1235 codec_params_it->second.find(cricket::kH264FmtpSpropParameterSets);
1236
1237 if (sprop_base64_it == codec_params_it->second.end())
1238 return;
1239
1240 if (!sprop_decoder.DecodeSprop(sprop_base64_it->second.c_str()))
1241 return;
1242
1243 tracker_.InsertSpsPpsNalus(sprop_decoder.sps_nalu(),
1244 sprop_decoder.pps_nalu());
1245}
1246
philipelce423ce2021-04-12 11:42:031247void RtpVideoStreamReceiver2::UpdatePacketReceiveTimestamps(
1248 const RtpPacketReceived& packet,
1249 bool is_keyframe) {
1250 Timestamp now = clock_->CurrentTime();
philipelb8493112021-04-16 10:10:221251 if (is_keyframe ||
1252 last_received_keyframe_rtp_timestamp_ == packet.Timestamp()) {
1253 last_received_keyframe_rtp_timestamp_ = packet.Timestamp();
philipelce423ce2021-04-12 11:42:031254 last_received_keyframe_rtp_system_time_ = now;
1255 }
1256 last_received_rtp_system_time_ = now;
1257 last_received_rtp_timestamp_ = packet.Timestamp();
1258
1259 // Periodically log the RTP header of incoming packets.
1260 if (now.ms() - last_packet_log_ms_ > kPacketLogIntervalMs) {
1261 rtc::StringBuilder ss;
1262 ss << "Packet received on SSRC: " << packet.Ssrc()
1263 << " with payload type: " << static_cast<int>(packet.PayloadType())
1264 << ", timestamp: " << packet.Timestamp()
1265 << ", sequence number: " << packet.SequenceNumber()
Tommi2497a272021-05-05 10:33:001266 << ", arrival time: " << ToString(packet.arrival_time());
philipelce423ce2021-04-12 11:42:031267 int32_t time_offset;
1268 if (packet.GetExtension<TransmissionOffset>(&time_offset)) {
1269 ss << ", toffset: " << time_offset;
1270 }
1271 uint32_t send_time;
1272 if (packet.GetExtension<AbsoluteSendTime>(&send_time)) {
1273 ss << ", abs send time: " << send_time;
1274 }
1275 RTC_LOG(LS_INFO) << ss.str();
1276 last_packet_log_ms_ = now.ms();
1277 }
1278}
1279
Tommid3807da2020-05-22 15:36:361280} // namespace webrtc