Use Timestamp and TimeDelta in VCMTiming
* Switches TimestampExtrapolator to use Timestamp as well.
Bug: webrtc:13589
Change-Id: I042be5d693068553d2e8eb92fa532092d77bd7ef
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/249993
Reviewed-by: Tomas Gunnarsson <tommi@webrtc.org>
Commit-Queue: Evan Shrubsole <eshr@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#36112}
diff --git a/video/frame_buffer_proxy.cc b/video/frame_buffer_proxy.cc
index 31aa86f..d277a36 100644
--- a/video/frame_buffer_proxy.cc
+++ b/video/frame_buffer_proxy.cc
@@ -148,7 +148,7 @@
contentType(frame.contentType()),
delayed_by_retransmission(frame.delayed_by_retransmission()),
rtp_timestamp(frame.Timestamp()),
- receive_time(frame.ReceivedTime()) {}
+ receive_time_ms(frame.ReceivedTime()) {}
const bool is_last_spatial_layer;
const bool is_keyframe;
@@ -156,7 +156,7 @@
const VideoContentType contentType;
const bool delayed_by_retransmission;
const uint32_t rtp_timestamp;
- const int64_t receive_time;
+ const int64_t receive_time_ms;
};
// Encapsulates use of the new frame buffer for use in VideoReceiveStream. This
@@ -247,9 +247,12 @@
if (complete_units < buffer_->GetTotalNumberOfContinuousTemporalUnits()) {
stats_proxy_->OnCompleteFrame(metadata.is_keyframe, metadata.size,
metadata.contentType);
- if (!metadata.delayed_by_retransmission)
+ RTC_DCHECK_GE(metadata.receive_time_ms, 0)
+ << "Frame receive time must be positive for received frames, was "
+ << metadata.receive_time_ms << ".";
+ if (!metadata.delayed_by_retransmission && metadata.receive_time_ms >= 0)
timing_->IncomingTimestamp(metadata.rtp_timestamp,
- metadata.receive_time);
+ Timestamp::Millis(metadata.receive_time_ms));
MaybeScheduleFrameForRelease();
}
@@ -293,7 +296,7 @@
timeout_tracker_.OnEncodedFrameReleased();
- int64_t now_ms = clock_->TimeInMilliseconds();
+ Timestamp now = clock_->CurrentTime();
bool superframe_delayed_by_retransmission = false;
size_t superframe_size = 0;
const EncodedFrame& first_frame = *frames.front();
@@ -303,12 +306,11 @@
keyframe_required_ = false;
// Gracefully handle bad RTP timestamps and render time issues.
- if (FrameHasBadRenderTiming(render_time.ms(), now_ms,
+ if (FrameHasBadRenderTiming(render_time, now,
timing_->TargetVideoDelay())) {
jitter_estimator_.Reset();
timing_->Reset();
- render_time = Timestamp::Millis(
- timing_->RenderTimeMs(first_frame.Timestamp(), now_ms));
+ render_time = timing_->RenderTime(first_frame.Timestamp(), now);
}
for (std::unique_ptr<EncodedFrame>& frame : frames) {
@@ -334,9 +336,9 @@
rtt_mult = rtt_mult_settings_->rtt_mult_setting;
rtt_mult_add_cap_ms = rtt_mult_settings_->rtt_mult_add_cap_ms;
}
- timing_->SetJitterDelay(
- jitter_estimator_.GetJitterEstimate(rtt_mult, rtt_mult_add_cap_ms));
- timing_->UpdateCurrentDelay(render_time.ms(), now_ms);
+ timing_->SetJitterDelay(TimeDelta::Millis(
+ jitter_estimator_.GetJitterEstimate(rtt_mult, rtt_mult_add_cap_ms)));
+ timing_->UpdateCurrentDelay(render_time, now);
} else if (RttMultExperiment::RttMultEnabled()) {
jitter_estimator_.FrameNacked();
}
@@ -349,7 +351,7 @@
std::unique_ptr<EncodedFrame> frame =
CombineAndDeleteFrames(std::move(frames));
- timing_->SetLastDecodeScheduledTimestamp(now_ms);
+ timing_->SetLastDecodeScheduledTimestamp(now);
decoder_ready_for_new_frame_ = false;
// VideoReceiveStream2 wants frames on the decoder thread.
@@ -399,18 +401,18 @@
}
void UpdateJitterDelay() {
- int max_decode_ms;
- int current_delay_ms;
- int target_delay_ms;
- int jitter_buffer_ms;
- int min_playout_delay_ms;
- int render_delay_ms;
- if (timing_->GetTimings(&max_decode_ms, ¤t_delay_ms, &target_delay_ms,
- &jitter_buffer_ms, &min_playout_delay_ms,
- &render_delay_ms)) {
+ TimeDelta max_decode = TimeDelta::Zero();
+ TimeDelta current_delay = TimeDelta::Zero();
+ TimeDelta target_delay = TimeDelta::Zero();
+ TimeDelta jitter_buffer = TimeDelta::Zero();
+ TimeDelta min_playout_delay = TimeDelta::Zero();
+ TimeDelta render_delay = TimeDelta::Zero();
+ if (timing_->GetTimings(&max_decode, ¤t_delay, &target_delay,
+ &jitter_buffer, &min_playout_delay,
+ &render_delay)) {
stats_proxy_->OnFrameBufferTimingsUpdated(
- max_decode_ms, current_delay_ms, target_delay_ms, jitter_buffer_ms,
- min_playout_delay_ms, render_delay_ms);
+ max_decode.ms(), current_delay.ms(), target_delay.ms(),
+ jitter_buffer.ms(), min_playout_delay.ms(), render_delay.ms());
}
}
@@ -437,8 +439,8 @@
}
// Found keyframe - decode right away.
if (next_frame.front()->is_keyframe()) {
- auto render_time = Timestamp::Millis(timing_->RenderTimeMs(
- next_frame.front()->Timestamp(), clock_->TimeInMilliseconds()));
+ auto render_time = timing_->RenderTime(next_frame.front()->Timestamp(),
+ clock_->CurrentTime());
OnFrameReady(std::move(next_frame), render_time);
return;
}
diff --git a/video/frame_buffer_proxy_unittest.cc b/video/frame_buffer_proxy_unittest.cc
index 81e5bd2..e7307fd 100644
--- a/video/frame_buffer_proxy_unittest.cc
+++ b/video/frame_buffer_proxy_unittest.cc
@@ -233,7 +233,7 @@
kMaxWaitForFrame,
&decode_sync_)) {
// Avoid starting with negative render times.
- timing_.set_min_playout_delay(10);
+ timing_.set_min_playout_delay(TimeDelta::Millis(10));
ON_CALL(stats_callback_, OnDroppedFrames)
.WillByDefault(
@@ -631,8 +631,7 @@
EXPECT_CALL(stats_callback_, OnFrameBufferTimingsUpdated);
// Fake timing having received decoded frame.
- timing_.StopDecodeTimer(clock_->TimeInMicroseconds() + 1,
- clock_->TimeInMilliseconds());
+ timing_.StopDecodeTimer(TimeDelta::Millis(1), clock_->CurrentTime());
StartNextDecodeForceKeyframe();
proxy_->InsertFrame(Builder().Id(0).Time(0).AsLast().Build());
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(WithId(0)));
@@ -775,8 +774,8 @@
FramesDecodedInstantlyWithLowLatencyRendering) {
// Initial keyframe.
StartNextDecodeForceKeyframe();
- timing_.set_min_playout_delay(0);
- timing_.set_max_playout_delay(10);
+ timing_.set_min_playout_delay(TimeDelta::Zero());
+ timing_.set_max_playout_delay(TimeDelta::Millis(10));
auto frame = Builder().Id(0).Time(0).AsLast().Build();
// Playout delay of 0 implies low-latency rendering.
frame->SetPlayoutDelay({0, 10});
@@ -798,8 +797,8 @@
TEST_P(LowLatencyFrameBufferProxyTest, ZeroPlayoutDelayFullQueue) {
// Initial keyframe.
StartNextDecodeForceKeyframe();
- timing_.set_min_playout_delay(0);
- timing_.set_max_playout_delay(10);
+ timing_.set_min_playout_delay(TimeDelta::Zero());
+ timing_.set_max_playout_delay(TimeDelta::Millis(10));
auto frame = Builder().Id(0).Time(0).AsLast().Build();
// Playout delay of 0 implies low-latency rendering.
frame->SetPlayoutDelay({0, 10});
@@ -822,8 +821,8 @@
TEST_P(LowLatencyFrameBufferProxyTest, MinMaxDelayZeroLowLatencyMode) {
// Initial keyframe.
StartNextDecodeForceKeyframe();
- timing_.set_min_playout_delay(0);
- timing_.set_max_playout_delay(0);
+ timing_.set_min_playout_delay(TimeDelta::Zero());
+ timing_.set_max_playout_delay(TimeDelta::Zero());
auto frame = Builder().Id(0).Time(0).AsLast().Build();
// Playout delay of 0 implies low-latency rendering.
frame->SetPlayoutDelay({0, 0});
diff --git a/video/frame_decode_timing.cc b/video/frame_decode_timing.cc
index ddc6030..c683834 100644
--- a/video/frame_decode_timing.cc
+++ b/video/frame_decode_timing.cc
@@ -30,10 +30,9 @@
uint32_t last_temporal_unit_rtp,
bool too_many_frames_queued) {
const Timestamp now = clock_->CurrentTime();
- Timestamp render_time = Timestamp::Millis(
- timing_->RenderTimeMs(next_temporal_unit_rtp, now.ms()));
- TimeDelta max_wait = TimeDelta::Millis(timing_->MaxWaitingTime(
- render_time.ms(), now.ms(), too_many_frames_queued));
+ Timestamp render_time = timing_->RenderTime(next_temporal_unit_rtp, now);
+ TimeDelta max_wait =
+ timing_->MaxWaitingTime(render_time, now, too_many_frames_queued);
// If the delay is not too far in the past, or this is the last decodable
// frame then it is the best frame to be decoded. Otherwise, fast-forward
diff --git a/video/frame_decode_timing_unittest.cc b/video/frame_decode_timing_unittest.cc
index ac5bf9e..0d99847 100644
--- a/video/frame_decode_timing_unittest.cc
+++ b/video/frame_decode_timing_unittest.cc
@@ -32,20 +32,18 @@
public:
explicit FakeVCMTiming(Clock* clock) : webrtc::VCMTiming(clock) {}
- int64_t RenderTimeMs(uint32_t frame_timestamp,
- int64_t now_ms) const override {
+ Timestamp RenderTime(uint32_t frame_timestamp, Timestamp now) const override {
RTC_DCHECK(render_time_map_.contains(frame_timestamp));
auto it = render_time_map_.find(frame_timestamp);
- return it->second.ms();
+ return it->second;
}
- int64_t MaxWaitingTime(int64_t render_time_ms,
- int64_t now_ms,
- bool too_many_frames_queued) const override {
- auto render_time = Timestamp::Millis(render_time_ms);
+ TimeDelta MaxWaitingTime(Timestamp render_time,
+ Timestamp now,
+ bool too_many_frames_queued) const override {
RTC_DCHECK(wait_time_map_.contains(render_time));
auto it = wait_time_map_.find(render_time);
- return it->second.ms();
+ return it->second;
}
void SetTimes(uint32_t frame_timestamp,
diff --git a/video/video_receive_stream2.cc b/video/video_receive_stream2.cc
index 5436c01..290180b 100644
--- a/video/video_receive_stream2.cc
+++ b/video/video_receive_stream2.cc
@@ -269,7 +269,7 @@
decoder_payload_types.insert(decoder.payload_type);
}
- timing_->set_render_delay(config_.render_delay_ms);
+ timing_->set_render_delay(TimeDelta::Millis(config_.render_delay_ms));
frame_buffer_ = FrameBufferProxy::CreateFromFieldTrial(
clock_, call_->worker_thread(), timing_.get(), &stats_proxy_,
@@ -710,7 +710,7 @@
if (!info)
return absl::nullopt;
- info->current_delay_ms = timing_->TargetVideoDelay();
+ info->current_delay_ms = timing_->TargetVideoDelay().ms();
return info;
}
@@ -970,7 +970,7 @@
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(minimum_delay_ms);
+ timing_->set_min_playout_delay(TimeDelta::Millis(minimum_delay_ms));
if (frame_minimum_playout_delay_ms_ == 0 &&
frame_maximum_playout_delay_ms_ > 0 && low_latency_renderer_enabled_) {
// TODO(kron): Estimate frame rate from video stream.
@@ -991,7 +991,7 @@
const int maximum_delay_ms = frame_maximum_playout_delay_ms_;
if (maximum_delay_ms >= 0) {
- timing_->set_max_playout_delay(maximum_delay_ms);
+ timing_->set_max_playout_delay(TimeDelta::Millis(maximum_delay_ms));
}
}
diff --git a/video/video_receive_stream2_unittest.cc b/video/video_receive_stream2_unittest.cc
index 3c6640a..213df38 100644
--- a/video/video_receive_stream2_unittest.cc
+++ b/video/video_receive_stream2_unittest.cc
@@ -163,30 +163,30 @@
test_frame->SetPlayoutDelay(kPlayoutDelayMs);
video_receive_stream_->OnCompleteFrame(std::move(test_frame));
- EXPECT_EQ(kPlayoutDelayMs.min_ms, timing_->min_playout_delay());
- EXPECT_EQ(kPlayoutDelayMs.max_ms, timing_->max_playout_delay());
+ EXPECT_EQ(kPlayoutDelayMs.min_ms, timing_->min_playout_delay().ms());
+ EXPECT_EQ(kPlayoutDelayMs.max_ms, timing_->max_playout_delay().ms());
// Check that the biggest minimum delay is chosen.
video_receive_stream_->SetMinimumPlayoutDelay(400);
- EXPECT_EQ(400, timing_->min_playout_delay());
+ EXPECT_EQ(400, timing_->min_playout_delay().ms());
// Check base minimum delay validation.
EXPECT_FALSE(video_receive_stream_->SetBaseMinimumPlayoutDelayMs(12345));
EXPECT_FALSE(video_receive_stream_->SetBaseMinimumPlayoutDelayMs(-1));
EXPECT_TRUE(video_receive_stream_->SetBaseMinimumPlayoutDelayMs(500));
- EXPECT_EQ(500, timing_->min_playout_delay());
+ EXPECT_EQ(500, timing_->min_playout_delay().ms());
// Check that intermidiate values are remembered and the biggest remembered
// is chosen.
video_receive_stream_->SetBaseMinimumPlayoutDelayMs(0);
- EXPECT_EQ(400, timing_->min_playout_delay());
+ EXPECT_EQ(400, timing_->min_playout_delay().ms());
video_receive_stream_->SetMinimumPlayoutDelay(0);
- EXPECT_EQ(123, timing_->min_playout_delay());
+ EXPECT_EQ(123, timing_->min_playout_delay().ms());
}
TEST_F(VideoReceiveStream2Test, PlayoutDelayPreservesDefaultMaxValue) {
- const int default_max_playout_latency = timing_->max_playout_delay();
+ const TimeDelta default_max_playout_latency = timing_->max_playout_delay();
const VideoPlayoutDelay kPlayoutDelayMs = {123, -1};
std::unique_ptr<FrameObjectFake> test_frame(new FrameObjectFake());
@@ -196,13 +196,13 @@
video_receive_stream_->OnCompleteFrame(std::move(test_frame));
// Ensure that -1 preserves default maximum value from `timing_`.
- EXPECT_EQ(kPlayoutDelayMs.min_ms, timing_->min_playout_delay());
- EXPECT_NE(kPlayoutDelayMs.max_ms, timing_->max_playout_delay());
+ EXPECT_EQ(kPlayoutDelayMs.min_ms, timing_->min_playout_delay().ms());
+ EXPECT_NE(kPlayoutDelayMs.max_ms, timing_->max_playout_delay().ms());
EXPECT_EQ(default_max_playout_latency, timing_->max_playout_delay());
}
TEST_F(VideoReceiveStream2Test, PlayoutDelayPreservesDefaultMinValue) {
- const int default_min_playout_latency = timing_->min_playout_delay();
+ const TimeDelta default_min_playout_latency = timing_->min_playout_delay();
const VideoPlayoutDelay kPlayoutDelayMs = {-1, 321};
std::unique_ptr<FrameObjectFake> test_frame(new FrameObjectFake());
@@ -212,8 +212,8 @@
video_receive_stream_->OnCompleteFrame(std::move(test_frame));
// Ensure that -1 preserves default minimum value from `timing_`.
- EXPECT_NE(kPlayoutDelayMs.min_ms, timing_->min_playout_delay());
- EXPECT_EQ(kPlayoutDelayMs.max_ms, timing_->max_playout_delay());
+ EXPECT_NE(kPlayoutDelayMs.min_ms, timing_->min_playout_delay().ms());
+ EXPECT_EQ(kPlayoutDelayMs.max_ms, timing_->max_playout_delay().ms());
EXPECT_EQ(default_min_playout_latency, timing_->min_playout_delay());
}
diff --git a/video/video_stream_decoder_impl.cc b/video/video_stream_decoder_impl.cc
index bbd67ee..907b8b0 100644
--- a/video/video_stream_decoder_impl.cc
+++ b/video/video_stream_decoder_impl.cc
@@ -70,11 +70,11 @@
}
void VideoStreamDecoderImpl::SetMinPlayoutDelay(TimeDelta min_delay) {
- timing_.set_min_playout_delay(min_delay.ms());
+ timing_.set_min_playout_delay(min_delay);
}
void VideoStreamDecoderImpl::SetMaxPlayoutDelay(TimeDelta max_delay) {
- timing_.set_max_playout_delay(max_delay.ms());
+ timing_.set_max_playout_delay(max_delay);
}
VideoDecoder* VideoStreamDecoderImpl::GetDecoder(int payload_type) {
@@ -258,7 +258,8 @@
Timestamp::Millis(frame_info->decode_start_time_ms +
*decode_time_ms)});
decoded_image.set_timestamp_us(frame_info->render_time_us);
- timing_.StopDecodeTimer(*decode_time_ms, decode_stop_time_ms);
+ timing_.StopDecodeTimer(TimeDelta::Millis(*decode_time_ms),
+ Timestamp::Millis(decode_stop_time_ms));
callbacks_->OnDecodedFrame(decoded_image, callback_info);
});