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

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * i420_yuy2.c : YUV to YUV conversion module for vlc
  3.  *****************************************************************************
  4.  * Copyright (C) 2000, 2001 VideoLAN
  5.  * $Id: i420_yuy2.c 8582 2004-08-30 01:03:12Z 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. #ifdef HAVE_ALTIVEC_H
  31. #   include <altivec.h>
  32. #endif
  33. #include "i420_yuy2.h"
  34. #define SRC_FOURCC  "I420,IYUV,YV12"
  35. #if defined (MODULE_NAME_IS_i420_yuy2)
  36. #    define DEST_FOURCC "YUY2,YUNV,YVYU,UYVY,UYNV,Y422,IUYV,cyuv,Y211"
  37. #elif defined (MODULE_NAME_IS_i420_yuy2_mmx)
  38. #    define DEST_FOURCC "YUY2,YUNV,YVYU,UYVY,UYNV,Y422,IUYV,cyuv"
  39. #elif defined (MODULE_NAME_IS_i420_yuy2_altivec)
  40. #    define DEST_FOURCC "YUY2,YUNV"
  41. #endif
  42. /*****************************************************************************
  43.  * Local and extern prototypes.
  44.  *****************************************************************************/
  45. static int  Activate ( vlc_object_t * );
  46. static void I420_YUY2           ( vout_thread_t *, picture_t *, picture_t * );
  47. #if !defined (MODULE_NAME_IS_i420_yuy2_altivec)
  48. static void I420_YVYU           ( vout_thread_t *, picture_t *, picture_t * );
  49. static void I420_UYVY           ( vout_thread_t *, picture_t *, picture_t * );
  50. static void I420_IUYV           ( vout_thread_t *, picture_t *, picture_t * );
  51. static void I420_cyuv           ( vout_thread_t *, picture_t *, picture_t * );
  52. #endif
  53. #if defined (MODULE_NAME_IS_i420_yuy2)
  54. static void I420_Y211           ( vout_thread_t *, picture_t *, picture_t * );
  55. #endif
  56. #ifdef MODULE_NAME_IS_i420_yuy2_mmx
  57. static uint64_t i_00ffw;
  58. static uint64_t i_80w;
  59. #endif
  60. /*****************************************************************************
  61.  * Module descriptor.
  62.  *****************************************************************************/
  63. vlc_module_begin();
  64. #if defined (MODULE_NAME_IS_i420_yuy2)
  65.     set_description( _("Conversions from " SRC_FOURCC " to " DEST_FOURCC) );
  66.     set_capability( "chroma", 80 );
  67. #elif defined (MODULE_NAME_IS_i420_yuy2_mmx)
  68.     set_description( _("MMX conversions from " SRC_FOURCC " to " DEST_FOURCC) );
  69.     set_capability( "chroma", 100 );
  70.     add_requirement( MMX );
  71.     /* Initialize MMX-specific constants */
  72.     i_00ffw = 0x00ff00ff00ff00ffULL;
  73.     i_80w   = 0x0000000080808080ULL;
  74. #elif defined (MODULE_NAME_IS_i420_yuy2_altivec)
  75.     set_description(
  76.             _("AltiVec conversions from " SRC_FOURCC " to " DEST_FOURCC) );
  77.     set_capability( "chroma", 100 );
  78.     add_requirement( ALTIVEC );
  79. #endif
  80.     set_callbacks( Activate, NULL );
  81. vlc_module_end();
  82. /*****************************************************************************
  83.  * Activate: allocate a chroma function
  84.  *****************************************************************************
  85.  * This function allocates and initializes a chroma function
  86.  *****************************************************************************/
  87. static int Activate( vlc_object_t *p_this )
  88. {
  89.     vout_thread_t *p_vout = (vout_thread_t *)p_this;
  90.     if( p_vout->render.i_width & 1 || p_vout->render.i_height & 1 )
  91.     {
  92.         return -1;
  93.     }
  94.     switch( p_vout->render.i_chroma )
  95.     {
  96.         case VLC_FOURCC('Y','V','1','2'):
  97.         case VLC_FOURCC('I','4','2','0'):
  98.         case VLC_FOURCC('I','Y','U','V'):
  99.             switch( p_vout->output.i_chroma )
  100.             {
  101.                 case VLC_FOURCC('Y','U','Y','2'):
  102.                 case VLC_FOURCC('Y','U','N','V'):
  103.                     p_vout->chroma.pf_convert = I420_YUY2;
  104.                     break;
  105. #if !defined (MODULE_NAME_IS_i420_yuy2_altivec)
  106.                 case VLC_FOURCC('Y','V','Y','U'):
  107.                     p_vout->chroma.pf_convert = I420_YVYU;
  108.                     break;
  109.                 case VLC_FOURCC('U','Y','V','Y'):
  110.                 case VLC_FOURCC('U','Y','N','V'):
  111.                 case VLC_FOURCC('Y','4','2','2'):
  112.                     p_vout->chroma.pf_convert = I420_UYVY;
  113.                     break;
  114.                 case VLC_FOURCC('I','U','Y','V'):
  115.                     p_vout->chroma.pf_convert = I420_IUYV;
  116.                     break;
  117.                 case VLC_FOURCC('c','y','u','v'):
  118.                     p_vout->chroma.pf_convert = I420_cyuv;
  119.                     break;
  120. #endif
  121. #if defined (MODULE_NAME_IS_i420_yuy2)
  122.                 case VLC_FOURCC('Y','2','1','1'):
  123.                     p_vout->chroma.pf_convert = I420_Y211;
  124.                     break;
  125. #endif
  126.                 default:
  127.                     return -1;
  128.             }
  129.             break;
  130.         default:
  131.             return -1;
  132.     }
  133.     return 0;
  134. }
  135. /* Following functions are local */
  136. /*****************************************************************************
  137.  * I420_YUY2: planar YUV 4:2:0 to packed YUYV 4:2:2
  138.  *****************************************************************************/
  139. static void I420_YUY2( vout_thread_t *p_vout, picture_t *p_source,
  140.                                               picture_t *p_dest )
  141. {
  142.     uint8_t *p_line1, *p_line2 = p_dest->p->p_pixels;
  143.     uint8_t *p_y1, *p_y2 = p_source->Y_PIXELS;
  144.     uint8_t *p_u = p_source->U_PIXELS;
  145.     uint8_t *p_v = p_source->V_PIXELS;
  146.     int i_x, i_y;
  147. #if defined (MODULE_NAME_IS_i420_yuy2_altivec)
  148. #define VEC_NEXT_LINES( ) 
  149.     p_line1  = p_line2; 
  150.     p_line2 += p_dest->p->i_pitch; 
  151.     p_y1     = p_y2; 
  152.     p_y2    += p_source->p[Y_PLANE].i_pitch;
  153. #define VEC_LOAD_UV( ) 
  154.     u_vec = vec_ld( 0, p_u ); p_u += 16; 
  155.     v_vec = vec_ld( 0, p_v ); p_v += 16;
  156. #define VEC_MERGE( a ) 
  157.     uv_vec = a( u_vec, v_vec ); 
  158.     y_vec = vec_ld( 0, p_y1 ); p_y1 += 16; 
  159.     vec_st( vec_mergeh( y_vec, uv_vec ), 0, p_line1 ); p_line1 += 16; 
  160.     vec_st( vec_mergel( y_vec, uv_vec ), 0, p_line1 ); p_line1 += 16; 
  161.     y_vec = vec_ld( 0, p_y2 ); p_y2 += 16; 
  162.     vec_st( vec_mergeh( y_vec, uv_vec ), 0, p_line2 ); p_line2 += 16; 
  163.     vec_st( vec_mergel( y_vec, uv_vec ), 0, p_line2 ); p_line2 += 16;
  164.     vector unsigned char u_vec;
  165.     vector unsigned char v_vec;
  166.     vector unsigned char uv_vec;
  167.     vector unsigned char y_vec;
  168.     if( !( ( p_vout->render.i_width % 32 ) |
  169.            ( p_vout->render.i_height % 2 ) ) )
  170.     {
  171.         /* Width is a multiple of 32, we take 2 lines at a time */
  172.         for( i_y = p_vout->render.i_height / 2 ; i_y-- ; )
  173.         {
  174.             VEC_NEXT_LINES( );
  175.             for( i_x = p_vout->render.i_width / 32 ; i_x-- ; )
  176.             {
  177.                 VEC_LOAD_UV( );
  178.                 VEC_MERGE( vec_mergeh );
  179.                 VEC_MERGE( vec_mergel );
  180.             }
  181.         }
  182.     }
  183.     else if( !( ( p_vout->render.i_width % 16 ) |
  184.                 ( p_vout->render.i_height % 4 ) ) )
  185.     {
  186.         /* Width is only a multiple of 16, we take 4 lines at a time */
  187.         for( i_y = p_vout->render.i_height / 4 ; i_y-- ; )
  188.         {
  189.             /* Line 1 and 2, pixels 0 to ( width - 16 ) */
  190.             VEC_NEXT_LINES( );
  191.             for( i_x = p_vout->render.i_width / 32 ; i_x-- ; )
  192.             {
  193.                 VEC_LOAD_UV( );
  194.                 VEC_MERGE( vec_mergeh );
  195.                 VEC_MERGE( vec_mergel );
  196.             }
  197.             /* Line 1 and 2, pixels ( width - 16 ) to ( width ) */
  198.             VEC_LOAD_UV( );
  199.             VEC_MERGE( vec_mergeh );
  200.             /* Line 3 and 4, pixels 0 to 16 */
  201.             VEC_NEXT_LINES( );
  202.             VEC_MERGE( vec_mergel );
  203.             /* Line 3 and 4, pixels 16 to ( width ) */
  204.             for( i_x = p_vout->render.i_width / 32 ; i_x-- ; )
  205.             {
  206.                 VEC_LOAD_UV( );
  207.                 VEC_MERGE( vec_mergeh );
  208.                 VEC_MERGE( vec_mergel );
  209.             }
  210.         }
  211.     }
  212.     else
  213.     {
  214.         /* Crap, use the C version */
  215. #undef VEC_NEXT_LINES
  216. #undef VEC_LOAD_UV
  217. #undef VEC_MERGE
  218. #endif
  219.     const int i_source_margin = p_source->p[0].i_pitch
  220.                                  - p_source->p[0].i_visible_pitch;
  221.     const int i_source_margin_c = p_source->p[1].i_pitch
  222.                                  - p_source->p[1].i_visible_pitch;
  223.     const int i_dest_margin = p_dest->p->i_pitch
  224.                                - p_dest->p->i_visible_pitch;
  225.     for( i_y = p_vout->render.i_height / 2 ; i_y-- ; )
  226.     {
  227.         p_line1 = p_line2;
  228.         p_line2 += p_dest->p->i_pitch;
  229.         p_y1 = p_y2;
  230.         p_y2 += p_source->p[Y_PLANE].i_pitch;
  231. #if !defined (MODULE_NAME_IS_i420_yuy2_mmx)
  232.         for( i_x = p_vout->render.i_width / 2 ; i_x-- ; )
  233.         {
  234.             C_YUV420_YUYV( );
  235.         }
  236. #else
  237.         for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
  238.         {
  239.             MMX_CALL( MMX_YUV420_YUYV );
  240.         }
  241.         for( i_x = ( p_vout->render.i_width % 8 ) / 2; i_x-- ; )
  242.         {
  243.             C_YUV420_YUYV( );
  244.         }
  245. #endif
  246.         p_y1 += i_source_margin;
  247.         p_y2 += i_source_margin;
  248.         p_u += i_source_margin_c;
  249.         p_v += i_source_margin_c;
  250.         p_line1 += i_dest_margin;
  251.         p_line2 += i_dest_margin;
  252.     }
  253. #if defined (MODULE_NAME_IS_i420_yuy2_altivec)
  254.     }
  255. #endif
  256. }
  257. /*****************************************************************************
  258.  * I420_YVYU: planar YUV 4:2:0 to packed YVYU 4:2:2
  259.  *****************************************************************************/
  260. #if !defined (MODULE_NAME_IS_i420_yuy2_altivec)
  261. static void I420_YVYU( vout_thread_t *p_vout, picture_t *p_source,
  262.                                               picture_t *p_dest )
  263. {
  264.     uint8_t *p_line1, *p_line2 = p_dest->p->p_pixels;
  265.     uint8_t *p_y1, *p_y2 = p_source->Y_PIXELS;
  266.     uint8_t *p_u = p_source->U_PIXELS;
  267.     uint8_t *p_v = p_source->V_PIXELS;
  268.     int i_x, i_y;
  269.     const int i_source_margin = p_source->p[0].i_pitch
  270.                                  - p_source->p[0].i_visible_pitch;
  271.     const int i_source_margin_c = p_source->p[1].i_pitch
  272.                                  - p_source->p[1].i_visible_pitch;
  273.     const int i_dest_margin = p_dest->p->i_pitch
  274.                                - p_dest->p->i_visible_pitch;
  275.     for( i_y = p_vout->render.i_height / 2 ; i_y-- ; )
  276.     {
  277.         p_line1 = p_line2;
  278.         p_line2 += p_dest->p->i_pitch;
  279.         p_y1 = p_y2;
  280.         p_y2 += p_source->p[Y_PLANE].i_pitch;
  281.         for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
  282.         {
  283. #if defined (MODULE_NAME_IS_i420_yuy2)
  284.             C_YUV420_YVYU( );
  285.             C_YUV420_YVYU( );
  286.             C_YUV420_YVYU( );
  287.             C_YUV420_YVYU( );
  288. #else
  289.             MMX_CALL( MMX_YUV420_YVYU );
  290. #endif
  291.         }
  292.         p_y1 += i_source_margin;
  293.         p_y2 += i_source_margin;
  294.         p_u += i_source_margin_c;
  295.         p_v += i_source_margin_c;
  296.         p_line1 += i_dest_margin;
  297.         p_line2 += i_dest_margin;
  298.     }
  299. }
  300. /*****************************************************************************
  301.  * I420_UYVY: planar YUV 4:2:0 to packed UYVY 4:2:2
  302.  *****************************************************************************/
  303. static void I420_UYVY( vout_thread_t *p_vout, picture_t *p_source,
  304.                                               picture_t *p_dest )
  305. {
  306.     uint8_t *p_line1, *p_line2 = p_dest->p->p_pixels;
  307.     uint8_t *p_y1, *p_y2 = p_source->Y_PIXELS;
  308.     uint8_t *p_u = p_source->U_PIXELS;
  309.     uint8_t *p_v = p_source->V_PIXELS;
  310.     int i_x, i_y;
  311.     const int i_source_margin = p_source->p[0].i_pitch
  312.                                  - p_source->p[0].i_visible_pitch;
  313.     const int i_source_margin_c = p_source->p[1].i_pitch
  314.                                  - p_source->p[1].i_visible_pitch;
  315.     const int i_dest_margin = p_dest->p->i_pitch
  316.                                - p_dest->p->i_visible_pitch;
  317.     for( i_y = p_vout->render.i_height / 2 ; i_y-- ; )
  318.     {
  319.         p_line1 = p_line2;
  320.         p_line2 += p_dest->p->i_pitch;
  321.         p_y1 = p_y2;
  322.         p_y2 += p_source->p[Y_PLANE].i_pitch;
  323.         for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
  324.         {
  325. #if defined (MODULE_NAME_IS_i420_yuy2)
  326.             C_YUV420_UYVY( );
  327.             C_YUV420_UYVY( );
  328.             C_YUV420_UYVY( );
  329.             C_YUV420_UYVY( );
  330. #else
  331.             MMX_CALL( MMX_YUV420_UYVY );
  332. #endif
  333.         }
  334.         p_y1 += i_source_margin;
  335.         p_y2 += i_source_margin;
  336.         p_u += i_source_margin_c;
  337.         p_v += i_source_margin_c;
  338.         p_line1 += i_dest_margin;
  339.         p_line2 += i_dest_margin;
  340.     }
  341. }
  342. /*****************************************************************************
  343.  * I420_IUYV: planar YUV 4:2:0 to interleaved packed UYVY 4:2:2
  344.  *****************************************************************************/
  345. static void I420_IUYV( vout_thread_t *p_vout, picture_t *p_source,
  346.                                               picture_t *p_dest )
  347. {
  348.     /* FIXME: TODO ! */
  349.     msg_Err( p_vout, "I420_IUYV unimplemented, please harass <sam@zoy.org>" );
  350. }
  351. /*****************************************************************************
  352.  * I420_cyuv: planar YUV 4:2:0 to upside-down packed UYVY 4:2:2
  353.  *****************************************************************************/
  354. static void I420_cyuv( vout_thread_t *p_vout, picture_t *p_source,
  355.                                               picture_t *p_dest )
  356. {
  357.     uint8_t *p_line1 = p_dest->p->p_pixels +
  358.                        p_dest->p->i_visible_lines * p_dest->p->i_pitch
  359.                        + p_dest->p->i_pitch;
  360.     uint8_t *p_line2 = p_dest->p->p_pixels +
  361.                        p_dest->p->i_visible_lines * p_dest->p->i_pitch;
  362.     uint8_t *p_y1, *p_y2 = p_source->Y_PIXELS;
  363.     uint8_t *p_u = p_source->U_PIXELS;
  364.     uint8_t *p_v = p_source->V_PIXELS;
  365.     int i_x, i_y;
  366.     const int i_source_margin = p_source->p[0].i_pitch
  367.                                  - p_source->p[0].i_visible_pitch;
  368.     const int i_source_margin_c = p_source->p[1].i_pitch
  369.                                  - p_source->p[1].i_visible_pitch;
  370.     const int i_dest_margin = p_dest->p->i_pitch
  371.                                - p_dest->p->i_visible_pitch;
  372.     for( i_y = p_vout->render.i_height / 2 ; i_y-- ; )
  373.     {
  374.         p_line1 -= 3 * p_dest->p->i_pitch;
  375.         p_line2 -= 3 * p_dest->p->i_pitch;
  376.         p_y1 = p_y2;
  377.         p_y2 += p_source->p[Y_PLANE].i_pitch;
  378.         for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
  379.         {
  380. #if defined (MODULE_NAME_IS_i420_yuy2)
  381.             C_YUV420_UYVY( );
  382.             C_YUV420_UYVY( );
  383.             C_YUV420_UYVY( );
  384.             C_YUV420_UYVY( );
  385. #else
  386.             MMX_CALL( MMX_YUV420_UYVY );
  387. #endif
  388.         }
  389.         p_y1 += i_source_margin;
  390.         p_y2 += i_source_margin;
  391.         p_u += i_source_margin_c;
  392.         p_v += i_source_margin_c;
  393.         p_line1 += i_dest_margin;
  394.         p_line2 += i_dest_margin;
  395.     }
  396. }
  397. #endif // !defined (MODULE_NAME_IS_i420_yuy2_altivec)
  398. /*****************************************************************************
  399.  * I420_Y211: planar YUV 4:2:0 to packed YUYV 2:1:1
  400.  *****************************************************************************/
  401. #if defined (MODULE_NAME_IS_i420_yuy2)
  402. static void I420_Y211( vout_thread_t *p_vout, picture_t *p_source,
  403.                                               picture_t *p_dest )
  404. {
  405.     uint8_t *p_line1, *p_line2 = p_dest->p->p_pixels;
  406.     uint8_t *p_y1, *p_y2 = p_source->Y_PIXELS;
  407.     uint8_t *p_u = p_source->U_PIXELS;
  408.     uint8_t *p_v = p_source->V_PIXELS;
  409.     int i_x, i_y;
  410.     const int i_source_margin = p_source->p[0].i_pitch
  411.                                  - p_source->p[0].i_visible_pitch;
  412.     const int i_source_margin_c = p_source->p[1].i_pitch
  413.                                  - p_source->p[1].i_visible_pitch;
  414.     const int i_dest_margin = p_dest->p->i_pitch
  415.                                - p_dest->p->i_visible_pitch;
  416.     for( i_y = p_vout->render.i_height / 2 ; i_y-- ; )
  417.     {
  418.         p_line1 = p_line2;
  419.         p_line2 += p_dest->p->i_pitch;
  420.         p_y1 = p_y2;
  421.         p_y2 += p_source->p[Y_PLANE].i_pitch;
  422.         for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
  423.         {
  424.             C_YUV420_Y211( );
  425.             C_YUV420_Y211( );
  426.         }
  427.         p_y1 += i_source_margin;
  428.         p_y2 += i_source_margin;
  429.         p_u += i_source_margin_c;
  430.         p_v += i_source_margin_c;
  431.         p_line1 += i_dest_margin;
  432.         p_line2 += i_dest_margin;
  433.     }
  434. }
  435. #endif