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
|
// Copyright 2020 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.
#include "src/gav1/frame_buffer.h"
#include <cstdint>
#include "src/frame_buffer_utils.h"
#include "src/utils/common.h"
extern "C" {
Libgav1StatusCode Libgav1ComputeFrameBufferInfo(
int bitdepth, Libgav1ImageFormat image_format, int width, int height,
int left_border, int right_border, int top_border, int bottom_border,
int stride_alignment, Libgav1FrameBufferInfo* info) {
switch (bitdepth) {
case 8:
#if LIBGAV1_MAX_BITDEPTH >= 10
case 10:
#endif
#if LIBGAV1_MAX_BITDEPTH == 12
case 12:
#endif
break;
default:
return kLibgav1StatusInvalidArgument;
}
switch (image_format) {
case kLibgav1ImageFormatYuv420:
case kLibgav1ImageFormatYuv422:
case kLibgav1ImageFormatYuv444:
case kLibgav1ImageFormatMonochrome400:
break;
default:
return kLibgav1StatusInvalidArgument;
}
// All int arguments must be nonnegative. Borders must be a multiple of 2.
// |stride_alignment| must be a power of 2.
if ((width | height | left_border | right_border | top_border |
bottom_border | stride_alignment) < 0 ||
((left_border | right_border | top_border | bottom_border) & 1) != 0 ||
(stride_alignment & (stride_alignment - 1)) != 0 || info == nullptr) {
return kLibgav1StatusInvalidArgument;
}
bool is_monochrome;
int8_t subsampling_x;
int8_t subsampling_y;
libgav1::DecomposeImageFormat(image_format, &is_monochrome, &subsampling_x,
&subsampling_y);
// Calculate y_stride (in bytes). It is padded to a multiple of
// |stride_alignment| bytes.
int y_stride = width + left_border + right_border;
#if LIBGAV1_MAX_BITDEPTH >= 10
if (bitdepth > 8) y_stride *= sizeof(uint16_t);
#endif
y_stride = libgav1::Align(y_stride, stride_alignment);
// Size of the Y buffer in bytes.
const uint64_t y_buffer_size =
(height + top_border + bottom_border) * static_cast<uint64_t>(y_stride) +
(stride_alignment - 1);
const int uv_width =
is_monochrome ? 0 : libgav1::SubsampledValue(width, subsampling_x);
const int uv_height =
is_monochrome ? 0 : libgav1::SubsampledValue(height, subsampling_y);
const int uv_left_border = is_monochrome ? 0 : left_border >> subsampling_x;
const int uv_right_border = is_monochrome ? 0 : right_border >> subsampling_x;
const int uv_top_border = is_monochrome ? 0 : top_border >> subsampling_y;
const int uv_bottom_border =
is_monochrome ? 0 : bottom_border >> subsampling_y;
// Calculate uv_stride (in bytes). It is padded to a multiple of
// |stride_alignment| bytes.
int uv_stride = uv_width + uv_left_border + uv_right_border;
#if LIBGAV1_MAX_BITDEPTH >= 10
if (bitdepth > 8) uv_stride *= sizeof(uint16_t);
#endif
uv_stride = libgav1::Align(uv_stride, stride_alignment);
// Size of the U or V buffer in bytes.
const uint64_t uv_buffer_size =
is_monochrome ? 0
: (uv_height + uv_top_border + uv_bottom_border) *
static_cast<uint64_t>(uv_stride) +
(stride_alignment - 1);
// Check if it is safe to cast y_buffer_size and uv_buffer_size to size_t.
if (y_buffer_size > SIZE_MAX || uv_buffer_size > SIZE_MAX) {
return kLibgav1StatusInvalidArgument;
}
int left_border_bytes = left_border;
int uv_left_border_bytes = uv_left_border;
#if LIBGAV1_MAX_BITDEPTH >= 10
if (bitdepth > 8) {
left_border_bytes *= sizeof(uint16_t);
uv_left_border_bytes *= sizeof(uint16_t);
}
#endif
info->y_stride = y_stride;
info->uv_stride = uv_stride;
info->y_buffer_size = static_cast<size_t>(y_buffer_size);
info->uv_buffer_size = static_cast<size_t>(uv_buffer_size);
info->y_plane_offset = top_border * y_stride + left_border_bytes;
info->uv_plane_offset = uv_top_border * uv_stride + uv_left_border_bytes;
info->stride_alignment = stride_alignment;
return kLibgav1StatusOk;
}
Libgav1StatusCode Libgav1SetFrameBuffer(const Libgav1FrameBufferInfo* info,
uint8_t* y_buffer, uint8_t* u_buffer,
uint8_t* v_buffer,
void* buffer_private_data,
Libgav1FrameBuffer* frame_buffer) {
if (info == nullptr ||
(info->uv_buffer_size == 0 &&
(u_buffer != nullptr || v_buffer != nullptr)) ||
frame_buffer == nullptr) {
return kLibgav1StatusInvalidArgument;
}
if (y_buffer == nullptr || (info->uv_buffer_size != 0 &&
(u_buffer == nullptr || v_buffer == nullptr))) {
return kLibgav1StatusOutOfMemory;
}
frame_buffer->plane[0] = libgav1::AlignAddr(y_buffer + info->y_plane_offset,
info->stride_alignment);
frame_buffer->plane[1] = libgav1::AlignAddr(u_buffer + info->uv_plane_offset,
info->stride_alignment);
frame_buffer->plane[2] = libgav1::AlignAddr(v_buffer + info->uv_plane_offset,
info->stride_alignment);
frame_buffer->stride[0] = info->y_stride;
frame_buffer->stride[1] = frame_buffer->stride[2] = info->uv_stride;
frame_buffer->private_data = buffer_private_data;
return kLibgav1StatusOk;
}
} // extern "C"
|