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