/* * Copyright (c) 2026, Alliance for Open Media. All rights reserved. * * This source code is subject to the terms of the BSD 2 Clause License and * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License * was not distributed with this source code in the LICENSE file, you can * obtain it at www.aomedia.org/license/software. If the Alliance for Open * Media Patent License 1.0 was not distributed with this source code in the * PATENTS file, you can obtain it at www.aomedia.org/license/patent. */ #include #include "gtest/gtest.h" #include "test/codec_factory.h" #include "test/encode_test_driver.h" #include "test/util.h" #include "test/video_source.h" namespace { class CancellableVideoSource : public ::libaom_test::VideoSource { public: explicit CancellableVideoSource(::libaom_test::VideoSource *source) : source_(source), cancel_after_(-1), current_pass_(0) {} void Begin() override { source_->Begin(); current_pass_++; } void Next() override { source_->Next(); } aom_image_t *img() const override { if (current_pass_ == 2 && cancel_after_ >= 0 && static_cast(source_->frame()) >= cancel_after_) { return nullptr; } return source_->img(); } aom_codec_pts_t pts() const override { return source_->pts(); } unsigned long duration() const override { return source_->duration(); } aom_rational_t timebase() const override { return source_->timebase(); } unsigned int frame() const override { return source_->frame(); } unsigned int limit() const override { return source_->limit(); } void set_cancel_after(int frame) { cancel_after_ = frame; } private: ::libaom_test::VideoSource *source_; int cancel_after_; int current_pass_; }; class CancellationTest : public ::libaom_test::EncoderTest, public ::libaom_test::CodecTestWithParam< ::libaom_test::TestMode> { protected: CancellationTest() : EncoderTest(GET_PARAM(0)), tile_columns_(0), tile_rows_(0) {} ~CancellationTest() override = default; void SetUp() override { InitializeConfig(GET_PARAM(1)); } void PreEncodeFrameHook(::libaom_test::VideoSource *video, ::libaom_test::Encoder *encoder) override { if (video->frame() == 0) { encoder->Control(AOME_SET_CPUUSED, 4); // speed 4 encoder->Control(AV1E_SET_TILE_COLUMNS, tile_columns_); encoder->Control(AV1E_SET_TILE_ROWS, tile_rows_); } } void DoSimulateCancellationPass2(int threads, int tile_columns, int tile_rows) { cfg_.g_threads = threads; tile_columns_ = tile_columns; tile_rows_ = tile_rows; ::libaom_test::RandomVideoSource raw_video; raw_video.SetSize(256, 256); raw_video.set_limit(40); // 40 frames total CancellableVideoSource video(&raw_video); video.set_cancel_after(20); // Cancel after 20 frames in pass 2 // This should not crash ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); } private: int tile_columns_; int tile_rows_; }; TEST_P(CancellationTest, SimulateCancellationPass2) { DoSimulateCancellationPass2(/*threads=*/1, /*tile_columns=*/0, /*tile_rows=*/0); } TEST_P(CancellationTest, SimulateCancellationPass2Threads4) { DoSimulateCancellationPass2(/*threads=*/4, /*tile_columns=*/1, /*tile_rows=*/1); } // Test 2-pass good quality AV1_INSTANTIATE_TEST_SUITE(CancellationTest, ::testing::Values(::libaom_test::kTwoPassGood)); } // namespace