// Copyright 2023 Google LLC // SPDX-License-Identifier: BSD-2-Clause #include "avif/avif.h" #include "aviftest_helpers.h" #include "gtest/gtest.h" namespace avif { namespace { // Used to pass the data folder path to the GoogleTest suites. const char* data_path = nullptr; std::string get_file_name(const char* file_name) { return std::string(data_path) + file_name; } TEST(AvifDecodeTest, OneShotDecodeFile) { if (!testutil::Av1DecoderAvailable()) { GTEST_SKIP() << "AV1 Codec unavailable, skip test."; } const char* file_name = "sofa_grid1x5_420.avif"; DecoderPtr decoder(avifDecoderCreate()); ASSERT_NE(decoder, nullptr); avifImage image; ASSERT_EQ(avifDecoderReadFile(decoder.get(), &image, get_file_name(file_name).c_str()), AVIF_RESULT_OK); EXPECT_EQ(image.width, 1024); EXPECT_EQ(image.height, 770); EXPECT_EQ(image.depth, 8); // Call avifDecoderReadFile with a different file but with the same decoder // instance. file_name = "white_1x1.avif"; ASSERT_EQ(avifDecoderReadFile(decoder.get(), &image, get_file_name(file_name).c_str()), AVIF_RESULT_OK); EXPECT_EQ(image.width, 1); EXPECT_EQ(image.height, 1); EXPECT_EQ(image.depth, 8); } TEST(AvifDecodeTest, OneShotDecodeMemory) { if (!testutil::Av1DecoderAvailable()) { GTEST_SKIP() << "AV1 Codec unavailable, skip test."; } const char* file_name = "sofa_grid1x5_420.avif"; auto file_data = testutil::read_file(get_file_name(file_name).c_str()); DecoderPtr decoder(avifDecoderCreate()); ASSERT_NE(decoder, nullptr); avifImage image; ASSERT_EQ(avifDecoderReadMemory(decoder.get(), &image, file_data.data(), file_data.size()), AVIF_RESULT_OK); EXPECT_EQ(image.width, 1024); EXPECT_EQ(image.height, 770); EXPECT_EQ(image.depth, 8); } avifResult io_read(struct avifIO* io, uint32_t flags, uint64_t offset, size_t size, avifROData* out) { avifROData* src = (avifROData*)io->data; if (flags != 0 || offset > src->size) { return AVIF_RESULT_IO_ERROR; } uint64_t available_size = src->size - offset; if (size > available_size) { size = static_cast(available_size); } out->data = src->data + offset; out->size = size; return AVIF_RESULT_OK; } TEST(AvifDecodeTest, OneShotDecodeCustomIO) { if (!testutil::Av1DecoderAvailable()) { GTEST_SKIP() << "AV1 Codec unavailable, skip test."; } const char* file_name = "sofa_grid1x5_420.avif"; auto data = testutil::read_file(get_file_name(file_name).c_str()); avifROData ro_data = {.data = data.data(), .size = data.size()}; avifIO io = {.destroy = nullptr, .read = io_read, .sizeHint = data.size(), .persistent = false, .data = static_cast(&ro_data)}; DecoderPtr decoder(avifDecoderCreate()); ASSERT_NE(decoder, nullptr); avifDecoderSetIO(decoder.get(), &io); avifImage image; ASSERT_EQ(avifDecoderRead(decoder.get(), &image), AVIF_RESULT_OK); EXPECT_EQ(image.width, 1024); EXPECT_EQ(image.height, 770); EXPECT_EQ(image.depth, 8); } TEST(AvifDecodeTest, NthImage) { if (!testutil::Av1DecoderAvailable()) { GTEST_SKIP() << "AV1 Codec unavailable, skip test."; } const char* file_name = "colors-animated-8bpc.avif"; DecoderPtr decoder(avifDecoderCreate()); ASSERT_NE(decoder, nullptr); ASSERT_EQ(avifDecoderSetIOFile(decoder.get(), (std::string(data_path) + file_name).c_str()), AVIF_RESULT_OK); ASSERT_EQ(avifDecoderParse(decoder.get()), AVIF_RESULT_OK); EXPECT_EQ(decoder->compressionFormat, COMPRESSION_FORMAT_AVIF); EXPECT_EQ(decoder->imageCount, 5); EXPECT_EQ(avifDecoderNthImage(decoder.get(), 3), AVIF_RESULT_OK); EXPECT_EQ(avifDecoderNextImage(decoder.get()), AVIF_RESULT_OK); EXPECT_NE(avifDecoderNextImage(decoder.get()), AVIF_RESULT_OK); EXPECT_EQ(avifDecoderNthImage(decoder.get(), 1), AVIF_RESULT_OK); EXPECT_EQ(avifDecoderNthImage(decoder.get(), 4), AVIF_RESULT_OK); EXPECT_NE(avifDecoderNthImage(decoder.get(), 50), AVIF_RESULT_OK); for (int i = 0; i < 5; ++i) { } } } // namespace } // namespace avif int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); if (argc != 2) { std::cerr << "There must be exactly one argument containing the path to " "the test data folder" << std::endl; return 1; } avif::data_path = argv[1]; return RUN_ALL_TESTS(); }