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