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