Fix encoder range check for frame width and height
[libvpx.git] / vpx_scale / generic / vpxscale.c
blob13c9122f0a9d7a51c0c17a3edce28d75f5ec48bb
1 /*
2 * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
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 */
12 /****************************************************************************
14 * Module Title : scale.c
16 * Description : Image scaling functions.
18 ***************************************************************************/
20 /****************************************************************************
21 * Header Files
22 ****************************************************************************/
23 #include "vpx_mem/vpx_mem.h"
24 #include "vpx_scale/yv12config.h"
25 #include "vpx_scale/scale_mode.h"
27 /****************************************************************************
28 * Exports
29 ****************************************************************************/
30 #ifndef VPX_NO_GLOBALS
31 void (*vp8_vertical_band_4_5_scale)(unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width) = 0;
32 void (*vp8_last_vertical_band_4_5_scale)(unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width) = 0;
33 void (*vp8_vertical_band_2_3_scale)(unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width) = 0;
34 void (*vp8_last_vertical_band_2_3_scale)(unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width) = 0;
35 void (*vp8_vertical_band_3_5_scale)(unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width) = 0;
36 void (*vp8_last_vertical_band_3_5_scale)(unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width) = 0;
37 void (*vp8_vertical_band_3_4_scale)(unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width) = 0;
38 void (*vp8_last_vertical_band_3_4_scale)(unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width) = 0;
39 void (*vp8_horizontal_line_1_2_scale)(const unsigned char *source, unsigned int source_width, unsigned char *dest, unsigned int dest_width) = 0;
40 void (*vp8_horizontal_line_3_5_scale)(const unsigned char *source, unsigned int source_width, unsigned char *dest, unsigned int dest_width) = 0;
41 void (*vp8_horizontal_line_3_4_scale)(const unsigned char *source, unsigned int source_width, unsigned char *dest, unsigned int dest_width) = 0;
42 void (*vp8_horizontal_line_2_3_scale)(const unsigned char *source, unsigned int source_width, unsigned char *dest, unsigned int dest_width) = 0;
43 void (*vp8_horizontal_line_4_5_scale)(const unsigned char *source, unsigned int source_width, unsigned char *dest, unsigned int dest_width) = 0;
44 void (*vp8_vertical_band_1_2_scale)(unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width) = 0;
45 void (*vp8_last_vertical_band_1_2_scale)(unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width) = 0;
47 void (*vp8_vertical_band_5_4_scale)(unsigned char *source, unsigned int src_pitch, unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width) = 0;
48 void (*vp8_vertical_band_5_3_scale)(unsigned char *source, unsigned int src_pitch, unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width) = 0;
49 void (*vp8_vertical_band_2_1_scale)(unsigned char *source, unsigned int src_pitch, unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width) = 0;
50 void (*vp8_vertical_band_2_1_scale_i)(unsigned char *source, unsigned int src_pitch, unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width) = 0;
51 void (*vp8_horizontal_line_2_1_scale)(const unsigned char *source, unsigned int source_width, unsigned char *dest, unsigned int dest_width) = 0;
52 void (*vp8_horizontal_line_5_3_scale)(const unsigned char *source, unsigned int source_width, unsigned char *dest, unsigned int dest_width) = 0;
53 void (*vp8_horizontal_line_5_4_scale)(const unsigned char *source, unsigned int source_width, unsigned char *dest, unsigned int dest_width) = 0;
54 #else
55 # include "vpxscale_nofp.h"
56 #endif
58 typedef struct
60 int expanded_frame_width;
61 int expanded_frame_height;
63 int HScale;
64 int HRatio;
65 int VScale;
66 int VRatio;
68 YV12_BUFFER_CONFIG *src_yuv_config;
69 YV12_BUFFER_CONFIG *dst_yuv_config;
71 } SCALE_VARS;
73 /****************************************************************************
75 * ROUTINE : horizontal_line_copy
77 * INPUTS : None
80 * OUTPUTS : None.
82 * RETURNS : None
84 * FUNCTION : 1 to 1 scaling up for a horizontal line of pixles
86 * SPECIAL NOTES : None.
88 * ERRORS : None.
90 ****************************************************************************/
91 static
92 void horizontal_line_copy(
93 const unsigned char *source,
94 unsigned int source_width,
95 unsigned char *dest,
96 unsigned int dest_width
99 (void) dest_width;
101 duck_memcpy(dest, source, source_width);
103 /****************************************************************************
105 * ROUTINE : null_scale
107 * INPUTS : None
110 * OUTPUTS : None.
112 * RETURNS : None
114 * FUNCTION : 1 to 1 scaling up for a vertical band
116 * SPECIAL NOTES : None.
118 * ERRORS : None.
120 ****************************************************************************/
121 static
122 void null_scale(
123 unsigned char *dest,
124 unsigned int dest_pitch,
125 unsigned int dest_width
128 (void) dest;
129 (void) dest_pitch;
130 (void) dest_width;
132 return;
135 /****************************************************************************
137 * ROUTINE : scale1d_2t1_i
139 * INPUTS : const unsigned char *source : Pointer to data to be scaled.
140 * int source_step : Number of pixels to step on in source.
141 * unsigned int source_scale : Scale for source (UNUSED).
142 * unsigned int source_length : Length of source (UNUSED).
143 * unsigned char *dest : Pointer to output data array.
144 * int dest_step : Number of pixels to step on in destination.
145 * unsigned int dest_scale : Scale for destination (UNUSED).
146 * unsigned int dest_length : Length of destination.
148 * OUTPUTS : None.
150 * RETURNS : void
152 * FUNCTION : Performs 2-to-1 interpolated scaling.
154 * SPECIAL NOTES : None.
156 ****************************************************************************/
157 static
158 void scale1d_2t1_i
160 const unsigned char *source,
161 int source_step,
162 unsigned int source_scale,
163 unsigned int source_length,
164 unsigned char *dest,
165 int dest_step,
166 unsigned int dest_scale,
167 unsigned int dest_length
170 unsigned int i, j;
171 unsigned int temp;
172 int source_pitch = source_step;
173 (void) source_length;
174 (void) source_scale;
175 (void) dest_scale;
177 source_step *= 2;
178 dest[0] = source[0];
180 for (i = dest_step, j = source_step; i < dest_length * dest_step; i += dest_step, j += source_step)
182 temp = 8;
183 temp += 3 * source[j-source_pitch];
184 temp += 10 * source[j];
185 temp += 3 * source[j+source_pitch];
186 temp >>= 4;
187 dest[i] = (char)(temp);
191 /****************************************************************************
193 * ROUTINE : scale1d_2t1_ps
195 * INPUTS : const unsigned char *source : Pointer to data to be scaled.
196 * int source_step : Number of pixels to step on in source.
197 * unsigned int source_scale : Scale for source (UNUSED).
198 * unsigned int source_length : Length of source (UNUSED).
199 * unsigned char *dest : Pointer to output data array.
200 * int dest_step : Number of pixels to step on in destination.
201 * unsigned int dest_scale : Scale for destination (UNUSED).
202 * unsigned int dest_length : Length of destination.
204 * OUTPUTS : None.
206 * RETURNS : void
208 * FUNCTION : Performs 2-to-1 point subsampled scaling.
210 * SPECIAL NOTES : None.
212 ****************************************************************************/
213 static
214 void scale1d_2t1_ps
216 const unsigned char *source,
217 int source_step,
218 unsigned int source_scale,
219 unsigned int source_length,
220 unsigned char *dest,
221 int dest_step,
222 unsigned int dest_scale,
223 unsigned int dest_length
226 unsigned int i, j;
228 (void) source_length;
229 (void) source_scale;
230 (void) dest_scale;
232 source_step *= 2;
233 j = 0;
235 for (i = 0; i < dest_length * dest_step; i += dest_step, j += source_step)
236 dest[i] = source[j];
238 /****************************************************************************
240 * ROUTINE : scale1d_c
242 * INPUTS : const unsigned char *source : Pointer to data to be scaled.
243 * int source_step : Number of pixels to step on in source.
244 * unsigned int source_scale : Scale for source.
245 * unsigned int source_length : Length of source (UNUSED).
246 * unsigned char *dest : Pointer to output data array.
247 * int dest_step : Number of pixels to step on in destination.
248 * unsigned int dest_scale : Scale for destination.
249 * unsigned int dest_length : Length of destination.
251 * OUTPUTS : None.
253 * RETURNS : void
255 * FUNCTION : Performs linear interpolation in one dimension.
257 * SPECIAL NOTES : None.
259 ****************************************************************************/
260 static
261 void scale1d_c
263 const unsigned char *source,
264 int source_step,
265 unsigned int source_scale,
266 unsigned int source_length,
267 unsigned char *dest,
268 int dest_step,
269 unsigned int dest_scale,
270 unsigned int dest_length
273 unsigned int i;
274 unsigned int round_value = dest_scale / 2;
275 unsigned int left_modifier = dest_scale;
276 unsigned int right_modifier = 0;
277 unsigned char left_pixel = *source;
278 unsigned char right_pixel = *(source + source_step);
280 (void) source_length;
282 /* These asserts are needed if there are boundary issues... */
283 /*assert ( dest_scale > source_scale );*/
284 /*assert ( (source_length-1) * dest_scale >= (dest_length-1) * source_scale );*/
286 for (i = 0; i < dest_length * dest_step; i += dest_step)
288 dest[i] = (char)((left_modifier * left_pixel + right_modifier * right_pixel + round_value) / dest_scale);
290 right_modifier += source_scale;
292 while (right_modifier > dest_scale)
294 right_modifier -= dest_scale;
295 source += source_step;
296 left_pixel = *source;
297 right_pixel = *(source + source_step);
300 left_modifier = dest_scale - right_modifier;
304 /****************************************************************************
306 * ROUTINE : Scale2D
308 * INPUTS : const unsigned char *source : Pointer to data to be scaled.
309 * int source_pitch : Stride of source image.
310 * unsigned int source_width : Width of input image.
311 * unsigned int source_height : Height of input image.
312 * unsigned char *dest : Pointer to output data array.
313 * int dest_pitch : Stride of destination image.
314 * unsigned int dest_width : Width of destination image.
315 * unsigned int dest_height : Height of destination image.
316 * unsigned char *temp_area : Pointer to temp work area.
317 * unsigned char temp_area_height : Height of temp work area.
318 * unsigned int hscale : Horizontal scale factor numerator.
319 * unsigned int hratio : Horizontal scale factor denominator.
320 * unsigned int vscale : Vertical scale factor numerator.
321 * unsigned int vratio : Vertical scale factor denominator.
322 * unsigned int interlaced : Interlace flag.
324 * OUTPUTS : None.
326 * RETURNS : void
328 * FUNCTION : Performs 2-tap linear interpolation in two dimensions.
330 * SPECIAL NOTES : Expansion is performed one band at a time to help with
331 * caching.
333 ****************************************************************************/
334 static
335 void Scale2D
337 /*const*/
338 unsigned char *source,
339 int source_pitch,
340 unsigned int source_width,
341 unsigned int source_height,
342 unsigned char *dest,
343 int dest_pitch,
344 unsigned int dest_width,
345 unsigned int dest_height,
346 unsigned char *temp_area,
347 unsigned char temp_area_height,
348 unsigned int hscale,
349 unsigned int hratio,
350 unsigned int vscale,
351 unsigned int vratio,
352 unsigned int interlaced
355 /*unsigned*/
356 int i, j, k;
357 int bands;
358 int dest_band_height;
359 int source_band_height;
361 typedef void (*Scale1D)(const unsigned char * source, int source_step, unsigned int source_scale, unsigned int source_length,
362 unsigned char * dest, int dest_step, unsigned int dest_scale, unsigned int dest_length);
364 Scale1D Scale1Dv = scale1d_c;
365 Scale1D Scale1Dh = scale1d_c;
367 void (*horiz_line_scale)(const unsigned char *, unsigned int, unsigned char *, unsigned int) = NULL;
368 void (*vert_band_scale)(unsigned char *, unsigned int, unsigned char *, unsigned int, unsigned int) = NULL;
370 int ratio_scalable = 1;
371 int interpolation = 0;
373 unsigned char *source_base; /* = (unsigned char *) ((source_pitch >= 0) ? source : (source + ((source_height-1) * source_pitch))); */
374 unsigned char *line_src;
377 source_base = (unsigned char *)source;
379 if (source_pitch < 0)
381 int offset;
383 offset = (source_height - 1);
384 offset *= source_pitch;
386 source_base += offset;
389 /* find out the ratio for each direction */
390 switch (hratio * 10 / hscale)
392 case 8:
393 /* 4-5 Scale in Width direction */
394 horiz_line_scale = vp8_horizontal_line_5_4_scale;
395 break;
396 case 6:
397 /* 3-5 Scale in Width direction */
398 horiz_line_scale = vp8_horizontal_line_5_3_scale;
399 break;
400 case 5:
401 /* 1-2 Scale in Width direction */
402 horiz_line_scale = vp8_horizontal_line_2_1_scale;
403 break;
404 default:
405 /* The ratio is not acceptable now */
406 /* throw("The ratio is not acceptable for now!"); */
407 ratio_scalable = 0;
408 break;
411 switch (vratio * 10 / vscale)
413 case 8:
414 /* 4-5 Scale in vertical direction */
415 vert_band_scale = vp8_vertical_band_5_4_scale;
416 source_band_height = 5;
417 dest_band_height = 4;
418 break;
419 case 6:
420 /* 3-5 Scale in vertical direction */
421 vert_band_scale = vp8_vertical_band_5_3_scale;
422 source_band_height = 5;
423 dest_band_height = 3;
424 break;
425 case 5:
426 /* 1-2 Scale in vertical direction */
428 if (interlaced)
430 /* if the content is interlaced, point sampling is used */
431 vert_band_scale = vp8_vertical_band_2_1_scale;
433 else
436 interpolation = 1;
437 /* if the content is progressive, interplo */
438 vert_band_scale = vp8_vertical_band_2_1_scale_i;
442 source_band_height = 2;
443 dest_band_height = 1;
444 break;
445 default:
446 /* The ratio is not acceptable now */
447 /* throw("The ratio is not acceptable for now!"); */
448 ratio_scalable = 0;
449 break;
452 if (ratio_scalable)
454 if (source_height == dest_height)
456 /* for each band of the image */
457 for (k = 0; k < (int)dest_height; k++)
459 horiz_line_scale(source, source_width, dest, dest_width);
460 source += source_pitch;
461 dest += dest_pitch;
464 return;
467 if (interpolation)
469 if (source < source_base)
470 source = source_base;
472 horiz_line_scale(source, source_width, temp_area, dest_width);
475 for (k = 0; k < (int)(dest_height + dest_band_height - 1) / dest_band_height; k++)
477 /* scale one band horizontally */
478 for (i = 0; i < source_band_height; i++)
480 /* Trap case where we could read off the base of the source buffer */
482 line_src = (unsigned char *)source + i * source_pitch;
484 if (line_src < source_base)
485 line_src = source_base;
487 horiz_line_scale(line_src, source_width,
488 temp_area + (i + 1)*dest_pitch, dest_width);
491 /* Vertical scaling is in place */
492 vert_band_scale(temp_area + dest_pitch, dest_pitch, dest, dest_pitch, dest_width);
494 if (interpolation)
495 vpx_memcpy(temp_area, temp_area + source_band_height * dest_pitch, dest_width);
497 /* Next band... */
498 source += (unsigned long) source_band_height * source_pitch;
499 dest += (unsigned long) dest_band_height * dest_pitch;
502 return;
505 if (hscale == 2 && hratio == 1)
506 Scale1Dh = scale1d_2t1_ps;
508 if (vscale == 2 && vratio == 1)
510 if (interlaced)
511 Scale1Dv = scale1d_2t1_ps;
512 else
513 Scale1Dv = scale1d_2t1_i;
516 if (source_height == dest_height)
518 /* for each band of the image */
519 for (k = 0; k < (int)dest_height; k++)
521 Scale1Dh(source, 1, hscale, source_width + 1, dest, 1, hratio, dest_width);
522 source += source_pitch;
523 dest += dest_pitch;
526 return;
529 if (dest_height > source_height)
531 dest_band_height = temp_area_height - 1;
532 source_band_height = dest_band_height * source_height / dest_height;
534 else
536 source_band_height = temp_area_height - 1;
537 dest_band_height = source_band_height * vratio / vscale;
540 /* first row needs to be done so that we can stay one row ahead for vertical zoom */
541 Scale1Dh(source, 1, hscale, source_width + 1, temp_area, 1, hratio, dest_width);
543 /* for each band of the image */
544 bands = (dest_height + dest_band_height - 1) / dest_band_height;
546 for (k = 0; k < bands; k++)
548 /* scale one band horizontally */
549 for (i = 1; i < source_band_height + 1; i++)
551 if (k * source_band_height + i < (int) source_height)
553 Scale1Dh(source + i * source_pitch, 1, hscale, source_width + 1,
554 temp_area + i * dest_pitch, 1, hratio, dest_width);
556 else /* Duplicate the last row */
558 /* copy temp_area row 0 over from last row in the past */
559 duck_memcpy(temp_area + i * dest_pitch, temp_area + (i - 1)*dest_pitch, dest_pitch);
563 /* scale one band vertically */
564 for (j = 0; j < (int)dest_width; j++)
566 Scale1Dv(&temp_area[j], dest_pitch, vscale, source_band_height + 1,
567 &dest[j], dest_pitch, vratio, dest_band_height);
570 /* copy temp_area row 0 over from last row in the past */
571 duck_memcpy(temp_area, temp_area + source_band_height * dest_pitch, dest_pitch);
573 /* move to the next band */
574 source += source_band_height * source_pitch;
575 dest += dest_band_height * dest_pitch;
579 /****************************************************************************
581 * ROUTINE :
583 * INPUTS : YV12_BUFFER_CONFIG *src : Pointer to frame to be scaled.
584 * YV12_BUFFER_CONFIG *dst : Pointer to buffer to hold scaled frame.
585 * unsigned char *temp_area : Pointer to temp work area.
586 * unsigned char temp_area_height : Height of temp work area.
587 * unsigned int hscale : Horizontal scale factor numerator.
588 * unsigned int hratio : Horizontal scale factor denominator.
589 * unsigned int vscale : Vertical scale factor numerator.
590 * unsigned int vratio : Vertical scale factor denominator.
591 * unsigned int interlaced : Interlace flag.
593 * OUTPUTS : None.
595 * RETURNS : void
597 * FUNCTION : Performs 2-tap linear interpolation in two dimensions.
599 * SPECIAL NOTES : Expansion is performed one band at a time to help with
600 * caching.
602 ****************************************************************************/
603 void vp8_scale_frame
605 YV12_BUFFER_CONFIG *src,
606 YV12_BUFFER_CONFIG *dst,
607 unsigned char *temp_area,
608 unsigned char temp_height,
609 unsigned int hscale,
610 unsigned int hratio,
611 unsigned int vscale,
612 unsigned int vratio,
613 unsigned int interlaced
616 int i;
617 int dw = (hscale - 1 + src->y_width * hratio) / hscale;
618 int dh = (vscale - 1 + src->y_height * vratio) / vscale;
620 /* call our internal scaling routines!! */
621 Scale2D((unsigned char *) src->y_buffer, src->y_stride, src->y_width, src->y_height,
622 (unsigned char *) dst->y_buffer, dst->y_stride, dw, dh,
623 temp_area, temp_height, hscale, hratio, vscale, vratio, interlaced);
625 if (dw < (int)dst->y_width)
626 for (i = 0; i < dh; i++)
627 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);
629 if (dh < (int)dst->y_height)
630 for (i = dh - 1; i < (int)dst->y_height; i++)
631 duck_memcpy(dst->y_buffer + i * dst->y_stride, dst->y_buffer + (dh - 2) * dst->y_stride, dst->y_width + 1);
633 Scale2D((unsigned char *) src->u_buffer, src->uv_stride, src->uv_width, src->uv_height,
634 (unsigned char *) dst->u_buffer, dst->uv_stride, dw / 2, dh / 2,
635 temp_area, temp_height, hscale, hratio, vscale, vratio, interlaced);
637 if (dw / 2 < (int)dst->uv_width)
638 for (i = 0; i < dst->uv_height; i++)
639 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);
641 if (dh / 2 < (int)dst->uv_height)
642 for (i = dh / 2 - 1; i < (int)dst->y_height / 2; i++)
643 duck_memcpy(dst->u_buffer + i * dst->uv_stride, dst->u_buffer + (dh / 2 - 2)*dst->uv_stride, dst->uv_width);
645 Scale2D((unsigned char *) src->v_buffer, src->uv_stride, src->uv_width, src->uv_height,
646 (unsigned char *) dst->v_buffer, dst->uv_stride, dw / 2, dh / 2,
647 temp_area, temp_height, hscale, hratio, vscale, vratio, interlaced);
649 if (dw / 2 < (int)dst->uv_width)
650 for (i = 0; i < dst->uv_height; i++)
651 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);
653 if (dh / 2 < (int) dst->uv_height)
654 for (i = dh / 2 - 1; i < (int)dst->y_height / 2; i++)
655 duck_memcpy(dst->v_buffer + i * dst->uv_stride, dst->v_buffer + (dh / 2 - 2)*dst->uv_stride, dst->uv_width);
657 /****************************************************************************
659 * ROUTINE : any_ratio_2d_scale
661 * INPUTS : SCALE_INSTANCE *si : Pointer to post-processor instance (NOT USED).
662 * const unsigned char *source : Pointer to source image.
663 * unsigned int source_pitch : Stride of source image.
664 * unsigned int source_width : Width of source image.
665 * unsigned int source_height : Height of source image (NOT USED).
666 * unsigned char *dest : Pointer to destination image.
667 * unsigned int dest_pitch : Stride of destination image.
668 * unsigned int dest_width : Width of destination image.
669 * unsigned int dest_height : Height of destination image.
671 * OUTPUTS : None.
673 * RETURNS : int: 1 if image scaled, 0 if image could not be scaled.
675 * FUNCTION : Scale the image with changing apect ratio.
677 * SPECIAL NOTES : This scaling is a bi-linear scaling. Need to re-work the
678 * whole function for new scaling algorithm.
680 ****************************************************************************/
681 static
682 int any_ratio_2d_scale
684 SCALE_VARS *si,
685 const unsigned char *source,
686 int source_pitch,
687 unsigned int source_width,
688 unsigned int source_height,
689 unsigned char *dest,
690 unsigned int dest_pitch,
691 unsigned int dest_width,
692 unsigned int dest_height
695 unsigned int i, k;
696 unsigned int src_band_height = 0;
697 unsigned int dest_band_height = 0;
699 /* suggested scale factors */
700 int hs = si->HScale;
701 int hr = si->HRatio;
702 int vs = si->VScale;
703 int vr = si->VRatio;
705 /* assume the ratios are scalable instead of should be centered */
706 int ratio_scalable = 1;
708 const unsigned char *source_base = ((source_pitch >= 0) ? source : (source + ((source_height - 1) * source_pitch)));
709 const unsigned char *line_src;
711 void (*horiz_line_scale)(const unsigned char *, unsigned int, unsigned char *, unsigned int) = NULL;
712 void (*vert_band_scale)(unsigned char *, unsigned int, unsigned int) = NULL;
713 void (*last_vert_band_scale)(unsigned char *, unsigned int, unsigned int) = NULL;
715 (void) si;
717 /* find out the ratio for each direction */
718 switch (hr * 30 / hs)
720 case 24:
721 /* 4-5 Scale in Width direction */
722 horiz_line_scale = vp8_horizontal_line_4_5_scale;
723 break;
724 case 22:
725 /* 3-4 Scale in Width direction */
726 horiz_line_scale = vp8_horizontal_line_3_4_scale;
727 break;
729 case 20:
730 /* 4-5 Scale in Width direction */
731 horiz_line_scale = vp8_horizontal_line_2_3_scale;
732 break;
733 case 18:
734 /* 3-5 Scale in Width direction */
735 horiz_line_scale = vp8_horizontal_line_3_5_scale;
736 break;
737 case 15:
738 /* 1-2 Scale in Width direction */
739 horiz_line_scale = vp8_horizontal_line_1_2_scale;
740 break;
741 case 30:
742 /* no scale in Width direction */
743 horiz_line_scale = horizontal_line_copy;
744 break;
745 default:
746 /* The ratio is not acceptable now */
747 /* throw("The ratio is not acceptable for now!"); */
748 ratio_scalable = 0;
749 break;
752 switch (vr * 30 / vs)
754 case 24:
755 /* 4-5 Scale in vertical direction */
756 vert_band_scale = vp8_vertical_band_4_5_scale;
757 last_vert_band_scale = vp8_last_vertical_band_4_5_scale;
758 src_band_height = 4;
759 dest_band_height = 5;
760 break;
761 case 22:
762 /* 3-4 Scale in vertical direction */
763 vert_band_scale = vp8_vertical_band_3_4_scale;
764 last_vert_band_scale = vp8_last_vertical_band_3_4_scale;
765 src_band_height = 3;
766 dest_band_height = 4;
767 break;
768 case 20:
769 /* 2-3 Scale in vertical direction */
770 vert_band_scale = vp8_vertical_band_2_3_scale;
771 last_vert_band_scale = vp8_last_vertical_band_2_3_scale;
772 src_band_height = 2;
773 dest_band_height = 3;
774 break;
775 case 18:
776 /* 3-5 Scale in vertical direction */
777 vert_band_scale = vp8_vertical_band_3_5_scale;
778 last_vert_band_scale = vp8_last_vertical_band_3_5_scale;
779 src_band_height = 3;
780 dest_band_height = 5;
781 break;
782 case 15:
783 /* 1-2 Scale in vertical direction */
784 vert_band_scale = vp8_vertical_band_1_2_scale;
785 last_vert_band_scale = vp8_last_vertical_band_1_2_scale;
786 src_band_height = 1;
787 dest_band_height = 2;
788 break;
789 case 30:
790 /* no scale in Width direction */
791 vert_band_scale = null_scale;
792 last_vert_band_scale = null_scale;
793 src_band_height = 4;
794 dest_band_height = 4;
795 break;
796 default:
797 /* The ratio is not acceptable now */
798 /* throw("The ratio is not acceptable for now!"); */
799 ratio_scalable = 0;
800 break;
803 if (ratio_scalable == 0)
804 return ratio_scalable;
806 horiz_line_scale(source, source_width, dest, dest_width);
808 /* except last band */
809 for (k = 0; k < (dest_height + dest_band_height - 1) / dest_band_height - 1; k++)
811 /* scale one band horizontally */
812 for (i = 1; i < src_band_height; i++)
814 /* Trap case where we could read off the base of the source buffer */
815 line_src = source + i * source_pitch;
817 if (line_src < source_base)
818 line_src = source_base;
820 horiz_line_scale(line_src, source_width,
821 dest + i * dest_pitch, dest_width);
824 /* first line of next band */
825 /* Trap case where we could read off the base of the source buffer */
826 line_src = source + src_band_height * source_pitch;
828 if (line_src < source_base)
829 line_src = source_base;
831 horiz_line_scale(line_src, source_width,
832 dest + dest_band_height * dest_pitch,
833 dest_width);
835 /* Vertical scaling is in place */
836 vert_band_scale(dest, dest_pitch, dest_width);
838 /* Next band... */
839 source += src_band_height * source_pitch;
840 dest += dest_band_height * dest_pitch;
843 /* scale one band horizontally */
844 for (i = 1; i < src_band_height; i++)
846 /* Trap case where we could read off the base of the source buffer */
847 line_src = source + i * source_pitch;
849 if (line_src < source_base)
850 line_src = source_base;
852 horiz_line_scale(line_src, source_width,
853 dest + i * dest_pitch,
854 dest_width);
857 /* Vertical scaling is in place */
858 last_vert_band_scale(dest, dest_pitch, dest_width);
860 return ratio_scalable;
863 /****************************************************************************
865 * ROUTINE : any_ratio_frame_scale
867 * INPUTS : SCALE_INSTANCE *si : Pointer to post-processor instance (NOT USED).
868 * unsigned char *frame_buffer : Pointer to source image.
869 * int YOffset : Offset from start of buffer to Y samples.
870 * int UVOffset : Offset from start of buffer to UV samples.
872 * OUTPUTS : None.
874 * RETURNS : int: 1 if image scaled, 0 if image could not be scaled.
876 * FUNCTION : Scale the image with changing apect ratio.
878 * SPECIAL NOTES : None.
880 ****************************************************************************/
881 static
882 int any_ratio_frame_scale(SCALE_VARS *scale_vars, int YOffset, int UVOffset)
884 int i;
885 int ew;
886 int eh;
888 /* suggested scale factors */
889 int hs = scale_vars->HScale;
890 int hr = scale_vars->HRatio;
891 int vs = scale_vars->VScale;
892 int vr = scale_vars->VRatio;
894 int ratio_scalable = 1;
896 int sw = (scale_vars->expanded_frame_width * hr + hs - 1) / hs;
897 int sh = (scale_vars->expanded_frame_height * vr + vs - 1) / vs;
898 int dw = scale_vars->expanded_frame_width;
899 int dh = scale_vars->expanded_frame_height;
900 YV12_BUFFER_CONFIG *src_yuv_config = scale_vars->src_yuv_config;
901 YV12_BUFFER_CONFIG *dst_yuv_config = scale_vars->dst_yuv_config;
903 if (hr == 3)
904 ew = (sw + 2) / 3 * 3 * hs / hr;
905 else
906 ew = (sw + 7) / 8 * 8 * hs / hr;
908 if (vr == 3)
909 eh = (sh + 2) / 3 * 3 * vs / vr;
910 else
911 eh = (sh + 7) / 8 * 8 * vs / vr;
913 ratio_scalable = any_ratio_2d_scale(scale_vars,
914 (const unsigned char *)src_yuv_config->y_buffer,
915 src_yuv_config->y_stride, sw, sh,
916 (unsigned char *) dst_yuv_config->y_buffer + YOffset,
917 dst_yuv_config->y_stride, dw, dh);
919 for (i = 0; i < eh; i++)
920 duck_memset(dst_yuv_config->y_buffer + YOffset + i * dst_yuv_config->y_stride + dw, 0, ew - dw);
922 for (i = dh; i < eh; i++)
923 duck_memset(dst_yuv_config->y_buffer + YOffset + i * dst_yuv_config->y_stride, 0, ew);
925 if (ratio_scalable == 0)
926 return ratio_scalable;
928 sw = (sw + 1) >> 1;
929 sh = (sh + 1) >> 1;
930 dw = (dw + 1) >> 1;
931 dh = (dh + 1) >> 1;
933 any_ratio_2d_scale(scale_vars,
934 (const unsigned char *)src_yuv_config->u_buffer,
935 src_yuv_config->y_stride / 2, sw, sh,
936 (unsigned char *)dst_yuv_config->u_buffer + UVOffset,
937 dst_yuv_config->uv_stride, dw, dh);
939 any_ratio_2d_scale(scale_vars,
940 (const unsigned char *)src_yuv_config->v_buffer,
941 src_yuv_config->y_stride / 2, sw, sh,
942 (unsigned char *)dst_yuv_config->v_buffer + UVOffset,
943 dst_yuv_config->uv_stride, dw, dh);
945 return ratio_scalable;
948 /****************************************************************************
950 * ROUTINE : center_image
952 * INPUTS : SCALE_INSTANCE *si : Pointer to post-processor instance.
954 * OUTPUTS : None.
956 * RETURNS : void
958 * FUNCTION : Centers the image without scaling in the output buffer.
960 * SPECIAL NOTES : None.
962 ****************************************************************************/
963 static void
964 center_image(YV12_BUFFER_CONFIG *src_yuv_config, YV12_BUFFER_CONFIG *dst_yuv_config)
966 int i;
967 int row_offset, col_offset;
968 unsigned char *src_data_pointer;
969 unsigned char *dst_data_pointer;
971 /* center values */
972 row_offset = (dst_yuv_config->y_height - src_yuv_config->y_height) / 2;
973 col_offset = (dst_yuv_config->y_width - src_yuv_config->y_width) / 2;
975 /* Y's */
976 src_data_pointer = src_yuv_config->y_buffer;
977 dst_data_pointer = (unsigned char *)dst_yuv_config->y_buffer + (row_offset * dst_yuv_config->y_stride) + col_offset;
979 for (i = 0; i < src_yuv_config->y_height; i++)
981 duck_memcpy(dst_data_pointer, src_data_pointer, src_yuv_config->y_width);
982 dst_data_pointer += dst_yuv_config->y_stride;
983 src_data_pointer += src_yuv_config->y_stride;
986 row_offset /= 2;
987 col_offset /= 2;
989 /* U's */
990 src_data_pointer = src_yuv_config->u_buffer;
991 dst_data_pointer = (unsigned char *)dst_yuv_config->u_buffer + (row_offset * dst_yuv_config->uv_stride) + col_offset;
993 for (i = 0; i < src_yuv_config->uv_height; i++)
995 duck_memcpy(dst_data_pointer, src_data_pointer, src_yuv_config->uv_width);
996 dst_data_pointer += dst_yuv_config->uv_stride;
997 src_data_pointer += src_yuv_config->uv_stride;
1000 /* V's */
1001 src_data_pointer = src_yuv_config->v_buffer;
1002 dst_data_pointer = (unsigned char *)dst_yuv_config->v_buffer + (row_offset * dst_yuv_config->uv_stride) + col_offset;
1004 for (i = 0; i < src_yuv_config->uv_height; i++)
1006 duck_memcpy(dst_data_pointer, src_data_pointer, src_yuv_config->uv_width);
1007 dst_data_pointer += dst_yuv_config->uv_stride;
1008 src_data_pointer += src_yuv_config->uv_stride;
1012 /****************************************************************************
1014 * ROUTINE : scale_or_center
1016 * INPUTS : SCALE_INSTANCE *si : Pointer to post-processor instance.
1020 * OUTPUTS : None.
1022 * RETURNS : void
1024 * FUNCTION : Decides to scale or center image in scale buffer for blit
1026 * SPECIAL NOTES : None.
1028 ****************************************************************************/
1029 void
1030 vp8_yv12_scale_or_center
1032 YV12_BUFFER_CONFIG *src_yuv_config,
1033 YV12_BUFFER_CONFIG *dst_yuv_config,
1034 int expanded_frame_width,
1035 int expanded_frame_height,
1036 int scaling_mode,
1037 int HScale,
1038 int HRatio,
1039 int VScale,
1040 int VRatio
1043 /*if ( ppi->post_processing_level )
1044 update_umvborder ( ppi, frame_buffer );*/
1047 switch (scaling_mode)
1049 case SCALE_TO_FIT:
1050 case MAINTAIN_ASPECT_RATIO:
1052 SCALE_VARS scale_vars;
1053 /* center values */
1054 #if 1
1055 int row = (dst_yuv_config->y_height - expanded_frame_height) / 2;
1056 int col = (dst_yuv_config->y_width - expanded_frame_width) / 2;
1057 /*int YOffset = row * dst_yuv_config->y_width + col;
1058 int UVOffset = (row>>1) * dst_yuv_config->uv_width + (col>>1);*/
1059 int YOffset = row * dst_yuv_config->y_stride + col;
1060 int UVOffset = (row >> 1) * dst_yuv_config->uv_stride + (col >> 1);
1061 #else
1062 int row = (src_yuv_config->y_height - expanded_frame_height) / 2;
1063 int col = (src_yuv_config->y_width - expanded_frame_width) / 2;
1064 int YOffset = row * src_yuv_config->y_width + col;
1065 int UVOffset = (row >> 1) * src_yuv_config->uv_width + (col >> 1);
1066 #endif
1068 scale_vars.dst_yuv_config = dst_yuv_config;
1069 scale_vars.src_yuv_config = src_yuv_config;
1070 scale_vars.HScale = HScale;
1071 scale_vars.HRatio = HRatio;
1072 scale_vars.VScale = VScale;
1073 scale_vars.VRatio = VRatio;
1074 scale_vars.expanded_frame_width = expanded_frame_width;
1075 scale_vars.expanded_frame_height = expanded_frame_height;
1077 /* perform center and scale */
1078 any_ratio_frame_scale(&scale_vars, YOffset, UVOffset);
1080 break;
1082 case CENTER:
1083 center_image(src_yuv_config, dst_yuv_config);
1084 break;
1086 default:
1087 break;