Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
| 3 | * |
| 4 | * Use of this source code is governed by a BSD-style license |
| 5 | * that can be found in the LICENSE file in the root of the source |
| 6 | * tree. An additional intellectual property rights grant can be found |
| 7 | * in the file PATENTS. All contributing project authors may |
| 8 | * be found in the AUTHORS file in the root of the source tree. |
| 9 | */ |
| 10 | |
| 11 | #include "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" |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 20 | #include "absl/memory/memory.h" |
| 21 | #include "absl/types/optional.h" |
Danil Chapovalov | 5653c95 | 2021-08-10 14:57:56 | [diff] [blame] | 22 | #include "api/video/video_codec_type.h" |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 23 | #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" |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 28 | #include "modules/rtp_rtcp/source/create_video_rtp_depacketizer.h" |
Tony Herre | be9b576 | 2023-02-03 11:29:04 | [diff] [blame] | 29 | #include "modules/rtp_rtcp/source/frame_object.h" |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 30 | #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" |
Tommi | e488a87 | 2022-08-09 15:50:45 | [diff] [blame] | 37 | #include "modules/rtp_rtcp/source/ulpfec_receiver.h" |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 38 | #include "modules/rtp_rtcp/source/video_rtp_depacketizer.h" |
| 39 | #include "modules/rtp_rtcp/source/video_rtp_depacketizer_raw.h" |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 40 | #include "modules/video_coding/h264_sprop_parameter_sets.h" |
| 41 | #include "modules/video_coding/h264_sps_pps_tracker.h" |
Markus Handell | 06a2bf0 | 2021-07-22 13:09:39 | [diff] [blame] | 42 | #include "modules/video_coding/nack_requester.h" |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 43 | #include "modules/video_coding/packet_buffer.h" |
| 44 | #include "rtc_base/checks.h" |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 45 | #include "rtc_base/logging.h" |
| 46 | #include "rtc_base/strings/string_builder.h" |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 47 | #include "system_wrappers/include/metrics.h" |
| 48 | #include "system_wrappers/include/ntp_time.h" |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 49 | |
| 50 | namespace webrtc { |
| 51 | |
| 52 | namespace { |
| 53 | // TODO(philipel): Change kPacketBufferStartSize back to 32 in M63 see: |
| 54 | // crbug.com/752886 |
| 55 | constexpr int kPacketBufferStartSize = 512; |
| 56 | constexpr int kPacketBufferMaxSize = 2048; |
| 57 | |
Tommi | 3900f21 | 2022-08-05 14:21:54 | [diff] [blame] | 58 | constexpr int kMaxPacketAgeToNack = 450; |
| 59 | |
Jonas Oreland | e62c2f2 | 2022-03-29 09:04:48 | [diff] [blame] | 60 | int PacketBufferMaxSize(const FieldTrialsView& field_trials) { |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 61 | // 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 Oreland | 8ca0613 | 2022-03-14 11:52:48 | [diff] [blame] | 64 | field_trials.Lookup("WebRTC-PacketBufferMaxSize"); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 65 | 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 Gunnarsson | f25761d | 2020-06-03 20:55:33 | [diff] [blame] | 77 | std::unique_ptr<ModuleRtpRtcpImpl2> CreateRtpRtcpModule( |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 78 | 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öller | be810cba | 2020-12-02 13:25:03 | [diff] [blame] | 84 | bool non_sender_rtt_measurement, |
Brett Hebert | e04d0fa | 2022-08-09 18:25:04 | [diff] [blame] | 85 | uint32_t local_ssrc, |
| 86 | RtcEventLog* rtc_event_log) { |
Tomas Gunnarsson | f25761d | 2020-06-03 20:55:33 | [diff] [blame] | 87 | RtpRtcpInterface::Configuration configuration; |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 88 | 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öller | be810cba | 2020-12-02 13:25:03 | [diff] [blame] | 98 | configuration.non_sender_rtt_measurement = non_sender_rtt_measurement; |
Brett Hebert | e04d0fa | 2022-08-09 18:25:04 | [diff] [blame] | 99 | configuration.event_log = rtc_event_log; |
Niels Moller | 2accc7d | 2021-01-12 15:54:16 | [diff] [blame] | 100 | |
| 101 | std::unique_ptr<ModuleRtpRtcpImpl2> rtp_rtcp = |
| 102 | ModuleRtpRtcpImpl2::Create(configuration); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 103 | rtp_rtcp->SetRTCPStatus(RtcpMode::kCompound); |
| 104 | |
| 105 | return rtp_rtcp; |
| 106 | } |
| 107 | |
Markus Handell | 06a2bf0 | 2021-07-22 13:09:39 | [diff] [blame] | 108 | std::unique_ptr<NackRequester> MaybeConstructNackModule( |
Tommi | 63673fe | 2020-05-27 10:55:38 | [diff] [blame] | 109 | TaskQueueBase* current_queue, |
Markus Handell | 0e62f7a | 2021-07-20 11:32:02 | [diff] [blame] | 110 | NackPeriodicProcessor* nack_periodic_processor, |
Tommi | 3900f21 | 2022-08-05 14:21:54 | [diff] [blame] | 111 | const NackConfig& nack, |
Tommi | 63673fe | 2020-05-27 10:55:38 | [diff] [blame] | 112 | Clock* clock, |
| 113 | NackSender* nack_sender, |
Jonas Oreland | e02f9ee | 2022-03-25 11:43:14 | [diff] [blame] | 114 | KeyFrameRequestSender* keyframe_request_sender, |
Jonas Oreland | e62c2f2 | 2022-03-29 09:04:48 | [diff] [blame] | 115 | const FieldTrialsView& field_trials) { |
Tommi | 3900f21 | 2022-08-05 14:21:54 | [diff] [blame] | 116 | if (nack.rtp_history_ms == 0) |
Tommi | 63673fe | 2020-05-27 10:55:38 | [diff] [blame] | 117 | return nullptr; |
| 118 | |
Philipp Hancke | 006206d | 2021-03-24 16:49:02 | [diff] [blame] | 119 | // TODO(bugs.webrtc.org/12420): pass rtp_history_ms to the nack module. |
Markus Handell | 06a2bf0 | 2021-07-22 13:09:39 | [diff] [blame] | 120 | return std::make_unique<NackRequester>(current_queue, nack_periodic_processor, |
| 121 | clock, nack_sender, |
Jonas Oreland | e02f9ee | 2022-03-25 11:43:14 | [diff] [blame] | 122 | keyframe_request_sender, field_trials); |
Tommi | 63673fe | 2020-05-27 10:55:38 | [diff] [blame] | 123 | } |
| 124 | |
Tommi | b69b819 | 2022-08-12 09:03:34 | [diff] [blame] | 125 | std::unique_ptr<UlpfecReceiver> MaybeConstructUlpfecReceiver( |
Tommi | 66d20c4 | 2022-08-12 13:05:17 | [diff] [blame] | 126 | uint32_t remote_ssrc, |
| 127 | int red_payload_type, |
| 128 | int ulpfec_payload_type, |
Tommi | b69b819 | 2022-08-12 09:03:34 | [diff] [blame] | 129 | RecoveredPacketReceiver* callback, |
| 130 | Clock* clock) { |
Tommi | 66d20c4 | 2022-08-12 13:05:17 | [diff] [blame] | 131 | RTC_DCHECK_GE(red_payload_type, -1); |
| 132 | RTC_DCHECK_GE(ulpfec_payload_type, -1); |
| 133 | if (red_payload_type == -1) |
Tommi | b69b819 | 2022-08-12 09:03:34 | [diff] [blame] | 134 | 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. |
Tommi | 66d20c4 | 2022-08-12 13:05:17 | [diff] [blame] | 139 | // if (ulpfec_payload_type == -1) |
Tommi | b69b819 | 2022-08-12 09:03:34 | [diff] [blame] | 140 | // return nullptr; |
| 141 | |
Tommi | 66d20c4 | 2022-08-12 13:05:17 | [diff] [blame] | 142 | return std::make_unique<UlpfecReceiver>(remote_ssrc, ulpfec_payload_type, |
Per K | 5e5d017 | 2022-12-22 12:43:41 | [diff] [blame] | 143 | callback, clock); |
Tommi | b69b819 | 2022-08-12 09:03:34 | [diff] [blame] | 144 | } |
| 145 | |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 146 | static const int kPacketLogIntervalMs = 10000; |
Tommi | 63673fe | 2020-05-27 10:55:38 | [diff] [blame] | 147 | |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 148 | } // namespace |
| 149 | |
| 150 | RtpVideoStreamReceiver2::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_); |
Tommi | 376cf07 | 2021-05-31 17:14:38 | [diff] [blame] | 161 | packet_sequence_checker_.Detach(); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 162 | } |
| 163 | |
| 164 | void RtpVideoStreamReceiver2::RtcpFeedbackBuffer::RequestKeyFrame() { |
Tommi | 376cf07 | 2021-05-31 17:14:38 | [diff] [blame] | 165 | RTC_DCHECK_RUN_ON(&packet_sequence_checker_); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 166 | request_key_frame_ = true; |
| 167 | } |
| 168 | |
| 169 | void RtpVideoStreamReceiver2::RtcpFeedbackBuffer::SendNack( |
| 170 | const std::vector<uint16_t>& sequence_numbers, |
| 171 | bool buffering_allowed) { |
Tommi | 376cf07 | 2021-05-31 17:14:38 | [diff] [blame] | 172 | RTC_DCHECK_RUN_ON(&packet_sequence_checker_); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 173 | RTC_DCHECK(!sequence_numbers.empty()); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 174 | 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. |
Tommi | 63673fe | 2020-05-27 10:55:38 | [diff] [blame] | 180 | SendBufferedRtcpFeedback(); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 181 | } |
| 182 | } |
| 183 | |
| 184 | void 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) { |
Tommi | 376cf07 | 2021-05-31 17:14:38 | [diff] [blame] | 189 | RTC_DCHECK_RUN_ON(&packet_sequence_checker_); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 190 | RTC_DCHECK(buffering_allowed); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 191 | 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 | |
| 198 | void RtpVideoStreamReceiver2::RtcpFeedbackBuffer::SendBufferedRtcpFeedback() { |
Tommi | 376cf07 | 2021-05-31 17:14:38 | [diff] [blame] | 199 | RTC_DCHECK_RUN_ON(&packet_sequence_checker_); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 200 | |
Tommi | 63673fe | 2020-05-27 10:55:38 | [diff] [blame] | 201 | bool request_key_frame = false; |
| 202 | std::vector<uint16_t> nack_sequence_numbers; |
| 203 | absl::optional<LossNotificationState> lntf_state; |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 204 | |
Tommi | 63673fe | 2020-05-27 10:55:38 | [diff] [blame] | 205 | std::swap(request_key_frame, request_key_frame_); |
| 206 | std::swap(nack_sequence_numbers, nack_sequence_numbers_); |
| 207 | std::swap(lntf_state, lntf_state_); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 208 | |
Tommi | 63673fe | 2020-05-27 10:55:38 | [diff] [blame] | 209 | if (lntf_state) { |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 210 | // 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 = |
Tommi | 63673fe | 2020-05-27 10:55:38 | [diff] [blame] | 215 | request_key_frame || !nack_sequence_numbers.empty(); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 216 | |
| 217 | loss_notification_sender_->SendLossNotification( |
Tommi | 63673fe | 2020-05-27 10:55:38 | [diff] [blame] | 218 | lntf_state->last_decoded_seq_num, lntf_state->last_received_seq_num, |
| 219 | lntf_state->decodability_flag, buffering_allowed); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 220 | } |
| 221 | |
Tommi | 63673fe | 2020-05-27 10:55:38 | [diff] [blame] | 222 | if (request_key_frame) { |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 223 | key_frame_request_sender_->RequestKeyFrame(); |
Tommi | 63673fe | 2020-05-27 10:55:38 | [diff] [blame] | 224 | } else if (!nack_sequence_numbers.empty()) { |
| 225 | nack_sender_->SendNack(nack_sequence_numbers, true); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 226 | } |
| 227 | } |
| 228 | |
Tommi | e644a4b | 2022-08-03 14:13:53 | [diff] [blame] | 229 | void RtpVideoStreamReceiver2::RtcpFeedbackBuffer::ClearLossNotificationState() { |
| 230 | RTC_DCHECK_RUN_ON(&packet_sequence_checker_); |
| 231 | lntf_state_.reset(); |
| 232 | } |
| 233 | |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 234 | RtpVideoStreamReceiver2::RtpVideoStreamReceiver2( |
Tommi | 63673fe | 2020-05-27 10:55:38 | [diff] [blame] | 235 | TaskQueueBase* current_queue, |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 236 | Clock* clock, |
| 237 | Transport* transport, |
| 238 | RtcpRttStats* rtt_stats, |
| 239 | PacketRouter* packet_router, |
Tommi | f6f4543 | 2022-05-20 13:21:20 | [diff] [blame] | 240 | const VideoReceiveStreamInterface::Config* config, |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 241 | ReceiveStatistics* rtp_receive_statistics, |
| 242 | RtcpPacketTypeCounterObserver* rtcp_packet_type_counter_observer, |
| 243 | RtcpCnameCallback* rtcp_cname_callback, |
Markus Handell | 0e62f7a | 2021-07-20 11:32:02 | [diff] [blame] | 244 | NackPeriodicProcessor* nack_periodic_processor, |
philipel | 6a67150 | 2021-03-22 13:17:09 | [diff] [blame] | 245 | OnCompleteFrameCallback* complete_frame_callback, |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 246 | rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor, |
Jonas Oreland | 8ca0613 | 2022-03-14 11:52:48 | [diff] [blame] | 247 | rtc::scoped_refptr<FrameTransformerInterface> frame_transformer, |
Brett Hebert | e04d0fa | 2022-08-09 18:25:04 | [diff] [blame] | 248 | const FieldTrialsView& field_trials, |
| 249 | RtcEventLog* event_log) |
Jonas Oreland | 8ca0613 | 2022-03-14 11:52:48 | [diff] [blame] | 250 | : field_trials_(field_trials), |
Tommi | 3900f21 | 2022-08-05 14:21:54 | [diff] [blame] | 251 | worker_queue_(current_queue), |
Jonas Oreland | 8ca0613 | 2022-03-14 11:52:48 | [diff] [blame] | 252 | clock_(clock), |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 253 | config_(*config), |
| 254 | packet_router_(packet_router), |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 255 | ntp_estimator_(clock), |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 256 | 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), |
Tommi | 66d20c4 | 2022-08-12 13:05:17 | [diff] [blame] | 259 | ulpfec_receiver_( |
| 260 | MaybeConstructUlpfecReceiver(config->rtp.remote_ssrc, |
| 261 | config->rtp.red_payload_type, |
| 262 | config->rtp.ulpfec_payload_type, |
Tommi | 66d20c4 | 2022-08-12 13:05:17 | [diff] [blame] | 263 | this, |
| 264 | clock_)), |
Tommi | 1c5f317 | 2022-08-13 08:43:59 | [diff] [blame] | 265 | red_payload_type_(config_.rtp.red_payload_type), |
Tommi | 185f10c | 2022-08-02 09:51:20 | [diff] [blame] | 266 | packet_sink_(config->rtp.packet_sink_), |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 267 | receiving_(false), |
| 268 | last_packet_log_ms_(-1), |
Niels Möller | be810cba | 2020-12-02 13:25:03 | [diff] [blame] | 269 | 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 Hebert | e04d0fa | 2022-08-09 18:25:04 | [diff] [blame] | 277 | config_.rtp.local_ssrc, |
| 278 | event_log)), |
Tommi | 3900f21 | 2022-08-05 14:21:54 | [diff] [blame] | 279 | nack_periodic_processor_(nack_periodic_processor), |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 280 | complete_frame_callback_(complete_frame_callback), |
Nico Grunbaum | a36f10b | 2021-12-09 04:59:31 | [diff] [blame] | 281 | keyframe_request_method_(config_.rtp.keyframe_method), |
Artem Titov | ab30d72 | 2021-07-27 14:22:11 | [diff] [blame] | 282 | // TODO(bugs.webrtc.org/10336): Let `rtcp_feedback_buffer_` communicate |
| 283 | // directly with `rtp_rtcp_`. |
philipel | b981394 | 2022-07-05 09:31:36 | [diff] [blame] | 284 | rtcp_feedback_buffer_(this, this, this), |
Tommi | 63673fe | 2020-05-27 10:55:38 | [diff] [blame] | 285 | nack_module_(MaybeConstructNackModule(current_queue, |
Markus Handell | 0e62f7a | 2021-07-20 11:32:02 | [diff] [blame] | 286 | nack_periodic_processor, |
Tommi | 3900f21 | 2022-08-05 14:21:54 | [diff] [blame] | 287 | config_.rtp.nack, |
Tommi | 63673fe | 2020-05-27 10:55:38 | [diff] [blame] | 288 | clock_, |
| 289 | &rtcp_feedback_buffer_, |
Jonas Oreland | e02f9ee | 2022-03-25 11:43:14 | [diff] [blame] | 290 | &rtcp_feedback_buffer_, |
| 291 | field_trials_)), |
Jonas Oreland | 8ca0613 | 2022-03-14 11:52:48 | [diff] [blame] | 292 | packet_buffer_(kPacketBufferStartSize, |
| 293 | PacketBufferMaxSize(field_trials_)), |
philipel | 2182096 | 2021-05-25 13:35:57 | [diff] [blame] | 294 | reference_finder_(std::make_unique<RtpFrameReferenceFinder>()), |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 295 | has_received_frame_(false), |
Artem Titarenko | 3c2359c | 2022-05-05 10:29:51 | [diff] [blame] | 296 | frames_decryptable_(false), |
Minyue Li | 63b3095 | 2021-05-19 12:38:25 | [diff] [blame] | 297 | absolute_capture_time_interpolator_(clock) { |
Tommi | 376cf07 | 2021-05-31 17:14:38 | [diff] [blame] | 298 | packet_sequence_checker_.Detach(); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 299 | 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öller | 761072f | 2022-07-20 12:06:05 | [diff] [blame] | 313 | if (config_.rtp.nack.rtp_history_ms > 0) { |
Niels Möller | 761072f | 2022-07-20 12:06:05 | [diff] [blame] | 314 | rtp_receive_statistics_->SetMaxReorderingThreshold(config_.rtp.remote_ssrc, |
| 315 | kMaxPacketAgeToNack); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 316 | } |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 317 | ParseFieldTrial( |
| 318 | {&forced_playout_delay_max_ms_, &forced_playout_delay_min_ms_}, |
Jonas Oreland | 8ca0613 | 2022-03-14 11:52:48 | [diff] [blame] | 319 | field_trials_.Lookup("WebRTC-ForcePlayoutDelay")); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 320 | |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 321 | if (config_.rtp.lntf.enabled) { |
| 322 | loss_notification_controller_ = |
| 323 | std::make_unique<LossNotificationController>(&rtcp_feedback_buffer_, |
| 324 | &rtcp_feedback_buffer_); |
| 325 | } |
| 326 | |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 327 | // Only construct the encrypted receiver if frame encryption is enabled. |
| 328 | if (config_.crypto_options.sframe.require_frame_encryption) { |
| 329 | buffered_frame_decryptor_ = |
Jonas Oreland | 8ca0613 | 2022-03-14 11:52:48 | [diff] [blame] | 330 | std::make_unique<BufferedFrameDecryptor>(this, this, field_trials_); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 331 | if (frame_decryptor != nullptr) { |
| 332 | buffered_frame_decryptor_->SetFrameDecryptor(std::move(frame_decryptor)); |
| 333 | } |
| 334 | } |
| 335 | |
| 336 | if (frame_transformer) { |
Tomas Gunnarsson | c1d5891 | 2021-04-22 17:21:43 | [diff] [blame] | 337 | frame_transformer_delegate_ = |
| 338 | rtc::make_ref_counted<RtpVideoStreamReceiverFrameTransformerDelegate>( |
Tony Herre | 9d677f4 | 2023-07-11 12:41:06 | [diff] [blame] | 339 | this, clock_, std::move(frame_transformer), rtc::Thread::Current(), |
Tomas Gunnarsson | c1d5891 | 2021-04-22 17:21:43 | [diff] [blame] | 340 | config_.rtp.remote_ssrc); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 341 | frame_transformer_delegate_->Init(); |
| 342 | } |
| 343 | } |
| 344 | |
| 345 | RtpVideoStreamReceiver2::~RtpVideoStreamReceiver2() { |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 346 | if (packet_router_) |
| 347 | packet_router_->RemoveReceiveRtpModule(rtp_rtcp_.get()); |
Tommi | 7fbab87 | 2022-08-10 05:45:43 | [diff] [blame] | 348 | ulpfec_receiver_.reset(); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 349 | if (frame_transformer_delegate_) |
| 350 | frame_transformer_delegate_->Reset(); |
| 351 | } |
| 352 | |
| 353 | void RtpVideoStreamReceiver2::AddReceiveCodec( |
Niels Möller | 5401bad | 2020-08-11 10:17:42 | [diff] [blame] | 354 | uint8_t payload_type, |
Danil Chapovalov | 5653c95 | 2021-08-10 14:57:56 | [diff] [blame] | 355 | VideoCodecType video_codec, |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 356 | const std::map<std::string, std::string>& codec_params, |
| 357 | bool raw_payload) { |
Tommi | 376cf07 | 2021-05-31 17:14:38 | [diff] [blame] | 358 | RTC_DCHECK_RUN_ON(&packet_sequence_checker_); |
Tommi | 96c1a9b | 2022-09-29 10:24:02 | [diff] [blame] | 359 | if (codec_params.count(cricket::kH264FmtpSpsPpsIdrInKeyframe) > 0 || |
Erik Språng | eb3307f | 2022-08-22 09:06:06 | [diff] [blame] | 360 | field_trials_.IsEnabled("WebRTC-SpsPpsIdrIsH264Keyframe")) { |
Andrew Johnson | f288f5b | 2020-09-19 05:35:59 | [diff] [blame] | 361 | packet_buffer_.ForceSpsPpsIdrIsH264Keyframe(); |
| 362 | } |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 363 | payload_type_map_.emplace( |
Danil Chapovalov | 5653c95 | 2021-08-10 14:57:56 | [diff] [blame] | 364 | payload_type, raw_payload ? std::make_unique<VideoRtpDepacketizerRaw>() |
| 365 | : CreateVideoRtpDepacketizer(video_codec)); |
Niels Möller | 5401bad | 2020-08-11 10:17:42 | [diff] [blame] | 366 | pt_codec_params_.emplace(payload_type, codec_params); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 367 | } |
| 368 | |
Tommi | 96c1a9b | 2022-09-29 10:24:02 | [diff] [blame] | 369 | void 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 | |
| 396 | void 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 | |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 404 | absl::optional<Syncable::Info> RtpVideoStreamReceiver2::GetSyncInfo() const { |
Tommi | 376cf07 | 2021-05-31 17:14:38 | [diff] [blame] | 405 | RTC_DCHECK_RUN_ON(&packet_sequence_checker_); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 406 | Syncable::Info info; |
Danil Chapovalov | 9f39721 | 2023-02-27 18:49:31 | [diff] [blame] | 407 | absl::optional<RtpRtcpInterface::SenderReportStats> last_sr = |
| 408 | rtp_rtcp_->GetSenderReportStats(); |
| 409 | if (!last_sr.has_value()) { |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 410 | return absl::nullopt; |
| 411 | } |
Danil Chapovalov | 9f39721 | 2023-02-27 18:49:31 | [diff] [blame] | 412 | 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; |
Tommi | 63673fe | 2020-05-27 10:55:38 | [diff] [blame] | 415 | |
philipel | ce423ce | 2021-04-12 11:42:03 | [diff] [blame] | 416 | if (!last_received_rtp_timestamp_ || !last_received_rtp_system_time_) { |
Tommi | 63673fe | 2020-05-27 10:55:38 | [diff] [blame] | 417 | return absl::nullopt; |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 418 | } |
Tommi | 63673fe | 2020-05-27 10:55:38 | [diff] [blame] | 419 | info.latest_received_capture_timestamp = *last_received_rtp_timestamp_; |
philipel | ce423ce | 2021-04-12 11:42:03 | [diff] [blame] | 420 | info.latest_receive_time_ms = last_received_rtp_system_time_->ms(); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 421 | |
| 422 | // Leaves info.current_delay_ms uninitialized. |
| 423 | return info; |
| 424 | } |
| 425 | |
| 426 | RtpVideoStreamReceiver2::ParseGenericDependenciesResult |
| 427 | RtpVideoStreamReceiver2::ParseGenericDependenciesExtension( |
| 428 | const RtpPacketReceived& rtp_packet, |
| 429 | RTPVideoHeader* video_header) { |
Danil Chapovalov | 6e7c268 | 2022-07-25 13:58:28 | [diff] [blame] | 430 | RTC_DCHECK_RUN_ON(&packet_sequence_checker_); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 431 | 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. |
philipel | c4ea5ae | 2023-01-20 12:13:01 | [diff] [blame] | 440 | 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 | } |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 446 | 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 | |
| 536 | void RtpVideoStreamReceiver2::OnReceivedPayloadData( |
| 537 | rtc::CopyOnWriteBuffer codec_payload, |
| 538 | const RtpPacketReceived& rtp_packet, |
| 539 | const RTPVideoHeader& video) { |
Tommi | 376cf07 | 2021-05-31 17:14:38 | [diff] [blame] | 540 | RTC_DCHECK_RUN_ON(&packet_sequence_checker_); |
philipel | 9599b3c | 2021-05-11 09:30:52 | [diff] [blame] | 541 | |
| 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 Bazzica | a1d0356 | 2022-09-19 16:05:29 | [diff] [blame] | 547 | |
| 548 | RtpPacketInfo& packet_info = |
philipel | 9599b3c | 2021-05-11 09:30:52 | [diff] [blame] | 549 | packet_infos_ |
Alessio Bazzica | a1d0356 | 2022-09-19 16:05:29 | [diff] [blame] | 550 | .emplace(unwrapped_rtp_seq_num, |
| 551 | RtpPacketInfo(rtp_packet.Ssrc(), rtp_packet.Csrcs(), |
| 552 | rtp_packet.Timestamp(), |
| 553 | /*receive_time_ms=*/clock_->CurrentTime())) |
philipel | 9599b3c | 2021-05-11 09:30:52 | [diff] [blame] | 554 | .first->second; |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 555 | |
| 556 | // Try to extrapolate absolute capture time if it is missing. |
philipel | 9599b3c | 2021-05-11 09:30:52 | [diff] [blame] | 557 | packet_info.set_absolute_capture_time( |
Minyue Li | 63b3095 | 2021-05-19 12:38:25 | [diff] [blame] | 558 | absolute_capture_time_interpolator_.OnReceivePacket( |
| 559 | AbsoluteCaptureTimeInterpolator::GetSource(packet_info.ssrc(), |
| 560 | packet_info.csrcs()), |
philipel | 9599b3c | 2021-05-11 09:30:52 | [diff] [blame] | 561 | packet_info.rtp_timestamp(), |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 562 | // Assume frequency is the same one for all video frames. |
Alessio Bazzica | a1d0356 | 2022-09-19 16:05:29 | [diff] [blame] | 563 | kVideoPayloadTypeFrequency, |
| 564 | rtp_packet.GetExtension<AbsoluteCaptureTimeExtension>())); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 565 | |
| 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(); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 571 | |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 572 | 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 | } |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 582 | |
| 583 | ParseGenericDependenciesResult generic_descriptor_state = |
| 584 | ParseGenericDependenciesExtension(rtp_packet, &video_header); |
philipel | ce423ce | 2021-04-12 11:42:03 | [diff] [blame] | 585 | |
| 586 | if (!rtp_packet.recovered()) { |
| 587 | UpdatePacketReceiveTimestamps( |
| 588 | rtp_packet, video_header.frame_type == VideoFrameType::kVideoFrameKey); |
| 589 | } |
| 590 | |
philipel | 1709341 | 2022-06-13 11:14:43 | [diff] [blame] | 591 | 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 | } |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 601 | return; |
philipel | 1709341 | 2022-06-13 11:14:43 | [diff] [blame] | 602 | } |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 603 | |
| 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 Leconte | b258c56 | 2021-03-18 12:50:42 | [diff] [blame] | 619 | video_header.video_frame_tracking_id = |
| 620 | rtp_packet.GetExtension<VideoFrameTrackingIdExtension>(); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 621 | |
| 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 Chapovalov | 46cc32d | 2022-01-17 13:41:13 | [diff] [blame] | 682 | [[fallthrough]]; |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 683 | 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 K | 5e5d017 | 2022-12-22 12:43:41 | [diff] [blame] | 699 | void RtpVideoStreamReceiver2::OnRecoveredPacket( |
| 700 | const RtpPacketReceived& packet) { |
Tommi | 376cf07 | 2021-05-31 17:14:38 | [diff] [blame] | 701 | RTC_DCHECK_RUN_ON(&packet_sequence_checker_); |
Tommi | 1c5f317 | 2022-08-13 08:43:59 | [diff] [blame] | 702 | if (packet.PayloadType() == red_payload_type_) { |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 703 | RTC_LOG(LS_WARNING) << "Discarding recovered packet with RED encapsulation"; |
| 704 | return; |
| 705 | } |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 706 | ReceivePacket(packet); |
| 707 | } |
| 708 | |
| 709 | // This method handles both regular RTP packets and packets recovered |
| 710 | // via FlexFEC. |
| 711 | void RtpVideoStreamReceiver2::OnRtpPacket(const RtpPacketReceived& packet) { |
Tommi | 376cf07 | 2021-05-31 17:14:38 | [diff] [blame] | 712 | RTC_DCHECK_RUN_ON(&packet_sequence_checker_); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 713 | |
Tommi | 376cf07 | 2021-05-31 17:14:38 | [diff] [blame] | 714 | if (!receiving_) |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 715 | return; |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 716 | |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 717 | 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 | |
Tommi | 185f10c | 2022-08-02 09:51:20 | [diff] [blame] | 726 | if (packet_sink_) { |
| 727 | packet_sink_->OnRtpPacket(packet); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 728 | } |
| 729 | } |
| 730 | |
| 731 | void RtpVideoStreamReceiver2::RequestKeyFrame() { |
Tommi | 63673fe | 2020-05-27 10:55:38 | [diff] [blame] | 732 | RTC_DCHECK_RUN_ON(&worker_task_checker_); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 733 | // 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. |
philipel | 27b35a7 | 2022-07-05 07:59:55 | [diff] [blame] | 736 | if (keyframe_request_method_ == KeyFrameReqMethod::kPliRtcp) { |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 737 | rtp_rtcp_->SendPictureLossIndication(); |
Nico Grunbaum | a36f10b | 2021-12-09 04:59:31 | [diff] [blame] | 738 | } else if (keyframe_request_method_ == KeyFrameReqMethod::kFirRtcp) { |
| 739 | rtp_rtcp_->SendFullIntraRequest(); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 740 | } |
| 741 | } |
| 742 | |
philipel | b981394 | 2022-07-05 09:31:36 | [diff] [blame] | 743 | void RtpVideoStreamReceiver2::SendNack( |
| 744 | const std::vector<uint16_t>& sequence_numbers, |
| 745 | bool /*buffering_allowed*/) { |
| 746 | rtp_rtcp_->SendNack(sequence_numbers); |
| 747 | } |
| 748 | |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 749 | void 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 | |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 759 | bool RtpVideoStreamReceiver2::IsDecryptable() const { |
Tommi | 63673fe | 2020-05-27 10:55:38 | [diff] [blame] | 760 | RTC_DCHECK_RUN_ON(&worker_task_checker_); |
| 761 | return frames_decryptable_; |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 762 | } |
| 763 | |
| 764 | void RtpVideoStreamReceiver2::OnInsertedPacket( |
| 765 | video_coding::PacketBuffer::InsertResult result) { |
Danil Chapovalov | 6e7c268 | 2022-07-25 13:58:28 | [diff] [blame] | 766 | RTC_DCHECK_RUN_ON(&packet_sequence_checker_); |
Tommi | 31b5649 | 2021-06-01 07:50:26 | [diff] [blame] | 767 | RTC_DCHECK_RUN_ON(&worker_task_checker_); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 768 | 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()); |
philipel | 9599b3c | 2021-05-11 09:30:52 | [diff] [blame] | 780 | int64_t unwrapped_rtp_seq_num = |
| 781 | rtp_seq_num_unwrapper_.Unwrap(packet->seq_num); |
Tommi | 96c1a9b | 2022-09-29 10:24:02 | [diff] [blame] | 782 | RTC_DCHECK_GT(packet_infos_.count(unwrapped_rtp_seq_num), 0); |
philipel | 9599b3c | 2021-05-11 09:30:52 | [diff] [blame] | 783 | RtpPacketInfo& packet_info = packet_infos_[unwrapped_rtp_seq_num]; |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 784 | if (packet->is_first_packet_in_frame()) { |
| 785 | first_packet = packet.get(); |
| 786 | max_nack_count = packet->times_nacked; |
philipel | 9599b3c | 2021-05-11 09:30:52 | [diff] [blame] | 787 | min_recv_time = packet_info.receive_time().ms(); |
| 788 | max_recv_time = packet_info.receive_time().ms(); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 789 | } else { |
| 790 | max_nack_count = std::max(max_nack_count, packet->times_nacked); |
philipel | 9599b3c | 2021-05-11 09:30:52 | [diff] [blame] | 791 | 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()); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 793 | } |
| 794 | payloads.emplace_back(packet->video_payload); |
philipel | 9599b3c | 2021-05-11 09:30:52 | [diff] [blame] | 795 | packet_infos.push_back(packet_info); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 796 | |
| 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; |
philipel | ca18809 | 2021-03-23 11:00:49 | [diff] [blame] | 810 | OnAssembledFrame(std::make_unique<RtpFrameObject>( |
philipel | 7c7885c | 2021-03-12 13:33:46 | [diff] [blame] | 811 | 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)), // |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 827 | std::move(bitstream))); |
Emil Lundmark | af5ca5a | 2021-11-30 09:37:25 | [diff] [blame] | 828 | payloads.clear(); |
| 829 | packet_infos.clear(); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 830 | } |
| 831 | } |
| 832 | RTC_DCHECK(frame_boundary); |
| 833 | if (result.buffer_cleared) { |
philipel | b849311 | 2021-04-16 10:10:22 | [diff] [blame] | 834 | last_received_rtp_system_time_.reset(); |
| 835 | last_received_keyframe_rtp_system_time_.reset(); |
| 836 | last_received_keyframe_rtp_timestamp_.reset(); |
philipel | 9599b3c | 2021-05-11 09:30:52 | [diff] [blame] | 837 | packet_infos_.clear(); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 838 | RequestKeyFrame(); |
| 839 | } |
| 840 | } |
| 841 | |
| 842 | void RtpVideoStreamReceiver2::OnAssembledFrame( |
philipel | ca18809 | 2021-03-23 11:00:49 | [diff] [blame] | 843 | std::unique_ptr<RtpFrameObject> frame) { |
Danil Chapovalov | 6e7c268 | 2022-07-25 13:58:28 | [diff] [blame] | 844 | RTC_DCHECK_RUN_ON(&packet_sequence_checker_); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 845 | 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 Titov | ab30d72 | 2021-07-27 14:22:11 | [diff] [blame] | 862 | // `loss_notification_controller_`, if present, would have already |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 863 | // 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 Titov | ab30d72 | 2021-07-27 14:22:11 | [diff] [blame] | 872 | // Reset `reference_finder_` if `frame` is new and the codec have changed. |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 873 | 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 Titov | ab30d72 | 2021-07-27 14:22:11 | [diff] [blame] | 879 | // When we reset the `reference_finder_` we don't want new picture ids |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 880 | // to overlap with old picture ids. To ensure that doesn't happen we |
Artem Titov | ab30d72 | 2021-07-27 14:22:11 | [diff] [blame] | 881 | // start from the `last_completed_picture_id_` and add an offset in case |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 882 | // of reordering. |
philipel | 6a67150 | 2021-03-22 13:17:09 | [diff] [blame] | 883 | reference_finder_ = std::make_unique<RtpFrameReferenceFinder>( |
philipel | 6a67150 | 2021-03-22 13:17:09 | [diff] [blame] | 884 | last_completed_picture_id_ + std::numeric_limits<uint16_t>::max()); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 885 | 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 { |
philipel | 2182096 | 2021-05-25 13:35:57 | [diff] [blame] | 905 | OnCompleteFrames(reference_finder_->ManageFrame(std::move(frame))); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 906 | } |
| 907 | } |
| 908 | |
philipel | 2182096 | 2021-05-25 13:35:57 | [diff] [blame] | 909 | void RtpVideoStreamReceiver2::OnCompleteFrames( |
| 910 | RtpFrameReferenceFinder::ReturnVector frames) { |
Danil Chapovalov | 6e7c268 | 2022-07-25 13:58:28 | [diff] [blame] | 911 | RTC_DCHECK_RUN_ON(&packet_sequence_checker_); |
philipel | 2182096 | 2021-05-25 13:35:57 | [diff] [blame] | 912 | for (auto& frame : frames) { |
Evan Shrubsole | a43ffb3 | 2021-09-10 15:09:51 | [diff] [blame] | 913 | last_seq_num_for_pic_id_[frame->Id()] = frame->last_seq_num(); |
Tommi | 63673fe | 2020-05-27 10:55:38 | [diff] [blame] | 914 | |
philipel | 2182096 | 2021-05-25 13:35:57 | [diff] [blame] | 915 | last_completed_picture_id_ = |
| 916 | std::max(last_completed_picture_id_, frame->Id()); |
| 917 | complete_frame_callback_->OnCompleteFrame(std::move(frame)); |
| 918 | } |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 919 | } |
| 920 | |
| 921 | void RtpVideoStreamReceiver2::OnDecryptedFrame( |
philipel | ca18809 | 2021-03-23 11:00:49 | [diff] [blame] | 922 | std::unique_ptr<RtpFrameObject> frame) { |
Tommi | 376cf07 | 2021-05-31 17:14:38 | [diff] [blame] | 923 | RTC_DCHECK_RUN_ON(&packet_sequence_checker_); |
philipel | 2182096 | 2021-05-25 13:35:57 | [diff] [blame] | 924 | OnCompleteFrames(reference_finder_->ManageFrame(std::move(frame))); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 925 | } |
| 926 | |
| 927 | void RtpVideoStreamReceiver2::OnDecryptionStatusChange( |
| 928 | FrameDecryptorInterface::Status status) { |
Tommi | 63673fe | 2020-05-27 10:55:38 | [diff] [blame] | 929 | RTC_DCHECK_RUN_ON(&worker_task_checker_); |
| 930 | // Called from BufferedFrameDecryptor::DecryptFrame. |
| 931 | frames_decryptable_ = |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 932 | (status == FrameDecryptorInterface::Status::kOk) || |
Tommi | 63673fe | 2020-05-27 10:55:38 | [diff] [blame] | 933 | (status == FrameDecryptorInterface::Status::kRecoverable); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 934 | } |
| 935 | |
| 936 | void RtpVideoStreamReceiver2::SetFrameDecryptor( |
| 937 | rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor) { |
Tommi | 376cf07 | 2021-05-31 17:14:38 | [diff] [blame] | 938 | // 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_); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 941 | if (buffered_frame_decryptor_ == nullptr) { |
| 942 | buffered_frame_decryptor_ = |
Jonas Oreland | 8ca0613 | 2022-03-14 11:52:48 | [diff] [blame] | 943 | std::make_unique<BufferedFrameDecryptor>(this, this, field_trials_); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 944 | } |
| 945 | buffered_frame_decryptor_->SetFrameDecryptor(std::move(frame_decryptor)); |
| 946 | } |
| 947 | |
| 948 | void RtpVideoStreamReceiver2::SetDepacketizerToDecoderFrameTransformer( |
| 949 | rtc::scoped_refptr<FrameTransformerInterface> frame_transformer) { |
Tommi | 63673fe | 2020-05-27 10:55:38 | [diff] [blame] | 950 | RTC_DCHECK_RUN_ON(&worker_task_checker_); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 951 | frame_transformer_delegate_ = |
Tomas Gunnarsson | c1d5891 | 2021-04-22 17:21:43 | [diff] [blame] | 952 | rtc::make_ref_counted<RtpVideoStreamReceiverFrameTransformerDelegate>( |
Tony Herre | 9d677f4 | 2023-07-11 12:41:06 | [diff] [blame] | 953 | this, clock_, std::move(frame_transformer), rtc::Thread::Current(), |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 954 | config_.rtp.remote_ssrc); |
| 955 | frame_transformer_delegate_->Init(); |
| 956 | } |
| 957 | |
| 958 | void RtpVideoStreamReceiver2::UpdateRtt(int64_t max_rtt_ms) { |
Tommi | 3900f21 | 2022-08-05 14:21:54 | [diff] [blame] | 959 | RTC_DCHECK_RUN_ON(&packet_sequence_checker_); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 960 | if (nack_module_) |
| 961 | nack_module_->UpdateRtt(max_rtt_ms); |
| 962 | } |
| 963 | |
Tommi | 1331c18 | 2022-05-17 08:13:52 | [diff] [blame] | 964 | void RtpVideoStreamReceiver2::OnLocalSsrcChange(uint32_t local_ssrc) { |
| 965 | RTC_DCHECK_RUN_ON(&packet_sequence_checker_); |
| 966 | rtp_rtcp_->SetLocalSsrc(local_ssrc); |
| 967 | } |
| 968 | |
Tommi | aeb4412 | 2022-07-14 16:33:42 | [diff] [blame] | 969 | void RtpVideoStreamReceiver2::SetRtcpMode(RtcpMode mode) { |
| 970 | RTC_DCHECK_RUN_ON(&packet_sequence_checker_); |
| 971 | rtp_rtcp_->SetRTCPStatus(mode); |
| 972 | } |
| 973 | |
Tommi | 2e80936 | 2022-08-12 20:06:20 | [diff] [blame] | 974 | void RtpVideoStreamReceiver2::SetReferenceTimeReport(bool enabled) { |
| 975 | RTC_DCHECK_RUN_ON(&packet_sequence_checker_); |
| 976 | rtp_rtcp_->SetNonSenderRttMeasurement(enabled); |
| 977 | } |
| 978 | |
Tommi | 185f10c | 2022-08-02 09:51:20 | [diff] [blame] | 979 | void RtpVideoStreamReceiver2::SetPacketSink( |
| 980 | RtpPacketSinkInterface* packet_sink) { |
| 981 | RTC_DCHECK_RUN_ON(&packet_sequence_checker_); |
| 982 | packet_sink_ = packet_sink; |
| 983 | } |
| 984 | |
Tommi | e644a4b | 2022-08-03 14:13:53 | [diff] [blame] | 985 | void 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 | |
Tommi | 3900f21 | 2022-08-05 14:21:54 | [diff] [blame] | 997 | void 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 | |
Tommi | 66d20c4 | 2022-08-12 13:05:17 | [diff] [blame] | 1012 | int 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 | |
Tommi | 1c5f317 | 2022-08-13 08:43:59 | [diff] [blame] | 1017 | int RtpVideoStreamReceiver2::red_payload_type() const { |
| 1018 | RTC_DCHECK_RUN_ON(&packet_sequence_checker_); |
| 1019 | return red_payload_type_; |
| 1020 | } |
| 1021 | |
Tommi | e1bd833 | 2022-08-13 08:44:10 | [diff] [blame] | 1022 | void RtpVideoStreamReceiver2::SetProtectionPayloadTypes( |
| 1023 | int red_payload_type, |
| 1024 | int ulpfec_payload_type) { |
Tommi | 1c5f317 | 2022-08-13 08:43:59 | [diff] [blame] | 1025 | RTC_DCHECK_RUN_ON(&packet_sequence_checker_); |
Tommi | e1bd833 | 2022-08-13 08:44:10 | [diff] [blame] | 1026 | RTC_DCHECK(red_payload_type >= -1 && red_payload_type < 0x80); |
| 1027 | RTC_DCHECK(ulpfec_payload_type >= -1 && ulpfec_payload_type < 0x80); |
Sergey Silkin | 1cb3cde | 2022-11-01 08:56:59 | [diff] [blame] | 1028 | red_payload_type_ = red_payload_type; |
Per K | 5e5d017 | 2022-12-22 12:43:41 | [diff] [blame] | 1029 | ulpfec_receiver_ = |
| 1030 | MaybeConstructUlpfecReceiver(config_.rtp.remote_ssrc, red_payload_type, |
| 1031 | ulpfec_payload_type, this, clock_); |
Tommi | 66d20c4 | 2022-08-12 13:05:17 | [diff] [blame] | 1032 | } |
| 1033 | |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 1034 | absl::optional<int64_t> RtpVideoStreamReceiver2::LastReceivedPacketMs() const { |
Tommi | 376cf07 | 2021-05-31 17:14:38 | [diff] [blame] | 1035 | RTC_DCHECK_RUN_ON(&packet_sequence_checker_); |
philipel | ce423ce | 2021-04-12 11:42:03 | [diff] [blame] | 1036 | if (last_received_rtp_system_time_) { |
| 1037 | return absl::optional<int64_t>(last_received_rtp_system_time_->ms()); |
| 1038 | } |
| 1039 | return absl::nullopt; |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 1040 | } |
| 1041 | |
Philipp Hancke | 5f4a7e0 | 2023-07-03 09:18:37 | [diff] [blame] | 1042 | absl::optional<uint32_t> |
| 1043 | RtpVideoStreamReceiver2::LastReceivedFrameRtpTimestamp() const { |
| 1044 | RTC_DCHECK_RUN_ON(&packet_sequence_checker_); |
| 1045 | return last_received_rtp_timestamp_; |
| 1046 | } |
| 1047 | |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 1048 | absl::optional<int64_t> RtpVideoStreamReceiver2::LastReceivedKeyframePacketMs() |
| 1049 | const { |
Tommi | 376cf07 | 2021-05-31 17:14:38 | [diff] [blame] | 1050 | RTC_DCHECK_RUN_ON(&packet_sequence_checker_); |
philipel | ce423ce | 2021-04-12 11:42:03 | [diff] [blame] | 1051 | 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; |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 1056 | } |
| 1057 | |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 1058 | void RtpVideoStreamReceiver2::ManageFrame( |
philipel | ca18809 | 2021-03-23 11:00:49 | [diff] [blame] | 1059 | std::unique_ptr<RtpFrameObject> frame) { |
Tommi | 376cf07 | 2021-05-31 17:14:38 | [diff] [blame] | 1060 | RTC_DCHECK_RUN_ON(&packet_sequence_checker_); |
philipel | 2182096 | 2021-05-25 13:35:57 | [diff] [blame] | 1061 | OnCompleteFrames(reference_finder_->ManageFrame(std::move(frame))); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 1062 | } |
| 1063 | |
| 1064 | void RtpVideoStreamReceiver2::ReceivePacket(const RtpPacketReceived& packet) { |
Danil Chapovalov | 6e7c268 | 2022-07-25 13:58:28 | [diff] [blame] | 1065 | RTC_DCHECK_RUN_ON(&packet_sequence_checker_); |
Tommi | 3900f21 | 2022-08-05 14:21:54 | [diff] [blame] | 1066 | |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 1067 | 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 | } |
Tommi | 1c5f317 | 2022-08-13 08:43:59 | [diff] [blame] | 1074 | if (packet.PayloadType() == red_payload_type_) { |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 1075 | 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 | |
| 1094 | void RtpVideoStreamReceiver2::ParseAndHandleEncapsulatingHeader( |
| 1095 | const RtpPacketReceived& packet) { |
Danil Chapovalov | 6e7c268 | 2022-07-25 13:58:28 | [diff] [blame] | 1096 | RTC_DCHECK_RUN_ON(&packet_sequence_checker_); |
Tommi | 1c5f317 | 2022-08-13 08:43:59 | [diff] [blame] | 1097 | RTC_DCHECK_EQ(packet.PayloadType(), red_payload_type_); |
Tommi | 66d20c4 | 2022-08-12 13:05:17 | [diff] [blame] | 1098 | |
| 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(); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 1109 | } |
| 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. |
| 1115 | void RtpVideoStreamReceiver2::NotifyReceiverOfEmptyPacket(uint16_t seq_num) { |
Danil Chapovalov | 6e7c268 | 2022-07-25 13:58:28 | [diff] [blame] | 1116 | RTC_DCHECK_RUN_ON(&packet_sequence_checker_); |
Tommi | 31b5649 | 2021-06-01 07:50:26 | [diff] [blame] | 1117 | RTC_DCHECK_RUN_ON(&worker_task_checker_); |
| 1118 | |
philipel | 2182096 | 2021-05-25 13:35:57 | [diff] [blame] | 1119 | OnCompleteFrames(reference_finder_->PaddingReceived(seq_num)); |
Tommi | 63673fe | 2020-05-27 10:55:38 | [diff] [blame] | 1120 | |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 1121 | 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 | |
| 1133 | bool RtpVideoStreamReceiver2::DeliverRtcp(const uint8_t* rtcp_packet, |
| 1134 | size_t rtcp_packet_length) { |
Tommi | 376cf07 | 2021-05-31 17:14:38 | [diff] [blame] | 1135 | RTC_DCHECK_RUN_ON(&packet_sequence_checker_); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 1136 | |
| 1137 | if (!receiving_) { |
| 1138 | return false; |
| 1139 | } |
| 1140 | |
Harald Alvestrand | 1f206b8 | 2023-02-01 11:12:46 | [diff] [blame] | 1141 | rtp_rtcp_->IncomingRtcpPacket( |
| 1142 | rtc::MakeArrayView(rtcp_packet, rtcp_packet_length)); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 1143 | |
Danil Chapovalov | 8095d02 | 2023-05-09 07:59:46 | [diff] [blame] | 1144 | absl::optional<TimeDelta> rtt = rtp_rtcp_->LastRtt(); |
| 1145 | if (!rtt.has_value()) { |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 1146 | // Waiting for valid rtt. |
| 1147 | return true; |
| 1148 | } |
Danil Chapovalov | 9f39721 | 2023-02-27 18:49:31 | [diff] [blame] | 1149 | |
| 1150 | absl::optional<RtpRtcpInterface::SenderReportStats> last_sr = |
| 1151 | rtp_rtcp_->GetSenderReportStats(); |
| 1152 | if (!last_sr.has_value()) { |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 1153 | // Waiting for RTCP. |
| 1154 | return true; |
| 1155 | } |
Danil Chapovalov | 9f39721 | 2023-02-27 18:49:31 | [diff] [blame] | 1156 | int64_t time_since_received = clock_->CurrentNtpInMilliseconds() - |
| 1157 | last_sr->last_arrival_timestamp.ToMs(); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 1158 | // Don't use old SRs to estimate time. |
Niels Möller | be74b80 | 2022-03-18 13:10:15 | [diff] [blame] | 1159 | if (time_since_received <= 1) { |
Danil Chapovalov | 8095d02 | 2023-05-09 07:59:46 | [diff] [blame] | 1160 | ntp_estimator_.UpdateRtcpTimestamp(*rtt, last_sr->last_remote_timestamp, |
Danil Chapovalov | 9f39721 | 2023-02-27 18:49:31 | [diff] [blame] | 1161 | last_sr->last_remote_rtp_timestamp); |
Danil Chapovalov | edcb25b | 2022-05-10 09:33:20 | [diff] [blame] | 1162 | absl::optional<int64_t> remote_to_local_clock_offset = |
| 1163 | ntp_estimator_.EstimateRemoteToLocalClockOffset(); |
| 1164 | if (remote_to_local_clock_offset.has_value()) { |
Minyue Li | 63b3095 | 2021-05-19 12:38:25 | [diff] [blame] | 1165 | capture_clock_offset_updater_.SetRemoteToLocalClockOffset( |
Danil Chapovalov | edcb25b | 2022-05-10 09:33:20 | [diff] [blame] | 1166 | *remote_to_local_clock_offset); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 1167 | } |
| 1168 | } |
| 1169 | |
| 1170 | return true; |
| 1171 | } |
| 1172 | |
| 1173 | void RtpVideoStreamReceiver2::FrameContinuous(int64_t picture_id) { |
Tommi | 376cf07 | 2021-05-31 17:14:38 | [diff] [blame] | 1174 | RTC_DCHECK_RUN_ON(&packet_sequence_checker_); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 1175 | if (!nack_module_) |
| 1176 | return; |
| 1177 | |
| 1178 | int seq_num = -1; |
Tommi | 63673fe | 2020-05-27 10:55:38 | [diff] [blame] | 1179 | 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; |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 1182 | if (seq_num != -1) |
| 1183 | nack_module_->ClearUpTo(seq_num); |
| 1184 | } |
| 1185 | |
| 1186 | void RtpVideoStreamReceiver2::FrameDecoded(int64_t picture_id) { |
Tommi | 376cf07 | 2021-05-31 17:14:38 | [diff] [blame] | 1187 | RTC_DCHECK_RUN_ON(&packet_sequence_checker_); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 1188 | int seq_num = -1; |
Tommi | 63673fe | 2020-05-27 10:55:38 | [diff] [blame] | 1189 | 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); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 1194 | } |
Tommi | 63673fe | 2020-05-27 10:55:38 | [diff] [blame] | 1195 | |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 1196 | if (seq_num != -1) { |
philipel | 9599b3c | 2021-05-11 09:30:52 | [diff] [blame] | 1197 | 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)); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 1200 | packet_buffer_.ClearTo(seq_num); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 1201 | reference_finder_->ClearTo(seq_num); |
| 1202 | } |
| 1203 | } |
| 1204 | |
| 1205 | void RtpVideoStreamReceiver2::SignalNetworkState(NetworkState state) { |
Tommi | 63673fe | 2020-05-27 10:55:38 | [diff] [blame] | 1206 | RTC_DCHECK_RUN_ON(&worker_task_checker_); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 1207 | rtp_rtcp_->SetRTCPStatus(state == kNetworkUp ? config_.rtp.rtcp_mode |
| 1208 | : RtcpMode::kOff); |
| 1209 | } |
| 1210 | |
| 1211 | void RtpVideoStreamReceiver2::StartReceive() { |
Tommi | 376cf07 | 2021-05-31 17:14:38 | [diff] [blame] | 1212 | RTC_DCHECK_RUN_ON(&packet_sequence_checker_); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 1213 | receiving_ = true; |
| 1214 | } |
| 1215 | |
| 1216 | void RtpVideoStreamReceiver2::StopReceive() { |
Tommi | 376cf07 | 2021-05-31 17:14:38 | [diff] [blame] | 1217 | RTC_DCHECK_RUN_ON(&packet_sequence_checker_); |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 1218 | receiving_ = false; |
| 1219 | } |
| 1220 | |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 1221 | void RtpVideoStreamReceiver2::InsertSpsPpsIntoTracker(uint8_t payload_type) { |
Danil Chapovalov | 6e7c268 | 2022-07-25 13:58:28 | [diff] [blame] | 1222 | RTC_DCHECK_RUN_ON(&packet_sequence_checker_); |
Tommi | 31b5649 | 2021-06-01 07:50:26 | [diff] [blame] | 1223 | RTC_DCHECK_RUN_ON(&worker_task_checker_); |
| 1224 | |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 1225 | 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 | |
philipel | ce423ce | 2021-04-12 11:42:03 | [diff] [blame] | 1247 | void RtpVideoStreamReceiver2::UpdatePacketReceiveTimestamps( |
| 1248 | const RtpPacketReceived& packet, |
| 1249 | bool is_keyframe) { |
| 1250 | Timestamp now = clock_->CurrentTime(); |
philipel | b849311 | 2021-04-16 10:10:22 | [diff] [blame] | 1251 | if (is_keyframe || |
| 1252 | last_received_keyframe_rtp_timestamp_ == packet.Timestamp()) { |
| 1253 | last_received_keyframe_rtp_timestamp_ = packet.Timestamp(); |
philipel | ce423ce | 2021-04-12 11:42:03 | [diff] [blame] | 1254 | 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() |
Tommi | 2497a27 | 2021-05-05 10:33:00 | [diff] [blame] | 1266 | << ", arrival time: " << ToString(packet.arrival_time()); |
philipel | ce423ce | 2021-04-12 11:42:03 | [diff] [blame] | 1267 | 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 | |
Tommi | d3807da | 2020-05-22 15:36:36 | [diff] [blame] | 1280 | } // namespace webrtc |