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

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * transform.c : transform image module for vlc
  3.  *****************************************************************************
  4.  * Copyright (C) 2000-2004 VideoLAN
  5.  * $Id: transform.c 8551 2004-08-28 17:36:02Z 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 <stdlib.h>                                      /* malloc(), free() */
  27. #include <string.h>
  28. #include <vlc/vlc.h>
  29. #include <vlc/vout.h>
  30. #include "filter_common.h"
  31. #define TRANSFORM_MODE_HFLIP   1
  32. #define TRANSFORM_MODE_VFLIP   2
  33. #define TRANSFORM_MODE_90      3
  34. #define TRANSFORM_MODE_180     4
  35. #define TRANSFORM_MODE_270     5
  36. /*****************************************************************************
  37.  * Local prototypes
  38.  *****************************************************************************/
  39. static int  Create    ( vlc_object_t * );
  40. static void Destroy   ( vlc_object_t * );
  41. static int  Init      ( vout_thread_t * );
  42. static void End       ( vout_thread_t * );
  43. static void Render    ( vout_thread_t *, picture_t * );
  44. static int  SendEvents( vlc_object_t *, char const *,
  45.                         vlc_value_t, vlc_value_t, void * );
  46. /*****************************************************************************
  47.  * Module descriptor
  48.  *****************************************************************************/
  49. #define TYPE_TEXT N_("Transform type")
  50. #define TYPE_LONGTEXT N_("One of '90', '180', '270', 'hflip' and 'vflip'")
  51. static char *type_list[] = { "90", "180", "270", "hflip", "vflip" };
  52. static char *type_list_text[] = { N_("Rotate by 90 degrees"),
  53.   N_("Rotate by 180 degrees"), N_("Rotate by 270 degrees"),
  54.   N_("Flip horizontally"), N_("Flip vertically") };
  55. vlc_module_begin();
  56.     set_description( _("Video transformation filter") );
  57.     set_capability( "video filter", 0 );
  58.     add_string( "transform-type", "90", NULL,
  59.                           TYPE_TEXT, TYPE_LONGTEXT, VLC_FALSE);
  60.         change_string_list( type_list, type_list_text, 0);
  61.     add_shortcut( "transform" );
  62.     set_callbacks( Create, Destroy );
  63. vlc_module_end();
  64. /*****************************************************************************
  65.  * vout_sys_t: Transform video output method descriptor
  66.  *****************************************************************************
  67.  * This structure is part of the video output thread descriptor.
  68.  * It describes the Transform specific properties of an output thread.
  69.  *****************************************************************************/
  70. struct vout_sys_t
  71. {
  72.     int i_mode;
  73.     vlc_bool_t b_rotation;
  74.     vout_thread_t *p_vout;
  75. };
  76. /*****************************************************************************
  77.  * Control: control facility for the vout (forwards to child vout)
  78.  *****************************************************************************/
  79. static int Control( vout_thread_t *p_vout, int i_query, va_list args )
  80. {
  81.     return vout_vaControl( p_vout->p_sys->p_vout, i_query, args );
  82. }
  83. /*****************************************************************************
  84.  * Create: allocates Transform video thread output method
  85.  *****************************************************************************
  86.  * This function allocates and initializes a Transform vout method.
  87.  *****************************************************************************/
  88. static int Create( vlc_object_t *p_this )
  89. {
  90.     vout_thread_t *p_vout = (vout_thread_t *)p_this;
  91.     char *psz_method;
  92.     /* Allocate structure */
  93.     p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
  94.     if( p_vout->p_sys == NULL )
  95.     {
  96.         msg_Err( p_vout, "out of memory" );
  97.         return VLC_ENOMEM;
  98.     }
  99.     p_vout->pf_init = Init;
  100.     p_vout->pf_end = End;
  101.     p_vout->pf_manage = NULL;
  102.     p_vout->pf_render = Render;
  103.     p_vout->pf_display = NULL;
  104.     p_vout->pf_control = Control;
  105.     /* Look what method was requested */
  106.     psz_method = config_GetPsz( p_vout, "transform-type" );
  107.     if( psz_method == NULL )
  108.     {
  109.         msg_Err( p_vout, "configuration variable %s empty", "transform-type" );
  110.         msg_Err( p_vout, "no valid transform mode provided, using '90'" );
  111.         p_vout->p_sys->i_mode = TRANSFORM_MODE_90;
  112.         p_vout->p_sys->b_rotation = 1;
  113.     }
  114.     else
  115.     {
  116.         if( !strcmp( psz_method, "hflip" ) )
  117.         {
  118.             p_vout->p_sys->i_mode = TRANSFORM_MODE_HFLIP;
  119.             p_vout->p_sys->b_rotation = 0;
  120.         }
  121.         else if( !strcmp( psz_method, "vflip" ) )
  122.         {
  123.             p_vout->p_sys->i_mode = TRANSFORM_MODE_VFLIP;
  124.             p_vout->p_sys->b_rotation = 0;
  125.         }
  126.         else if( !strcmp( psz_method, "90" ) )
  127.         {
  128.             p_vout->p_sys->i_mode = TRANSFORM_MODE_90;
  129.             p_vout->p_sys->b_rotation = 1;
  130.         }
  131.         else if( !strcmp( psz_method, "180" ) )
  132.         {
  133.             p_vout->p_sys->i_mode = TRANSFORM_MODE_180;
  134.             p_vout->p_sys->b_rotation = 0;
  135.         }
  136.         else if( !strcmp( psz_method, "270" ) )
  137.         {
  138.             p_vout->p_sys->i_mode = TRANSFORM_MODE_270;
  139.             p_vout->p_sys->b_rotation = 1;
  140.         }
  141.         else
  142.         {
  143.             msg_Err( p_vout, "no valid transform mode provided, using '90'" );
  144.             p_vout->p_sys->i_mode = TRANSFORM_MODE_90;
  145.             p_vout->p_sys->b_rotation = 1;
  146.         }
  147.         free( psz_method );
  148.     }
  149.     return VLC_SUCCESS;
  150. }
  151. /*****************************************************************************
  152.  * Init: initialize Transform video thread output method
  153.  *****************************************************************************/
  154. static int Init( vout_thread_t *p_vout )
  155. {
  156.     int i_index;
  157.     picture_t *p_pic;
  158.     I_OUTPUTPICTURES = 0;
  159.     /* Initialize the output structure */
  160.     p_vout->output.i_chroma = p_vout->render.i_chroma;
  161.     p_vout->output.i_width  = p_vout->render.i_width;
  162.     p_vout->output.i_height = p_vout->render.i_height;
  163.     p_vout->output.i_aspect = p_vout->render.i_aspect;
  164.     /* Try to open the real video output */
  165.     msg_Dbg( p_vout, "spawning the real video output" );
  166.     if( p_vout->p_sys->b_rotation )
  167.     {
  168.         p_vout->p_sys->p_vout = vout_Create( p_vout,
  169.                            p_vout->render.i_height, p_vout->render.i_width,
  170.                            p_vout->render.i_chroma,
  171.                            (uint64_t)VOUT_ASPECT_FACTOR
  172.                             * (uint64_t)VOUT_ASPECT_FACTOR
  173.                             / (uint64_t)p_vout->render.i_aspect );
  174.     }
  175.     else
  176.     {
  177.         p_vout->p_sys->p_vout = vout_Create( p_vout,
  178.                            p_vout->render.i_width, p_vout->render.i_height,
  179.                            p_vout->render.i_chroma, p_vout->render.i_aspect );
  180.     }
  181.     /* Everything failed */
  182.     if( p_vout->p_sys->p_vout == NULL )
  183.     {
  184.         msg_Err( p_vout, "cannot open vout, aborting" );
  185.         return VLC_EGENERIC;
  186.     }
  187.     ALLOCATE_DIRECTBUFFERS( VOUT_MAX_PICTURES );
  188.     ADD_CALLBACKS( p_vout->p_sys->p_vout, SendEvents );
  189.     ADD_PARENT_CALLBACKS( SendEventsToChild );
  190.     return VLC_SUCCESS;
  191. }
  192. /*****************************************************************************
  193.  * End: terminate Transform video thread output method
  194.  *****************************************************************************/
  195. static void End( vout_thread_t *p_vout )
  196. {
  197.     int i_index;
  198.     /* Free the fake output buffers we allocated */
  199.     for( i_index = I_OUTPUTPICTURES ; i_index ; )
  200.     {
  201.         i_index--;
  202.         free( PP_OUTPUTPICTURE[ i_index ]->p_data_orig );
  203.     }
  204. }
  205. /*****************************************************************************
  206.  * Destroy: destroy Transform video thread output method
  207.  *****************************************************************************
  208.  * Terminate an output method created by TransformCreateOutputMethod
  209.  *****************************************************************************/
  210. static void Destroy( vlc_object_t *p_this )
  211. {
  212.     vout_thread_t *p_vout = (vout_thread_t *)p_this;
  213.     if( p_vout->p_sys->p_vout )
  214.     {
  215.         DEL_CALLBACKS( p_vout->p_sys->p_vout, SendEvents );
  216.         vlc_object_detach( p_vout->p_sys->p_vout );
  217.         vout_Destroy( p_vout->p_sys->p_vout );
  218.     }
  219.     DEL_PARENT_CALLBACKS( SendEventsToChild );
  220.     free( p_vout->p_sys );
  221. }
  222. /*****************************************************************************
  223.  * Render: displays previously rendered output
  224.  *****************************************************************************
  225.  * This function send the currently rendered image to Transform image, waits
  226.  * until it is displayed and switch the two rendering buffers, preparing next
  227.  * frame.
  228.  *****************************************************************************/
  229. static void Render( vout_thread_t *p_vout, picture_t *p_pic )
  230. {
  231.     picture_t *p_outpic;
  232.     int i_index;
  233.     /* This is a new frame. Get a structure from the video_output. */
  234.     while( ( p_outpic = vout_CreatePicture( p_vout->p_sys->p_vout, 0, 0, 0 ) )
  235.               == NULL )
  236.     {
  237.         if( p_vout->b_die || p_vout->b_error )
  238.         {
  239.             return;
  240.         }
  241.         msleep( VOUT_OUTMEM_SLEEP );
  242.     }
  243.     vout_DatePicture( p_vout->p_sys->p_vout, p_outpic, p_pic->date );
  244.     vout_LinkPicture( p_vout->p_sys->p_vout, p_outpic );
  245.     switch( p_vout->p_sys->i_mode )
  246.     {
  247.         case TRANSFORM_MODE_90:
  248.             for( i_index = 0 ; i_index < p_pic->i_planes ; i_index++ )
  249.             {
  250.                 int i_pitch = p_pic->p[i_index].i_pitch;
  251.                 uint8_t *p_in = p_pic->p[i_index].p_pixels;
  252.                 uint8_t *p_out = p_outpic->p[i_index].p_pixels;
  253.                 uint8_t *p_out_end = p_out +
  254.                     p_outpic->p[i_index].i_visible_lines *
  255.                     p_outpic->p[i_index].i_pitch;
  256.                 for( ; p_out < p_out_end ; )
  257.                 {
  258.                     uint8_t *p_line_end;
  259.                     p_out_end -= p_outpic->p[i_index].i_pitch
  260.                                   - p_outpic->p[i_index].i_visible_pitch;
  261.                     p_line_end = p_in + p_pic->p[i_index].i_visible_lines *
  262.                         i_pitch;
  263.                     for( ; p_in < p_line_end ; )
  264.                     {
  265.                         p_line_end -= i_pitch;
  266.                         *(--p_out_end) = *p_line_end;
  267.                     }
  268.                     p_in++;
  269.                 }
  270.             }
  271.             break;
  272.         case TRANSFORM_MODE_180:
  273.             for( i_index = 0 ; i_index < p_pic->i_planes ; i_index++ )
  274.             {
  275.                 uint8_t *p_in = p_pic->p[i_index].p_pixels;
  276.                 uint8_t *p_in_end = p_in + p_pic->p[i_index].i_visible_lines
  277.                                             * p_pic->p[i_index].i_pitch;
  278.                 uint8_t *p_out = p_outpic->p[i_index].p_pixels;
  279.                 for( ; p_in < p_in_end ; )
  280.                 {
  281.                     uint8_t *p_line_start = p_in_end
  282.                                              - p_pic->p[i_index].i_pitch;
  283.                     p_in_end -= p_pic->p[i_index].i_pitch
  284.                                  - p_pic->p[i_index].i_visible_pitch;
  285.                     for( ; p_line_start < p_in_end ; )
  286.                     {
  287.                         *p_out++ = *(--p_in_end);
  288.                     }
  289.                     p_out += p_outpic->p[i_index].i_pitch
  290.                               - p_outpic->p[i_index].i_visible_pitch;
  291.                 }
  292.             }
  293.             break;
  294.         case TRANSFORM_MODE_270:
  295.             for( i_index = 0 ; i_index < p_pic->i_planes ; i_index++ )
  296.             {
  297.                 int i_pitch = p_pic->p[i_index].i_pitch;
  298.                 uint8_t *p_in = p_pic->p[i_index].p_pixels;
  299.                 uint8_t *p_out = p_outpic->p[i_index].p_pixels;
  300.                 uint8_t *p_out_end = p_out +
  301.                     p_outpic->p[i_index].i_visible_lines *
  302.                     p_outpic->p[i_index].i_pitch;
  303.                 for( ; p_out < p_out_end ; )
  304.                 {
  305.                     uint8_t *p_in_end;
  306.                     p_in_end = p_in + p_pic->p[i_index].i_visible_lines *
  307.                         i_pitch;
  308.                     for( ; p_in < p_in_end ; )
  309.                     {
  310.                         p_in_end -= i_pitch;
  311.                         *p_out++ = *p_in_end;
  312.                     }
  313.                     p_out += p_outpic->p[i_index].i_pitch
  314.                               - p_outpic->p[i_index].i_visible_pitch;
  315.                     p_in++;
  316.                 }
  317.             }
  318.             break;
  319.         case TRANSFORM_MODE_HFLIP:
  320.             for( i_index = 0 ; i_index < p_pic->i_planes ; i_index++ )
  321.             {
  322.                 uint8_t *p_in = p_pic->p[i_index].p_pixels;
  323.                 uint8_t *p_in_end = p_in + p_pic->p[i_index].i_visible_lines
  324.                                             * p_pic->p[i_index].i_pitch;
  325.                 uint8_t *p_out = p_outpic->p[i_index].p_pixels;
  326.                 for( ; p_in < p_in_end ; )
  327.                 {
  328.                     p_in_end -= p_pic->p[i_index].i_pitch;
  329.                     p_vout->p_vlc->pf_memcpy( p_out, p_in_end,
  330.                                            p_pic->p[i_index].i_visible_pitch );
  331.                     p_out += p_pic->p[i_index].i_pitch;
  332.                 }
  333.             }
  334.             break;
  335.         case TRANSFORM_MODE_VFLIP:
  336.             for( i_index = 0 ; i_index < p_pic->i_planes ; i_index++ )
  337.             {
  338.                 uint8_t *p_in = p_pic->p[i_index].p_pixels;
  339.                 uint8_t *p_in_end = p_in + p_pic->p[i_index].i_visible_lines
  340.                                             * p_pic->p[i_index].i_pitch;
  341.                 uint8_t *p_out = p_outpic->p[i_index].p_pixels;
  342.                 for( ; p_in < p_in_end ; )
  343.                 {
  344.                     uint8_t *p_line_end = p_in
  345.                                            + p_pic->p[i_index].i_visible_pitch;
  346.                     for( ; p_in < p_line_end ; )
  347.                     {
  348.                         *p_out++ = *(--p_line_end);
  349.                     }
  350.                     p_in += p_pic->p[i_index].i_pitch;
  351.                 }
  352.             }
  353.             break;
  354.         default:
  355.             break;
  356.     }
  357.     vout_UnlinkPicture( p_vout->p_sys->p_vout, p_outpic );
  358.     vout_DisplayPicture( p_vout->p_sys->p_vout, p_outpic );
  359. }
  360. /*****************************************************************************
  361.  * SendEvents: forward mouse and keyboard events to the parent p_vout
  362.  *****************************************************************************/
  363. static int SendEvents( vlc_object_t *p_this, char const *psz_var,
  364.                        vlc_value_t oldval, vlc_value_t newval, void *_p_vout )
  365. {
  366.     vout_thread_t *p_vout = (vout_thread_t *)_p_vout;
  367.     vlc_value_t sentval = newval;
  368.     /* Translate the mouse coordinates */
  369.     if( !strcmp( psz_var, "mouse-x" ) )
  370.     {
  371.         switch( p_vout->p_sys->i_mode )
  372.         {
  373.         case TRANSFORM_MODE_270:
  374.             sentval.i_int = p_vout->p_sys->p_vout->output.i_width
  375.                              - sentval.i_int;
  376.         case TRANSFORM_MODE_90:
  377.             var_Set( p_vout, "mouse-y", sentval );
  378.             return VLC_SUCCESS;
  379.         case TRANSFORM_MODE_180:
  380.         case TRANSFORM_MODE_HFLIP:
  381.             sentval.i_int = p_vout->p_sys->p_vout->output.i_width
  382.                              - sentval.i_int;
  383.             break;
  384.         case TRANSFORM_MODE_VFLIP:
  385.         default:
  386.             break;
  387.         }
  388.     }
  389.     else if( !strcmp( psz_var, "mouse-y" ) )
  390.     {
  391.         switch( p_vout->p_sys->i_mode )
  392.         {
  393.         case TRANSFORM_MODE_90:
  394.             sentval.i_int = p_vout->p_sys->p_vout->output.i_height
  395.                              - sentval.i_int;
  396.         case TRANSFORM_MODE_270:
  397.             var_Set( p_vout, "mouse-x", sentval );
  398.             return VLC_SUCCESS;
  399.         case TRANSFORM_MODE_180:
  400.         case TRANSFORM_MODE_VFLIP:
  401.             sentval.i_int = p_vout->p_sys->p_vout->output.i_height
  402.                              - sentval.i_int;
  403.             break;
  404.         case TRANSFORM_MODE_HFLIP:
  405.         default:
  406.             break;
  407.         }
  408.     }
  409.     var_Set( p_vout, psz_var, sentval );
  410.     return VLC_SUCCESS;
  411. }
  412. /*****************************************************************************
  413.  * SendEventsToChild: forward events to the child/children vout
  414.  *****************************************************************************/
  415. static int SendEventsToChild( vlc_object_t *p_this, char const *psz_var,
  416.                        vlc_value_t oldval, vlc_value_t newval, void *p_data )
  417. {
  418.     vout_thread_t *p_vout = (vout_thread_t *)p_this;
  419.     var_Set( p_vout->p_sys->p_vout, psz_var, newval );
  420.     return VLC_SUCCESS;
  421. }