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