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 12 /**************************************************************************** 13 * 14 * Module Title : scale.c 15 * 16 * Description : Image scaling functions. 17 * 18 ***************************************************************************/ 19 20 /**************************************************************************** 21 * Header Files 22 ****************************************************************************/ 23 #include "./vpx_rtcd.h" 24 #include "vpx_mem/vpx_mem.h" 25 #include "vpx_scale/yv12config.h" 26 #include "vpx_scale/scale_mode.h" 27 28 typedef struct { 29 int expanded_frame_width; 30 int expanded_frame_height; 31 32 int HScale; 33 int HRatio; 34 int VScale; 35 int VRatio; 36 37 YV12_BUFFER_CONFIG *src_yuv_config; 38 YV12_BUFFER_CONFIG *dst_yuv_config; 39 40 } SCALE_VARS; 41 42 /**************************************************************************** 43 * 44 * ROUTINE : horizontal_line_copy 45 * 46 * INPUTS : None 47 * 48 * 49 * OUTPUTS : None. 50 * 51 * RETURNS : None 52 * 53 * FUNCTION : 1 to 1 scaling up for a horizontal line of pixles 54 * 55 * SPECIAL NOTES : None. 56 * 57 * ERRORS : None. 58 * 59 ****************************************************************************/ 60 static 61 void horizontal_line_copy( 62 const unsigned char *source, 63 unsigned int source_width, 64 unsigned char *dest, 65 unsigned int dest_width 66 ) { 67 (void) dest_width; 68 69 duck_memcpy(dest, source, source_width); 70 } 71 /**************************************************************************** 72 * 73 * ROUTINE : null_scale 74 * 75 * INPUTS : None 76 * 77 * 78 * OUTPUTS : None. 79 * 80 * RETURNS : None 81 * 82 * FUNCTION : 1 to 1 scaling up for a vertical band 83 * 84 * SPECIAL NOTES : None. 85 * 86 * ERRORS : None. 87 * 88 ****************************************************************************/ 89 static 90 void null_scale( 91 unsigned char *dest, 92 unsigned int dest_pitch, 93 unsigned int dest_width 94 ) { 95 (void) dest; 96 (void) dest_pitch; 97 (void) dest_width; 98 99 return; 100 } 101 102 /**************************************************************************** 103 * 104 * ROUTINE : scale1d_2t1_i 105 * 106 * INPUTS : const unsigned char *source : Pointer to data to be scaled. 107 * int source_step : Number of pixels to step on in source. 108 * unsigned int source_scale : Scale for source (UNUSED). 109 * unsigned int source_length : Length of source (UNUSED). 110 * unsigned char *dest : Pointer to output data array. 111 * int dest_step : Number of pixels to step on in destination. 112 * unsigned int dest_scale : Scale for destination (UNUSED). 113 * unsigned int dest_length : Length of destination. 114 * 115 * OUTPUTS : None. 116 * 117 * RETURNS : void 118 * 119 * FUNCTION : Performs 2-to-1 interpolated scaling. 120 * 121 * SPECIAL NOTES : None. 122 * 123 ****************************************************************************/ 124 static 125 void scale1d_2t1_i 126 ( 127 const unsigned char *source, 128 int source_step, 129 unsigned int source_scale, 130 unsigned int source_length, 131 unsigned char *dest, 132 int dest_step, 133 unsigned int dest_scale, 134 unsigned int dest_length 135 ) { 136 unsigned int i, j; 137 unsigned int temp; 138 int source_pitch = source_step; 139 (void) source_length; 140 (void) source_scale; 141 (void) dest_scale; 142 143 source_step *= 2; 144 dest[0] = source[0]; 145 146 for (i = dest_step, j = source_step; i < dest_length * dest_step; i += dest_step, j += source_step) { 147 temp = 8; 148 temp += 3 * source[j - source_pitch]; 149 temp += 10 * source[j]; 150 temp += 3 * source[j + source_pitch]; 151 temp >>= 4; 152 dest[i] = (char)(temp); 153 } 154 } 155 156 /**************************************************************************** 157 * 158 * ROUTINE : scale1d_2t1_ps 159 * 160 * INPUTS : const unsigned char *source : Pointer to data to be scaled. 161 * int source_step : Number of pixels to step on in source. 162 * unsigned int source_scale : Scale for source (UNUSED). 163 * unsigned int source_length : Length of source (UNUSED). 164 * unsigned char *dest : Pointer to output data array. 165 * int dest_step : Number of pixels to step on in destination. 166 * unsigned int dest_scale : Scale for destination (UNUSED). 167 * unsigned int dest_length : Length of destination. 168 * 169 * OUTPUTS : None. 170 * 171 * RETURNS : void 172 * 173 * FUNCTION : Performs 2-to-1 point subsampled scaling. 174 * 175 * SPECIAL NOTES : None. 176 * 177 ****************************************************************************/ 178 static 179 void scale1d_2t1_ps 180 ( 181 const unsigned char *source, 182 int source_step, 183 unsigned int source_scale, 184 unsigned int source_length, 185 unsigned char *dest, 186 int dest_step, 187 unsigned int dest_scale, 188 unsigned int dest_length 189 ) { 190 unsigned int i, j; 191 192 (void) source_length; 193 (void) source_scale; 194 (void) dest_scale; 195 196 source_step *= 2; 197 j = 0; 198 199 for (i = 0; i < dest_length * dest_step; i += dest_step, j += source_step) 200 dest[i] = source[j]; 201 } 202 /**************************************************************************** 203 * 204 * ROUTINE : scale1d_c 205 * 206 * INPUTS : const unsigned char *source : Pointer to data to be scaled. 207 * int source_step : Number of pixels to step on in source. 208 * unsigned int source_scale : Scale for source. 209 * unsigned int source_length : Length of source (UNUSED). 210 * unsigned char *dest : Pointer to output data array. 211 * int dest_step : Number of pixels to step on in destination. 212 * unsigned int dest_scale : Scale for destination. 213 * unsigned int dest_length : Length of destination. 214 * 215 * OUTPUTS : None. 216 * 217 * RETURNS : void 218 * 219 * FUNCTION : Performs linear interpolation in one dimension. 220 * 221 * SPECIAL NOTES : None. 222 * 223 ****************************************************************************/ 224 static 225 void scale1d_c 226 ( 227 const unsigned char *source, 228 int source_step, 229 unsigned int source_scale, 230 unsigned int source_length, 231 unsigned char *dest, 232 int dest_step, 233 unsigned int dest_scale, 234 unsigned int dest_length 235 ) { 236 unsigned int i; 237 unsigned int round_value = dest_scale / 2; 238 unsigned int left_modifier = dest_scale; 239 unsigned int right_modifier = 0; 240 unsigned char left_pixel = *source; 241 unsigned char right_pixel = *(source + source_step); 242 243 (void) source_length; 244 245 /* These asserts are needed if there are boundary issues... */ 246 /*assert ( dest_scale > source_scale );*/ 247 /*assert ( (source_length-1) * dest_scale >= (dest_length-1) * source_scale );*/ 248 249 for (i = 0; i < dest_length * dest_step; i += dest_step) { 250 dest[i] = (char)((left_modifier * left_pixel + right_modifier * right_pixel + round_value) / dest_scale); 251 252 right_modifier += source_scale; 253 254 while (right_modifier > dest_scale) { 255 right_modifier -= dest_scale; 256 source += source_step; 257 left_pixel = *source; 258 right_pixel = *(source + source_step); 259 } 260 261 left_modifier = dest_scale - right_modifier; 262 } 263 } 264 265 /**************************************************************************** 266 * 267 * ROUTINE : Scale2D 268 * 269 * INPUTS : const unsigned char *source : Pointer to data to be scaled. 270 * int source_pitch : Stride of source image. 271 * unsigned int source_width : Width of input image. 272 * unsigned int source_height : Height of input image. 273 * unsigned char *dest : Pointer to output data array. 274 * int dest_pitch : Stride of destination image. 275 * unsigned int dest_width : Width of destination image. 276 * unsigned int dest_height : Height of destination image. 277 * unsigned char *temp_area : Pointer to temp work area. 278 * unsigned char temp_area_height : Height of temp work area. 279 * unsigned int hscale : Horizontal scale factor numerator. 280 * unsigned int hratio : Horizontal scale factor denominator. 281 * unsigned int vscale : Vertical scale factor numerator. 282 * unsigned int vratio : Vertical scale factor denominator. 283 * unsigned int interlaced : Interlace flag. 284 * 285 * OUTPUTS : None. 286 * 287 * RETURNS : void 288 * 289 * FUNCTION : Performs 2-tap linear interpolation in two dimensions. 290 * 291 * SPECIAL NOTES : Expansion is performed one band at a time to help with 292 * caching. 293 * 294 ****************************************************************************/ 295 static 296 void Scale2D 297 ( 298 /*const*/ 299 unsigned char *source, 300 int source_pitch, 301 unsigned int source_width, 302 unsigned int source_height, 303 unsigned char *dest, 304 int dest_pitch, 305 unsigned int dest_width, 306 unsigned int dest_height, 307 unsigned char *temp_area, 308 unsigned char temp_area_height, 309 unsigned int hscale, 310 unsigned int hratio, 311 unsigned int vscale, 312 unsigned int vratio, 313 unsigned int interlaced 314 ) { 315 /*unsigned*/ 316 int i, j, k; 317 int bands; 318 int dest_band_height; 319 int source_band_height; 320 321 typedef void (*Scale1D)(const unsigned char * source, int source_step, unsigned int source_scale, unsigned int source_length, 322 unsigned char * dest, int dest_step, unsigned int dest_scale, unsigned int dest_length); 323 324 Scale1D Scale1Dv = scale1d_c; 325 Scale1D Scale1Dh = scale1d_c; 326 327 void (*horiz_line_scale)(const unsigned char *, unsigned int, unsigned char *, unsigned int) = NULL; 328 void (*vert_band_scale)(unsigned char *, unsigned int, unsigned char *, unsigned int, unsigned int) = NULL; 329 330 int ratio_scalable = 1; 331 int interpolation = 0; 332 333 unsigned char *source_base; /* = (unsigned char *) ((source_pitch >= 0) ? source : (source + ((source_height-1) * source_pitch))); */ 334 unsigned char *line_src; 335 336 337 source_base = (unsigned char *)source; 338 339 if (source_pitch < 0) { 340 int offset; 341 342 offset = (source_height - 1); 343 offset *= source_pitch; 344 345 source_base += offset; 346 } 347 348 /* find out the ratio for each direction */ 349 switch (hratio * 10 / hscale) { 350 case 8: 351 /* 4-5 Scale in Width direction */ 352 horiz_line_scale = vp8_horizontal_line_5_4_scale; 353 break; 354 case 6: 355 /* 3-5 Scale in Width direction */ 356 horiz_line_scale = vp8_horizontal_line_5_3_scale; 357 break; 358 case 5: 359 /* 1-2 Scale in Width direction */ 360 horiz_line_scale = vp8_horizontal_line_2_1_scale; 361 break; 362 default: 363 /* The ratio is not acceptable now */ 364 /* throw("The ratio is not acceptable for now!"); */ 365 ratio_scalable = 0; 366 break; 367 } 368 369 switch (vratio * 10 / vscale) { 370 case 8: 371 /* 4-5 Scale in vertical direction */ 372 vert_band_scale = vp8_vertical_band_5_4_scale; 373 source_band_height = 5; 374 dest_band_height = 4; 375 break; 376 case 6: 377 /* 3-5 Scale in vertical direction */ 378 vert_band_scale = vp8_vertical_band_5_3_scale; 379 source_band_height = 5; 380 dest_band_height = 3; 381 break; 382 case 5: 383 /* 1-2 Scale in vertical direction */ 384 385 if (interlaced) { 386 /* if the content is interlaced, point sampling is used */ 387 vert_band_scale = vp8_vertical_band_2_1_scale; 388 } else { 389 390 interpolation = 1; 391 /* if the content is progressive, interplo */ 392 vert_band_scale = vp8_vertical_band_2_1_scale_i; 393 394 } 395 396 source_band_height = 2; 397 dest_band_height = 1; 398 break; 399 default: 400 /* The ratio is not acceptable now */ 401 /* throw("The ratio is not acceptable for now!"); */ 402 ratio_scalable = 0; 403 break; 404 } 405 406 if (ratio_scalable) { 407 if (source_height == dest_height) { 408 /* for each band of the image */ 409 for (k = 0; k < (int)dest_height; k++) { 410 horiz_line_scale(source, source_width, dest, dest_width); 411 source += source_pitch; 412 dest += dest_pitch; 413 } 414 415 return; 416 } 417 418 if (interpolation) { 419 if (source < source_base) 420 source = source_base; 421 422 horiz_line_scale(source, source_width, temp_area, dest_width); 423 } 424 425 for (k = 0; k < (int)(dest_height + dest_band_height - 1) / dest_band_height; k++) { 426 /* scale one band horizontally */ 427 for (i = 0; i < source_band_height; i++) { 428 /* Trap case where we could read off the base of the source buffer */ 429 430 line_src = (unsigned char *)source + i * source_pitch; 431 432 if (line_src < source_base) 433 line_src = source_base; 434 435 horiz_line_scale(line_src, source_width, 436 temp_area + (i + 1)*dest_pitch, dest_width); 437 } 438 439 /* Vertical scaling is in place */ 440 vert_band_scale(temp_area + dest_pitch, dest_pitch, dest, dest_pitch, dest_width); 441 442 if (interpolation) 443 vpx_memcpy(temp_area, temp_area + source_band_height * dest_pitch, dest_width); 444 445 /* Next band... */ 446 source += (unsigned long) source_band_height * source_pitch; 447 dest += (unsigned long) dest_band_height * dest_pitch; 448 } 449 450 return; 451 } 452 453 if (hscale == 2 && hratio == 1) 454 Scale1Dh = scale1d_2t1_ps; 455 456 if (vscale == 2 && vratio == 1) { 457 if (interlaced) 458 Scale1Dv = scale1d_2t1_ps; 459 else 460 Scale1Dv = scale1d_2t1_i; 461 } 462 463 if (source_height == dest_height) { 464 /* for each band of the image */ 465 for (k = 0; k < (int)dest_height; k++) { 466 Scale1Dh(source, 1, hscale, source_width + 1, dest, 1, hratio, dest_width); 467 source += source_pitch; 468 dest += dest_pitch; 469 } 470 471 return; 472 } 473 474 if (dest_height > source_height) { 475 dest_band_height = temp_area_height - 1; 476 source_band_height = dest_band_height * source_height / dest_height; 477 } else { 478 source_band_height = temp_area_height - 1; 479 dest_band_height = source_band_height * vratio / vscale; 480 } 481 482 /* first row needs to be done so that we can stay one row ahead for vertical zoom */ 483 Scale1Dh(source, 1, hscale, source_width + 1, temp_area, 1, hratio, dest_width); 484 485 /* for each band of the image */ 486 bands = (dest_height + dest_band_height - 1) / dest_band_height; 487 488 for (k = 0; k < bands; k++) { 489 /* scale one band horizontally */ 490 for (i = 1; i < source_band_height + 1; i++) { 491 if (k * source_band_height + i < (int) source_height) { 492 Scale1Dh(source + i * source_pitch, 1, hscale, source_width + 1, 493 temp_area + i * dest_pitch, 1, hratio, dest_width); 494 } else { /* Duplicate the last row */ 495 /* copy temp_area row 0 over from last row in the past */ 496 duck_memcpy(temp_area + i * dest_pitch, temp_area + (i - 1)*dest_pitch, dest_pitch); 497 } 498 } 499 500 /* scale one band vertically */ 501 for (j = 0; j < (int)dest_width; j++) { 502 Scale1Dv(&temp_area[j], dest_pitch, vscale, source_band_height + 1, 503 &dest[j], dest_pitch, vratio, dest_band_height); 504 } 505 506 /* copy temp_area row 0 over from last row in the past */ 507 duck_memcpy(temp_area, temp_area + source_band_height * dest_pitch, dest_pitch); 508 509 /* move to the next band */ 510 source += source_band_height * source_pitch; 511 dest += dest_band_height * dest_pitch; 512 } 513 } 514 515 /**************************************************************************** 516 * 517 * ROUTINE : 518 * 519 * INPUTS : YV12_BUFFER_CONFIG *src : Pointer to frame to be scaled. 520 * YV12_BUFFER_CONFIG *dst : Pointer to buffer to hold scaled frame. 521 * unsigned char *temp_area : Pointer to temp work area. 522 * unsigned char temp_area_height : Height of temp work area. 523 * unsigned int hscale : Horizontal scale factor numerator. 524 * unsigned int hratio : Horizontal scale factor denominator. 525 * unsigned int vscale : Vertical scale factor numerator. 526 * unsigned int vratio : Vertical scale factor denominator. 527 * unsigned int interlaced : Interlace flag. 528 * 529 * OUTPUTS : None. 530 * 531 * RETURNS : void 532 * 533 * FUNCTION : Performs 2-tap linear interpolation in two dimensions. 534 * 535 * SPECIAL NOTES : Expansion is performed one band at a time to help with 536 * caching. 537 * 538 ****************************************************************************/ 539 void vp8_scale_frame 540 ( 541 YV12_BUFFER_CONFIG *src, 542 YV12_BUFFER_CONFIG *dst, 543 unsigned char *temp_area, 544 unsigned char temp_height, 545 unsigned int hscale, 546 unsigned int hratio, 547 unsigned int vscale, 548 unsigned int vratio, 549 unsigned int interlaced 550 ) { 551 int i; 552 int dw = (hscale - 1 + src->y_width * hratio) / hscale; 553 int dh = (vscale - 1 + src->y_height * vratio) / vscale; 554 555 /* call our internal scaling routines!! */ 556 Scale2D((unsigned char *) src->y_buffer, src->y_stride, src->y_width, src->y_height, 557 (unsigned char *) dst->y_buffer, dst->y_stride, dw, dh, 558 temp_area, temp_height, hscale, hratio, vscale, vratio, interlaced); 559 560 if (dw < (int)dst->y_width) 561 for (i = 0; i < dh; i++) 562 duck_memset(dst->y_buffer + i * dst->y_stride + dw - 1, dst->y_buffer[i * dst->y_stride + dw - 2], dst->y_width - dw + 1); 563 564 if (dh < (int)dst->y_height) 565 for (i = dh - 1; i < (int)dst->y_height; i++) 566 duck_memcpy(dst->y_buffer + i * dst->y_stride, dst->y_buffer + (dh - 2) * dst->y_stride, dst->y_width + 1); 567 568 Scale2D((unsigned char *) src->u_buffer, src->uv_stride, src->uv_width, src->uv_height, 569 (unsigned char *) dst->u_buffer, dst->uv_stride, dw / 2, dh / 2, 570 temp_area, temp_height, hscale, hratio, vscale, vratio, interlaced); 571 572 if (dw / 2 < (int)dst->uv_width) 573 for (i = 0; i < dst->uv_height; i++) 574 duck_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); 575 576 if (dh / 2 < (int)dst->uv_height) 577 for (i = dh / 2 - 1; i < (int)dst->y_height / 2; i++) 578 duck_memcpy(dst->u_buffer + i * dst->uv_stride, dst->u_buffer + (dh / 2 - 2)*dst->uv_stride, dst->uv_width); 579 580 Scale2D((unsigned char *) src->v_buffer, src->uv_stride, src->uv_width, src->uv_height, 581 (unsigned char *) dst->v_buffer, dst->uv_stride, dw / 2, dh / 2, 582 temp_area, temp_height, hscale, hratio, vscale, vratio, interlaced); 583 584 if (dw / 2 < (int)dst->uv_width) 585 for (i = 0; i < dst->uv_height; i++) 586 duck_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); 587 588 if (dh / 2 < (int) dst->uv_height) 589 for (i = dh / 2 - 1; i < (int)dst->y_height / 2; i++) 590 duck_memcpy(dst->v_buffer + i * dst->uv_stride, dst->v_buffer + (dh / 2 - 2)*dst->uv_stride, dst->uv_width); 591 } 592 /**************************************************************************** 593 * 594 * ROUTINE : any_ratio_2d_scale 595 * 596 * INPUTS : SCALE_INSTANCE *si : Pointer to post-processor instance (NOT USED). 597 * const unsigned char *source : Pointer to source image. 598 * unsigned int source_pitch : Stride of source image. 599 * unsigned int source_width : Width of source image. 600 * unsigned int source_height : Height of source image (NOT USED). 601 * unsigned char *dest : Pointer to destination image. 602 * unsigned int dest_pitch : Stride of destination image. 603 * unsigned int dest_width : Width of destination image. 604 * unsigned int dest_height : Height of destination image. 605 * 606 * OUTPUTS : None. 607 * 608 * RETURNS : int: 1 if image scaled, 0 if image could not be scaled. 609 * 610 * FUNCTION : Scale the image with changing apect ratio. 611 * 612 * SPECIAL NOTES : This scaling is a bi-linear scaling. Need to re-work the 613 * whole function for new scaling algorithm. 614 * 615 ****************************************************************************/ 616 static 617 int any_ratio_2d_scale 618 ( 619 SCALE_VARS *si, 620 const unsigned char *source, 621 int source_pitch, 622 unsigned int source_width, 623 unsigned int source_height, 624 unsigned char *dest, 625 unsigned int dest_pitch, 626 unsigned int dest_width, 627 unsigned int dest_height 628 ) { 629 unsigned int i, k; 630 unsigned int src_band_height = 0; 631 unsigned int dest_band_height = 0; 632 633 /* suggested scale factors */ 634 int hs = si->HScale; 635 int hr = si->HRatio; 636 int vs = si->VScale; 637 int vr = si->VRatio; 638 639 /* assume the ratios are scalable instead of should be centered */ 640 int ratio_scalable = 1; 641 642 const unsigned char *source_base = ((source_pitch >= 0) ? source : (source + ((source_height - 1) * source_pitch))); 643 const unsigned char *line_src; 644 645 void (*horiz_line_scale)(const unsigned char *, unsigned int, unsigned char *, unsigned int) = NULL; 646 void (*vert_band_scale)(unsigned char *, unsigned int, unsigned int) = NULL; 647 void (*last_vert_band_scale)(unsigned char *, unsigned int, unsigned int) = NULL; 648 649 (void) si; 650 651 /* find out the ratio for each direction */ 652 switch (hr * 30 / hs) { 653 case 24: 654 /* 4-5 Scale in Width direction */ 655 horiz_line_scale = vp8_horizontal_line_4_5_scale; 656 break; 657 case 22: 658 /* 3-4 Scale in Width direction */ 659 horiz_line_scale = vp8_horizontal_line_3_4_scale; 660 break; 661 662 case 20: 663 /* 4-5 Scale in Width direction */ 664 horiz_line_scale = vp8_horizontal_line_2_3_scale; 665 break; 666 case 18: 667 /* 3-5 Scale in Width direction */ 668 horiz_line_scale = vp8_horizontal_line_3_5_scale; 669 break; 670 case 15: 671 /* 1-2 Scale in Width direction */ 672 horiz_line_scale = vp8_horizontal_line_1_2_scale; 673 break; 674 case 30: 675 /* no scale in Width direction */ 676 horiz_line_scale = horizontal_line_copy; 677 break; 678 default: 679 /* The ratio is not acceptable now */ 680 /* throw("The ratio is not acceptable for now!"); */ 681 ratio_scalable = 0; 682 break; 683 } 684 685 switch (vr * 30 / vs) { 686 case 24: 687 /* 4-5 Scale in vertical direction */ 688 vert_band_scale = vp8_vertical_band_4_5_scale; 689 last_vert_band_scale = vp8_last_vertical_band_4_5_scale; 690 src_band_height = 4; 691 dest_band_height = 5; 692 break; 693 case 22: 694 /* 3-4 Scale in vertical direction */ 695 vert_band_scale = vp8_vertical_band_3_4_scale; 696 last_vert_band_scale = vp8_last_vertical_band_3_4_scale; 697 src_band_height = 3; 698 dest_band_height = 4; 699 break; 700 case 20: 701 /* 2-3 Scale in vertical direction */ 702 vert_band_scale = vp8_vertical_band_2_3_scale; 703 last_vert_band_scale = vp8_last_vertical_band_2_3_scale; 704 src_band_height = 2; 705 dest_band_height = 3; 706 break; 707 case 18: 708 /* 3-5 Scale in vertical direction */ 709 vert_band_scale = vp8_vertical_band_3_5_scale; 710 last_vert_band_scale = vp8_last_vertical_band_3_5_scale; 711 src_band_height = 3; 712 dest_band_height = 5; 713 break; 714 case 15: 715 /* 1-2 Scale in vertical direction */ 716 vert_band_scale = vp8_vertical_band_1_2_scale; 717 last_vert_band_scale = vp8_last_vertical_band_1_2_scale; 718 src_band_height = 1; 719 dest_band_height = 2; 720 break; 721 case 30: 722 /* no scale in Width direction */ 723 vert_band_scale = null_scale; 724 last_vert_band_scale = null_scale; 725 src_band_height = 4; 726 dest_band_height = 4; 727 break; 728 default: 729 /* The ratio is not acceptable now */ 730 /* throw("The ratio is not acceptable for now!"); */ 731 ratio_scalable = 0; 732 break; 733 } 734 735 if (ratio_scalable == 0) 736 return ratio_scalable; 737 738 horiz_line_scale(source, source_width, dest, dest_width); 739 740 /* except last band */ 741 for (k = 0; k < (dest_height + dest_band_height - 1) / dest_band_height - 1; k++) { 742 /* scale one band horizontally */ 743 for (i = 1; i < src_band_height; i++) { 744 /* Trap case where we could read off the base of the source buffer */ 745 line_src = source + i * source_pitch; 746 747 if (line_src < source_base) 748 line_src = source_base; 749 750 horiz_line_scale(line_src, source_width, 751 dest + i * dest_pitch, dest_width); 752 } 753 754 /* first line of next band */ 755 /* Trap case where we could read off the base of the source buffer */ 756 line_src = source + src_band_height * source_pitch; 757 758 if (line_src < source_base) 759 line_src = source_base; 760 761 horiz_line_scale(line_src, source_width, 762 dest + dest_band_height * dest_pitch, 763 dest_width); 764 765 /* Vertical scaling is in place */ 766 vert_band_scale(dest, dest_pitch, dest_width); 767 768 /* Next band... */ 769 source += src_band_height * source_pitch; 770 dest += dest_band_height * dest_pitch; 771 } 772 773 /* scale one band horizontally */ 774 for (i = 1; i < src_band_height; i++) { 775 /* Trap case where we could read off the base of the source buffer */ 776 line_src = source + i * source_pitch; 777 778 if (line_src < source_base) 779 line_src = source_base; 780 781 horiz_line_scale(line_src, source_width, 782 dest + i * dest_pitch, 783 dest_width); 784 } 785 786 /* Vertical scaling is in place */ 787 last_vert_band_scale(dest, dest_pitch, dest_width); 788 789 return ratio_scalable; 790 } 791 792 /**************************************************************************** 793 * 794 * ROUTINE : any_ratio_frame_scale 795 * 796 * INPUTS : SCALE_INSTANCE *si : Pointer to post-processor instance (NOT USED). 797 * unsigned char *frame_buffer : Pointer to source image. 798 * int YOffset : Offset from start of buffer to Y samples. 799 * int UVOffset : Offset from start of buffer to UV samples. 800 * 801 * OUTPUTS : None. 802 * 803 * RETURNS : int: 1 if image scaled, 0 if image could not be scaled. 804 * 805 * FUNCTION : Scale the image with changing apect ratio. 806 * 807 * SPECIAL NOTES : None. 808 * 809 ****************************************************************************/ 810 static 811 int any_ratio_frame_scale(SCALE_VARS *scale_vars, int YOffset, int UVOffset) { 812 int i; 813 int ew; 814 int eh; 815 816 /* suggested scale factors */ 817 int hs = scale_vars->HScale; 818 int hr = scale_vars->HRatio; 819 int vs = scale_vars->VScale; 820 int vr = scale_vars->VRatio; 821 822 int ratio_scalable = 1; 823 824 int sw = (scale_vars->expanded_frame_width * hr + hs - 1) / hs; 825 int sh = (scale_vars->expanded_frame_height * vr + vs - 1) / vs; 826 int dw = scale_vars->expanded_frame_width; 827 int dh = scale_vars->expanded_frame_height; 828 YV12_BUFFER_CONFIG *src_yuv_config = scale_vars->src_yuv_config; 829 YV12_BUFFER_CONFIG *dst_yuv_config = scale_vars->dst_yuv_config; 830 831 if (hr == 3) 832 ew = (sw + 2) / 3 * 3 * hs / hr; 833 else 834 ew = (sw + 7) / 8 * 8 * hs / hr; 835 836 if (vr == 3) 837 eh = (sh + 2) / 3 * 3 * vs / vr; 838 else 839 eh = (sh + 7) / 8 * 8 * vs / vr; 840 841 ratio_scalable = any_ratio_2d_scale(scale_vars, 842 (const unsigned char *)src_yuv_config->y_buffer, 843 src_yuv_config->y_stride, sw, sh, 844 (unsigned char *) dst_yuv_config->y_buffer + YOffset, 845 dst_yuv_config->y_stride, dw, dh); 846 847 for (i = 0; i < eh; i++) 848 duck_memset(dst_yuv_config->y_buffer + YOffset + i * dst_yuv_config->y_stride + dw, 0, ew - dw); 849 850 for (i = dh; i < eh; i++) 851 duck_memset(dst_yuv_config->y_buffer + YOffset + i * dst_yuv_config->y_stride, 0, ew); 852 853 if (ratio_scalable == 0) 854 return ratio_scalable; 855 856 sw = (sw + 1) >> 1; 857 sh = (sh + 1) >> 1; 858 dw = (dw + 1) >> 1; 859 dh = (dh + 1) >> 1; 860 861 any_ratio_2d_scale(scale_vars, 862 (const unsigned char *)src_yuv_config->u_buffer, 863 src_yuv_config->y_stride / 2, sw, sh, 864 (unsigned char *)dst_yuv_config->u_buffer + UVOffset, 865 dst_yuv_config->uv_stride, dw, dh); 866 867 any_ratio_2d_scale(scale_vars, 868 (const unsigned char *)src_yuv_config->v_buffer, 869 src_yuv_config->y_stride / 2, sw, sh, 870 (unsigned char *)dst_yuv_config->v_buffer + UVOffset, 871 dst_yuv_config->uv_stride, dw, dh); 872 873 return ratio_scalable; 874 } 875 876 /**************************************************************************** 877 * 878 * ROUTINE : center_image 879 * 880 * INPUTS : SCALE_INSTANCE *si : Pointer to post-processor instance. 881 * 882 * OUTPUTS : None. 883 * 884 * RETURNS : void 885 * 886 * FUNCTION : Centers the image without scaling in the output buffer. 887 * 888 * SPECIAL NOTES : None. 889 * 890 ****************************************************************************/ 891 static void 892 center_image(YV12_BUFFER_CONFIG *src_yuv_config, YV12_BUFFER_CONFIG *dst_yuv_config) { 893 int i; 894 int row_offset, col_offset; 895 unsigned char *src_data_pointer; 896 unsigned char *dst_data_pointer; 897 898 /* center values */ 899 row_offset = (dst_yuv_config->y_height - src_yuv_config->y_height) / 2; 900 col_offset = (dst_yuv_config->y_width - src_yuv_config->y_width) / 2; 901 902 /* Y's */ 903 src_data_pointer = src_yuv_config->y_buffer; 904 dst_data_pointer = (unsigned char *)dst_yuv_config->y_buffer + (row_offset * dst_yuv_config->y_stride) + col_offset; 905 906 for (i = 0; i < src_yuv_config->y_height; i++) { 907 duck_memcpy(dst_data_pointer, src_data_pointer, src_yuv_config->y_width); 908 dst_data_pointer += dst_yuv_config->y_stride; 909 src_data_pointer += src_yuv_config->y_stride; 910 } 911 912 row_offset /= 2; 913 col_offset /= 2; 914 915 /* U's */ 916 src_data_pointer = src_yuv_config->u_buffer; 917 dst_data_pointer = (unsigned char *)dst_yuv_config->u_buffer + (row_offset * dst_yuv_config->uv_stride) + col_offset; 918 919 for (i = 0; i < src_yuv_config->uv_height; i++) { 920 duck_memcpy(dst_data_pointer, src_data_pointer, src_yuv_config->uv_width); 921 dst_data_pointer += dst_yuv_config->uv_stride; 922 src_data_pointer += src_yuv_config->uv_stride; 923 } 924 925 /* V's */ 926 src_data_pointer = src_yuv_config->v_buffer; 927 dst_data_pointer = (unsigned char *)dst_yuv_config->v_buffer + (row_offset * dst_yuv_config->uv_stride) + col_offset; 928 929 for (i = 0; i < src_yuv_config->uv_height; i++) { 930 duck_memcpy(dst_data_pointer, src_data_pointer, src_yuv_config->uv_width); 931 dst_data_pointer += dst_yuv_config->uv_stride; 932 src_data_pointer += src_yuv_config->uv_stride; 933 } 934 } 935 936 /**************************************************************************** 937 * 938 * ROUTINE : scale_or_center 939 * 940 * INPUTS : SCALE_INSTANCE *si : Pointer to post-processor instance. 941 * 942 * 943 * 944 * OUTPUTS : None. 945 * 946 * RETURNS : void 947 * 948 * FUNCTION : Decides to scale or center image in scale buffer for blit 949 * 950 * SPECIAL NOTES : None. 951 * 952 ****************************************************************************/ 953 void 954 vp8_yv12_scale_or_center 955 ( 956 YV12_BUFFER_CONFIG *src_yuv_config, 957 YV12_BUFFER_CONFIG *dst_yuv_config, 958 int expanded_frame_width, 959 int expanded_frame_height, 960 int scaling_mode, 961 int HScale, 962 int HRatio, 963 int VScale, 964 int VRatio 965 ) { 966 /*if ( ppi->post_processing_level ) 967 update_umvborder ( ppi, frame_buffer );*/ 968 969 970 switch (scaling_mode) { 971 case SCALE_TO_FIT: 972 case MAINTAIN_ASPECT_RATIO: { 973 SCALE_VARS scale_vars; 974 /* center values */ 975 #if 1 976 int row = (dst_yuv_config->y_height - expanded_frame_height) / 2; 977 int col = (dst_yuv_config->y_width - expanded_frame_width) / 2; 978 /*int YOffset = row * dst_yuv_config->y_width + col; 979 int UVOffset = (row>>1) * dst_yuv_config->uv_width + (col>>1);*/ 980 int YOffset = row * dst_yuv_config->y_stride + col; 981 int UVOffset = (row >> 1) * dst_yuv_config->uv_stride + (col >> 1); 982 #else 983 int row = (src_yuv_config->y_height - expanded_frame_height) / 2; 984 int col = (src_yuv_config->y_width - expanded_frame_width) / 2; 985 int YOffset = row * src_yuv_config->y_width + col; 986 int UVOffset = (row >> 1) * src_yuv_config->uv_width + (col >> 1); 987 #endif 988 989 scale_vars.dst_yuv_config = dst_yuv_config; 990 scale_vars.src_yuv_config = src_yuv_config; 991 scale_vars.HScale = HScale; 992 scale_vars.HRatio = HRatio; 993 scale_vars.VScale = VScale; 994 scale_vars.VRatio = VRatio; 995 scale_vars.expanded_frame_width = expanded_frame_width; 996 scale_vars.expanded_frame_height = expanded_frame_height; 997 998 /* perform center and scale */ 999 any_ratio_frame_scale(&scale_vars, YOffset, UVOffset); 1000 1001 break; 1002 } 1003 case CENTER: 1004 center_image(src_yuv_config, dst_yuv_config); 1005 break; 1006 1007 default: 1008 break; 1009 } 1010 } 1011