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

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * clone.c : Clone video plugin for vlc
  3.  *****************************************************************************
  4.  * Copyright (C) 2002, 2003 VideoLAN
  5.  * $Id: clone.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 VOUTSEPARATOR ','
  32. /*****************************************************************************
  33.  * Local prototypes
  34.  *****************************************************************************/
  35. static int  Create    ( vlc_object_t * );
  36. static void Destroy   ( vlc_object_t * );
  37. static int  Init      ( vout_thread_t * );
  38. static void End       ( vout_thread_t * );
  39. static void Render    ( vout_thread_t *, picture_t * );
  40. static void RemoveAllVout  ( vout_thread_t *p_vout );
  41. static int  SendEvents( vlc_object_t *, char const *,
  42.                         vlc_value_t, vlc_value_t, void * );
  43. /*****************************************************************************
  44.  * Module descriptor
  45.  *****************************************************************************/
  46. #define COUNT_TEXT N_("Number of clones")
  47. #define COUNT_LONGTEXT N_("Select the number of video windows in which to "
  48.     "clone the video.")
  49. #define VOUTLIST_TEXT N_("List of video output modules")
  50. #define VOUTLIST_LONGTEXT N_("Select the specific video output modules that you want to activate.")
  51. vlc_module_begin();
  52.     set_description( _("Clone video filter") );
  53.     set_capability( "video filter", 0 );
  54.     
  55.     add_integer( "clone-count", 2, NULL, COUNT_TEXT, COUNT_LONGTEXT, VLC_FALSE );
  56.     add_string ( "clone-vout-list", NULL, NULL, VOUTLIST_TEXT, VOUTLIST_LONGTEXT, VLC_FALSE );
  57.     
  58.     add_shortcut( "clone" );
  59.     set_callbacks( Create, Destroy );
  60. vlc_module_end();
  61. /*****************************************************************************
  62.  * vout_sys_t: Clone video output method descriptor
  63.  *****************************************************************************
  64.  * This structure is part of the video output thread descriptor.
  65.  * It describes the Clone specific properties of an output thread.
  66.  *****************************************************************************/
  67. struct vout_sys_t
  68. {
  69.     int    i_clones;
  70.     /* list of vout modules to use. "default" will launch a default
  71.      * module. If specified, overrides the setting in i_clones (which it
  72.      * sets to the list length) */
  73.     char **ppsz_vout_list;
  74.     vout_thread_t **pp_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.     int i_vout;
  82.     for( i_vout = 0; i_vout < p_vout->p_sys->i_clones; i_vout++ )
  83.     {
  84.         vout_vaControl( p_vout->p_sys->pp_vout[ i_vout ], i_query, args );
  85.     }
  86.     return VLC_SUCCESS;
  87. }
  88. /*****************************************************************************
  89.  * Create: allocates Clone video thread output method
  90.  *****************************************************************************
  91.  * This function allocates and initializes a Clone vout method.
  92.  *****************************************************************************/
  93. static int Create( vlc_object_t *p_this )
  94. {
  95.     vout_thread_t *p_vout = (vout_thread_t *)p_this;
  96.     char *psz_clonelist;
  97.     /* Allocate structure */
  98.     p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
  99.     if( p_vout->p_sys == NULL )
  100.     {
  101.         msg_Err( p_vout, "out of memory" );
  102.         return VLC_ENOMEM;
  103.     }
  104.     p_vout->pf_init = Init;
  105.     p_vout->pf_end = End;
  106.     p_vout->pf_manage = NULL;
  107.     p_vout->pf_render = Render;
  108.     p_vout->pf_display = NULL;
  109.     p_vout->pf_control = Control;
  110.     psz_clonelist = config_GetPsz( p_vout, "clone-vout-list" );
  111.     if( psz_clonelist )
  112.     {
  113.         int i_dummy;
  114.         char *psz_token;
  115.         /* Count the number of defined vout */
  116.         p_vout->p_sys->i_clones = 1;
  117.         i_dummy = 0;
  118.         while( psz_clonelist[i_dummy] != 0 )
  119.         {
  120.             if( psz_clonelist[i_dummy] == VOUTSEPARATOR )
  121.                 p_vout->p_sys->i_clones++;
  122.             i_dummy++;
  123.         }
  124.         p_vout->p_sys->ppsz_vout_list = malloc( p_vout->p_sys->i_clones
  125.                                                 * sizeof(char *) );
  126.         if( !p_vout->p_sys->ppsz_vout_list )
  127.         {
  128.             msg_Err( p_vout, "out of memory" );
  129.             free( p_vout->p_sys );
  130.             return VLC_ENOMEM;
  131.         }
  132.         /* Tokenize the list */
  133.         i_dummy = 0;
  134.         psz_token = psz_clonelist;
  135.         while( psz_token && *psz_token )
  136.         {
  137.            char *psz_module;
  138.            psz_module = psz_token;
  139.            psz_token = strchr( psz_module, VOUTSEPARATOR );
  140.            if( psz_token )
  141.            {
  142.                *psz_token = '';
  143.                psz_token++;
  144.            }
  145.            p_vout->p_sys->ppsz_vout_list[i_dummy] = strdup( psz_module );
  146.            i_dummy++;
  147.         }
  148.         free( psz_clonelist );
  149.     }
  150.     else
  151.     {
  152.         /* No list was specified. We will use the default vout, and get
  153.          * the number of clones from clone-count */
  154.         p_vout->p_sys->i_clones = config_GetInt( p_vout, "clone-count" );
  155.         p_vout->p_sys->ppsz_vout_list = NULL;
  156.     }
  157.     p_vout->p_sys->i_clones = __MAX( 1, __MIN( 99, p_vout->p_sys->i_clones ) );
  158.     msg_Dbg( p_vout, "spawning %i clone(s)", p_vout->p_sys->i_clones );
  159.     p_vout->p_sys->pp_vout = malloc( p_vout->p_sys->i_clones *
  160.                                      sizeof(vout_thread_t *) );
  161.     if( p_vout->p_sys->pp_vout == NULL )
  162.     {
  163.         msg_Err( p_vout, "out of memory" );
  164.         free( p_vout->p_sys );
  165.         return VLC_ENOMEM;
  166.     }
  167.     return VLC_SUCCESS;
  168. }
  169. /*****************************************************************************
  170.  * Init: initialize Clone video thread output method
  171.  *****************************************************************************/
  172. static int Init( vout_thread_t *p_vout )
  173. {
  174.     int   i_index, i_vout;
  175.     picture_t *p_pic;
  176.     char *psz_default_vout;
  177.     I_OUTPUTPICTURES = 0;
  178.     /* Initialize the output structure */
  179.     p_vout->output.i_chroma = p_vout->render.i_chroma;
  180.     p_vout->output.i_width  = p_vout->render.i_width;
  181.     p_vout->output.i_height = p_vout->render.i_height;
  182.     p_vout->output.i_aspect = p_vout->render.i_aspect;
  183.     /* Try to open the real video output */
  184.     msg_Dbg( p_vout, "spawning the real video outputs" );
  185.     /* Save the default vout */
  186.     psz_default_vout = config_GetPsz( p_vout, "vout" );
  187.     for( i_vout = 0; i_vout < p_vout->p_sys->i_clones; i_vout++ )
  188.     {
  189.         if( p_vout->p_sys->ppsz_vout_list == NULL 
  190.             || ( !strncmp( p_vout->p_sys->ppsz_vout_list[i_vout],
  191.                            "default", 8 ) ) )
  192.         {
  193.             p_vout->p_sys->pp_vout[i_vout] =
  194.                 vout_Create( p_vout, p_vout->render.i_width,
  195.                              p_vout->render.i_height, p_vout->render.i_chroma, 
  196.                              p_vout->render.i_aspect );
  197.         }
  198.         else
  199.         {
  200.             /* create the appropriate vout instead of the default one */
  201.             config_PutPsz( p_vout, "vout",
  202.                            p_vout->p_sys->ppsz_vout_list[i_vout] );
  203.             p_vout->p_sys->pp_vout[i_vout] =
  204.                 vout_Create( p_vout, p_vout->render.i_width,
  205.                              p_vout->render.i_height, p_vout->render.i_chroma, 
  206.                              p_vout->render.i_aspect );
  207.             /* Reset the default value */
  208.             config_PutPsz( p_vout, "vout", psz_default_vout );
  209.         }
  210.         if( p_vout->p_sys->pp_vout[ i_vout ] == NULL )
  211.         {
  212.             msg_Err( p_vout, "failed to clone %i vout threads",
  213.                      p_vout->p_sys->i_clones );
  214.             p_vout->p_sys->i_clones = i_vout;
  215.             if( psz_default_vout ) free( psz_default_vout );
  216.             RemoveAllVout( p_vout );
  217.             return VLC_EGENERIC;
  218.         }
  219.         ADD_CALLBACKS( p_vout->p_sys->pp_vout[ i_vout ], SendEvents );
  220.     }
  221.     if( psz_default_vout ) free( psz_default_vout );
  222.     ALLOCATE_DIRECTBUFFERS( VOUT_MAX_PICTURES );
  223.     ADD_PARENT_CALLBACKS( SendEventsToChild );
  224.     return VLC_SUCCESS;
  225. }
  226. /*****************************************************************************
  227.  * End: terminate Clone video thread output method
  228.  *****************************************************************************/
  229. static void End( vout_thread_t *p_vout )
  230. {
  231.     int i_index;
  232.     /* Free the fake output buffers we allocated */
  233.     for( i_index = I_OUTPUTPICTURES ; i_index ; )
  234.     {
  235.         i_index--;
  236.         free( PP_OUTPUTPICTURE[ i_index ]->p_data_orig );
  237.     }
  238. }
  239. /*****************************************************************************
  240.  * Destroy: destroy Clone video thread output method
  241.  *****************************************************************************
  242.  * Terminate an output method created by CloneCreateOutputMethod
  243.  *****************************************************************************/
  244. static void Destroy( vlc_object_t *p_this )
  245. {
  246.     vout_thread_t *p_vout = (vout_thread_t *)p_this;
  247.     RemoveAllVout( p_vout );
  248.     DEL_PARENT_CALLBACKS( SendEventsToChild );
  249.     free( p_vout->p_sys->pp_vout );
  250.     free( p_vout->p_sys );
  251. }
  252. /*****************************************************************************
  253.  * Render: displays previously rendered output
  254.  *****************************************************************************
  255.  * This function send the currently rendered image to Clone image, waits
  256.  * until it is displayed and switch the two rendering buffers, preparing next
  257.  * frame.
  258.  *****************************************************************************/
  259. static void Render( vout_thread_t *p_vout, picture_t *p_pic )
  260. {
  261.     picture_t *p_outpic = NULL;
  262.     int i_vout, i_plane;
  263.     for( i_vout = 0; i_vout < p_vout->p_sys->i_clones; i_vout++ )
  264.     {
  265.         while( ( p_outpic =
  266.             vout_CreatePicture( p_vout->p_sys->pp_vout[ i_vout ], 0, 0, 0 )
  267.                ) == NULL )
  268.         {
  269.             if( p_vout->b_die || p_vout->b_error )
  270.             {
  271.                 vout_DestroyPicture(
  272.                     p_vout->p_sys->pp_vout[ i_vout ], p_outpic );
  273.                 return;
  274.             }
  275.             msleep( VOUT_OUTMEM_SLEEP );
  276.         }
  277.         vout_DatePicture( p_vout->p_sys->pp_vout[ i_vout ],
  278.                           p_outpic, p_pic->date );
  279.         vout_LinkPicture( p_vout->p_sys->pp_vout[ i_vout ], p_outpic );
  280.         for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
  281.         {
  282.             uint8_t *p_in, *p_in_end, *p_out;
  283.             int i_in_pitch = p_pic->p[i_plane].i_pitch;
  284.             const int i_out_pitch = p_outpic->p[i_plane].i_pitch;
  285.             const int i_copy_pitch = p_outpic->p[i_plane].i_visible_pitch;
  286.             p_in = p_pic->p[i_plane].p_pixels;
  287.             p_out = p_outpic->p[i_plane].p_pixels;
  288.             if( i_in_pitch == i_copy_pitch
  289.                  && i_out_pitch == i_copy_pitch )
  290.             {
  291.                 p_vout->p_vlc->pf_memcpy( p_out, p_in, i_in_pitch
  292.                                      * p_outpic->p[i_plane].i_visible_lines );
  293.             }
  294.             else
  295.             {
  296.                 p_in_end = p_in + i_in_pitch *
  297.                     p_outpic->p[i_plane].i_visible_lines;
  298.                 while( p_in < p_in_end )
  299.                 {
  300.                     p_vout->p_vlc->pf_memcpy( p_out, p_in, i_copy_pitch );
  301.                     p_in += i_in_pitch;
  302.                     p_out += i_out_pitch;
  303.                 }
  304.             }
  305.         }
  306.         vout_UnlinkPicture( p_vout->p_sys->pp_vout[ i_vout ], p_outpic );
  307.         vout_DisplayPicture( p_vout->p_sys->pp_vout[ i_vout ], p_outpic );
  308.     }
  309. }
  310. /*****************************************************************************
  311.  * RemoveAllVout: destroy all the child video output threads
  312.  *****************************************************************************/
  313. static void RemoveAllVout( vout_thread_t *p_vout )
  314. {
  315.     while( p_vout->p_sys->i_clones )
  316.     {
  317.          --p_vout->p_sys->i_clones;
  318.          DEL_CALLBACKS( p_vout->p_sys->pp_vout[p_vout->p_sys->i_clones],
  319.                         SendEvents );
  320.          vlc_object_detach( p_vout->p_sys->pp_vout[p_vout->p_sys->i_clones] );
  321.          vout_Destroy( p_vout->p_sys->pp_vout[p_vout->p_sys->i_clones] );
  322.     }
  323. }
  324. /*****************************************************************************
  325.  * SendEvents: forward mouse and keyboard events to the parent p_vout
  326.  *****************************************************************************/
  327. static int SendEvents( vlc_object_t *p_this, char const *psz_var,
  328.                        vlc_value_t oldval, vlc_value_t newval, void *p_data )
  329. {
  330.     var_Set( (vlc_object_t *)p_data, psz_var, newval );
  331.     return VLC_SUCCESS;
  332. }
  333. /*****************************************************************************
  334.  * SendEventsToChild: forward events to the child/children vout
  335.  *****************************************************************************/
  336. static int SendEventsToChild( vlc_object_t *p_this, char const *psz_var,
  337.                        vlc_value_t oldval, vlc_value_t newval, void *p_data )
  338. {
  339.     vout_thread_t *p_vout = (vout_thread_t *)p_this;
  340.     int i_vout;
  341.     for( i_vout = 0; i_vout < p_vout->p_sys->i_clones; i_vout++ )
  342.     {
  343.         var_Set( p_vout->p_sys->pp_vout[ i_vout ], psz_var, newval );
  344.         if( !strcmp( psz_var, "fullscreen" ) ) break;
  345.     }
  346.     return VLC_SUCCESS;
  347. }