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 "./vpx_config.h" 12 #include "vpx_scale/yv12config.h" 13 #include "vpx_mem/vpx_mem.h" 14 15 /**************************************************************************** 16 * Exports 17 ****************************************************************************/ 18 19 /**************************************************************************** 20 * 21 ****************************************************************************/ 22 int 23 vp8_yv12_de_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf) { 24 if (ybf) { 25 vpx_free(ybf->buffer_alloc); 26 27 /* buffer_alloc isn't accessed by most functions. Rather y_buffer, 28 u_buffer and v_buffer point to buffer_alloc and are used. Clear out 29 all of this so that a freed pointer isn't inadvertently used */ 30 vpx_memset(ybf, 0, sizeof(YV12_BUFFER_CONFIG)); 31 } else { 32 return -1; 33 } 34 35 return 0; 36 } 37 38 int vp8_yv12_realloc_frame_buffer(YV12_BUFFER_CONFIG *ybf, 39 int width, int height, int border) { 40 if (ybf) { 41 int aligned_width = (width + 15) & ~15; 42 int aligned_height = (height + 15) & ~15; 43 int y_stride = ((aligned_width + 2 * border) + 31) & ~31; 44 int yplane_size = (aligned_height + 2 * border) * y_stride; 45 int uv_width = aligned_width >> 1; 46 int uv_height = aligned_height >> 1; 47 /** There is currently a bunch of code which assumes 48 * uv_stride == y_stride/2, so enforce this here. */ 49 int uv_stride = y_stride >> 1; 50 int uvplane_size = (uv_height + border) * uv_stride; 51 const int frame_size = yplane_size + 2 * uvplane_size; 52 53 if (!ybf->buffer_alloc) { 54 ybf->buffer_alloc = vpx_memalign(32, frame_size); 55 ybf->buffer_alloc_sz = frame_size; 56 } 57 58 if (!ybf->buffer_alloc || ybf->buffer_alloc_sz < frame_size) 59 return -1; 60 61 /* Only support allocating buffers that have a border that's a multiple 62 * of 32. The border restriction is required to get 16-byte alignment of 63 * the start of the chroma rows without introducing an arbitrary gap 64 * between planes, which would break the semantics of things like 65 * vpx_img_set_rect(). */ 66 if (border & 0x1f) 67 return -3; 68 69 ybf->y_crop_width = width; 70 ybf->y_crop_height = height; 71 ybf->y_width = aligned_width; 72 ybf->y_height = aligned_height; 73 ybf->y_stride = y_stride; 74 75 ybf->uv_width = uv_width; 76 ybf->uv_height = uv_height; 77 ybf->uv_stride = uv_stride; 78 79 ybf->alpha_width = 0; 80 ybf->alpha_height = 0; 81 ybf->alpha_stride = 0; 82 83 ybf->border = border; 84 ybf->frame_size = frame_size; 85 86 ybf->y_buffer = ybf->buffer_alloc + (border * y_stride) + border; 87 ybf->u_buffer = ybf->buffer_alloc + yplane_size + (border / 2 * uv_stride) + border / 2; 88 ybf->v_buffer = ybf->buffer_alloc + yplane_size + uvplane_size + (border / 2 * uv_stride) + border / 2; 89 ybf->alpha_buffer = NULL; 90 91 ybf->corrupted = 0; /* assume not currupted by errors */ 92 return 0; 93 } 94 return -2; 95 } 96 97 int vp8_yv12_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf, 98 int width, int height, int border) { 99 if (ybf) { 100 vp8_yv12_de_alloc_frame_buffer(ybf); 101 return vp8_yv12_realloc_frame_buffer(ybf, width, height, border); 102 } 103 return -2; 104 } 105 106 #if CONFIG_VP9 107 // TODO(jkoleszar): Maybe replace this with struct vpx_image 108 109 int vp9_free_frame_buffer(YV12_BUFFER_CONFIG *ybf) { 110 if (ybf) { 111 vpx_free(ybf->buffer_alloc); 112 113 /* buffer_alloc isn't accessed by most functions. Rather y_buffer, 114 u_buffer and v_buffer point to buffer_alloc and are used. Clear out 115 all of this so that a freed pointer isn't inadvertently used */ 116 vpx_memset(ybf, 0, sizeof(YV12_BUFFER_CONFIG)); 117 } else { 118 return -1; 119 } 120 121 return 0; 122 } 123 124 int vp9_realloc_frame_buffer(YV12_BUFFER_CONFIG *ybf, 125 int width, int height, 126 int ss_x, int ss_y, int border) { 127 if (ybf) { 128 const int aligned_width = (width + 7) & ~7; 129 const int aligned_height = (height + 7) & ~7; 130 const int y_stride = ((aligned_width + 2 * border) + 31) & ~31; 131 const int yplane_size = (aligned_height + 2 * border) * y_stride; 132 const int uv_width = aligned_width >> ss_x; 133 const int uv_height = aligned_height >> ss_y; 134 const int uv_stride = y_stride >> ss_x; 135 const int uv_border_w = border >> ss_x; 136 const int uv_border_h = border >> ss_y; 137 const int uvplane_size = (uv_height + 2 * uv_border_h) * uv_stride; 138 #if CONFIG_ALPHA 139 const int alpha_width = aligned_width; 140 const int alpha_height = aligned_height; 141 const int alpha_stride = y_stride; 142 const int alpha_border_w = border; 143 const int alpha_border_h = border; 144 const int alpha_plane_size = (alpha_height + 2 * alpha_border_h) * 145 alpha_stride; 146 const int frame_size = yplane_size + 2 * uvplane_size + 147 alpha_plane_size; 148 #else 149 const int frame_size = yplane_size + 2 * uvplane_size; 150 #endif 151 if (frame_size > ybf->buffer_alloc_sz) { 152 // Allocation to hold larger frame, or first allocation. 153 if (ybf->buffer_alloc) 154 vpx_free(ybf->buffer_alloc); 155 ybf->buffer_alloc = vpx_memalign(32, frame_size); 156 ybf->buffer_alloc_sz = frame_size; 157 } 158 159 if (!ybf->buffer_alloc || ybf->buffer_alloc_sz < frame_size) 160 return -1; 161 162 /* Only support allocating buffers that have a border that's a multiple 163 * of 32. The border restriction is required to get 16-byte alignment of 164 * the start of the chroma rows without introducing an arbitrary gap 165 * between planes, which would break the semantics of things like 166 * vpx_img_set_rect(). */ 167 if (border & 0x1f) 168 return -3; 169 170 ybf->y_crop_width = width; 171 ybf->y_crop_height = height; 172 ybf->y_width = aligned_width; 173 ybf->y_height = aligned_height; 174 ybf->y_stride = y_stride; 175 176 ybf->uv_crop_width = (width + ss_x) >> ss_x; 177 ybf->uv_crop_height = (height + ss_y) >> ss_y; 178 ybf->uv_width = uv_width; 179 ybf->uv_height = uv_height; 180 ybf->uv_stride = uv_stride; 181 182 ybf->border = border; 183 ybf->frame_size = frame_size; 184 185 ybf->y_buffer = ybf->buffer_alloc + (border * y_stride) + border; 186 ybf->u_buffer = ybf->buffer_alloc + yplane_size + 187 (uv_border_h * uv_stride) + uv_border_w; 188 ybf->v_buffer = ybf->buffer_alloc + yplane_size + uvplane_size + 189 (uv_border_h * uv_stride) + uv_border_w; 190 191 #if CONFIG_ALPHA 192 ybf->alpha_width = alpha_width; 193 ybf->alpha_height = alpha_height; 194 ybf->alpha_stride = alpha_stride; 195 ybf->alpha_buffer = ybf->buffer_alloc + yplane_size + 2 * uvplane_size + 196 (alpha_border_h * alpha_stride) + alpha_border_w; 197 #endif 198 ybf->corrupted = 0; /* assume not corrupted by errors */ 199 return 0; 200 } 201 return -2; 202 } 203 204 int vp9_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf, 205 int width, int height, 206 int ss_x, int ss_y, int border) { 207 if (ybf) { 208 vp9_free_frame_buffer(ybf); 209 return vp9_realloc_frame_buffer(ybf, width, height, ss_x, ss_y, border); 210 } 211 return -2; 212 } 213 #endif 214