Skip to content

Commit

Permalink
Add tests for more encoding cases
Browse files Browse the repository at this point in the history
  • Loading branch information
tongyuantongyu committed Jan 15, 2023
1 parent d0d7290 commit 3eeb8c1
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 61 deletions.
4 changes: 4 additions & 0 deletions src/codec_aom.c
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,10 @@ static avifResult aomCodecEncodeImage(avifCodec * codec,
// Tell libaom that all frames will be key frames.
cfg->kf_max_dist = 0;
}
if ((encoder->width || encoder->height) && (cfg->g_lag_in_frames > 1)) {
// libaom do not allow changing frame dimension if g_lag_in_frames > 1.
cfg->g_lag_in_frames = 1;
}
if (encoder->maxThreads > 1) {
cfg->g_threads = encoder->maxThreads;
}
Expand Down
5 changes: 5 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ if(AVIF_ENABLE_GTEST)
target_include_directories(avifalphapremtest PRIVATE ${GTEST_INCLUDE_DIRS})
add_test(NAME avifalphapremtest COMMAND avifalphapremtest)

add_executable(avifchangedimensiontest gtest/avifchangedimensiontest.cc)
target_link_libraries(avifchangedimensiontest aviftest_helpers ${GTEST_BOTH_LIBRARIES})
target_include_directories(avifchangedimensiontest PRIVATE ${GTEST_INCLUDE_DIRS})
add_test(NAME avifchangedimensiontest COMMAND avifchangedimensiontest)

add_executable(avifchangesettingtest gtest/avifchangesettingtest.cc)
target_link_libraries(avifchangesettingtest aviftest_helpers ${GTEST_BOTH_LIBRARIES})
target_include_directories(avifchangesettingtest PRIVATE ${GTEST_INCLUDE_DIRS})
Expand Down
136 changes: 136 additions & 0 deletions tests/gtest/avifchangedimensiontest.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
// Copyright 2022 Yuan Tong. All rights reserved.
// SPDX-License-Identifier: BSD-2-Clause

#include <map>
#include <string>

#include "avif/avif.h"
#include "aviftest_helpers.h"
#include "gtest/gtest.h"

using testing::Bool;
using testing::Combine;
using testing::Values;

namespace libavif {
namespace {

class ChangeDimensionTest
: public testing::TestWithParam<std::tuple<
/*speed=*/int, /*depth=*/int, /*maxThreads*/int, /*tiling*/ bool, /*end_usage=*/std::string,
/*tune=*/std::string, /*denoise=*/bool>> {};

TEST_P(ChangeDimensionTest, EncodeDecode) {
if (avifCodecName(AVIF_CODEC_CHOICE_AOM, AVIF_CODEC_FLAG_CAN_ENCODE) ==
nullptr) {
GTEST_SKIP() << "Codec unavailable, skip test.";
}

const int speed = std::get<0>(GetParam());
const int depth = std::get<1>(GetParam());
const int maxThreads = std::get<2>(GetParam());
const bool tiling = std::get<3>(GetParam());
const std::string end_usage = std::get<4>(GetParam());
const std::string tune = std::get<5>(GetParam());
const bool denoise = std::get<6>(GetParam());

int size_small = 64;
int size_display = 128;
if (maxThreads > 1) {
size_small = 512;
size_display = 768;
}

testutil::AvifImagePtr first = testutil::CreateImage(
size_small, size_small, depth, AVIF_PIXEL_FORMAT_YUV420, AVIF_PLANES_YUV,
AVIF_RANGE_FULL);
ASSERT_NE(first, nullptr);
testutil::FillImageGradient(first.get());

testutil::AvifImagePtr second = testutil::CreateImage(
size_display, size_display, depth, AVIF_PIXEL_FORMAT_YUV420,
AVIF_PLANES_YUV, AVIF_RANGE_FULL);
ASSERT_NE(second, nullptr);
testutil::FillImageGradient(second.get());

testutil::AvifRwData encodedAvif;

// Encode
{
testutil::AvifEncoderPtr encoder(avifEncoderCreate(), avifEncoderDestroy);
ASSERT_NE(encoder, nullptr);
encoder->codecChoice = AVIF_CODEC_CHOICE_AOM;
encoder->speed = speed;
encoder->maxThreads = maxThreads;
encoder->timescale = 1;
encoder->minQuantizer = 20;
encoder->maxQuantizer = 40;
encoder->tileRowsLog2 = (tiling ? 1 : 0);
encoder->width = size_display;
encoder->height = size_display;

avifEncoderSetCodecSpecificOption(encoder.get(), "end-usage",
end_usage.c_str());
if (end_usage == "q") {
avifEncoderSetCodecSpecificOption(encoder.get(), "cq-level", "30");
}
avifEncoderSetCodecSpecificOption(encoder.get(), "tune", tune.c_str());
if (denoise) {
avifEncoderSetCodecSpecificOption(encoder.get(), "denoise-noise-level",
"25");
}

ASSERT_EQ(avifEncoderAddImage(encoder.get(), first.get(), 1, 0),
AVIF_RESULT_OK)
<< encoder->diag.error;

ASSERT_EQ(avifEncoderAddImage(encoder.get(), second.get(), 1, 0),
AVIF_RESULT_OK)
<< encoder->diag.error;

ASSERT_EQ(avifEncoderFinish(encoder.get(), &encodedAvif), AVIF_RESULT_OK)
<< encoder->diag.error;
}

// Decode
{
testutil::AvifDecoderPtr decoder(avifDecoderCreate(), avifDecoderDestroy);
ASSERT_NE(decoder, nullptr);

avifDecoderSetIOMemory(decoder.get(), encodedAvif.data, encodedAvif.size);
ASSERT_EQ(avifDecoderParse(decoder.get()), AVIF_RESULT_OK)
<< decoder->diag.error;
ASSERT_EQ(avifDecoderNextImage(decoder.get()), AVIF_RESULT_OK)
<< decoder->diag.error;
// libavif scales frames automatically.
ASSERT_EQ(decoder->image->width, size_display);
ASSERT_EQ(decoder->image->height, size_display);
ASSERT_EQ(avifDecoderNextImage(decoder.get()), AVIF_RESULT_OK)
<< decoder->diag.error;
ASSERT_EQ(decoder->image->width, size_display);
ASSERT_EQ(decoder->image->height, size_display);
}
}

INSTANTIATE_TEST_SUITE_P(
AOM, ChangeDimensionTest,
Combine(/*speed=*/Values(6, 10), // Test both GOOD_QUALITY and REALTIME
/*depth=*/Values(8, 10),
/*maxThreads*/Values(1),
/*tiling*/ Bool(),
/*end_usage=*/Values("q", "cbr"),
/*tune=*/Values("ssim", "psnr"),
/*denoise=*/Bool()));

INSTANTIATE_TEST_SUITE_P(
AOMMultiThread, ChangeDimensionTest,
Combine(/*speed=*/Values(6, 10), // Test both GOOD_QUALITY and REALTIME
/*depth=*/Values(8, 10),
/*maxThreads*/Values(8),
/*tiling*/ Values(true),
/*end_usage=*/Values("q"),
/*tune=*/Values("ssim"),
/*denoise=*/Values(true)));

} // namespace
} // namespace libavif
61 changes: 0 additions & 61 deletions tests/gtest/avifchangesettingtest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -154,66 +154,5 @@ TEST(ChangeSettingTest, UnchangeableSetting) {
AVIF_RESULT_CANNOT_CHANGE_SETTING);
}

TEST(ChangeSettingTest, ChangeDimension) {
if (avifCodecName(AVIF_CODEC_CHOICE_AOM, AVIF_CODEC_FLAG_CAN_ENCODE) ==
nullptr) {
GTEST_SKIP() << "Codec unavailable, skip test.";
}

const uint32_t size_small = 256;
const uint32_t size_display = 512;

testutil::AvifImagePtr first =
testutil::CreateImage(size_small, size_small, 8, AVIF_PIXEL_FORMAT_YUV420,
AVIF_PLANES_YUV, AVIF_RANGE_FULL);
ASSERT_NE(first, nullptr);
testutil::FillImageGradient(first.get());

testutil::AvifImagePtr second = testutil::CreateImage(
size_display, size_display, 8, AVIF_PIXEL_FORMAT_YUV420, AVIF_PLANES_YUV,
AVIF_RANGE_FULL);
ASSERT_NE(second, nullptr);
testutil::FillImageGradient(second.get());

testutil::AvifRwData encodedAvif;

// Encode
{
testutil::AvifEncoderPtr encoder(avifEncoderCreate(), avifEncoderDestroy);
ASSERT_NE(encoder, nullptr);
encoder->codecChoice = AVIF_CODEC_CHOICE_AOM;
encoder->speed = AVIF_SPEED_FASTEST;
encoder->timescale = 1;
encoder->minQuantizer = 63;
encoder->maxQuantizer = 63;
encoder->width = size_display;
encoder->height = size_display;

ASSERT_EQ(avifEncoderAddImage(encoder.get(), first.get(), 1, 0),
AVIF_RESULT_OK);

ASSERT_EQ(avifEncoderAddImage(encoder.get(), second.get(), 1, 0),
AVIF_RESULT_OK);

ASSERT_EQ(avifEncoderFinish(encoder.get(), &encodedAvif), AVIF_RESULT_OK);
}

// Decode
{
testutil::AvifDecoderPtr decoder(avifDecoderCreate(), avifDecoderDestroy);
ASSERT_NE(decoder, nullptr);

avifDecoderSetIOMemory(decoder.get(), encodedAvif.data, encodedAvif.size);
ASSERT_EQ(avifDecoderParse(decoder.get()), AVIF_RESULT_OK);
ASSERT_EQ(avifDecoderNextImage(decoder.get()), AVIF_RESULT_OK);
// libavif scales frame automatically.
ASSERT_EQ(decoder->image->width, size_display);
ASSERT_EQ(decoder->image->height, size_display);
ASSERT_EQ(avifDecoderNextImage(decoder.get()), AVIF_RESULT_OK);
ASSERT_EQ(decoder->image->width, size_display);
ASSERT_EQ(decoder->image->height, size_display);
}
}

} // namespace
} // namespace libavif

0 comments on commit 3eeb8c1

Please sign in to comment.