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.
12 /****************************************************************************
14 * Module Title : scale.c
16 * Description : Image scaling functions.
18 ***************************************************************************/
20 /****************************************************************************
22 ****************************************************************************/
23 #include "vpx_mem/vpx_mem.h"
24 #include "vpx_scale/yv12config.h"
25 #include "vpx_scale/scale_mode.h"
27 /****************************************************************************
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;
55 # include "vpxscale_nofp.h"
60 int expanded_frame_width
;
61 int expanded_frame_height
;
68 YV12_BUFFER_CONFIG
*src_yuv_config
;
69 YV12_BUFFER_CONFIG
*dst_yuv_config
;
73 /****************************************************************************
75 * ROUTINE : horizontal_line_copy
84 * FUNCTION : 1 to 1 scaling up for a horizontal line of pixles
86 * SPECIAL NOTES : None.
90 ****************************************************************************/
92 void horizontal_line_copy(
93 const unsigned char *source
,
94 unsigned int source_width
,
96 unsigned int dest_width
101 duck_memcpy(dest
, source
, source_width
);
103 /****************************************************************************
105 * ROUTINE : null_scale
114 * FUNCTION : 1 to 1 scaling up for a vertical band
116 * SPECIAL NOTES : None.
120 ****************************************************************************/
124 unsigned int dest_pitch
,
125 unsigned int dest_width
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.
152 * FUNCTION : Performs 2-to-1 interpolated scaling.
154 * SPECIAL NOTES : None.
156 ****************************************************************************/
160 const unsigned char *source
,
162 unsigned int source_scale
,
163 unsigned int source_length
,
166 unsigned int dest_scale
,
167 unsigned int dest_length
172 int source_pitch
= source_step
;
173 (void) source_length
;
180 for (i
= dest_step
, j
= source_step
; i
< dest_length
* dest_step
; i
+= dest_step
, j
+= source_step
)
183 temp
+= 3 * source
[j
-source_pitch
];
184 temp
+= 10 * source
[j
];
185 temp
+= 3 * source
[j
+source_pitch
];
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.
208 * FUNCTION : Performs 2-to-1 point subsampled scaling.
210 * SPECIAL NOTES : None.
212 ****************************************************************************/
216 const unsigned char *source
,
218 unsigned int source_scale
,
219 unsigned int source_length
,
222 unsigned int dest_scale
,
223 unsigned int dest_length
228 (void) source_length
;
235 for (i
= 0; i
< dest_length
* dest_step
; i
+= dest_step
, j
+= source_step
)
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.
255 * FUNCTION : Performs linear interpolation in one dimension.
257 * SPECIAL NOTES : None.
259 ****************************************************************************/
263 const unsigned char *source
,
265 unsigned int source_scale
,
266 unsigned int source_length
,
269 unsigned int dest_scale
,
270 unsigned int dest_length
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 /****************************************************************************
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.
328 * FUNCTION : Performs 2-tap linear interpolation in two dimensions.
330 * SPECIAL NOTES : Expansion is performed one band at a time to help with
333 ****************************************************************************/
338 unsigned char *source
,
340 unsigned int source_width
,
341 unsigned int source_height
,
344 unsigned int dest_width
,
345 unsigned int dest_height
,
346 unsigned char *temp_area
,
347 unsigned char temp_area_height
,
352 unsigned int interlaced
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)
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
)
393 /* 4-5 Scale in Width direction */
394 horiz_line_scale
= vp8_horizontal_line_5_4_scale
;
397 /* 3-5 Scale in Width direction */
398 horiz_line_scale
= vp8_horizontal_line_5_3_scale
;
401 /* 1-2 Scale in Width direction */
402 horiz_line_scale
= vp8_horizontal_line_2_1_scale
;
405 /* The ratio is not acceptable now */
406 /* throw("The ratio is not acceptable for now!"); */
411 switch (vratio
* 10 / vscale
)
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;
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;
426 /* 1-2 Scale in vertical direction */
430 /* if the content is interlaced, point sampling is used */
431 vert_band_scale
= vp8_vertical_band_2_1_scale
;
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;
446 /* The ratio is not acceptable now */
447 /* throw("The ratio is not acceptable for now!"); */
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
;
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
);
495 vpx_memcpy(temp_area
, temp_area
+ source_band_height
* dest_pitch
, dest_width
);
498 source
+= (unsigned long) source_band_height
* source_pitch
;
499 dest
+= (unsigned long) dest_band_height
* dest_pitch
;
505 if (hscale
== 2 && hratio
== 1)
506 Scale1Dh
= scale1d_2t1_ps
;
508 if (vscale
== 2 && vratio
== 1)
511 Scale1Dv
= scale1d_2t1_ps
;
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
;
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
;
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 /****************************************************************************
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.
597 * FUNCTION : Performs 2-tap linear interpolation in two dimensions.
599 * SPECIAL NOTES : Expansion is performed one band at a time to help with
602 ****************************************************************************/
605 YV12_BUFFER_CONFIG
*src
,
606 YV12_BUFFER_CONFIG
*dst
,
607 unsigned char *temp_area
,
608 unsigned char temp_height
,
613 unsigned int interlaced
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.
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 ****************************************************************************/
682 int any_ratio_2d_scale
685 const unsigned char *source
,
687 unsigned int source_width
,
688 unsigned int source_height
,
690 unsigned int dest_pitch
,
691 unsigned int dest_width
,
692 unsigned int dest_height
696 unsigned int src_band_height
= 0;
697 unsigned int dest_band_height
= 0;
699 /* suggested scale factors */
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
;
717 /* find out the ratio for each direction */
718 switch (hr
* 30 / hs
)
721 /* 4-5 Scale in Width direction */
722 horiz_line_scale
= vp8_horizontal_line_4_5_scale
;
725 /* 3-4 Scale in Width direction */
726 horiz_line_scale
= vp8_horizontal_line_3_4_scale
;
730 /* 4-5 Scale in Width direction */
731 horiz_line_scale
= vp8_horizontal_line_2_3_scale
;
734 /* 3-5 Scale in Width direction */
735 horiz_line_scale
= vp8_horizontal_line_3_5_scale
;
738 /* 1-2 Scale in Width direction */
739 horiz_line_scale
= vp8_horizontal_line_1_2_scale
;
742 /* no scale in Width direction */
743 horiz_line_scale
= horizontal_line_copy
;
746 /* The ratio is not acceptable now */
747 /* throw("The ratio is not acceptable for now!"); */
752 switch (vr
* 30 / vs
)
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
;
759 dest_band_height
= 5;
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
;
766 dest_band_height
= 4;
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
;
773 dest_band_height
= 3;
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
;
780 dest_band_height
= 5;
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
;
787 dest_band_height
= 2;
790 /* no scale in Width direction */
791 vert_band_scale
= null_scale
;
792 last_vert_band_scale
= null_scale
;
794 dest_band_height
= 4;
797 /* The ratio is not acceptable now */
798 /* throw("The ratio is not acceptable for now!"); */
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
,
835 /* Vertical scaling is in place */
836 vert_band_scale(dest
, dest_pitch
, dest_width
);
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
,
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.
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 ****************************************************************************/
882 int any_ratio_frame_scale(SCALE_VARS
*scale_vars
, int YOffset
, int UVOffset
)
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
;
904 ew
= (sw
+ 2) / 3 * 3 * hs
/ hr
;
906 ew
= (sw
+ 7) / 8 * 8 * hs
/ hr
;
909 eh
= (sh
+ 2) / 3 * 3 * vs
/ vr
;
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
;
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.
958 * FUNCTION : Centers the image without scaling in the output buffer.
960 * SPECIAL NOTES : None.
962 ****************************************************************************/
964 center_image(YV12_BUFFER_CONFIG
*src_yuv_config
, YV12_BUFFER_CONFIG
*dst_yuv_config
)
967 int row_offset
, col_offset
;
968 unsigned char *src_data_pointer
;
969 unsigned char *dst_data_pointer
;
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;
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
;
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
;
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.
1024 * FUNCTION : Decides to scale or center image in scale buffer for blit
1026 * SPECIAL NOTES : None.
1028 ****************************************************************************/
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
,
1043 /*if ( ppi->post_processing_level )
1044 update_umvborder ( ppi, frame_buffer );*/
1047 switch (scaling_mode
)
1050 case MAINTAIN_ASPECT_RATIO
:
1052 SCALE_VARS scale_vars
;
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);
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);
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
);
1083 center_image(src_yuv_config
, dst_yuv_config
);