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