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 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 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 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 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 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 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