1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/libvpx/vpx_scale/generic/vpx_scale.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,530 @@ 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 +/**************************************************************************** 1.16 + * 1.17 + * Module Title : scale.c 1.18 + * 1.19 + * Description : Image scaling functions. 1.20 + * 1.21 + ***************************************************************************/ 1.22 + 1.23 +/**************************************************************************** 1.24 +* Header Files 1.25 +****************************************************************************/ 1.26 +#include "./vpx_scale_rtcd.h" 1.27 +#include "vpx_mem/vpx_mem.h" 1.28 +#include "vpx_scale/yv12config.h" 1.29 + 1.30 +typedef struct { 1.31 + int expanded_frame_width; 1.32 + int expanded_frame_height; 1.33 + 1.34 + int HScale; 1.35 + int HRatio; 1.36 + int VScale; 1.37 + int VRatio; 1.38 + 1.39 + YV12_BUFFER_CONFIG *src_yuv_config; 1.40 + YV12_BUFFER_CONFIG *dst_yuv_config; 1.41 + 1.42 +} SCALE_VARS; 1.43 + 1.44 +/**************************************************************************** 1.45 + * 1.46 + * ROUTINE : scale1d_2t1_i 1.47 + * 1.48 + * INPUTS : const unsigned char *source : Pointer to data to be scaled. 1.49 + * int source_step : Number of pixels to step on in source. 1.50 + * unsigned int source_scale : Scale for source (UNUSED). 1.51 + * unsigned int source_length : Length of source (UNUSED). 1.52 + * unsigned char *dest : Pointer to output data array. 1.53 + * int dest_step : Number of pixels to step on in destination. 1.54 + * unsigned int dest_scale : Scale for destination (UNUSED). 1.55 + * unsigned int dest_length : Length of destination. 1.56 + * 1.57 + * OUTPUTS : None. 1.58 + * 1.59 + * RETURNS : void 1.60 + * 1.61 + * FUNCTION : Performs 2-to-1 interpolated scaling. 1.62 + * 1.63 + * SPECIAL NOTES : None. 1.64 + * 1.65 + ****************************************************************************/ 1.66 +static 1.67 +void scale1d_2t1_i 1.68 +( 1.69 + const unsigned char *source, 1.70 + int source_step, 1.71 + unsigned int source_scale, 1.72 + unsigned int source_length, 1.73 + unsigned char *dest, 1.74 + int dest_step, 1.75 + unsigned int dest_scale, 1.76 + unsigned int dest_length 1.77 +) { 1.78 + unsigned int i, j; 1.79 + unsigned int temp; 1.80 + int source_pitch = source_step; 1.81 + (void) source_length; 1.82 + (void) source_scale; 1.83 + (void) dest_scale; 1.84 + 1.85 + source_step *= 2; 1.86 + dest[0] = source[0]; 1.87 + 1.88 + for (i = dest_step, j = source_step; i < dest_length * dest_step; i += dest_step, j += source_step) { 1.89 + temp = 8; 1.90 + temp += 3 * source[j - source_pitch]; 1.91 + temp += 10 * source[j]; 1.92 + temp += 3 * source[j + source_pitch]; 1.93 + temp >>= 4; 1.94 + dest[i] = (char)(temp); 1.95 + } 1.96 +} 1.97 + 1.98 +/**************************************************************************** 1.99 + * 1.100 + * ROUTINE : scale1d_2t1_ps 1.101 + * 1.102 + * INPUTS : const unsigned char *source : Pointer to data to be scaled. 1.103 + * int source_step : Number of pixels to step on in source. 1.104 + * unsigned int source_scale : Scale for source (UNUSED). 1.105 + * unsigned int source_length : Length of source (UNUSED). 1.106 + * unsigned char *dest : Pointer to output data array. 1.107 + * int dest_step : Number of pixels to step on in destination. 1.108 + * unsigned int dest_scale : Scale for destination (UNUSED). 1.109 + * unsigned int dest_length : Length of destination. 1.110 + * 1.111 + * OUTPUTS : None. 1.112 + * 1.113 + * RETURNS : void 1.114 + * 1.115 + * FUNCTION : Performs 2-to-1 point subsampled scaling. 1.116 + * 1.117 + * SPECIAL NOTES : None. 1.118 + * 1.119 + ****************************************************************************/ 1.120 +static 1.121 +void scale1d_2t1_ps 1.122 +( 1.123 + const unsigned char *source, 1.124 + int source_step, 1.125 + unsigned int source_scale, 1.126 + unsigned int source_length, 1.127 + unsigned char *dest, 1.128 + int dest_step, 1.129 + unsigned int dest_scale, 1.130 + unsigned int dest_length 1.131 +) { 1.132 + unsigned int i, j; 1.133 + 1.134 + (void) source_length; 1.135 + (void) source_scale; 1.136 + (void) dest_scale; 1.137 + 1.138 + source_step *= 2; 1.139 + j = 0; 1.140 + 1.141 + for (i = 0; i < dest_length * dest_step; i += dest_step, j += source_step) 1.142 + dest[i] = source[j]; 1.143 +} 1.144 +/**************************************************************************** 1.145 + * 1.146 + * ROUTINE : scale1d_c 1.147 + * 1.148 + * INPUTS : const unsigned char *source : Pointer to data to be scaled. 1.149 + * int source_step : Number of pixels to step on in source. 1.150 + * unsigned int source_scale : Scale for source. 1.151 + * unsigned int source_length : Length of source (UNUSED). 1.152 + * unsigned char *dest : Pointer to output data array. 1.153 + * int dest_step : Number of pixels to step on in destination. 1.154 + * unsigned int dest_scale : Scale for destination. 1.155 + * unsigned int dest_length : Length of destination. 1.156 + * 1.157 + * OUTPUTS : None. 1.158 + * 1.159 + * RETURNS : void 1.160 + * 1.161 + * FUNCTION : Performs linear interpolation in one dimension. 1.162 + * 1.163 + * SPECIAL NOTES : None. 1.164 + * 1.165 + ****************************************************************************/ 1.166 +static 1.167 +void scale1d_c 1.168 +( 1.169 + const unsigned char *source, 1.170 + int source_step, 1.171 + unsigned int source_scale, 1.172 + unsigned int source_length, 1.173 + unsigned char *dest, 1.174 + int dest_step, 1.175 + unsigned int dest_scale, 1.176 + unsigned int dest_length 1.177 +) { 1.178 + unsigned int i; 1.179 + unsigned int round_value = dest_scale / 2; 1.180 + unsigned int left_modifier = dest_scale; 1.181 + unsigned int right_modifier = 0; 1.182 + unsigned char left_pixel = *source; 1.183 + unsigned char right_pixel = *(source + source_step); 1.184 + 1.185 + (void) source_length; 1.186 + 1.187 + /* These asserts are needed if there are boundary issues... */ 1.188 + /*assert ( dest_scale > source_scale );*/ 1.189 + /*assert ( (source_length-1) * dest_scale >= (dest_length-1) * source_scale );*/ 1.190 + 1.191 + for (i = 0; i < dest_length * dest_step; i += dest_step) { 1.192 + dest[i] = (char)((left_modifier * left_pixel + right_modifier * right_pixel + round_value) / dest_scale); 1.193 + 1.194 + right_modifier += source_scale; 1.195 + 1.196 + while (right_modifier > dest_scale) { 1.197 + right_modifier -= dest_scale; 1.198 + source += source_step; 1.199 + left_pixel = *source; 1.200 + right_pixel = *(source + source_step); 1.201 + } 1.202 + 1.203 + left_modifier = dest_scale - right_modifier; 1.204 + } 1.205 +} 1.206 + 1.207 +/**************************************************************************** 1.208 + * 1.209 + * ROUTINE : Scale2D 1.210 + * 1.211 + * INPUTS : const unsigned char *source : Pointer to data to be scaled. 1.212 + * int source_pitch : Stride of source image. 1.213 + * unsigned int source_width : Width of input image. 1.214 + * unsigned int source_height : Height of input image. 1.215 + * unsigned char *dest : Pointer to output data array. 1.216 + * int dest_pitch : Stride of destination image. 1.217 + * unsigned int dest_width : Width of destination image. 1.218 + * unsigned int dest_height : Height of destination image. 1.219 + * unsigned char *temp_area : Pointer to temp work area. 1.220 + * unsigned char temp_area_height : Height of temp work area. 1.221 + * unsigned int hscale : Horizontal scale factor numerator. 1.222 + * unsigned int hratio : Horizontal scale factor denominator. 1.223 + * unsigned int vscale : Vertical scale factor numerator. 1.224 + * unsigned int vratio : Vertical scale factor denominator. 1.225 + * unsigned int interlaced : Interlace flag. 1.226 + * 1.227 + * OUTPUTS : None. 1.228 + * 1.229 + * RETURNS : void 1.230 + * 1.231 + * FUNCTION : Performs 2-tap linear interpolation in two dimensions. 1.232 + * 1.233 + * SPECIAL NOTES : Expansion is performed one band at a time to help with 1.234 + * caching. 1.235 + * 1.236 + ****************************************************************************/ 1.237 +static 1.238 +void Scale2D 1.239 +( 1.240 + /*const*/ 1.241 + unsigned char *source, 1.242 + int source_pitch, 1.243 + unsigned int source_width, 1.244 + unsigned int source_height, 1.245 + unsigned char *dest, 1.246 + int dest_pitch, 1.247 + unsigned int dest_width, 1.248 + unsigned int dest_height, 1.249 + unsigned char *temp_area, 1.250 + unsigned char temp_area_height, 1.251 + unsigned int hscale, 1.252 + unsigned int hratio, 1.253 + unsigned int vscale, 1.254 + unsigned int vratio, 1.255 + unsigned int interlaced 1.256 +) { 1.257 + /*unsigned*/ 1.258 + int i, j, k; 1.259 + int bands; 1.260 + int dest_band_height; 1.261 + int source_band_height; 1.262 + 1.263 + typedef void (*Scale1D)(const unsigned char * source, int source_step, unsigned int source_scale, unsigned int source_length, 1.264 + unsigned char * dest, int dest_step, unsigned int dest_scale, unsigned int dest_length); 1.265 + 1.266 + Scale1D Scale1Dv = scale1d_c; 1.267 + Scale1D Scale1Dh = scale1d_c; 1.268 + 1.269 + void (*horiz_line_scale)(const unsigned char *, unsigned int, unsigned char *, unsigned int) = NULL; 1.270 + void (*vert_band_scale)(unsigned char *, unsigned int, unsigned char *, unsigned int, unsigned int) = NULL; 1.271 + 1.272 + int ratio_scalable = 1; 1.273 + int interpolation = 0; 1.274 + 1.275 + unsigned char *source_base; /* = (unsigned char *) ((source_pitch >= 0) ? source : (source + ((source_height-1) * source_pitch))); */ 1.276 + unsigned char *line_src; 1.277 + 1.278 + 1.279 + source_base = (unsigned char *)source; 1.280 + 1.281 + if (source_pitch < 0) { 1.282 + int offset; 1.283 + 1.284 + offset = (source_height - 1); 1.285 + offset *= source_pitch; 1.286 + 1.287 + source_base += offset; 1.288 + } 1.289 + 1.290 + /* find out the ratio for each direction */ 1.291 + switch (hratio * 10 / hscale) { 1.292 + case 8: 1.293 + /* 4-5 Scale in Width direction */ 1.294 + horiz_line_scale = vp8_horizontal_line_5_4_scale; 1.295 + break; 1.296 + case 6: 1.297 + /* 3-5 Scale in Width direction */ 1.298 + horiz_line_scale = vp8_horizontal_line_5_3_scale; 1.299 + break; 1.300 + case 5: 1.301 + /* 1-2 Scale in Width direction */ 1.302 + horiz_line_scale = vp8_horizontal_line_2_1_scale; 1.303 + break; 1.304 + default: 1.305 + /* The ratio is not acceptable now */ 1.306 + /* throw("The ratio is not acceptable for now!"); */ 1.307 + ratio_scalable = 0; 1.308 + break; 1.309 + } 1.310 + 1.311 + switch (vratio * 10 / vscale) { 1.312 + case 8: 1.313 + /* 4-5 Scale in vertical direction */ 1.314 + vert_band_scale = vp8_vertical_band_5_4_scale; 1.315 + source_band_height = 5; 1.316 + dest_band_height = 4; 1.317 + break; 1.318 + case 6: 1.319 + /* 3-5 Scale in vertical direction */ 1.320 + vert_band_scale = vp8_vertical_band_5_3_scale; 1.321 + source_band_height = 5; 1.322 + dest_band_height = 3; 1.323 + break; 1.324 + case 5: 1.325 + /* 1-2 Scale in vertical direction */ 1.326 + 1.327 + if (interlaced) { 1.328 + /* if the content is interlaced, point sampling is used */ 1.329 + vert_band_scale = vp8_vertical_band_2_1_scale; 1.330 + } else { 1.331 + 1.332 + interpolation = 1; 1.333 + /* if the content is progressive, interplo */ 1.334 + vert_band_scale = vp8_vertical_band_2_1_scale_i; 1.335 + 1.336 + } 1.337 + 1.338 + source_band_height = 2; 1.339 + dest_band_height = 1; 1.340 + break; 1.341 + default: 1.342 + /* The ratio is not acceptable now */ 1.343 + /* throw("The ratio is not acceptable for now!"); */ 1.344 + ratio_scalable = 0; 1.345 + break; 1.346 + } 1.347 + 1.348 + if (ratio_scalable) { 1.349 + if (source_height == dest_height) { 1.350 + /* for each band of the image */ 1.351 + for (k = 0; k < (int)dest_height; k++) { 1.352 + horiz_line_scale(source, source_width, dest, dest_width); 1.353 + source += source_pitch; 1.354 + dest += dest_pitch; 1.355 + } 1.356 + 1.357 + return; 1.358 + } 1.359 + 1.360 + if (interpolation) { 1.361 + if (source < source_base) 1.362 + source = source_base; 1.363 + 1.364 + horiz_line_scale(source, source_width, temp_area, dest_width); 1.365 + } 1.366 + 1.367 + for (k = 0; k < (int)(dest_height + dest_band_height - 1) / dest_band_height; k++) { 1.368 + /* scale one band horizontally */ 1.369 + for (i = 0; i < source_band_height; i++) { 1.370 + /* Trap case where we could read off the base of the source buffer */ 1.371 + 1.372 + line_src = (unsigned char *)source + i * source_pitch; 1.373 + 1.374 + if (line_src < source_base) 1.375 + line_src = source_base; 1.376 + 1.377 + horiz_line_scale(line_src, source_width, 1.378 + temp_area + (i + 1)*dest_pitch, dest_width); 1.379 + } 1.380 + 1.381 + /* Vertical scaling is in place */ 1.382 + vert_band_scale(temp_area + dest_pitch, dest_pitch, dest, dest_pitch, dest_width); 1.383 + 1.384 + if (interpolation) 1.385 + vpx_memcpy(temp_area, temp_area + source_band_height * dest_pitch, dest_width); 1.386 + 1.387 + /* Next band... */ 1.388 + source += (unsigned long) source_band_height * source_pitch; 1.389 + dest += (unsigned long) dest_band_height * dest_pitch; 1.390 + } 1.391 + 1.392 + return; 1.393 + } 1.394 + 1.395 + if (hscale == 2 && hratio == 1) 1.396 + Scale1Dh = scale1d_2t1_ps; 1.397 + 1.398 + if (vscale == 2 && vratio == 1) { 1.399 + if (interlaced) 1.400 + Scale1Dv = scale1d_2t1_ps; 1.401 + else 1.402 + Scale1Dv = scale1d_2t1_i; 1.403 + } 1.404 + 1.405 + if (source_height == dest_height) { 1.406 + /* for each band of the image */ 1.407 + for (k = 0; k < (int)dest_height; k++) { 1.408 + Scale1Dh(source, 1, hscale, source_width + 1, dest, 1, hratio, dest_width); 1.409 + source += source_pitch; 1.410 + dest += dest_pitch; 1.411 + } 1.412 + 1.413 + return; 1.414 + } 1.415 + 1.416 + if (dest_height > source_height) { 1.417 + dest_band_height = temp_area_height - 1; 1.418 + source_band_height = dest_band_height * source_height / dest_height; 1.419 + } else { 1.420 + source_band_height = temp_area_height - 1; 1.421 + dest_band_height = source_band_height * vratio / vscale; 1.422 + } 1.423 + 1.424 + /* first row needs to be done so that we can stay one row ahead for vertical zoom */ 1.425 + Scale1Dh(source, 1, hscale, source_width + 1, temp_area, 1, hratio, dest_width); 1.426 + 1.427 + /* for each band of the image */ 1.428 + bands = (dest_height + dest_band_height - 1) / dest_band_height; 1.429 + 1.430 + for (k = 0; k < bands; k++) { 1.431 + /* scale one band horizontally */ 1.432 + for (i = 1; i < source_band_height + 1; i++) { 1.433 + if (k * source_band_height + i < (int) source_height) { 1.434 + Scale1Dh(source + i * source_pitch, 1, hscale, source_width + 1, 1.435 + temp_area + i * dest_pitch, 1, hratio, dest_width); 1.436 + } else { /* Duplicate the last row */ 1.437 + /* copy temp_area row 0 over from last row in the past */ 1.438 + vpx_memcpy(temp_area + i * dest_pitch, temp_area + (i - 1)*dest_pitch, dest_pitch); 1.439 + } 1.440 + } 1.441 + 1.442 + /* scale one band vertically */ 1.443 + for (j = 0; j < (int)dest_width; j++) { 1.444 + Scale1Dv(&temp_area[j], dest_pitch, vscale, source_band_height + 1, 1.445 + &dest[j], dest_pitch, vratio, dest_band_height); 1.446 + } 1.447 + 1.448 + /* copy temp_area row 0 over from last row in the past */ 1.449 + vpx_memcpy(temp_area, temp_area + source_band_height * dest_pitch, dest_pitch); 1.450 + 1.451 + /* move to the next band */ 1.452 + source += source_band_height * source_pitch; 1.453 + dest += dest_band_height * dest_pitch; 1.454 + } 1.455 +} 1.456 + 1.457 +/**************************************************************************** 1.458 + * 1.459 + * ROUTINE : vpx_scale_frame 1.460 + * 1.461 + * INPUTS : YV12_BUFFER_CONFIG *src : Pointer to frame to be scaled. 1.462 + * YV12_BUFFER_CONFIG *dst : Pointer to buffer to hold scaled frame. 1.463 + * unsigned char *temp_area : Pointer to temp work area. 1.464 + * unsigned char temp_area_height : Height of temp work area. 1.465 + * unsigned int hscale : Horizontal scale factor numerator. 1.466 + * unsigned int hratio : Horizontal scale factor denominator. 1.467 + * unsigned int vscale : Vertical scale factor numerator. 1.468 + * unsigned int vratio : Vertical scale factor denominator. 1.469 + * unsigned int interlaced : Interlace flag. 1.470 + * 1.471 + * OUTPUTS : None. 1.472 + * 1.473 + * RETURNS : void 1.474 + * 1.475 + * FUNCTION : Performs 2-tap linear interpolation in two dimensions. 1.476 + * 1.477 + * SPECIAL NOTES : Expansion is performed one band at a time to help with 1.478 + * caching. 1.479 + * 1.480 + ****************************************************************************/ 1.481 +void vpx_scale_frame 1.482 +( 1.483 + YV12_BUFFER_CONFIG *src, 1.484 + YV12_BUFFER_CONFIG *dst, 1.485 + unsigned char *temp_area, 1.486 + unsigned char temp_height, 1.487 + unsigned int hscale, 1.488 + unsigned int hratio, 1.489 + unsigned int vscale, 1.490 + unsigned int vratio, 1.491 + unsigned int interlaced 1.492 +) { 1.493 + int i; 1.494 + int dw = (hscale - 1 + src->y_width * hratio) / hscale; 1.495 + int dh = (vscale - 1 + src->y_height * vratio) / vscale; 1.496 + 1.497 + /* call our internal scaling routines!! */ 1.498 + Scale2D((unsigned char *) src->y_buffer, src->y_stride, src->y_width, src->y_height, 1.499 + (unsigned char *) dst->y_buffer, dst->y_stride, dw, dh, 1.500 + temp_area, temp_height, hscale, hratio, vscale, vratio, interlaced); 1.501 + 1.502 + if (dw < (int)dst->y_width) 1.503 + for (i = 0; i < dh; i++) 1.504 + vpx_memset(dst->y_buffer + i * dst->y_stride + dw - 1, dst->y_buffer[i * dst->y_stride + dw - 2], dst->y_width - dw + 1); 1.505 + 1.506 + if (dh < (int)dst->y_height) 1.507 + for (i = dh - 1; i < (int)dst->y_height; i++) 1.508 + vpx_memcpy(dst->y_buffer + i * dst->y_stride, dst->y_buffer + (dh - 2) * dst->y_stride, dst->y_width + 1); 1.509 + 1.510 + Scale2D((unsigned char *) src->u_buffer, src->uv_stride, src->uv_width, src->uv_height, 1.511 + (unsigned char *) dst->u_buffer, dst->uv_stride, dw / 2, dh / 2, 1.512 + temp_area, temp_height, hscale, hratio, vscale, vratio, interlaced); 1.513 + 1.514 + if (dw / 2 < (int)dst->uv_width) 1.515 + for (i = 0; i < dst->uv_height; i++) 1.516 + vpx_memset(dst->u_buffer + i * dst->uv_stride + dw / 2 - 1, dst->u_buffer[i * dst->uv_stride + dw / 2 - 2], dst->uv_width - dw / 2 + 1); 1.517 + 1.518 + if (dh / 2 < (int)dst->uv_height) 1.519 + for (i = dh / 2 - 1; i < (int)dst->y_height / 2; i++) 1.520 + vpx_memcpy(dst->u_buffer + i * dst->uv_stride, dst->u_buffer + (dh / 2 - 2)*dst->uv_stride, dst->uv_width); 1.521 + 1.522 + Scale2D((unsigned char *) src->v_buffer, src->uv_stride, src->uv_width, src->uv_height, 1.523 + (unsigned char *) dst->v_buffer, dst->uv_stride, dw / 2, dh / 2, 1.524 + temp_area, temp_height, hscale, hratio, vscale, vratio, interlaced); 1.525 + 1.526 + if (dw / 2 < (int)dst->uv_width) 1.527 + for (i = 0; i < dst->uv_height; i++) 1.528 + vpx_memset(dst->v_buffer + i * dst->uv_stride + dw / 2 - 1, dst->v_buffer[i * dst->uv_stride + dw / 2 - 2], dst->uv_width - dw / 2 + 1); 1.529 + 1.530 + if (dh / 2 < (int) dst->uv_height) 1.531 + for (i = dh / 2 - 1; i < (int)dst->y_height / 2; i++) 1.532 + vpx_memcpy(dst->v_buffer + i * dst->uv_stride, dst->v_buffer + (dh / 2 - 2)*dst->uv_stride, dst->uv_width); 1.533 +}