| /* | |
| * 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_VIDEO_STREAM_BUFFER_CONTROLLER_H_ | |
| #define VIDEO_VIDEO_STREAM_BUFFER_CONTROLLER_H_ | |
| #include <cstddef> | |
| #include <cstdint> | |
| #include <memory> | |
| #include <optional> | |
| #include "absl/container/inlined_vector.h" | |
| #include "api/field_trials_view.h" | |
| #include "api/sequence_checker.h" | |
| #include "api/task_queue/pending_task_safety_flag.h" | |
| #include "api/task_queue/task_queue_base.h" | |
| #include "api/units/time_delta.h" | |
| #include "api/units/timestamp.h" | |
| #include "api/video/encoded_frame.h" | |
| #include "api/video/frame_buffer.h" | |
| #include "api/video/video_content_type.h" | |
| #include "api/video/video_timing.h" | |
| #include "modules/video_coding/include/video_coding_defines.h" | |
| #include "modules/video_coding/timing/inter_frame_delay_variation_calculator.h" | |
| #include "modules/video_coding/timing/jitter_estimator.h" | |
| #include "modules/video_coding/timing/timing.h" | |
| #include "rtc_base/experiments/field_trial_parser.h" | |
| #include "rtc_base/system/no_unique_address.h" | |
| #include "rtc_base/thread_annotations.h" | |
| #include "system_wrappers/include/clock.h" | |
| #include "video/frame_decode_scheduler.h" | |
| #include "video/frame_decode_timing.h" | |
| #include "video/video_receive_stream_timeout_tracker.h" | |
| namespace webrtc { | |
| class FrameSchedulingReceiver { | |
| public: | |
| virtual ~FrameSchedulingReceiver() = default; | |
| virtual void OnEncodedFrame(std::unique_ptr<EncodedFrame> frame) = 0; | |
| virtual void OnDecodableFrameTimeout(TimeDelta wait_time) = 0; | |
| }; | |
| class VideoStreamBufferControllerStatsObserver { | |
| public: | |
| virtual ~VideoStreamBufferControllerStatsObserver() = default; | |
| virtual void OnCompleteFrame(bool is_keyframe, | |
| size_t size_bytes, | |
| VideoContentType content_type) = 0; | |
| virtual void OnDroppedFrames(uint32_t frames_dropped) = 0; | |
| // `jitter_buffer_delay` is the delay experienced by a single frame, | |
| // whereas `target_delay` and `minimum_delay` are the current delays | |
| // applied by the jitter buffer. | |
| virtual void OnDecodableFrame(TimeDelta jitter_buffer_delay, | |
| TimeDelta target_delay, | |
| TimeDelta minimum_delay) = 0; | |
| // Various jitter buffer delays determined by VCMTiming. | |
| virtual void OnFrameBufferTimingsUpdated(int estimated_max_decode_time_ms, | |
| int current_delay_ms, | |
| int target_delay_ms, | |
| int jitter_delay_ms, | |
| int min_playout_delay_ms, | |
| int render_delay_ms) = 0; | |
| virtual void OnTimingFrameInfoUpdated(const TimingFrameInfo& info) = 0; | |
| }; | |
| class VideoStreamBufferController { | |
| public: | |
| VideoStreamBufferController( | |
| Clock* clock, | |
| TaskQueueBase* worker_queue, | |
| VCMTiming* timing, | |
| VideoStreamBufferControllerStatsObserver* stats_proxy, | |
| FrameSchedulingReceiver* receiver, | |
| TimeDelta max_wait_for_keyframe, | |
| TimeDelta max_wait_for_frame, | |
| std::unique_ptr<FrameDecodeScheduler> frame_decode_scheduler, | |
| const FieldTrialsView& field_trials); | |
| virtual ~VideoStreamBufferController() = default; | |
| void Stop(); | |
| void SetProtectionMode(VCMVideoProtection protection_mode); | |
| void Clear(); | |
| std::optional<int64_t> InsertFrame(std::unique_ptr<EncodedFrame> frame); | |
| void UpdateRtt(int64_t max_rtt_ms); | |
| void SetMaxWaits(TimeDelta max_wait_for_keyframe, | |
| TimeDelta max_wait_for_frame); | |
| void StartNextDecode(bool keyframe_required); | |
| int Size(); | |
| private: | |
| void OnFrameReady( | |
| absl::InlinedVector<std::unique_ptr<EncodedFrame>, 4> frames, | |
| Timestamp render_time); | |
| void OnTimeout(TimeDelta delay); | |
| void FrameReadyForDecode(uint32_t rtp_timestamp, Timestamp render_time); | |
| void UpdateDroppedFrames() RTC_RUN_ON(&worker_sequence_checker_); | |
| void UpdateFrameBufferTimings(Timestamp min_receive_time, Timestamp now); | |
| void UpdateTimingFrameInfo(); | |
| bool IsTooManyFramesQueued() const RTC_RUN_ON(&worker_sequence_checker_); | |
| void ForceKeyFrameReleaseImmediately() RTC_RUN_ON(&worker_sequence_checker_); | |
| void MaybeScheduleFrameForRelease() RTC_RUN_ON(&worker_sequence_checker_); | |
| RTC_NO_UNIQUE_ADDRESS SequenceChecker worker_sequence_checker_; | |
| const FieldTrialsView& field_trials_; | |
| Clock* const clock_; | |
| VideoStreamBufferControllerStatsObserver* const stats_proxy_; | |
| FrameSchedulingReceiver* const receiver_; | |
| VCMTiming* const timing_; | |
| const std::unique_ptr<FrameDecodeScheduler> frame_decode_scheduler_ | |
| RTC_GUARDED_BY(&worker_sequence_checker_); | |
| JitterEstimator jitter_estimator_ RTC_GUARDED_BY(&worker_sequence_checker_); | |
| InterFrameDelayVariationCalculator ifdv_calculator_ | |
| RTC_GUARDED_BY(&worker_sequence_checker_); | |
| bool keyframe_required_ RTC_GUARDED_BY(&worker_sequence_checker_) = false; | |
| std::unique_ptr<FrameBuffer> buffer_ | |
| RTC_GUARDED_BY(&worker_sequence_checker_); | |
| FrameDecodeTiming decode_timing_ RTC_GUARDED_BY(&worker_sequence_checker_); | |
| VideoReceiveStreamTimeoutTracker timeout_tracker_ | |
| RTC_GUARDED_BY(&worker_sequence_checker_); | |
| int frames_dropped_before_last_new_frame_ | |
| RTC_GUARDED_BY(&worker_sequence_checker_) = 0; | |
| VCMVideoProtection protection_mode_ | |
| RTC_GUARDED_BY(&worker_sequence_checker_) = kProtectionNack; | |
| // This flag guards frames from queuing in front of the decoder. Without this | |
| // guard, encoded frames will not wait for the decoder to finish decoding a | |
| // frame and just queue up, meaning frames will not be dropped or | |
| // fast-forwarded when the decoder is slow or hangs. | |
| bool decoder_ready_for_new_frame_ RTC_GUARDED_BY(&worker_sequence_checker_) = | |
| false; | |
| // Maximum number of frames in the decode queue to allow pacing. If the | |
| // queue grows beyond the max limit, pacing will be disabled and frames will | |
| // be pushed to the decoder as soon as possible. This only has an effect | |
| // when the low-latency rendering path is active, which is indicated by | |
| // the frame's render time == 0. | |
| FieldTrialParameter<unsigned> zero_playout_delay_max_decode_queue_size_; | |
| ScopedTaskSafety worker_safety_; | |
| }; | |
| } // namespace webrtc | |
| #endif // VIDEO_VIDEO_STREAM_BUFFER_CONTROLLER_H_ |