xref: /aosp_15_r20/external/libgav1/tests/utils.cc (revision 095378508e87ed692bf8dfeb34008b65b3735891)
1 // Copyright 2020 The libgav1 Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "tests/utils.h"
16 
17 #include <cstddef>
18 #include <cstdint>
19 #include <cstdio>
20 #include <cstring>
21 #include <memory>
22 #include <string>
23 
24 #include "absl/strings/string_view.h"
25 #include "absl/time/time.h"
26 #include "gtest/gtest.h"
27 #include "src/dsp/dsp.h"
28 #include "src/gav1/decoder_buffer.h"
29 #include "src/utils/constants.h"
30 #include "tests/third_party/libvpx/md5_helper.h"
31 
32 namespace libgav1 {
33 namespace test_utils {
34 namespace {
35 
CloseFile(FILE * stream)36 int CloseFile(FILE* stream) { return fclose(stream); }
37 
ReadFileToString(absl::string_view file_name,std::string * const string)38 bool ReadFileToString(absl::string_view file_name, std::string* const string) {
39   using FilePtr = std::unique_ptr<FILE, decltype(&CloseFile)>;
40   FilePtr file(fopen(std::string(file_name).c_str(), "rb"), &CloseFile);
41   if (file == nullptr) return false;
42 
43   do {
44     int c = fgetc(file.get());
45     if (ferror(file.get()) != 0) return false;
46 
47     if (c != EOF) {
48       string->append(1, static_cast<char>(c));
49     } else {
50       break;
51     }
52   } while (true);
53 
54   return true;
55 }
56 
57 }  // namespace
58 
ResetDspTable(const int bitdepth)59 void ResetDspTable(const int bitdepth) {
60   dsp::Dsp* const dsp = dsp_internal::GetWritableDspTable(bitdepth);
61   ASSERT_NE(dsp, nullptr);
62   memset(dsp, 0, sizeof(dsp::Dsp));
63 }
64 
GetMd5Sum(const void * bytes,size_t size)65 std::string GetMd5Sum(const void* bytes, size_t size) {
66   libvpx_test::MD5 md5;
67   md5.Add(static_cast<const uint8_t*>(bytes), size);
68   return md5.Get();
69 }
70 
71 template <typename Pixel>
GetMd5Sum(const Pixel * block,int width,int height,int stride)72 std::string GetMd5Sum(const Pixel* block, int width, int height, int stride) {
73   libvpx_test::MD5 md5;
74   const Pixel* row = block;
75   for (int i = 0; i < height; ++i) {
76     md5.Add(reinterpret_cast<const uint8_t*>(row), width * sizeof(Pixel));
77     row += stride;
78   }
79   return md5.Get();
80 }
81 
82 template std::string GetMd5Sum(const int8_t* block, int width, int height,
83                                int stride);
84 template std::string GetMd5Sum(const int16_t* block, int width, int height,
85                                int stride);
86 
GetMd5Sum(const DecoderBuffer & buffer)87 std::string GetMd5Sum(const DecoderBuffer& buffer) {
88   libvpx_test::MD5 md5;
89   const size_t pixel_size =
90       (buffer.bitdepth == 8) ? sizeof(uint8_t) : sizeof(uint16_t);
91   for (int plane = kPlaneY; plane < buffer.NumPlanes(); ++plane) {
92     const int height = buffer.displayed_height[plane];
93     const size_t width = buffer.displayed_width[plane] * pixel_size;
94     const int stride = buffer.stride[plane];
95     const uint8_t* plane_buffer = buffer.plane[plane];
96     for (int row = 0; row < height; ++row) {
97       md5.Add(plane_buffer, width);
98       plane_buffer += stride;
99     }
100   }
101   return md5.Get();
102 }
103 
CheckMd5Digest(const char name[],const char function_name[],const char expected_digest[],const void * data,size_t size,absl::Duration elapsed_time)104 void CheckMd5Digest(const char name[], const char function_name[],
105                     const char expected_digest[], const void* data, size_t size,
106                     absl::Duration elapsed_time) {
107   const std::string digest = test_utils::GetMd5Sum(data, size);
108   printf("Mode %s[%31s]: %5d us     MD5: %s\n", name, function_name,
109          static_cast<int>(absl::ToInt64Microseconds(elapsed_time)),
110          digest.c_str());
111   EXPECT_STREQ(expected_digest, digest.c_str());
112 }
113 
114 template <typename Pixel>
CheckMd5Digest(const char name[],const char function_name[],const char expected_digest[],const Pixel * block,int width,int height,int stride,absl::Duration elapsed_time)115 void CheckMd5Digest(const char name[], const char function_name[],
116                     const char expected_digest[], const Pixel* block, int width,
117                     int height, int stride, absl::Duration elapsed_time) {
118   const std::string digest =
119       test_utils::GetMd5Sum(block, width, height, stride);
120   printf("Mode %s[%31s]: %5d us     MD5: %s\n", name, function_name,
121          static_cast<int>(absl::ToInt64Microseconds(elapsed_time)),
122          digest.c_str());
123   EXPECT_STREQ(expected_digest, digest.c_str());
124 }
125 
126 template void CheckMd5Digest(const char name[], const char function_name[],
127                              const char expected_digest[], const int8_t* block,
128                              int width, int height, int stride,
129                              absl::Duration elapsed_time);
130 template void CheckMd5Digest(const char name[], const char function_name[],
131                              const char expected_digest[], const int16_t* block,
132                              int width, int height, int stride,
133                              absl::Duration elapsed_time);
134 
CheckMd5Digest(const char name[],const char function_name[],const char expected_digest[],const char actual_digest[],absl::Duration elapsed_time)135 void CheckMd5Digest(const char name[], const char function_name[],
136                     const char expected_digest[], const char actual_digest[],
137                     absl::Duration elapsed_time) {
138   printf("Mode %s[%31s]: %5d us     MD5: %s\n", name, function_name,
139          static_cast<int>(absl::ToInt64Microseconds(elapsed_time)),
140          actual_digest);
141   EXPECT_STREQ(expected_digest, actual_digest);
142 }
143 
144 namespace {
145 
GetSourceDir()146 std::string GetSourceDir() {
147 #if defined(__ANDROID__)
148   // Test files must be manually supplied. This path is frequently
149   // available on development devices.
150   return std::string("/data/local/tmp/tests/data");
151 #elif defined(LIBGAV1_FLAGS_SRCDIR)
152   return std::string(LIBGAV1_FLAGS_SRCDIR) + "/tests/data";
153 #else
154   return std::string(".");
155 #endif  // defined(__ANDROID__)
156 }
157 
GetTempDir()158 std::string GetTempDir() {
159   const char* path = getenv("TMPDIR");
160   if (path == nullptr || path[0] == '\0') path = getenv("TEMP");
161   if (path != nullptr && path[0] != '\0') return std::string(path);
162 
163 #if defined(__ANDROID__)
164   return std::string("/data/local/tmp");
165 #elif defined(LIBGAV1_FLAGS_TMPDIR)
166   return std::string(LIBGAV1_FLAGS_TMPDIR);
167 #else
168   return std::string(".");
169 #endif  // defined(__ANDROID__)
170 }
171 
172 }  // namespace
173 
GetTestInputFilePath(absl::string_view file_name)174 std::string GetTestInputFilePath(absl::string_view file_name) {
175   const char* const path = getenv("LIBGAV1_TEST_DATA_PATH");
176   if (path != nullptr && path[0] != '\0') {
177     return std::string(path) + "/" + std::string(file_name);
178   }
179   return GetSourceDir() + "/" + std::string(file_name);
180 }
181 
GetTestOutputFilePath(absl::string_view file_name)182 std::string GetTestOutputFilePath(absl::string_view file_name) {
183   return GetTempDir() + "/" + std::string(file_name);
184 }
185 
GetTestData(absl::string_view file_name,const bool is_output_file,std::string * const output)186 void GetTestData(absl::string_view file_name, const bool is_output_file,
187                  std::string* const output) {
188   ASSERT_NE(output, nullptr);
189   const std::string absolute_file_path = is_output_file
190                                              ? GetTestOutputFilePath(file_name)
191                                              : GetTestInputFilePath(file_name);
192 
193   ASSERT_TRUE(ReadFileToString(absolute_file_path, output));
194 }
195 
196 }  // namespace test_utils
197 }  // namespace libgav1
198