diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /third_party/libwebrtc/video/decode_synchronizer.h | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/libwebrtc/video/decode_synchronizer.h')
-rw-r--r-- | third_party/libwebrtc/video/decode_synchronizer.h | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/third_party/libwebrtc/video/decode_synchronizer.h b/third_party/libwebrtc/video/decode_synchronizer.h new file mode 100644 index 0000000000..c6f8efdb29 --- /dev/null +++ b/third_party/libwebrtc/video/decode_synchronizer.h @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2022 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef VIDEO_DECODE_SYNCHRONIZER_H_ +#define VIDEO_DECODE_SYNCHRONIZER_H_ + +#include <stdint.h> + +#include <functional> +#include <memory> +#include <set> +#include <utility> + +#include "absl/types/optional.h" +#include "api/metronome/metronome.h" +#include "api/sequence_checker.h" +#include "api/task_queue/task_queue_base.h" +#include "api/units/timestamp.h" +#include "rtc_base/checks.h" +#include "rtc_base/thread_annotations.h" +#include "video/frame_decode_scheduler.h" +#include "video/frame_decode_timing.h" + +namespace webrtc { + +// DecodeSynchronizer synchronizes the frame scheduling by coalescing decoding +// on the metronome. +// +// A video receive stream can use the DecodeSynchronizer by receiving a +// FrameDecodeScheduler instance with `CreateSynchronizedFrameScheduler()`. +// This instance implements FrameDecodeScheduler and can be used as a normal +// scheduler. This instance is owned by the receive stream, and is borrowed by +// the DecodeSynchronizer. The DecodeSynchronizer will stop borrowing the +// instance when `FrameDecodeScheduler::Stop()` is called, after which the +// scheduler may be destroyed by the receive stream. +// +// When a frame is scheduled for decode by a receive stream using the +// DecodeSynchronizer, it will instead be executed on the metronome during the +// tick interval where `max_decode_time` occurs. For example, if a frame is +// scheduled for decode in 50ms and the tick interval is 20ms, then the frame +// will be released for decoding in 2 ticks. See below for illustration, +// +// In the case where the decode time is in the past, or must occur before the +// next metronome tick then the frame will be released right away, allowing a +// delayed stream to catch up quickly. +// +// DecodeSynchronizer is single threaded - all method calls must run on the +// `worker_queue_`. +class DecodeSynchronizer { + public: + DecodeSynchronizer(Clock* clock, + Metronome* metronome, + TaskQueueBase* worker_queue); + ~DecodeSynchronizer(); + DecodeSynchronizer(const DecodeSynchronizer&) = delete; + DecodeSynchronizer& operator=(const DecodeSynchronizer&) = delete; + + std::unique_ptr<FrameDecodeScheduler> CreateSynchronizedFrameScheduler(); + + private: + class ScheduledFrame { + public: + ScheduledFrame(uint32_t rtp_timestamp, + FrameDecodeTiming::FrameSchedule schedule, + FrameDecodeScheduler::FrameReleaseCallback callback); + + // Disallow copy since `callback` should only be moved. + ScheduledFrame(const ScheduledFrame&) = delete; + ScheduledFrame& operator=(const ScheduledFrame&) = delete; + ScheduledFrame(ScheduledFrame&&) = default; + ScheduledFrame& operator=(ScheduledFrame&&) = default; + + // Executes `callback_`. + void RunFrameReleaseCallback() &&; + + uint32_t rtp_timestamp() const { return rtp_timestamp_; } + Timestamp LatestDecodeTime() const; + + private: + uint32_t rtp_timestamp_; + FrameDecodeTiming::FrameSchedule schedule_; + FrameDecodeScheduler::FrameReleaseCallback callback_; + }; + + class SynchronizedFrameDecodeScheduler : public FrameDecodeScheduler { + public: + explicit SynchronizedFrameDecodeScheduler(DecodeSynchronizer* sync); + ~SynchronizedFrameDecodeScheduler() override; + + // Releases the outstanding frame for decoding. This invalidates + // `next_frame_`. There must be a frame scheduled. + ScheduledFrame ReleaseNextFrame(); + + // Returns `next_frame_.schedule.max_decode_time`. There must be a frame + // scheduled when this is called. + Timestamp LatestDecodeTime(); + + // FrameDecodeScheduler implementation. + absl::optional<uint32_t> ScheduledRtpTimestamp() override; + void ScheduleFrame(uint32_t rtp, + FrameDecodeTiming::FrameSchedule schedule, + FrameReleaseCallback cb) override; + void CancelOutstanding() override; + void Stop() override; + + private: + DecodeSynchronizer* sync_; + absl::optional<ScheduledFrame> next_frame_; + bool stopped_ = false; + }; + + void OnFrameScheduled(SynchronizedFrameDecodeScheduler* scheduler); + void RemoveFrameScheduler(SynchronizedFrameDecodeScheduler* scheduler); + + void ScheduleNextTick(); + void OnTick(); + + Clock* const clock_; + TaskQueueBase* const worker_queue_; + Metronome* const metronome_; + + Timestamp expected_next_tick_ = Timestamp::PlusInfinity(); + std::set<SynchronizedFrameDecodeScheduler*> schedulers_ + RTC_GUARDED_BY(worker_queue_); + ScopedTaskSafetyDetached safety_; +}; + +} // namespace webrtc + +#endif // VIDEO_DECODE_SYNCHRONIZER_H_ |