/* * 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. */ #include "video/frame_buffer_proxy.h" #include #include #include "modules/video_coding/frame_buffer2.h" namespace webrtc { class FrameBuffer2Proxy : public FrameBufferProxy { public: FrameBuffer2Proxy(Clock* clock, VCMTiming* timing, VCMReceiveStatisticsCallback* stats_proxy, rtc::TaskQueue* decode_queue, FrameSchedulingReceiver* receiver, TimeDelta max_wait_for_keyframe, TimeDelta max_wait_for_frame) : max_wait_for_keyframe_(max_wait_for_keyframe), max_wait_for_frame_(max_wait_for_frame), frame_buffer_(clock, timing, stats_proxy), decode_queue_(decode_queue), stats_proxy_(stats_proxy), receiver_(receiver) { RTC_DCHECK(decode_queue_); RTC_DCHECK(stats_proxy_); RTC_DCHECK(receiver_); } void StopOnWorker() override { RTC_DCHECK_RUN_ON(&worker_sequence_checker_); decode_queue_->PostTask([this] { frame_buffer_.Stop(); decode_safety_->SetNotAlive(); }); } void SetProtectionMode(VCMVideoProtection protection_mode) override { RTC_DCHECK_RUN_ON(&worker_sequence_checker_); frame_buffer_.SetProtectionMode(kProtectionNackFEC); } void Clear() override { RTC_DCHECK_RUN_ON(&worker_sequence_checker_); frame_buffer_.Clear(); } absl::optional InsertFrame( std::unique_ptr frame) override { RTC_DCHECK_RUN_ON(&worker_sequence_checker_); int64_t last_continuous_pid = frame_buffer_.InsertFrame(std::move(frame)); if (last_continuous_pid != -1) return last_continuous_pid; return absl::nullopt; } void UpdateRtt(int64_t max_rtt_ms) override { RTC_DCHECK_RUN_ON(&worker_sequence_checker_); frame_buffer_.UpdateRtt(max_rtt_ms); } void StartNextDecode(bool keyframe_required) override { if (!decode_queue_->IsCurrent()) { decode_queue_->PostTask(ToQueuedTask( decode_safety_, [this, keyframe_required] { StartNextDecode(keyframe_required); })); return; } RTC_DCHECK_RUN_ON(decode_queue_); frame_buffer_.NextFrame( MaxWait(keyframe_required).ms(), keyframe_required, decode_queue_, /* encoded frame handler */ [this, keyframe_required](std::unique_ptr frame) { RTC_DCHECK_RUN_ON(decode_queue_); if (!decode_safety_->alive()) return; if (frame) { receiver_->OnEncodedFrame(std::move(frame)); } else { receiver_->OnDecodableFrameTimeout(MaxWait(keyframe_required)); } }); } int Size() override { RTC_DCHECK_RUN_ON(&worker_sequence_checker_); return frame_buffer_.Size(); } private: TimeDelta MaxWait(bool keyframe_required) const { return keyframe_required ? max_wait_for_keyframe_ : max_wait_for_frame_; } RTC_NO_UNIQUE_ADDRESS SequenceChecker worker_sequence_checker_; const TimeDelta max_wait_for_keyframe_; const TimeDelta max_wait_for_frame_; video_coding::FrameBuffer frame_buffer_; rtc::TaskQueue* const decode_queue_; VCMReceiveStatisticsCallback* const stats_proxy_; FrameSchedulingReceiver* const receiver_; rtc::scoped_refptr decode_safety_ = PendingTaskSafetyFlag::CreateDetached(); }; // TODO(bugs.webrtc.org/13343): Create FrameBuffer3Proxy when complete. std::unique_ptr FrameBufferProxy::CreateFromFieldTrial( Clock* clock, TaskQueueBase* worker_queue, VCMTiming* timing, VCMReceiveStatisticsCallback* stats_proxy, rtc::TaskQueue* decode_queue, FrameSchedulingReceiver* receiver, TimeDelta max_wait_for_keyframe, TimeDelta max_wait_for_frame) { return std::make_unique( clock, timing, stats_proxy, decode_queue, receiver, max_wait_for_keyframe, max_wait_for_frame); } } // namespace webrtc