1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/libvpx/vpx/src/vpx_image.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,279 @@ 1.4 +/* 1.5 + * Copyright (c) 2010 The WebM project authors. All Rights Reserved. 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license 1.8 + * that can be found in the LICENSE file in the root of the source 1.9 + * tree. An additional intellectual property rights grant can be found 1.10 + * in the file PATENTS. All contributing project authors may 1.11 + * be found in the AUTHORS file in the root of the source tree. 1.12 + */ 1.13 + 1.14 + 1.15 +#include <stdlib.h> 1.16 +#include <string.h> 1.17 +#include "vpx/vpx_image.h" 1.18 + 1.19 +#define ADDRESS_STORAGE_SIZE sizeof(size_t) 1.20 +/*returns an addr aligned to the byte boundary specified by align*/ 1.21 +#define align_addr(addr,align) (void*)(((size_t)(addr) + ((align) - 1)) & (size_t)-(align)) 1.22 + 1.23 +/* Memalign code is copied from vpx_mem.c */ 1.24 +static void *img_buf_memalign(size_t align, size_t size) { 1.25 + void *addr, 1.26 + * x = NULL; 1.27 + 1.28 + addr = malloc(size + align - 1 + ADDRESS_STORAGE_SIZE); 1.29 + 1.30 + if (addr) { 1.31 + x = align_addr((unsigned char *)addr + ADDRESS_STORAGE_SIZE, (int)align); 1.32 + /* save the actual malloc address */ 1.33 + ((size_t *)x)[-1] = (size_t)addr; 1.34 + } 1.35 + 1.36 + return x; 1.37 +} 1.38 + 1.39 +static void img_buf_free(void *memblk) { 1.40 + if (memblk) { 1.41 + void *addr = (void *)(((size_t *)memblk)[-1]); 1.42 + free(addr); 1.43 + } 1.44 +} 1.45 + 1.46 +static vpx_image_t *img_alloc_helper(vpx_image_t *img, 1.47 + vpx_img_fmt_t fmt, 1.48 + unsigned int d_w, 1.49 + unsigned int d_h, 1.50 + unsigned int buf_align, 1.51 + unsigned int stride_align, 1.52 + unsigned char *img_data) { 1.53 + 1.54 + unsigned int h, w, s, xcs, ycs, bps; 1.55 + int align; 1.56 + 1.57 + /* Treat align==0 like align==1 */ 1.58 + if (!buf_align) 1.59 + buf_align = 1; 1.60 + 1.61 + /* Validate alignment (must be power of 2) */ 1.62 + if (buf_align & (buf_align - 1)) 1.63 + goto fail; 1.64 + 1.65 + /* Treat align==0 like align==1 */ 1.66 + if (!stride_align) 1.67 + stride_align = 1; 1.68 + 1.69 + /* Validate alignment (must be power of 2) */ 1.70 + if (stride_align & (stride_align - 1)) 1.71 + goto fail; 1.72 + 1.73 + /* Get sample size for this format */ 1.74 + switch (fmt) { 1.75 + case VPX_IMG_FMT_RGB32: 1.76 + case VPX_IMG_FMT_RGB32_LE: 1.77 + case VPX_IMG_FMT_ARGB: 1.78 + case VPX_IMG_FMT_ARGB_LE: 1.79 + bps = 32; 1.80 + break; 1.81 + case VPX_IMG_FMT_RGB24: 1.82 + case VPX_IMG_FMT_BGR24: 1.83 + bps = 24; 1.84 + break; 1.85 + case VPX_IMG_FMT_RGB565: 1.86 + case VPX_IMG_FMT_RGB565_LE: 1.87 + case VPX_IMG_FMT_RGB555: 1.88 + case VPX_IMG_FMT_RGB555_LE: 1.89 + case VPX_IMG_FMT_UYVY: 1.90 + case VPX_IMG_FMT_YUY2: 1.91 + case VPX_IMG_FMT_YVYU: 1.92 + bps = 16; 1.93 + break; 1.94 + case VPX_IMG_FMT_I420: 1.95 + case VPX_IMG_FMT_YV12: 1.96 + case VPX_IMG_FMT_VPXI420: 1.97 + case VPX_IMG_FMT_VPXYV12: 1.98 + bps = 12; 1.99 + break; 1.100 + default: 1.101 + bps = 16; 1.102 + break; 1.103 + } 1.104 + 1.105 + /* Get chroma shift values for this format */ 1.106 + switch (fmt) { 1.107 + case VPX_IMG_FMT_I420: 1.108 + case VPX_IMG_FMT_YV12: 1.109 + case VPX_IMG_FMT_VPXI420: 1.110 + case VPX_IMG_FMT_VPXYV12: 1.111 + xcs = 1; 1.112 + break; 1.113 + default: 1.114 + xcs = 0; 1.115 + break; 1.116 + } 1.117 + 1.118 + switch (fmt) { 1.119 + case VPX_IMG_FMT_I420: 1.120 + case VPX_IMG_FMT_YV12: 1.121 + case VPX_IMG_FMT_VPXI420: 1.122 + case VPX_IMG_FMT_VPXYV12: 1.123 + ycs = 1; 1.124 + break; 1.125 + default: 1.126 + ycs = 0; 1.127 + break; 1.128 + } 1.129 + 1.130 + /* Calculate storage sizes given the chroma subsampling */ 1.131 + align = (1 << xcs) - 1; 1.132 + w = (d_w + align) & ~align; 1.133 + align = (1 << ycs) - 1; 1.134 + h = (d_h + align) & ~align; 1.135 + s = (fmt & VPX_IMG_FMT_PLANAR) ? w : bps * w / 8; 1.136 + s = (s + stride_align - 1) & ~(stride_align - 1); 1.137 + 1.138 + /* Allocate the new image */ 1.139 + if (!img) { 1.140 + img = (vpx_image_t *)calloc(1, sizeof(vpx_image_t)); 1.141 + 1.142 + if (!img) 1.143 + goto fail; 1.144 + 1.145 + img->self_allocd = 1; 1.146 + } else { 1.147 + memset(img, 0, sizeof(vpx_image_t)); 1.148 + } 1.149 + 1.150 + img->img_data = img_data; 1.151 + 1.152 + if (!img_data) { 1.153 + img->img_data = img_buf_memalign(buf_align, ((fmt & VPX_IMG_FMT_PLANAR) ? 1.154 + h * s * bps / 8 : h * s)); 1.155 + img->img_data_owner = 1; 1.156 + } 1.157 + 1.158 + if (!img->img_data) 1.159 + goto fail; 1.160 + 1.161 + img->fmt = fmt; 1.162 + img->w = w; 1.163 + img->h = h; 1.164 + img->x_chroma_shift = xcs; 1.165 + img->y_chroma_shift = ycs; 1.166 + img->bps = bps; 1.167 + 1.168 + /* Calculate strides */ 1.169 + img->stride[VPX_PLANE_Y] = img->stride[VPX_PLANE_ALPHA] = s; 1.170 + img->stride[VPX_PLANE_U] = img->stride[VPX_PLANE_V] = s >> xcs; 1.171 + 1.172 + /* Default viewport to entire image */ 1.173 + if (!vpx_img_set_rect(img, 0, 0, d_w, d_h)) 1.174 + return img; 1.175 + 1.176 +fail: 1.177 + vpx_img_free(img); 1.178 + return NULL; 1.179 +} 1.180 + 1.181 +vpx_image_t *vpx_img_alloc(vpx_image_t *img, 1.182 + vpx_img_fmt_t fmt, 1.183 + unsigned int d_w, 1.184 + unsigned int d_h, 1.185 + unsigned int align) { 1.186 + return img_alloc_helper(img, fmt, d_w, d_h, align, align, NULL); 1.187 +} 1.188 + 1.189 +vpx_image_t *vpx_img_wrap(vpx_image_t *img, 1.190 + vpx_img_fmt_t fmt, 1.191 + unsigned int d_w, 1.192 + unsigned int d_h, 1.193 + unsigned int stride_align, 1.194 + unsigned char *img_data) { 1.195 + /* By setting buf_align = 1, we don't change buffer alignment in this 1.196 + * function. */ 1.197 + return img_alloc_helper(img, fmt, d_w, d_h, 1, stride_align, img_data); 1.198 +} 1.199 + 1.200 +int vpx_img_set_rect(vpx_image_t *img, 1.201 + unsigned int x, 1.202 + unsigned int y, 1.203 + unsigned int w, 1.204 + unsigned int h) { 1.205 + unsigned char *data; 1.206 + 1.207 + if (x + w <= img->w && y + h <= img->h) { 1.208 + img->d_w = w; 1.209 + img->d_h = h; 1.210 + 1.211 + /* Calculate plane pointers */ 1.212 + if (!(img->fmt & VPX_IMG_FMT_PLANAR)) { 1.213 + img->planes[VPX_PLANE_PACKED] = 1.214 + img->img_data + x * img->bps / 8 + y * img->stride[VPX_PLANE_PACKED]; 1.215 + } else { 1.216 + data = img->img_data; 1.217 + 1.218 + if (img->fmt & VPX_IMG_FMT_HAS_ALPHA) { 1.219 + img->planes[VPX_PLANE_ALPHA] = 1.220 + data + x + y * img->stride[VPX_PLANE_ALPHA]; 1.221 + data += img->h * img->stride[VPX_PLANE_ALPHA]; 1.222 + } 1.223 + 1.224 + img->planes[VPX_PLANE_Y] = data + x + y * img->stride[VPX_PLANE_Y]; 1.225 + data += img->h * img->stride[VPX_PLANE_Y]; 1.226 + 1.227 + if (!(img->fmt & VPX_IMG_FMT_UV_FLIP)) { 1.228 + img->planes[VPX_PLANE_U] = data 1.229 + + (x >> img->x_chroma_shift) 1.230 + + (y >> img->y_chroma_shift) * img->stride[VPX_PLANE_U]; 1.231 + data += (img->h >> img->y_chroma_shift) * img->stride[VPX_PLANE_U]; 1.232 + img->planes[VPX_PLANE_V] = data 1.233 + + (x >> img->x_chroma_shift) 1.234 + + (y >> img->y_chroma_shift) * img->stride[VPX_PLANE_V]; 1.235 + } else { 1.236 + img->planes[VPX_PLANE_V] = data 1.237 + + (x >> img->x_chroma_shift) 1.238 + + (y >> img->y_chroma_shift) * img->stride[VPX_PLANE_V]; 1.239 + data += (img->h >> img->y_chroma_shift) * img->stride[VPX_PLANE_V]; 1.240 + img->planes[VPX_PLANE_U] = data 1.241 + + (x >> img->x_chroma_shift) 1.242 + + (y >> img->y_chroma_shift) * img->stride[VPX_PLANE_U]; 1.243 + } 1.244 + } 1.245 + 1.246 + return 0; 1.247 + } 1.248 + 1.249 + return -1; 1.250 +} 1.251 + 1.252 +void vpx_img_flip(vpx_image_t *img) { 1.253 + /* Note: In the calculation pointer adjustment calculation, we want the 1.254 + * rhs to be promoted to a signed type. Section 6.3.1.8 of the ISO C99 1.255 + * standard indicates that if the adjustment parameter is unsigned, the 1.256 + * stride parameter will be promoted to unsigned, causing errors when 1.257 + * the lhs is a larger type than the rhs. 1.258 + */ 1.259 + img->planes[VPX_PLANE_Y] += (signed)(img->d_h - 1) * img->stride[VPX_PLANE_Y]; 1.260 + img->stride[VPX_PLANE_Y] = -img->stride[VPX_PLANE_Y]; 1.261 + 1.262 + img->planes[VPX_PLANE_U] += (signed)((img->d_h >> img->y_chroma_shift) - 1) 1.263 + * img->stride[VPX_PLANE_U]; 1.264 + img->stride[VPX_PLANE_U] = -img->stride[VPX_PLANE_U]; 1.265 + 1.266 + img->planes[VPX_PLANE_V] += (signed)((img->d_h >> img->y_chroma_shift) - 1) 1.267 + * img->stride[VPX_PLANE_V]; 1.268 + img->stride[VPX_PLANE_V] = -img->stride[VPX_PLANE_V]; 1.269 + 1.270 + img->planes[VPX_PLANE_ALPHA] += (signed)(img->d_h - 1) * img->stride[VPX_PLANE_ALPHA]; 1.271 + img->stride[VPX_PLANE_ALPHA] = -img->stride[VPX_PLANE_ALPHA]; 1.272 +} 1.273 + 1.274 +void vpx_img_free(vpx_image_t *img) { 1.275 + if (img) { 1.276 + if (img->img_data && img->img_data_owner) 1.277 + img_buf_free(img->img_data); 1.278 + 1.279 + if (img->self_allocd) 1.280 + free(img); 1.281 + } 1.282 +}