xref: /aosp_15_r20/external/libgav1/src/buffer_pool_test.cc (revision 095378508e87ed692bf8dfeb34008b65b3735891)
1 // Copyright 2021 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 "src/buffer_pool.h"
16 
17 #include <climits>
18 #include <cstdint>
19 #include <memory>
20 #include <ostream>
21 #include <tuple>
22 #include <utility>
23 
24 #include "gtest/gtest.h"
25 #include "src/frame_buffer_utils.h"
26 #include "src/gav1/decoder_buffer.h"
27 #include "src/gav1/frame_buffer.h"
28 #include "src/internal_frame_buffer_list.h"
29 #include "src/utils/constants.h"
30 #include "src/utils/types.h"
31 #include "src/yuv_buffer.h"
32 
33 namespace libgav1 {
34 namespace {
35 
TEST(BufferPoolTest,RefCountedBufferPtr)36 TEST(BufferPoolTest, RefCountedBufferPtr) {
37   InternalFrameBufferList buffer_list;
38   BufferPool buffer_pool(OnInternalFrameBufferSizeChanged,
39                          GetInternalFrameBuffer, ReleaseInternalFrameBuffer,
40                          &buffer_list);
41   RefCountedBufferPtr buffer_ptr = buffer_pool.GetFreeBuffer();
42   EXPECT_NE(buffer_ptr, nullptr);
43   EXPECT_EQ(buffer_ptr.use_count(), 1);
44 
45   RefCountedBufferPtr buffer_ptr2 = buffer_ptr;
46   RefCountedBufferPtr buffer_ptr3 = buffer_ptr;
47   EXPECT_EQ(buffer_ptr.use_count(), 3);
48   EXPECT_EQ(buffer_ptr2.use_count(), 3);
49   EXPECT_EQ(buffer_ptr3.use_count(), 3);
50 
51   buffer_ptr2 = nullptr;
52   EXPECT_EQ(buffer_ptr.use_count(), 2);
53   EXPECT_EQ(buffer_ptr2.use_count(), 0);
54   EXPECT_EQ(buffer_ptr3.use_count(), 2);
55 
56   RefCountedBufferPtr buffer_ptr4 = std::move(buffer_ptr);
57   EXPECT_EQ(buffer_ptr.use_count(), 0);
58   EXPECT_EQ(buffer_ptr2.use_count(), 0);
59   EXPECT_EQ(buffer_ptr3.use_count(), 2);
60   EXPECT_EQ(buffer_ptr4.use_count(), 2);
61 }
62 
TEST(RefCountedBufferTest,SetFrameDimensions)63 TEST(RefCountedBufferTest, SetFrameDimensions) {
64   InternalFrameBufferList buffer_list;
65   BufferPool buffer_pool(OnInternalFrameBufferSizeChanged,
66                          GetInternalFrameBuffer, ReleaseInternalFrameBuffer,
67                          &buffer_list);
68   RefCountedBufferPtr buffer_ptr = buffer_pool.GetFreeBuffer();
69   EXPECT_NE(buffer_ptr, nullptr);
70 
71   // Test the undocumented default values of rows4x4() and columns4x4(). (Not
72   // sure if this is a good idea.)
73   EXPECT_EQ(buffer_ptr->rows4x4(), 0);
74   EXPECT_EQ(buffer_ptr->columns4x4(), 0);
75 
76   // Test the side effects of SetFrameDimensions().
77   ObuFrameHeader frame_header = {};
78   frame_header.rows4x4 = 20;
79   frame_header.columns4x4 = 30;
80   EXPECT_TRUE(buffer_ptr->SetFrameDimensions(frame_header));
81   EXPECT_EQ(buffer_ptr->rows4x4(), 20);
82   EXPECT_EQ(buffer_ptr->columns4x4(), 30);
83 }
84 
TEST(RefCountedBuffertTest,WaitUntil)85 TEST(RefCountedBuffertTest, WaitUntil) {
86   InternalFrameBufferList buffer_list;
87   BufferPool buffer_pool(OnInternalFrameBufferSizeChanged,
88                          GetInternalFrameBuffer, ReleaseInternalFrameBuffer,
89                          &buffer_list);
90   RefCountedBufferPtr buffer_ptr = buffer_pool.GetFreeBuffer();
91   EXPECT_NE(buffer_ptr, nullptr);
92 
93   int progress_row_cache;
94   buffer_ptr->SetProgress(10);
95   EXPECT_TRUE(buffer_ptr->WaitUntil(5, &progress_row_cache));
96   EXPECT_EQ(progress_row_cache, 10);
97 
98   buffer_ptr->SetFrameState(kFrameStateDecoded);
99   EXPECT_TRUE(buffer_ptr->WaitUntil(500, &progress_row_cache));
100   EXPECT_EQ(progress_row_cache, INT_MAX);
101 
102   buffer_ptr->Abort();
103   EXPECT_FALSE(buffer_ptr->WaitUntil(50, &progress_row_cache));
104 }
105 
106 constexpr struct Params {
107   int width;
108   int height;
109   int8_t subsampling_x;
110   int8_t subsampling_y;
111   int border;
112 } kParams[] = {
113     {1920, 1080, 1, 1, 96},   //
114     {1920, 1080, 1, 1, 64},   //
115     {1920, 1080, 1, 1, 32},   //
116     {1920, 1080, 1, 1, 160},  //
117     {1920, 1080, 1, 0, 160},  //
118     {1920, 1080, 0, 0, 160},  //
119 };
120 
operator <<(std::ostream & os,const Params & param)121 std::ostream& operator<<(std::ostream& os, const Params& param) {
122   return os << param.width << "x" << param.height
123             << ", subsampling(x/y): " << static_cast<int>(param.subsampling_x)
124             << "/" << static_cast<int>(param.subsampling_y)
125             << ", border: " << param.border;
126 }
127 
128 class RefCountedBufferReallocTest
129     : public testing::TestWithParam<std::tuple<bool, Params>> {
130  protected:
131   const bool use_external_callbacks_ = std::get<0>(GetParam());
132   const Params& param_ = std::get<1>(GetParam());
133 };
134 
135 TEST_P(RefCountedBufferReallocTest, 8Bit) {
136   InternalFrameBufferList buffer_list;
137   FrameBufferSizeChangedCallback on_frame_buffer_size_changed = nullptr;
138   GetFrameBufferCallback get_frame_buffer = nullptr;
139   ReleaseFrameBufferCallback release_frame_buffer = nullptr;
140   void* callback_private_data = nullptr;
141   if (use_external_callbacks_) {
142     on_frame_buffer_size_changed = OnInternalFrameBufferSizeChanged;
143     get_frame_buffer = GetInternalFrameBuffer;
144     release_frame_buffer = ReleaseInternalFrameBuffer;
145     callback_private_data = &buffer_list;
146   }
147 
148   BufferPool buffer_pool(on_frame_buffer_size_changed, get_frame_buffer,
149                          release_frame_buffer, callback_private_data);
150 
151   RefCountedBufferPtr buffer_ptr = buffer_pool.GetFreeBuffer();
152   EXPECT_NE(buffer_ptr, nullptr);
153 
154   const Libgav1ImageFormat image_format = ComposeImageFormat(
155       /*is_monochrome=*/false, param_.subsampling_x, param_.subsampling_y);
156   EXPECT_TRUE(buffer_pool.OnFrameBufferSizeChanged(
157       /*bitdepth=*/8, image_format, param_.width, param_.height, param_.border,
158       param_.border, param_.border, param_.border));
159 
160   EXPECT_TRUE(buffer_ptr->Realloc(
161       /*bitdepth=*/8, /*is_monochrome=*/false, param_.width, param_.height,
162       param_.subsampling_x, param_.subsampling_y, param_.border, param_.border,
163       param_.border, param_.border));
164 
165   // The first row of each plane is aligned at 16-byte boundaries.
166   EXPECT_EQ(
167       reinterpret_cast<uintptr_t>(buffer_ptr->buffer()->data(kPlaneY)) % 16, 0);
168   EXPECT_EQ(
169       reinterpret_cast<uintptr_t>(buffer_ptr->buffer()->data(kPlaneU)) % 16, 0);
170   EXPECT_EQ(
171       reinterpret_cast<uintptr_t>(buffer_ptr->buffer()->data(kPlaneV)) % 16, 0);
172 
173   // Subsequent rows are aligned at 16-byte boundaries.
174   EXPECT_EQ(buffer_ptr->buffer()->stride(kPlaneY) % 16, 0);
175   EXPECT_EQ(buffer_ptr->buffer()->stride(kPlaneU) % 16, 0);
176   EXPECT_EQ(buffer_ptr->buffer()->stride(kPlaneV) % 16, 0);
177 
178   // Check the borders.
179   EXPECT_EQ(buffer_ptr->buffer()->left_border(kPlaneY), param_.border);
180   EXPECT_EQ(buffer_ptr->buffer()->right_border(kPlaneY), param_.border);
181   EXPECT_EQ(buffer_ptr->buffer()->top_border(kPlaneY), param_.border);
182   EXPECT_EQ(buffer_ptr->buffer()->bottom_border(kPlaneY), param_.border);
183   EXPECT_EQ(buffer_ptr->buffer()->left_border(kPlaneU),
184             param_.border >> param_.subsampling_x);
185   EXPECT_EQ(buffer_ptr->buffer()->right_border(kPlaneU),
186             param_.border >> param_.subsampling_x);
187   EXPECT_EQ(buffer_ptr->buffer()->top_border(kPlaneU),
188             param_.border >> param_.subsampling_y);
189   EXPECT_EQ(buffer_ptr->buffer()->bottom_border(kPlaneU),
190             param_.border >> param_.subsampling_y);
191   EXPECT_EQ(buffer_ptr->buffer()->left_border(kPlaneV),
192             param_.border >> param_.subsampling_x);
193   EXPECT_EQ(buffer_ptr->buffer()->right_border(kPlaneV),
194             param_.border >> param_.subsampling_x);
195   EXPECT_EQ(buffer_ptr->buffer()->top_border(kPlaneV),
196             param_.border >> param_.subsampling_y);
197   EXPECT_EQ(buffer_ptr->buffer()->bottom_border(kPlaneV),
198             param_.border >> param_.subsampling_y);
199 
200   // Write to the upper-left corner of the border.
201   uint8_t* y_buffer = buffer_ptr->buffer()->data(kPlaneY);
202   int y_stride = buffer_ptr->buffer()->stride(kPlaneY);
203   y_buffer[-buffer_ptr->buffer()->left_border(kPlaneY) -
204            buffer_ptr->buffer()->top_border(kPlaneY) * y_stride] = 0;
205   // Write to the lower-right corner of the border.
206   uint8_t* v_buffer = buffer_ptr->buffer()->data(kPlaneV);
207   int v_stride = buffer_ptr->buffer()->stride(kPlaneV);
208   v_buffer[(buffer_ptr->buffer()->height(kPlaneV) +
209             buffer_ptr->buffer()->bottom_border(kPlaneV) - 1) *
210                v_stride +
211            buffer_ptr->buffer()->width(kPlaneV) +
212            buffer_ptr->buffer()->right_border(kPlaneV) - 1] = 0;
213 }
214 
215 #if LIBGAV1_MAX_BITDEPTH >= 10
216 TEST_P(RefCountedBufferReallocTest, 10Bit) {
217   InternalFrameBufferList buffer_list;
218   FrameBufferSizeChangedCallback on_frame_buffer_size_changed = nullptr;
219   GetFrameBufferCallback get_frame_buffer = nullptr;
220   ReleaseFrameBufferCallback release_frame_buffer = nullptr;
221   void* callback_private_data = nullptr;
222   if (use_external_callbacks_) {
223     on_frame_buffer_size_changed = OnInternalFrameBufferSizeChanged;
224     get_frame_buffer = GetInternalFrameBuffer;
225     release_frame_buffer = ReleaseInternalFrameBuffer;
226     callback_private_data = &buffer_list;
227   }
228 
229   BufferPool buffer_pool(on_frame_buffer_size_changed, get_frame_buffer,
230                          release_frame_buffer, callback_private_data);
231 
232   RefCountedBufferPtr buffer_ptr = buffer_pool.GetFreeBuffer();
233   EXPECT_NE(buffer_ptr, nullptr);
234 
235   const Libgav1ImageFormat image_format = ComposeImageFormat(
236       /*is_monochrome=*/false, param_.subsampling_x, param_.subsampling_y);
237   EXPECT_TRUE(buffer_pool.OnFrameBufferSizeChanged(
238       /*bitdepth=*/8, image_format, param_.width, param_.height, param_.border,
239       param_.border, param_.border, param_.border));
240 
241   EXPECT_TRUE(buffer_ptr->Realloc(
242       /*bitdepth=*/10, /*is_monochrome=*/false, param_.width, param_.height,
243       param_.subsampling_x, param_.subsampling_y, param_.border, param_.border,
244       param_.border, param_.border));
245 
246   // The first row of each plane is aligned at 16-byte boundaries.
247   EXPECT_EQ(
248       reinterpret_cast<uintptr_t>(buffer_ptr->buffer()->data(kPlaneY)) % 16, 0);
249   EXPECT_EQ(
250       reinterpret_cast<uintptr_t>(buffer_ptr->buffer()->data(kPlaneU)) % 16, 0);
251   EXPECT_EQ(
252       reinterpret_cast<uintptr_t>(buffer_ptr->buffer()->data(kPlaneV)) % 16, 0);
253 
254   // Subsequent rows are aligned at 16-byte boundaries.
255   EXPECT_EQ(buffer_ptr->buffer()->stride(kPlaneY) % 16, 0);
256   EXPECT_EQ(buffer_ptr->buffer()->stride(kPlaneU) % 16, 0);
257   EXPECT_EQ(buffer_ptr->buffer()->stride(kPlaneV) % 16, 0);
258 
259   // Check the borders.
260   EXPECT_EQ(buffer_ptr->buffer()->left_border(kPlaneY), param_.border);
261   EXPECT_EQ(buffer_ptr->buffer()->right_border(kPlaneY), param_.border);
262   EXPECT_EQ(buffer_ptr->buffer()->top_border(kPlaneY), param_.border);
263   EXPECT_EQ(buffer_ptr->buffer()->bottom_border(kPlaneY), param_.border);
264   EXPECT_EQ(buffer_ptr->buffer()->left_border(kPlaneU),
265             param_.border >> param_.subsampling_x);
266   EXPECT_EQ(buffer_ptr->buffer()->right_border(kPlaneU),
267             param_.border >> param_.subsampling_x);
268   EXPECT_EQ(buffer_ptr->buffer()->top_border(kPlaneU),
269             param_.border >> param_.subsampling_y);
270   EXPECT_EQ(buffer_ptr->buffer()->bottom_border(kPlaneU),
271             param_.border >> param_.subsampling_y);
272   EXPECT_EQ(buffer_ptr->buffer()->left_border(kPlaneV),
273             param_.border >> param_.subsampling_x);
274   EXPECT_EQ(buffer_ptr->buffer()->right_border(kPlaneV),
275             param_.border >> param_.subsampling_x);
276   EXPECT_EQ(buffer_ptr->buffer()->top_border(kPlaneV),
277             param_.border >> param_.subsampling_y);
278   EXPECT_EQ(buffer_ptr->buffer()->bottom_border(kPlaneV),
279             param_.border >> param_.subsampling_y);
280 
281   // Write to the upper-left corner of the border.
282   auto* y_buffer =
283       reinterpret_cast<uint16_t*>(buffer_ptr->buffer()->data(kPlaneY));
284   int y_stride = buffer_ptr->buffer()->stride(kPlaneY) / sizeof(uint16_t);
285   y_buffer[-buffer_ptr->buffer()->left_border(kPlaneY) -
286            buffer_ptr->buffer()->top_border(kPlaneY) * y_stride] = 0;
287   // Write to the lower-right corner of the border.
288   auto* v_buffer =
289       reinterpret_cast<uint16_t*>(buffer_ptr->buffer()->data(kPlaneV));
290   int v_stride = buffer_ptr->buffer()->stride(kPlaneV) / sizeof(uint16_t);
291   v_buffer[(buffer_ptr->buffer()->height(kPlaneV) +
292             buffer_ptr->buffer()->bottom_border(kPlaneV) - 1) *
293                v_stride +
294            buffer_ptr->buffer()->width(kPlaneV) +
295            buffer_ptr->buffer()->right_border(kPlaneV) - 1] = 0;
296 }
297 #endif  // LIBGAV1_MAX_BITDEPTH >= 10
298 
299 INSTANTIATE_TEST_SUITE_P(
300     Default, RefCountedBufferReallocTest,
301     testing::Combine(testing::Bool(),  // use_external_callbacks
302                      testing::ValuesIn(kParams)));
303 
304 }  // namespace
305 }  // namespace libgav1
306