This is a delegate that is used by video_receive_stream2 to handle frame buffer tasks like threading, and stats. This will be used in a follow up to use FrameBuffer3 as a strategy selected by field trial. Unit-tests will be used in follow-up CLs containing Frame Buffer 3, and are expected to work with both Frame buffer proxy versions. Change-Id: I524279343d60a348d044d9085d618f12d7bf3a23 Bug: webrtc:13343 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/241605 Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org> Reviewed-by: Philip Eliasson <philipel@webrtc.org> Commit-Queue: Evan Shrubsole <eshr@webrtc.org> Cr-Commit-Position: refs/heads/main@{#35803}
133 lines
4.3 KiB
C++
133 lines
4.3 KiB
C++
/*
|
|
* 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 <memory>
|
|
#include <utility>
|
|
|
|
#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<int64_t> InsertFrame(
|
|
std::unique_ptr<EncodedFrame> 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<EncodedFrame> 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<PendingTaskSafetyFlag> decode_safety_ =
|
|
PendingTaskSafetyFlag::CreateDetached();
|
|
};
|
|
|
|
// TODO(bugs.webrtc.org/13343): Create FrameBuffer3Proxy when complete.
|
|
std::unique_ptr<FrameBufferProxy> 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<FrameBuffer2Proxy>(
|
|
clock, timing, stats_proxy, decode_queue, receiver, max_wait_for_keyframe,
|
|
max_wait_for_frame);
|
|
}
|
|
|
|
} // namespace webrtc
|