i420_rgb16.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:21k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * i420_rgb16.c : YUV to bitmap RGB conversion module for vlc
  3.  *****************************************************************************
  4.  * Copyright (C) 2000 VideoLAN
  5.  * $Id: i420_rgb16.c 8583 2004-08-30 01:24:08Z gbazin $
  6.  *
  7.  * Authors: Samuel Hocevar <sam@zoy.org>
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  * 
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  22.  *****************************************************************************/
  23. /*****************************************************************************
  24.  * Preamble
  25.  *****************************************************************************/
  26. #include <string.h>                                            /* strerror() */
  27. #include <stdlib.h>                                      /* malloc(), free() */
  28. #include <vlc/vlc.h>
  29. #include <vlc/vout.h>
  30. #include "i420_rgb.h"
  31. #if defined (MODULE_NAME_IS_i420_rgb)
  32. #   include "i420_rgb_c.h"
  33. #elif defined (MODULE_NAME_IS_i420_rgb_mmx)
  34. #   include "i420_rgb_mmx.h"
  35. #endif
  36. static void SetOffset( int, int, int, int, vlc_bool_t *, int *, int * );
  37. #if defined (MODULE_NAME_IS_i420_rgb)
  38. /*****************************************************************************
  39.  * I420_RGB16: color YUV 4:2:0 to RGB 16 bpp with dithering
  40.  *****************************************************************************
  41.  * Horizontal alignment needed:
  42.  *  - input: 8 pixels (8 Y bytes, 4 U/V bytes), margins not allowed
  43.  *  - output: 1 pixel (2 bytes), margins allowed
  44.  * Vertical alignment needed:
  45.  *  - input: 2 lines (2 Y lines, 1 U/V line)
  46.  *  - output: 1 line
  47.  *****************************************************************************/
  48. void E_(I420_RGB16_dithering)( vout_thread_t *p_vout, picture_t *p_src,
  49.                                                       picture_t *p_dest )
  50. {
  51.     /* We got this one from the old arguments */
  52.     uint16_t *p_pic = (uint16_t*)p_dest->p->p_pixels;
  53.     uint8_t  *p_y   = p_src->Y_PIXELS;
  54.     uint8_t  *p_u   = p_src->U_PIXELS;
  55.     uint8_t  *p_v   = p_src->V_PIXELS;
  56.     vlc_bool_t   b_hscale;                        /* horizontal scaling type */
  57.     int          i_vscale;                          /* vertical scaling type */
  58.     unsigned int i_x, i_y;                /* horizontal and vertical indexes */
  59.     unsigned int i_real_y;                                          /* y % 4 */
  60.     int         i_right_margin;
  61.     int         i_rewind;
  62.     int         i_scale_count;                       /* scale modulo counter */
  63.     int         i_chroma_width = p_vout->render.i_width / 2; /* chroma width */
  64.     uint16_t *  p_pic_start;       /* beginning of the current line for copy */
  65.     int         i_uval, i_vval;                           /* U and V samples */
  66.     int         i_red, i_green, i_blue;          /* U and V modified samples */
  67.     uint16_t *  p_yuv = p_vout->chroma.p_sys->p_rgb16;
  68.     uint16_t *  p_ybase;                     /* Y dependant conversion table */
  69.     /* Conversion buffer pointer */
  70.     uint16_t *  p_buffer_start = (uint16_t*)p_vout->chroma.p_sys->p_buffer;
  71.     uint16_t *  p_buffer;
  72.     /* Offset array pointer */
  73.     int *       p_offset_start = p_vout->chroma.p_sys->p_offset;
  74.     int *       p_offset;
  75.     const int i_source_margin = p_src->p[0].i_pitch
  76.                                  - p_src->p[0].i_visible_pitch;
  77.     const int i_source_margin_c = p_src->p[1].i_pitch
  78.                                  - p_src->p[1].i_visible_pitch;
  79.     /* The dithering matrices */
  80.     int dither10[4] = {  0x0,  0x8,  0x2,  0xa };
  81.     int dither11[4] = {  0xc,  0x4,  0xe,  0x6 };
  82.     int dither12[4] = {  0x3,  0xb,  0x1,  0x9 };
  83.     int dither13[4] = {  0xf,  0x7,  0xd,  0x5 };
  84.     for(i_x = 0; i_x < 4; i_x++)
  85.     {
  86.         dither10[i_x] = dither10[i_x] << (SHIFT - 4 + p_vout->output.i_rrshift);
  87.         dither11[i_x] = dither11[i_x] << (SHIFT - 4 + p_vout->output.i_rrshift);
  88.         dither12[i_x] = dither12[i_x] << (SHIFT - 4 + p_vout->output.i_rrshift);
  89.         dither13[i_x] = dither13[i_x] << (SHIFT - 4 + p_vout->output.i_rrshift);
  90.     }
  91.     i_right_margin = p_dest->p->i_pitch - p_dest->p->i_visible_pitch;
  92.     if( p_vout->render.i_width & 7 )
  93.     {
  94.         i_rewind = 8 - ( p_vout->render.i_width & 7 );
  95.     }
  96.     else
  97.     {
  98.         i_rewind = 0;
  99.     }
  100.     /* Rule: when a picture of size (x1,y1) with aspect ratio r1 is rendered
  101.      * on a picture of size (x2,y2) with aspect ratio r2, if x1 grows to x1'
  102.      * then y1 grows to y1' = x1' * y2/x2 * r2/r1 */
  103.     SetOffset( p_vout->render.i_width, p_vout->render.i_height,
  104.                p_vout->output.i_width, p_vout->output.i_height,
  105.                &b_hscale, &i_vscale, p_offset_start );
  106.     /*
  107.      * Perform conversion
  108.      */
  109.     i_scale_count = ( i_vscale == 1 ) ?
  110.                     p_vout->output.i_height : p_vout->render.i_height;
  111.     for( i_y = 0; i_y < p_vout->render.i_height; i_y++ )
  112.     {
  113.         i_real_y = i_y & 0x3;
  114.         p_pic_start = p_pic;
  115.         p_buffer = b_hscale ? p_buffer_start : p_pic;
  116.         for ( i_x = p_vout->render.i_width / 8; i_x--; )
  117.         {
  118.             int *p_dither = dither10;
  119.             CONVERT_YUV_PIXEL_DITHER(2);
  120.             p_dither = dither11;
  121.             CONVERT_Y_PIXEL_DITHER(2);
  122.             p_dither = dither12;
  123.             CONVERT_YUV_PIXEL_DITHER(2);
  124.             p_dither = dither13;
  125.             CONVERT_Y_PIXEL_DITHER(2);
  126.             p_dither = dither10;
  127.             CONVERT_YUV_PIXEL_DITHER(2);
  128.             p_dither = dither11;
  129.             CONVERT_Y_PIXEL_DITHER(2);
  130.             p_dither = dither12;
  131.             CONVERT_YUV_PIXEL_DITHER(2);
  132.             p_dither = dither13;
  133.             CONVERT_Y_PIXEL_DITHER(2);
  134.         }
  135.         /* Here we do some unaligned reads and duplicate conversions, but
  136.          * at least we have all the pixels */
  137.         if( i_rewind )
  138.         {
  139.             int *p_dither = dither10;
  140.             p_y -= i_rewind;
  141.             p_u -= i_rewind >> 1;
  142.             p_v -= i_rewind >> 1;
  143.             p_buffer -= i_rewind;
  144.             CONVERT_YUV_PIXEL_DITHER(2);
  145.             p_dither = dither11;
  146.             CONVERT_Y_PIXEL_DITHER(2);
  147.             p_dither = dither12;
  148.             CONVERT_YUV_PIXEL_DITHER(2);
  149.             p_dither = dither13;
  150.             CONVERT_Y_PIXEL_DITHER(2);
  151.             p_dither = dither10;
  152.             CONVERT_YUV_PIXEL_DITHER(2);
  153.             p_dither = dither11;
  154.             CONVERT_Y_PIXEL_DITHER(2);
  155.             p_dither = dither12;
  156.             CONVERT_YUV_PIXEL_DITHER(2);
  157.             p_dither = dither13;
  158.             CONVERT_Y_PIXEL_DITHER(2);
  159.         }
  160.         SCALE_WIDTH;
  161.         SCALE_HEIGHT( 420, 2 );
  162.         p_y += i_source_margin;
  163.         if( i_y % 2 )
  164.         {
  165.             p_u += i_source_margin_c;
  166.             p_v += i_source_margin_c;
  167.         }
  168.     }
  169. }
  170. #endif
  171. /*****************************************************************************
  172.  * I420_RGB16: color YUV 4:2:0 to RGB 16 bpp
  173.  *****************************************************************************
  174.  * Horizontal alignment needed:
  175.  *  - input: 8 pixels (8 Y bytes, 4 U/V bytes), margins not allowed
  176.  *  - output: 1 pixel (2 bytes), margins allowed
  177.  * Vertical alignment needed:
  178.  *  - input: 2 lines (2 Y lines, 1 U/V line)
  179.  *  - output: 1 line
  180.  *****************************************************************************/
  181. void E_(I420_RGB16)( vout_thread_t *p_vout, picture_t *p_src,
  182.                                             picture_t *p_dest )
  183. {
  184.     /* We got this one from the old arguments */
  185.     uint16_t *p_pic = (uint16_t*)p_dest->p->p_pixels;
  186.     uint8_t  *p_y   = p_src->Y_PIXELS;
  187.     uint8_t  *p_u   = p_src->U_PIXELS;
  188.     uint8_t  *p_v   = p_src->V_PIXELS;
  189.     vlc_bool_t  b_hscale;                         /* horizontal scaling type */
  190.     unsigned int i_vscale;                          /* vertical scaling type */
  191.     unsigned int i_x, i_y;                /* horizontal and vertical indexes */
  192.     int         i_right_margin;
  193.     int         i_rewind;
  194.     int         i_scale_count;                       /* scale modulo counter */
  195.     int         i_chroma_width = p_vout->render.i_width / 2; /* chroma width */
  196.     uint16_t *  p_pic_start;       /* beginning of the current line for copy */
  197. #if defined (MODULE_NAME_IS_i420_rgb)
  198.     int         i_uval, i_vval;                           /* U and V samples */
  199.     int         i_red, i_green, i_blue;          /* U and V modified samples */
  200.     uint16_t *  p_yuv = p_vout->chroma.p_sys->p_rgb16;
  201.     uint16_t *  p_ybase;                     /* Y dependant conversion table */
  202. #endif
  203.     /* Conversion buffer pointer */
  204.     uint16_t *  p_buffer_start = (uint16_t*)p_vout->chroma.p_sys->p_buffer;
  205.     uint16_t *  p_buffer;
  206.     /* Offset array pointer */
  207.     int *       p_offset_start = p_vout->chroma.p_sys->p_offset;
  208.     int *       p_offset;
  209.     const int i_source_margin = p_src->p[0].i_pitch
  210.                                  - p_src->p[0].i_visible_pitch;
  211.     const int i_source_margin_c = p_src->p[1].i_pitch
  212.                                  - p_src->p[1].i_visible_pitch;
  213.     i_right_margin = p_dest->p->i_pitch - p_dest->p->i_visible_pitch;
  214.     if( p_vout->render.i_width & 7 )
  215.     {
  216.         i_rewind = 8 - ( p_vout->render.i_width & 7 );
  217.     }
  218.     else
  219.     {
  220.         i_rewind = 0;
  221.     }
  222.     /* Rule: when a picture of size (x1,y1) with aspect ratio r1 is rendered
  223.      * on a picture of size (x2,y2) with aspect ratio r2, if x1 grows to x1'
  224.      * then y1 grows to y1' = x1' * y2/x2 * r2/r1 */
  225.     SetOffset( p_vout->render.i_width, p_vout->render.i_height,
  226.                p_vout->output.i_width, p_vout->output.i_height,
  227.                &b_hscale, &i_vscale, p_offset_start );
  228.     /*
  229.      * Perform conversion
  230.      */
  231.     i_scale_count = ( i_vscale == 1 ) ?
  232.                     p_vout->output.i_height : p_vout->render.i_height;
  233.     for( i_y = 0; i_y < p_vout->render.i_height; i_y++ )
  234.     {
  235.         p_pic_start = p_pic;
  236.         p_buffer = b_hscale ? p_buffer_start : p_pic;
  237. #if defined (MODULE_NAME_IS_i420_rgb)
  238.         for ( i_x = p_vout->render.i_width / 8; i_x--; )
  239.         {
  240.             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
  241.             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
  242.             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
  243.             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
  244.         }
  245. #elif defined (MODULE_NAME_IS_i420_rgb_mmx)
  246.         if( p_vout->output.i_rmask == 0x7c00 )
  247.         {
  248.             /* 15bpp 5/5/5 */
  249.             for ( i_x = p_vout->render.i_width / 8; i_x--; )
  250.             {
  251.                 __asm__( MMX_INIT_16
  252.                          : : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
  253.                 __asm__( ".align 8"
  254.                          MMX_YUV_MUL
  255.                          MMX_YUV_ADD
  256.                          MMX_UNPACK_15
  257.                          : : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
  258.                 p_y += 8;
  259.                 p_u += 4;
  260.                 p_v += 4;
  261.                 p_buffer += 8;
  262.             }
  263.         }
  264.         else
  265.         {
  266.             /* 16bpp 5/6/5 */
  267.             for ( i_x = p_vout->render.i_width / 8; i_x--; )
  268.             {
  269.                 __asm__( MMX_INIT_16
  270.                          : : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
  271.                 __asm__( ".align 8"
  272.                          MMX_YUV_MUL
  273.                          MMX_YUV_ADD
  274.                          MMX_UNPACK_16
  275.                          : : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
  276.                 p_y += 8;
  277.                 p_u += 4;
  278.                 p_v += 4;
  279.                 p_buffer += 8;
  280.             }
  281.         }
  282. #endif
  283.         /* Here we do some unaligned reads and duplicate conversions, but
  284.          * at least we have all the pixels */
  285.         if( i_rewind )
  286.         {
  287.             p_y -= i_rewind;
  288.             p_u -= i_rewind >> 1;
  289.             p_v -= i_rewind >> 1;
  290.             p_buffer -= i_rewind;
  291. #if defined (MODULE_NAME_IS_i420_rgb)
  292.             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
  293.             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
  294.             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
  295.             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
  296. #elif defined (MODULE_NAME_IS_i420_rgb_mmx)
  297.             __asm__( MMX_INIT_16
  298.                      : : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
  299.             if( p_vout->output.i_rmask == 0x7c00 )
  300.             {
  301.                 /* 15bpp 5/5/5 */
  302.                 __asm__( ".align 8"
  303.                          MMX_YUV_MUL
  304.                          MMX_YUV_ADD
  305.                          MMX_UNPACK_15
  306.                          : : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
  307.             }
  308.             else
  309.             {
  310.                 /* 16bpp 5/6/5 */
  311.                 __asm__( ".align 8"
  312.                          MMX_YUV_MUL
  313.                          MMX_YUV_ADD
  314.                          MMX_UNPACK_16
  315.                          : : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
  316.             }
  317.             p_y += 8;
  318.             p_u += 4;
  319.             p_v += 4;
  320.             p_buffer += 8;
  321. #endif
  322.         }
  323.         SCALE_WIDTH;
  324.         SCALE_HEIGHT( 420, 2 );
  325.         p_y += i_source_margin;
  326.         if( i_y % 2 )
  327.         {
  328.             p_u += i_source_margin_c;
  329.             p_v += i_source_margin_c;
  330.         }
  331.     }
  332. }
  333. /*****************************************************************************
  334.  * I420_RGB32: color YUV 4:2:0 to RGB 32 bpp
  335.  *****************************************************************************
  336.  * Horizontal alignment needed:
  337.  *  - input: 8 pixels (8 Y bytes, 4 U/V bytes), margins not allowed
  338.  *  - output: 1 pixel (2 bytes), margins allowed
  339.  * Vertical alignment needed:
  340.  *  - input: 2 lines (2 Y lines, 1 U/V line)
  341.  *  - output: 1 line
  342.  *****************************************************************************/
  343. void E_(I420_RGB32)( vout_thread_t *p_vout, picture_t *p_src,
  344.                                             picture_t *p_dest )
  345. {
  346.     /* We got this one from the old arguments */
  347.     uint32_t *p_pic = (uint32_t*)p_dest->p->p_pixels;
  348.     uint8_t  *p_y   = p_src->Y_PIXELS;
  349.     uint8_t  *p_u   = p_src->U_PIXELS;
  350.     uint8_t  *p_v   = p_src->V_PIXELS;
  351.     vlc_bool_t  b_hscale;                         /* horizontal scaling type */
  352.     unsigned int i_vscale;                          /* vertical scaling type */
  353.     unsigned int i_x, i_y;                /* horizontal and vertical indexes */
  354.     int         i_right_margin;
  355.     int         i_rewind;
  356.     int         i_scale_count;                       /* scale modulo counter */
  357.     int         i_chroma_width = p_vout->render.i_width / 2; /* chroma width */
  358.     uint32_t *  p_pic_start;       /* beginning of the current line for copy */
  359. #if defined (MODULE_NAME_IS_i420_rgb)
  360.     int         i_uval, i_vval;                           /* U and V samples */
  361.     int         i_red, i_green, i_blue;          /* U and V modified samples */
  362.     uint32_t *  p_yuv = p_vout->chroma.p_sys->p_rgb32;
  363.     uint32_t *  p_ybase;                     /* Y dependant conversion table */
  364. #endif
  365.     /* Conversion buffer pointer */
  366.     uint32_t *  p_buffer_start = (uint32_t*)p_vout->chroma.p_sys->p_buffer;
  367.     uint32_t *  p_buffer;
  368.     /* Offset array pointer */
  369.     int *       p_offset_start = p_vout->chroma.p_sys->p_offset;
  370.     int *       p_offset;
  371.     const int i_source_margin = p_src->p[0].i_pitch
  372.                                  - p_src->p[0].i_visible_pitch;
  373.     const int i_source_margin_c = p_src->p[1].i_pitch
  374.                                  - p_src->p[1].i_visible_pitch;
  375.     i_right_margin = p_dest->p->i_pitch - p_dest->p->i_visible_pitch;
  376.     if( p_vout->render.i_width & 7 )
  377.     {
  378.         i_rewind = 8 - ( p_vout->render.i_width & 7 );
  379.     }
  380.     else
  381.     {
  382.         i_rewind = 0;
  383.     }
  384.     /* Rule: when a picture of size (x1,y1) with aspect ratio r1 is rendered
  385.      * on a picture of size (x2,y2) with aspect ratio r2, if x1 grows to x1'
  386.      * then y1 grows to y1' = x1' * y2/x2 * r2/r1 */
  387.     SetOffset( p_vout->render.i_width, p_vout->render.i_height,
  388.                p_vout->output.i_width, p_vout->output.i_height,
  389.                &b_hscale, &i_vscale, p_offset_start );
  390.     /*
  391.      * Perform conversion
  392.      */
  393.     i_scale_count = ( i_vscale == 1 ) ?
  394.                     p_vout->output.i_height : p_vout->render.i_height;
  395.     for( i_y = 0; i_y < p_vout->render.i_height; i_y++ )
  396.     {
  397.         p_pic_start = p_pic;
  398.         p_buffer = b_hscale ? p_buffer_start : p_pic;
  399.         for ( i_x = p_vout->render.i_width / 8; i_x--; )
  400.         {
  401. #if defined (MODULE_NAME_IS_i420_rgb)
  402.             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
  403.             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
  404.             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
  405.             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
  406. #elif defined (MODULE_NAME_IS_i420_rgb_mmx)
  407.             __asm__( MMX_INIT_32
  408.                      : : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
  409.             __asm__( ".align 8"
  410.                      MMX_YUV_MUL
  411.                      MMX_YUV_ADD
  412.                      MMX_UNPACK_32
  413.                      : : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
  414.             p_y += 8;
  415.             p_u += 4;
  416.             p_v += 4;
  417.             p_buffer += 8;
  418. #endif
  419.         }
  420.         /* Here we do some unaligned reads and duplicate conversions, but
  421.          * at least we have all the pixels */
  422.         if( i_rewind )
  423.         {
  424.             p_y -= i_rewind;
  425.             p_u -= i_rewind >> 1;
  426.             p_v -= i_rewind >> 1;
  427.             p_buffer -= i_rewind;
  428. #if defined (MODULE_NAME_IS_i420_rgb)
  429.             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
  430.             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
  431.             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
  432.             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
  433. #elif defined (MODULE_NAME_IS_i420_rgb_mmx)
  434.             __asm__( MMX_INIT_32
  435.                      : : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
  436.             __asm__( ".align 8"
  437.                      MMX_YUV_MUL
  438.                      MMX_YUV_ADD
  439.                      MMX_UNPACK_32
  440.                      : : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
  441.             p_y += 8;
  442.             p_u += 4;
  443.             p_v += 4;
  444.             p_buffer += 8;
  445. #endif
  446.         }
  447.         SCALE_WIDTH;
  448.         SCALE_HEIGHT( 420, 4 );
  449.         p_y += i_source_margin;
  450.         if( i_y % 2 )
  451.         {
  452.             p_u += i_source_margin_c;
  453.             p_v += i_source_margin_c;
  454.         }
  455.     }
  456. }
  457. /* Following functions are local */
  458. /*****************************************************************************
  459.  * SetOffset: build offset array for conversion functions
  460.  *****************************************************************************
  461.  * This function will build an offset array used in later conversion functions.
  462.  * It will also set horizontal and vertical scaling indicators.
  463.  *****************************************************************************/
  464. static void SetOffset( int i_width, int i_height, int i_pic_width,
  465.                        int i_pic_height, vlc_bool_t *pb_hscale,
  466.                        int *pi_vscale, int *p_offset )
  467. {
  468.     int i_x;                                    /* x position in destination */
  469.     int i_scale_count;                                     /* modulo counter */
  470.     /*
  471.      * Prepare horizontal offset array
  472.      */
  473.     if( i_pic_width - i_width == 0 )
  474.     {
  475.         /* No horizontal scaling: YUV conversion is done directly to picture */
  476.         *pb_hscale = 0;
  477.     }
  478.     else if( i_pic_width - i_width > 0 )
  479.     {
  480.         /* Prepare scaling array for horizontal extension */
  481.         *pb_hscale = 1;
  482.         i_scale_count = i_pic_width;
  483.         for( i_x = i_width; i_x--; )
  484.         {
  485.             while( (i_scale_count -= i_width) > 0 )
  486.             {
  487.                 *p_offset++ = 0;
  488.             }
  489.             *p_offset++ = 1;
  490.             i_scale_count += i_pic_width;
  491.         }
  492.     }
  493.     else /* if( i_pic_width - i_width < 0 ) */
  494.     {
  495.         /* Prepare scaling array for horizontal reduction */
  496.         *pb_hscale = 1;
  497.         i_scale_count = i_width;
  498.         for( i_x = i_pic_width; i_x--; )
  499.         {
  500.             *p_offset = 1;
  501.             while( (i_scale_count -= i_pic_width) > 0 )
  502.             {
  503.                 *p_offset += 1;
  504.             }
  505.             p_offset++;
  506.             i_scale_count += i_width;
  507.         }
  508.     }
  509.     /*
  510.      * Set vertical scaling indicator
  511.      */
  512.     if( i_pic_height - i_height == 0 )
  513.     {
  514.         *pi_vscale = 0;
  515.     }
  516.     else if( i_pic_height - i_height > 0 )
  517.     {
  518.         *pi_vscale = 1;
  519.     }
  520.     else /* if( i_pic_height - i_height < 0 ) */
  521.     {
  522.         *pi_vscale = -1;
  523.     }
  524. }