blob: 2807e654bfe6a405ea58342030f8f7d65c63facd [file] [log] [blame]
/*
* 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/task_queue_frame_decode_scheduler.h"
#include <stddef.h>
#include <memory>
#include <utility>
#include "absl/functional/bind_front.h"
#include "absl/types/optional.h"
#include "api/units/time_delta.h"
#include "api/units/timestamp.h"
#include "rtc_base/task_queue.h"
#include "test/gmock.h"
#include "test/gtest.h"
#include "test/time_controller/simulated_time_controller.h"
namespace webrtc {
using ::testing::Eq;
using ::testing::Optional;
class TaskQueueFrameDecodeSchedulerTest : public ::testing::Test {
public:
TaskQueueFrameDecodeSchedulerTest()
: time_controller_(Timestamp::Millis(2000)),
task_queue_(time_controller_.GetTaskQueueFactory()->CreateTaskQueue(
"scheduler",
TaskQueueFactory::Priority::NORMAL)),
scheduler_(std::make_unique<TaskQueueFrameDecodeScheduler>(
time_controller_.GetClock(),
task_queue_.Get())) {}
~TaskQueueFrameDecodeSchedulerTest() override {
if (scheduler_) {
OnQueue([&] {
scheduler_->Stop();
scheduler_ = nullptr;
});
}
}
void FrameReadyForDecode(uint32_t timestamp, Timestamp render_time) {
last_rtp_ = timestamp;
last_render_time_ = render_time;
}
protected:
template <class Task>
void OnQueue(Task&& t) {
task_queue_.PostTask(std::forward<Task>(t));
time_controller_.AdvanceTime(TimeDelta::Zero());
}
GlobalSimulatedTimeController time_controller_;
rtc::TaskQueue task_queue_;
std::unique_ptr<FrameDecodeScheduler> scheduler_;
absl::optional<uint32_t> last_rtp_;
absl::optional<Timestamp> last_render_time_;
};
TEST_F(TaskQueueFrameDecodeSchedulerTest, FrameYieldedAfterSpecifiedPeriod) {
constexpr TimeDelta decode_delay = TimeDelta::Millis(5);
const Timestamp now = time_controller_.GetClock()->CurrentTime();
const uint32_t rtp = 90000;
const Timestamp render_time = now + TimeDelta::Millis(15);
FrameDecodeTiming::FrameSchedule schedule = {
.latest_decode_time = now + decode_delay, .render_time = render_time};
OnQueue([&] {
scheduler_->ScheduleFrame(
rtp, schedule,
absl::bind_front(
&TaskQueueFrameDecodeSchedulerTest::FrameReadyForDecode, this));
EXPECT_THAT(scheduler_->ScheduledRtpTimestamp(), Optional(rtp));
});
EXPECT_THAT(last_rtp_, Eq(absl::nullopt));
time_controller_.AdvanceTime(decode_delay);
EXPECT_THAT(last_rtp_, Optional(rtp));
EXPECT_THAT(last_render_time_, Optional(render_time));
}
TEST_F(TaskQueueFrameDecodeSchedulerTest, NegativeDecodeDelayIsRoundedToZero) {
constexpr TimeDelta decode_delay = TimeDelta::Millis(-5);
const Timestamp now = time_controller_.GetClock()->CurrentTime();
const uint32_t rtp = 90000;
const Timestamp render_time = now + TimeDelta::Millis(15);
FrameDecodeTiming::FrameSchedule schedule = {
.latest_decode_time = now + decode_delay, .render_time = render_time};
OnQueue([&] {
scheduler_->ScheduleFrame(
rtp, schedule,
absl::bind_front(
&TaskQueueFrameDecodeSchedulerTest::FrameReadyForDecode, this));
EXPECT_THAT(scheduler_->ScheduledRtpTimestamp(), Optional(rtp));
});
EXPECT_THAT(last_rtp_, Optional(rtp));
EXPECT_THAT(last_render_time_, Optional(render_time));
}
TEST_F(TaskQueueFrameDecodeSchedulerTest, CancelOutstanding) {
constexpr TimeDelta decode_delay = TimeDelta::Millis(50);
const Timestamp now = time_controller_.GetClock()->CurrentTime();
const uint32_t rtp = 90000;
FrameDecodeTiming::FrameSchedule schedule = {
.latest_decode_time = now + decode_delay,
.render_time = now + TimeDelta::Millis(75)};
OnQueue([&] {
scheduler_->ScheduleFrame(
rtp, schedule,
absl::bind_front(
&TaskQueueFrameDecodeSchedulerTest::FrameReadyForDecode, this));
EXPECT_THAT(scheduler_->ScheduledRtpTimestamp(), Optional(rtp));
});
time_controller_.AdvanceTime(decode_delay / 2);
OnQueue([&] {
EXPECT_THAT(scheduler_->ScheduledRtpTimestamp(), Optional(rtp));
scheduler_->CancelOutstanding();
EXPECT_THAT(scheduler_->ScheduledRtpTimestamp(), Eq(absl::nullopt));
});
time_controller_.AdvanceTime(decode_delay / 2);
EXPECT_THAT(last_rtp_, Eq(absl::nullopt));
EXPECT_THAT(last_render_time_, Eq(absl::nullopt));
}
} // namespace webrtc