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