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

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * mosaic_bridge.c:
  3.  *****************************************************************************
  4.  * Copyright (C) 2004-2007 the VideoLAN team
  5.  * $Id: 4a8e6382e5c7eb0b8e82fa9bf70c967855e08ed0 $
  6.  *
  7.  * Authors: Antoine Cellerier <dionoea@videolan.org>
  8.  *          Christophe Massiot <massiot@via.ecp.fr>
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  23.  *****************************************************************************/
  24. /*****************************************************************************
  25.  * Preamble
  26.  *****************************************************************************/
  27. #ifdef HAVE_CONFIG_H
  28. # include "config.h"
  29. #endif
  30. #include <errno.h>                                                 /* ENOMEM */
  31. #include <vlc_common.h>
  32. #include <vlc_plugin.h>
  33. #include <vlc_sout.h>
  34. #include <vlc_block.h>
  35. #include <vlc_codec.h>
  36. #include <vlc_meta.h>
  37. #include <vlc_image.h>
  38. #include <vlc_filter.h>
  39. #include "../video_filter/mosaic.h"
  40. #include <assert.h>
  41. /*****************************************************************************
  42.  * Local structures
  43.  *****************************************************************************/
  44. struct sout_stream_sys_t
  45. {
  46.     bridged_es_t *p_es;
  47.     vlc_mutex_t *p_lock;
  48.     decoder_t       *p_decoder;
  49.     image_handler_t *p_image; /* filter for resizing */
  50.     int i_height, i_width;
  51.     unsigned int i_sar_num, i_sar_den;
  52.     char *psz_id;
  53.     bool b_inited;
  54.     int i_chroma; /* force image format chroma */
  55.     filter_chain_t *p_vf2;
  56. };
  57. #define PICTURE_RING_SIZE 4
  58. struct decoder_owner_sys_t
  59. {
  60.     picture_t *pp_pics[PICTURE_RING_SIZE];
  61.     /* Current format in use by the output */
  62.     video_format_t video;
  63. };
  64. typedef void (* pf_release_t)( picture_t * );
  65. static void ReleasePicture( picture_t *p_pic )
  66. {
  67.     assert( p_pic );
  68.     if( p_pic->p_sys )
  69.     {
  70.         pf_release_t pf_release = (pf_release_t)p_pic->p_sys;
  71.         p_pic->p_sys = NULL;
  72.         pf_release( p_pic );
  73.     }
  74.     else
  75.     {
  76.         if( --p_pic->i_refcount == 0 )
  77.         {
  78.             free( p_pic->p_q );
  79.             free( p_pic->p_data_orig );
  80.             free( p_pic );
  81.         }
  82.     }
  83. }
  84. /*****************************************************************************
  85.  * Local prototypes
  86.  *****************************************************************************/
  87. static int  Open    ( vlc_object_t * );
  88. static void Close   ( vlc_object_t * );
  89. static sout_stream_id_t *Add ( sout_stream_t *, es_format_t * );
  90. static int               Del ( sout_stream_t *, sout_stream_id_t * );
  91. static int               Send( sout_stream_t *, sout_stream_id_t *, block_t * );
  92. inline static void video_del_buffer_decoder( decoder_t *, picture_t * );
  93. inline static void video_del_buffer_filter( filter_t *, picture_t * );
  94. static void video_del_buffer( picture_t * );
  95. inline static picture_t *video_new_buffer_decoder( decoder_t * );
  96. inline static picture_t *video_new_buffer_filter( filter_t * );
  97. static picture_t *video_new_buffer( vlc_object_t *, decoder_owner_sys_t *,
  98.                                     es_format_t *, void (*)( picture_t * ) );
  99. static void video_link_picture_decoder( decoder_t *, picture_t * );
  100. static void video_unlink_picture_decoder( decoder_t *, picture_t * );
  101. static int HeightCallback( vlc_object_t *, char const *,
  102.                            vlc_value_t, vlc_value_t, void * );
  103. static int WidthCallback( vlc_object_t *, char const *,
  104.                           vlc_value_t, vlc_value_t, void * );
  105. static int alphaCallback( vlc_object_t *, char const *,
  106.                           vlc_value_t, vlc_value_t, void * );
  107. static int xCallback( vlc_object_t *, char const *,
  108.                       vlc_value_t, vlc_value_t, void * );
  109. static int yCallback( vlc_object_t *, char const *,
  110.                       vlc_value_t, vlc_value_t, void * );
  111. /*****************************************************************************
  112.  * Module descriptor
  113.  *****************************************************************************/
  114. #define ID_TEXT N_("ID")
  115. #define ID_LONGTEXT N_( 
  116.     "Specify an identifier string for this subpicture" )
  117. #define WIDTH_TEXT N_("Video width")
  118. #define WIDTH_LONGTEXT N_( 
  119.     "Output video width." )
  120. #define HEIGHT_TEXT N_("Video height")
  121. #define HEIGHT_LONGTEXT N_( 
  122.     "Output video height." )
  123. #define RATIO_TEXT N_("Sample aspect ratio")
  124. #define RATIO_LONGTEXT N_( 
  125.     "Sample aspect ratio of the destination (1:1, 3:4, 2:3)." )
  126. #define VFILTER_TEXT N_("Video filter")
  127. #define VFILTER_LONGTEXT N_( 
  128.     "Video filters will be applied to the video stream." )
  129. #define CHROMA_TEXT N_("Image chroma")
  130. #define CHROMA_LONGTEXT N_( 
  131.     "Force the use of a specific chroma. Use YUVA if you're planning " 
  132.     "to use the Alphamask or Bluescreen video filter." )
  133. #define ALPHA_TEXT N_("Transparency")
  134. #define ALPHA_LONGTEXT N_( 
  135.     "Transparency of the mosaic picture." )
  136. #define X_TEXT N_("X offset")
  137. #define X_LONGTEXT N_( 
  138.     "X coordinate of the upper left corner in the mosaic if non negative." )
  139. #define Y_TEXT N_("Y offset")
  140. #define Y_LONGTEXT N_( 
  141.     "Y coordinate of the upper left corner in the mosaic if non negative." )
  142. #define CFG_PREFIX "sout-mosaic-bridge-"
  143. vlc_module_begin ()
  144.     set_shortname( N_( "Mosaic bridge" ) )
  145.     set_description(N_("Mosaic bridge stream output") )
  146.     set_capability( "sout stream", 0 )
  147.     add_shortcut( "mosaic-bridge" )
  148.     add_string( CFG_PREFIX "id", "Id", NULL, ID_TEXT, ID_LONGTEXT,
  149.                 false )
  150.     add_integer( CFG_PREFIX "width", 0, NULL, WIDTH_TEXT,
  151.                  WIDTH_LONGTEXT, true )
  152.     add_integer( CFG_PREFIX "height", 0, NULL, HEIGHT_TEXT,
  153.                  HEIGHT_LONGTEXT, true )
  154.     add_string( CFG_PREFIX "sar", "1:1", NULL, RATIO_TEXT,
  155.                 RATIO_LONGTEXT, false )
  156.     add_string( CFG_PREFIX "chroma", 0, NULL, CHROMA_TEXT, CHROMA_LONGTEXT,
  157.                 false )
  158.     add_module_list( CFG_PREFIX "vfilter", "video filter2",
  159.                      NULL, NULL, VFILTER_TEXT, VFILTER_LONGTEXT, false )
  160.     add_integer_with_range( CFG_PREFIX "alpha", 255, 0, 255, NULL,
  161.                             ALPHA_TEXT, ALPHA_LONGTEXT, false )
  162.     add_integer( CFG_PREFIX "x", -1, NULL, X_TEXT, X_LONGTEXT, false )
  163.     add_integer( CFG_PREFIX "y", -1, NULL, Y_TEXT, Y_LONGTEXT, false )
  164.     set_callbacks( Open, Close )
  165. vlc_module_end ()
  166. static const char *const ppsz_sout_options[] = {
  167.     "id", "width", "height", "sar", "vfilter", "chroma", "alpha", "x", "y", NULL
  168. };
  169. /*****************************************************************************
  170.  * Open
  171.  *****************************************************************************/
  172. static int Open( vlc_object_t *p_this )
  173. {
  174.     sout_stream_t        *p_stream = (sout_stream_t *)p_this;
  175.     sout_stream_sys_t    *p_sys;
  176.     vlc_object_t         *p_libvlc = VLC_OBJECT( p_this->p_libvlc );
  177.     vlc_value_t           val;
  178.     config_ChainParse( p_stream, CFG_PREFIX, ppsz_sout_options,
  179.                        p_stream->p_cfg );
  180.     p_sys = malloc( sizeof( sout_stream_sys_t ) );
  181.     if( !p_sys )
  182.         return VLC_ENOMEM;
  183.     p_stream->p_sys = p_sys;
  184.     p_sys->b_inited = false;
  185.     var_Create( p_libvlc, "mosaic-lock", VLC_VAR_MUTEX );
  186.     var_Get( p_libvlc, "mosaic-lock", &val );
  187.     p_sys->p_lock = val.p_address;
  188.     p_sys->psz_id = var_CreateGetString( p_stream, CFG_PREFIX "id" );
  189.     p_sys->i_height =
  190.         var_CreateGetIntegerCommand( p_stream, CFG_PREFIX "height" );
  191.     var_AddCallback( p_stream, CFG_PREFIX "height", HeightCallback, p_stream );
  192.     p_sys->i_width =
  193.         var_CreateGetIntegerCommand( p_stream, CFG_PREFIX "width" );
  194.     var_AddCallback( p_stream, CFG_PREFIX "width", WidthCallback, p_stream );
  195.     var_Get( p_stream, CFG_PREFIX "sar", &val );
  196.     if( val.psz_string )
  197.     {
  198.         char *psz_parser = strchr( val.psz_string, ':' );
  199.         if( psz_parser )
  200.         {
  201.             *psz_parser++ = '';
  202.             p_sys->i_sar_num = atoi( val.psz_string );
  203.             p_sys->i_sar_den = atoi( psz_parser );
  204.             vlc_ureduce( &p_sys->i_sar_num, &p_sys->i_sar_den,
  205.                          p_sys->i_sar_num, p_sys->i_sar_den, 0 );
  206.         }
  207.         else
  208.         {
  209.             msg_Warn( p_stream, "bad aspect ratio %s", val.psz_string );
  210.             p_sys->i_sar_num = p_sys->i_sar_den = 1;
  211.         }
  212.         free( val.psz_string );
  213.     }
  214.     else
  215.     {
  216.         p_sys->i_sar_num = p_sys->i_sar_den = 1;
  217.     }
  218.     p_sys->i_chroma = 0;
  219.     val.psz_string = var_GetNonEmptyString( p_stream, CFG_PREFIX "chroma" );
  220.     if( val.psz_string && strlen( val.psz_string ) >= 4 )
  221.     {
  222.         memcpy( &p_sys->i_chroma, val.psz_string, 4 );
  223.         msg_Dbg( p_stream, "Forcing image chroma to 0x%.8x (%4.4s)", p_sys->i_chroma, (char*)&p_sys->i_chroma );
  224.     }
  225.     free( val.psz_string );
  226. #define INT_COMMAND( a ) do { 
  227.     var_Create( p_stream, CFG_PREFIX #a, 
  228.                 VLC_VAR_INTEGER | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND ); 
  229.     var_AddCallback( p_stream, CFG_PREFIX #a, a ## Callback, 
  230.                      p_stream ); } while(0)
  231.     INT_COMMAND( alpha );
  232.     INT_COMMAND( x );
  233.     INT_COMMAND( y );
  234. #undef INT_COMMAND
  235.     p_stream->pf_add    = Add;
  236.     p_stream->pf_del    = Del;
  237.     p_stream->pf_send   = Send;
  238.     p_stream->p_sout->i_out_pace_nocontrol++;
  239.     return VLC_SUCCESS;
  240. }
  241. /*****************************************************************************
  242.  * Close
  243.  *****************************************************************************/
  244. static void Close( vlc_object_t * p_this )
  245. {
  246.     sout_stream_t     *p_stream = (sout_stream_t*)p_this;
  247.     sout_stream_sys_t *p_sys = p_stream->p_sys;
  248.     p_stream->p_sout->i_out_pace_nocontrol--;
  249.     free( p_sys->psz_id );
  250.     free( p_sys );
  251. }
  252. static int video_filter_buffer_allocation_init( filter_t *p_filter, void *p_data )
  253. {
  254.     p_filter->pf_vout_buffer_new = video_new_buffer_filter;
  255.     p_filter->pf_vout_buffer_del = video_del_buffer_filter;
  256.     p_filter->p_owner = p_data;
  257.     return VLC_SUCCESS;
  258. }
  259. static sout_stream_id_t * Add( sout_stream_t *p_stream, es_format_t *p_fmt )
  260. {
  261.     sout_stream_sys_t *p_sys = p_stream->p_sys;
  262.     bridge_t *p_bridge;
  263.     bridged_es_t *p_es;
  264.     char *psz_chain;
  265.     int i;
  266.     if( p_sys->b_inited || p_fmt->i_cat != VIDEO_ES )
  267.         return NULL;
  268.     /* Create decoder object */
  269.     p_sys->p_decoder = vlc_object_create( p_stream, VLC_OBJECT_DECODER );
  270.     if( !p_sys->p_decoder )
  271.         return NULL;
  272.     vlc_object_attach( p_sys->p_decoder, p_stream );
  273.     p_sys->p_decoder->p_module = NULL;
  274.     p_sys->p_decoder->fmt_in = *p_fmt;
  275.     p_sys->p_decoder->b_pace_control = false;
  276.     p_sys->p_decoder->fmt_out = p_sys->p_decoder->fmt_in;
  277.     p_sys->p_decoder->fmt_out.i_extra = 0;
  278.     p_sys->p_decoder->fmt_out.p_extra = 0;
  279.     p_sys->p_decoder->pf_decode_video = 0;
  280.     p_sys->p_decoder->pf_vout_buffer_new = video_new_buffer_decoder;
  281.     p_sys->p_decoder->pf_vout_buffer_del = video_del_buffer_decoder;
  282.     p_sys->p_decoder->pf_picture_link    = video_link_picture_decoder;
  283.     p_sys->p_decoder->pf_picture_unlink  = video_unlink_picture_decoder;
  284.     p_sys->p_decoder->p_owner = malloc( sizeof(decoder_owner_sys_t) );
  285.     if( !p_sys->p_decoder->p_owner )
  286.     {
  287.         vlc_object_detach( p_sys->p_decoder );
  288.         vlc_object_release( p_sys->p_decoder );
  289.         return NULL;
  290.     }
  291.     for( i = 0; i < PICTURE_RING_SIZE; i++ )
  292.         p_sys->p_decoder->p_owner->pp_pics[i] = NULL;
  293.     p_sys->p_decoder->p_owner->video = p_fmt->video;
  294.     //p_sys->p_decoder->p_cfg = p_sys->p_video_cfg;
  295.     p_sys->p_decoder->p_module =
  296.         module_need( p_sys->p_decoder, "decoder", "$codec", false );
  297.     if( !p_sys->p_decoder->p_module || !p_sys->p_decoder->pf_decode_video )
  298.     {
  299.         if( p_sys->p_decoder->p_module )
  300.         {
  301.             msg_Err( p_stream, "instanciated a non video decoder" );
  302.             module_unneed( p_sys->p_decoder, p_sys->p_decoder->p_module );
  303.         }
  304.         else
  305.         {
  306.             msg_Err( p_stream, "cannot find decoder" );
  307.         }
  308.         free( p_sys->p_decoder->p_owner );
  309.         vlc_object_detach( p_sys->p_decoder );
  310.         vlc_object_release( p_sys->p_decoder );
  311.         return NULL;
  312.     }
  313.     p_sys->b_inited = true;
  314.     vlc_mutex_lock( p_sys->p_lock );
  315.     p_bridge = GetBridge( p_stream );
  316.     if ( p_bridge == NULL )
  317.     {
  318.         vlc_object_t *p_libvlc = VLC_OBJECT( p_stream->p_libvlc );
  319.         vlc_value_t val;
  320.         p_bridge = malloc( sizeof( bridge_t ) );
  321.         var_Create( p_libvlc, "mosaic-struct", VLC_VAR_ADDRESS );
  322.         val.p_address = p_bridge;
  323.         var_Set( p_libvlc, "mosaic-struct", val );
  324.         p_bridge->i_es_num = 0;
  325.         p_bridge->pp_es = NULL;
  326.     }
  327.     for ( i = 0; i < p_bridge->i_es_num; i++ )
  328.     {
  329.         if ( p_bridge->pp_es[i]->b_empty )
  330.             break;
  331.     }
  332.     if ( i == p_bridge->i_es_num )
  333.     {
  334.         p_bridge->pp_es = realloc( p_bridge->pp_es,
  335.                                    (p_bridge->i_es_num + 1)
  336.                                      * sizeof(bridged_es_t *) );
  337.         p_bridge->i_es_num++;
  338.         p_bridge->pp_es[i] = malloc( sizeof(bridged_es_t) );
  339.     }
  340.     p_sys->p_es = p_es = p_bridge->pp_es[i];
  341.     p_es->i_alpha = var_GetInteger( p_stream, CFG_PREFIX "alpha" );
  342.     p_es->i_x = var_GetInteger( p_stream, CFG_PREFIX "x" );
  343.     p_es->i_y = var_GetInteger( p_stream, CFG_PREFIX "y" );
  344.     //p_es->fmt = *p_fmt;
  345.     p_es->psz_id = p_sys->psz_id;
  346.     p_es->p_picture = NULL;
  347.     p_es->pp_last = &p_es->p_picture;
  348.     p_es->b_empty = false;
  349.     vlc_mutex_unlock( p_sys->p_lock );
  350.     if ( p_sys->i_height || p_sys->i_width )
  351.     {
  352.         p_sys->p_image = image_HandlerCreate( p_stream );
  353.     }
  354.     else
  355.     {
  356.         p_sys->p_image = NULL;
  357.     }
  358.     msg_Dbg( p_stream, "mosaic bridge id=%s pos=%d", p_es->psz_id, i );
  359.     /* Create user specified video filters */
  360.     psz_chain = var_GetNonEmptyString( p_stream, CFG_PREFIX "vfilter" );
  361.     msg_Dbg( p_stream, "psz_chain: %s", psz_chain );
  362.     if( psz_chain )
  363.     {
  364.         p_sys->p_vf2 = filter_chain_New( p_stream, "video filter2", false,
  365.                                          video_filter_buffer_allocation_init,
  366.                                          NULL, p_sys->p_decoder->p_owner );
  367.         es_format_t fmt;
  368.         es_format_Copy( &fmt, &p_sys->p_decoder->fmt_out );
  369.         if( p_sys->i_chroma )
  370.             fmt.video.i_chroma = p_sys->i_chroma;
  371.         filter_chain_Reset( p_sys->p_vf2, &fmt, &fmt );
  372.         filter_chain_AppendFromString( p_sys->p_vf2, psz_chain );
  373.         free( psz_chain );
  374.     }
  375.     else
  376.     {
  377.         p_sys->p_vf2 = NULL;
  378.     }
  379.     return (sout_stream_id_t *)p_sys;
  380. }
  381. static int Del( sout_stream_t *p_stream, sout_stream_id_t *id )
  382. {
  383.     VLC_UNUSED(id);
  384.     sout_stream_sys_t *p_sys = p_stream->p_sys;
  385.     bridge_t *p_bridge;
  386.     bridged_es_t *p_es;
  387.     bool b_last_es = true;
  388.     int i;
  389.     if( !p_sys->b_inited )
  390.         return VLC_SUCCESS;
  391.     if( p_sys->p_decoder != NULL )
  392.     {
  393.         decoder_owner_sys_t *p_owner = p_sys->p_decoder->p_owner;
  394.         if( p_sys->p_decoder->p_module )
  395.             module_unneed( p_sys->p_decoder, p_sys->p_decoder->p_module );
  396.         if( p_sys->p_decoder->p_description )
  397.             vlc_meta_Delete( p_sys->p_decoder->p_description );
  398.         vlc_object_detach( p_sys->p_decoder );
  399.         vlc_object_release( p_sys->p_decoder );
  400.         picture_t **pp_ring = p_owner->pp_pics;
  401.         for( i = 0; i < PICTURE_RING_SIZE; i++ )
  402.         {
  403.             if ( pp_ring[i] != NULL )
  404.             {
  405.                 free( pp_ring[i]->p_data_orig );
  406.                 free( pp_ring[i]->p_sys );
  407.                 free( pp_ring[i] );
  408.             }
  409.         }
  410.         free( p_owner );
  411.     }
  412.     /* Destroy user specified video filters */
  413.     if( p_sys->p_vf2 )
  414.         filter_chain_Delete( p_sys->p_vf2 );
  415.     vlc_mutex_lock( p_sys->p_lock );
  416.     p_bridge = GetBridge( p_stream );
  417.     p_es = p_sys->p_es;
  418.     p_es->b_empty = true;
  419.     while ( p_es->p_picture )
  420.     {
  421.         picture_t *p_next = p_es->p_picture->p_next;
  422.         p_es->p_picture->pf_release( p_es->p_picture );
  423.         p_es->p_picture = p_next;
  424.     }
  425.     for ( i = 0; i < p_bridge->i_es_num; i++ )
  426.     {
  427.         if ( !p_bridge->pp_es[i]->b_empty )
  428.         {
  429.             b_last_es = false;
  430.             break;
  431.         }
  432.     }
  433.     if ( b_last_es )
  434.     {
  435.         vlc_object_t *p_libvlc = VLC_OBJECT( p_stream->p_libvlc );
  436.         for ( i = 0; i < p_bridge->i_es_num; i++ )
  437.             free( p_bridge->pp_es[i] );
  438.         free( p_bridge->pp_es );
  439.         free( p_bridge );
  440.         var_Destroy( p_libvlc, "mosaic-struct" );
  441.     }
  442.     vlc_mutex_unlock( p_sys->p_lock );
  443.     if ( p_sys->p_image )
  444.     {
  445.         image_HandlerDelete( p_sys->p_image );
  446.     }
  447.     p_sys->b_inited = false;
  448.     return VLC_SUCCESS;
  449. }
  450. /*****************************************************************************
  451.  * PushPicture : push a picture in the mosaic-struct structure
  452.  *****************************************************************************/
  453. static void PushPicture( sout_stream_t *p_stream, picture_t *p_picture )
  454. {
  455.     sout_stream_sys_t *p_sys = p_stream->p_sys;
  456.     bridged_es_t *p_es = p_sys->p_es;
  457.     vlc_mutex_lock( p_sys->p_lock );
  458.     *p_es->pp_last = p_picture;
  459.     p_picture->p_next = NULL;
  460.     p_es->pp_last = &p_picture->p_next;
  461.     vlc_mutex_unlock( p_sys->p_lock );
  462. }
  463. static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
  464.                  block_t *p_buffer )
  465. {
  466.     sout_stream_sys_t *p_sys = p_stream->p_sys;
  467.     picture_t *p_pic;
  468.     if ( (sout_stream_sys_t *)id != p_sys )
  469.     {
  470.         block_ChainRelease( p_buffer );
  471.         return VLC_SUCCESS;
  472.     }
  473.     while ( (p_pic = p_sys->p_decoder->pf_decode_video( p_sys->p_decoder,
  474.                                                         &p_buffer )) )
  475.     {
  476.         picture_t *p_new_pic;
  477.         if( p_sys->i_height || p_sys->i_width )
  478.         {
  479.             video_format_t fmt_out, fmt_in;
  480.             memset( &fmt_in, 0, sizeof(video_format_t) );
  481.             memset( &fmt_out, 0, sizeof(video_format_t) );
  482.             fmt_in = p_sys->p_decoder->fmt_out.video;
  483.             if( p_sys->i_chroma )
  484.                 fmt_out.i_chroma = p_sys->i_chroma;
  485.             else
  486.                 fmt_out.i_chroma = VLC_FOURCC('I','4','2','0');
  487.             if ( !p_sys->i_height )
  488.             {
  489.                 fmt_out.i_width = p_sys->i_width;
  490.                 fmt_out.i_height = (p_sys->i_width * VOUT_ASPECT_FACTOR
  491.                     * p_sys->i_sar_num / p_sys->i_sar_den / fmt_in.i_aspect)
  492.                       & ~0x1;
  493.             }
  494.             else if ( !p_sys->i_width )
  495.             {
  496.                 fmt_out.i_height = p_sys->i_height;
  497.                 fmt_out.i_width = (p_sys->i_height * fmt_in.i_aspect
  498.                     * p_sys->i_sar_den / p_sys->i_sar_num / VOUT_ASPECT_FACTOR)
  499.                       & ~0x1;
  500.             }
  501.             else
  502.             {
  503.                 fmt_out.i_width = p_sys->i_width;
  504.                 fmt_out.i_height = p_sys->i_height;
  505.             }
  506.             fmt_out.i_visible_width = fmt_out.i_width;
  507.             fmt_out.i_visible_height = fmt_out.i_height;
  508.             p_new_pic = image_Convert( p_sys->p_image,
  509.                                        p_pic, &fmt_in, &fmt_out );
  510.             if ( p_new_pic == NULL )
  511.             {
  512.                 msg_Err( p_stream, "image conversion failed" );
  513.                 picture_Release( p_pic );
  514.                 continue;
  515.             }
  516.         }
  517.         else
  518.         {
  519.             /* TODO: chroma conversion if needed */
  520.             p_new_pic = (picture_t*)malloc( sizeof(picture_t) );
  521.             if( p_new_pic == NULL )
  522.             {
  523.                 msg_Err( p_stream, "image conversion failed" );
  524.                 continue;
  525.             }
  526.             if( vout_AllocatePicture(
  527.                                   p_stream, p_new_pic, p_pic->format.i_chroma,
  528.                                   p_pic->format.i_width, p_pic->format.i_height,
  529.                                   p_sys->p_decoder->fmt_out.video.i_aspect )
  530.                 != VLC_SUCCESS )
  531.             {
  532.                 picture_Release( p_pic );
  533.                 free( p_new_pic );
  534.                 msg_Err( p_stream, "image allocation failed" );
  535.                 continue;
  536.             }
  537.             picture_Copy( p_new_pic, p_pic );
  538.         }
  539.         p_new_pic->i_refcount = 1;
  540.         p_new_pic->i_status = DESTROYED_PICTURE;
  541.         p_new_pic->i_type   = DIRECT_PICTURE;
  542.         p_new_pic->p_sys = (picture_sys_t *)p_new_pic->pf_release;
  543.         p_new_pic->pf_release = ReleasePicture;
  544.         p_new_pic->date = p_pic->date;
  545.         picture_Release( p_pic );
  546.         if( p_sys->p_vf2 )
  547.             p_new_pic = filter_chain_VideoFilter( p_sys->p_vf2, p_new_pic );
  548.         PushPicture( p_stream, p_new_pic );
  549.     }
  550.     return VLC_SUCCESS;
  551. }
  552. struct picture_sys_t
  553. {
  554.     vlc_object_t *p_owner;
  555.     bool b_dead;
  556. };
  557. static void video_release_buffer_decoder( picture_t *p_pic )
  558. {
  559.     assert( p_pic && p_pic->p_sys );
  560.     if( --p_pic->i_refcount > 0 )
  561.         return;
  562.     video_del_buffer_decoder( (decoder_t *)p_pic->p_sys->p_owner, p_pic );
  563. }
  564. static void video_release_buffer_filter( picture_t *p_pic )
  565. {
  566.     assert( p_pic );
  567.     if( --p_pic->i_refcount > 0 )
  568.         return;
  569.     assert( p_pic->p_sys );
  570.     video_del_buffer_filter( (filter_t *)p_pic->p_sys->p_owner, p_pic );
  571. }
  572. inline static picture_t *video_new_buffer_decoder( decoder_t *p_dec )
  573. {
  574.     return video_new_buffer( VLC_OBJECT( p_dec ),
  575.                              (decoder_owner_sys_t *)p_dec->p_owner,
  576.                              &p_dec->fmt_out,
  577.                              video_release_buffer_decoder );
  578. }
  579. inline static picture_t *video_new_buffer_filter( filter_t *p_filter )
  580. {
  581.     return video_new_buffer( VLC_OBJECT( p_filter ),
  582.                              (decoder_owner_sys_t *)p_filter->p_owner,
  583.                              &p_filter->fmt_out,
  584.                              video_release_buffer_filter );
  585. }
  586. static picture_t *video_new_buffer( vlc_object_t *p_this,
  587.                                     decoder_owner_sys_t *p_sys,
  588.                                     es_format_t *fmt_out,
  589.                                     void ( *pf_release )( picture_t * ) )
  590. {
  591.     picture_t **pp_ring = p_sys->pp_pics;
  592.     picture_t *p_pic;
  593.     int i;
  594.     if( fmt_out->video.i_width != p_sys->video.i_width ||
  595.         fmt_out->video.i_height != p_sys->video.i_height ||
  596.         fmt_out->video.i_chroma != p_sys->video.i_chroma ||
  597.         fmt_out->video.i_aspect != p_sys->video.i_aspect )
  598.     {
  599.         if( !fmt_out->video.i_sar_num ||
  600.             !fmt_out->video.i_sar_den )
  601.         {
  602.             fmt_out->video.i_sar_num =
  603.                 fmt_out->video.i_aspect * fmt_out->video.i_height;
  604.             fmt_out->video.i_sar_den =
  605.                 VOUT_ASPECT_FACTOR * fmt_out->video.i_width;
  606.         }
  607.         vlc_ureduce( &fmt_out->video.i_sar_num,
  608.                      &fmt_out->video.i_sar_den,
  609.                      fmt_out->video.i_sar_num,
  610.                      fmt_out->video.i_sar_den, 0 );
  611.         if( !fmt_out->video.i_visible_width ||
  612.             !fmt_out->video.i_visible_height )
  613.         {
  614.             fmt_out->video.i_visible_width = fmt_out->video.i_width;
  615.             fmt_out->video.i_visible_height = fmt_out->video.i_height;
  616.         }
  617.         fmt_out->video.i_chroma = fmt_out->i_codec;
  618.         p_sys->video = fmt_out->video;
  619.         for( i = 0; i < PICTURE_RING_SIZE; i++ )
  620.         {
  621.             if ( pp_ring[i] != NULL )
  622.             {
  623.                 if ( pp_ring[i]->i_status == DESTROYED_PICTURE )
  624.                 {
  625.                     free( pp_ring[i]->p_data_orig );
  626.                     free( pp_ring[i]->p_sys );
  627.                     free( pp_ring[i] );
  628.                 }
  629.                 else
  630.                 {
  631.                     pp_ring[i]->p_sys->b_dead = true;
  632.                 }
  633.                 pp_ring[i] = NULL;
  634.             }
  635.         }
  636.     }
  637.     /* Find an empty space in the picture ring buffer */
  638.     for( i = 0; i < PICTURE_RING_SIZE; i++ )
  639.     {
  640.         if( pp_ring[i] != NULL && pp_ring[i]->i_status == DESTROYED_PICTURE )
  641.         {
  642.             pp_ring[i]->i_status = RESERVED_PICTURE;
  643.             pp_ring[i]->i_refcount = 1;
  644.             return pp_ring[i];
  645.         }
  646.     }
  647.     for( i = 0; i < PICTURE_RING_SIZE; i++ )
  648.     {
  649.         if( pp_ring[i] == NULL ) break;
  650.     }
  651.     if( i == PICTURE_RING_SIZE )
  652.     {
  653.         msg_Err( p_this, "decoder/filter is leaking pictures, "
  654.                  "resetting its ring buffer" );
  655.         for( i = 0; i < PICTURE_RING_SIZE; i++ )
  656.         {
  657.             pp_ring[i]->p_sys->b_dead = true;
  658.             pp_ring[i]->pf_release( pp_ring[i] );
  659.             pp_ring[i] = NULL;
  660.         }
  661.         i = 0;
  662.     }
  663.     p_pic = malloc( sizeof(picture_t) );
  664.     if( !p_pic ) return NULL;
  665.     fmt_out->video.i_chroma = fmt_out->i_codec;
  666.     if( vout_AllocatePicture( p_this, p_pic,
  667.                           fmt_out->video.i_chroma,
  668.                           fmt_out->video.i_width,
  669.                           fmt_out->video.i_height,
  670.                           fmt_out->video.i_aspect ) != VLC_SUCCESS )
  671.     {
  672.         free( p_pic );
  673.         return NULL;
  674.     }
  675.     if( !p_pic->i_planes )
  676.     {
  677.         free( p_pic );
  678.         return NULL;
  679.     }
  680.     p_pic->pf_release = pf_release;
  681.     p_pic->i_refcount = 1;
  682.     p_pic->p_sys = malloc( sizeof(picture_sys_t) );
  683.     p_pic->p_sys->p_owner = p_this;
  684.     p_pic->p_sys->b_dead = false;
  685.     p_pic->i_status = RESERVED_PICTURE;
  686.     pp_ring[i] = p_pic;
  687.     return p_pic;
  688. }
  689. inline static void video_del_buffer_decoder( decoder_t *p_this,
  690.                                              picture_t *p_pic )
  691. {
  692.     VLC_UNUSED(p_this);
  693.     video_del_buffer( p_pic );
  694. }
  695. inline static void video_del_buffer_filter( filter_t *p_this,
  696.                                             picture_t *p_pic )
  697. {
  698.     VLC_UNUSED(p_this);
  699.     video_del_buffer( p_pic );
  700. }
  701. static void video_del_buffer( picture_t *p_pic )
  702. {
  703.     p_pic->i_refcount = 0;
  704.     p_pic->i_status = DESTROYED_PICTURE;
  705.     if ( p_pic->p_sys->b_dead )
  706.     {
  707.         free( p_pic->p_data_orig );
  708.         free( p_pic->p_sys );
  709.         free( p_pic );
  710.     }
  711. }
  712. static void video_link_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
  713. {
  714.     VLC_UNUSED(p_dec);
  715.     p_pic->i_refcount++;
  716. }
  717. static void video_unlink_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
  718. {
  719.     VLC_UNUSED(p_dec);
  720.     video_release_buffer_decoder( p_pic );
  721. }
  722. /**********************************************************************
  723.  * Callback to update (some) params on the fly
  724.  **********************************************************************/
  725. static int HeightCallback( vlc_object_t *p_this, char const *psz_var,
  726.                            vlc_value_t oldval, vlc_value_t newval,
  727.                            void *p_data )
  728. {
  729.     VLC_UNUSED(p_this); VLC_UNUSED(oldval); VLC_UNUSED(psz_var);
  730.     sout_stream_t *p_stream = (sout_stream_t *)p_data;
  731.     sout_stream_sys_t *p_sys = p_stream->p_sys;
  732.     /* We create the handler before updating the value in p_sys
  733.      * so we don't have to worry about locking */
  734.     if( !p_sys->p_image && newval.i_int )
  735.         p_sys->p_image = image_HandlerCreate( p_stream );
  736.     p_sys->i_height = newval.i_int;
  737.     return VLC_SUCCESS;
  738. }
  739. static int WidthCallback( vlc_object_t *p_this, char const *psz_var,
  740.                            vlc_value_t oldval, vlc_value_t newval,
  741.                            void *p_data )
  742. {
  743.     VLC_UNUSED(p_this); VLC_UNUSED(oldval); VLC_UNUSED(psz_var);
  744.     sout_stream_t *p_stream = (sout_stream_t *)p_data;
  745.     sout_stream_sys_t *p_sys = p_stream->p_sys;
  746.     /* We create the handler before updating the value in p_sys
  747.      * so we don't have to worry about locking */
  748.     if( !p_sys->p_image && newval.i_int )
  749.         p_sys->p_image = image_HandlerCreate( p_stream );
  750.     p_sys->i_width = newval.i_int;
  751.     return VLC_SUCCESS;
  752. }
  753. static int alphaCallback( vlc_object_t *p_this, char const *psz_var,
  754.                           vlc_value_t oldval, vlc_value_t newval,
  755.                           void *p_data )
  756. {
  757.     VLC_UNUSED(p_this); VLC_UNUSED(oldval); VLC_UNUSED(psz_var);
  758.     sout_stream_t *p_stream = (sout_stream_t *)p_data;
  759.     sout_stream_sys_t *p_sys = p_stream->p_sys;
  760.     if( p_sys->p_es )
  761.         p_sys->p_es->i_alpha = newval.i_int;
  762.     return VLC_SUCCESS;
  763. }
  764. static int xCallback( vlc_object_t *p_this, char const *psz_var,
  765.                       vlc_value_t oldval, vlc_value_t newval,
  766.                       void *p_data )
  767. {
  768.     VLC_UNUSED(p_this); VLC_UNUSED(oldval); VLC_UNUSED(psz_var);
  769.     sout_stream_t *p_stream = (sout_stream_t *)p_data;
  770.     sout_stream_sys_t *p_sys = p_stream->p_sys;
  771.     if( p_sys->p_es )
  772.         p_sys->p_es->i_x = newval.i_int;
  773.     return VLC_SUCCESS;
  774. }
  775. static int yCallback( vlc_object_t *p_this, char const *psz_var,
  776.                       vlc_value_t oldval, vlc_value_t newval,
  777.                       void *p_data )
  778. {
  779.     VLC_UNUSED(p_this); VLC_UNUSED(oldval); VLC_UNUSED(psz_var);
  780.     sout_stream_t *p_stream = (sout_stream_t *)p_data;
  781.     sout_stream_sys_t *p_sys = p_stream->p_sys;
  782.     if( p_sys->p_es )
  783.         p_sys->p_es->i_y = newval.i_int;
  784.     return VLC_SUCCESS;
  785. }