1 // Copyright 2023 Google LLC
2 // SPDX-License-Identifier: BSD-2-Clause
3 
4 #include "avif/avif.h"
5 #include "aviftest_helpers.h"
6 #include "gtest/gtest.h"
7 
8 namespace avif {
9 namespace {
10 
11 // Used to pass the data folder path to the GoogleTest suites.
12 const char* data_path = nullptr;
13 
get_file_name(const char * file_name)14 std::string get_file_name(const char* file_name) {
15   return std::string(data_path) + file_name;
16 }
17 
TEST(AvifDecodeTest,OneShotDecodeFile)18 TEST(AvifDecodeTest, OneShotDecodeFile) {
19   if (!testutil::Av1DecoderAvailable()) {
20     GTEST_SKIP() << "AV1 Codec unavailable, skip test.";
21   }
22   const char* file_name = "sofa_grid1x5_420.avif";
23   DecoderPtr decoder(avifDecoderCreate());
24   ASSERT_NE(decoder, nullptr);
25   avifImage image;
26   ASSERT_EQ(avifDecoderReadFile(decoder.get(), &image,
27                                 get_file_name(file_name).c_str()),
28             AVIF_RESULT_OK);
29   EXPECT_EQ(image.width, 1024);
30   EXPECT_EQ(image.height, 770);
31   EXPECT_EQ(image.depth, 8);
32 
33   // Call avifDecoderReadFile with a different file but with the same decoder
34   // instance.
35   file_name = "white_1x1.avif";
36   ASSERT_EQ(avifDecoderReadFile(decoder.get(), &image,
37                                 get_file_name(file_name).c_str()),
38             AVIF_RESULT_OK);
39   EXPECT_EQ(image.width, 1);
40   EXPECT_EQ(image.height, 1);
41   EXPECT_EQ(image.depth, 8);
42 }
43 
TEST(AvifDecodeTest,OneShotDecodeMemory)44 TEST(AvifDecodeTest, OneShotDecodeMemory) {
45   if (!testutil::Av1DecoderAvailable()) {
46     GTEST_SKIP() << "AV1 Codec unavailable, skip test.";
47   }
48   const char* file_name = "sofa_grid1x5_420.avif";
49   auto file_data = testutil::read_file(get_file_name(file_name).c_str());
50   DecoderPtr decoder(avifDecoderCreate());
51   ASSERT_NE(decoder, nullptr);
52   avifImage image;
53   ASSERT_EQ(avifDecoderReadMemory(decoder.get(), &image, file_data.data(),
54                                   file_data.size()),
55             AVIF_RESULT_OK);
56   EXPECT_EQ(image.width, 1024);
57   EXPECT_EQ(image.height, 770);
58   EXPECT_EQ(image.depth, 8);
59 }
60 
io_read(struct avifIO * io,uint32_t flags,uint64_t offset,size_t size,avifROData * out)61 avifResult io_read(struct avifIO* io, uint32_t flags, uint64_t offset,
62                    size_t size, avifROData* out) {
63   avifROData* src = (avifROData*)io->data;
64   if (flags != 0 || offset > src->size) {
65     return AVIF_RESULT_IO_ERROR;
66   }
67   uint64_t available_size = src->size - offset;
68   if (size > available_size) {
69     size = static_cast<size_t>(available_size);
70   }
71   out->data = src->data + offset;
72   out->size = size;
73   return AVIF_RESULT_OK;
74 }
75 
TEST(AvifDecodeTest,OneShotDecodeCustomIO)76 TEST(AvifDecodeTest, OneShotDecodeCustomIO) {
77   if (!testutil::Av1DecoderAvailable()) {
78     GTEST_SKIP() << "AV1 Codec unavailable, skip test.";
79   }
80   const char* file_name = "sofa_grid1x5_420.avif";
81   auto data = testutil::read_file(get_file_name(file_name).c_str());
82   avifROData ro_data = {.data = data.data(), .size = data.size()};
83   avifIO io = {.destroy = nullptr,
84                .read = io_read,
85                .sizeHint = data.size(),
86                .persistent = false,
87                .data = static_cast<void*>(&ro_data)};
88   DecoderPtr decoder(avifDecoderCreate());
89   ASSERT_NE(decoder, nullptr);
90   avifDecoderSetIO(decoder.get(), &io);
91   avifImage image;
92   ASSERT_EQ(avifDecoderRead(decoder.get(), &image), AVIF_RESULT_OK);
93   EXPECT_EQ(image.width, 1024);
94   EXPECT_EQ(image.height, 770);
95   EXPECT_EQ(image.depth, 8);
96 }
97 
TEST(AvifDecodeTest,NthImage)98 TEST(AvifDecodeTest, NthImage) {
99   if (!testutil::Av1DecoderAvailable()) {
100     GTEST_SKIP() << "AV1 Codec unavailable, skip test.";
101   }
102   const char* file_name = "colors-animated-8bpc.avif";
103   DecoderPtr decoder(avifDecoderCreate());
104   ASSERT_NE(decoder, nullptr);
105   ASSERT_EQ(avifDecoderSetIOFile(decoder.get(),
106                                  (std::string(data_path) + file_name).c_str()),
107             AVIF_RESULT_OK);
108   ASSERT_EQ(avifDecoderParse(decoder.get()), AVIF_RESULT_OK);
109   EXPECT_EQ(decoder->compressionFormat, COMPRESSION_FORMAT_AVIF);
110   EXPECT_EQ(decoder->imageCount, 5);
111   EXPECT_EQ(avifDecoderNthImage(decoder.get(), 3), AVIF_RESULT_OK);
112   EXPECT_EQ(avifDecoderNextImage(decoder.get()), AVIF_RESULT_OK);
113   EXPECT_NE(avifDecoderNextImage(decoder.get()), AVIF_RESULT_OK);
114   EXPECT_EQ(avifDecoderNthImage(decoder.get(), 1), AVIF_RESULT_OK);
115   EXPECT_EQ(avifDecoderNthImage(decoder.get(), 4), AVIF_RESULT_OK);
116   EXPECT_NE(avifDecoderNthImage(decoder.get(), 50), AVIF_RESULT_OK);
117   for (int i = 0; i < 5; ++i) {
118   }
119 }
120 
121 }  // namespace
122 }  // namespace avif
123 
main(int argc,char ** argv)124 int main(int argc, char** argv) {
125   ::testing::InitGoogleTest(&argc, argv);
126   if (argc != 2) {
127     std::cerr << "There must be exactly one argument containing the path to "
128                  "the test data folder"
129               << std::endl;
130     return 1;
131   }
132   avif::data_path = argv[1];
133   return RUN_ALL_TESTS();
134 }
135