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