From 2dd39152844c427747f801a22943139e9d196a87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Bostr=C3=B6m?= Date: Tue, 25 Jan 2022 08:20:33 +0100 Subject: [PATCH] Make use of TaskQueue/TaskQueueBase's PostDelayedHighPrecisionTask. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use cases of TaskQueue or TaskQueueBase that are considered high precision are updated to make use of PostDelayedHighPrecisionTask (see go/postdelayedtask-precision-in-webrtc) instead of PostDelayedTask. The cases here are the ones covered by that document, plus some testing-only uses. The FrameBuffer2 and DataTracker use cases will be covered by separate CLs because FrameBuffer2 uses RepeatingTaskHandle and DataTracker uses dcsctp::Timer. This protects these use cases against regressions when PostDelayedTask gets its precision lowered. This CL also adds TaskQueue::PostDelayedHighPrecisionTask which calls TaskQueueBase::PostDelayedHighPrecisionTask (same pattern as for PostDelayedTask). Bug: webrtc:13604 Change-Id: I7dcab59cbe4d274d27b734ceb4fc06daa12ffd0f Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/248864 Reviewed-by: Erik Språng Reviewed-by: Tomas Gunnarsson Commit-Queue: Henrik Boström Cr-Commit-Position: refs/heads/main@{#35781} --- call/degraded_call.cc | 2 +- common_video/incoming_video_stream.cc | 3 ++- modules/pacing/task_queue_paced_sender.cc | 2 +- pc/dtmf_sender.cc | 2 +- rtc_base/task_queue.cc | 6 ++++++ rtc_base/task_queue.h | 19 +++++++++++-------- test/fake_decoder.cc | 2 +- video/frame_cadence_adapter.cc | 15 ++++++++------- 8 files changed, 31 insertions(+), 20 deletions(-) diff --git a/call/degraded_call.cc b/call/degraded_call.cc index 5462085490..2370bc0b38 100644 --- a/call/degraded_call.cc +++ b/call/degraded_call.cc @@ -66,7 +66,7 @@ bool DegradedCall::FakeNetworkPipeOnTaskQueue::Process() { int64_t next_process_time = *time_to_next + clock_->TimeInMilliseconds(); if (!next_process_ms_ || next_process_time < *next_process_ms_) { next_process_ms_ = next_process_time; - task_queue_.PostDelayedTask( + task_queue_.PostDelayedHighPrecisionTask( [this]() { RTC_DCHECK_RUN_ON(&task_queue_); if (!Process()) { diff --git a/common_video/incoming_video_stream.cc b/common_video/incoming_video_stream.cc index 15c668e78e..1511c9f30c 100644 --- a/common_video/incoming_video_stream.cc +++ b/common_video/incoming_video_stream.cc @@ -57,7 +57,8 @@ void IncomingVideoStream::Dequeue() { if (render_buffers_.HasPendingFrames()) { uint32_t wait_time = render_buffers_.TimeToNextFrameRelease(); - incoming_render_queue_.PostDelayedTask([this]() { Dequeue(); }, wait_time); + incoming_render_queue_.PostDelayedHighPrecisionTask([this]() { Dequeue(); }, + wait_time); } } diff --git a/modules/pacing/task_queue_paced_sender.cc b/modules/pacing/task_queue_paced_sender.cc index 16c2de58c6..c58241fdd8 100644 --- a/modules/pacing/task_queue_paced_sender.cc +++ b/modules/pacing/task_queue_paced_sender.cc @@ -271,7 +271,7 @@ void TaskQueuePacedSender::MaybeProcessPackets( // Set a new scheduled process time and post a delayed task. next_process_time_ = next_process_time; - task_queue_.PostDelayedTask( + task_queue_.PostDelayedHighPrecisionTask( [this, next_process_time]() { MaybeProcessPackets(next_process_time); }, time_to_next_process->ms()); } diff --git a/pc/dtmf_sender.cc b/pc/dtmf_sender.cc index 46811c881b..1148350aa2 100644 --- a/pc/dtmf_sender.cc +++ b/pc/dtmf_sender.cc @@ -167,7 +167,7 @@ int DtmfSender::comma_delay() const { void DtmfSender::QueueInsertDtmf(const rtc::Location& posted_from, uint32_t delay_ms) { - signaling_thread_->PostDelayedTask( + signaling_thread_->PostDelayedHighPrecisionTask( ToQueuedTask(safety_flag_, [this] { RTC_DCHECK_RUN_ON(signaling_thread_); diff --git a/rtc_base/task_queue.cc b/rtc_base/task_queue.cc index 965a4d8c69..f0dbdb3ae0 100644 --- a/rtc_base/task_queue.cc +++ b/rtc_base/task_queue.cc @@ -38,4 +38,10 @@ void TaskQueue::PostDelayedTask(std::unique_ptr task, return impl_->PostDelayedTask(std::move(task), milliseconds); } +void TaskQueue::PostDelayedHighPrecisionTask( + std::unique_ptr task, + uint32_t milliseconds) { + return impl_->PostDelayedHighPrecisionTask(std::move(task), milliseconds); +} + } // namespace rtc diff --git a/rtc_base/task_queue.h b/rtc_base/task_queue.h index 1798d06b5d..4ad3fedd95 100644 --- a/rtc_base/task_queue.h +++ b/rtc_base/task_queue.h @@ -95,14 +95,11 @@ class RTC_LOCKABLE RTC_EXPORT TaskQueue { // Ownership of the task is passed to PostTask. void PostTask(std::unique_ptr task); - - // Schedules a task to execute a specified number of milliseconds from when - // the call is made. The precision should be considered as "best effort" - // and in some cases, such as on Windows when all high precision timers have - // been used up, can be off by as much as 15 millseconds (although 8 would be - // more likely). This can be mitigated by limiting the use of delayed tasks. + // See webrtc::TaskQueueBase for precision expectations. void PostDelayedTask(std::unique_ptr task, uint32_t milliseconds); + void PostDelayedHighPrecisionTask(std::unique_ptr task, + uint32_t milliseconds); // std::enable_if is used here to make sure that calls to PostTask() with // std::unique_ptr would not end up being @@ -114,8 +111,6 @@ class RTC_LOCKABLE RTC_EXPORT TaskQueue { void PostTask(Closure&& closure) { PostTask(webrtc::ToQueuedTask(std::forward(closure))); } - - // See documentation above for performance expectations. template (closure)), milliseconds); } + template >::value>::type* = nullptr> + void PostDelayedHighPrecisionTask(Closure&& closure, uint32_t milliseconds) { + PostDelayedHighPrecisionTask( + webrtc::ToQueuedTask(std::forward(closure)), milliseconds); + } private: webrtc::TaskQueueBase* const impl_; diff --git a/test/fake_decoder.cc b/test/fake_decoder.cc index 46765d5b31..2cb2aa258e 100644 --- a/test/fake_decoder.cc +++ b/test/fake_decoder.cc @@ -61,7 +61,7 @@ int32_t FakeDecoder::Decode(const EncodedImage& input, if (decode_delay_ms_ == 0 || !task_queue_) { callback_->Decoded(frame); } else { - task_queue_->PostDelayedTask( + task_queue_->PostDelayedHighPrecisionTask( [frame, this]() { VideoFrame copy = frame; callback_->Decoded(copy); diff --git a/video/frame_cadence_adapter.cc b/video/frame_cadence_adapter.cc index 7b69165fc8..30c16b1db4 100644 --- a/video/frame_cadence_adapter.cc +++ b/video/frame_cadence_adapter.cc @@ -359,12 +359,13 @@ void ZeroHertzAdapterMode::OnFrame(Timestamp post_time, queued_frames_.push_back(frame); current_frame_id_++; scheduled_repeat_ = absl::nullopt; - queue_->PostDelayedTask(ToQueuedTask(safety_, - [this] { - RTC_DCHECK_RUN_ON(&sequence_checker_); - ProcessOnDelayedCadence(); - }), - frame_delay_.ms()); + queue_->PostDelayedHighPrecisionTask( + ToQueuedTask(safety_, + [this] { + RTC_DCHECK_RUN_ON(&sequence_checker_); + ProcessOnDelayedCadence(); + }), + frame_delay_.ms()); } absl::optional ZeroHertzAdapterMode::GetInputFrameRateFps() { @@ -475,7 +476,7 @@ void ZeroHertzAdapterMode::ScheduleRepeat(int frame_id, bool idle_repeat) { scheduled_repeat_->idle = idle_repeat; TimeDelta repeat_delay = RepeatDuration(idle_repeat); - queue_->PostDelayedTask( + queue_->PostDelayedHighPrecisionTask( ToQueuedTask(safety_, [this, frame_id] { RTC_DCHECK_RUN_ON(&sequence_checker_);