xref: /aosp_15_r20/external/libgav1/src/yuv_buffer.h (revision 095378508e87ed692bf8dfeb34008b65b3735891)
1*09537850SAkhilesh Sanikop /*
2*09537850SAkhilesh Sanikop  * Copyright 2019 The libgav1 Authors
3*09537850SAkhilesh Sanikop  *
4*09537850SAkhilesh Sanikop  * Licensed under the Apache License, Version 2.0 (the "License");
5*09537850SAkhilesh Sanikop  * you may not use this file except in compliance with the License.
6*09537850SAkhilesh Sanikop  * You may obtain a copy of the License at
7*09537850SAkhilesh Sanikop  *
8*09537850SAkhilesh Sanikop  *      http://www.apache.org/licenses/LICENSE-2.0
9*09537850SAkhilesh Sanikop  *
10*09537850SAkhilesh Sanikop  * Unless required by applicable law or agreed to in writing, software
11*09537850SAkhilesh Sanikop  * distributed under the License is distributed on an "AS IS" BASIS,
12*09537850SAkhilesh Sanikop  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*09537850SAkhilesh Sanikop  * See the License for the specific language governing permissions and
14*09537850SAkhilesh Sanikop  * limitations under the License.
15*09537850SAkhilesh Sanikop  */
16*09537850SAkhilesh Sanikop 
17*09537850SAkhilesh Sanikop #ifndef LIBGAV1_SRC_YUV_BUFFER_H_
18*09537850SAkhilesh Sanikop #define LIBGAV1_SRC_YUV_BUFFER_H_
19*09537850SAkhilesh Sanikop 
20*09537850SAkhilesh Sanikop #include <cassert>
21*09537850SAkhilesh Sanikop #include <cstddef>
22*09537850SAkhilesh Sanikop #include <cstdint>
23*09537850SAkhilesh Sanikop #include <memory>
24*09537850SAkhilesh Sanikop #include <type_traits>
25*09537850SAkhilesh Sanikop 
26*09537850SAkhilesh Sanikop #include "src/gav1/frame_buffer.h"
27*09537850SAkhilesh Sanikop #include "src/utils/compiler_attributes.h"
28*09537850SAkhilesh Sanikop #include "src/utils/constants.h"
29*09537850SAkhilesh Sanikop 
30*09537850SAkhilesh Sanikop namespace libgav1 {
31*09537850SAkhilesh Sanikop 
32*09537850SAkhilesh Sanikop class YuvBuffer {
33*09537850SAkhilesh Sanikop  public:
34*09537850SAkhilesh Sanikop   // Allocates the buffer. Returns true on success. Returns false on failure.
35*09537850SAkhilesh Sanikop   //
36*09537850SAkhilesh Sanikop   // * |width| and |height| are the image dimensions in pixels.
37*09537850SAkhilesh Sanikop   // * |subsampling_x| and |subsampling_y| (either 0 or 1) specify the
38*09537850SAkhilesh Sanikop   //   subsampling of the width and height of the chroma planes, respectively.
39*09537850SAkhilesh Sanikop   // * |left_border|, |right_border|, |top_border|, and |bottom_border| are
40*09537850SAkhilesh Sanikop   //   the sizes (in pixels) of the borders on the left, right, top, and
41*09537850SAkhilesh Sanikop   //   bottom sides, respectively. The four border sizes must all be a
42*09537850SAkhilesh Sanikop   //   multiple of 2.
43*09537850SAkhilesh Sanikop   // * If |get_frame_buffer| is not null, it is invoked to allocate the memory.
44*09537850SAkhilesh Sanikop   //   If |get_frame_buffer| is null, YuvBuffer allocates the memory directly
45*09537850SAkhilesh Sanikop   //   and ignores the |callback_private_data| and |buffer_private_data|
46*09537850SAkhilesh Sanikop   //   parameters, which should be null.
47*09537850SAkhilesh Sanikop   //
48*09537850SAkhilesh Sanikop   // NOTE: The strides are a multiple of 16. Since the first row in each plane
49*09537850SAkhilesh Sanikop   // is 16-byte aligned, subsequent rows are also 16-byte aligned.
50*09537850SAkhilesh Sanikop   //
51*09537850SAkhilesh Sanikop   // Example: bitdepth=8 width=20 height=6 left/right/top/bottom_border=2. The
52*09537850SAkhilesh Sanikop   // diagram below shows how Realloc() allocates the data buffer for the Y
53*09537850SAkhilesh Sanikop   // plane.
54*09537850SAkhilesh Sanikop   //
55*09537850SAkhilesh Sanikop   //   16-byte aligned
56*09537850SAkhilesh Sanikop   //          |
57*09537850SAkhilesh Sanikop   //          v
58*09537850SAkhilesh Sanikop   //        ++++++++++++++++++++++++pppppppp
59*09537850SAkhilesh Sanikop   //        ++++++++++++++++++++++++pppppppp
60*09537850SAkhilesh Sanikop   //        ++01234567890123456789++pppppppp
61*09537850SAkhilesh Sanikop   //        ++11234567890123456789++pppppppp
62*09537850SAkhilesh Sanikop   //        ++21234567890123456789++pppppppp
63*09537850SAkhilesh Sanikop   //        ++31234567890123456789++pppppppp
64*09537850SAkhilesh Sanikop   //        ++41234567890123456789++pppppppp
65*09537850SAkhilesh Sanikop   //        ++51234567890123456789++pppppppp
66*09537850SAkhilesh Sanikop   //        ++++++++++++++++++++++++pppppppp
67*09537850SAkhilesh Sanikop   //        ++++++++++++++++++++++++pppppppp
68*09537850SAkhilesh Sanikop   //        |                              |
69*09537850SAkhilesh Sanikop   //        |<-- stride (multiple of 16) ->|
70*09537850SAkhilesh Sanikop   //
71*09537850SAkhilesh Sanikop   // The video frame has 6 rows of 20 pixels each. Each row is shown as the
72*09537850SAkhilesh Sanikop   // pattern r1234567890123456789, where |r| is 0, 1, 2, 3, 4, 5.
73*09537850SAkhilesh Sanikop   //
74*09537850SAkhilesh Sanikop   // Realloc() first adds a border of 2 pixels around the video frame. The
75*09537850SAkhilesh Sanikop   // border pixels are shown as '+'.
76*09537850SAkhilesh Sanikop   //
77*09537850SAkhilesh Sanikop   // Each row is then padded to a multiple of the default alignment in bytes,
78*09537850SAkhilesh Sanikop   // which is 16. The padding bytes are shown as lowercase 'p'. (Since
79*09537850SAkhilesh Sanikop   // |bitdepth| is 8 in this example, each pixel is one byte.) The padded size
80*09537850SAkhilesh Sanikop   // in bytes is the stride. In this example, the stride is 32 bytes.
81*09537850SAkhilesh Sanikop   //
82*09537850SAkhilesh Sanikop   // Finally, Realloc() aligns the first byte of frame data, which is the '0'
83*09537850SAkhilesh Sanikop   // pixel/byte in the upper left corner of the frame, to the default (16-byte)
84*09537850SAkhilesh Sanikop   // alignment boundary.
85*09537850SAkhilesh Sanikop   //
86*09537850SAkhilesh Sanikop   // TODO(wtc): Add a check for width and height limits to defend against
87*09537850SAkhilesh Sanikop   // invalid bitstreams.
88*09537850SAkhilesh Sanikop   bool Realloc(int bitdepth, bool is_monochrome, int width, int height,
89*09537850SAkhilesh Sanikop                int8_t subsampling_x, int8_t subsampling_y, int left_border,
90*09537850SAkhilesh Sanikop                int right_border, int top_border, int bottom_border,
91*09537850SAkhilesh Sanikop                GetFrameBufferCallback get_frame_buffer,
92*09537850SAkhilesh Sanikop                void* callback_private_data, void** buffer_private_data);
93*09537850SAkhilesh Sanikop 
bitdepth()94*09537850SAkhilesh Sanikop   int bitdepth() const { return bitdepth_; }
95*09537850SAkhilesh Sanikop 
is_monochrome()96*09537850SAkhilesh Sanikop   bool is_monochrome() const { return is_monochrome_; }
97*09537850SAkhilesh Sanikop 
subsampling_x()98*09537850SAkhilesh Sanikop   int8_t subsampling_x() const { return subsampling_x_; }
subsampling_y()99*09537850SAkhilesh Sanikop   int8_t subsampling_y() const { return subsampling_y_; }
100*09537850SAkhilesh Sanikop 
width(int plane)101*09537850SAkhilesh Sanikop   int width(int plane) const {
102*09537850SAkhilesh Sanikop     return (plane == kPlaneY) ? y_width_ : uv_width_;
103*09537850SAkhilesh Sanikop   }
height(int plane)104*09537850SAkhilesh Sanikop   int height(int plane) const {
105*09537850SAkhilesh Sanikop     return (plane == kPlaneY) ? y_height_ : uv_height_;
106*09537850SAkhilesh Sanikop   }
107*09537850SAkhilesh Sanikop 
108*09537850SAkhilesh Sanikop   // Returns border sizes in pixels.
left_border(int plane)109*09537850SAkhilesh Sanikop   int left_border(int plane) const { return left_border_[plane]; }
right_border(int plane)110*09537850SAkhilesh Sanikop   int right_border(int plane) const { return right_border_[plane]; }
top_border(int plane)111*09537850SAkhilesh Sanikop   int top_border(int plane) const { return top_border_[plane]; }
bottom_border(int plane)112*09537850SAkhilesh Sanikop   int bottom_border(int plane) const { return bottom_border_[plane]; }
113*09537850SAkhilesh Sanikop 
114*09537850SAkhilesh Sanikop   // Returns the alignment of frame buffer row in bytes.
alignment()115*09537850SAkhilesh Sanikop   int alignment() const { return kFrameBufferRowAlignment; }
116*09537850SAkhilesh Sanikop 
117*09537850SAkhilesh Sanikop   // Backup the current set of warnings and disable -Warray-bounds for the
118*09537850SAkhilesh Sanikop   // following three functions as the compiler cannot, in all cases, determine
119*09537850SAkhilesh Sanikop   // whether |plane| is within [0, kMaxPlanes), e.g., with a variable based for
120*09537850SAkhilesh Sanikop   // loop.
121*09537850SAkhilesh Sanikop #ifdef __GNUC__
122*09537850SAkhilesh Sanikop #pragma GCC diagnostic push
123*09537850SAkhilesh Sanikop #pragma GCC diagnostic ignored "-Warray-bounds"
124*09537850SAkhilesh Sanikop #endif
125*09537850SAkhilesh Sanikop   // Returns the data buffer for |plane|.
data(int plane)126*09537850SAkhilesh Sanikop   uint8_t* data(int plane) {
127*09537850SAkhilesh Sanikop     assert(plane >= 0);
128*09537850SAkhilesh Sanikop     assert(static_cast<size_t>(plane) < std::extent<decltype(buffer_)>::value);
129*09537850SAkhilesh Sanikop     return buffer_[plane];
130*09537850SAkhilesh Sanikop   }
data(int plane)131*09537850SAkhilesh Sanikop   const uint8_t* data(int plane) const {
132*09537850SAkhilesh Sanikop     assert(plane >= 0);
133*09537850SAkhilesh Sanikop     assert(static_cast<size_t>(plane) < std::extent<decltype(buffer_)>::value);
134*09537850SAkhilesh Sanikop     return buffer_[plane];
135*09537850SAkhilesh Sanikop   }
136*09537850SAkhilesh Sanikop 
137*09537850SAkhilesh Sanikop   // Returns the stride in bytes for |plane|.
stride(int plane)138*09537850SAkhilesh Sanikop   int stride(int plane) const {
139*09537850SAkhilesh Sanikop     assert(plane >= 0);
140*09537850SAkhilesh Sanikop     assert(static_cast<size_t>(plane) < std::extent<decltype(stride_)>::value);
141*09537850SAkhilesh Sanikop     return stride_[plane];
142*09537850SAkhilesh Sanikop   }
143*09537850SAkhilesh Sanikop   // Restore the previous set of compiler warnings.
144*09537850SAkhilesh Sanikop #ifdef __GNUC__
145*09537850SAkhilesh Sanikop #pragma GCC diagnostic pop
146*09537850SAkhilesh Sanikop #endif
147*09537850SAkhilesh Sanikop 
148*09537850SAkhilesh Sanikop  private:
149*09537850SAkhilesh Sanikop   static constexpr int kFrameBufferRowAlignment = 16;
150*09537850SAkhilesh Sanikop 
151*09537850SAkhilesh Sanikop #if LIBGAV1_MSAN
152*09537850SAkhilesh Sanikop   void InitializeFrameBorders();
153*09537850SAkhilesh Sanikop #endif
154*09537850SAkhilesh Sanikop 
155*09537850SAkhilesh Sanikop   int bitdepth_ = 0;
156*09537850SAkhilesh Sanikop   bool is_monochrome_ = false;
157*09537850SAkhilesh Sanikop 
158*09537850SAkhilesh Sanikop   // y_width_ and y_height_ are the |width| and |height| arguments passed to the
159*09537850SAkhilesh Sanikop   // Realloc() method.
160*09537850SAkhilesh Sanikop   //
161*09537850SAkhilesh Sanikop   // uv_width_ and uv_height_ are computed from y_width_ and y_height_ as
162*09537850SAkhilesh Sanikop   // follows:
163*09537850SAkhilesh Sanikop   //   uv_width_ = (y_width_ + subsampling_x_) >> subsampling_x_
164*09537850SAkhilesh Sanikop   //   uv_height_ = (y_height_ + subsampling_y_) >> subsampling_y_
165*09537850SAkhilesh Sanikop   int y_width_ = 0;
166*09537850SAkhilesh Sanikop   int uv_width_ = 0;
167*09537850SAkhilesh Sanikop   int y_height_ = 0;
168*09537850SAkhilesh Sanikop   int uv_height_ = 0;
169*09537850SAkhilesh Sanikop 
170*09537850SAkhilesh Sanikop   int left_border_[kMaxPlanes] = {};
171*09537850SAkhilesh Sanikop   int right_border_[kMaxPlanes] = {};
172*09537850SAkhilesh Sanikop   int top_border_[kMaxPlanes] = {};
173*09537850SAkhilesh Sanikop   int bottom_border_[kMaxPlanes] = {};
174*09537850SAkhilesh Sanikop 
175*09537850SAkhilesh Sanikop   int stride_[kMaxPlanes] = {};
176*09537850SAkhilesh Sanikop   uint8_t* buffer_[kMaxPlanes] = {};
177*09537850SAkhilesh Sanikop 
178*09537850SAkhilesh Sanikop   // buffer_alloc_ and buffer_alloc_size_ are only used if the
179*09537850SAkhilesh Sanikop   // get_frame_buffer callback is null and we allocate the buffer ourselves.
180*09537850SAkhilesh Sanikop   std::unique_ptr<uint8_t[]> buffer_alloc_;
181*09537850SAkhilesh Sanikop   size_t buffer_alloc_size_ = 0;
182*09537850SAkhilesh Sanikop 
183*09537850SAkhilesh Sanikop   int8_t subsampling_x_ = 0;  // 0 or 1.
184*09537850SAkhilesh Sanikop   int8_t subsampling_y_ = 0;  // 0 or 1.
185*09537850SAkhilesh Sanikop };
186*09537850SAkhilesh Sanikop 
187*09537850SAkhilesh Sanikop }  // namespace libgav1
188*09537850SAkhilesh Sanikop 
189*09537850SAkhilesh Sanikop #endif  // LIBGAV1_SRC_YUV_BUFFER_H_
190