From 3900f21702c4624e354f921a5a3e9cfd9f31f736 Mon Sep 17 00:00:00 2001 From: Tommi Date: Fri, 5 Aug 2022 16:21:54 +0200 Subject: [PATCH] Make nack history configurable. This allows for `config_.rtp.nack.rtp_history_ms` to be modified without deleting and recreating video receive streams. Bug: webrtc:11993 Change-Id: I8ba132b22fe0e6de03d1c42fc38a570cbe138817 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/269301 Reviewed-by: Danil Chapovalov Commit-Queue: Tomas Gunnarsson Cr-Commit-Position: refs/heads/main@{#37701} --- call/video_receive_stream.h | 5 ++ media/engine/fake_webrtc_call.h | 4 + media/engine/webrtc_video_engine.cc | 32 +++---- video/frame_buffer_proxy.cc | 8 ++ video/frame_buffer_proxy.h | 2 + video/rtp_video_stream_receiver2.cc | 34 ++++--- video/rtp_video_stream_receiver2.h | 10 ++- video/video_receive_stream2.cc | 89 +++++++++++++------ video/video_receive_stream2.h | 15 ++-- video/video_receive_stream_timeout_tracker.cc | 9 ++ video/video_receive_stream_timeout_tracker.h | 6 +- 11 files changed, 149 insertions(+), 65 deletions(-) diff --git a/call/video_receive_stream.h b/call/video_receive_stream.h index 998710d044..451203b01f 100644 --- a/call/video_receive_stream.h +++ b/call/video_receive_stream.h @@ -298,6 +298,11 @@ class VideoReceiveStreamInterface : public MediaReceiveStreamInterface { // thread. virtual void SetLossNotificationEnabled(bool enabled) = 0; + // Modify `rtp.nack.rtp_history_ms` post construction. Setting this value + // to 0 disables nack. + // Must be called on the packet delivery thread. + virtual void SetNackHistory(TimeDelta history) = 0; + protected: virtual ~VideoReceiveStreamInterface() {} }; diff --git a/media/engine/fake_webrtc_call.h b/media/engine/fake_webrtc_call.h index 9276a78784..c807d3163e 100644 --- a/media/engine/fake_webrtc_call.h +++ b/media/engine/fake_webrtc_call.h @@ -293,6 +293,10 @@ class FakeVideoReceiveStream final config_.rtp.lntf.enabled = enabled; } + void SetNackHistory(webrtc::TimeDelta history) override { + config_.rtp.nack.rtp_history_ms = history.ms(); + } + void Start() override; void Stop() override; diff --git a/media/engine/webrtc_video_engine.cc b/media/engine/webrtc_video_engine.cc index 4cc18fbd31..c562abe9dd 100644 --- a/media/engine/webrtc_video_engine.cc +++ b/media/engine/webrtc_video_engine.cc @@ -2991,26 +2991,32 @@ bool WebRtcVideoChannel::WebRtcVideoReceiveStream::ReconfigureCodecs( stream_->SetLossNotificationEnabled(has_lntf); } + int new_history_ms = config_.rtp.nack.rtp_history_ms; const int rtp_history_ms = HasNack(codec.codec) ? kNackHistoryMs : 0; if (rtp_history_ms != config_.rtp.nack.rtp_history_ms) { - config_.rtp.nack.rtp_history_ms = rtp_history_ms; - recreate_needed = true; + new_history_ms = rtp_history_ms; } // The rtx-time parameter can be used to override the hardcoded default for // the NACK buffer length. - if (codec.rtx_time != -1 && config_.rtp.nack.rtp_history_ms != 0) { - config_.rtp.nack.rtp_history_ms = codec.rtx_time; - recreate_needed = true; + if (codec.rtx_time != -1 && new_history_ms != 0) { + new_history_ms = codec.rtx_time; + } + + if (config_.rtp.nack.rtp_history_ms != new_history_ms) { + config_.rtp.nack.rtp_history_ms = new_history_ms; + stream_->SetNackHistory(webrtc::TimeDelta::Millis(new_history_ms)); } const bool has_rtr = HasRrtr(codec.codec); if (has_rtr != config_.rtp.rtcp_xr.receiver_reference_time_report) { + // TODO(tommi): Look into if/when this happens in practice. config_.rtp.rtcp_xr.receiver_reference_time_report = has_rtr; recreate_needed = true; } if (codec.ulpfec.red_rtx_payload_type != -1) { + // TODO(tommi): Look into if/when this happens in practice. rtx_associated_payload_types[codec.ulpfec.red_rtx_payload_type] = codec.ulpfec.red_payload_type; } @@ -3068,22 +3074,8 @@ void WebRtcVideoChannel::WebRtcVideoReceiveStream::SetFeedbackParameters( int nack_history_ms = nack_enabled ? rtx_time != -1 ? rtx_time : kNackHistoryMs : 0; - if (config_.rtp.nack.rtp_history_ms == nack_history_ms) { - RTC_LOG(LS_INFO) - << "Ignoring call to SetFeedbackParameters because parameters are " - "unchanged; nack=" - << nack_enabled << ", rtx_time=" << rtx_time; - return; - } - - RTC_LOG_F(LS_INFO) << "(recv) because of SetFeedbackParameters; nack=" - << nack_enabled << ". rtp_history_ms " - << config_.rtp.nack.rtp_history_ms << "->" - << nack_history_ms; - config_.rtp.nack.rtp_history_ms = nack_history_ms; - - RecreateReceiveStream(); + stream_->SetNackHistory(webrtc::TimeDelta::Millis(nack_history_ms)); } void WebRtcVideoChannel::WebRtcVideoReceiveStream::SetFlexFecPayload( diff --git a/video/frame_buffer_proxy.cc b/video/frame_buffer_proxy.cc index 9f79c9267a..f8901aed3a 100644 --- a/video/frame_buffer_proxy.cc +++ b/video/frame_buffer_proxy.cc @@ -173,6 +173,14 @@ class FrameBuffer3Proxy : public FrameBufferProxy { jitter_estimator_.UpdateRtt(TimeDelta::Millis(max_rtt_ms)); } + void SetMaxWaits(TimeDelta max_wait_for_keyframe, + TimeDelta max_wait_for_frame) override { + RTC_DCHECK_RUN_ON(&worker_sequence_checker_); + timeout_tracker_.SetTimeouts( + {.max_wait_for_keyframe = max_wait_for_keyframe, + .max_wait_for_frame = max_wait_for_frame}); + } + void StartNextDecode(bool keyframe_required) override { if (!worker_queue_->IsCurrent()) { worker_queue_->PostTask(SafeTask( diff --git a/video/frame_buffer_proxy.h b/video/frame_buffer_proxy.h index 1d440ed955..a616d491d0 100644 --- a/video/frame_buffer_proxy.h +++ b/video/frame_buffer_proxy.h @@ -59,6 +59,8 @@ class FrameBufferProxy { std::unique_ptr frame) = 0; virtual void UpdateRtt(int64_t max_rtt_ms) = 0; virtual int Size() = 0; + virtual void SetMaxWaits(TimeDelta max_wait_for_keyframe, + TimeDelta max_wait_for_frame) = 0; // Run on either the worker thread or the decode thread. virtual void StartNextDecode(bool keyframe_required) = 0; diff --git a/video/rtp_video_stream_receiver2.cc b/video/rtp_video_stream_receiver2.cc index 2fe72d14ec..1f31c41d0b 100644 --- a/video/rtp_video_stream_receiver2.cc +++ b/video/rtp_video_stream_receiver2.cc @@ -56,6 +56,8 @@ namespace { constexpr int kPacketBufferStartSize = 512; constexpr int kPacketBufferMaxSize = 2048; +constexpr int kMaxPacketAgeToNack = 450; + int PacketBufferMaxSize(const FieldTrialsView& field_trials) { // The group here must be a positive power of 2, in which case that is used as // size. All other values shall result in the default value being used. @@ -105,12 +107,12 @@ std::unique_ptr CreateRtpRtcpModule( std::unique_ptr MaybeConstructNackModule( TaskQueueBase* current_queue, NackPeriodicProcessor* nack_periodic_processor, - const VideoReceiveStreamInterface::Config& config, + const NackConfig& nack, Clock* clock, NackSender* nack_sender, KeyFrameRequestSender* keyframe_request_sender, const FieldTrialsView& field_trials) { - if (config.rtp.nack.rtp_history_ms == 0) + if (nack.rtp_history_ms == 0) return nullptr; // TODO(bugs.webrtc.org/12420): pass rtp_history_ms to the nack module. @@ -223,6 +225,7 @@ RtpVideoStreamReceiver2::RtpVideoStreamReceiver2( rtc::scoped_refptr frame_transformer, const FieldTrialsView& field_trials) : field_trials_(field_trials), + worker_queue_(current_queue), clock_(clock), config_(*config), packet_router_(packet_router), @@ -246,6 +249,7 @@ RtpVideoStreamReceiver2::RtpVideoStreamReceiver2( rtcp_cname_callback, config_.rtp.rtcp_xr.receiver_reference_time_report, config_.rtp.local_ssrc)), + nack_periodic_processor_(nack_periodic_processor), complete_frame_callback_(complete_frame_callback), keyframe_request_method_(config_.rtp.keyframe_method), // TODO(bugs.webrtc.org/10336): Let `rtcp_feedback_buffer_` communicate @@ -253,7 +257,7 @@ RtpVideoStreamReceiver2::RtpVideoStreamReceiver2( rtcp_feedback_buffer_(this, this, this), nack_module_(MaybeConstructNackModule(current_queue, nack_periodic_processor, - config_, + config_.rtp.nack, clock_, &rtcp_feedback_buffer_, &rtcp_feedback_buffer_, @@ -280,7 +284,6 @@ RtpVideoStreamReceiver2::RtpVideoStreamReceiver2( rtp_rtcp_->SetRemoteSSRC(config_.rtp.remote_ssrc); if (config_.rtp.nack.rtp_history_ms > 0) { - static constexpr int kMaxPacketAgeToNack = 450; rtp_receive_statistics_->SetMaxReorderingThreshold(config_.rtp.remote_ssrc, kMaxPacketAgeToNack); } @@ -704,10 +707,6 @@ bool RtpVideoStreamReceiver2::IsUlpfecEnabled() const { return config_.rtp.ulpfec_payload_type != -1; } -bool RtpVideoStreamReceiver2::IsRetransmissionsEnabled() const { - return config_.rtp.nack.rtp_history_ms > 0; -} - bool RtpVideoStreamReceiver2::IsDecryptable() const { RTC_DCHECK_RUN_ON(&worker_task_checker_); return frames_decryptable_; @@ -919,7 +918,7 @@ const RtpHeaderExtensionMap& RtpVideoStreamReceiver2::GetRtpExtensions() const { } void RtpVideoStreamReceiver2::UpdateRtt(int64_t max_rtt_ms) { - RTC_DCHECK_RUN_ON(&worker_task_checker_); + RTC_DCHECK_RUN_ON(&packet_sequence_checker_); if (nack_module_) nack_module_->UpdateRtt(max_rtt_ms); } @@ -952,6 +951,21 @@ void RtpVideoStreamReceiver2::SetLossNotificationEnabled(bool enabled) { } } +void RtpVideoStreamReceiver2::SetNackHistory(TimeDelta history) { + RTC_DCHECK_RUN_ON(&packet_sequence_checker_); + if (history.ms() == 0) { + nack_module_.reset(); + } else if (!nack_module_) { + nack_module_ = std::make_unique( + worker_queue_, nack_periodic_processor_, clock_, &rtcp_feedback_buffer_, + &rtcp_feedback_buffer_, field_trials_); + } + + rtp_receive_statistics_->SetMaxReorderingThreshold( + config_.rtp.remote_ssrc, + history.ms() > 0 ? kMaxPacketAgeToNack : kDefaultMaxReorderingThreshold); +} + absl::optional RtpVideoStreamReceiver2::LastReceivedPacketMs() const { RTC_DCHECK_RUN_ON(&packet_sequence_checker_); if (last_received_rtp_system_time_) { @@ -978,7 +992,7 @@ void RtpVideoStreamReceiver2::ManageFrame( void RtpVideoStreamReceiver2::ReceivePacket(const RtpPacketReceived& packet) { RTC_DCHECK_RUN_ON(&packet_sequence_checker_); - RTC_DCHECK_RUN_ON(&worker_task_checker_); + if (packet.payload_size() == 0) { // Padding or keep-alive packet. // TODO(nisse): Could drop empty packets earlier, but need to figure out how diff --git a/video/rtp_video_stream_receiver2.h b/video/rtp_video_stream_receiver2.h index dff3bfcf38..4fc11da1c9 100644 --- a/video/rtp_video_stream_receiver2.h +++ b/video/rtp_video_stream_receiver2.h @@ -149,7 +149,6 @@ class RtpVideoStreamReceiver2 : public LossNotificationSender, bool buffering_allowed) override; bool IsUlpfecEnabled() const; - bool IsRetransmissionsEnabled() const; // Returns true if a decryptor is attached and frames can be decrypted. // Updated by OnDecryptionStatusChangeCallback. Note this refers to Frame @@ -198,6 +197,8 @@ class RtpVideoStreamReceiver2 : public LossNotificationSender, // thread. void SetLossNotificationEnabled(bool enabled); + void SetNackHistory(TimeDelta history); + absl::optional LastReceivedPacketMs() const; absl::optional LastReceivedKeyframePacketMs() const; @@ -305,6 +306,7 @@ class RtpVideoStreamReceiver2 : public LossNotificationSender, RTC_RUN_ON(packet_sequence_checker_); const FieldTrialsView& field_trials_; + TaskQueueBase* const worker_queue_; Clock* const clock_; // Ownership of this object lies with VideoReceiveStreamInterface, which owns // `this`. @@ -337,11 +339,15 @@ class RtpVideoStreamReceiver2 : public LossNotificationSender, const std::unique_ptr rtp_rtcp_; + NackPeriodicProcessor* const nack_periodic_processor_; OnCompleteFrameCallback* complete_frame_callback_; const KeyFrameReqMethod keyframe_request_method_; RtcpFeedbackBuffer rtcp_feedback_buffer_; - const std::unique_ptr nack_module_; + // TODO(tommi): Consider absl::optional instead of unique_ptr + // since nack is usually configured. + std::unique_ptr nack_module_ + RTC_GUARDED_BY(packet_sequence_checker_); std::unique_ptr loss_notification_controller_ RTC_GUARDED_BY(packet_sequence_checker_); diff --git a/video/video_receive_stream2.cc b/video/video_receive_stream2.cc index f84b981dcb..ec40b414d7 100644 --- a/video/video_receive_stream2.cc +++ b/video/video_receive_stream2.cc @@ -182,17 +182,12 @@ std::string OptionalDelayToLogString(const absl::optional opt) { } // namespace -TimeDelta DetermineMaxWaitForFrame( - const VideoReceiveStreamInterface::Config& config, - bool is_keyframe) { +TimeDelta DetermineMaxWaitForFrame(TimeDelta rtp_history, bool is_keyframe) { // A (arbitrary) conversion factor between the remotely signalled NACK buffer // time (if not present defaults to 1000ms) and the maximum time we wait for a // remote frame. Chosen to not change existing defaults when using not // rtx-time. const int conversion_factor = 3; - const TimeDelta rtp_history = - TimeDelta::Millis(config.rtp.nack.rtp_history_ms); - if (rtp_history > TimeDelta::Zero() && conversion_factor * rtp_history < kMaxWaitForFrame) { return is_keyframe ? rtp_history : conversion_factor * rtp_history; @@ -238,8 +233,12 @@ VideoReceiveStream2::VideoReceiveStream2( std::move(config_.frame_transformer), call->trials()), rtp_stream_sync_(call->worker_thread(), this), - max_wait_for_keyframe_(DetermineMaxWaitForFrame(config_, true)), - max_wait_for_frame_(DetermineMaxWaitForFrame(config_, false)), + max_wait_for_keyframe_(DetermineMaxWaitForFrame( + TimeDelta::Millis(config_.rtp.nack.rtp_history_ms), + true)), + max_wait_for_frame_(DetermineMaxWaitForFrame( + TimeDelta::Millis(config_.rtp.nack.rtp_history_ms), + false)), maximum_pre_stream_decoders_("max", kDefaultMaximumPreStreamDecoders), decode_sync_(decode_sync), decode_queue_(task_queue_factory_->CreateTaskQueue( @@ -355,8 +354,7 @@ void VideoReceiveStream2::Start() { const bool protected_by_fec = config_.rtp.protected_by_flexfec || rtp_video_stream_receiver_.IsUlpfecEnabled(); - if (rtp_video_stream_receiver_.IsRetransmissionsEnabled() && - protected_by_fec) { + if (config_.rtp.nack.rtp_history_ms > 0 && protected_by_fec) { frame_buffer_->SetProtectionMode(kProtectionNackFEC); } @@ -524,6 +522,36 @@ void VideoReceiveStream2::SetLossNotificationEnabled(bool enabled) { rtp_video_stream_receiver_.SetLossNotificationEnabled(enabled); } +void VideoReceiveStream2::SetNackHistory(TimeDelta history) { + RTC_DCHECK_RUN_ON(&packet_sequence_checker_); + RTC_DCHECK_GE(history.ms(), 0); + + if (config_.rtp.nack.rtp_history_ms == history.ms()) + return; + + // TODO(tommi): Stop using the config struct for the internal state. + const_cast(config_.rtp.nack.rtp_history_ms) = history.ms(); + + const bool protected_by_fec = config_.rtp.protected_by_flexfec || + rtp_video_stream_receiver_.IsUlpfecEnabled(); + + frame_buffer_->SetProtectionMode(history.ms() > 0 && protected_by_fec + ? kProtectionNackFEC + : kProtectionNack); + + rtp_video_stream_receiver_.SetNackHistory(history); + TimeDelta max_wait_for_keyframe = DetermineMaxWaitForFrame(history, true); + TimeDelta max_wait_for_frame = DetermineMaxWaitForFrame(history, false); + + decode_queue_.PostTask([this, max_wait_for_keyframe, max_wait_for_frame]() { + RTC_DCHECK_RUN_ON(&decode_queue_); + max_wait_for_keyframe_ = max_wait_for_keyframe; + max_wait_for_frame_ = max_wait_for_frame; + }); + + frame_buffer_->SetMaxWaits(max_wait_for_keyframe, max_wait_for_frame); +} + void VideoReceiveStream2::CreateAndRegisterExternalDecoder( const Decoder& decoder) { TRACE_EVENT0("webrtc", @@ -765,6 +793,7 @@ bool VideoReceiveStream2::SetMinimumPlayoutDelay(int delay_ms) { } TimeDelta VideoReceiveStream2::GetMaxWait() const { + RTC_DCHECK_RUN_ON(&decode_queue_); return keyframe_required_ ? max_wait_for_keyframe_ : max_wait_for_frame_; } @@ -780,10 +809,11 @@ void VideoReceiveStream2::OnDecodableFrameTimeout(TimeDelta wait_time) { RTC_DCHECK_RUN_ON(&decode_queue_); Timestamp now = clock_->CurrentTime(); // TODO(bugs.webrtc.org/11993): PostTask to the network thread. - call_->worker_thread()->PostTask( - SafeTask(task_safety_.flag(), [this, wait_time, now] { + call_->worker_thread()->PostTask(SafeTask( + task_safety_.flag(), + [this, wait_time, now, max_wait_for_keyframe = max_wait_for_keyframe_] { RTC_DCHECK_RUN_ON(&packet_sequence_checker_); - HandleFrameBufferTimeout(now, wait_time); + HandleFrameBufferTimeout(now, wait_time, max_wait_for_keyframe); decode_queue_.PostTask([this] { RTC_DCHECK_RUN_ON(&decode_queue_); @@ -849,15 +879,16 @@ void VideoReceiveStream2::HandleEncodedFrame( call_->worker_thread()->PostTask(SafeTask( task_safety_.flag(), [this, now, received_frame_is_keyframe, force_request_key_frame, - decoded_frame_picture_id, keyframe_request_is_due]() { + decoded_frame_picture_id, keyframe_request_is_due, + max_wait_for_keyframe = max_wait_for_keyframe_]() { RTC_DCHECK_RUN_ON(&packet_sequence_checker_); if (decoded_frame_picture_id != -1) rtp_video_stream_receiver_.FrameDecoded(decoded_frame_picture_id); - HandleKeyFrameGeneration(received_frame_is_keyframe, now, - force_request_key_frame, - keyframe_request_is_due); + HandleKeyFrameGeneration( + received_frame_is_keyframe, now, force_request_key_frame, + keyframe_request_is_due, max_wait_for_keyframe); })); } } @@ -926,7 +957,8 @@ void VideoReceiveStream2::HandleKeyFrameGeneration( bool received_frame_is_keyframe, Timestamp now, bool always_request_key_frame, - bool keyframe_request_is_due) { + bool keyframe_request_is_due, + TimeDelta max_wait_for_keyframe) { RTC_DCHECK_RUN_ON(&packet_sequence_checker_); bool request_key_frame = always_request_key_frame; @@ -935,7 +967,7 @@ void VideoReceiveStream2::HandleKeyFrameGeneration( if (received_frame_is_keyframe) { keyframe_generation_requested_ = false; } else if (keyframe_request_is_due) { - if (!IsReceivingKeyFrame(now)) { + if (!IsReceivingKeyFrame(now, max_wait_for_keyframe)) { request_key_frame = true; } } else { @@ -951,9 +983,12 @@ void VideoReceiveStream2::HandleKeyFrameGeneration( } } -void VideoReceiveStream2::HandleFrameBufferTimeout(Timestamp now, - TimeDelta wait) { +void VideoReceiveStream2::HandleFrameBufferTimeout( + Timestamp now, + TimeDelta wait, + TimeDelta max_wait_for_keyframe) { RTC_DCHECK_RUN_ON(&packet_sequence_checker_); + absl::optional last_packet_ms = rtp_video_stream_receiver_.LastReceivedPacketMs(); @@ -966,7 +1001,7 @@ void VideoReceiveStream2::HandleFrameBufferTimeout(Timestamp now, if (!stream_is_active) stats_proxy_.OnStreamInactive(); - if (stream_is_active && !IsReceivingKeyFrame(now) && + if (stream_is_active && !IsReceivingKeyFrame(now, max_wait_for_keyframe) && (!config_.crypto_options.sframe.require_frame_encryption || rtp_video_stream_receiver_.IsDecryptable())) { RTC_LOG(LS_WARNING) << "No decodable frame in " << wait @@ -975,16 +1010,18 @@ void VideoReceiveStream2::HandleFrameBufferTimeout(Timestamp now, } } -bool VideoReceiveStream2::IsReceivingKeyFrame(Timestamp now) const { +bool VideoReceiveStream2::IsReceivingKeyFrame( + Timestamp now, + TimeDelta max_wait_for_keyframe) const { RTC_DCHECK_RUN_ON(&packet_sequence_checker_); absl::optional last_keyframe_packet_ms = rtp_video_stream_receiver_.LastReceivedKeyframePacketMs(); // If we recently have been receiving packets belonging to a keyframe then // we assume a keyframe is currently being received. - bool receiving_keyframe = last_keyframe_packet_ms && - now - Timestamp::Millis(*last_keyframe_packet_ms) < - max_wait_for_keyframe_; + bool receiving_keyframe = + last_keyframe_packet_ms && + now - Timestamp::Millis(*last_keyframe_packet_ms) < max_wait_for_keyframe; return receiving_keyframe; } diff --git a/video/video_receive_stream2.h b/video/video_receive_stream2.h index 79bd6caf5a..686e3af52a 100644 --- a/video/video_receive_stream2.h +++ b/video/video_receive_stream2.h @@ -148,6 +148,7 @@ class VideoReceiveStream2 void SetRtcpMode(RtcpMode mode) override; void SetFlexFecProtection(RtpPacketSinkInterface* flexfec_sink) override; void SetLossNotificationEnabled(bool enabled) override; + void SetNackHistory(TimeDelta history) override; webrtc::VideoReceiveStreamInterface::Stats GetStats() const override; @@ -195,7 +196,9 @@ class VideoReceiveStream2 TimeDelta GetMaxWait() const RTC_RUN_ON(decode_queue_); void HandleEncodedFrame(std::unique_ptr frame) RTC_RUN_ON(decode_queue_); - void HandleFrameBufferTimeout(Timestamp now, TimeDelta wait) + void HandleFrameBufferTimeout(Timestamp now, + TimeDelta wait, + TimeDelta max_wait_for_keyframe) RTC_RUN_ON(packet_sequence_checker_); void UpdatePlayoutDelays() const RTC_EXCLUSIVE_LOCKS_REQUIRED(worker_sequence_checker_); @@ -203,9 +206,11 @@ class VideoReceiveStream2 void HandleKeyFrameGeneration(bool received_frame_is_keyframe, Timestamp now, bool always_request_key_frame, - bool keyframe_request_is_due) + bool keyframe_request_is_due, + TimeDelta max_wait_for_keyframe) RTC_RUN_ON(packet_sequence_checker_); - bool IsReceivingKeyFrame(Timestamp timestamp) const + bool IsReceivingKeyFrame(Timestamp timestamp, + TimeDelta max_wait_for_keyframe) const RTC_RUN_ON(packet_sequence_checker_); int DecodeAndMaybeDispatchEncodedFrame(std::unique_ptr frame) RTC_RUN_ON(decode_queue_); @@ -274,8 +279,8 @@ class VideoReceiveStream2 RTC_GUARDED_BY(worker_sequence_checker_); // Keyframe request intervals are configurable through field trials. - const TimeDelta max_wait_for_keyframe_; - const TimeDelta max_wait_for_frame_; + TimeDelta max_wait_for_keyframe_ RTC_GUARDED_BY(decode_queue_); + TimeDelta max_wait_for_frame_ RTC_GUARDED_BY(decode_queue_); // All of them tries to change current min_playout_delay on `timing_` but // source of the change request is different in each case. Among them the diff --git a/video/video_receive_stream_timeout_tracker.cc b/video/video_receive_stream_timeout_tracker.cc index 32e8bf8dc7..0409f26560 100644 --- a/video/video_receive_stream_timeout_tracker.cc +++ b/video/video_receive_stream_timeout_tracker.cc @@ -40,6 +40,7 @@ TimeDelta VideoReceiveStreamTimeoutTracker::TimeUntilTimeout() const { } void VideoReceiveStreamTimeoutTracker::Start(bool waiting_for_keyframe) { + RTC_DCHECK_RUN_ON(bookkeeping_queue_); RTC_DCHECK(!timeout_task_.Running()); waiting_for_keyframe_ = waiting_for_keyframe; TimeDelta timeout_delay = TimeoutForNextFrame(); @@ -55,6 +56,7 @@ void VideoReceiveStreamTimeoutTracker::Stop() { } void VideoReceiveStreamTimeoutTracker::SetWaitingForKeyframe() { + RTC_DCHECK_RUN_ON(bookkeeping_queue_); waiting_for_keyframe_ = true; TimeDelta timeout_delay = TimeoutForNextFrame(); if (clock_->CurrentTime() + timeout_delay < timeout_) { @@ -64,6 +66,7 @@ void VideoReceiveStreamTimeoutTracker::SetWaitingForKeyframe() { } void VideoReceiveStreamTimeoutTracker::OnEncodedFrameReleased() { + RTC_DCHECK_RUN_ON(bookkeeping_queue_); // If we were waiting for a keyframe, then it has just been released. waiting_for_keyframe_ = false; last_frame_ = clock_->CurrentTime(); @@ -71,6 +74,7 @@ void VideoReceiveStreamTimeoutTracker::OnEncodedFrameReleased() { } TimeDelta VideoReceiveStreamTimeoutTracker::HandleTimeoutTask() { + RTC_DCHECK_RUN_ON(bookkeeping_queue_); Timestamp now = clock_->CurrentTime(); // `timeout_` is hit and we have timed out. Schedule the next timeout at // the timeout delay. @@ -86,4 +90,9 @@ TimeDelta VideoReceiveStreamTimeoutTracker::HandleTimeoutTask() { return timeout_ - now; } +void VideoReceiveStreamTimeoutTracker::SetTimeouts(Timeouts timeouts) { + RTC_DCHECK_RUN_ON(bookkeeping_queue_); + timeouts_ = timeouts; +} + } // namespace webrtc diff --git a/video/video_receive_stream_timeout_tracker.h b/video/video_receive_stream_timeout_tracker.h index c5a1c73be5..c15aa70e92 100644 --- a/video/video_receive_stream_timeout_tracker.h +++ b/video/video_receive_stream_timeout_tracker.h @@ -46,8 +46,10 @@ class VideoReceiveStreamTimeoutTracker { void OnEncodedFrameReleased(); TimeDelta TimeUntilTimeout() const; + void SetTimeouts(Timeouts timeouts); + private: - TimeDelta TimeoutForNextFrame() const { + TimeDelta TimeoutForNextFrame() const RTC_RUN_ON(bookkeeping_queue_) { return waiting_for_keyframe_ ? timeouts_.max_wait_for_keyframe : timeouts_.max_wait_for_frame; } @@ -55,7 +57,7 @@ class VideoReceiveStreamTimeoutTracker { Clock* const clock_; TaskQueueBase* const bookkeeping_queue_; - const Timeouts timeouts_; + Timeouts timeouts_ RTC_GUARDED_BY(bookkeeping_queue_); const TimeoutCallback timeout_cb_; RepeatingTaskHandle timeout_task_;