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

midi

开发平台:

Unix_Linux

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