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

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * extract.c : Extract RGB components
  3.  *****************************************************************************
  4.  * Copyright (C) 2000-2006 the VideoLAN team
  5.  * $Id: c061884ac2cf26ad6ec8934c408492e04fe0e0c0 $
  6.  *
  7.  * Authors: Antoine Cellerier <dionoea .t videolan d@t 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  22.  *****************************************************************************/
  23. /*****************************************************************************
  24.  * Preamble
  25.  *****************************************************************************/
  26. #ifdef HAVE_CONFIG_H
  27. # include "config.h"
  28. #endif
  29. #include <vlc_common.h>
  30. #include <vlc_plugin.h>
  31. #include <vlc_vout.h>
  32. #include "vlc_filter.h"
  33. #include "filter_picture.h"
  34. #include "math.h"
  35. /*****************************************************************************
  36.  * Local prototypes
  37.  *****************************************************************************/
  38. static int  Create      ( vlc_object_t * );
  39. static void Destroy     ( vlc_object_t * );
  40. static picture_t *Filter( filter_t *, picture_t * );
  41. static int ExtractCallback( vlc_object_t *, char const *,
  42.                             vlc_value_t, vlc_value_t, void * );
  43. static void get_red_from_yuv420( picture_t *, picture_t *, int, int, int );
  44. static void get_green_from_yuv420( picture_t *, picture_t *, int, int, int );
  45. static void get_blue_from_yuv420( picture_t *, picture_t *, int, int, int );
  46. static void get_red_from_yuv422( picture_t *, picture_t *, int, int, int );
  47. static void get_green_from_yuv422( picture_t *, picture_t *, int, int, int );
  48. static void get_blue_from_yuv422( picture_t *, picture_t *, int, int, int );
  49. static void make_projection_matrix( filter_t *, int color, int *matrix );
  50. static void get_custom_from_yuv420( picture_t *, picture_t *, int, int, int, int * );
  51. static void get_custom_from_yuv422( picture_t *, picture_t *, int, int, int, int * );
  52. static void get_custom_from_packedyuv422( picture_t *, picture_t *, int * );
  53. #define COMPONENT_TEXT N_("RGB component to extract")
  54. #define COMPONENT_LONGTEXT N_("RGB component to extract. 0 for Red, 1 for Green and 2 for Blue.")
  55. #define FILTER_PREFIX "extract-"
  56. static const int pi_component_values[] = { 0xFF0000, 0x00FF00, 0x0000FF };
  57. static const char *const ppsz_component_descriptions[] = {
  58.     "Red", "Green", "Blue" };
  59. /*****************************************************************************
  60.  * Module descriptor
  61.  *****************************************************************************/
  62. vlc_module_begin ()
  63.     set_description( N_("Extract RGB component video filter") )
  64.     set_shortname( N_("Extract" ))
  65.     set_category( CAT_VIDEO )
  66.     set_subcategory( SUBCAT_VIDEO_VFILTER )
  67.     set_capability( "video filter2", 0 )
  68.     add_shortcut( "extract" )
  69.     add_integer_with_range( FILTER_PREFIX "component", 0xFF0000, 1, 0xFFFFFF,
  70.                  NULL, COMPONENT_TEXT, COMPONENT_LONGTEXT, false )
  71.         change_integer_list( pi_component_values, ppsz_component_descriptions, NULL )
  72.     set_callbacks( Create, Destroy )
  73. vlc_module_end ()
  74. static const char *const ppsz_filter_options[] = {
  75.     "component", NULL
  76. };
  77. enum { RED=0xFF0000, GREEN=0x00FF00, BLUE=0x0000FF };
  78. struct filter_sys_t
  79. {
  80.     vlc_mutex_t lock;
  81.     int *projection_matrix;
  82.     uint32_t i_color;
  83. };
  84. /*****************************************************************************
  85.  * Create
  86.  *****************************************************************************/
  87. static int Create( vlc_object_t *p_this )
  88. {
  89.     filter_t *p_filter = (filter_t *)p_this;
  90.     switch( p_filter->fmt_in.video.i_chroma )
  91.     {
  92.         case VLC_FOURCC('I','4','2','0'):
  93.         case VLC_FOURCC('I','Y','U','V'):
  94.         case VLC_FOURCC('J','4','2','0'):
  95.         case VLC_FOURCC('Y','V','1','2'):
  96.         case VLC_FOURCC('I','4','2','2'):
  97.         case VLC_FOURCC('J','4','2','2'):
  98.         CASE_PACKED_YUV_422
  99.             break;
  100.         default:
  101.             /* We only want planar YUV 4:2:0 or 4:2:2 */
  102.             msg_Err( p_filter, "Unsupported input chroma (%4s)",
  103.                      (char*)&(p_filter->fmt_in.video.i_chroma) );
  104.             return VLC_EGENERIC;
  105.     }
  106.     /* Allocate structure */
  107.     p_filter->p_sys = malloc( sizeof( filter_sys_t ) );
  108.     if( p_filter->p_sys == NULL )
  109.         return VLC_ENOMEM;
  110.     p_filter->p_sys->projection_matrix = malloc( 9 * sizeof( int ) );
  111.     if( !p_filter->p_sys->projection_matrix )
  112.     {
  113.         free( p_filter->p_sys );
  114.         return VLC_ENOMEM;
  115.     }
  116.     config_ChainParse( p_filter, FILTER_PREFIX, ppsz_filter_options,
  117.                        p_filter->p_cfg );
  118.     p_filter->p_sys->i_color = var_CreateGetIntegerCommand( p_filter,
  119.                                                FILTER_PREFIX "component" );
  120.     /* Matrix won't be used for RED, GREEN or BLUE in planar formats */
  121.     make_projection_matrix( p_filter, p_filter->p_sys->i_color,
  122.                             p_filter->p_sys->projection_matrix );
  123.     vlc_mutex_init( &p_filter->p_sys->lock );
  124.     var_AddCallback( p_filter, FILTER_PREFIX "component",
  125.                      ExtractCallback, p_filter->p_sys );
  126.     p_filter->pf_video_filter = Filter;
  127.     return VLC_SUCCESS;
  128. }
  129. /*****************************************************************************
  130.  * Destroy
  131.  *****************************************************************************/
  132. static void Destroy( vlc_object_t *p_this )
  133. {
  134.     filter_t *p_filter = (filter_t *)p_this;
  135.     filter_sys_t *p_sys = p_filter->p_sys;
  136.     var_DelCallback( p_filter, FILTER_PREFIX "component", ExtractCallback,
  137.                      p_sys );
  138.     vlc_mutex_destroy( &p_sys->lock );
  139.     free( p_sys->projection_matrix );
  140.     free( p_sys );
  141. }
  142. /*****************************************************************************
  143.  * Render
  144.  *****************************************************************************/
  145. static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
  146. {
  147.     picture_t *p_outpic;
  148.     filter_sys_t *p_sys = p_filter->p_sys;
  149.     if( !p_pic ) return NULL;
  150.     p_outpic = filter_NewPicture( p_filter );
  151.     if( !p_outpic )
  152.     {
  153.         picture_Release( p_pic );
  154.         return NULL;
  155.     }
  156.     vlc_mutex_lock( &p_sys->lock );
  157.     switch( p_pic->format.i_chroma )
  158.     {
  159.         case VLC_FOURCC('I','4','2','0'):
  160.         case VLC_FOURCC('I','Y','U','V'):
  161.         case VLC_FOURCC('J','4','2','0'):
  162.         case VLC_FOURCC('Y','V','1','2'):
  163.             switch( p_sys->i_color )
  164.             {
  165.                 case RED:
  166.                     get_red_from_yuv420( p_pic, p_outpic,
  167.                                          Y_PLANE, U_PLANE, V_PLANE );
  168.                     break;
  169.                 case GREEN:
  170.                     get_green_from_yuv420( p_pic, p_outpic,
  171.                                            Y_PLANE, U_PLANE, V_PLANE );
  172.                     break;
  173.                 case BLUE:
  174.                     get_blue_from_yuv420( p_pic, p_outpic,
  175.                                           Y_PLANE, U_PLANE, V_PLANE );
  176.                     break;
  177.                 default:
  178.                     get_custom_from_yuv420( p_pic, p_outpic,
  179.                                             Y_PLANE, U_PLANE, V_PLANE,
  180.                                             p_sys->projection_matrix);
  181.                     break;
  182.             }
  183.             break;
  184.         case VLC_FOURCC('I','4','2','2'):
  185.         case VLC_FOURCC('J','4','2','2'):
  186.             switch( p_filter->p_sys->i_color )
  187.             {
  188.                 case RED:
  189.                     get_red_from_yuv422( p_pic, p_outpic,
  190.                                          Y_PLANE, U_PLANE, V_PLANE );
  191.                     break;
  192.                 case GREEN:
  193.                     get_green_from_yuv422( p_pic, p_outpic,
  194.                                            Y_PLANE, U_PLANE, V_PLANE );
  195.                     break;
  196.                 case BLUE:
  197.                     get_blue_from_yuv422( p_pic, p_outpic,
  198.                                           Y_PLANE, U_PLANE, V_PLANE );
  199.                     break;
  200.                 default:
  201.                     get_custom_from_yuv422( p_pic, p_outpic,
  202.                                             Y_PLANE, U_PLANE, V_PLANE,
  203.                                             p_sys->projection_matrix);
  204.                     break;
  205.             }
  206.             break;
  207.         CASE_PACKED_YUV_422
  208.             get_custom_from_packedyuv422( p_pic, p_outpic,
  209.                                           p_sys->projection_matrix );
  210.             break;
  211.         default:
  212.             vlc_mutex_unlock( &p_sys->lock );
  213.             msg_Warn( p_filter, "Unsupported input chroma (%4s)",
  214.                       (char*)&(p_pic->format.i_chroma) );
  215.             picture_Release( p_pic );
  216.             return NULL;
  217.     }
  218.     vlc_mutex_unlock( &p_sys->lock );
  219.     return CopyInfoAndRelease( p_outpic, p_pic );
  220. }
  221. static inline uint8_t crop( int a )
  222. {
  223.     if( a < 0 ) return 0;
  224.     if( a > 255 ) return 255;
  225.     else return (uint8_t)a;
  226. }
  227. #define U 128
  228. #define V 128
  229. static void mmult( double *res, double *a, double *b )
  230. {
  231.     int i, j, k;
  232.     for( i = 0; i < 3; i++ )
  233.     {
  234.         for( j = 0; j < 3; j++ )
  235.         {
  236.             res[ i*3 + j ] = 0.;
  237.             for( k = 0; k < 3; k++ )
  238.             {
  239.                 res[ i*3 + j ] += a[ i*3 + k ] * b[ k*3 + j ];
  240.             }
  241.         }
  242.     }
  243. }
  244. static void make_projection_matrix( filter_t *p_filter, int color, int *matrix )
  245. {
  246.     double left_matrix[9] =
  247.         {  76.24500,  149.68500,  29.07000,
  248.           -43.02765,  -84.47235, 127.50000,
  249.           127.50000, -106.76534, -20.73466 };
  250.     double right_matrix[9] =
  251.         { 257.00392,   0.00000,  360.31950,
  252.           257.00392, -88.44438, -183.53583,
  253.           257.00392, 455.41095,    0.00000 };
  254.     double red = ((double)(( 0xFF0000 & color )>>16))/255.;
  255.     double green = ((double)(( 0x00FF00 & color )>>8))/255.;
  256.     double blue = ((double)( 0x0000FF & color ))/255.;
  257.     double norm = sqrt( red*red + green*green + blue*blue );
  258.     red /= norm;
  259.     green /= norm;
  260.     blue /= norm;
  261.     /* XXX: We might still need to norm the rgb_matrix */
  262.     double rgb_matrix[9] =
  263.         { red*red,    red*green,   red*blue,
  264.           red*green,  green*green, green*blue,
  265.           red*blue,   green*blue,  blue*blue };
  266.     double result1[9];
  267.     double result[9];
  268.     int i;
  269.     msg_Dbg( p_filter, "red: %f", red );
  270.     msg_Dbg( p_filter, "green: %f", green );
  271.     msg_Dbg( p_filter, "blue: %f", blue );
  272.     mmult( result1, rgb_matrix, right_matrix );
  273.     mmult( result, left_matrix, result1 );
  274.     for( i = 0; i < 9; i++ )
  275.     {
  276.         matrix[i] = (int)result[i];
  277.     }
  278.     msg_Dbg( p_filter, "Projection matrix:" );
  279.     msg_Dbg( p_filter, "%6d %6d %6d", matrix[0], matrix[1], matrix[2] );
  280.     msg_Dbg( p_filter, "%6d %6d %6d", matrix[3], matrix[4], matrix[5] );
  281.     msg_Dbg( p_filter, "%6d %6d %6d", matrix[6], matrix[7], matrix[8] );
  282. }
  283. static void get_custom_from_yuv420( picture_t *p_inpic, picture_t *p_outpic,
  284.                                     int yp, int up, int vp, int *m )
  285. {
  286.     uint8_t *y1in = p_inpic->p[yp].p_pixels;
  287.     uint8_t *y2in;
  288.     uint8_t *uin  = p_inpic->p[up].p_pixels;
  289.     uint8_t *vin  = p_inpic->p[vp].p_pixels;
  290.     uint8_t *y1out = p_outpic->p[yp].p_pixels;
  291.     uint8_t *y2out;
  292.     uint8_t *uout  = p_outpic->p[up].p_pixels;
  293.     uint8_t *vout  = p_outpic->p[vp].p_pixels;
  294.     const int i_pitch = p_inpic->p[yp].i_pitch;
  295.     const int i_visible_pitch = p_inpic->p[yp].i_visible_pitch;
  296.     const int i_visible_lines = p_inpic->p[yp].i_visible_lines;
  297.     const int i_uv_pitch = p_inpic->p[up].i_pitch;
  298.     const int i_uv_visible_pitch = p_inpic->p[up].i_visible_pitch;
  299.     const uint8_t *yend = y1in + i_visible_lines * i_pitch;
  300.     while( y1in < yend )
  301.     {
  302.         const uint8_t *y1end = y1in + i_visible_pitch;
  303.         y2in  = y1in + i_pitch;
  304.         y2out = y1out + i_pitch;
  305.         while( y1in < y1end )
  306.         {
  307.             *uout++ = crop( (*y1in * m[3] + (*uin-U) * m[4] + (*vin-V) * m[5])
  308.                       / 65536 + U );
  309.             *vout++ = crop( (*y1in * m[6] + (*uin-U) * m[7] + (*vin-V) * m[8])
  310.                       / 65536 + V );
  311.             *y1out++ = crop( (*y1in++ * m[0] + (*uin-U) * m[1] + (*vin-V) * m[2])
  312.                        / 65536 );
  313.             *y1out++ = crop( (*y1in++ * m[0] + (*uin-U) * m[1] + (*vin-V) * m[2])
  314.                        / 65536 );
  315.             *y2out++ = crop( (*y2in++ * m[0] + (*uin-U) * m[1] + (*vin-V) * m[2])
  316.                        / 65536 );
  317.             *y2out++ = crop( (*y2in++ * m[0] + (*uin++ - U) * m[1] + (*vin++ -V) * m[2])
  318.                        / 65536 );
  319.         }
  320.         y1in  += 2*i_pitch - i_visible_pitch;
  321.         y1out += 2*i_pitch - i_visible_pitch;
  322.         uin   += i_uv_pitch - i_uv_visible_pitch;
  323.         uout  += i_uv_pitch - i_uv_visible_pitch;
  324.         vin   += i_uv_pitch - i_uv_visible_pitch;
  325.         vout  += i_uv_pitch - i_uv_visible_pitch;
  326.     }
  327. }
  328. static void get_custom_from_yuv422( picture_t *p_inpic, picture_t *p_outpic,
  329.                                     int yp, int up, int vp, int *m )
  330. {
  331.     uint8_t *y1in = p_inpic->p[yp].p_pixels;
  332.     uint8_t *uin  = p_inpic->p[up].p_pixels;
  333.     uint8_t *vin  = p_inpic->p[vp].p_pixels;
  334.     uint8_t *y1out = p_outpic->p[yp].p_pixels;
  335.     uint8_t *uout  = p_outpic->p[up].p_pixels;
  336.     uint8_t *vout  = p_outpic->p[vp].p_pixels;
  337.     const int i_pitch = p_inpic->p[yp].i_pitch;
  338.     const int i_visible_pitch = p_inpic->p[yp].i_visible_pitch;
  339.     const int i_visible_lines = p_inpic->p[yp].i_visible_lines;
  340.     const int i_uv_pitch = p_inpic->p[up].i_pitch;
  341.     const int i_uv_visible_pitch = p_inpic->p[up].i_visible_pitch;
  342.     const uint8_t *yend = y1in + i_visible_lines * i_pitch;
  343.     while( y1in < yend )
  344.     {
  345.         const uint8_t *y1end = y1in + i_visible_pitch;
  346.         while( y1in < y1end )
  347.         {
  348.             *uout++ = crop( (*y1in * m[3] + (*uin-U) * m[4] + (*vin-V) * m[5])
  349.                       / 65536 + U );
  350.             *vout++ = crop( (*y1in * m[6] + (*uin-U) * m[7] + (*vin-V) * m[8])
  351.                       / 65536 + V );
  352.             *y1out++ = crop( (*y1in++ * m[0] + (*uin-U) * m[1] + (*vin-V) * m[2])
  353.                        / 65536 );
  354.             *y1out++ = crop( (*y1in++ * m[0] + (*uin++ -U) * m[1] + (*vin++ -V) * m[2])
  355.                        / 65536 );
  356.         }
  357.         y1in  += i_pitch - i_visible_pitch;
  358.         y1out += i_pitch - i_visible_pitch;
  359.         uin   += i_uv_pitch - i_uv_visible_pitch;
  360.         uout  += i_uv_pitch - i_uv_visible_pitch;
  361.         vin   += i_uv_pitch - i_uv_visible_pitch;
  362.         vout  += i_uv_pitch - i_uv_visible_pitch;
  363.     }
  364. }
  365. static void get_custom_from_packedyuv422( picture_t *p_inpic,
  366.                                           picture_t *p_outpic,
  367.                                           int *m )
  368. {
  369.     int i_y_offset, i_u_offset, i_v_offset;
  370.     if( GetPackedYuvOffsets( p_inpic->format.i_chroma, &i_y_offset,
  371.                          &i_u_offset, &i_v_offset ) != VLC_SUCCESS )
  372.         return;
  373.     uint8_t *yin = p_inpic->p->p_pixels + i_y_offset;
  374.     uint8_t *uin = p_inpic->p->p_pixels + i_u_offset;
  375.     uint8_t *vin = p_inpic->p->p_pixels + i_v_offset;
  376.     uint8_t *yout = p_outpic->p->p_pixels + i_y_offset;
  377.     uint8_t *uout = p_outpic->p->p_pixels + i_u_offset;
  378.     uint8_t *vout = p_outpic->p->p_pixels + i_v_offset;
  379.     const int i_pitch = p_inpic->p->i_pitch;
  380.     const int i_visible_pitch = p_inpic->p->i_visible_pitch;
  381.     const int i_visible_lines = p_inpic->p->i_visible_lines;
  382.     const uint8_t *yend = yin + i_visible_lines * i_pitch;
  383.     while( yin < yend )
  384.     {
  385.         const uint8_t *ylend = yin + i_visible_pitch;
  386.         while( yin < ylend )
  387.         {
  388.             *uout = crop( (*yin * m[3] + (*uin-U) * m[4] + (*vin-V) * m[5])
  389.                       / 65536 + U );
  390.             uout += 4;
  391.             *vout = crop( (*yin * m[6] + (*uin-U) * m[7] + (*vin-V) * m[8])
  392.                      / 65536 + V );
  393.             vout += 4;
  394.             *yout = crop( (*yin * m[0] + (*uin-U) * m[1] + (*vin-V) * m[2])
  395.                        / 65536 );
  396.             yin  += 2;
  397.             yout += 2;
  398.             *yout = crop( (*yin * m[0] + (*uin-U) * m[1] + (*vin-V) * m[2])
  399.                        / 65536 );
  400.             yin  += 2;
  401.             yout += 2;
  402.             uin  += 4;
  403.             vin  += 4;
  404.         }
  405.         yin  += i_pitch - i_visible_pitch;
  406.         yout += i_pitch - i_visible_pitch;
  407.         uin  += i_pitch - i_visible_pitch;
  408.         uout += i_pitch - i_visible_pitch;
  409.         vin  += i_pitch - i_visible_pitch;
  410.         vout += i_pitch - i_visible_pitch;
  411.     }
  412. }
  413. static void get_red_from_yuv420( picture_t *p_inpic, picture_t *p_outpic,
  414.                                  int yp, int up, int vp )
  415. {
  416.     uint8_t *y1in = p_inpic->p[yp].p_pixels;
  417.     uint8_t *y2in;
  418.     uint8_t *vin  = p_inpic->p[vp].p_pixels;
  419.     uint8_t *y1out = p_outpic->p[yp].p_pixels;
  420.     uint8_t *y2out;
  421.     uint8_t *uout  = p_outpic->p[up].p_pixels;
  422.     uint8_t *vout  = p_outpic->p[vp].p_pixels;
  423.     const int i_pitch = p_inpic->p[yp].i_pitch;
  424.     const int i_visible_pitch = p_inpic->p[yp].i_visible_pitch;
  425.     const int i_visible_lines = p_inpic->p[yp].i_visible_lines;
  426.     const int i_uv_pitch = p_inpic->p[up].i_pitch;
  427.     const int i_uv_visible_pitch = p_inpic->p[up].i_visible_pitch;
  428.     const uint8_t *yend = y1in + i_visible_lines * i_pitch;
  429.     while( y1in < yend )
  430.     {
  431.         const uint8_t *y1end = y1in + i_visible_pitch;
  432.         y2in  = y1in + i_pitch;
  433.         y2out = y1out + i_pitch;
  434.         while( y1in < y1end )
  435.         {
  436. /*
  437. 19595   0   27473
  438. -11058  0   -15504
  439. 32768   0   45941
  440. */
  441.             *uout++ = crop( (*y1in * -11058 + (*vin - V) * -15504)
  442.                       / 65536 + U );
  443.             *vout++ = crop( (*y1in * 32768 + (*vin - V) * 45941)
  444.                       / 65536 + V );
  445.             *y1out++ = crop( (*y1in++ * 19595 + (*vin - V) * 27473)
  446.                        / 65536 );
  447.             *y1out++ = crop( (*y1in++ * 19595 + (*vin - V) * 27473)
  448.                        / 65536 );
  449.             *y2out++ = crop( (*y2in++ * 19594 + (*vin - V) * 27473)
  450.                        / 65536 );
  451.             *y2out++ = crop( (*y2in++ * 19594 + (*vin++ - V) * 27473)
  452.                        / 65536 );
  453.         }
  454.         y1in  += 2*i_pitch - i_visible_pitch;
  455.         y1out += 2*i_pitch - i_visible_pitch;
  456.         uout  += i_uv_pitch - i_uv_visible_pitch;
  457.         vin   += i_uv_pitch - i_uv_visible_pitch;
  458.         vout  += i_uv_pitch - i_uv_visible_pitch;
  459.     }
  460. }
  461. static void get_green_from_yuv420( picture_t *p_inpic, picture_t *p_outpic,
  462.                                  int yp, int up, int vp )
  463. {
  464.     uint8_t *y1in = p_inpic->p[yp].p_pixels;
  465.     uint8_t *y2in;
  466.     uint8_t *uin  = p_inpic->p[up].p_pixels;
  467.     uint8_t *vin  = p_inpic->p[vp].p_pixels;
  468.     uint8_t *y1out = p_outpic->p[yp].p_pixels;
  469.     uint8_t *y2out;
  470.     uint8_t *uout  = p_outpic->p[up].p_pixels;
  471.     uint8_t *vout  = p_outpic->p[vp].p_pixels;
  472.     const int i_pitch = p_inpic->p[yp].i_pitch;
  473.     const int i_visible_pitch = p_inpic->p[yp].i_visible_pitch;
  474.     const int i_visible_lines = p_inpic->p[yp].i_visible_lines;
  475.     const int i_uv_pitch = p_inpic->p[up].i_pitch;
  476.     const int i_uv_visible_pitch = p_inpic->p[up].i_visible_pitch;
  477.     const uint8_t *yend = y1in + i_visible_lines * i_pitch;
  478.     while( y1in < yend )
  479.     {
  480.         const uint8_t *y1end = y1in + i_visible_pitch;
  481.         y2in  = y1in + i_pitch;
  482.         y2out = y1out + i_pitch;
  483.         while( y1in < y1end )
  484.         {
  485. /*
  486. 38470   -13239  -27473
  487. -21710  7471    15504
  488. -27439  9443    19595
  489. */
  490.             *uout++ = crop( (*y1in * -21710 + (*uin-U) * 7471 + (*vin-V) * 15504)
  491.                       / 65536 + U );
  492.             *vout++ = crop( (*y1in * -27439 + (*uin-U) * 9443 + (*vin-V) * 19595)
  493.                       / 65536 + V );
  494.             *y1out++ = crop( (*y1in++ * 38470 + (*uin-U) * -13239 + (*vin-V) * -27473)
  495.                        / 65536 );
  496.             *y1out++ = crop( (*y1in++ * 38470 + (*uin-U) * -13239 + (*vin-V) * -27473)
  497.                        / 65536 );
  498.             *y2out++ = crop( (*y2in++ * 38470 + (*uin-U) * -13239 + (*vin-V) * -27473)
  499.                        / 65536 );
  500.             *y2out++ = crop( (*y2in++ * 38470 + (*uin++ - U) * -13239 + (*vin++ -V) * -27473)
  501.                        / 65536 );
  502.         }
  503.         y1in  += 2*i_pitch - i_visible_pitch;
  504.         y1out += 2*i_pitch - i_visible_pitch;
  505.         uin   += i_uv_pitch - i_uv_visible_pitch;
  506.         uout  += i_uv_pitch - i_uv_visible_pitch;
  507.         vin   += i_uv_pitch - i_uv_visible_pitch;
  508.         vout  += i_uv_pitch - i_uv_visible_pitch;
  509.     }
  510. }
  511. static void get_blue_from_yuv420( picture_t *p_inpic, picture_t *p_outpic,
  512.                                  int yp, int up, int vp )
  513. {
  514.     uint8_t *y1in = p_inpic->p[yp].p_pixels;
  515.     uint8_t *y2in;
  516.     uint8_t *uin  = p_inpic->p[up].p_pixels;
  517.     uint8_t *y1out = p_outpic->p[yp].p_pixels;
  518.     uint8_t *y2out;
  519.     uint8_t *uout  = p_outpic->p[up].p_pixels;
  520.     uint8_t *vout  = p_outpic->p[vp].p_pixels;
  521.     const int i_pitch = p_inpic->p[yp].i_pitch;
  522.     const int i_visible_pitch = p_inpic->p[yp].i_visible_pitch;
  523.     const int i_visible_lines = p_inpic->p[yp].i_visible_lines;
  524.     const int i_uv_pitch = p_inpic->p[up].i_pitch;
  525.     const int i_uv_visible_pitch = p_inpic->p[up].i_visible_pitch;
  526.     const uint8_t *yend = y1in + i_visible_lines * i_pitch;
  527.     while( y1in < yend )
  528.     {
  529.         const uint8_t *y1end = y1in + i_visible_pitch;
  530.         y2in  = y1in + i_pitch;
  531.         y2out = y1out + i_pitch;
  532.         while( y1in < y1end )
  533.         {
  534. /*
  535. 7471    13239   0
  536. 32768   58065   0
  537. -5329   -9443   0
  538. */
  539.             *uout++ = crop( (*y1in* 32768 + (*uin - U) * 58065 )
  540.                       / 65536 + U );
  541.             *vout++ = crop( (*y1in * -5329 + (*uin - U) * -9443 )
  542.                       / 65536 + V );
  543.             *y1out++ = crop( (*y1in++ * 7471 + (*uin - U) * 13239 )
  544.                        / 65536 );
  545.             *y1out++ = crop( (*y1in++ * 7471 + (*uin - U) * 13239 )
  546.                        / 65536 );
  547.             *y2out++ = crop( (*y2in++ * 7471 + (*uin - U) * 13239 )
  548.                        / 65536 );
  549.             *y2out++ = crop( (*y2in++ * 7471 + (*uin++ - U) * 13239 )
  550.                        / 65536 );
  551.         }
  552.         y1in  += 2*i_pitch - i_visible_pitch;
  553.         y1out += 2*i_pitch - i_visible_pitch;
  554.         uin   += i_uv_pitch - i_uv_visible_pitch;
  555.         uout  += i_uv_pitch - i_uv_visible_pitch;
  556.         vout  += i_uv_pitch - i_uv_visible_pitch;
  557.     }
  558. }
  559. static void get_red_from_yuv422( picture_t *p_inpic, picture_t *p_outpic,
  560.                                  int yp, int up, int vp )
  561. {
  562.     uint8_t *y1in = p_inpic->p[yp].p_pixels;
  563.     uint8_t *vin  = p_inpic->p[vp].p_pixels;
  564.     uint8_t *y1out = p_outpic->p[yp].p_pixels;
  565.     uint8_t *uout  = p_outpic->p[up].p_pixels;
  566.     uint8_t *vout  = p_outpic->p[vp].p_pixels;
  567.     const int i_pitch = p_inpic->p[yp].i_pitch;
  568.     const int i_visible_pitch = p_inpic->p[yp].i_visible_pitch;
  569.     const int i_visible_lines = p_inpic->p[yp].i_visible_lines;
  570.     const int i_uv_pitch = p_inpic->p[up].i_pitch;
  571.     const int i_uv_visible_pitch = p_inpic->p[up].i_visible_pitch;
  572.     const uint8_t *yend = y1in + i_visible_lines * i_pitch;
  573.     while( y1in < yend )
  574.     {
  575.         const uint8_t *y1end = y1in + i_visible_pitch;
  576.         while( y1in < y1end )
  577.         {
  578. /*
  579. 19595   0   27473
  580. -11058  0   -15504
  581. 32768   0   45941
  582. */
  583.             *uout++ = crop( (*y1in * -11058 + (*vin - V) * -15504)
  584.                       / 65536 + U );
  585.             *vout++ = crop( (*y1in * 32768 + (*vin - V) * 45941)
  586.                       / 65536 + V );
  587.             *y1out++ = crop( (*y1in++ * 19595 + (*vin - V) * 27473)
  588.                        / 65536 );
  589.             *y1out++ = crop( (*y1in++ * 19595 + (*vin++ - V) * 27473)
  590.                        / 65536 );
  591.         }
  592.         y1in  += i_pitch - i_visible_pitch;
  593.         y1out += i_pitch - i_visible_pitch;
  594.         uout  += i_uv_pitch - i_uv_visible_pitch;
  595.         vin   += i_uv_pitch - i_uv_visible_pitch;
  596.         vout  += i_uv_pitch - i_uv_visible_pitch;
  597.     }
  598. }
  599. static void get_green_from_yuv422( picture_t *p_inpic, picture_t *p_outpic,
  600.                                    int yp, int up, int vp )
  601. {
  602.     uint8_t *y1in = p_inpic->p[yp].p_pixels;
  603.     uint8_t *uin  = p_inpic->p[up].p_pixels;
  604.     uint8_t *vin  = p_inpic->p[vp].p_pixels;
  605.     uint8_t *y1out = p_outpic->p[yp].p_pixels;
  606.     uint8_t *uout  = p_outpic->p[up].p_pixels;
  607.     uint8_t *vout  = p_outpic->p[vp].p_pixels;
  608.     const int i_pitch = p_inpic->p[yp].i_pitch;
  609.     const int i_visible_pitch = p_inpic->p[yp].i_visible_pitch;
  610.     const int i_visible_lines = p_inpic->p[yp].i_visible_lines;
  611.     const int i_uv_pitch = p_inpic->p[up].i_pitch;
  612.     const int i_uv_visible_pitch = p_inpic->p[up].i_visible_pitch;
  613.     const uint8_t *yend = y1in + i_visible_lines * i_pitch;
  614.     while( y1in < yend )
  615.     {
  616.         const uint8_t *y1end = y1in + i_visible_pitch;
  617.         while( y1in < y1end )
  618.         {
  619. /*
  620. 38470   -13239  -27473
  621. -21710  7471    15504
  622. -27439  9443    19595
  623. */
  624.             *uout++ = crop( (*y1in * -21710 + (*uin-U) * 7471 + (*vin-V) * 15504)
  625.                       / 65536 + U );
  626.             *vout++ = crop( (*y1in * -27439 + (*uin-U) * 9443 + (*vin-V) * 19595)
  627.                       / 65536 + V );
  628.             *y1out++ = crop( (*y1in++ * 38470 + (*uin-U) * -13239 + (*vin-V) * -27473)
  629.                        / 65536 );
  630.             *y1out++ = crop( (*y1in++ * 38470 + (*uin++-U) * -13239 + (*vin++-V) * -27473)
  631.                        / 65536 );
  632.         }
  633.         y1in  += i_pitch - i_visible_pitch;
  634.         y1out += i_pitch - i_visible_pitch;
  635.         uin   += i_uv_pitch - i_uv_visible_pitch;
  636.         uout  += i_uv_pitch - i_uv_visible_pitch;
  637.         vin   += i_uv_pitch - i_uv_visible_pitch;
  638.         vout  += i_uv_pitch - i_uv_visible_pitch;
  639.     }
  640. }
  641. static void get_blue_from_yuv422( picture_t *p_inpic, picture_t *p_outpic,
  642.                                  int yp, int up, int vp )
  643. {
  644.     uint8_t *y1in = p_inpic->p[yp].p_pixels;
  645.     uint8_t *uin  = p_inpic->p[up].p_pixels;
  646.     uint8_t *y1out = p_outpic->p[yp].p_pixels;
  647.     uint8_t *uout  = p_outpic->p[up].p_pixels;
  648.     uint8_t *vout  = p_outpic->p[vp].p_pixels;
  649.     const int i_pitch = p_inpic->p[yp].i_pitch;
  650.     const int i_visible_pitch = p_inpic->p[yp].i_visible_pitch;
  651.     const int i_visible_lines = p_inpic->p[yp].i_visible_lines;
  652.     const int i_uv_pitch = p_inpic->p[up].i_pitch;
  653.     const int i_uv_visible_pitch = p_inpic->p[up].i_visible_pitch;
  654.     const uint8_t *yend = y1in + i_visible_lines * i_pitch;
  655.     while( y1in < yend )
  656.     {
  657.         const uint8_t *y1end = y1in + i_visible_pitch;
  658.         while( y1in < y1end )
  659.         {
  660. /*
  661. 7471    13239   0
  662. 32768   58065   0
  663. -5329   -9443   0
  664. */
  665.             *uout++ = crop( (*y1in* 32768 + (*uin - U) * 58065 )
  666.                       / 65536 + U );
  667.             *vout++ = crop( (*y1in * -5329 + (*uin - U) * -9443 )
  668.                       / 65536 + V );
  669.             *y1out++ = crop( (*y1in++ * 7471 + (*uin - U) * 13239 )
  670.                        / 65536 );
  671.             *y1out++ = crop( (*y1in++ * 7471 + (*uin++ - U) * 13239 )
  672.                        / 65536 );
  673.         }
  674.         y1in  += i_pitch - i_visible_pitch;
  675.         y1out += i_pitch - i_visible_pitch;
  676.         uin   += i_uv_pitch - i_uv_visible_pitch;
  677.         uout  += i_uv_pitch - i_uv_visible_pitch;
  678.         vout  += i_uv_pitch - i_uv_visible_pitch;
  679.     }
  680. }
  681. static int ExtractCallback( vlc_object_t *p_this, char const *psz_var,
  682.                             vlc_value_t oldval, vlc_value_t newval,
  683.                             void *p_data )
  684. {
  685.     VLC_UNUSED(oldval);
  686.     filter_sys_t *p_sys = (filter_sys_t *)p_data;
  687.     vlc_mutex_lock( &p_sys->lock );
  688.     if( !strcmp( psz_var, FILTER_PREFIX "component" ) )
  689.     {
  690.         p_sys->i_color = newval.i_int;
  691.         /* Matrix won't be used for RED, GREEN or BLUE in planar formats */
  692.         make_projection_matrix( (filter_t *)p_this, p_sys->i_color,
  693.                                 p_sys->projection_matrix );
  694.     }
  695.     else
  696.     {
  697.         msg_Warn( p_this, "Unknown callback command." );
  698.     }
  699.     vlc_mutex_unlock( &p_sys->lock );
  700.     return VLC_SUCCESS;
  701. }