Home | History | Annotate | Download | only in generic
      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_mem/vpx_mem.h"
     24 #include "vpx_scale/yv12config.h"
     25 #include "vpx_scale/scale_mode.h"
     26 
     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;
     46 
     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
     57 
     58 typedef struct
     59 {
     60     int     expanded_frame_width;
     61     int     expanded_frame_height;
     62 
     63     int HScale;
     64     int HRatio;
     65     int VScale;
     66     int VRatio;
     67 
     68     YV12_BUFFER_CONFIG *src_yuv_config;
     69     YV12_BUFFER_CONFIG *dst_yuv_config;
     70 
     71 } SCALE_VARS;
     72 
     73 /****************************************************************************
     74  *
     75  *  ROUTINE       :     horizontal_line_copy
     76  *
     77  *  INPUTS        :     None
     78  *
     79  *
     80  *  OUTPUTS       :     None.
     81  *
     82  *  RETURNS       :     None
     83  *
     84  *  FUNCTION      :     1 to 1 scaling up for a horizontal line of pixles
     85  *
     86  *  SPECIAL NOTES :     None.
     87  *
     88  *  ERRORS        :     None.
     89  *
     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
     97 )
     98 {
     99     (void) dest_width;
    100 
    101     duck_memcpy(dest, source, source_width);
    102 }
    103 /****************************************************************************
    104  *
    105  *  ROUTINE       :     null_scale
    106  *
    107  *  INPUTS        :     None
    108  *
    109  *
    110  *  OUTPUTS       :     None.
    111  *
    112  *  RETURNS       :     None
    113  *
    114  *  FUNCTION      :     1 to 1 scaling up for a vertical band
    115  *
    116  *  SPECIAL NOTES :     None.
    117  *
    118  *  ERRORS        :     None.
    119  *
    120  ****************************************************************************/
    121 static
    122 void null_scale(
    123     unsigned char *dest,
    124     unsigned int dest_pitch,
    125     unsigned int dest_width
    126 )
    127 {
    128     (void) dest;
    129     (void) dest_pitch;
    130     (void) dest_width;
    131 
    132     return;
    133 }
    134 
    135 /****************************************************************************
    136  *
    137  *  ROUTINE       : scale1d_2t1_i
    138  *
    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.
    147  *
    148  *  OUTPUTS       : None.
    149  *
    150  *  RETURNS       : void
    151  *
    152  *  FUNCTION      : Performs 2-to-1 interpolated scaling.
    153  *
    154  *  SPECIAL NOTES : None.
    155  *
    156  ****************************************************************************/
    157 static
    158 void scale1d_2t1_i
    159 (
    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
    168 )
    169 {
    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;
    176 
    177     source_step *= 2;
    178     dest[0] = source[0];
    179 
    180     for (i = dest_step, j = source_step; i < dest_length * dest_step; i += dest_step, j += source_step)
    181     {
    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);
    188     }
    189 }
    190 
    191 /****************************************************************************
    192  *
    193  *  ROUTINE       : scale1d_2t1_ps
    194  *
    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.
    203  *
    204  *  OUTPUTS       : None.
    205  *
    206  *  RETURNS       : void
    207  *
    208  *  FUNCTION      : Performs 2-to-1 point subsampled scaling.
    209  *
    210  *  SPECIAL NOTES : None.
    211  *
    212  ****************************************************************************/
    213 static
    214 void scale1d_2t1_ps
    215 (
    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
    224 )
    225 {
    226     unsigned int i, j;
    227 
    228     (void) source_length;
    229     (void) source_scale;
    230     (void) dest_scale;
    231 
    232     source_step *= 2;
    233     j = 0;
    234 
    235     for (i = 0; i < dest_length * dest_step; i += dest_step, j += source_step)
    236         dest[i] = source[j];
    237 }
    238 /****************************************************************************
    239  *
    240  *  ROUTINE       : scale1d_c
    241  *
    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.
    250  *
    251  *  OUTPUTS       : None.
    252  *
    253  *  RETURNS       : void
    254  *
    255  *  FUNCTION      : Performs linear interpolation in one dimension.
    256  *
    257  *  SPECIAL NOTES : None.
    258  *
    259  ****************************************************************************/
    260 static
    261 void scale1d_c
    262 (
    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
    271 )
    272 {
    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);
    279 
    280     (void) source_length;
    281 
    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 );
    285 
    286     for (i = 0; i < dest_length * dest_step; i += dest_step)
    287     {
    288         dest[i] = (char)((left_modifier * left_pixel + right_modifier * right_pixel + round_value) / dest_scale);
    289 
    290         right_modifier += source_scale;
    291 
    292         while (right_modifier > dest_scale)
    293         {
    294             right_modifier -= dest_scale;
    295             source += source_step;
    296             left_pixel = *source;
    297             right_pixel = *(source + source_step);
    298         }
    299 
    300         left_modifier = dest_scale - right_modifier;
    301     }
    302 }
    303 
    304 /****************************************************************************
    305  *
    306  *  ROUTINE       : Scale2D
    307  *
    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.
    323  *
    324  *  OUTPUTS       : None.
    325  *
    326  *  RETURNS       : void
    327  *
    328  *  FUNCTION      : Performs 2-tap linear interpolation in two dimensions.
    329  *
    330  *  SPECIAL NOTES : Expansion is performed one band at a time to help with
    331  *                  caching.
    332  *
    333  ****************************************************************************/
    334 static
    335 void Scale2D
    336 (
    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
    353 )
    354 {
    355     //unsigned
    356     int i, j, k;
    357     int bands;
    358     int dest_band_height;
    359     int source_band_height;
    360 
    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);
    363 
    364     Scale1D Scale1Dv = scale1d_c;
    365     Scale1D Scale1Dh = scale1d_c;
    366 
    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;
    369 
    370     int ratio_scalable = 1;
    371     int interpolation = 0;
    372 
    373     unsigned char *source_base; // = (unsigned char *) ((source_pitch >= 0) ? source : (source + ((source_height-1) * source_pitch)));
    374     unsigned char *line_src;
    375 
    376 
    377     source_base = (unsigned char *)source;
    378 
    379     if (source_pitch < 0)
    380     {
    381         int offset;
    382 
    383         offset = (source_height - 1);
    384         offset *= source_pitch;
    385 
    386         source_base += offset;
    387     }
    388 
    389     // find out the ratio for each direction
    390     switch (hratio * 10 / hscale)
    391     {
    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;
    409     }
    410 
    411     switch (vratio * 10 / vscale)
    412     {
    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
    427 
    428         if (interlaced)
    429         {
    430             //if the content is interlaced, point sampling is used
    431             vert_band_scale     = vp8_vertical_band_2_1_scale;
    432         }
    433         else
    434         {
    435 
    436             interpolation = 1;
    437             //if the content is progressive, interplo
    438             vert_band_scale     = vp8_vertical_band_2_1_scale_i;
    439 
    440         }
    441 
    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;
    450     }
    451 
    452     if (ratio_scalable)
    453     {
    454         if (source_height == dest_height)
    455         {
    456             // for each band of the image
    457             for (k = 0; k < (int)dest_height; k++)
    458             {
    459                 horiz_line_scale(source, source_width, dest, dest_width);
    460                 source += source_pitch;
    461                 dest   += dest_pitch;
    462             }
    463 
    464             return;
    465         }
    466 
    467         if (interpolation)
    468         {
    469             if (source < source_base)
    470                 source = source_base;
    471 
    472             horiz_line_scale(source, source_width, temp_area, dest_width);
    473         }
    474 
    475         for (k = 0; k < (int)(dest_height + dest_band_height - 1) / dest_band_height; k++)
    476         {
    477             // scale one band horizontally
    478             for (i = 0; i < source_band_height; i++)
    479             {
    480                 // Trap case where we could read off the base of the source buffer
    481 
    482                 line_src = (unsigned char *)source + i * source_pitch;
    483 
    484                 if (line_src < source_base)
    485                     line_src = source_base;
    486 
    487                 horiz_line_scale(line_src, source_width,
    488                                  temp_area + (i + 1)*dest_pitch, dest_width);
    489             }
    490 
    491             // Vertical scaling is in place
    492             vert_band_scale(temp_area + dest_pitch, dest_pitch, dest, dest_pitch, dest_width);
    493 
    494             if (interpolation)
    495                 vpx_memcpy(temp_area, temp_area + source_band_height * dest_pitch, dest_width);
    496 
    497             // Next band...
    498             source += (unsigned long) source_band_height  * source_pitch;
    499             dest   += (unsigned long) dest_band_height * dest_pitch;
    500         }
    501 
    502         return;
    503     }
    504 
    505     if (hscale == 2 && hratio == 1)
    506         Scale1Dh = scale1d_2t1_ps;
    507 
    508     if (vscale == 2 && vratio == 1)
    509     {
    510         if (interlaced)
    511             Scale1Dv = scale1d_2t1_ps;
    512         else
    513             Scale1Dv = scale1d_2t1_i;
    514     }
    515 
    516     if (source_height == dest_height)
    517     {
    518         // for each band of the image
    519         for (k = 0; k < (int)dest_height; k++)
    520         {
    521             Scale1Dh(source, 1, hscale, source_width + 1, dest, 1, hratio, dest_width);
    522             source += source_pitch;
    523             dest   += dest_pitch;
    524         }
    525 
    526         return;
    527     }
    528 
    529     if (dest_height > source_height)
    530     {
    531         dest_band_height   = temp_area_height - 1;
    532         source_band_height = dest_band_height * source_height / dest_height;
    533     }
    534     else
    535     {
    536         source_band_height = temp_area_height - 1;
    537         dest_band_height   = source_band_height * vratio / vscale;
    538     }
    539 
    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);
    542 
    543     // for each band of the image
    544     bands = (dest_height + dest_band_height - 1) / dest_band_height;
    545 
    546     for (k = 0; k < bands; k++)
    547     {
    548         // scale one band horizontally
    549         for (i = 1; i < source_band_height + 1; i++)
    550         {
    551             if (k * source_band_height + i < (int) source_height)
    552             {
    553                 Scale1Dh(source + i * source_pitch, 1, hscale, source_width + 1,
    554                          temp_area + i * dest_pitch, 1, hratio, dest_width);
    555             }
    556             else  //  Duplicate the last row
    557             {
    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);
    560             }
    561         }
    562 
    563         // scale one band vertically
    564         for (j = 0; j < (int)dest_width; j++)
    565         {
    566             Scale1Dv(&temp_area[j], dest_pitch, vscale, source_band_height + 1,
    567                      &dest[j], dest_pitch, vratio, dest_band_height);
    568         }
    569 
    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);
    572 
    573         // move to the next band
    574         source += source_band_height * source_pitch;
    575         dest   += dest_band_height * dest_pitch;
    576     }
    577 }
    578 
    579 /****************************************************************************
    580  *
    581  *  ROUTINE       :
    582  *
    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.
    592  *
    593  *  OUTPUTS       : None.
    594  *
    595  *  RETURNS       : void
    596  *
    597  *  FUNCTION      : Performs 2-tap linear interpolation in two dimensions.
    598  *
    599  *  SPECIAL NOTES : Expansion is performed one band at a time to help with
    600  *                  caching.
    601  *
    602  ****************************************************************************/
    603 void vp8_scale_frame
    604 (
    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
    614 )
    615 {
    616     int i;
    617     int dw = (hscale - 1 + src->y_width * hratio) / hscale;
    618     int dh = (vscale - 1 + src->y_height * vratio) / vscale;
    619 
    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);
    624 
    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);
    628 
    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);
    632 
    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);
    636 
    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);
    640 
    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);
    644 
    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);
    648 
    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);
    652 
    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);
    656 }
    657 /****************************************************************************
    658  *
    659  *  ROUTINE       : any_ratio_2d_scale
    660  *
    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.
    670  *
    671  *  OUTPUTS       : None.
    672  *
    673  *  RETURNS       : int: 1 if image scaled, 0 if image could not be scaled.
    674  *
    675  *  FUNCTION      : Scale the image with changing apect ratio.
    676  *
    677  *  SPECIAL NOTES : This scaling is a bi-linear scaling. Need to re-work the
    678  *                  whole function for new scaling algorithm.
    679  *
    680  ****************************************************************************/
    681 static
    682 int any_ratio_2d_scale
    683 (
    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
    693 )
    694 {
    695     unsigned int i, k;
    696     unsigned int src_band_height  = 0;
    697     unsigned int dest_band_height = 0;
    698 
    699     // suggested scale factors
    700     int hs = si->HScale;
    701     int hr = si->HRatio;
    702     int vs = si->VScale;
    703     int vr = si->VRatio;
    704 
    705     // assume the ratios are scalable instead of should be centered
    706     int ratio_scalable = 1;
    707 
    708     const unsigned char *source_base = ((source_pitch >= 0) ? source : (source + ((source_height - 1) * source_pitch)));
    709     const unsigned char *line_src;
    710 
    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;
    714 
    715     (void) si;
    716 
    717     // find out the ratio for each direction
    718     switch (hr * 30 / hs)
    719     {
    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;
    728 
    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;
    750     }
    751 
    752     switch (vr * 30 / vs)
    753     {
    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;
    801     }
    802 
    803     if (ratio_scalable == 0)
    804         return ratio_scalable;
    805 
    806     horiz_line_scale(source, source_width, dest, dest_width);
    807 
    808     // except last band
    809     for (k = 0; k < (dest_height + dest_band_height - 1) / dest_band_height - 1; k++)
    810     {
    811         // scale one band horizontally
    812         for (i = 1; i < src_band_height; i++)
    813         {
    814             // Trap case where we could read off the base of the source buffer
    815             line_src = source + i * source_pitch;
    816 
    817             if (line_src < source_base)
    818                 line_src = source_base;
    819 
    820             horiz_line_scale(line_src, source_width,
    821                              dest + i * dest_pitch, dest_width);
    822         }
    823 
    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;
    827 
    828         if (line_src < source_base)
    829             line_src = source_base;
    830 
    831         horiz_line_scale(line_src, source_width,
    832                          dest + dest_band_height * dest_pitch,
    833                          dest_width);
    834 
    835         // Vertical scaling is in place
    836         vert_band_scale(dest, dest_pitch, dest_width);
    837 
    838         // Next band...
    839         source += src_band_height  * source_pitch;
    840         dest   += dest_band_height * dest_pitch;
    841     }
    842 
    843     // scale one band horizontally
    844     for (i = 1; i < src_band_height; i++)
    845     {
    846         // Trap case where we could read off the base of the source buffer
    847         line_src = source + i * source_pitch;
    848 
    849         if (line_src < source_base)
    850             line_src = source_base;
    851 
    852         horiz_line_scale(line_src, source_width,
    853                          dest + i * dest_pitch,
    854                          dest_width);
    855     }
    856 
    857     // Vertical scaling is in place
    858     last_vert_band_scale(dest, dest_pitch, dest_width);
    859 
    860     return ratio_scalable;
    861 }
    862 
    863 /****************************************************************************
    864  *
    865  *  ROUTINE       : any_ratio_frame_scale
    866  *
    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.
    871  *
    872  *  OUTPUTS       : None.
    873  *
    874  *  RETURNS       : int: 1 if image scaled, 0 if image could not be scaled.
    875  *
    876  *  FUNCTION      : Scale the image with changing apect ratio.
    877  *
    878  *  SPECIAL NOTES : None.
    879  *
    880  ****************************************************************************/
    881 static
    882 int any_ratio_frame_scale(SCALE_VARS *scale_vars, int YOffset, int UVOffset)
    883 {
    884     int i;
    885     int ew;
    886     int eh;
    887 
    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;
    893 
    894     int ratio_scalable = 1;
    895 
    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;
    902 
    903     if (hr == 3)
    904         ew = (sw + 2) / 3 * 3 * hs / hr;
    905     else
    906         ew = (sw + 7) / 8 * 8 * hs / hr;
    907 
    908     if (vr == 3)
    909         eh = (sh + 2) / 3 * 3 * vs / vr;
    910     else
    911         eh = (sh + 7) / 8 * 8 * vs / vr;
    912 
    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);
    918 
    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);
    921 
    922     for (i = dh; i < eh; i++)
    923         duck_memset(dst_yuv_config->y_buffer + YOffset + i * dst_yuv_config->y_stride, 0, ew);
    924 
    925     if (ratio_scalable == 0)
    926         return ratio_scalable;
    927 
    928     sw = (sw + 1) >> 1;
    929     sh = (sh + 1) >> 1;
    930     dw = (dw + 1) >> 1;
    931     dh = (dh + 1) >> 1;
    932 
    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);
    938 
    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);
    944 
    945     return ratio_scalable;
    946 }
    947 
    948 /****************************************************************************
    949  *
    950  *  ROUTINE       : center_image
    951  *
    952  *  INPUTS        : SCALE_INSTANCE *si       : Pointer to post-processor instance.
    953  *
    954  *  OUTPUTS       : None.
    955  *
    956  *  RETURNS       : void
    957  *
    958  *  FUNCTION      : Centers the image without scaling in the output buffer.
    959  *
    960  *  SPECIAL NOTES : None.
    961  *
    962  ****************************************************************************/
    963 static void
    964 center_image(YV12_BUFFER_CONFIG *src_yuv_config, YV12_BUFFER_CONFIG *dst_yuv_config)
    965 {
    966     int i;
    967     int row_offset, col_offset;
    968     unsigned char *src_data_pointer;
    969     unsigned char *dst_data_pointer;
    970 
    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;
    974 
    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;
    978 
    979     for (i = 0; i < src_yuv_config->y_height; i++)
    980     {
    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;
    984     }
    985 
    986     row_offset /= 2;
    987     col_offset /= 2;
    988 
    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;
    992 
    993     for (i = 0; i < src_yuv_config->uv_height; i++)
    994     {
    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;
    998     }
    999 
   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;
   1003 
   1004     for (i = 0; i < src_yuv_config->uv_height; i++)
   1005     {
   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;
   1009     }
   1010 }
   1011 
   1012 /****************************************************************************
   1013  *
   1014  *  ROUTINE       : scale_or_center
   1015  *
   1016  *  INPUTS        : SCALE_INSTANCE *si       : Pointer to post-processor instance.
   1017  *
   1018  *
   1019  *
   1020  *  OUTPUTS       : None.
   1021  *
   1022  *  RETURNS       : void
   1023  *
   1024  *  FUNCTION      : Decides to scale or center image in scale buffer for blit
   1025  *
   1026  *  SPECIAL NOTES : None.
   1027  *
   1028  ****************************************************************************/
   1029 void
   1030 vp8_yv12_scale_or_center
   1031 (
   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
   1041 )
   1042 {
   1043 //    if ( ppi->post_processing_level )
   1044     //      update_umvborder ( ppi, frame_buffer );
   1045 
   1046 
   1047     switch (scaling_mode)
   1048     {
   1049     case SCALE_TO_FIT:
   1050     case MAINTAIN_ASPECT_RATIO:
   1051     {
   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
   1067 
   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;
   1076 
   1077         // perform center and scale
   1078         any_ratio_frame_scale(&scale_vars, YOffset, UVOffset);
   1079 
   1080         break;
   1081     }
   1082     case CENTER:
   1083         center_image(src_yuv_config, dst_yuv_config);
   1084         break;
   1085 
   1086     default:
   1087         break;
   1088     }
   1089 }
   1090