1 /*
2 * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include <assert.h>
12
13 #include "./vpx_config.h"
14 #include "vpx_scale/yv12config.h"
15 #include "vpx_mem/vpx_mem.h"
16
17 #include "trace_conf.h"
18
19 /****************************************************************************
20 * Exports
21 ****************************************************************************/
22
23 /****************************************************************************
24 *
25 ****************************************************************************/
26 #define yv12_align_addr(addr, align) \
27 (void*)(((size_t)(addr) + ((align) - 1)) & (size_t)-(align))
28
29 int
vp8_yv12_de_alloc_frame_buffer(YV12_BUFFER_CONFIG * ybf)30 vp8_yv12_de_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf) {
31 if (ybf) {
32 // If libvpx is using frame buffer callbacks then buffer_alloc_sz must
33 // not be set.
34 if (ybf->buffer_alloc_sz > 0) {
35 vpx_free(ybf->buffer_alloc);
36 }
37
38 /* buffer_alloc isn't accessed by most functions. Rather y_buffer,
39 u_buffer and v_buffer point to buffer_alloc and are used. Clear out
40 all of this so that a freed pointer isn't inadvertently used */
41 vpx_memset(ybf, 0, sizeof(YV12_BUFFER_CONFIG));
42 } else {
43 return -1;
44 }
45
46 return 0;
47 }
48
vp8_yv12_realloc_frame_buffer(YV12_BUFFER_CONFIG * ybf,int width,int height,int border)49 int vp8_yv12_realloc_frame_buffer(YV12_BUFFER_CONFIG *ybf,
50 int width, int height, int border) {
51 if (ybf) {
52 int aligned_width = (width + 15) & ~15;
53 int aligned_height = (height + 15) & ~15;
54 int y_stride = ((aligned_width + 2 * border) + 31) & ~31;
55 int yplane_size = (aligned_height + 2 * border) * y_stride;
56 int uv_width = aligned_width >> 1;
57 int uv_height = aligned_height >> 1;
58 /** There is currently a bunch of code which assumes
59 * uv_stride == y_stride/2, so enforce this here. */
60 int uv_stride = y_stride >> 1;
61 int uvplane_size = (uv_height + border) * uv_stride;
62 const int frame_size = yplane_size + 2 * uvplane_size;
63
64 if (!ybf->buffer_alloc) {
65 ybf->buffer_alloc = (uint8_t *)vpx_memalign(32, frame_size);
66 ybf->buffer_alloc_sz = frame_size;
67 }
68
69 if (!ybf->buffer_alloc || ybf->buffer_alloc_sz < frame_size)
70 return -1;
71
72 /* Only support allocating buffers that have a border that's a multiple
73 * of 32. The border restriction is required to get 16-byte alignment of
74 * the start of the chroma rows without introducing an arbitrary gap
75 * between planes, which would break the semantics of things like
76 * vpx_img_set_rect(). */
77 if (border & 0x1f)
78 return -3;
79
80 ybf->y_crop_width = width;
81 ybf->y_crop_height = height;
82 ybf->y_width = aligned_width;
83 ybf->y_height = aligned_height;
84 ybf->y_stride = y_stride;
85
86 ybf->uv_width = uv_width;
87 ybf->uv_height = uv_height;
88 ybf->uv_stride = uv_stride;
89
90 ybf->alpha_width = 0;
91 ybf->alpha_height = 0;
92 ybf->alpha_stride = 0;
93
94 ybf->border = border;
95 ybf->frame_size = frame_size;
96
97 ybf->y_buffer = ybf->buffer_alloc + (border * y_stride) + border;
98 ybf->u_buffer = ybf->buffer_alloc + yplane_size + (border / 2 * uv_stride) + border / 2;
99 ybf->v_buffer = ybf->buffer_alloc + yplane_size + uvplane_size + (border / 2 * uv_stride) + border / 2;
100 ybf->alpha_buffer = NULL;
101
102 ybf->corrupted = 0; /* assume not currupted by errors */
103 return 0;
104 }
105 return -2;
106 }
107
vp8_yv12_alloc_frame_buffer(YV12_BUFFER_CONFIG * ybf,int width,int height,int border)108 int vp8_yv12_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf,
109 int width, int height, int border) {
110 if (ybf) {
111 vp8_yv12_de_alloc_frame_buffer(ybf);
112 return vp8_yv12_realloc_frame_buffer(ybf, width, height, border);
113 }
114 return -2;
115 }
116
117 #if CONFIG_VP9
118 // TODO(jkoleszar): Maybe replace this with struct vpx_image
119
vp9_free_frame_buffer(YV12_BUFFER_CONFIG * ybf)120 int vp9_free_frame_buffer(YV12_BUFFER_CONFIG *ybf) {
121 if (ybf) {
122 if (ybf->buffer_alloc_sz > 0) {
123 vpx_free(ybf->buffer_alloc);
124 }
125
126 /* buffer_alloc isn't accessed by most functions. Rather y_buffer,
127 u_buffer and v_buffer point to buffer_alloc and are used. Clear out
128 all of this so that a freed pointer isn't inadvertently used */
129 vpx_memset(ybf, 0, sizeof(YV12_BUFFER_CONFIG));
130 } else {
131 return -1;
132 }
133
134 return 0;
135 }
136
vp9_realloc_frame_buffer(YV12_BUFFER_CONFIG * ybf,int width,int height,int ss_x,int ss_y,int border,vpx_codec_frame_buffer_t * fb,vpx_get_frame_buffer_cb_fn_t cb,void * cb_priv)137 int vp9_realloc_frame_buffer(YV12_BUFFER_CONFIG *ybf,
138 int width, int height,
139 int ss_x, int ss_y, int border,
140 vpx_codec_frame_buffer_t *fb,
141 vpx_get_frame_buffer_cb_fn_t cb,
142 void *cb_priv) {
143 if (ybf) {
144 const int aligned_width = (width + 7) & ~7;
145 //int aligned_height = (height + 7) & ~7;
146 int aligned_height = (height + 31) & ~31;
147 int y_stride = ((aligned_width + 2 * border) + 31) & ~31;
148 int yplane_size = (aligned_height + 2 * border) * y_stride;
149
150 const int uv_width = aligned_width >> ss_x;
151 int uv_height = aligned_height >> ss_y;
152 int uv_stride = y_stride >> ss_x;
153 const int uv_border_w = border >> ss_x;
154 const int uv_border_h = border >> ss_y;
155 int uvplane_size = (uv_height + 2 * uv_border_h) * uv_stride;
156 #if CONFIG_ALPHA
157 const int alpha_width = aligned_width;
158 int alpha_height = aligned_height;
159 int alpha_stride = y_stride;
160 const int alpha_border_w = border;
161 const int alpha_border_h = border;
162 int alpha_plane_size = (alpha_height + 2 * alpha_border_h) *
163 alpha_stride;
164 int frame_size = yplane_size + 2 * uvplane_size +
165 alpha_plane_size;
166 #else
167 int frame_size = yplane_size + 2 * uvplane_size;
168 #endif
169 if (cb != NULL) {
170 const int align_addr_extra_size = 0; //31;
171 const size_t external_frame_size = frame_size + align_addr_extra_size;
172
173 assert(fb != NULL);
174
175 // Allocation to hold larger frame, or first allocation.
176 if (cb(cb_priv, external_frame_size, fb) < 0)
177 return -1;
178
179 if (fb->data == NULL || fb->size < external_frame_size)
180 return -1;
181
182 // This memset is needed for fixing valgrind error from C loop filter
183 // due to access uninitialized memory in frame border. It could be
184 // removed if border is totally removed.
185 //vpx_memset(fb->data, 0, fb->size);
186
187 ybf->buffer_alloc = (uint8_t *)yv12_align_addr(fb->data, 32);
188
189 // extra info from external buffer
190 ybf->fb_index = fb->fb_index;
191 if (fb->fb_stride > 0) {
192 if ((fb->fb_stride >= y_stride) && (fb->fb_height_stride >= aligned_height)) {
193 // re-calculate stride/size stuff
194 y_stride = fb->fb_stride;
195 // external height is 32-bit align, align here either
196 aligned_height = (aligned_height + 31) & ~31;
197 aligned_height = fb->fb_height_stride;
198
199 yplane_size = (aligned_height + 2 * border) * y_stride;
200
201 uv_stride = y_stride >> ss_x;
202 uv_height = aligned_height >> ss_y;
203 uvplane_size = (uv_height + 2 * uv_border_h) * uv_stride;
204 #if CONFIG_ALPHA
205 alpha_stride = y_stride;
206 alpha_height = aligned_height;
207 alpha_plane_size = (alpha_height + 2 * alpha_border_h) *
208 alpha_stride;
209 frame_size = yplane_size + 2 * uvplane_size +
210 alpha_plane_size;
211 #else
212 frame_size = yplane_size + 2 * uvplane_size;
213 #endif
214 } else {
215 LOGD("buffer stride get from external should not less than calculated!");
216 return -1;
217 }
218 }
219 } else if (frame_size > ybf->buffer_alloc_sz) {
220 // Allocation to hold larger frame, or first allocation.
221 if (ybf->buffer_alloc)
222 vpx_free(ybf->buffer_alloc);
223 ybf->buffer_alloc = (uint8_t *)vpx_memalign(32, frame_size);
224 if (!ybf->buffer_alloc)
225 return -1;
226
227 ybf->buffer_alloc_sz = frame_size;
228
229 // This memset is needed for fixing valgrind error from C loop filter
230 // due to access uninitialized memory in frame border. It could be
231 // removed if border is totally removed.
232 //vpx_memset(ybf->buffer_alloc, 0, ybf->buffer_alloc_sz);
233 }
234
235 /* Only support allocating buffers that have a border that's a multiple
236 * of 32. The border restriction is required to get 16-byte alignment of
237 * the start of the chroma rows without introducing an arbitrary gap
238 * between planes, which would break the semantics of things like
239 * vpx_img_set_rect(). */
240 if (border & 0x1f)
241 return -3;
242
243 ybf->y_crop_width = width;
244 ybf->y_crop_height = height;
245 ybf->y_width = aligned_width;
246 ybf->y_height = aligned_height;
247 ybf->y_stride = y_stride;
248
249 ybf->uv_crop_width = (width + ss_x) >> ss_x;
250 ybf->uv_crop_height = (height + ss_y) >> ss_y;
251 ybf->uv_width = uv_width;
252 ybf->uv_height = uv_height;
253 ybf->uv_stride = uv_stride;
254
255 ybf->border = border;
256 ybf->frame_size = frame_size;
257
258 ybf->y_buffer = ybf->buffer_alloc + (border * y_stride) + border;
259 ybf->v_buffer = ybf->buffer_alloc + yplane_size +
260 (uv_border_h * uv_stride) + uv_border_w;
261 ybf->u_buffer = ybf->buffer_alloc + yplane_size + uvplane_size +
262 (uv_border_h * uv_stride) + uv_border_w;
263
264 #if CONFIG_ALPHA
265 ybf->alpha_width = alpha_width;
266 ybf->alpha_height = alpha_height;
267 ybf->alpha_stride = alpha_stride;
268 ybf->alpha_buffer = ybf->buffer_alloc + yplane_size + 2 * uvplane_size +
269 (alpha_border_h * alpha_stride) + alpha_border_w;
270 #endif
271 ybf->corrupted = 0; /* assume not corrupted by errors */
272 return 0;
273 }
274 return -2;
275 }
276
vp9_alloc_frame_buffer(YV12_BUFFER_CONFIG * ybf,int width,int height,int ss_x,int ss_y,int border)277 int vp9_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf,
278 int width, int height,
279 int ss_x, int ss_y, int border) {
280 if (ybf) {
281 vp9_free_frame_buffer(ybf);
282 return vp9_realloc_frame_buffer(ybf, width, height, ss_x, ss_y, border,
283 NULL, NULL, NULL);
284 }
285 return -2;
286 }
287 #endif
288