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