xref: /aosp_15_r20/external/libgav1/src/frame_buffer.cc (revision 095378508e87ed692bf8dfeb34008b65b3735891)
1*09537850SAkhilesh Sanikop // Copyright 2020 The libgav1 Authors
2*09537850SAkhilesh Sanikop //
3*09537850SAkhilesh Sanikop // Licensed under the Apache License, Version 2.0 (the "License");
4*09537850SAkhilesh Sanikop // you may not use this file except in compliance with the License.
5*09537850SAkhilesh Sanikop // You may obtain a copy of the License at
6*09537850SAkhilesh Sanikop //
7*09537850SAkhilesh Sanikop //      http://www.apache.org/licenses/LICENSE-2.0
8*09537850SAkhilesh Sanikop //
9*09537850SAkhilesh Sanikop // Unless required by applicable law or agreed to in writing, software
10*09537850SAkhilesh Sanikop // distributed under the License is distributed on an "AS IS" BASIS,
11*09537850SAkhilesh Sanikop // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*09537850SAkhilesh Sanikop // See the License for the specific language governing permissions and
13*09537850SAkhilesh Sanikop // limitations under the License.
14*09537850SAkhilesh Sanikop 
15*09537850SAkhilesh Sanikop #include "src/gav1/frame_buffer.h"
16*09537850SAkhilesh Sanikop 
17*09537850SAkhilesh Sanikop #include <cstdint>
18*09537850SAkhilesh Sanikop 
19*09537850SAkhilesh Sanikop #include "src/frame_buffer_utils.h"
20*09537850SAkhilesh Sanikop #include "src/utils/common.h"
21*09537850SAkhilesh Sanikop 
22*09537850SAkhilesh Sanikop extern "C" {
23*09537850SAkhilesh Sanikop 
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)24*09537850SAkhilesh Sanikop Libgav1StatusCode Libgav1ComputeFrameBufferInfo(
25*09537850SAkhilesh Sanikop     int bitdepth, Libgav1ImageFormat image_format, int width, int height,
26*09537850SAkhilesh Sanikop     int left_border, int right_border, int top_border, int bottom_border,
27*09537850SAkhilesh Sanikop     int stride_alignment, Libgav1FrameBufferInfo* info) {
28*09537850SAkhilesh Sanikop   switch (bitdepth) {
29*09537850SAkhilesh Sanikop     case 8:
30*09537850SAkhilesh Sanikop #if LIBGAV1_MAX_BITDEPTH >= 10
31*09537850SAkhilesh Sanikop     case 10:
32*09537850SAkhilesh Sanikop #endif
33*09537850SAkhilesh Sanikop #if LIBGAV1_MAX_BITDEPTH == 12
34*09537850SAkhilesh Sanikop     case 12:
35*09537850SAkhilesh Sanikop #endif
36*09537850SAkhilesh Sanikop       break;
37*09537850SAkhilesh Sanikop     default:
38*09537850SAkhilesh Sanikop       return kLibgav1StatusInvalidArgument;
39*09537850SAkhilesh Sanikop   }
40*09537850SAkhilesh Sanikop   switch (image_format) {
41*09537850SAkhilesh Sanikop     case kLibgav1ImageFormatYuv420:
42*09537850SAkhilesh Sanikop     case kLibgav1ImageFormatYuv422:
43*09537850SAkhilesh Sanikop     case kLibgav1ImageFormatYuv444:
44*09537850SAkhilesh Sanikop     case kLibgav1ImageFormatMonochrome400:
45*09537850SAkhilesh Sanikop       break;
46*09537850SAkhilesh Sanikop     default:
47*09537850SAkhilesh Sanikop       return kLibgav1StatusInvalidArgument;
48*09537850SAkhilesh Sanikop   }
49*09537850SAkhilesh Sanikop   // All int arguments must be nonnegative. Borders must be a multiple of 2.
50*09537850SAkhilesh Sanikop   // |stride_alignment| must be a power of 2.
51*09537850SAkhilesh Sanikop   if ((width | height | left_border | right_border | top_border |
52*09537850SAkhilesh Sanikop        bottom_border | stride_alignment) < 0 ||
53*09537850SAkhilesh Sanikop       ((left_border | right_border | top_border | bottom_border) & 1) != 0 ||
54*09537850SAkhilesh Sanikop       (stride_alignment & (stride_alignment - 1)) != 0 || info == nullptr) {
55*09537850SAkhilesh Sanikop     return kLibgav1StatusInvalidArgument;
56*09537850SAkhilesh Sanikop   }
57*09537850SAkhilesh Sanikop 
58*09537850SAkhilesh Sanikop   bool is_monochrome;
59*09537850SAkhilesh Sanikop   int8_t subsampling_x;
60*09537850SAkhilesh Sanikop   int8_t subsampling_y;
61*09537850SAkhilesh Sanikop   libgav1::DecomposeImageFormat(image_format, &is_monochrome, &subsampling_x,
62*09537850SAkhilesh Sanikop                                 &subsampling_y);
63*09537850SAkhilesh Sanikop 
64*09537850SAkhilesh Sanikop   // Calculate y_stride (in bytes). It is padded to a multiple of
65*09537850SAkhilesh Sanikop   // |stride_alignment| bytes.
66*09537850SAkhilesh Sanikop   int y_stride = width + left_border + right_border;
67*09537850SAkhilesh Sanikop #if LIBGAV1_MAX_BITDEPTH >= 10
68*09537850SAkhilesh Sanikop   if (bitdepth > 8) y_stride *= sizeof(uint16_t);
69*09537850SAkhilesh Sanikop #endif
70*09537850SAkhilesh Sanikop   y_stride = libgav1::Align(y_stride, stride_alignment);
71*09537850SAkhilesh Sanikop   // Size of the Y buffer in bytes.
72*09537850SAkhilesh Sanikop   const uint64_t y_buffer_size =
73*09537850SAkhilesh Sanikop       (height + top_border + bottom_border) * static_cast<uint64_t>(y_stride) +
74*09537850SAkhilesh Sanikop       (stride_alignment - 1);
75*09537850SAkhilesh Sanikop 
76*09537850SAkhilesh Sanikop   const int uv_width =
77*09537850SAkhilesh Sanikop       is_monochrome ? 0 : libgav1::SubsampledValue(width, subsampling_x);
78*09537850SAkhilesh Sanikop   const int uv_height =
79*09537850SAkhilesh Sanikop       is_monochrome ? 0 : libgav1::SubsampledValue(height, subsampling_y);
80*09537850SAkhilesh Sanikop   const int uv_left_border = is_monochrome ? 0 : left_border >> subsampling_x;
81*09537850SAkhilesh Sanikop   const int uv_right_border = is_monochrome ? 0 : right_border >> subsampling_x;
82*09537850SAkhilesh Sanikop   const int uv_top_border = is_monochrome ? 0 : top_border >> subsampling_y;
83*09537850SAkhilesh Sanikop   const int uv_bottom_border =
84*09537850SAkhilesh Sanikop       is_monochrome ? 0 : bottom_border >> subsampling_y;
85*09537850SAkhilesh Sanikop 
86*09537850SAkhilesh Sanikop   // Calculate uv_stride (in bytes). It is padded to a multiple of
87*09537850SAkhilesh Sanikop   // |stride_alignment| bytes.
88*09537850SAkhilesh Sanikop   int uv_stride = uv_width + uv_left_border + uv_right_border;
89*09537850SAkhilesh Sanikop #if LIBGAV1_MAX_BITDEPTH >= 10
90*09537850SAkhilesh Sanikop   if (bitdepth > 8) uv_stride *= sizeof(uint16_t);
91*09537850SAkhilesh Sanikop #endif
92*09537850SAkhilesh Sanikop   uv_stride = libgav1::Align(uv_stride, stride_alignment);
93*09537850SAkhilesh Sanikop   // Size of the U or V buffer in bytes.
94*09537850SAkhilesh Sanikop   const uint64_t uv_buffer_size =
95*09537850SAkhilesh Sanikop       is_monochrome ? 0
96*09537850SAkhilesh Sanikop                     : (uv_height + uv_top_border + uv_bottom_border) *
97*09537850SAkhilesh Sanikop                               static_cast<uint64_t>(uv_stride) +
98*09537850SAkhilesh Sanikop                           (stride_alignment - 1);
99*09537850SAkhilesh Sanikop 
100*09537850SAkhilesh Sanikop   // Check if it is safe to cast y_buffer_size and uv_buffer_size to size_t.
101*09537850SAkhilesh Sanikop   if (y_buffer_size > SIZE_MAX || uv_buffer_size > SIZE_MAX) {
102*09537850SAkhilesh Sanikop     return kLibgav1StatusInvalidArgument;
103*09537850SAkhilesh Sanikop   }
104*09537850SAkhilesh Sanikop 
105*09537850SAkhilesh Sanikop   int left_border_bytes = left_border;
106*09537850SAkhilesh Sanikop   int uv_left_border_bytes = uv_left_border;
107*09537850SAkhilesh Sanikop #if LIBGAV1_MAX_BITDEPTH >= 10
108*09537850SAkhilesh Sanikop   if (bitdepth > 8) {
109*09537850SAkhilesh Sanikop     left_border_bytes *= sizeof(uint16_t);
110*09537850SAkhilesh Sanikop     uv_left_border_bytes *= sizeof(uint16_t);
111*09537850SAkhilesh Sanikop   }
112*09537850SAkhilesh Sanikop #endif
113*09537850SAkhilesh Sanikop 
114*09537850SAkhilesh Sanikop   info->y_stride = y_stride;
115*09537850SAkhilesh Sanikop   info->uv_stride = uv_stride;
116*09537850SAkhilesh Sanikop   info->y_buffer_size = static_cast<size_t>(y_buffer_size);
117*09537850SAkhilesh Sanikop   info->uv_buffer_size = static_cast<size_t>(uv_buffer_size);
118*09537850SAkhilesh Sanikop   info->y_plane_offset = top_border * y_stride + left_border_bytes;
119*09537850SAkhilesh Sanikop   info->uv_plane_offset = uv_top_border * uv_stride + uv_left_border_bytes;
120*09537850SAkhilesh Sanikop   info->stride_alignment = stride_alignment;
121*09537850SAkhilesh Sanikop   return kLibgav1StatusOk;
122*09537850SAkhilesh Sanikop }
123*09537850SAkhilesh Sanikop 
Libgav1SetFrameBuffer(const Libgav1FrameBufferInfo * info,uint8_t * y_buffer,uint8_t * u_buffer,uint8_t * v_buffer,void * buffer_private_data,Libgav1FrameBuffer * frame_buffer)124*09537850SAkhilesh Sanikop Libgav1StatusCode Libgav1SetFrameBuffer(const Libgav1FrameBufferInfo* info,
125*09537850SAkhilesh Sanikop                                         uint8_t* y_buffer, uint8_t* u_buffer,
126*09537850SAkhilesh Sanikop                                         uint8_t* v_buffer,
127*09537850SAkhilesh Sanikop                                         void* buffer_private_data,
128*09537850SAkhilesh Sanikop                                         Libgav1FrameBuffer* frame_buffer) {
129*09537850SAkhilesh Sanikop   if (info == nullptr ||
130*09537850SAkhilesh Sanikop       (info->uv_buffer_size == 0 &&
131*09537850SAkhilesh Sanikop        (u_buffer != nullptr || v_buffer != nullptr)) ||
132*09537850SAkhilesh Sanikop       frame_buffer == nullptr) {
133*09537850SAkhilesh Sanikop     return kLibgav1StatusInvalidArgument;
134*09537850SAkhilesh Sanikop   }
135*09537850SAkhilesh Sanikop   if (y_buffer == nullptr || (info->uv_buffer_size != 0 &&
136*09537850SAkhilesh Sanikop                               (u_buffer == nullptr || v_buffer == nullptr))) {
137*09537850SAkhilesh Sanikop     return kLibgav1StatusOutOfMemory;
138*09537850SAkhilesh Sanikop   }
139*09537850SAkhilesh Sanikop   frame_buffer->plane[0] = libgav1::AlignAddr(y_buffer + info->y_plane_offset,
140*09537850SAkhilesh Sanikop                                               info->stride_alignment);
141*09537850SAkhilesh Sanikop   frame_buffer->plane[1] = libgav1::AlignAddr(u_buffer + info->uv_plane_offset,
142*09537850SAkhilesh Sanikop                                               info->stride_alignment);
143*09537850SAkhilesh Sanikop   frame_buffer->plane[2] = libgav1::AlignAddr(v_buffer + info->uv_plane_offset,
144*09537850SAkhilesh Sanikop                                               info->stride_alignment);
145*09537850SAkhilesh Sanikop   frame_buffer->stride[0] = info->y_stride;
146*09537850SAkhilesh Sanikop   frame_buffer->stride[1] = frame_buffer->stride[2] = info->uv_stride;
147*09537850SAkhilesh Sanikop   frame_buffer->private_data = buffer_private_data;
148*09537850SAkhilesh Sanikop   return kLibgav1StatusOk;
149*09537850SAkhilesh Sanikop }
150*09537850SAkhilesh Sanikop 
151*09537850SAkhilesh Sanikop }  // extern "C"
152