| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2010 The WebM project authors. All Rights Reserved. | 2 * Copyright (c) 2010 The WebM project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| 11 | 11 |
| 12 #include <stdlib.h> | 12 #include <stdlib.h> |
| 13 #include <string.h> | 13 #include <string.h> |
| 14 #include "vpx/vpx_image.h" | 14 #include "vpx/vpx_image.h" |
| 15 | 15 |
| 16 #define ADDRESS_STORAGE_SIZE sizeof(size_t) | 16 #define ADDRESS_STORAGE_SIZE sizeof(size_t) |
| 17 /*returns an addr aligned to the byte boundary specified by align*/ | 17 /*returns an addr aligned to the byte boundary specified by align*/ |
| 18 #define align_addr(addr,align) (void*)(((size_t)(addr) + ((align) - 1)) & (size_
t)-(align)) | 18 #define align_addr(addr,align) (void*)(((size_t)(addr) + ((align) - 1)) & (size_
t)-(align)) |
| 19 | 19 |
| 20 /* Memalign code is copied from vpx_mem.c */ | 20 /* Memalign code is copied from vpx_mem.c */ |
| 21 static void *img_buf_memalign(size_t align, size_t size) | 21 static void *img_buf_memalign(size_t align, size_t size) { |
| 22 { | 22 void *addr, |
| 23 void *addr, | 23 * x = NULL; |
| 24 * x = NULL; | |
| 25 | 24 |
| 26 addr = malloc(size + align - 1 + ADDRESS_STORAGE_SIZE); | 25 addr = malloc(size + align - 1 + ADDRESS_STORAGE_SIZE); |
| 27 | 26 |
| 28 if (addr) | 27 if (addr) { |
| 29 { | 28 x = align_addr((unsigned char *)addr + ADDRESS_STORAGE_SIZE, (int)align); |
| 30 x = align_addr((unsigned char *)addr + ADDRESS_STORAGE_SIZE, (int)align)
; | 29 /* save the actual malloc address */ |
| 31 /* save the actual malloc address */ | 30 ((size_t *)x)[-1] = (size_t)addr; |
| 32 ((size_t *)x)[-1] = (size_t)addr; | 31 } |
| 33 } | |
| 34 | 32 |
| 35 return x; | 33 return x; |
| 36 } | 34 } |
| 37 | 35 |
| 38 static void img_buf_free(void *memblk) | 36 static void img_buf_free(void *memblk) { |
| 39 { | 37 if (memblk) { |
| 40 if (memblk) | 38 void *addr = (void *)(((size_t *)memblk)[-1]); |
| 41 { | 39 free(addr); |
| 42 void *addr = (void *)(((size_t *)memblk)[-1]); | 40 } |
| 43 free(addr); | |
| 44 } | |
| 45 } | 41 } |
| 46 | 42 |
| 47 static vpx_image_t *img_alloc_helper(vpx_image_t *img, | 43 static vpx_image_t *img_alloc_helper(vpx_image_t *img, |
| 48 vpx_img_fmt_t fmt, | 44 vpx_img_fmt_t fmt, |
| 49 unsigned int d_w, | 45 unsigned int d_w, |
| 50 unsigned int d_h, | 46 unsigned int d_h, |
| 51 unsigned int buf_align, | 47 unsigned int buf_align, |
| 52 unsigned int stride_align, | 48 unsigned int stride_align, |
| 53 unsigned char *img_data) | 49 unsigned char *img_data) { |
| 54 { | |
| 55 | 50 |
| 56 unsigned int h, w, s, xcs, ycs, bps; | 51 unsigned int h, w, s, xcs, ycs, bps; |
| 57 int align; | 52 int align; |
| 58 | 53 |
| 59 /* Treat align==0 like align==1 */ | 54 /* Treat align==0 like align==1 */ |
| 60 if (!buf_align) | 55 if (!buf_align) |
| 61 buf_align = 1; | 56 buf_align = 1; |
| 62 | 57 |
| 63 /* Validate alignment (must be power of 2) */ | 58 /* Validate alignment (must be power of 2) */ |
| 64 if (buf_align & (buf_align - 1)) | 59 if (buf_align & (buf_align - 1)) |
| 65 goto fail; | 60 goto fail; |
| 66 | 61 |
| 67 /* Treat align==0 like align==1 */ | 62 /* Treat align==0 like align==1 */ |
| 68 if (!stride_align) | 63 if (!stride_align) |
| 69 stride_align = 1; | 64 stride_align = 1; |
| 70 | 65 |
| 71 /* Validate alignment (must be power of 2) */ | 66 /* Validate alignment (must be power of 2) */ |
| 72 if (stride_align & (stride_align - 1)) | 67 if (stride_align & (stride_align - 1)) |
| 73 goto fail; | 68 goto fail; |
| 74 | 69 |
| 75 /* Get sample size for this format */ | 70 /* Get sample size for this format */ |
| 76 switch (fmt) | 71 switch (fmt) { |
| 77 { | |
| 78 case VPX_IMG_FMT_RGB32: | 72 case VPX_IMG_FMT_RGB32: |
| 79 case VPX_IMG_FMT_RGB32_LE: | 73 case VPX_IMG_FMT_RGB32_LE: |
| 80 case VPX_IMG_FMT_ARGB: | 74 case VPX_IMG_FMT_ARGB: |
| 81 case VPX_IMG_FMT_ARGB_LE: | 75 case VPX_IMG_FMT_ARGB_LE: |
| 82 bps = 32; | 76 bps = 32; |
| 83 break; | 77 break; |
| 84 case VPX_IMG_FMT_RGB24: | 78 case VPX_IMG_FMT_RGB24: |
| 85 case VPX_IMG_FMT_BGR24: | 79 case VPX_IMG_FMT_BGR24: |
| 86 bps = 24; | 80 bps = 24; |
| 87 break; | 81 break; |
| 88 case VPX_IMG_FMT_RGB565: | 82 case VPX_IMG_FMT_RGB565: |
| 89 case VPX_IMG_FMT_RGB565_LE: | 83 case VPX_IMG_FMT_RGB565_LE: |
| 90 case VPX_IMG_FMT_RGB555: | 84 case VPX_IMG_FMT_RGB555: |
| 91 case VPX_IMG_FMT_RGB555_LE: | 85 case VPX_IMG_FMT_RGB555_LE: |
| 92 case VPX_IMG_FMT_UYVY: | 86 case VPX_IMG_FMT_UYVY: |
| 93 case VPX_IMG_FMT_YUY2: | 87 case VPX_IMG_FMT_YUY2: |
| 94 case VPX_IMG_FMT_YVYU: | 88 case VPX_IMG_FMT_YVYU: |
| 95 bps = 16; | 89 bps = 16; |
| 96 break; | 90 break; |
| 97 case VPX_IMG_FMT_I420: | 91 case VPX_IMG_FMT_I420: |
| 98 case VPX_IMG_FMT_YV12: | 92 case VPX_IMG_FMT_YV12: |
| 99 case VPX_IMG_FMT_VPXI420: | 93 case VPX_IMG_FMT_VPXI420: |
| 100 case VPX_IMG_FMT_VPXYV12: | 94 case VPX_IMG_FMT_VPXYV12: |
| 101 bps = 12; | 95 bps = 12; |
| 102 break; | 96 break; |
| 103 default: | 97 default: |
| 104 bps = 16; | 98 bps = 16; |
| 105 break; | 99 break; |
| 106 } | 100 } |
| 107 | 101 |
| 108 /* Get chroma shift values for this format */ | 102 /* Get chroma shift values for this format */ |
| 109 switch (fmt) | 103 switch (fmt) { |
| 110 { | |
| 111 case VPX_IMG_FMT_I420: | 104 case VPX_IMG_FMT_I420: |
| 112 case VPX_IMG_FMT_YV12: | 105 case VPX_IMG_FMT_YV12: |
| 113 case VPX_IMG_FMT_VPXI420: | 106 case VPX_IMG_FMT_VPXI420: |
| 114 case VPX_IMG_FMT_VPXYV12: | 107 case VPX_IMG_FMT_VPXYV12: |
| 115 xcs = 1; | 108 xcs = 1; |
| 116 break; | 109 break; |
| 117 default: | 110 default: |
| 118 xcs = 0; | 111 xcs = 0; |
| 119 break; | 112 break; |
| 120 } | 113 } |
| 121 | 114 |
| 122 switch (fmt) | 115 switch (fmt) { |
| 123 { | |
| 124 case VPX_IMG_FMT_I420: | 116 case VPX_IMG_FMT_I420: |
| 125 case VPX_IMG_FMT_YV12: | 117 case VPX_IMG_FMT_YV12: |
| 126 case VPX_IMG_FMT_VPXI420: | 118 case VPX_IMG_FMT_VPXI420: |
| 127 case VPX_IMG_FMT_VPXYV12: | 119 case VPX_IMG_FMT_VPXYV12: |
| 128 ycs = 1; | 120 ycs = 1; |
| 129 break; | 121 break; |
| 130 default: | 122 default: |
| 131 ycs = 0; | 123 ycs = 0; |
| 132 break; | 124 break; |
| 133 } | 125 } |
| 134 | 126 |
| 135 /* Calculate storage sizes given the chroma subsampling */ | 127 /* Calculate storage sizes given the chroma subsampling */ |
| 136 align = (1 << xcs) - 1; | 128 align = (1 << xcs) - 1; |
| 137 w = (d_w + align) & ~align; | 129 w = (d_w + align) & ~align; |
| 138 align = (1 << ycs) - 1; | 130 align = (1 << ycs) - 1; |
| 139 h = (d_h + align) & ~align; | 131 h = (d_h + align) & ~align; |
| 140 s = (fmt & VPX_IMG_FMT_PLANAR) ? w : bps * w / 8; | 132 s = (fmt & VPX_IMG_FMT_PLANAR) ? w : bps * w / 8; |
| 141 s = (s + stride_align - 1) & ~(stride_align - 1); | 133 s = (s + stride_align - 1) & ~(stride_align - 1); |
| 142 | 134 |
| 143 /* Allocate the new image */ | 135 /* Allocate the new image */ |
| 136 if (!img) { |
| 137 img = (vpx_image_t *)calloc(1, sizeof(vpx_image_t)); |
| 138 |
| 144 if (!img) | 139 if (!img) |
| 145 { | 140 goto fail; |
| 146 img = (vpx_image_t *)calloc(1, sizeof(vpx_image_t)); | |
| 147 | 141 |
| 148 if (!img) | 142 img->self_allocd = 1; |
| 149 goto fail; | 143 } else { |
| 144 memset(img, 0, sizeof(vpx_image_t)); |
| 145 } |
| 150 | 146 |
| 151 img->self_allocd = 1; | 147 img->img_data = img_data; |
| 152 } | |
| 153 else | |
| 154 { | |
| 155 memset(img, 0, sizeof(vpx_image_t)); | |
| 156 } | |
| 157 | 148 |
| 158 img->img_data = img_data; | 149 if (!img_data) { |
| 150 img->img_data = img_buf_memalign(buf_align, ((fmt & VPX_IMG_FMT_PLANAR) ? |
| 151 h * s * bps / 8 : h * s)); |
| 152 img->img_data_owner = 1; |
| 153 } |
| 159 | 154 |
| 160 if (!img_data) | 155 if (!img->img_data) |
| 161 { | 156 goto fail; |
| 162 img->img_data = img_buf_memalign(buf_align, ((fmt & VPX_IMG_FMT_PLANAR)? | |
| 163 h * s * bps / 8 : h * s)); | |
| 164 img->img_data_owner = 1; | |
| 165 } | |
| 166 | 157 |
| 167 if (!img->img_data) | 158 img->fmt = fmt; |
| 168 goto fail; | 159 img->w = w; |
| 160 img->h = h; |
| 161 img->x_chroma_shift = xcs; |
| 162 img->y_chroma_shift = ycs; |
| 163 img->bps = bps; |
| 169 | 164 |
| 170 img->fmt = fmt; | 165 /* Calculate strides */ |
| 171 img->w = w; | 166 img->stride[VPX_PLANE_Y] = img->stride[VPX_PLANE_ALPHA] = s; |
| 172 img->h = h; | 167 img->stride[VPX_PLANE_U] = img->stride[VPX_PLANE_V] = s >> xcs; |
| 173 img->x_chroma_shift = xcs; | |
| 174 img->y_chroma_shift = ycs; | |
| 175 img->bps = bps; | |
| 176 | 168 |
| 177 /* Calculate strides */ | 169 /* Default viewport to entire image */ |
| 178 img->stride[VPX_PLANE_Y] = img->stride[VPX_PLANE_ALPHA] = s; | 170 if (!vpx_img_set_rect(img, 0, 0, d_w, d_h)) |
| 179 img->stride[VPX_PLANE_U] = img->stride[VPX_PLANE_V] = s >> xcs; | 171 return img; |
| 180 | |
| 181 /* Default viewport to entire image */ | |
| 182 if (!vpx_img_set_rect(img, 0, 0, d_w, d_h)) | |
| 183 return img; | |
| 184 | 172 |
| 185 fail: | 173 fail: |
| 186 vpx_img_free(img); | 174 vpx_img_free(img); |
| 187 return NULL; | 175 return NULL; |
| 188 } | 176 } |
| 189 | 177 |
| 190 vpx_image_t *vpx_img_alloc(vpx_image_t *img, | 178 vpx_image_t *vpx_img_alloc(vpx_image_t *img, |
| 191 vpx_img_fmt_t fmt, | 179 vpx_img_fmt_t fmt, |
| 192 unsigned int d_w, | 180 unsigned int d_w, |
| 193 unsigned int d_h, | 181 unsigned int d_h, |
| 194 unsigned int align) | 182 unsigned int align) { |
| 195 { | 183 return img_alloc_helper(img, fmt, d_w, d_h, align, align, NULL); |
| 196 return img_alloc_helper(img, fmt, d_w, d_h, align, align, NULL); | |
| 197 } | 184 } |
| 198 | 185 |
| 199 vpx_image_t *vpx_img_wrap(vpx_image_t *img, | 186 vpx_image_t *vpx_img_wrap(vpx_image_t *img, |
| 200 vpx_img_fmt_t fmt, | 187 vpx_img_fmt_t fmt, |
| 201 unsigned int d_w, | 188 unsigned int d_w, |
| 202 unsigned int d_h, | 189 unsigned int d_h, |
| 203 unsigned int stride_align, | 190 unsigned int stride_align, |
| 204 unsigned char *img_data) | 191 unsigned char *img_data) { |
| 205 { | 192 /* By setting buf_align = 1, we don't change buffer alignment in this |
| 206 /* By setting buf_align = 1, we don't change buffer alignment in this | 193 * function. */ |
| 207 * function. */ | 194 return img_alloc_helper(img, fmt, d_w, d_h, 1, stride_align, img_data); |
| 208 return img_alloc_helper(img, fmt, d_w, d_h, 1, stride_align, img_data); | |
| 209 } | 195 } |
| 210 | 196 |
| 211 int vpx_img_set_rect(vpx_image_t *img, | 197 int vpx_img_set_rect(vpx_image_t *img, |
| 212 unsigned int x, | 198 unsigned int x, |
| 213 unsigned int y, | 199 unsigned int y, |
| 214 unsigned int w, | 200 unsigned int w, |
| 215 unsigned int h) | 201 unsigned int h) { |
| 216 { | 202 unsigned char *data; |
| 217 unsigned char *data; | |
| 218 | 203 |
| 219 if (x + w <= img->w && y + h <= img->h) | 204 if (x + w <= img->w && y + h <= img->h) { |
| 220 { | 205 img->d_w = w; |
| 221 img->d_w = w; | 206 img->d_h = h; |
| 222 img->d_h = h; | |
| 223 | 207 |
| 224 /* Calculate plane pointers */ | 208 /* Calculate plane pointers */ |
| 225 if (!(img->fmt & VPX_IMG_FMT_PLANAR)) | 209 if (!(img->fmt & VPX_IMG_FMT_PLANAR)) { |
| 226 { | 210 img->planes[VPX_PLANE_PACKED] = |
| 227 img->planes[VPX_PLANE_PACKED] = | 211 img->img_data + x * img->bps / 8 + y * img->stride[VPX_PLANE_PACKED]; |
| 228 img->img_data + x * img->bps / 8 + y * img->stride[VPX_PLANE_PAC
KED]; | 212 } else { |
| 229 } | 213 data = img->img_data; |
| 230 else | |
| 231 { | |
| 232 data = img->img_data; | |
| 233 | 214 |
| 234 if (img->fmt & VPX_IMG_FMT_HAS_ALPHA) | 215 if (img->fmt & VPX_IMG_FMT_HAS_ALPHA) { |
| 235 { | 216 img->planes[VPX_PLANE_ALPHA] = |
| 236 img->planes[VPX_PLANE_ALPHA] = | 217 data + x + y * img->stride[VPX_PLANE_ALPHA]; |
| 237 data + x + y * img->stride[VPX_PLANE_ALPHA]; | 218 data += img->h * img->stride[VPX_PLANE_ALPHA]; |
| 238 data += img->h * img->stride[VPX_PLANE_ALPHA]; | 219 } |
| 239 } | |
| 240 | 220 |
| 241 img->planes[VPX_PLANE_Y] = data + x + y * img->stride[VPX_PLANE_Y]; | 221 img->planes[VPX_PLANE_Y] = data + x + y * img->stride[VPX_PLANE_Y]; |
| 242 data += img->h * img->stride[VPX_PLANE_Y]; | 222 data += img->h * img->stride[VPX_PLANE_Y]; |
| 243 | 223 |
| 244 if (!(img->fmt & VPX_IMG_FMT_UV_FLIP)) | 224 if (!(img->fmt & VPX_IMG_FMT_UV_FLIP)) { |
| 245 { | 225 img->planes[VPX_PLANE_U] = data |
| 246 img->planes[VPX_PLANE_U] = data | 226 + (x >> img->x_chroma_shift) |
| 247 + (x >> img->x_chroma_shift) | 227 + (y >> img->y_chroma_shift) * img->stride[VP
X_PLANE_U]; |
| 248 + (y >> img->y_chroma_shift) * img->strid
e[VPX_PLANE_U]; | 228 data += (img->h >> img->y_chroma_shift) * img->stride[VPX_PLANE_U]; |
| 249 data += (img->h >> img->y_chroma_shift) * img->stride[VPX_PLANE_
U]; | 229 img->planes[VPX_PLANE_V] = data |
| 250 img->planes[VPX_PLANE_V] = data | 230 + (x >> img->x_chroma_shift) |
| 251 + (x >> img->x_chroma_shift) | 231 + (y >> img->y_chroma_shift) * img->stride[VP
X_PLANE_V]; |
| 252 + (y >> img->y_chroma_shift) * img->strid
e[VPX_PLANE_V]; | 232 } else { |
| 253 } | 233 img->planes[VPX_PLANE_V] = data |
| 254 else | 234 + (x >> img->x_chroma_shift) |
| 255 { | 235 + (y >> img->y_chroma_shift) * img->stride[VP
X_PLANE_V]; |
| 256 img->planes[VPX_PLANE_V] = data | 236 data += (img->h >> img->y_chroma_shift) * img->stride[VPX_PLANE_V]; |
| 257 + (x >> img->x_chroma_shift) | 237 img->planes[VPX_PLANE_U] = data |
| 258 + (y >> img->y_chroma_shift) * img->strid
e[VPX_PLANE_V]; | 238 + (x >> img->x_chroma_shift) |
| 259 data += (img->h >> img->y_chroma_shift) * img->stride[VPX_PLANE_
V]; | 239 + (y >> img->y_chroma_shift) * img->stride[VP
X_PLANE_U]; |
| 260 img->planes[VPX_PLANE_U] = data | 240 } |
| 261 + (x >> img->x_chroma_shift) | |
| 262 + (y >> img->y_chroma_shift) * img->strid
e[VPX_PLANE_U]; | |
| 263 } | |
| 264 } | |
| 265 | |
| 266 return 0; | |
| 267 } | 241 } |
| 268 | 242 |
| 269 return -1; | 243 return 0; |
| 244 } |
| 245 |
| 246 return -1; |
| 270 } | 247 } |
| 271 | 248 |
| 272 void vpx_img_flip(vpx_image_t *img) | 249 void vpx_img_flip(vpx_image_t *img) { |
| 273 { | 250 /* Note: In the calculation pointer adjustment calculation, we want the |
| 274 /* Note: In the calculation pointer adjustment calculation, we want the | 251 * rhs to be promoted to a signed type. Section 6.3.1.8 of the ISO C99 |
| 275 * rhs to be promoted to a signed type. Section 6.3.1.8 of the ISO C99 | 252 * standard indicates that if the adjustment parameter is unsigned, the |
| 276 * standard indicates that if the adjustment parameter is unsigned, the | 253 * stride parameter will be promoted to unsigned, causing errors when |
| 277 * stride parameter will be promoted to unsigned, causing errors when | 254 * the lhs is a larger type than the rhs. |
| 278 * the lhs is a larger type than the rhs. | 255 */ |
| 279 */ | 256 img->planes[VPX_PLANE_Y] += (signed)(img->d_h - 1) * img->stride[VPX_PLANE_Y]; |
| 280 img->planes[VPX_PLANE_Y] += (signed)(img->d_h - 1) * img->stride[VPX_PLANE_Y
]; | 257 img->stride[VPX_PLANE_Y] = -img->stride[VPX_PLANE_Y]; |
| 281 img->stride[VPX_PLANE_Y] = -img->stride[VPX_PLANE_Y]; | |
| 282 | 258 |
| 283 img->planes[VPX_PLANE_U] += (signed)((img->d_h >> img->y_chroma_shift) - 1) | 259 img->planes[VPX_PLANE_U] += (signed)((img->d_h >> img->y_chroma_shift) - 1) |
| 284 * img->stride[VPX_PLANE_U]; | 260 * img->stride[VPX_PLANE_U]; |
| 285 img->stride[VPX_PLANE_U] = -img->stride[VPX_PLANE_U]; | 261 img->stride[VPX_PLANE_U] = -img->stride[VPX_PLANE_U]; |
| 286 | 262 |
| 287 img->planes[VPX_PLANE_V] += (signed)((img->d_h >> img->y_chroma_shift) - 1) | 263 img->planes[VPX_PLANE_V] += (signed)((img->d_h >> img->y_chroma_shift) - 1) |
| 288 * img->stride[VPX_PLANE_V]; | 264 * img->stride[VPX_PLANE_V]; |
| 289 img->stride[VPX_PLANE_V] = -img->stride[VPX_PLANE_V]; | 265 img->stride[VPX_PLANE_V] = -img->stride[VPX_PLANE_V]; |
| 290 | 266 |
| 291 img->planes[VPX_PLANE_ALPHA] += (signed)(img->d_h - 1) * img->stride[VPX_PLA
NE_ALPHA]; | 267 img->planes[VPX_PLANE_ALPHA] += (signed)(img->d_h - 1) * img->stride[VPX_PLANE
_ALPHA]; |
| 292 img->stride[VPX_PLANE_ALPHA] = -img->stride[VPX_PLANE_ALPHA]; | 268 img->stride[VPX_PLANE_ALPHA] = -img->stride[VPX_PLANE_ALPHA]; |
| 293 } | 269 } |
| 294 | 270 |
| 295 void vpx_img_free(vpx_image_t *img) | 271 void vpx_img_free(vpx_image_t *img) { |
| 296 { | 272 if (img) { |
| 297 if (img) | 273 if (img->img_data && img->img_data_owner) |
| 298 { | 274 img_buf_free(img->img_data); |
| 299 if (img->img_data && img->img_data_owner) | |
| 300 img_buf_free(img->img_data); | |
| 301 | 275 |
| 302 if (img->self_allocd) | 276 if (img->self_allocd) |
| 303 free(img); | 277 free(img); |
| 304 } | 278 } |
| 305 } | 279 } |
| OLD | NEW |