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

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * chain.c : chain multiple video filter modules as a last resort solution
  3.  *****************************************************************************
  4.  * Copyright (C) 2007-2008 the VideoLAN team
  5.  * $Id: d56f67e5e85e77b9d9cb03b9e423e11bb6d6b984 $
  6.  *
  7.  * Authors: Antoine Cellerier <dionoea at videolan dot 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_filter.h>
  32. /*****************************************************************************
  33.  * Module descriptor
  34.  *****************************************************************************/
  35. static int       Activate   ( vlc_object_t * );
  36. static void      Destroy    ( vlc_object_t * );
  37. vlc_module_begin ()
  38.     set_description( N_("Video filtering using a chain of video filter modules") )
  39.     set_capability( "video filter2", 1 )
  40.     set_callbacks( Activate, Destroy )
  41. vlc_module_end ()
  42. /*****************************************************************************
  43.  * Local prototypes.
  44.  *****************************************************************************/
  45. static picture_t *Chain         ( filter_t *, picture_t * );
  46. static int BufferAllocationInit ( filter_t *, void * );
  47. static int BuildChromaResize( filter_t * );
  48. static int BuildChromaChain( filter_t *p_filter );
  49. static int CreateChain( filter_chain_t *p_chain, es_format_t *p_fmt_mid );
  50. static void EsFormatMergeSize( es_format_t *p_dst,
  51.                                const es_format_t *p_base,
  52.                                const es_format_t *p_size );
  53. static const vlc_fourcc_t pi_allowed_chromas[] = {
  54.     VLC_FOURCC('I','4','2','0'),
  55.     VLC_FOURCC('I','4','2','2'),
  56.     VLC_FOURCC('R','V','3','2'),
  57.     VLC_FOURCC('R','V','2','4'),
  58.     0
  59. };
  60. struct filter_sys_t
  61. {
  62.     filter_chain_t *p_chain;
  63. };
  64. #define CHAIN_LEVEL_MAX 4
  65. /*****************************************************************************
  66.  * Activate: allocate a chroma function
  67.  *****************************************************************************
  68.  * This function allocates and initializes a chroma function
  69.  *****************************************************************************/
  70. static int Activate( vlc_object_t *p_this )
  71. {
  72.     filter_t *p_filter = (filter_t *)p_this;
  73.     filter_sys_t *p_sys;
  74.     int i_ret;
  75.     const bool b_chroma = p_filter->fmt_in.video.i_chroma != p_filter->fmt_out.video.i_chroma;
  76.     const bool b_resize = p_filter->fmt_in.video.i_width  != p_filter->fmt_out.video.i_width ||
  77.                           p_filter->fmt_in.video.i_height != p_filter->fmt_out.video.i_height;
  78.     /* XXX Remove check on b_resize to build chroma chain (untested) */
  79.     if( !b_chroma || !b_resize )
  80.         return VLC_EGENERIC;
  81.     p_sys = p_filter->p_sys = malloc( sizeof( *p_sys ) );
  82.     if( !p_sys )
  83.         return VLC_ENOMEM;
  84.     memset( p_sys, 0, sizeof( *p_sys ) );
  85.     p_sys->p_chain = filter_chain_New( p_filter, "video filter2", false, BufferAllocationInit, NULL, p_filter );
  86.     if( !p_sys->p_chain )
  87.     {
  88.         free( p_sys );
  89.         return VLC_EGENERIC;
  90.     }
  91.     filter_chain_Reset( p_sys->p_chain, &p_filter->fmt_in, &p_filter->fmt_out );
  92.     if( b_chroma && b_resize )
  93.         i_ret = BuildChromaResize( p_filter );
  94.     else if( b_chroma )
  95.         i_ret = BuildChromaChain( p_filter );
  96.     else
  97.         i_ret = VLC_EGENERIC;
  98.     if( i_ret )
  99.     {
  100.         /* Hum ... looks like this really isn't going to work. Too bad. */
  101.         filter_chain_Delete( p_sys->p_chain );
  102.         free( p_sys );
  103.         return VLC_EGENERIC;
  104.     }
  105.     /* */
  106.     p_filter->pf_video_filter = Chain;
  107.     return VLC_SUCCESS;
  108. }
  109. static void Destroy( vlc_object_t *p_this )
  110. {
  111.     filter_t *p_filter = (filter_t *)p_this;
  112.     filter_chain_Delete( p_filter->p_sys->p_chain );
  113.     free( p_filter->p_sys );
  114. }
  115. /*****************************************************************************
  116.  * Chain
  117.  *****************************************************************************/
  118. static picture_t *Chain( filter_t *p_filter, picture_t *p_pic )
  119. {
  120.     return filter_chain_VideoFilter( p_filter->p_sys->p_chain, p_pic );
  121. }
  122. /*****************************************************************************
  123.  * Builders
  124.  *****************************************************************************/
  125. static int BuildChromaResize( filter_t *p_filter )
  126. {
  127.     filter_sys_t *p_sys = p_filter->p_sys;
  128.     es_format_t fmt_mid;
  129.     int i_ret;
  130.     /* Lets try resizing and then doing the chroma conversion */
  131.     msg_Dbg( p_filter, "Trying to build resize+chroma" );
  132.     EsFormatMergeSize( &fmt_mid, &p_filter->fmt_in, &p_filter->fmt_out );
  133.     i_ret = CreateChain( p_sys->p_chain, &fmt_mid );
  134.     es_format_Clean( &fmt_mid );
  135.     if( i_ret == VLC_SUCCESS )
  136.         return VLC_SUCCESS;
  137.     /* Lets try it the other way arround (chroma and then resize) */
  138.     msg_Dbg( p_filter, "Trying to build chroma+resize" );
  139.     EsFormatMergeSize( &fmt_mid, &p_filter->fmt_out, &p_filter->fmt_in );
  140.     i_ret = CreateChain( p_sys->p_chain, &fmt_mid );
  141.     es_format_Clean( &fmt_mid );
  142.     if( i_ret == VLC_SUCCESS )
  143.         return VLC_SUCCESS;
  144.     return VLC_EGENERIC;
  145. }
  146. static int BuildChromaChain( filter_t *p_filter )
  147. {
  148.     filter_sys_t *p_sys = p_filter->p_sys;
  149.     es_format_t fmt_mid;
  150.     int i_ret;
  151.     int i;
  152.     /* We have to protect ourself against a too high recursion */
  153.     const char *psz_option = MODULE_STRING"-level";
  154.     bool b_first = !var_Type( p_filter, psz_option );
  155.     if( var_Create( p_filter, MODULE_STRING"-level", VLC_VAR_INTEGER | (b_first ? VLC_VAR_DOINHERIT : 0 ) ) )
  156.     {
  157.         msg_Err( p_filter, "Failed to create %s variable", psz_option );
  158.         return VLC_EGENERIC;
  159.     }
  160.     int i_level = var_GetInteger( p_filter, psz_option );
  161.     if( i_level >= CHAIN_LEVEL_MAX )
  162.     {
  163.         msg_Err( p_filter, "Too high level of recursion (%d)", i_level );
  164.         return VLC_EGENERIC;
  165.     }
  166.     var_SetInteger( p_filter, psz_option, i_level + 1 );
  167.     /* Now try chroma format list */
  168.     for( i = 0; pi_allowed_chromas[i]; i++ )
  169.     {
  170.         const vlc_fourcc_t i_chroma = pi_allowed_chromas[i];
  171.         msg_Dbg( p_filter, "Trying to use chroma %4.4s as middle man",
  172.                  (char*)&i_chroma );
  173.         es_format_Copy( &fmt_mid, &p_filter->fmt_in );
  174.         fmt_mid.video.i_chroma = i_chroma;
  175.         i_ret = CreateChain( p_sys->p_chain, &fmt_mid );
  176.         es_format_Clean( &fmt_mid );
  177.         if( i_ret == VLC_SUCCESS )
  178.             return VLC_SUCCESS;
  179.     }
  180.     return VLC_EGENERIC;
  181. }
  182. /*****************************************************************************
  183.  * Buffer management
  184.  *****************************************************************************/
  185. static picture_t *BufferNew( filter_t *p_filter )
  186. {
  187.     filter_t *p_parent = (filter_t*)p_filter->p_owner;
  188.     return p_parent->pf_vout_buffer_new( p_parent );
  189. }
  190. static void BufferDel( filter_t *p_filter, picture_t *p_pic )
  191. {
  192.     filter_t *p_parent = (filter_t*)p_filter->p_owner;
  193.     p_parent->pf_vout_buffer_del( p_parent, p_pic );
  194. }
  195. static int BufferAllocationInit ( filter_t *p_filter, void *p_data )
  196. {
  197.     p_filter->pf_vout_buffer_new = BufferNew;
  198.     p_filter->pf_vout_buffer_del = BufferDel;
  199.     p_filter->p_owner = p_data;
  200.     return VLC_SUCCESS;
  201. }
  202. /*****************************************************************************
  203.  *
  204.  *****************************************************************************/
  205. static int CreateChain( filter_chain_t *p_chain, es_format_t *p_fmt_mid )
  206. {
  207.     filter_t *p_filter1;
  208.     if( !( p_filter1 =
  209.            filter_chain_AppendFilter( p_chain, NULL, NULL, NULL, p_fmt_mid )) )
  210.         return VLC_EGENERIC;
  211.     if( !filter_chain_AppendFilter( p_chain, NULL, NULL, p_fmt_mid, NULL ) )
  212.     {
  213.         filter_chain_DeleteFilter( p_chain, p_filter1 );
  214.         return VLC_EGENERIC;
  215.     }
  216.     return VLC_SUCCESS;
  217. }
  218. static void EsFormatMergeSize( es_format_t *p_dst,
  219.                                const es_format_t *p_base,
  220.                                const es_format_t *p_size )
  221. {
  222.     es_format_Copy( p_dst, p_base );
  223.     p_dst->video.i_width  = p_size->video.i_width;
  224.     p_dst->video.i_height = p_size->video.i_height;
  225.     p_dst->video.i_visible_width  = p_size->video.i_visible_width;
  226.     p_dst->video.i_visible_height = p_size->video.i_visible_height;
  227. }