i420_rgb16.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:61k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * i420_rgb16.c : YUV to bitmap RGB conversion module for vlc
  3.  *****************************************************************************
  4.  * Copyright (C) 2000 the VideoLAN team
  5.  * $Id: 3f0c6734f5d3a20d09399c397a27a860edc1ce45 $
  6.  *
  7.  * Authors: Samuel Hocevar <sam@zoy.org>
  8.  *          Damien Fouilleul <damienf@videolan.org>
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  23.  *****************************************************************************/
  24. /*****************************************************************************
  25.  * Preamble
  26.  *****************************************************************************/
  27. #ifdef HAVE_CONFIG_H
  28. # include "config.h"
  29. #endif
  30. #include <vlc/vlc.h>
  31. #include <vlc_filter.h>
  32. #include <vlc_vout.h>
  33. #include "i420_rgb.h"
  34. #if defined (MODULE_NAME_IS_i420_rgb)
  35. #   include "i420_rgb_c.h"
  36. #elif defined (MODULE_NAME_IS_i420_rgb_mmx)
  37. #   include "i420_rgb_mmx.h"
  38. #elif defined (MODULE_NAME_IS_i420_rgb_sse2)
  39. #   include "i420_rgb_mmx.h"
  40. #endif
  41. static void SetOffset( int, int, int, int, bool *,
  42.                        unsigned int *, int * );
  43. #if defined (MODULE_NAME_IS_i420_rgb)
  44. /*****************************************************************************
  45.  * I420_RGB16: color YUV 4:2:0 to RGB 16 bpp with dithering
  46.  *****************************************************************************
  47.  * Horizontal alignment needed:
  48.  *  - input: 8 pixels (8 Y bytes, 4 U/V bytes), margins not allowed
  49.  *  - output: 1 pixel (2 bytes), margins allowed
  50.  * Vertical alignment needed:
  51.  *  - input: 2 lines (2 Y lines, 1 U/V line)
  52.  *  - output: 1 line
  53.  *****************************************************************************/
  54. void I420_RGB16_dither( filter_t *p_filter, picture_t *p_src,
  55.                                                 picture_t *p_dest )
  56. {
  57.     /* We got this one from the old arguments */
  58.     uint16_t *p_pic = (uint16_t*)p_dest->p->p_pixels;
  59.     uint8_t  *p_y   = p_src->Y_PIXELS;
  60.     uint8_t  *p_u   = p_src->U_PIXELS;
  61.     uint8_t  *p_v   = p_src->V_PIXELS;
  62.     bool   b_hscale;                        /* horizontal scaling type */
  63.     unsigned int i_vscale;                          /* vertical scaling type */
  64.     unsigned int i_x, i_y;                /* horizontal and vertical indexes */
  65.     unsigned int i_real_y;                                          /* y % 4 */
  66.     int         i_right_margin;
  67.     int         i_rewind;
  68.     int         i_scale_count;                       /* scale modulo counter */
  69.     int         i_chroma_width = p_filter->fmt_in.video.i_width / 2; /* chroma width */
  70.     uint16_t *  p_pic_start;       /* beginning of the current line for copy */
  71.     int         i_uval, i_vval;                           /* U and V samples */
  72.     int         i_red, i_green, i_blue;          /* U and V modified samples */
  73.     uint16_t *  p_yuv = p_filter->p_sys->p_rgb16;
  74.     uint16_t *  p_ybase;                     /* Y dependant conversion table */
  75.     /* Conversion buffer pointer */
  76.     uint16_t *  p_buffer_start = (uint16_t*)p_filter->p_sys->p_buffer;
  77.     uint16_t *  p_buffer;
  78.     /* Offset array pointer */
  79.     int *       p_offset_start = p_filter->p_sys->p_offset;
  80.     int *       p_offset;
  81.     const int i_source_margin = p_src->p[0].i_pitch
  82.                                  - p_src->p[0].i_visible_pitch;
  83.     const int i_source_margin_c = p_src->p[1].i_pitch
  84.                                  - p_src->p[1].i_visible_pitch;
  85.     /* The dithering matrices */
  86.     int dither10[4] = {  0x0,  0x8,  0x2,  0xa };
  87.     int dither11[4] = {  0xc,  0x4,  0xe,  0x6 };
  88.     int dither12[4] = {  0x3,  0xb,  0x1,  0x9 };
  89.     int dither13[4] = {  0xf,  0x7,  0xd,  0x5 };
  90.     for(i_x = 0; i_x < 4; i_x++)
  91.     {
  92.         dither10[i_x] = dither10[i_x] << (SHIFT - 4 + p_filter->fmt_out.video.i_rrshift);
  93.         dither11[i_x] = dither11[i_x] << (SHIFT - 4 + p_filter->fmt_out.video.i_rrshift);
  94.         dither12[i_x] = dither12[i_x] << (SHIFT - 4 + p_filter->fmt_out.video.i_rrshift);
  95.         dither13[i_x] = dither13[i_x] << (SHIFT - 4 + p_filter->fmt_out.video.i_rrshift);
  96.     }
  97.     i_right_margin = p_dest->p->i_pitch - p_dest->p->i_visible_pitch;
  98.     if( p_filter->fmt_in.video.i_width & 7 )
  99.     {
  100.         i_rewind = 8 - ( p_filter->fmt_in.video.i_width & 7 );
  101.     }
  102.     else
  103.     {
  104.         i_rewind = 0;
  105.     }
  106.     /* Rule: when a picture of size (x1,y1) with aspect ratio r1 is rendered
  107.      * on a picture of size (x2,y2) with aspect ratio r2, if x1 grows to x1'
  108.      * then y1 grows to y1' = x1' * y2/x2 * r2/r1 */
  109.     SetOffset( p_filter->fmt_in.video.i_width,
  110.                p_filter->fmt_in.video.i_height,
  111.                p_filter->fmt_out.video.i_width,
  112.                p_filter->fmt_out.video.i_height,
  113.                &b_hscale, &i_vscale, p_offset_start );
  114.     /*
  115.      * Perform conversion
  116.      */
  117.     i_scale_count = ( i_vscale == 1 ) ?
  118.                     p_filter->fmt_out.video.i_height :
  119.                     p_filter->fmt_in.video.i_height;
  120.     for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
  121.     {
  122.         i_real_y = i_y & 0x3;
  123.         p_pic_start = p_pic;
  124.         p_buffer = b_hscale ? p_buffer_start : p_pic;
  125.         for ( i_x = p_filter->fmt_in.video.i_width / 8; i_x--; )
  126.         {
  127.             int *p_dither = dither10;
  128.             CONVERT_YUV_PIXEL_DITHER(2);
  129.             p_dither = dither11;
  130.             CONVERT_Y_PIXEL_DITHER(2);
  131.             p_dither = dither12;
  132.             CONVERT_YUV_PIXEL_DITHER(2);
  133.             p_dither = dither13;
  134.             CONVERT_Y_PIXEL_DITHER(2);
  135.             p_dither = dither10;
  136.             CONVERT_YUV_PIXEL_DITHER(2);
  137.             p_dither = dither11;
  138.             CONVERT_Y_PIXEL_DITHER(2);
  139.             p_dither = dither12;
  140.             CONVERT_YUV_PIXEL_DITHER(2);
  141.             p_dither = dither13;
  142.             CONVERT_Y_PIXEL_DITHER(2);
  143.         }
  144.         /* Here we do some unaligned reads and duplicate conversions, but
  145.          * at least we have all the pixels */
  146.         if( i_rewind )
  147.         {
  148.             int *p_dither = dither10;
  149.             p_y -= i_rewind;
  150.             p_u -= i_rewind >> 1;
  151.             p_v -= i_rewind >> 1;
  152.             p_buffer -= i_rewind;
  153.             CONVERT_YUV_PIXEL_DITHER(2);
  154.             p_dither = dither11;
  155.             CONVERT_Y_PIXEL_DITHER(2);
  156.             p_dither = dither12;
  157.             CONVERT_YUV_PIXEL_DITHER(2);
  158.             p_dither = dither13;
  159.             CONVERT_Y_PIXEL_DITHER(2);
  160.             p_dither = dither10;
  161.             CONVERT_YUV_PIXEL_DITHER(2);
  162.             p_dither = dither11;
  163.             CONVERT_Y_PIXEL_DITHER(2);
  164.             p_dither = dither12;
  165.             CONVERT_YUV_PIXEL_DITHER(2);
  166.             p_dither = dither13;
  167.             CONVERT_Y_PIXEL_DITHER(2);
  168.         }
  169.         SCALE_WIDTH;
  170.         SCALE_HEIGHT( 420, 2 );
  171.         p_y += i_source_margin;
  172.         if( i_y % 2 )
  173.         {
  174.             p_u += i_source_margin_c;
  175.             p_v += i_source_margin_c;
  176.         }
  177.     }
  178. }
  179. #endif
  180. /*****************************************************************************
  181.  * I420_RGB16: color YUV 4:2:0 to RGB 16 bpp
  182.  *****************************************************************************
  183.  * Horizontal alignment needed:
  184.  *  - input: 8 pixels (8 Y bytes, 4 U/V bytes), margins not allowed
  185.  *  - output: 1 pixel (2 bytes), margins allowed
  186.  * Vertical alignment needed:
  187.  *  - input: 2 lines (2 Y lines, 1 U/V line)
  188.  *  - output: 1 line
  189.  *****************************************************************************/
  190. #if defined (MODULE_NAME_IS_i420_rgb)
  191. void I420_RGB16( filter_t *p_filter, picture_t *p_src,
  192.                                          picture_t *p_dest )
  193. {
  194.     /* We got this one from the old arguments */
  195.     uint16_t *p_pic = (uint16_t*)p_dest->p->p_pixels;
  196.     uint8_t  *p_y   = p_src->Y_PIXELS;
  197.     uint8_t  *p_u   = p_src->U_PIXELS;
  198.     uint8_t  *p_v   = p_src->V_PIXELS;
  199.     bool  b_hscale;                         /* horizontal scaling type */
  200.     unsigned int i_vscale;                          /* vertical scaling type */
  201.     unsigned int i_x, i_y;                /* horizontal and vertical indexes */
  202.     int         i_right_margin;
  203.     int         i_rewind;
  204.     int         i_scale_count;                       /* scale modulo counter */
  205.     int         i_chroma_width = p_filter->fmt_in.video.i_width / 2; /* chroma width */
  206.     uint16_t *  p_pic_start;       /* beginning of the current line for copy */
  207.     int         i_uval, i_vval;                           /* U and V samples */
  208.     int         i_red, i_green, i_blue;          /* U and V modified samples */
  209.     uint16_t *  p_yuv = p_filter->p_sys->p_rgb16;
  210.     uint16_t *  p_ybase;                     /* Y dependant conversion table */
  211.     /* Conversion buffer pointer */
  212.     uint16_t *  p_buffer_start = (uint16_t*)p_filter->p_sys->p_buffer;
  213.     uint16_t *  p_buffer;
  214.     /* Offset array pointer */
  215.     int *       p_offset_start = p_filter->p_sys->p_offset;
  216.     int *       p_offset;
  217.     const int i_source_margin = p_src->p[0].i_pitch
  218.                                  - p_src->p[0].i_visible_pitch;
  219.     const int i_source_margin_c = p_src->p[1].i_pitch
  220.                                  - p_src->p[1].i_visible_pitch;
  221.     i_right_margin = p_dest->p->i_pitch - p_dest->p->i_visible_pitch;
  222.     if( p_filter->fmt_in.video.i_width & 7 )
  223.     {
  224.         i_rewind = 8 - ( p_filter->fmt_in.video.i_width & 7 );
  225.     }
  226.     else
  227.     {
  228.         i_rewind = 0;
  229.     }
  230.     /* Rule: when a picture of size (x1,y1) with aspect ratio r1 is rendered
  231.      * on a picture of size (x2,y2) with aspect ratio r2, if x1 grows to x1'
  232.      * then y1 grows to y1' = x1' * y2/x2 * r2/r1 */
  233.     SetOffset( p_filter->fmt_in.video.i_width,
  234.                p_filter->fmt_in.video.i_height,
  235.                p_filter->fmt_out.video.i_width,
  236.                p_filter->fmt_out.video.i_height,
  237.                &b_hscale, &i_vscale, p_offset_start );
  238.     /*
  239.      * Perform conversion
  240.      */
  241.     i_scale_count = ( i_vscale == 1 ) ?
  242.                     p_filter->fmt_out.video.i_height :
  243.                     p_filter->fmt_in.video.i_height;
  244.     for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
  245.     {
  246.         p_pic_start = p_pic;
  247.         p_buffer = b_hscale ? p_buffer_start : p_pic;
  248.         for ( i_x = p_filter->fmt_in.video.i_width / 8; i_x--; )
  249.         {
  250.             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
  251.             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
  252.             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
  253.             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
  254.         }
  255.         /* Here we do some unaligned reads and duplicate conversions, but
  256.          * at least we have all the pixels */
  257.         if( i_rewind )
  258.         {
  259.             p_y -= i_rewind;
  260.             p_u -= i_rewind >> 1;
  261.             p_v -= i_rewind >> 1;
  262.             p_buffer -= i_rewind;
  263.             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
  264.             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
  265.             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
  266.             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
  267.         }
  268.         SCALE_WIDTH;
  269.         SCALE_HEIGHT( 420, 2 );
  270.         p_y += i_source_margin;
  271.         if( i_y % 2 )
  272.         {
  273.             p_u += i_source_margin_c;
  274.             p_v += i_source_margin_c;
  275.         }
  276.     }
  277. }
  278. #else // ! defined (MODULE_NAME_IS_i420_rgb)
  279. void I420_R5G5B5( filter_t *p_filter, picture_t *p_src,
  280.                                           picture_t *p_dest )
  281. {
  282.     /* We got this one from the old arguments */
  283.     uint16_t *p_pic = (uint16_t*)p_dest->p->p_pixels;
  284.     uint8_t  *p_y   = p_src->Y_PIXELS;
  285.     uint8_t  *p_u   = p_src->U_PIXELS;
  286.     uint8_t  *p_v   = p_src->V_PIXELS;
  287.     bool  b_hscale;                         /* horizontal scaling type */
  288.     unsigned int i_vscale;                          /* vertical scaling type */
  289.     unsigned int i_x, i_y;                /* horizontal and vertical indexes */
  290.     int         i_right_margin;
  291.     int         i_rewind;
  292.     int         i_scale_count;                       /* scale modulo counter */
  293.     int         i_chroma_width = p_filter->fmt_in.video.i_width / 2; /* chroma width */
  294.     uint16_t *  p_pic_start;       /* beginning of the current line for copy */
  295.     /* Conversion buffer pointer */
  296.     uint16_t *  p_buffer_start = (uint16_t*)p_filter->p_sys->p_buffer;
  297.     uint16_t *  p_buffer;
  298.     /* Offset array pointer */
  299.     int *       p_offset_start = p_filter->p_sys->p_offset;
  300.     int *       p_offset;
  301.     const int i_source_margin = p_src->p[0].i_pitch
  302.                                  - p_src->p[0].i_visible_pitch;
  303.     const int i_source_margin_c = p_src->p[1].i_pitch
  304.                                  - p_src->p[1].i_visible_pitch;
  305.     i_right_margin = p_dest->p->i_pitch - p_dest->p->i_visible_pitch;
  306.     /* Rule: when a picture of size (x1,y1) with aspect ratio r1 is rendered
  307.      * on a picture of size (x2,y2) with aspect ratio r2, if x1 grows to x1'
  308.      * then y1 grows to y1' = x1' * y2/x2 * r2/r1 */
  309.     SetOffset( p_filter->fmt_in.video.i_width,
  310.                p_filter->fmt_in.video.i_height,
  311.                p_filter->fmt_out.video.i_width,
  312.                p_filter->fmt_out.video.i_height,
  313.                &b_hscale, &i_vscale, p_offset_start );
  314.     /*
  315.      * Perform conversion
  316.      */
  317.     i_scale_count = ( i_vscale == 1 ) ?
  318.                     p_filter->fmt_out.video.i_height :
  319.                     p_filter->fmt_in.video.i_height;
  320. #if defined (MODULE_NAME_IS_i420_rgb_sse2)
  321.     if( p_filter->fmt_in.video.i_width & 15 )
  322.     {
  323.         i_rewind = 16 - ( p_filter->fmt_in.video.i_width & 15 );
  324.     }
  325.     else
  326.     {
  327.         i_rewind = 0;
  328.     }
  329.     /*
  330.     ** SSE2 128 bits fetch/store instructions are faster
  331.     ** if memory access is 16 bytes aligned
  332.     */
  333.     p_buffer = b_hscale ? p_buffer_start : p_pic;
  334.     if( 0 == (15 & (p_src->p[Y_PLANE].i_pitch|
  335.                     p_dest->p->i_pitch|
  336.                     ((intptr_t)p_y)|
  337.                     ((intptr_t)p_buffer))) )
  338.     {
  339.         /* use faster SSE2 aligned fetch and store */
  340.         for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
  341.         {
  342.             p_pic_start = p_pic;
  343.             for ( i_x = p_filter->fmt_in.video.i_width/16; i_x--; )
  344.             {
  345.                 SSE2_CALL (
  346.                     SSE2_INIT_16_ALIGNED
  347.                     SSE2_YUV_MUL
  348.                     SSE2_YUV_ADD
  349.                     SSE2_UNPACK_15_ALIGNED
  350.                 );
  351.                 p_y += 16;
  352.                 p_u += 8;
  353.                 p_v += 8;
  354.                 p_buffer += 16;
  355.             }
  356.             /* Here we do some unaligned reads and duplicate conversions, but
  357.              * at least we have all the pixels */
  358.             if( i_rewind )
  359.             {
  360.                 p_y -= i_rewind;
  361.                 p_u -= i_rewind >> 1;
  362.                 p_v -= i_rewind >> 1;
  363.                 p_buffer -= i_rewind;
  364.                 SSE2_CALL (
  365.                     SSE2_INIT_16_UNALIGNED
  366.                     SSE2_YUV_MUL
  367.                     SSE2_YUV_ADD
  368.                     SSE2_UNPACK_15_UNALIGNED
  369.                 );
  370.                 p_y += 16;
  371.                 p_u += 8;
  372.                 p_v += 8;
  373.             }
  374.             SCALE_WIDTH;
  375.             SCALE_HEIGHT( 420, 2 );
  376.             p_y += i_source_margin;
  377.             if( i_y % 2 )
  378.             {
  379.                 p_u += i_source_margin_c;
  380.                 p_v += i_source_margin_c;
  381.             }
  382.             p_buffer = b_hscale ? p_buffer_start : p_pic;
  383.         }
  384.     }
  385.     else
  386.     {
  387.         /* use slower SSE2 unaligned fetch and store */
  388.         for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
  389.         {
  390.             p_pic_start = p_pic;
  391.             p_buffer = b_hscale ? p_buffer_start : p_pic;
  392.             for ( i_x = p_filter->fmt_in.video.i_width/16; i_x--; )
  393.             {
  394.                 SSE2_CALL (
  395.                     SSE2_INIT_16_UNALIGNED
  396.                     SSE2_YUV_MUL
  397.                     SSE2_YUV_ADD
  398.                     SSE2_UNPACK_15_UNALIGNED
  399.                 );
  400.                 p_y += 16;
  401.                 p_u += 8;
  402.                 p_v += 8;
  403.                 p_buffer += 16;
  404.             }
  405.             /* Here we do some unaligned reads and duplicate conversions, but
  406.              * at least we have all the pixels */
  407.             if( i_rewind )
  408.             {
  409.                 p_y -= i_rewind;
  410.                 p_u -= i_rewind >> 1;
  411.                 p_v -= i_rewind >> 1;
  412.                 p_buffer -= i_rewind;
  413.                 SSE2_CALL (
  414.                     SSE2_INIT_16_UNALIGNED
  415.                     SSE2_YUV_MUL
  416.                     SSE2_YUV_ADD
  417.                     SSE2_UNPACK_15_UNALIGNED
  418.                 );
  419.                 p_y += 16;
  420.                 p_u += 8;
  421.                 p_v += 8;
  422.             }
  423.             SCALE_WIDTH;
  424.             SCALE_HEIGHT( 420, 2 );
  425.             p_y += i_source_margin;
  426.             if( i_y % 2 )
  427.             {
  428.                 p_u += i_source_margin_c;
  429.                 p_v += i_source_margin_c;
  430.             }
  431.             p_buffer = b_hscale ? p_buffer_start : p_pic;
  432.         }
  433.     }
  434.     /* make sure all SSE2 stores are visible thereafter */
  435.     SSE2_END;
  436. #else // defined (MODULE_NAME_IS_i420_rgb_mmx)
  437.     if( p_filter->fmt_in.video.i_width & 7 )
  438.     {
  439.         i_rewind = 8 - ( p_filter->fmt_in.video.i_width & 7 );
  440.     }
  441.     else
  442.     {
  443.         i_rewind = 0;
  444.     }
  445.     for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
  446.     {
  447.         p_pic_start = p_pic;
  448.         p_buffer = b_hscale ? p_buffer_start : p_pic;
  449.         for ( i_x = p_filter->fmt_in.video.i_width / 8; i_x--; )
  450.         {
  451.             MMX_CALL (
  452.                 MMX_INIT_16
  453.                 MMX_YUV_MUL
  454.                 MMX_YUV_ADD
  455.                 MMX_UNPACK_15
  456.             );
  457.             p_y += 8;
  458.             p_u += 4;
  459.             p_v += 4;
  460.             p_buffer += 8;
  461.         }
  462.         /* Here we do some unaligned reads and duplicate conversions, but
  463.          * at least we have all the pixels */
  464.         if( i_rewind )
  465.         {
  466.             p_y -= i_rewind;
  467.             p_u -= i_rewind >> 1;
  468.             p_v -= i_rewind >> 1;
  469.             p_buffer -= i_rewind;
  470.             MMX_CALL (
  471.                 MMX_INIT_16
  472.                 MMX_YUV_MUL
  473.                 MMX_YUV_ADD
  474.                 MMX_UNPACK_15
  475.             );
  476.             p_y += 8;
  477.             p_u += 4;
  478.             p_v += 4;
  479.             p_buffer += 8;
  480.         }
  481.         SCALE_WIDTH;
  482.         SCALE_HEIGHT( 420, 2 );
  483.         p_y += i_source_margin;
  484.         if( i_y % 2 )
  485.         {
  486.             p_u += i_source_margin_c;
  487.             p_v += i_source_margin_c;
  488.         }
  489.     }
  490.     /* re-enable FPU registers */
  491.     MMX_END;
  492. #endif
  493. }
  494. void I420_R5G6B5( filter_t *p_filter, picture_t *p_src,
  495.                                           picture_t *p_dest )
  496. {
  497.     /* We got this one from the old arguments */
  498.     uint16_t *p_pic = (uint16_t*)p_dest->p->p_pixels;
  499.     uint8_t  *p_y   = p_src->Y_PIXELS;
  500.     uint8_t  *p_u   = p_src->U_PIXELS;
  501.     uint8_t  *p_v   = p_src->V_PIXELS;
  502.     bool  b_hscale;                         /* horizontal scaling type */
  503.     unsigned int i_vscale;                          /* vertical scaling type */
  504.     unsigned int i_x, i_y;                /* horizontal and vertical indexes */
  505.     int         i_right_margin;
  506.     int         i_rewind;
  507.     int         i_scale_count;                       /* scale modulo counter */
  508.     int         i_chroma_width = p_filter->fmt_in.video.i_width / 2; /* chroma width */
  509.     uint16_t *  p_pic_start;       /* beginning of the current line for copy */
  510.     /* Conversion buffer pointer */
  511.     uint16_t *  p_buffer_start = (uint16_t*)p_filter->p_sys->p_buffer;
  512.     uint16_t *  p_buffer;
  513.     /* Offset array pointer */
  514.     int *       p_offset_start = p_filter->p_sys->p_offset;
  515.     int *       p_offset;
  516.     const int i_source_margin = p_src->p[0].i_pitch
  517.                                  - p_src->p[0].i_visible_pitch;
  518.     const int i_source_margin_c = p_src->p[1].i_pitch
  519.                                  - p_src->p[1].i_visible_pitch;
  520.     i_right_margin = p_dest->p->i_pitch - p_dest->p->i_visible_pitch;
  521.     /* Rule: when a picture of size (x1,y1) with aspect ratio r1 is rendered
  522.      * on a picture of size (x2,y2) with aspect ratio r2, if x1 grows to x1'
  523.      * then y1 grows to y1' = x1' * y2/x2 * r2/r1 */
  524.     SetOffset( p_filter->fmt_in.video.i_width,
  525.                p_filter->fmt_in.video.i_height,
  526.                p_filter->fmt_out.video.i_width,
  527.                p_filter->fmt_out.video.i_height,
  528.                &b_hscale, &i_vscale, p_offset_start );
  529.     /*
  530.      * Perform conversion
  531.      */
  532.     i_scale_count = ( i_vscale == 1 ) ?
  533.                     p_filter->fmt_out.video.i_height :
  534.                     p_filter->fmt_in.video.i_height;
  535. #if defined (MODULE_NAME_IS_i420_rgb_sse2)
  536.     if( p_filter->fmt_in.video.i_width & 15 )
  537.     {
  538.         i_rewind = 16 - ( p_filter->fmt_in.video.i_width & 15 );
  539.     }
  540.     else
  541.     {
  542.         i_rewind = 0;
  543.     }
  544.     /*
  545.     ** SSE2 128 bits fetch/store instructions are faster
  546.     ** if memory access is 16 bytes aligned
  547.     */
  548.     p_buffer = b_hscale ? p_buffer_start : p_pic;
  549.     if( 0 == (15 & (p_src->p[Y_PLANE].i_pitch|
  550.                     p_dest->p->i_pitch|
  551.                     ((intptr_t)p_y)|
  552.                     ((intptr_t)p_buffer))) )
  553.     {
  554.         /* use faster SSE2 aligned fetch and store */
  555.         for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
  556.         {
  557.             p_pic_start = p_pic;
  558.             for ( i_x = p_filter->fmt_in.video.i_width/16; i_x--; )
  559.             {
  560.                 SSE2_CALL (
  561.                     SSE2_INIT_16_ALIGNED
  562.                     SSE2_YUV_MUL
  563.                     SSE2_YUV_ADD
  564.                     SSE2_UNPACK_16_ALIGNED
  565.                 );
  566.                 p_y += 16;
  567.                 p_u += 8;
  568.                 p_v += 8;
  569.                 p_buffer += 16;
  570.             }
  571.             /* Here we do some unaligned reads and duplicate conversions, but
  572.              * at least we have all the pixels */
  573.             if( i_rewind )
  574.             {
  575.                 p_y -= i_rewind;
  576.                 p_u -= i_rewind >> 1;
  577.                 p_v -= i_rewind >> 1;
  578.                 p_buffer -= i_rewind;
  579.                 SSE2_CALL (
  580.                     SSE2_INIT_16_UNALIGNED
  581.                     SSE2_YUV_MUL
  582.                     SSE2_YUV_ADD
  583.                     SSE2_UNPACK_16_UNALIGNED
  584.                 );
  585.                 p_y += 16;
  586.                 p_u += 8;
  587.                 p_v += 8;
  588.             }
  589.             SCALE_WIDTH;
  590.             SCALE_HEIGHT( 420, 2 );
  591.             p_y += i_source_margin;
  592.             if( i_y % 2 )
  593.             {
  594.                 p_u += i_source_margin_c;
  595.                 p_v += i_source_margin_c;
  596.             }
  597.             p_buffer = b_hscale ? p_buffer_start : p_pic;
  598.         }
  599.     }
  600.     else
  601.     {
  602.         /* use slower SSE2 unaligned fetch and store */
  603.         for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
  604.         {
  605.             p_pic_start = p_pic;
  606.             p_buffer = b_hscale ? p_buffer_start : p_pic;
  607.             for ( i_x = p_filter->fmt_in.video.i_width/16; i_x--; )
  608.             {
  609.                 SSE2_CALL(
  610.                     SSE2_INIT_16_UNALIGNED
  611.                     SSE2_YUV_MUL
  612.                     SSE2_YUV_ADD
  613.                     SSE2_UNPACK_16_UNALIGNED
  614.                 );
  615.                 p_y += 16;
  616.                 p_u += 8;
  617.                 p_v += 8;
  618.                 p_buffer += 16;
  619.             }
  620.             /* Here we do some unaligned reads and duplicate conversions, but
  621.              * at least we have all the pixels */
  622.             if( i_rewind )
  623.             {
  624.                 p_y -= i_rewind;
  625.                 p_u -= i_rewind >> 1;
  626.                 p_v -= i_rewind >> 1;
  627.                 p_buffer -= i_rewind;
  628.                 SSE2_CALL(
  629.                     SSE2_INIT_16_UNALIGNED
  630.                     SSE2_YUV_MUL
  631.                     SSE2_YUV_ADD
  632.                     SSE2_UNPACK_16_UNALIGNED
  633.                 );
  634.                 p_y += 16;
  635.                 p_u += 8;
  636.                 p_v += 8;
  637.             }
  638.             SCALE_WIDTH;
  639.             SCALE_HEIGHT( 420, 2 );
  640.             p_y += i_source_margin;
  641.             if( i_y % 2 )
  642.             {
  643.                 p_u += i_source_margin_c;
  644.                 p_v += i_source_margin_c;
  645.             }
  646.             p_buffer = b_hscale ? p_buffer_start : p_pic;
  647.         }
  648.     }
  649.     /* make sure all SSE2 stores are visible thereafter */
  650.     SSE2_END;
  651. #else // defined (MODULE_NAME_IS_i420_rgb_mmx)
  652.     if( p_filter->fmt_in.video.i_width & 7 )
  653.     {
  654.         i_rewind = 8 - ( p_filter->fmt_in.video.i_width & 7 );
  655.     }
  656.     else
  657.     {
  658.         i_rewind = 0;
  659.     }
  660.     for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
  661.     {
  662.         p_pic_start = p_pic;
  663.         p_buffer = b_hscale ? p_buffer_start : p_pic;
  664.         for ( i_x = p_filter->fmt_in.video.i_width / 8; i_x--; )
  665.         {
  666.             MMX_CALL (
  667.                 MMX_INIT_16
  668.                 MMX_YUV_MUL
  669.                 MMX_YUV_ADD
  670.                 MMX_UNPACK_16
  671.             );
  672.             p_y += 8;
  673.             p_u += 4;
  674.             p_v += 4;
  675.             p_buffer += 8;
  676.         }
  677.         /* Here we do some unaligned reads and duplicate conversions, but
  678.          * at least we have all the pixels */
  679.         if( i_rewind )
  680.         {
  681.             p_y -= i_rewind;
  682.             p_u -= i_rewind >> 1;
  683.             p_v -= i_rewind >> 1;
  684.             p_buffer -= i_rewind;
  685.             MMX_CALL (
  686.                 MMX_INIT_16
  687.                 MMX_YUV_MUL
  688.                 MMX_YUV_ADD
  689.                 MMX_UNPACK_16
  690.             );
  691.             p_y += 8;
  692.             p_u += 4;
  693.             p_v += 4;
  694.             p_buffer += 8;
  695.         }
  696.         SCALE_WIDTH;
  697.         SCALE_HEIGHT( 420, 2 );
  698.         p_y += i_source_margin;
  699.         if( i_y % 2 )
  700.         {
  701.             p_u += i_source_margin_c;
  702.             p_v += i_source_margin_c;
  703.         }
  704.     }
  705.     /* re-enable FPU registers */
  706.     MMX_END;
  707. #endif
  708. }
  709. #endif
  710. /*****************************************************************************
  711.  * I420_RGB32: color YUV 4:2:0 to RGB 32 bpp
  712.  *****************************************************************************
  713.  * Horizontal alignment needed:
  714.  *  - input: 8 pixels (8 Y bytes, 4 U/V bytes), margins not allowed
  715.  *  - output: 1 pixel (2 bytes), margins allowed
  716.  * Vertical alignment needed:
  717.  *  - input: 2 lines (2 Y lines, 1 U/V line)
  718.  *  - output: 1 line
  719.  *****************************************************************************/
  720. #if defined (MODULE_NAME_IS_i420_rgb)
  721. void I420_RGB32( filter_t *p_filter, picture_t *p_src,
  722.                                          picture_t *p_dest )
  723. {
  724.     /* We got this one from the old arguments */
  725.     uint32_t *p_pic = (uint32_t*)p_dest->p->p_pixels;
  726.     uint8_t  *p_y   = p_src->Y_PIXELS;
  727.     uint8_t  *p_u   = p_src->U_PIXELS;
  728.     uint8_t  *p_v   = p_src->V_PIXELS;
  729.     bool  b_hscale;                         /* horizontal scaling type */
  730.     unsigned int i_vscale;                          /* vertical scaling type */
  731.     unsigned int i_x, i_y;                /* horizontal and vertical indexes */
  732.     int         i_right_margin;
  733.     int         i_rewind;
  734.     int         i_scale_count;                       /* scale modulo counter */
  735.     int         i_chroma_width = p_filter->fmt_in.video.i_width / 2; /* chroma width */
  736.     uint32_t *  p_pic_start;       /* beginning of the current line for copy */
  737.     int         i_uval, i_vval;                           /* U and V samples */
  738.     int         i_red, i_green, i_blue;          /* U and V modified samples */
  739.     uint32_t *  p_yuv = p_filter->p_sys->p_rgb32;
  740.     uint32_t *  p_ybase;                     /* Y dependant conversion table */
  741.     /* Conversion buffer pointer */
  742.     uint32_t *  p_buffer_start = (uint32_t*)p_filter->p_sys->p_buffer;
  743.     uint32_t *  p_buffer;
  744.     /* Offset array pointer */
  745.     int *       p_offset_start = p_filter->p_sys->p_offset;
  746.     int *       p_offset;
  747.     const int i_source_margin = p_src->p[0].i_pitch
  748.                                  - p_src->p[0].i_visible_pitch;
  749.     const int i_source_margin_c = p_src->p[1].i_pitch
  750.                                  - p_src->p[1].i_visible_pitch;
  751.     i_right_margin = p_dest->p->i_pitch - p_dest->p->i_visible_pitch;
  752.     if( p_filter->fmt_in.video.i_width & 7 )
  753.     {
  754.         i_rewind = 8 - ( p_filter->fmt_in.video.i_width & 7 );
  755.     }
  756.     else
  757.     {
  758.         i_rewind = 0;
  759.     }
  760.     /* Rule: when a picture of size (x1,y1) with aspect ratio r1 is rendered
  761.      * on a picture of size (x2,y2) with aspect ratio r2, if x1 grows to x1'
  762.      * then y1 grows to y1' = x1' * y2/x2 * r2/r1 */
  763.     SetOffset( p_filter->fmt_in.video.i_width,
  764.                p_filter->fmt_in.video.i_height,
  765.                p_filter->fmt_out.video.i_width,
  766.                p_filter->fmt_out.video.i_height,
  767.                &b_hscale, &i_vscale, p_offset_start );
  768.     /*
  769.      * Perform conversion
  770.      */
  771.     i_scale_count = ( i_vscale == 1 ) ?
  772.                     p_filter->fmt_out.video.i_height :
  773.                     p_filter->fmt_in.video.i_height;
  774.     for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
  775.     {
  776.         p_pic_start = p_pic;
  777.         p_buffer = b_hscale ? p_buffer_start : p_pic;
  778.         for ( i_x = p_filter->fmt_in.video.i_width / 8; i_x--; )
  779.         {
  780.             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
  781.             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
  782.             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
  783.             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
  784.         }
  785.         /* Here we do some unaligned reads and duplicate conversions, but
  786.          * at least we have all the pixels */
  787.         if( i_rewind )
  788.         {
  789.             p_y -= i_rewind;
  790.             p_u -= i_rewind >> 1;
  791.             p_v -= i_rewind >> 1;
  792.             p_buffer -= i_rewind;
  793.             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
  794.             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
  795.             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
  796.             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
  797.         }
  798.         SCALE_WIDTH;
  799.         SCALE_HEIGHT( 420, 4 );
  800.         p_y += i_source_margin;
  801.         if( i_y % 2 )
  802.         {
  803.             p_u += i_source_margin_c;
  804.             p_v += i_source_margin_c;
  805.         }
  806.     }
  807. }
  808. #else // defined (MODULE_NAME_IS_i420_rgb_mmx) || defined (MODULE_NAME_IS_i420_rgb_sse2)
  809. void I420_A8R8G8B8( filter_t *p_filter, picture_t *p_src,
  810.                                             picture_t *p_dest )
  811. {
  812.     /* We got this one from the old arguments */
  813.     uint32_t *p_pic = (uint32_t*)p_dest->p->p_pixels;
  814.     uint8_t  *p_y   = p_src->Y_PIXELS;
  815.     uint8_t  *p_u   = p_src->U_PIXELS;
  816.     uint8_t  *p_v   = p_src->V_PIXELS;
  817.     bool  b_hscale;                         /* horizontal scaling type */
  818.     unsigned int i_vscale;                          /* vertical scaling type */
  819.     unsigned int i_x, i_y;                /* horizontal and vertical indexes */
  820.     int         i_right_margin;
  821.     int         i_rewind;
  822.     int         i_scale_count;                       /* scale modulo counter */
  823.     int         i_chroma_width = p_filter->fmt_in.video.i_width / 2; /* chroma width */
  824.     uint32_t *  p_pic_start;       /* beginning of the current line for copy */
  825.     /* Conversion buffer pointer */
  826.     uint32_t *  p_buffer_start = (uint32_t*)p_filter->p_sys->p_buffer;
  827.     uint32_t *  p_buffer;
  828.     /* Offset array pointer */
  829.     int *       p_offset_start = p_filter->p_sys->p_offset;
  830.     int *       p_offset;
  831.     const int i_source_margin = p_src->p[0].i_pitch
  832.                                  - p_src->p[0].i_visible_pitch;
  833.     const int i_source_margin_c = p_src->p[1].i_pitch
  834.                                  - p_src->p[1].i_visible_pitch;
  835.     i_right_margin = p_dest->p->i_pitch - p_dest->p->i_visible_pitch;
  836.     /* Rule: when a picture of size (x1,y1) with aspect ratio r1 is rendered
  837.      * on a picture of size (x2,y2) with aspect ratio r2, if x1 grows to x1'
  838.      * then y1 grows to y1' = x1' * y2/x2 * r2/r1 */
  839.     SetOffset( p_filter->fmt_in.video.i_width,
  840.                p_filter->fmt_in.video.i_height,
  841.                p_filter->fmt_out.video.i_width,
  842.                p_filter->fmt_out.video.i_height,
  843.                &b_hscale, &i_vscale, p_offset_start );
  844.     /*
  845.      * Perform conversion
  846.      */
  847.     i_scale_count = ( i_vscale == 1 ) ?
  848.                     p_filter->fmt_out.video.i_height :
  849.                     p_filter->fmt_in.video.i_height;
  850. #if defined (MODULE_NAME_IS_i420_rgb_sse2)
  851.     if( p_filter->fmt_in.video.i_width & 15 )
  852.     {
  853.         i_rewind = 16 - ( p_filter->fmt_in.video.i_width & 15 );
  854.     }
  855.     else
  856.     {
  857.         i_rewind = 0;
  858.     }
  859.     /*
  860.     ** SSE2 128 bits fetch/store instructions are faster
  861.     ** if memory access is 16 bytes aligned
  862.     */
  863.     p_buffer = b_hscale ? p_buffer_start : p_pic;
  864.     if( 0 == (15 & (p_src->p[Y_PLANE].i_pitch|
  865.                     p_dest->p->i_pitch|
  866.                     ((intptr_t)p_y)|
  867.                     ((intptr_t)p_buffer))) )
  868.     {
  869.         /* use faster SSE2 aligned fetch and store */
  870.         for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
  871.         {
  872.             p_pic_start = p_pic;
  873.             for ( i_x = p_filter->fmt_in.video.i_width / 16; i_x--; )
  874.             {
  875.                 SSE2_CALL (
  876.                     SSE2_INIT_32_ALIGNED
  877.                     SSE2_YUV_MUL
  878.                     SSE2_YUV_ADD
  879.                     SSE2_UNPACK_32_ARGB_ALIGNED
  880.                 );
  881.                 p_y += 16;
  882.                 p_u += 8;
  883.                 p_v += 8;
  884.                 p_buffer += 16;
  885.             }
  886.             /* Here we do some unaligned reads and duplicate conversions, but
  887.              * at least we have all the pixels */
  888.             if( i_rewind )
  889.             {
  890.                 p_y -= i_rewind;
  891.                 p_u -= i_rewind >> 1;
  892.                 p_v -= i_rewind >> 1;
  893.                 p_buffer -= i_rewind;
  894.                 SSE2_CALL (
  895.                     SSE2_INIT_32_UNALIGNED
  896.                     SSE2_YUV_MUL
  897.                     SSE2_YUV_ADD
  898.                     SSE2_UNPACK_32_ARGB_UNALIGNED
  899.                 );
  900.                 p_y += 16;
  901.                 p_u += 4;
  902.                 p_v += 4;
  903.             }
  904.             SCALE_WIDTH;
  905.             SCALE_HEIGHT( 420, 4 );
  906.             p_y += i_source_margin;
  907.             if( i_y % 2 )
  908.             {
  909.                 p_u += i_source_margin_c;
  910.                 p_v += i_source_margin_c;
  911.             }
  912.             p_buffer = b_hscale ? p_buffer_start : p_pic;
  913.         }
  914.     }
  915.     else
  916.     {
  917.         /* use slower SSE2 unaligned fetch and store */
  918.         for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
  919.         {
  920.             p_pic_start = p_pic;
  921.             p_buffer = b_hscale ? p_buffer_start : p_pic;
  922.             for ( i_x = p_filter->fmt_in.video.i_width / 16; i_x--; )
  923.             {
  924.                 SSE2_CALL (
  925.                     SSE2_INIT_32_UNALIGNED
  926.                     SSE2_YUV_MUL
  927.                     SSE2_YUV_ADD
  928.                     SSE2_UNPACK_32_ARGB_UNALIGNED
  929.                 );
  930.                 p_y += 16;
  931.                 p_u += 8;
  932.                 p_v += 8;
  933.                 p_buffer += 16;
  934.             }
  935.             /* Here we do some unaligned reads and duplicate conversions, but
  936.              * at least we have all the pixels */
  937.             if( i_rewind )
  938.             {
  939.                 p_y -= i_rewind;
  940.                 p_u -= i_rewind >> 1;
  941.                 p_v -= i_rewind >> 1;
  942.                 p_buffer -= i_rewind;
  943.                 SSE2_CALL (
  944.                     SSE2_INIT_32_UNALIGNED
  945.                     SSE2_YUV_MUL
  946.                     SSE2_YUV_ADD
  947.                     SSE2_UNPACK_32_ARGB_UNALIGNED
  948.                 );
  949.                 p_y += 16;
  950.                 p_u += 8;
  951.                 p_v += 8;
  952.             }
  953.             SCALE_WIDTH;
  954.             SCALE_HEIGHT( 420, 4 );
  955.             p_y += i_source_margin;
  956.             if( i_y % 2 )
  957.             {
  958.                 p_u += i_source_margin_c;
  959.                 p_v += i_source_margin_c;
  960.             }
  961.             p_buffer = b_hscale ? p_buffer_start : p_pic;
  962.         }
  963.     }
  964.     /* make sure all SSE2 stores are visible thereafter */
  965.     SSE2_END;
  966. #else // defined (MODULE_NAME_IS_i420_rgb_mmx)
  967.     if( p_filter->fmt_in.video.i_width & 7 )
  968.     {
  969.         i_rewind = 8 - ( p_filter->fmt_in.video.i_width & 7 );
  970.     }
  971.     else
  972.     {
  973.         i_rewind = 0;
  974.     }
  975.     for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
  976.     {
  977.         p_pic_start = p_pic;
  978.         p_buffer = b_hscale ? p_buffer_start : p_pic;
  979.         for ( i_x = p_filter->fmt_in.video.i_width / 8; i_x--; )
  980.         {
  981.             MMX_CALL (
  982.                 MMX_INIT_32
  983.                 MMX_YUV_MUL
  984.                 MMX_YUV_ADD
  985.                 MMX_UNPACK_32_ARGB
  986.             );
  987.             p_y += 8;
  988.             p_u += 4;
  989.             p_v += 4;
  990.             p_buffer += 8;
  991.         }
  992.         /* Here we do some unaligned reads and duplicate conversions, but
  993.          * at least we have all the pixels */
  994.         if( i_rewind )
  995.         {
  996.             p_y -= i_rewind;
  997.             p_u -= i_rewind >> 1;
  998.             p_v -= i_rewind >> 1;
  999.             p_buffer -= i_rewind;
  1000.             MMX_CALL (
  1001.                 MMX_INIT_32
  1002.                 MMX_YUV_MUL
  1003.                 MMX_YUV_ADD
  1004.                 MMX_UNPACK_32_ARGB
  1005.             );
  1006.             p_y += 8;
  1007.             p_u += 4;
  1008.             p_v += 4;
  1009.             p_buffer += 8;
  1010.         }
  1011.         SCALE_WIDTH;
  1012.         SCALE_HEIGHT( 420, 4 );
  1013.         p_y += i_source_margin;
  1014.         if( i_y % 2 )
  1015.         {
  1016.             p_u += i_source_margin_c;
  1017.             p_v += i_source_margin_c;
  1018.         }
  1019.     }
  1020.     /* re-enable FPU registers */
  1021.     MMX_END;
  1022. #endif
  1023. }
  1024. void I420_R8G8B8A8( filter_t *p_filter, picture_t *p_src,
  1025.                                             picture_t *p_dest )
  1026. {
  1027.     /* We got this one from the old arguments */
  1028.     uint32_t *p_pic = (uint32_t*)p_dest->p->p_pixels;
  1029.     uint8_t  *p_y   = p_src->Y_PIXELS;
  1030.     uint8_t  *p_u   = p_src->U_PIXELS;
  1031.     uint8_t  *p_v   = p_src->V_PIXELS;
  1032.     bool  b_hscale;                         /* horizontal scaling type */
  1033.     unsigned int i_vscale;                          /* vertical scaling type */
  1034.     unsigned int i_x, i_y;                /* horizontal and vertical indexes */
  1035.     int         i_right_margin;
  1036.     int         i_rewind;
  1037.     int         i_scale_count;                       /* scale modulo counter */
  1038.     int         i_chroma_width = p_filter->fmt_in.video.i_width / 2; /* chroma width */
  1039.     uint32_t *  p_pic_start;       /* beginning of the current line for copy */
  1040.     /* Conversion buffer pointer */
  1041.     uint32_t *  p_buffer_start = (uint32_t*)p_filter->p_sys->p_buffer;
  1042.     uint32_t *  p_buffer;
  1043.     /* Offset array pointer */
  1044.     int *       p_offset_start = p_filter->p_sys->p_offset;
  1045.     int *       p_offset;
  1046.     const int i_source_margin = p_src->p[0].i_pitch
  1047.                                  - p_src->p[0].i_visible_pitch;
  1048.     const int i_source_margin_c = p_src->p[1].i_pitch
  1049.                                  - p_src->p[1].i_visible_pitch;
  1050.     i_right_margin = p_dest->p->i_pitch - p_dest->p->i_visible_pitch;
  1051.     /* Rule: when a picture of size (x1,y1) with aspect ratio r1 is rendered
  1052.      * on a picture of size (x2,y2) with aspect ratio r2, if x1 grows to x1'
  1053.      * then y1 grows to y1' = x1' * y2/x2 * r2/r1 */
  1054.     SetOffset( p_filter->fmt_in.video.i_width,
  1055.                p_filter->fmt_in.video.i_height,
  1056.                p_filter->fmt_out.video.i_width,
  1057.                p_filter->fmt_out.video.i_height,
  1058.                &b_hscale, &i_vscale, p_offset_start );
  1059.     /*
  1060.      * Perform conversion
  1061.      */
  1062.     i_scale_count = ( i_vscale == 1 ) ?
  1063.                     p_filter->fmt_out.video.i_height :
  1064.                     p_filter->fmt_in.video.i_height;
  1065. #if defined (MODULE_NAME_IS_i420_rgb_sse2)
  1066.     if( p_filter->fmt_in.video.i_width & 15 )
  1067.     {
  1068.         i_rewind = 16 - ( p_filter->fmt_in.video.i_width & 15 );
  1069.     }
  1070.     else
  1071.     {
  1072.         i_rewind = 0;
  1073.     }
  1074.     /*
  1075.     ** SSE2 128 bits fetch/store instructions are faster
  1076.     ** if memory access is 16 bytes aligned
  1077.     */
  1078.     p_buffer = b_hscale ? p_buffer_start : p_pic;
  1079.     if( 0 == (15 & (p_src->p[Y_PLANE].i_pitch|
  1080.                     p_dest->p->i_pitch|
  1081.                     ((intptr_t)p_y)|
  1082.                     ((intptr_t)p_buffer))) )
  1083.     {
  1084.         /* use faster SSE2 aligned fetch and store */
  1085.         for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
  1086.         {
  1087.             p_pic_start = p_pic;
  1088.             for ( i_x = p_filter->fmt_in.video.i_width / 16; i_x--; )
  1089.             {
  1090.                 SSE2_CALL (
  1091.                     SSE2_INIT_32_ALIGNED
  1092.                     SSE2_YUV_MUL
  1093.                     SSE2_YUV_ADD
  1094.                     SSE2_UNPACK_32_RGBA_ALIGNED
  1095.                 );
  1096.                 p_y += 16;
  1097.                 p_u += 8;
  1098.                 p_v += 8;
  1099.                 p_buffer += 16;
  1100.             }
  1101.             /* Here we do some unaligned reads and duplicate conversions, but
  1102.              * at least we have all the pixels */
  1103.             if( i_rewind )
  1104.             {
  1105.                 p_y -= i_rewind;
  1106.                 p_u -= i_rewind >> 1;
  1107.                 p_v -= i_rewind >> 1;
  1108.                 p_buffer -= i_rewind;
  1109.                 SSE2_CALL (
  1110.                     SSE2_INIT_32_UNALIGNED
  1111.                     SSE2_YUV_MUL
  1112.                     SSE2_YUV_ADD
  1113.                     SSE2_UNPACK_32_RGBA_UNALIGNED
  1114.                 );
  1115.                 p_y += 16;
  1116.                 p_u += 4;
  1117.                 p_v += 4;
  1118.             }
  1119.             SCALE_WIDTH;
  1120.             SCALE_HEIGHT( 420, 4 );
  1121.             p_y += i_source_margin;
  1122.             if( i_y % 2 )
  1123.             {
  1124.                 p_u += i_source_margin_c;
  1125.                 p_v += i_source_margin_c;
  1126.             }
  1127.             p_buffer = b_hscale ? p_buffer_start : p_pic;
  1128.         }
  1129.     }
  1130.     else
  1131.     {
  1132.         /* use slower SSE2 unaligned fetch and store */
  1133.         for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
  1134.         {
  1135.             p_pic_start = p_pic;
  1136.             p_buffer = b_hscale ? p_buffer_start : p_pic;
  1137.             for ( i_x = p_filter->fmt_in.video.i_width / 16; i_x--; )
  1138.             {
  1139.                 SSE2_CALL (
  1140.                     SSE2_INIT_32_UNALIGNED
  1141.                     SSE2_YUV_MUL
  1142.                     SSE2_YUV_ADD
  1143.                     SSE2_UNPACK_32_RGBA_UNALIGNED
  1144.                 );
  1145.                 p_y += 16;
  1146.                 p_u += 8;
  1147.                 p_v += 8;
  1148.                 p_buffer += 16;
  1149.             }
  1150.             /* Here we do some unaligned reads and duplicate conversions, but
  1151.              * at least we have all the pixels */
  1152.             if( i_rewind )
  1153.             {
  1154.                 p_y -= i_rewind;
  1155.                 p_u -= i_rewind >> 1;
  1156.                 p_v -= i_rewind >> 1;
  1157.                 p_buffer -= i_rewind;
  1158.                 SSE2_CALL (
  1159.                     SSE2_INIT_32_UNALIGNED
  1160.                     SSE2_YUV_MUL
  1161.                     SSE2_YUV_ADD
  1162.                     SSE2_UNPACK_32_RGBA_UNALIGNED
  1163.                 );
  1164.                 p_y += 16;
  1165.                 p_u += 8;
  1166.                 p_v += 8;
  1167.             }
  1168.             SCALE_WIDTH;
  1169.             SCALE_HEIGHT( 420, 4 );
  1170.             p_y += i_source_margin;
  1171.             if( i_y % 2 )
  1172.             {
  1173.                 p_u += i_source_margin_c;
  1174.                 p_v += i_source_margin_c;
  1175.             }
  1176.             p_buffer = b_hscale ? p_buffer_start : p_pic;
  1177.         }
  1178.     }
  1179.     /* make sure all SSE2 stores are visible thereafter */
  1180.     SSE2_END;
  1181. #else // defined (MODULE_NAME_IS_i420_rgb_mmx)
  1182.     if( p_filter->fmt_in.video.i_width & 7 )
  1183.     {
  1184.         i_rewind = 8 - ( p_filter->fmt_in.video.i_width & 7 );
  1185.     }
  1186.     else
  1187.     {
  1188.         i_rewind = 0;
  1189.     }
  1190.     for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
  1191.     {
  1192.         p_pic_start = p_pic;
  1193.         p_buffer = b_hscale ? p_buffer_start : p_pic;
  1194.         for ( i_x = p_filter->fmt_in.video.i_width / 8; i_x--; )
  1195.         {
  1196.             MMX_CALL (
  1197.                 MMX_INIT_32
  1198.                 MMX_YUV_MUL
  1199.                 MMX_YUV_ADD
  1200.                 MMX_UNPACK_32_RGBA
  1201.             );
  1202.             p_y += 8;
  1203.             p_u += 4;
  1204.             p_v += 4;
  1205.             p_buffer += 8;
  1206.         }
  1207.         /* Here we do some unaligned reads and duplicate conversions, but
  1208.          * at least we have all the pixels */
  1209.         if( i_rewind )
  1210.         {
  1211.             p_y -= i_rewind;
  1212.             p_u -= i_rewind >> 1;
  1213.             p_v -= i_rewind >> 1;
  1214.             p_buffer -= i_rewind;
  1215.             MMX_CALL (
  1216.                 MMX_INIT_32
  1217.                 MMX_YUV_MUL
  1218.                 MMX_YUV_ADD
  1219.                 MMX_UNPACK_32_RGBA
  1220.             );
  1221.             p_y += 8;
  1222.             p_u += 4;
  1223.             p_v += 4;
  1224.             p_buffer += 8;
  1225.         }
  1226.         SCALE_WIDTH;
  1227.         SCALE_HEIGHT( 420, 4 );
  1228.         p_y += i_source_margin;
  1229.         if( i_y % 2 )
  1230.         {
  1231.             p_u += i_source_margin_c;
  1232.             p_v += i_source_margin_c;
  1233.         }
  1234.     }
  1235.     /* re-enable FPU registers */
  1236.     MMX_END;
  1237. #endif
  1238. }
  1239. void I420_B8G8R8A8( filter_t *p_filter, picture_t *p_src,
  1240.                                             picture_t *p_dest )
  1241. {
  1242.     /* We got this one from the old arguments */
  1243.     uint32_t *p_pic = (uint32_t*)p_dest->p->p_pixels;
  1244.     uint8_t  *p_y   = p_src->Y_PIXELS;
  1245.     uint8_t  *p_u   = p_src->U_PIXELS;
  1246.     uint8_t  *p_v   = p_src->V_PIXELS;
  1247.     bool  b_hscale;                         /* horizontal scaling type */
  1248.     unsigned int i_vscale;                          /* vertical scaling type */
  1249.     unsigned int i_x, i_y;                /* horizontal and vertical indexes */
  1250.     int         i_right_margin;
  1251.     int         i_rewind;
  1252.     int         i_scale_count;                       /* scale modulo counter */
  1253.     int         i_chroma_width = p_filter->fmt_in.video.i_width / 2; /* chroma width */
  1254.     uint32_t *  p_pic_start;       /* beginning of the current line for copy */
  1255.     /* Conversion buffer pointer */
  1256.     uint32_t *  p_buffer_start = (uint32_t*)p_filter->p_sys->p_buffer;
  1257.     uint32_t *  p_buffer;
  1258.     /* Offset array pointer */
  1259.     int *       p_offset_start = p_filter->p_sys->p_offset;
  1260.     int *       p_offset;
  1261.     const int i_source_margin = p_src->p[0].i_pitch
  1262.                                  - p_src->p[0].i_visible_pitch;
  1263.     const int i_source_margin_c = p_src->p[1].i_pitch
  1264.                                  - p_src->p[1].i_visible_pitch;
  1265.     i_right_margin = p_dest->p->i_pitch - p_dest->p->i_visible_pitch;
  1266.     /* Rule: when a picture of size (x1,y1) with aspect ratio r1 is rendered
  1267.      * on a picture of size (x2,y2) with aspect ratio r2, if x1 grows to x1'
  1268.      * then y1 grows to y1' = x1' * y2/x2 * r2/r1 */
  1269.     SetOffset( p_filter->fmt_in.video.i_width,
  1270.                p_filter->fmt_in.video.i_height,
  1271.                p_filter->fmt_out.video.i_width,
  1272.                p_filter->fmt_out.video.i_height,
  1273.                &b_hscale, &i_vscale, p_offset_start );
  1274.     /*
  1275.      * Perform conversion
  1276.      */
  1277.     i_scale_count = ( i_vscale == 1 ) ?
  1278.                     p_filter->fmt_out.video.i_height :
  1279.                     p_filter->fmt_in.video.i_height;
  1280. #if defined (MODULE_NAME_IS_i420_rgb_sse2)
  1281.     if( p_filter->fmt_in.video.i_width & 15 )
  1282.     {
  1283.         i_rewind = 16 - ( p_filter->fmt_in.video.i_width & 15 );
  1284.     }
  1285.     else
  1286.     {
  1287.         i_rewind = 0;
  1288.     }
  1289.     /*
  1290.     ** SSE2 128 bits fetch/store instructions are faster
  1291.     ** if memory access is 16 bytes aligned
  1292.     */
  1293.     p_buffer = b_hscale ? p_buffer_start : p_pic;
  1294.     if( 0 == (15 & (p_src->p[Y_PLANE].i_pitch|
  1295.                     p_dest->p->i_pitch|
  1296.                     ((intptr_t)p_y)|
  1297.                     ((intptr_t)p_buffer))) )
  1298.     {
  1299.         /* use faster SSE2 aligned fetch and store */
  1300.         for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
  1301.         {
  1302.             p_pic_start = p_pic;
  1303.             for ( i_x = p_filter->fmt_in.video.i_width / 16; i_x--; )
  1304.             {
  1305.                 SSE2_CALL (
  1306.                     SSE2_INIT_32_ALIGNED
  1307.                     SSE2_YUV_MUL
  1308.                     SSE2_YUV_ADD
  1309.                     SSE2_UNPACK_32_BGRA_ALIGNED
  1310.                 );
  1311.                 p_y += 16;
  1312.                 p_u += 8;
  1313.                 p_v += 8;
  1314.                 p_buffer += 16;
  1315.             }
  1316.             /* Here we do some unaligned reads and duplicate conversions, but
  1317.              * at least we have all the pixels */
  1318.             if( i_rewind )
  1319.             {
  1320.                 p_y -= i_rewind;
  1321.                 p_u -= i_rewind >> 1;
  1322.                 p_v -= i_rewind >> 1;
  1323.                 p_buffer -= i_rewind;
  1324.                 SSE2_CALL (
  1325.                     SSE2_INIT_32_UNALIGNED
  1326.                     SSE2_YUV_MUL
  1327.                     SSE2_YUV_ADD
  1328.                     SSE2_UNPACK_32_BGRA_UNALIGNED
  1329.                 );
  1330.                 p_y += 16;
  1331.                 p_u += 4;
  1332.                 p_v += 4;
  1333.             }
  1334.             SCALE_WIDTH;
  1335.             SCALE_HEIGHT( 420, 4 );
  1336.             p_y += i_source_margin;
  1337.             if( i_y % 2 )
  1338.             {
  1339.                 p_u += i_source_margin_c;
  1340.                 p_v += i_source_margin_c;
  1341.             }
  1342.             p_buffer = b_hscale ? p_buffer_start : p_pic;
  1343.         }
  1344.     }
  1345.     else
  1346.     {
  1347.         /* use slower SSE2 unaligned fetch and store */
  1348.         for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
  1349.         {
  1350.             p_pic_start = p_pic;
  1351.             p_buffer = b_hscale ? p_buffer_start : p_pic;
  1352.             for ( i_x = p_filter->fmt_in.video.i_width / 16; i_x--; )
  1353.             {
  1354.                 SSE2_CALL (
  1355.                     SSE2_INIT_32_UNALIGNED
  1356.                     SSE2_YUV_MUL
  1357.                     SSE2_YUV_ADD
  1358.                     SSE2_UNPACK_32_BGRA_UNALIGNED
  1359.                 );
  1360.                 p_y += 16;
  1361.                 p_u += 8;
  1362.                 p_v += 8;
  1363.                 p_buffer += 16;
  1364.             }
  1365.             /* Here we do some unaligned reads and duplicate conversions, but
  1366.              * at least we have all the pixels */
  1367.             if( i_rewind )
  1368.             {
  1369.                 p_y -= i_rewind;
  1370.                 p_u -= i_rewind >> 1;
  1371.                 p_v -= i_rewind >> 1;
  1372.                 p_buffer -= i_rewind;
  1373.                 SSE2_CALL (
  1374.                     SSE2_INIT_32_UNALIGNED
  1375.                     SSE2_YUV_MUL
  1376.                     SSE2_YUV_ADD
  1377.                     SSE2_UNPACK_32_BGRA_UNALIGNED
  1378.                 );
  1379.                 p_y += 16;
  1380.                 p_u += 8;
  1381.                 p_v += 8;
  1382.             }
  1383.             SCALE_WIDTH;
  1384.             SCALE_HEIGHT( 420, 4 );
  1385.             p_y += i_source_margin;
  1386.             if( i_y % 2 )
  1387.             {
  1388.                 p_u += i_source_margin_c;
  1389.                 p_v += i_source_margin_c;
  1390.             }
  1391.             p_buffer = b_hscale ? p_buffer_start : p_pic;
  1392.         }
  1393.     }
  1394. #else
  1395.     if( p_filter->fmt_in.video.i_width & 7 )
  1396.     {
  1397.         i_rewind = 8 - ( p_filter->fmt_in.video.i_width & 7 );
  1398.     }
  1399.     else
  1400.     {
  1401.         i_rewind = 0;
  1402.     }
  1403.     for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
  1404.     {
  1405.         p_pic_start = p_pic;
  1406.         p_buffer = b_hscale ? p_buffer_start : p_pic;
  1407.         for ( i_x = p_filter->fmt_in.video.i_width / 8; i_x--; )
  1408.         {
  1409.             MMX_CALL (
  1410.                 MMX_INIT_32
  1411.                 MMX_YUV_MUL
  1412.                 MMX_YUV_ADD
  1413.                 MMX_UNPACK_32_BGRA
  1414.             );
  1415.             p_y += 8;
  1416.             p_u += 4;
  1417.             p_v += 4;
  1418.             p_buffer += 8;
  1419.         }
  1420.         /* Here we do some unaligned reads and duplicate conversions, but
  1421.          * at least we have all the pixels */
  1422.         if( i_rewind )
  1423.         {
  1424.             p_y -= i_rewind;
  1425.             p_u -= i_rewind >> 1;
  1426.             p_v -= i_rewind >> 1;
  1427.             p_buffer -= i_rewind;
  1428.             MMX_CALL (
  1429.                 MMX_INIT_32
  1430.                 MMX_YUV_MUL
  1431.                 MMX_YUV_ADD
  1432.                 MMX_UNPACK_32_BGRA
  1433.             );
  1434.             p_y += 8;
  1435.             p_u += 4;
  1436.             p_v += 4;
  1437.             p_buffer += 8;
  1438.         }
  1439.         SCALE_WIDTH;
  1440.         SCALE_HEIGHT( 420, 4 );
  1441.         p_y += i_source_margin;
  1442.         if( i_y % 2 )
  1443.         {
  1444.             p_u += i_source_margin_c;
  1445.             p_v += i_source_margin_c;
  1446.         }
  1447.     }
  1448.     /* re-enable FPU registers */
  1449.     MMX_END;
  1450. #endif
  1451. }
  1452. void I420_A8B8G8R8( filter_t *p_filter, picture_t *p_src,
  1453.                                             picture_t *p_dest )
  1454. {
  1455.     /* We got this one from the old arguments */
  1456.     uint32_t *p_pic = (uint32_t*)p_dest->p->p_pixels;
  1457.     uint8_t  *p_y   = p_src->Y_PIXELS;
  1458.     uint8_t  *p_u   = p_src->U_PIXELS;
  1459.     uint8_t  *p_v   = p_src->V_PIXELS;
  1460.     bool  b_hscale;                         /* horizontal scaling type */
  1461.     unsigned int i_vscale;                          /* vertical scaling type */
  1462.     unsigned int i_x, i_y;                /* horizontal and vertical indexes */
  1463.     int         i_right_margin;
  1464.     int         i_rewind;
  1465.     int         i_scale_count;                       /* scale modulo counter */
  1466.     int         i_chroma_width = p_filter->fmt_in.video.i_width / 2; /* chroma width */
  1467.     uint32_t *  p_pic_start;       /* beginning of the current line for copy */
  1468.     /* Conversion buffer pointer */
  1469.     uint32_t *  p_buffer_start = (uint32_t*)p_filter->p_sys->p_buffer;
  1470.     uint32_t *  p_buffer;
  1471.     /* Offset array pointer */
  1472.     int *       p_offset_start = p_filter->p_sys->p_offset;
  1473.     int *       p_offset;
  1474.     const int i_source_margin = p_src->p[0].i_pitch
  1475.                                  - p_src->p[0].i_visible_pitch;
  1476.     const int i_source_margin_c = p_src->p[1].i_pitch
  1477.                                  - p_src->p[1].i_visible_pitch;
  1478.     i_right_margin = p_dest->p->i_pitch - p_dest->p->i_visible_pitch;
  1479.     /* Rule: when a picture of size (x1,y1) with aspect ratio r1 is rendered
  1480.      * on a picture of size (x2,y2) with aspect ratio r2, if x1 grows to x1'
  1481.      * then y1 grows to y1' = x1' * y2/x2 * r2/r1 */
  1482.     SetOffset( p_filter->fmt_in.video.i_width,
  1483.                p_filter->fmt_in.video.i_height,
  1484.                p_filter->fmt_out.video.i_width,
  1485.                p_filter->fmt_out.video.i_height,
  1486.                &b_hscale, &i_vscale, p_offset_start );
  1487.     /*
  1488.      * Perform conversion
  1489.      */
  1490.     i_scale_count = ( i_vscale == 1 ) ?
  1491.                     p_filter->fmt_out.video.i_height :
  1492.                     p_filter->fmt_in.video.i_height;
  1493. #if defined (MODULE_NAME_IS_i420_rgb_sse2)
  1494.     if( p_filter->fmt_in.video.i_width & 15 )
  1495.     {
  1496.         i_rewind = 16 - ( p_filter->fmt_in.video.i_width & 15 );
  1497.     }
  1498.     else
  1499.     {
  1500.         i_rewind = 0;
  1501.     }
  1502.     /*
  1503.     ** SSE2 128 bits fetch/store instructions are faster
  1504.     ** if memory access is 16 bytes aligned
  1505.     */
  1506.     p_buffer = b_hscale ? p_buffer_start : p_pic;
  1507.     if( 0 == (15 & (p_src->p[Y_PLANE].i_pitch|
  1508.                     p_dest->p->i_pitch|
  1509.                     ((intptr_t)p_y)|
  1510.                     ((intptr_t)p_buffer))) )
  1511.     {
  1512.         /* use faster SSE2 aligned fetch and store */
  1513.         for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
  1514.         {
  1515.             p_pic_start = p_pic;
  1516.             for ( i_x = p_filter->fmt_in.video.i_width / 16; i_x--; )
  1517.             {
  1518.                 SSE2_CALL (
  1519.                     SSE2_INIT_32_ALIGNED
  1520.                     SSE2_YUV_MUL
  1521.                     SSE2_YUV_ADD
  1522.                     SSE2_UNPACK_32_ABGR_ALIGNED
  1523.                 );
  1524.                 p_y += 16;
  1525.                 p_u += 8;
  1526.                 p_v += 8;
  1527.                 p_buffer += 16;
  1528.             }
  1529.             /* Here we do some unaligned reads and duplicate conversions, but
  1530.              * at least we have all the pixels */
  1531.             if( i_rewind )
  1532.             {
  1533.                 p_y -= i_rewind;
  1534.                 p_u -= i_rewind >> 1;
  1535.                 p_v -= i_rewind >> 1;
  1536.                 p_buffer -= i_rewind;
  1537.                 SSE2_CALL (
  1538.                     SSE2_INIT_32_UNALIGNED
  1539.                     SSE2_YUV_MUL
  1540.                     SSE2_YUV_ADD
  1541.                     SSE2_UNPACK_32_ABGR_UNALIGNED
  1542.                 );
  1543.                 p_y += 16;
  1544.                 p_u += 4;
  1545.                 p_v += 4;
  1546.             }
  1547.             SCALE_WIDTH;
  1548.             SCALE_HEIGHT( 420, 4 );
  1549.             p_y += i_source_margin;
  1550.             if( i_y % 2 )
  1551.             {
  1552.                 p_u += i_source_margin_c;
  1553.                 p_v += i_source_margin_c;
  1554.             }
  1555.             p_buffer = b_hscale ? p_buffer_start : p_pic;
  1556.         }
  1557.     }
  1558.     else
  1559.     {
  1560.         /* use slower SSE2 unaligned fetch and store */
  1561.         for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
  1562.         {
  1563.             p_pic_start = p_pic;
  1564.             p_buffer = b_hscale ? p_buffer_start : p_pic;
  1565.             for ( i_x = p_filter->fmt_in.video.i_width / 16; i_x--; )
  1566.             {
  1567.                 SSE2_CALL (
  1568.                     SSE2_INIT_32_UNALIGNED
  1569.                     SSE2_YUV_MUL
  1570.                     SSE2_YUV_ADD
  1571.                     SSE2_UNPACK_32_ABGR_UNALIGNED
  1572.                 );
  1573.                 p_y += 16;
  1574.                 p_u += 8;
  1575.                 p_v += 8;
  1576.                 p_buffer += 16;
  1577.             }
  1578.             /* Here we do some unaligned reads and duplicate conversions, but
  1579.              * at least we have all the pixels */
  1580.             if( i_rewind )
  1581.             {
  1582.                 p_y -= i_rewind;
  1583.                 p_u -= i_rewind >> 1;
  1584.                 p_v -= i_rewind >> 1;
  1585.                 p_buffer -= i_rewind;
  1586.                 SSE2_CALL (
  1587.                     SSE2_INIT_32_UNALIGNED
  1588.                     SSE2_YUV_MUL
  1589.                     SSE2_YUV_ADD
  1590.                     SSE2_UNPACK_32_ABGR_UNALIGNED
  1591.                 );
  1592.                 p_y += 16;
  1593.                 p_u += 8;
  1594.                 p_v += 8;
  1595.             }
  1596.             SCALE_WIDTH;
  1597.             SCALE_HEIGHT( 420, 4 );
  1598.             p_y += i_source_margin;
  1599.             if( i_y % 2 )
  1600.             {
  1601.                 p_u += i_source_margin_c;
  1602.                 p_v += i_source_margin_c;
  1603.             }
  1604.             p_buffer = b_hscale ? p_buffer_start : p_pic;
  1605.         }
  1606.     }
  1607. #else
  1608.     if( p_filter->fmt_in.video.i_width & 7 )
  1609.     {
  1610.         i_rewind = 8 - ( p_filter->fmt_in.video.i_width & 7 );
  1611.     }
  1612.     else
  1613.     {
  1614.         i_rewind = 0;
  1615.     }
  1616.     for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
  1617.     {
  1618.         p_pic_start = p_pic;
  1619.         p_buffer = b_hscale ? p_buffer_start : p_pic;
  1620.         for ( i_x = p_filter->fmt_in.video.i_width / 8; i_x--; )
  1621.         {
  1622.             MMX_CALL (
  1623.                 MMX_INIT_32
  1624.                 MMX_YUV_MUL
  1625.                 MMX_YUV_ADD
  1626.                 MMX_UNPACK_32_ABGR
  1627.             );
  1628.             p_y += 8;
  1629.             p_u += 4;
  1630.             p_v += 4;
  1631.             p_buffer += 8;
  1632.         }
  1633.         /* Here we do some unaligned reads and duplicate conversions, but
  1634.          * at least we have all the pixels */
  1635.         if( i_rewind )
  1636.         {
  1637.             p_y -= i_rewind;
  1638.             p_u -= i_rewind >> 1;
  1639.             p_v -= i_rewind >> 1;
  1640.             p_buffer -= i_rewind;
  1641.             MMX_CALL (
  1642.                 MMX_INIT_32
  1643.                 MMX_YUV_MUL
  1644.                 MMX_YUV_ADD
  1645.                 MMX_UNPACK_32_ABGR
  1646.             );
  1647.             p_y += 8;
  1648.             p_u += 4;
  1649.             p_v += 4;
  1650.             p_buffer += 8;
  1651.         }
  1652.         SCALE_WIDTH;
  1653.         SCALE_HEIGHT( 420, 4 );
  1654.         p_y += i_source_margin;
  1655.         if( i_y % 2 )
  1656.         {
  1657.             p_u += i_source_margin_c;
  1658.             p_v += i_source_margin_c;
  1659.         }
  1660.     }
  1661.     /* re-enable FPU registers */
  1662.     MMX_END;
  1663. #endif
  1664. }
  1665. #endif
  1666. /* Following functions are local */
  1667. /*****************************************************************************
  1668.  * SetOffset: build offset array for conversion functions
  1669.  *****************************************************************************
  1670.  * This function will build an offset array used in later conversion functions.
  1671.  * It will also set horizontal and vertical scaling indicators.
  1672.  *****************************************************************************/
  1673. static void SetOffset( int i_width, int i_height, int i_pic_width,
  1674.                        int i_pic_height, bool *pb_hscale,
  1675.                        unsigned int *pi_vscale, int *p_offset )
  1676. {
  1677.     int i_x;                                    /* x position in destination */
  1678.     int i_scale_count;                                     /* modulo counter */
  1679.     /*
  1680.      * Prepare horizontal offset array
  1681.      */
  1682.     if( i_pic_width - i_width == 0 )
  1683.     {
  1684.         /* No horizontal scaling: YUV conversion is done directly to picture */
  1685.         *pb_hscale = 0;
  1686.     }
  1687.     else if( i_pic_width - i_width > 0 )
  1688.     {
  1689.         /* Prepare scaling array for horizontal extension */
  1690.         *pb_hscale = 1;
  1691.         i_scale_count = i_pic_width;
  1692.         for( i_x = i_width; i_x--; )
  1693.         {
  1694.             while( (i_scale_count -= i_width) > 0 )
  1695.             {
  1696.                 *p_offset++ = 0;
  1697.             }
  1698.             *p_offset++ = 1;
  1699.             i_scale_count += i_pic_width;
  1700.         }
  1701.     }
  1702.     else /* if( i_pic_width - i_width < 0 ) */
  1703.     {
  1704.         /* Prepare scaling array for horizontal reduction */
  1705.         *pb_hscale = 1;
  1706.         i_scale_count = i_width;
  1707.         for( i_x = i_pic_width; i_x--; )
  1708.         {
  1709.             *p_offset = 1;
  1710.             while( (i_scale_count -= i_pic_width) > 0 )
  1711.             {
  1712.                 *p_offset += 1;
  1713.             }
  1714.             p_offset++;
  1715.             i_scale_count += i_width;
  1716.         }
  1717.     }
  1718.     /*
  1719.      * Set vertical scaling indicator
  1720.      */
  1721.     if( i_pic_height - i_height == 0 )
  1722.     {
  1723.         *pi_vscale = 0;
  1724.     }
  1725.     else if( i_pic_height - i_height > 0 )
  1726.     {
  1727.         *pi_vscale = 1;
  1728.     }
  1729.     else /* if( i_pic_height - i_height < 0 ) */
  1730.     {
  1731.         *pi_vscale = -1;
  1732.     }
  1733. }