From d425f506ad0ff0f13013c3dc479cbb4630714f02 Mon Sep 17 00:00:00 2001 From: Evan Shrubsole Date: Thu, 28 Apr 2022 10:18:12 +0200 Subject: [PATCH] Switch VideoReceiveStream2 internals to Time units MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ifcee6372120e968499acbdf3bf2c0d002d1c4724 Bug: webrtc:13756 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/259777 Reviewed-by: Erik Språng Commit-Queue: Evan Shrubsole Reviewed-by: Tomas Gunnarsson Reviewed-by: Johannes Kron Cr-Commit-Position: refs/heads/main@{#36685} --- api/units/time_delta.h | 5 + api/units/time_delta_unittest.cc | 4 + video/BUILD.gn | 1 + video/video_receive_stream2.cc | 166 ++++++++++++------------ video/video_receive_stream2.h | 44 +++---- video/video_receive_stream2_unittest.cc | 13 +- 6 files changed, 123 insertions(+), 110 deletions(-) diff --git a/api/units/time_delta.h b/api/units/time_delta.h index 6f1910379b..d5951005e3 100644 --- a/api/units/time_delta.h +++ b/api/units/time_delta.h @@ -32,6 +32,11 @@ namespace webrtc { // microseconds (us). class TimeDelta final : public rtc_units_impl::RelativeUnit { public: + template + static constexpr TimeDelta Minutes(T value) { + static_assert(std::is_arithmetic::value, ""); + return Seconds(value * 60); + } template static constexpr TimeDelta Seconds(T value) { static_assert(std::is_arithmetic::value, ""); diff --git a/api/units/time_delta_unittest.cc b/api/units/time_delta_unittest.cc index cb43860531..3483d641bd 100644 --- a/api/units/time_delta_unittest.cc +++ b/api/units/time_delta_unittest.cc @@ -28,10 +28,12 @@ TEST(TimeDeltaTest, ConstExpr) { static_assert(kTimeDeltaPlusInf > kTimeDeltaZero, ""); + constexpr TimeDelta kTimeDeltaMinutes = TimeDelta::Minutes(kValue); constexpr TimeDelta kTimeDeltaSeconds = TimeDelta::Seconds(kValue); constexpr TimeDelta kTimeDeltaMs = TimeDelta::Millis(kValue); constexpr TimeDelta kTimeDeltaUs = TimeDelta::Micros(kValue); + static_assert(kTimeDeltaMinutes.seconds_or(0) == kValue * 60, ""); static_assert(kTimeDeltaSeconds.seconds_or(0) == kValue, ""); static_assert(kTimeDeltaMs.ms_or(0) == kValue, ""); static_assert(kTimeDeltaUs.us_or(0) == kValue, ""); @@ -54,10 +56,12 @@ TEST(TimeDeltaTest, GetDifferentPrefix) { EXPECT_EQ(TimeDelta::Micros(kValue).seconds(), kValue / 1000000); EXPECT_EQ(TimeDelta::Millis(kValue).seconds(), kValue / 1000); EXPECT_EQ(TimeDelta::Micros(kValue).ms(), kValue / 1000); + EXPECT_EQ(TimeDelta::Minutes(kValue / 60).seconds(), kValue); EXPECT_EQ(TimeDelta::Millis(kValue).us(), kValue * 1000); EXPECT_EQ(TimeDelta::Seconds(kValue).ms(), kValue * 1000); EXPECT_EQ(TimeDelta::Seconds(kValue).us(), kValue * 1000000); + EXPECT_EQ(TimeDelta::Minutes(kValue / 60).seconds(), kValue); } TEST(TimeDeltaTest, IdentityChecks) { diff --git a/video/BUILD.gn b/video/BUILD.gn index 58484031df..27b821bfd7 100644 --- a/video/BUILD.gn +++ b/video/BUILD.gn @@ -72,6 +72,7 @@ rtc_library("video") { "../api/crypto:options", "../api/rtc_event_log", "../api/task_queue", + "../api/units:frequency", "../api/units:time_delta", "../api/units:timestamp", "../api/video:encoded_image", diff --git a/video/video_receive_stream2.cc b/video/video_receive_stream2.cc index 43fd0c37cf..873fa3d964 100644 --- a/video/video_receive_stream2.cc +++ b/video/video_receive_stream2.cc @@ -28,7 +28,9 @@ #include "api/scoped_refptr.h" #include "api/sequence_checker.h" #include "api/task_queue/task_queue_base.h" +#include "api/units/frequency.h" #include "api/units/time_delta.h" +#include "api/units/timestamp.h" #include "api/video/encoded_image.h" #include "api/video_codecs/h264_profile_level_id.h" #include "api/video_codecs/sdp_video_format.h" @@ -70,14 +72,14 @@ namespace webrtc { namespace internal { -constexpr int VideoReceiveStream2::kMaxWaitForKeyFrameMs; namespace { -constexpr int kMinBaseMinimumDelayMs = 0; -constexpr int kMaxBaseMinimumDelayMs = 10000; - -constexpr int kMaxWaitForFrameMs = 3000; +// The default delay before re-requesting a key frame to be sent. +constexpr TimeDelta kMaxWaitForKeyFrame = TimeDelta::Millis(200); +constexpr TimeDelta kMinBaseMinimumDelay = TimeDelta::Zero(); +constexpr TimeDelta kMaxBaseMinimumDelay = TimeDelta::Seconds(10); +constexpr TimeDelta kMaxWaitForFrame = TimeDelta::Seconds(3); // Create a decoder for the preferred codec before the stream starts and any // other decoder lazily on demand. @@ -178,25 +180,25 @@ bool IsKeyFrameAndUnspecifiedResolution(const EncodedFrame& frame) { // TODO(https://bugs.webrtc.org/9974): Consider removing this workaround. // Maximum time between frames before resetting the FrameBuffer to avoid RTP // timestamps wraparound to affect FrameBuffer. -constexpr int kInactiveStreamThresholdMs = 600000; // 10 minutes. +constexpr TimeDelta kInactiveStreamThreshold = TimeDelta::Minutes(10); } // namespace -int DetermineMaxWaitForFrame(const VideoReceiveStream::Config& config, - bool is_keyframe) { +TimeDelta DetermineMaxWaitForFrame(const VideoReceiveStream::Config& config, + 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 (config.rtp.nack.rtp_history_ms > 0 && - conversion_factor * config.rtp.nack.rtp_history_ms < kMaxWaitForFrameMs) { - return is_keyframe ? config.rtp.nack.rtp_history_ms - : conversion_factor * 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; } - return is_keyframe ? VideoReceiveStream2::kMaxWaitForKeyFrameMs - : kMaxWaitForFrameMs; + return is_keyframe ? kMaxWaitForKeyFrame : kMaxWaitForFrame; } VideoReceiveStream2::VideoReceiveStream2( @@ -242,8 +244,8 @@ VideoReceiveStream2::VideoReceiveStream2( std::move(config_.frame_transformer), call->trials()), rtp_stream_sync_(call->worker_thread(), this), - max_wait_for_keyframe_ms_(DetermineMaxWaitForFrame(config_, true)), - max_wait_for_frame_ms_(DetermineMaxWaitForFrame(config_, false)), + max_wait_for_keyframe_(DetermineMaxWaitForFrame(config_, true)), + max_wait_for_frame_(DetermineMaxWaitForFrame(config_, false)), maximum_pre_stream_decoders_("max", kDefaultMaximumPreStreamDecoders), decode_sync_(decode_sync), decode_queue_(task_queue_factory_->CreateTaskQueue( @@ -271,8 +273,8 @@ VideoReceiveStream2::VideoReceiveStream2( frame_buffer_ = FrameBufferProxy::CreateFromFieldTrial( clock_, call_->worker_thread(), timing_.get(), &stats_proxy_, - &decode_queue_, this, TimeDelta::Millis(max_wait_for_keyframe_ms_), - TimeDelta::Millis(max_wait_for_frame_ms_), decode_sync_, call_->trials()); + &decode_queue_, this, max_wait_for_keyframe_, max_wait_for_frame_, + decode_sync_, call_->trials()); if (config_.rtp.rtx_ssrc) { rtx_receive_stream_ = std::make_unique( @@ -566,18 +568,22 @@ void VideoReceiveStream2::UpdateHistograms() { bool VideoReceiveStream2::SetBaseMinimumPlayoutDelayMs(int delay_ms) { RTC_DCHECK_RUN_ON(&worker_sequence_checker_); - if (delay_ms < kMinBaseMinimumDelayMs || delay_ms > kMaxBaseMinimumDelayMs) { + TimeDelta delay = TimeDelta::Millis(delay_ms); + if (delay < kMinBaseMinimumDelay || delay > kMaxBaseMinimumDelay) { return false; } - base_minimum_playout_delay_ms_ = delay_ms; + base_minimum_playout_delay_ = delay; UpdatePlayoutDelays(); return true; } int VideoReceiveStream2::GetBaseMinimumPlayoutDelayMs() const { RTC_DCHECK_RUN_ON(&worker_sequence_checker_); - return base_minimum_playout_delay_ms_; + constexpr TimeDelta kDefaultBaseMinPlayoutDelay = TimeDelta::Millis(-1); + // Unset must be -1. + static_assert(-1 == kDefaultBaseMinPlayoutDelay.ms(), ""); + return base_minimum_playout_delay_.value_or(kDefaultBaseMinPlayoutDelay).ms(); } void VideoReceiveStream2::OnFrame(const VideoFrame& video_frame) { @@ -640,14 +646,14 @@ void VideoReceiveStream2::SendNack( rtp_video_stream_receiver_.RequestPacketRetransmit(sequence_numbers); } -void VideoReceiveStream2::RequestKeyFrame(int64_t timestamp_ms) { +void VideoReceiveStream2::RequestKeyFrame(Timestamp now) { // Running on worker_sequence_checker_. // Called from RtpVideoStreamReceiver (rtp_video_stream_receiver_ is // ultimately responsible). rtp_video_stream_receiver_.RequestKeyFrame(); - decode_queue_.PostTask([this, timestamp_ms]() { + decode_queue_.PostTask([this, now]() { RTC_DCHECK_RUN_ON(&decode_queue_); - last_keyframe_request_ms_ = timestamp_ms; + last_keyframe_request_ = now; }); } @@ -658,21 +664,20 @@ void VideoReceiveStream2::OnCompleteFrame(std::unique_ptr frame) { // TODO(https://bugs.webrtc.org/13343): Remove this check when FrameBuffer3 is // deployed. With FrameBuffer3, this case is properly handled and tested in // the FrameBufferProxyTest.PausedStream unit test. - int64_t time_now_ms = clock_->TimeInMilliseconds(); - if (last_complete_frame_time_ms_ > 0 && - time_now_ms - last_complete_frame_time_ms_ > kInactiveStreamThresholdMs) { + Timestamp time_now = clock_->CurrentTime(); + if (last_complete_frame_time_ && + time_now - *last_complete_frame_time_ > kInactiveStreamThreshold) { frame_buffer_->Clear(); } - last_complete_frame_time_ms_ = time_now_ms; + last_complete_frame_time_ = time_now; const VideoPlayoutDelay& playout_delay = frame->EncodedImage().playout_delay_; if (playout_delay.min_ms >= 0) { - frame_minimum_playout_delay_ms_ = playout_delay.min_ms; + frame_minimum_playout_delay_ = TimeDelta::Millis(playout_delay.min_ms); UpdatePlayoutDelays(); } - if (playout_delay.max_ms >= 0) { - frame_maximum_playout_delay_ms_ = playout_delay.max_ms; + frame_maximum_playout_delay_ = TimeDelta::Millis(playout_delay.max_ms); UpdatePlayoutDelays(); } @@ -725,14 +730,13 @@ void VideoReceiveStream2::SetEstimatedPlayoutNtpTimestampMs( bool VideoReceiveStream2::SetMinimumPlayoutDelay(int delay_ms) { RTC_DCHECK_RUN_ON(&worker_sequence_checker_); - syncable_minimum_playout_delay_ms_ = delay_ms; + syncable_minimum_playout_delay_ = TimeDelta::Millis(delay_ms); UpdatePlayoutDelays(); return true; } -int64_t VideoReceiveStream2::GetMaxWaitMs() const { - return keyframe_required_ ? max_wait_for_keyframe_ms_ - : max_wait_for_frame_ms_; +TimeDelta VideoReceiveStream2::GetMaxWait() const { + return keyframe_required_ ? max_wait_for_keyframe_ : max_wait_for_frame_; } void VideoReceiveStream2::OnEncodedFrame(std::unique_ptr frame) { @@ -759,8 +763,7 @@ void VideoReceiveStream2::OnDecodableFrameTimeout(TimeDelta wait_time) { // TODO(bugs.webrtc.org/11993): PostTask to the network thread. RTC_DCHECK_RUN_ON(&packet_sequence_checker_); - int64_t now_ms = clock_->TimeInMilliseconds(); - HandleFrameBufferTimeout(now_ms, wait_time.ms()); + HandleFrameBufferTimeout(clock_->CurrentTime(), wait_time); decode_queue_.PostTask([this] { RTC_DCHECK_RUN_ON(&decode_queue_); @@ -771,7 +774,7 @@ void VideoReceiveStream2::OnDecodableFrameTimeout(TimeDelta wait_time) { void VideoReceiveStream2::HandleEncodedFrame( std::unique_ptr frame) { // Running on `decode_queue_`. - int64_t now_ms = clock_->TimeInMilliseconds(); + Timestamp now = clock_->CurrentTime(); // Current OnPreDecode only cares about QP for VP8. int qp = -1; @@ -786,7 +789,8 @@ void VideoReceiveStream2::HandleEncodedFrame( int64_t decoded_frame_picture_id = -1; const bool keyframe_request_is_due = - now_ms >= (last_keyframe_request_ms_ + max_wait_for_keyframe_ms_); + !last_keyframe_request_ || + now >= (*last_keyframe_request_ + max_wait_for_keyframe_); if (!video_receiver_.IsExternalDecoderRegistered(frame->PayloadType())) { // Look for the decoder with this payload type. @@ -823,14 +827,14 @@ void VideoReceiveStream2::HandleEncodedFrame( // TODO(bugs.webrtc.org/11993): Make this PostTask to the network thread. call_->worker_thread()->PostTask(ToQueuedTask( task_safety_, - [this, now_ms, received_frame_is_keyframe, force_request_key_frame, + [this, now, received_frame_is_keyframe, force_request_key_frame, decoded_frame_picture_id, keyframe_request_is_due]() { 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_ms, + HandleKeyFrameGeneration(received_frame_is_keyframe, now, force_request_key_frame, keyframe_request_is_due); })); @@ -900,7 +904,7 @@ int VideoReceiveStream2::DecodeAndMaybeDispatchEncodedFrame( // RTC_RUN_ON(packet_sequence_checker_) void VideoReceiveStream2::HandleKeyFrameGeneration( bool received_frame_is_keyframe, - int64_t now_ms, + Timestamp now, bool always_request_key_frame, bool keyframe_request_is_due) { bool request_key_frame = always_request_key_frame; @@ -910,7 +914,7 @@ void VideoReceiveStream2::HandleKeyFrameGeneration( if (received_frame_is_keyframe) { keyframe_generation_requested_ = false; } else if (keyframe_request_is_due) { - if (!IsReceivingKeyFrame(now_ms)) { + if (!IsReceivingKeyFrame(now)) { request_key_frame = true; } } else { @@ -919,74 +923,75 @@ void VideoReceiveStream2::HandleKeyFrameGeneration( } if (request_key_frame) { - // HandleKeyFrameGeneration is initated from the decode thread - + // HandleKeyFrameGeneration is initiated from the decode thread - // RequestKeyFrame() triggers a call back to the decode thread. // Perhaps there's a way to avoid that. - RequestKeyFrame(now_ms); + RequestKeyFrame(now); } } // RTC_RUN_ON(packet_sequence_checker_) -void VideoReceiveStream2::HandleFrameBufferTimeout(int64_t now_ms, - int64_t wait_ms) { +void VideoReceiveStream2::HandleFrameBufferTimeout(Timestamp now, + TimeDelta wait) { absl::optional last_packet_ms = rtp_video_stream_receiver_.LastReceivedPacketMs(); // To avoid spamming keyframe requests for a stream that is not active we // check if we have received a packet within the last 5 seconds. + constexpr TimeDelta kInactiveDuraction = TimeDelta::Seconds(5); const bool stream_is_active = - last_packet_ms && now_ms - *last_packet_ms < 5000; + last_packet_ms && + now - Timestamp::Millis(*last_packet_ms) < kInactiveDuraction; if (!stream_is_active) stats_proxy_.OnStreamInactive(); - if (stream_is_active && !IsReceivingKeyFrame(now_ms) && + if (stream_is_active && !IsReceivingKeyFrame(now) && (!config_.crypto_options.sframe.require_frame_encryption || rtp_video_stream_receiver_.IsDecryptable())) { - RTC_LOG(LS_WARNING) << "No decodable frame in " << wait_ms - << " ms, requesting keyframe."; - RequestKeyFrame(now_ms); + RTC_LOG(LS_WARNING) << "No decodable frame in " << wait + << ", requesting keyframe."; + RequestKeyFrame(now); } } // RTC_RUN_ON(packet_sequence_checker_) -bool VideoReceiveStream2::IsReceivingKeyFrame(int64_t timestamp_ms) const { +bool VideoReceiveStream2::IsReceivingKeyFrame(Timestamp now) const { 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 && - timestamp_ms - *last_keyframe_packet_ms < max_wait_for_keyframe_ms_; + bool receiving_keyframe = last_keyframe_packet_ms && + now - Timestamp::Millis(*last_keyframe_packet_ms) < + max_wait_for_keyframe_; return receiving_keyframe; } void VideoReceiveStream2::UpdatePlayoutDelays() const { // Running on worker_sequence_checker_. - const int minimum_delay_ms = - std::max({frame_minimum_playout_delay_ms_, base_minimum_playout_delay_ms_, - syncable_minimum_playout_delay_ms_}); - if (minimum_delay_ms >= 0) { - timing_->set_min_playout_delay(TimeDelta::Millis(minimum_delay_ms)); - if (frame_minimum_playout_delay_ms_ == 0 && - frame_maximum_playout_delay_ms_ > 0) { + // Since nullopt < anything, this will return the largest of the minumum + // delays, or nullopt if all are nullopt. + absl::optional minimum_delay = + std::max({frame_minimum_playout_delay_, base_minimum_playout_delay_, + syncable_minimum_playout_delay_}); + if (minimum_delay) { + timing_->set_min_playout_delay(*minimum_delay); + if (frame_minimum_playout_delay_ == TimeDelta::Zero() && + frame_maximum_playout_delay_ > TimeDelta::Zero()) { // TODO(kron): Estimate frame rate from video stream. - constexpr double kFrameRate = 60.0; + constexpr Frequency kFrameRate = Frequency::Hertz(60); // Convert playout delay in ms to number of frames. - int max_composition_delay_in_frames = std::lrint( - static_cast(frame_maximum_playout_delay_ms_ * kFrameRate) / - rtc::kNumMillisecsPerSec); + int max_composition_delay_in_frames = + std::lrint(*frame_maximum_playout_delay_ * kFrameRate); // Subtract frames in buffer. - max_composition_delay_in_frames = std::max( - max_composition_delay_in_frames - frame_buffer_->Size(), 0); - timing_->SetMaxCompositionDelayInFrames( - absl::make_optional(max_composition_delay_in_frames)); + max_composition_delay_in_frames = + std::max(max_composition_delay_in_frames - frame_buffer_->Size(), 0); + timing_->SetMaxCompositionDelayInFrames(max_composition_delay_in_frames); } } - const int maximum_delay_ms = frame_maximum_playout_delay_ms_; - if (maximum_delay_ms >= 0) { - timing_->set_max_playout_delay(TimeDelta::Millis(maximum_delay_ms)); + if (frame_maximum_playout_delay_) { + timing_->set_max_playout_delay(*frame_maximum_playout_delay_); } } @@ -1006,15 +1011,16 @@ VideoReceiveStream2::SetAndGetRecordingState(RecordingState state, decode_queue_.PostTask( [this, &event, &old_state, callback = std::move(state.callback), generate_key_frame, - last_keyframe_request = state.last_keyframe_request_ms.value_or(0)] { + last_keyframe_request = + Timestamp::Millis(state.last_keyframe_request_ms.value_or(0))] { RTC_DCHECK_RUN_ON(&decode_queue_); old_state.callback = std::move(encoded_frame_buffer_function_); encoded_frame_buffer_function_ = std::move(callback); - old_state.last_keyframe_request_ms = last_keyframe_request_ms_; - last_keyframe_request_ms_ = generate_key_frame - ? clock_->TimeInMilliseconds() - : last_keyframe_request; + old_state.last_keyframe_request_ms = + last_keyframe_request_.value_or(Timestamp::Zero()).ms(); + last_keyframe_request_ = + generate_key_frame ? clock_->CurrentTime() : last_keyframe_request; event.Set(); }); @@ -1034,7 +1040,7 @@ VideoReceiveStream2::SetAndGetRecordingState(RecordingState state, void VideoReceiveStream2::GenerateKeyFrame() { RTC_DCHECK_RUN_ON(&packet_sequence_checker_); - RequestKeyFrame(clock_->TimeInMilliseconds()); + RequestKeyFrame(clock_->CurrentTime()); keyframe_generation_requested_ = true; } diff --git a/video/video_receive_stream2.h b/video/video_receive_stream2.h index 2bb5fa005c..726e91be54 100644 --- a/video/video_receive_stream2.h +++ b/video/video_receive_stream2.h @@ -17,6 +17,7 @@ #include "api/sequence_checker.h" #include "api/task_queue/task_queue_factory.h" +#include "api/units/time_delta.h" #include "api/units/timestamp.h" #include "api/video/recordable_encoded_frame.h" #include "call/call.h" @@ -53,7 +54,7 @@ class CallStats; // Utility struct for grabbing metadata from a VideoFrame and processing it // asynchronously without needing the actual frame data. // Additionally the caller can bundle information from the current clock -// when the metadata is captured, for accurate reporting and not needeing +// when the metadata is captured, for accurate reporting and not needing // multiple calls to clock->Now(). struct VideoFrameMetaData { VideoFrameMetaData(const webrtc::VideoFrame& frame, Timestamp now) @@ -86,9 +87,6 @@ class VideoReceiveStream2 public CallStatsObserver, public FrameSchedulingReceiver { public: - // The default number of milliseconds to pass before re-requesting a key frame - // to be sent. - static constexpr int kMaxWaitForKeyFrameMs = 200; // The maximum number of buffered encoded frames when encoded output is // configured. static constexpr size_t kBufferedEncodedFramesMaxSize = 60; @@ -189,21 +187,20 @@ class VideoReceiveStream2 void OnEncodedFrame(std::unique_ptr frame) override; void OnDecodableFrameTimeout(TimeDelta wait_time) override; void CreateAndRegisterExternalDecoder(const Decoder& decoder); - int64_t GetMaxWaitMs() const RTC_RUN_ON(decode_queue_); + TimeDelta GetMaxWait() const RTC_RUN_ON(decode_queue_); void HandleEncodedFrame(std::unique_ptr frame) RTC_RUN_ON(decode_queue_); - void HandleFrameBufferTimeout(int64_t now_ms, int64_t wait_ms) + void HandleFrameBufferTimeout(Timestamp now, TimeDelta wait) RTC_RUN_ON(packet_sequence_checker_); void UpdatePlayoutDelays() const RTC_EXCLUSIVE_LOCKS_REQUIRED(worker_sequence_checker_); - void RequestKeyFrame(int64_t timestamp_ms) - RTC_RUN_ON(packet_sequence_checker_); + void RequestKeyFrame(Timestamp now) RTC_RUN_ON(packet_sequence_checker_); void HandleKeyFrameGeneration(bool received_frame_is_keyframe, - int64_t now_ms, + Timestamp now, bool always_request_key_frame, bool keyframe_request_is_due) RTC_RUN_ON(packet_sequence_checker_); - bool IsReceivingKeyFrame(int64_t timestamp_ms) const + bool IsReceivingKeyFrame(Timestamp timestamp) const RTC_RUN_ON(packet_sequence_checker_); int DecodeAndMaybeDispatchEncodedFrame(std::unique_ptr frame) RTC_RUN_ON(decode_queue_); @@ -266,31 +263,32 @@ class VideoReceiveStream2 // If we have successfully decoded any frame. bool frame_decoded_ RTC_GUARDED_BY(decode_queue_) = false; - int64_t last_keyframe_request_ms_ RTC_GUARDED_BY(decode_queue_) = 0; - int64_t last_complete_frame_time_ms_ - RTC_GUARDED_BY(worker_sequence_checker_) = 0; + absl::optional last_keyframe_request_ + RTC_GUARDED_BY(decode_queue_); + absl::optional last_complete_frame_time_ + RTC_GUARDED_BY(worker_sequence_checker_); // Keyframe request intervals are configurable through field trials. - const int max_wait_for_keyframe_ms_; - const int max_wait_for_frame_ms_; + const TimeDelta max_wait_for_keyframe_; + const TimeDelta max_wait_for_frame_; // 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 // biggest delay is used. -1 means use default value from the `timing_`. // // Minimum delay as decided by the RTP playout delay extension. - int frame_minimum_playout_delay_ms_ RTC_GUARDED_BY(worker_sequence_checker_) = - -1; + absl::optional frame_minimum_playout_delay_ + RTC_GUARDED_BY(worker_sequence_checker_); // Minimum delay as decided by the setLatency function in "webrtc/api". - int base_minimum_playout_delay_ms_ RTC_GUARDED_BY(worker_sequence_checker_) = - -1; + absl::optional base_minimum_playout_delay_ + RTC_GUARDED_BY(worker_sequence_checker_); // Minimum delay as decided by the A/V synchronization feature. - int syncable_minimum_playout_delay_ms_ - RTC_GUARDED_BY(worker_sequence_checker_) = -1; + absl::optional syncable_minimum_playout_delay_ + RTC_GUARDED_BY(worker_sequence_checker_); // Maximum delay as decided by the RTP playout delay extension. - int frame_maximum_playout_delay_ms_ RTC_GUARDED_BY(worker_sequence_checker_) = - -1; + absl::optional frame_maximum_playout_delay_ + RTC_GUARDED_BY(worker_sequence_checker_); // Function that is triggered with encoded frames, if not empty. std::function diff --git a/video/video_receive_stream2_unittest.cc b/video/video_receive_stream2_unittest.cc index 317a322330..c20f484f51 100644 --- a/video/video_receive_stream2_unittest.cc +++ b/video/video_receive_stream2_unittest.cc @@ -483,7 +483,7 @@ TEST_F(VideoReceiveStream2TestWithFakeDecoder, } class VideoReceiveStream2TestWithSimulatedClock - : public ::testing::TestWithParam> { + : public ::testing::TestWithParam> { public: class FakeRenderer : public rtc::VideoSinkInterface { public: @@ -531,7 +531,7 @@ class VideoReceiveStream2TestWithSimulatedClock VideoReceiveStream::Config config(transport, decoder_factory); config.rtp.remote_ssrc = 1111; config.rtp.local_ssrc = 2222; - config.rtp.nack.rtp_history_ms = std::get<0>(GetParam()); // rtx-time. + config.rtp.nack.rtp_history_ms = std::get<0>(GetParam()).ms(); // rtx-time. config.renderer = renderer; VideoReceiveStream::Decoder fake_decoder; fake_decoder.payload_type = 99; @@ -606,7 +606,7 @@ class VideoReceiveStream2TestWithSimulatedClock TEST_P(VideoReceiveStream2TestWithSimulatedClock, RequestsKeyFramesUntilKeyFrameReceived) { - auto tick = TimeDelta::Millis(std::get<0>(GetParam()) / 2); + auto tick = std::get<0>(GetParam()) / 2; bool sent_rtcp = false; EXPECT_CALL(mock_transport_, SendRtcp) .Times(1) @@ -711,10 +711,9 @@ TEST_P(VideoReceiveStream2TestWithSimulatedClock, INSTANTIATE_TEST_SUITE_P( RtxTime, VideoReceiveStream2TestWithSimulatedClock, - ::testing::Combine( - ::testing::Values(internal::VideoReceiveStream2::kMaxWaitForKeyFrameMs, - 50 /*ms*/), - ::testing::Bool())); + ::testing::Combine(::testing::Values(TimeDelta::Millis(200), + TimeDelta::Millis(50)), + ::testing::Bool())); class VideoReceiveStream2TestWithLazyDecoderCreation : public ::testing::Test { public: