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