mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-14 06:10:40 +01:00

Bug: b/237997865 Change-Id: I6d6e3faa48e6bddbe298ead7b1350dd3c70481b2 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/268545 Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org> Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org> Commit-Queue: Artem Titov <titovartem@webrtc.org> Cr-Commit-Position: refs/heads/main@{#37543}
114 lines
3.1 KiB
C++
114 lines
3.1 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 "test/testsupport/fixed_fps_video_frame_writer_adapter.h"
|
|
|
|
#include <cmath>
|
|
#include <utility>
|
|
|
|
#include "absl/types/optional.h"
|
|
#include "api/units/time_delta.h"
|
|
#include "api/video/video_sink_interface.h"
|
|
#include "rtc_base/checks.h"
|
|
#include "test/testsupport/video_frame_writer.h"
|
|
|
|
namespace webrtc {
|
|
namespace test {
|
|
namespace {
|
|
|
|
constexpr TimeDelta kOneSecond = TimeDelta::Seconds(1);
|
|
|
|
} // namespace
|
|
|
|
FixedFpsVideoFrameWriterAdapter::FixedFpsVideoFrameWriterAdapter(
|
|
int fps,
|
|
Clock* clock,
|
|
std::unique_ptr<VideoFrameWriter> delegate)
|
|
: inter_frame_interval_(kOneSecond / fps),
|
|
clock_(clock),
|
|
delegate_(std::move(delegate)) {}
|
|
|
|
FixedFpsVideoFrameWriterAdapter::~FixedFpsVideoFrameWriterAdapter() {
|
|
Close();
|
|
}
|
|
|
|
void FixedFpsVideoFrameWriterAdapter::Close() {
|
|
if (is_closed_) {
|
|
return;
|
|
}
|
|
is_closed_ = true;
|
|
if (!last_frame_.has_value()) {
|
|
return;
|
|
}
|
|
Timestamp now = Now();
|
|
RTC_CHECK(WriteMissedSlotsExceptLast(now));
|
|
RTC_CHECK(delegate_->WriteFrame(*last_frame_));
|
|
delegate_->Close();
|
|
}
|
|
|
|
bool FixedFpsVideoFrameWriterAdapter::WriteFrame(const VideoFrame& frame) {
|
|
RTC_CHECK(!is_closed_);
|
|
Timestamp now = Now();
|
|
if (!last_frame_.has_value()) {
|
|
RTC_CHECK(!last_frame_time_.IsFinite());
|
|
last_frame_ = frame;
|
|
last_frame_time_ = now;
|
|
return true;
|
|
}
|
|
|
|
RTC_CHECK(last_frame_time_.IsFinite());
|
|
|
|
if (last_frame_time_ > now) {
|
|
// New frame was recevied before expected time "slot" for current
|
|
// `last_frame_` came => just replace current `last_frame_` with
|
|
// received `frame`.
|
|
RTC_CHECK_LE(last_frame_time_ - now, inter_frame_interval_ / 2);
|
|
last_frame_ = frame;
|
|
return true;
|
|
}
|
|
|
|
if (!WriteMissedSlotsExceptLast(now)) {
|
|
return false;
|
|
}
|
|
|
|
if (now - last_frame_time_ < inter_frame_interval_ / 2) {
|
|
// New frame was received closer to the expected time "slot" for current
|
|
// `last_frame_` than to the next "slot" => just replace current
|
|
// `last_frame_` with received `frame`.
|
|
last_frame_ = frame;
|
|
return true;
|
|
}
|
|
|
|
if (!delegate_->WriteFrame(*last_frame_)) {
|
|
return false;
|
|
}
|
|
last_frame_ = frame;
|
|
last_frame_time_ = last_frame_time_ + inter_frame_interval_;
|
|
return true;
|
|
}
|
|
|
|
bool FixedFpsVideoFrameWriterAdapter::WriteMissedSlotsExceptLast(
|
|
Timestamp now) {
|
|
RTC_CHECK(last_frame_time_.IsFinite());
|
|
while (now - last_frame_time_ > inter_frame_interval_) {
|
|
if (!delegate_->WriteFrame(*last_frame_)) {
|
|
return false;
|
|
}
|
|
last_frame_time_ = last_frame_time_ + inter_frame_interval_;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
Timestamp FixedFpsVideoFrameWriterAdapter::Now() const {
|
|
return clock_->CurrentTime();
|
|
}
|
|
|
|
} // namespace test
|
|
} // namespace webrtc
|