media/libvpx/vpx_scale/generic/vpx_scale.c

Thu, 15 Jan 2015 15:59:08 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:59:08 +0100
branch
TOR_BUG_9701
changeset 10
ac0c01689b40
permissions
-rw-r--r--

Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1 /*
michael@0 2 * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
michael@0 3 *
michael@0 4 * Use of this source code is governed by a BSD-style license
michael@0 5 * that can be found in the LICENSE file in the root of the source
michael@0 6 * tree. An additional intellectual property rights grant can be found
michael@0 7 * in the file PATENTS. All contributing project authors may
michael@0 8 * be found in the AUTHORS file in the root of the source tree.
michael@0 9 */
michael@0 10
michael@0 11
michael@0 12 /****************************************************************************
michael@0 13 *
michael@0 14 * Module Title : scale.c
michael@0 15 *
michael@0 16 * Description : Image scaling functions.
michael@0 17 *
michael@0 18 ***************************************************************************/
michael@0 19
michael@0 20 /****************************************************************************
michael@0 21 * Header Files
michael@0 22 ****************************************************************************/
michael@0 23 #include "./vpx_scale_rtcd.h"
michael@0 24 #include "vpx_mem/vpx_mem.h"
michael@0 25 #include "vpx_scale/yv12config.h"
michael@0 26
michael@0 27 typedef struct {
michael@0 28 int expanded_frame_width;
michael@0 29 int expanded_frame_height;
michael@0 30
michael@0 31 int HScale;
michael@0 32 int HRatio;
michael@0 33 int VScale;
michael@0 34 int VRatio;
michael@0 35
michael@0 36 YV12_BUFFER_CONFIG *src_yuv_config;
michael@0 37 YV12_BUFFER_CONFIG *dst_yuv_config;
michael@0 38
michael@0 39 } SCALE_VARS;
michael@0 40
michael@0 41 /****************************************************************************
michael@0 42 *
michael@0 43 * ROUTINE : scale1d_2t1_i
michael@0 44 *
michael@0 45 * INPUTS : const unsigned char *source : Pointer to data to be scaled.
michael@0 46 * int source_step : Number of pixels to step on in source.
michael@0 47 * unsigned int source_scale : Scale for source (UNUSED).
michael@0 48 * unsigned int source_length : Length of source (UNUSED).
michael@0 49 * unsigned char *dest : Pointer to output data array.
michael@0 50 * int dest_step : Number of pixels to step on in destination.
michael@0 51 * unsigned int dest_scale : Scale for destination (UNUSED).
michael@0 52 * unsigned int dest_length : Length of destination.
michael@0 53 *
michael@0 54 * OUTPUTS : None.
michael@0 55 *
michael@0 56 * RETURNS : void
michael@0 57 *
michael@0 58 * FUNCTION : Performs 2-to-1 interpolated scaling.
michael@0 59 *
michael@0 60 * SPECIAL NOTES : None.
michael@0 61 *
michael@0 62 ****************************************************************************/
michael@0 63 static
michael@0 64 void scale1d_2t1_i
michael@0 65 (
michael@0 66 const unsigned char *source,
michael@0 67 int source_step,
michael@0 68 unsigned int source_scale,
michael@0 69 unsigned int source_length,
michael@0 70 unsigned char *dest,
michael@0 71 int dest_step,
michael@0 72 unsigned int dest_scale,
michael@0 73 unsigned int dest_length
michael@0 74 ) {
michael@0 75 unsigned int i, j;
michael@0 76 unsigned int temp;
michael@0 77 int source_pitch = source_step;
michael@0 78 (void) source_length;
michael@0 79 (void) source_scale;
michael@0 80 (void) dest_scale;
michael@0 81
michael@0 82 source_step *= 2;
michael@0 83 dest[0] = source[0];
michael@0 84
michael@0 85 for (i = dest_step, j = source_step; i < dest_length * dest_step; i += dest_step, j += source_step) {
michael@0 86 temp = 8;
michael@0 87 temp += 3 * source[j - source_pitch];
michael@0 88 temp += 10 * source[j];
michael@0 89 temp += 3 * source[j + source_pitch];
michael@0 90 temp >>= 4;
michael@0 91 dest[i] = (char)(temp);
michael@0 92 }
michael@0 93 }
michael@0 94
michael@0 95 /****************************************************************************
michael@0 96 *
michael@0 97 * ROUTINE : scale1d_2t1_ps
michael@0 98 *
michael@0 99 * INPUTS : const unsigned char *source : Pointer to data to be scaled.
michael@0 100 * int source_step : Number of pixels to step on in source.
michael@0 101 * unsigned int source_scale : Scale for source (UNUSED).
michael@0 102 * unsigned int source_length : Length of source (UNUSED).
michael@0 103 * unsigned char *dest : Pointer to output data array.
michael@0 104 * int dest_step : Number of pixels to step on in destination.
michael@0 105 * unsigned int dest_scale : Scale for destination (UNUSED).
michael@0 106 * unsigned int dest_length : Length of destination.
michael@0 107 *
michael@0 108 * OUTPUTS : None.
michael@0 109 *
michael@0 110 * RETURNS : void
michael@0 111 *
michael@0 112 * FUNCTION : Performs 2-to-1 point subsampled scaling.
michael@0 113 *
michael@0 114 * SPECIAL NOTES : None.
michael@0 115 *
michael@0 116 ****************************************************************************/
michael@0 117 static
michael@0 118 void scale1d_2t1_ps
michael@0 119 (
michael@0 120 const unsigned char *source,
michael@0 121 int source_step,
michael@0 122 unsigned int source_scale,
michael@0 123 unsigned int source_length,
michael@0 124 unsigned char *dest,
michael@0 125 int dest_step,
michael@0 126 unsigned int dest_scale,
michael@0 127 unsigned int dest_length
michael@0 128 ) {
michael@0 129 unsigned int i, j;
michael@0 130
michael@0 131 (void) source_length;
michael@0 132 (void) source_scale;
michael@0 133 (void) dest_scale;
michael@0 134
michael@0 135 source_step *= 2;
michael@0 136 j = 0;
michael@0 137
michael@0 138 for (i = 0; i < dest_length * dest_step; i += dest_step, j += source_step)
michael@0 139 dest[i] = source[j];
michael@0 140 }
michael@0 141 /****************************************************************************
michael@0 142 *
michael@0 143 * ROUTINE : scale1d_c
michael@0 144 *
michael@0 145 * INPUTS : const unsigned char *source : Pointer to data to be scaled.
michael@0 146 * int source_step : Number of pixels to step on in source.
michael@0 147 * unsigned int source_scale : Scale for source.
michael@0 148 * unsigned int source_length : Length of source (UNUSED).
michael@0 149 * unsigned char *dest : Pointer to output data array.
michael@0 150 * int dest_step : Number of pixels to step on in destination.
michael@0 151 * unsigned int dest_scale : Scale for destination.
michael@0 152 * unsigned int dest_length : Length of destination.
michael@0 153 *
michael@0 154 * OUTPUTS : None.
michael@0 155 *
michael@0 156 * RETURNS : void
michael@0 157 *
michael@0 158 * FUNCTION : Performs linear interpolation in one dimension.
michael@0 159 *
michael@0 160 * SPECIAL NOTES : None.
michael@0 161 *
michael@0 162 ****************************************************************************/
michael@0 163 static
michael@0 164 void scale1d_c
michael@0 165 (
michael@0 166 const unsigned char *source,
michael@0 167 int source_step,
michael@0 168 unsigned int source_scale,
michael@0 169 unsigned int source_length,
michael@0 170 unsigned char *dest,
michael@0 171 int dest_step,
michael@0 172 unsigned int dest_scale,
michael@0 173 unsigned int dest_length
michael@0 174 ) {
michael@0 175 unsigned int i;
michael@0 176 unsigned int round_value = dest_scale / 2;
michael@0 177 unsigned int left_modifier = dest_scale;
michael@0 178 unsigned int right_modifier = 0;
michael@0 179 unsigned char left_pixel = *source;
michael@0 180 unsigned char right_pixel = *(source + source_step);
michael@0 181
michael@0 182 (void) source_length;
michael@0 183
michael@0 184 /* These asserts are needed if there are boundary issues... */
michael@0 185 /*assert ( dest_scale > source_scale );*/
michael@0 186 /*assert ( (source_length-1) * dest_scale >= (dest_length-1) * source_scale );*/
michael@0 187
michael@0 188 for (i = 0; i < dest_length * dest_step; i += dest_step) {
michael@0 189 dest[i] = (char)((left_modifier * left_pixel + right_modifier * right_pixel + round_value) / dest_scale);
michael@0 190
michael@0 191 right_modifier += source_scale;
michael@0 192
michael@0 193 while (right_modifier > dest_scale) {
michael@0 194 right_modifier -= dest_scale;
michael@0 195 source += source_step;
michael@0 196 left_pixel = *source;
michael@0 197 right_pixel = *(source + source_step);
michael@0 198 }
michael@0 199
michael@0 200 left_modifier = dest_scale - right_modifier;
michael@0 201 }
michael@0 202 }
michael@0 203
michael@0 204 /****************************************************************************
michael@0 205 *
michael@0 206 * ROUTINE : Scale2D
michael@0 207 *
michael@0 208 * INPUTS : const unsigned char *source : Pointer to data to be scaled.
michael@0 209 * int source_pitch : Stride of source image.
michael@0 210 * unsigned int source_width : Width of input image.
michael@0 211 * unsigned int source_height : Height of input image.
michael@0 212 * unsigned char *dest : Pointer to output data array.
michael@0 213 * int dest_pitch : Stride of destination image.
michael@0 214 * unsigned int dest_width : Width of destination image.
michael@0 215 * unsigned int dest_height : Height of destination image.
michael@0 216 * unsigned char *temp_area : Pointer to temp work area.
michael@0 217 * unsigned char temp_area_height : Height of temp work area.
michael@0 218 * unsigned int hscale : Horizontal scale factor numerator.
michael@0 219 * unsigned int hratio : Horizontal scale factor denominator.
michael@0 220 * unsigned int vscale : Vertical scale factor numerator.
michael@0 221 * unsigned int vratio : Vertical scale factor denominator.
michael@0 222 * unsigned int interlaced : Interlace flag.
michael@0 223 *
michael@0 224 * OUTPUTS : None.
michael@0 225 *
michael@0 226 * RETURNS : void
michael@0 227 *
michael@0 228 * FUNCTION : Performs 2-tap linear interpolation in two dimensions.
michael@0 229 *
michael@0 230 * SPECIAL NOTES : Expansion is performed one band at a time to help with
michael@0 231 * caching.
michael@0 232 *
michael@0 233 ****************************************************************************/
michael@0 234 static
michael@0 235 void Scale2D
michael@0 236 (
michael@0 237 /*const*/
michael@0 238 unsigned char *source,
michael@0 239 int source_pitch,
michael@0 240 unsigned int source_width,
michael@0 241 unsigned int source_height,
michael@0 242 unsigned char *dest,
michael@0 243 int dest_pitch,
michael@0 244 unsigned int dest_width,
michael@0 245 unsigned int dest_height,
michael@0 246 unsigned char *temp_area,
michael@0 247 unsigned char temp_area_height,
michael@0 248 unsigned int hscale,
michael@0 249 unsigned int hratio,
michael@0 250 unsigned int vscale,
michael@0 251 unsigned int vratio,
michael@0 252 unsigned int interlaced
michael@0 253 ) {
michael@0 254 /*unsigned*/
michael@0 255 int i, j, k;
michael@0 256 int bands;
michael@0 257 int dest_band_height;
michael@0 258 int source_band_height;
michael@0 259
michael@0 260 typedef void (*Scale1D)(const unsigned char * source, int source_step, unsigned int source_scale, unsigned int source_length,
michael@0 261 unsigned char * dest, int dest_step, unsigned int dest_scale, unsigned int dest_length);
michael@0 262
michael@0 263 Scale1D Scale1Dv = scale1d_c;
michael@0 264 Scale1D Scale1Dh = scale1d_c;
michael@0 265
michael@0 266 void (*horiz_line_scale)(const unsigned char *, unsigned int, unsigned char *, unsigned int) = NULL;
michael@0 267 void (*vert_band_scale)(unsigned char *, unsigned int, unsigned char *, unsigned int, unsigned int) = NULL;
michael@0 268
michael@0 269 int ratio_scalable = 1;
michael@0 270 int interpolation = 0;
michael@0 271
michael@0 272 unsigned char *source_base; /* = (unsigned char *) ((source_pitch >= 0) ? source : (source + ((source_height-1) * source_pitch))); */
michael@0 273 unsigned char *line_src;
michael@0 274
michael@0 275
michael@0 276 source_base = (unsigned char *)source;
michael@0 277
michael@0 278 if (source_pitch < 0) {
michael@0 279 int offset;
michael@0 280
michael@0 281 offset = (source_height - 1);
michael@0 282 offset *= source_pitch;
michael@0 283
michael@0 284 source_base += offset;
michael@0 285 }
michael@0 286
michael@0 287 /* find out the ratio for each direction */
michael@0 288 switch (hratio * 10 / hscale) {
michael@0 289 case 8:
michael@0 290 /* 4-5 Scale in Width direction */
michael@0 291 horiz_line_scale = vp8_horizontal_line_5_4_scale;
michael@0 292 break;
michael@0 293 case 6:
michael@0 294 /* 3-5 Scale in Width direction */
michael@0 295 horiz_line_scale = vp8_horizontal_line_5_3_scale;
michael@0 296 break;
michael@0 297 case 5:
michael@0 298 /* 1-2 Scale in Width direction */
michael@0 299 horiz_line_scale = vp8_horizontal_line_2_1_scale;
michael@0 300 break;
michael@0 301 default:
michael@0 302 /* The ratio is not acceptable now */
michael@0 303 /* throw("The ratio is not acceptable for now!"); */
michael@0 304 ratio_scalable = 0;
michael@0 305 break;
michael@0 306 }
michael@0 307
michael@0 308 switch (vratio * 10 / vscale) {
michael@0 309 case 8:
michael@0 310 /* 4-5 Scale in vertical direction */
michael@0 311 vert_band_scale = vp8_vertical_band_5_4_scale;
michael@0 312 source_band_height = 5;
michael@0 313 dest_band_height = 4;
michael@0 314 break;
michael@0 315 case 6:
michael@0 316 /* 3-5 Scale in vertical direction */
michael@0 317 vert_band_scale = vp8_vertical_band_5_3_scale;
michael@0 318 source_band_height = 5;
michael@0 319 dest_band_height = 3;
michael@0 320 break;
michael@0 321 case 5:
michael@0 322 /* 1-2 Scale in vertical direction */
michael@0 323
michael@0 324 if (interlaced) {
michael@0 325 /* if the content is interlaced, point sampling is used */
michael@0 326 vert_band_scale = vp8_vertical_band_2_1_scale;
michael@0 327 } else {
michael@0 328
michael@0 329 interpolation = 1;
michael@0 330 /* if the content is progressive, interplo */
michael@0 331 vert_band_scale = vp8_vertical_band_2_1_scale_i;
michael@0 332
michael@0 333 }
michael@0 334
michael@0 335 source_band_height = 2;
michael@0 336 dest_band_height = 1;
michael@0 337 break;
michael@0 338 default:
michael@0 339 /* The ratio is not acceptable now */
michael@0 340 /* throw("The ratio is not acceptable for now!"); */
michael@0 341 ratio_scalable = 0;
michael@0 342 break;
michael@0 343 }
michael@0 344
michael@0 345 if (ratio_scalable) {
michael@0 346 if (source_height == dest_height) {
michael@0 347 /* for each band of the image */
michael@0 348 for (k = 0; k < (int)dest_height; k++) {
michael@0 349 horiz_line_scale(source, source_width, dest, dest_width);
michael@0 350 source += source_pitch;
michael@0 351 dest += dest_pitch;
michael@0 352 }
michael@0 353
michael@0 354 return;
michael@0 355 }
michael@0 356
michael@0 357 if (interpolation) {
michael@0 358 if (source < source_base)
michael@0 359 source = source_base;
michael@0 360
michael@0 361 horiz_line_scale(source, source_width, temp_area, dest_width);
michael@0 362 }
michael@0 363
michael@0 364 for (k = 0; k < (int)(dest_height + dest_band_height - 1) / dest_band_height; k++) {
michael@0 365 /* scale one band horizontally */
michael@0 366 for (i = 0; i < source_band_height; i++) {
michael@0 367 /* Trap case where we could read off the base of the source buffer */
michael@0 368
michael@0 369 line_src = (unsigned char *)source + i * source_pitch;
michael@0 370
michael@0 371 if (line_src < source_base)
michael@0 372 line_src = source_base;
michael@0 373
michael@0 374 horiz_line_scale(line_src, source_width,
michael@0 375 temp_area + (i + 1)*dest_pitch, dest_width);
michael@0 376 }
michael@0 377
michael@0 378 /* Vertical scaling is in place */
michael@0 379 vert_band_scale(temp_area + dest_pitch, dest_pitch, dest, dest_pitch, dest_width);
michael@0 380
michael@0 381 if (interpolation)
michael@0 382 vpx_memcpy(temp_area, temp_area + source_band_height * dest_pitch, dest_width);
michael@0 383
michael@0 384 /* Next band... */
michael@0 385 source += (unsigned long) source_band_height * source_pitch;
michael@0 386 dest += (unsigned long) dest_band_height * dest_pitch;
michael@0 387 }
michael@0 388
michael@0 389 return;
michael@0 390 }
michael@0 391
michael@0 392 if (hscale == 2 && hratio == 1)
michael@0 393 Scale1Dh = scale1d_2t1_ps;
michael@0 394
michael@0 395 if (vscale == 2 && vratio == 1) {
michael@0 396 if (interlaced)
michael@0 397 Scale1Dv = scale1d_2t1_ps;
michael@0 398 else
michael@0 399 Scale1Dv = scale1d_2t1_i;
michael@0 400 }
michael@0 401
michael@0 402 if (source_height == dest_height) {
michael@0 403 /* for each band of the image */
michael@0 404 for (k = 0; k < (int)dest_height; k++) {
michael@0 405 Scale1Dh(source, 1, hscale, source_width + 1, dest, 1, hratio, dest_width);
michael@0 406 source += source_pitch;
michael@0 407 dest += dest_pitch;
michael@0 408 }
michael@0 409
michael@0 410 return;
michael@0 411 }
michael@0 412
michael@0 413 if (dest_height > source_height) {
michael@0 414 dest_band_height = temp_area_height - 1;
michael@0 415 source_band_height = dest_band_height * source_height / dest_height;
michael@0 416 } else {
michael@0 417 source_band_height = temp_area_height - 1;
michael@0 418 dest_band_height = source_band_height * vratio / vscale;
michael@0 419 }
michael@0 420
michael@0 421 /* first row needs to be done so that we can stay one row ahead for vertical zoom */
michael@0 422 Scale1Dh(source, 1, hscale, source_width + 1, temp_area, 1, hratio, dest_width);
michael@0 423
michael@0 424 /* for each band of the image */
michael@0 425 bands = (dest_height + dest_band_height - 1) / dest_band_height;
michael@0 426
michael@0 427 for (k = 0; k < bands; k++) {
michael@0 428 /* scale one band horizontally */
michael@0 429 for (i = 1; i < source_band_height + 1; i++) {
michael@0 430 if (k * source_band_height + i < (int) source_height) {
michael@0 431 Scale1Dh(source + i * source_pitch, 1, hscale, source_width + 1,
michael@0 432 temp_area + i * dest_pitch, 1, hratio, dest_width);
michael@0 433 } else { /* Duplicate the last row */
michael@0 434 /* copy temp_area row 0 over from last row in the past */
michael@0 435 vpx_memcpy(temp_area + i * dest_pitch, temp_area + (i - 1)*dest_pitch, dest_pitch);
michael@0 436 }
michael@0 437 }
michael@0 438
michael@0 439 /* scale one band vertically */
michael@0 440 for (j = 0; j < (int)dest_width; j++) {
michael@0 441 Scale1Dv(&temp_area[j], dest_pitch, vscale, source_band_height + 1,
michael@0 442 &dest[j], dest_pitch, vratio, dest_band_height);
michael@0 443 }
michael@0 444
michael@0 445 /* copy temp_area row 0 over from last row in the past */
michael@0 446 vpx_memcpy(temp_area, temp_area + source_band_height * dest_pitch, dest_pitch);
michael@0 447
michael@0 448 /* move to the next band */
michael@0 449 source += source_band_height * source_pitch;
michael@0 450 dest += dest_band_height * dest_pitch;
michael@0 451 }
michael@0 452 }
michael@0 453
michael@0 454 /****************************************************************************
michael@0 455 *
michael@0 456 * ROUTINE : vpx_scale_frame
michael@0 457 *
michael@0 458 * INPUTS : YV12_BUFFER_CONFIG *src : Pointer to frame to be scaled.
michael@0 459 * YV12_BUFFER_CONFIG *dst : Pointer to buffer to hold scaled frame.
michael@0 460 * unsigned char *temp_area : Pointer to temp work area.
michael@0 461 * unsigned char temp_area_height : Height of temp work area.
michael@0 462 * unsigned int hscale : Horizontal scale factor numerator.
michael@0 463 * unsigned int hratio : Horizontal scale factor denominator.
michael@0 464 * unsigned int vscale : Vertical scale factor numerator.
michael@0 465 * unsigned int vratio : Vertical scale factor denominator.
michael@0 466 * unsigned int interlaced : Interlace flag.
michael@0 467 *
michael@0 468 * OUTPUTS : None.
michael@0 469 *
michael@0 470 * RETURNS : void
michael@0 471 *
michael@0 472 * FUNCTION : Performs 2-tap linear interpolation in two dimensions.
michael@0 473 *
michael@0 474 * SPECIAL NOTES : Expansion is performed one band at a time to help with
michael@0 475 * caching.
michael@0 476 *
michael@0 477 ****************************************************************************/
michael@0 478 void vpx_scale_frame
michael@0 479 (
michael@0 480 YV12_BUFFER_CONFIG *src,
michael@0 481 YV12_BUFFER_CONFIG *dst,
michael@0 482 unsigned char *temp_area,
michael@0 483 unsigned char temp_height,
michael@0 484 unsigned int hscale,
michael@0 485 unsigned int hratio,
michael@0 486 unsigned int vscale,
michael@0 487 unsigned int vratio,
michael@0 488 unsigned int interlaced
michael@0 489 ) {
michael@0 490 int i;
michael@0 491 int dw = (hscale - 1 + src->y_width * hratio) / hscale;
michael@0 492 int dh = (vscale - 1 + src->y_height * vratio) / vscale;
michael@0 493
michael@0 494 /* call our internal scaling routines!! */
michael@0 495 Scale2D((unsigned char *) src->y_buffer, src->y_stride, src->y_width, src->y_height,
michael@0 496 (unsigned char *) dst->y_buffer, dst->y_stride, dw, dh,
michael@0 497 temp_area, temp_height, hscale, hratio, vscale, vratio, interlaced);
michael@0 498
michael@0 499 if (dw < (int)dst->y_width)
michael@0 500 for (i = 0; i < dh; i++)
michael@0 501 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);
michael@0 502
michael@0 503 if (dh < (int)dst->y_height)
michael@0 504 for (i = dh - 1; i < (int)dst->y_height; i++)
michael@0 505 vpx_memcpy(dst->y_buffer + i * dst->y_stride, dst->y_buffer + (dh - 2) * dst->y_stride, dst->y_width + 1);
michael@0 506
michael@0 507 Scale2D((unsigned char *) src->u_buffer, src->uv_stride, src->uv_width, src->uv_height,
michael@0 508 (unsigned char *) dst->u_buffer, dst->uv_stride, dw / 2, dh / 2,
michael@0 509 temp_area, temp_height, hscale, hratio, vscale, vratio, interlaced);
michael@0 510
michael@0 511 if (dw / 2 < (int)dst->uv_width)
michael@0 512 for (i = 0; i < dst->uv_height; i++)
michael@0 513 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);
michael@0 514
michael@0 515 if (dh / 2 < (int)dst->uv_height)
michael@0 516 for (i = dh / 2 - 1; i < (int)dst->y_height / 2; i++)
michael@0 517 vpx_memcpy(dst->u_buffer + i * dst->uv_stride, dst->u_buffer + (dh / 2 - 2)*dst->uv_stride, dst->uv_width);
michael@0 518
michael@0 519 Scale2D((unsigned char *) src->v_buffer, src->uv_stride, src->uv_width, src->uv_height,
michael@0 520 (unsigned char *) dst->v_buffer, dst->uv_stride, dw / 2, dh / 2,
michael@0 521 temp_area, temp_height, hscale, hratio, vscale, vratio, interlaced);
michael@0 522
michael@0 523 if (dw / 2 < (int)dst->uv_width)
michael@0 524 for (i = 0; i < dst->uv_height; i++)
michael@0 525 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);
michael@0 526
michael@0 527 if (dh / 2 < (int) dst->uv_height)
michael@0 528 for (i = dh / 2 - 1; i < (int)dst->y_height / 2; i++)
michael@0 529 vpx_memcpy(dst->v_buffer + i * dst->uv_stride, dst->v_buffer + (dh / 2 - 2)*dst->uv_stride, dst->uv_width);
michael@0 530 }

mercurial