Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

transcode.c

00001 /*****************************************************************************
00002  * transcode.c: transcoding stream output module
00003  *****************************************************************************
00004  * Copyright (C) 2003-2004 the VideoLAN team
00005  * $Id: transcode.c 13101 2005-11-02 18:16:58Z gbazin $
00006  *
00007  * Authors: Laurent Aimar <[email protected]>
00008  *          Gildas Bazin <[email protected]>
00009  *          Jean-Paul Saman <jpsaman #_at_# m2x dot nl> 
00010  *
00011  * This program is free software; you can redistribute it and/or modify
00012  * it under the terms of the GNU General Public License as published by
00013  * the Free Software Foundation; either version 2 of the License, or
00014  * (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software
00023  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00024  *****************************************************************************/
00025 
00026 /*****************************************************************************
00027  * Preamble
00028  *****************************************************************************/
00029 #include <stdlib.h>
00030 #include <string.h>
00031 #include <math.h>
00032 
00033 #include <vlc/vlc.h>
00034 #include <vlc/input.h>
00035 #include <vlc/sout.h>
00036 #include <vlc/vout.h>
00037 #include <vlc/decoder.h>
00038 #include "vlc_filter.h"
00039 #include "vlc_osd.h"
00040 
00041 #define MASTER_SYNC_MAX_DRIFT 100000
00042 
00043 /*****************************************************************************
00044  * Module descriptor
00045  *****************************************************************************/
00046 #define VENC_TEXT N_("Video encoder")
00047 #define VENC_LONGTEXT N_( \
00048     "Allows you to specify the video encoder to use and its associated " \
00049     "options." )
00050 #define VCODEC_TEXT N_("Destination video codec")
00051 #define VCODEC_LONGTEXT N_( \
00052     "Allows you to specify the destination video codec used for the " \
00053     "streaming output." )
00054 #define VB_TEXT N_("Video bitrate")
00055 #define VB_LONGTEXT N_( \
00056     "Allows you to specify the video bitrate used for the streaming " \
00057     "output." )
00058 #define SCALE_TEXT N_("Video scaling")
00059 #define SCALE_LONGTEXT N_( \
00060     "Allows you to scale the video before encoding." )
00061 #define FPS_TEXT N_("Video frame-rate")
00062 #define FPS_LONGTEXT N_( \
00063     "Allows you to specify an output frame rate for the video." )
00064 #define DEINTERLACE_TEXT N_("Deinterlace video")
00065 #define DEINTERLACE_LONGTEXT N_( \
00066     "Allows you to deinterlace the video before encoding." )
00067 #define DEINTERLACE_MODULE_TEXT N_("Deinterlace module")
00068 #define DEINTERLACE_MODULE_LONGTEXT N_( \
00069     "Specifies the deinterlace module to use." )
00070 #define WIDTH_TEXT N_("Video width")
00071 #define WIDTH_LONGTEXT N_( \
00072     "Allows you to specify the output video width." )
00073 #define HEIGHT_TEXT N_("Video height")
00074 #define HEIGHT_LONGTEXT N_( \
00075     "Allows you to specify the output video height." )
00076 #define MAXWIDTH_TEXT N_("Maximum video width")
00077 #define MAXWIDTH_LONGTEXT N_( \
00078     "Allows you to specify a maximum output video width." )
00079 #define MAXHEIGHT_TEXT N_("Maximum video height")
00080 #define MAXHEIGHT_LONGTEXT N_( \
00081     "Allows you to specify a maximum output video height." )
00082 #define VFILTER_TEXT N_("Video filter")
00083 #define VFILTER_LONGTEXT N_( \
00084     "Allows you to specify video filters used after the video " \
00085     "transcoding and subpictures overlaying." )
00086 
00087 #define CROPTOP_TEXT N_("Video crop top")
00088 #define CROPTOP_LONGTEXT N_( \
00089     "Allows you to specify the top coordinate for the video cropping." )
00090 #define CROPLEFT_TEXT N_("Video crop left")
00091 #define CROPLEFT_LONGTEXT N_( \
00092     "Allows you to specify the left coordinate for the video cropping." )
00093 #define CROPBOTTOM_TEXT N_("Video crop bottom")
00094 #define CROPBOTTOM_LONGTEXT N_( \
00095     "Allows you to specify the bottom coordinate for the video cropping." )
00096 #define CROPRIGHT_TEXT N_("Video crop right")
00097 #define CROPRIGHT_LONGTEXT N_( \
00098     "Allows you to specify the right coordinate for the video cropping." )
00099 
00100 #define AENC_TEXT N_("Audio encoder")
00101 #define AENC_LONGTEXT N_( \
00102     "Allows you to specify the audio encoder to use and its associated " \
00103     "options." )
00104 #define ACODEC_TEXT N_("Destination audio codec")
00105 #define ACODEC_LONGTEXT N_( \
00106     "Allows you to specify the destination audio codec used for the " \
00107     "streaming output." )
00108 #define AB_TEXT N_("Audio bitrate")
00109 #define AB_LONGTEXT N_( \
00110     "Allows you to specify the audio bitrate used for the streaming " \
00111     "output." )
00112 #define ARATE_TEXT N_("Audio sample rate")
00113 #define ARATE_LONGTEXT N_( \
00114     "Allows you to specify the audio sample rate used for the streaming " \
00115     "output." )
00116 #define ACHANS_TEXT N_("Audio channels")
00117 #define ACHANS_LONGTEXT N_( \
00118     "Allows you to specify the number of audio channels used for the " \
00119     "streaming output." )
00120 
00121 #define SENC_TEXT N_("Subtitles encoder")
00122 #define SENC_LONGTEXT N_( \
00123     "Allows you to specify the subtitles encoder to use and its associated " \
00124     "options." )
00125 #define SCODEC_TEXT N_("Destination subtitles codec")
00126 #define SCODEC_LONGTEXT N_( \
00127     "Allows you to specify the destination subtitles codec used for the " \
00128     "streaming output." )
00129 #define SFILTER_TEXT N_("Subpictures filter")
00130 #define SFILTER_LONGTEXT N_( \
00131     "Allows you to specify subpictures filters used during the video " \
00132     "transcoding. The subpictures produced by the filters will be overlayed " \
00133     "directly onto the video." )
00134 
00135 #define OSD_TEXT N_("OSD menu")
00136 #define OSD_LONGTEXT N_(\
00137     "Enable streaming of the On Screen Display. It uses the osdmenu subfilter." )
00138                   
00139 #define THREADS_TEXT N_("Number of threads")
00140 #define THREADS_LONGTEXT N_( \
00141     "Allows you to specify the number of threads used for the transcoding." )
00142 #define HP_TEXT N_("High priority")
00143 #define HP_LONGTEXT N_( \
00144     "Runs the optional encoder thread at the OUTPUT priority instead of " \
00145     "VIDEO." )
00146 
00147 #define ASYNC_TEXT N_("Synchronise on audio track")
00148 #define ASYNC_LONGTEXT N_( \
00149     "This option will drop/duplicate video frames to synchronise the video " \
00150     "track on the audio track." )
00151 
00152 #define HURRYUP_TEXT N_( "Hurry up" )
00153 #define HURRYUP_LONGTEXT N_( "Allows you to specify if the transcoder " \
00154   "should drop frames if your CPU can't keep up with the encoding rate." )
00155 
00156 static char *ppsz_deinterlace_type[] =
00157 {
00158     "deinterlace", "ffmpeg-deinterlace"
00159 };
00160 
00161 static int  Open ( vlc_object_t * );
00162 static void Close( vlc_object_t * );
00163 
00164 #define SOUT_CFG_PREFIX "sout-transcode-"
00165 
00166 vlc_module_begin();
00167     set_shortname( _("Transcode"));
00168     set_description( _("Transcode stream output") );
00169     set_capability( "sout stream", 50 );
00170     add_shortcut( "transcode" );
00171     set_callbacks( Open, Close );
00172     set_category( CAT_SOUT );
00173     set_subcategory( SUBCAT_SOUT_STREAM );
00174     set_section( N_("Video"), NULL );
00175     add_string( SOUT_CFG_PREFIX "venc", NULL, NULL, VENC_TEXT,
00176                 VENC_LONGTEXT, VLC_FALSE );
00177     add_string( SOUT_CFG_PREFIX "vcodec", NULL, NULL, VCODEC_TEXT,
00178                 VCODEC_LONGTEXT, VLC_FALSE );
00179     add_integer( SOUT_CFG_PREFIX "vb", 800 * 1000, NULL, VB_TEXT,
00180                  VB_LONGTEXT, VLC_FALSE );
00181     add_float( SOUT_CFG_PREFIX "scale", 1, NULL, SCALE_TEXT,
00182                SCALE_LONGTEXT, VLC_FALSE );
00183     add_float( SOUT_CFG_PREFIX "fps", 0, NULL, FPS_TEXT,
00184                FPS_LONGTEXT, VLC_FALSE );
00185     add_bool( SOUT_CFG_PREFIX "hurry-up", VLC_TRUE, NULL, HURRYUP_TEXT,
00186                HURRYUP_LONGTEXT, VLC_FALSE );
00187     add_bool( SOUT_CFG_PREFIX "deinterlace", 0, NULL, DEINTERLACE_TEXT,
00188               DEINTERLACE_LONGTEXT, VLC_FALSE );
00189     add_string( SOUT_CFG_PREFIX "deinterlace-module", "deinterlace", NULL,
00190                 DEINTERLACE_MODULE_TEXT, DEINTERLACE_MODULE_LONGTEXT,
00191                 VLC_FALSE );
00192         change_string_list( ppsz_deinterlace_type, 0, 0 );
00193     add_integer( SOUT_CFG_PREFIX "width", 0, NULL, WIDTH_TEXT,
00194                  WIDTH_LONGTEXT, VLC_TRUE );
00195     add_integer( SOUT_CFG_PREFIX "height", 0, NULL, HEIGHT_TEXT,
00196                  HEIGHT_LONGTEXT, VLC_TRUE );
00197     add_integer( SOUT_CFG_PREFIX "maxwidth", 0, NULL, MAXWIDTH_TEXT,
00198                  MAXWIDTH_LONGTEXT, VLC_TRUE );
00199     add_integer( SOUT_CFG_PREFIX "maxheight", 0, NULL, MAXHEIGHT_TEXT,
00200                  MAXHEIGHT_LONGTEXT, VLC_TRUE );
00201     add_module_list_cat( SOUT_CFG_PREFIX "vfilter", SUBCAT_VIDEO_VFILTER,
00202                      NULL, NULL,
00203                      VFILTER_TEXT, VFILTER_LONGTEXT, VLC_FALSE );
00204 
00205     add_integer( SOUT_CFG_PREFIX "croptop", 0, NULL, CROPTOP_TEXT,
00206                  CROPTOP_LONGTEXT, VLC_TRUE );
00207     add_integer( SOUT_CFG_PREFIX "cropleft", 0, NULL, CROPLEFT_TEXT,
00208                  CROPLEFT_LONGTEXT, VLC_TRUE );
00209     add_integer( SOUT_CFG_PREFIX "cropbottom", 0, NULL, CROPBOTTOM_TEXT,
00210                  CROPBOTTOM_LONGTEXT, VLC_TRUE );
00211     add_integer( SOUT_CFG_PREFIX "cropright", 0, NULL, CROPRIGHT_TEXT,
00212                  CROPRIGHT_LONGTEXT, VLC_TRUE );
00213 
00214     set_section( N_("Audio"), NULL );
00215     add_string( SOUT_CFG_PREFIX "aenc", NULL, NULL, AENC_TEXT,
00216                 AENC_LONGTEXT, VLC_FALSE );
00217     add_string( SOUT_CFG_PREFIX "acodec", NULL, NULL, ACODEC_TEXT,
00218                 ACODEC_LONGTEXT, VLC_FALSE );
00219     add_integer( SOUT_CFG_PREFIX "ab", 64000, NULL, AB_TEXT,
00220                  AB_LONGTEXT, VLC_FALSE );
00221     add_integer( SOUT_CFG_PREFIX "channels", 0, NULL, ACHANS_TEXT,
00222                  ACHANS_LONGTEXT, VLC_FALSE );
00223     add_integer( SOUT_CFG_PREFIX "samplerate", 0, NULL, ARATE_TEXT,
00224                  ARATE_LONGTEXT, VLC_TRUE );
00225     add_bool( SOUT_CFG_PREFIX "audio-sync", 0, NULL, ASYNC_TEXT,
00226               ASYNC_LONGTEXT, VLC_FALSE );
00227 
00228     set_section( N_("Overlays/Subtitles"), NULL );
00229     add_string( SOUT_CFG_PREFIX "senc", NULL, NULL, SENC_TEXT,
00230                 SENC_LONGTEXT, VLC_FALSE );
00231     add_string( SOUT_CFG_PREFIX "scodec", NULL, NULL, SCODEC_TEXT,
00232                 SCODEC_LONGTEXT, VLC_FALSE );
00233     add_bool( SOUT_CFG_PREFIX "soverlay", 0, NULL, SCODEC_TEXT,
00234                SCODEC_LONGTEXT, VLC_FALSE );
00235     add_module_list_cat( SOUT_CFG_PREFIX "sfilter", SUBCAT_VIDEO_SUBPIC,
00236                      NULL, NULL,
00237                      SFILTER_TEXT, SFILTER_LONGTEXT, VLC_FALSE );
00238 
00239     set_section( N_("On Screen Display"), NULL );
00240     add_bool( SOUT_CFG_PREFIX "osd", 0, NULL, OSD_TEXT,
00241               OSD_LONGTEXT, VLC_FALSE );
00242     
00243     set_section( N_("Miscellaneous"), NULL );
00244     add_integer( SOUT_CFG_PREFIX "threads", 0, NULL, THREADS_TEXT,
00245                  THREADS_LONGTEXT, VLC_TRUE );
00246     add_bool( SOUT_CFG_PREFIX "high-priority", 0, NULL, HP_TEXT, HP_LONGTEXT,
00247               VLC_TRUE );
00248 
00249 vlc_module_end();
00250 
00251 static const char *ppsz_sout_options[] = {
00252     "venc", "vcodec", "vb", "croptop", "cropbottom", "cropleft", "cropright",
00253     "scale", "fps", "width", "height", "vfilter", "deinterlace",
00254     "deinterlace-module", "threads", "hurry-up", "aenc", "acodec", "ab",
00255     "samplerate", "channels", "senc", "scodec", "soverlay", "sfilter",
00256     "osd", "audio-sync", "high-priority", "maxwidth", "maxheight", NULL
00257 };
00258 
00259 /*****************************************************************************
00260  * Exported prototypes
00261  *****************************************************************************/
00262 static sout_stream_id_t *Add ( sout_stream_t *, es_format_t * );
00263 static int               Del ( sout_stream_t *, sout_stream_id_t * );
00264 static int               Send( sout_stream_t *, sout_stream_id_t *, block_t* );
00265 
00266 static int  transcode_audio_new    ( sout_stream_t *, sout_stream_id_t * );
00267 static void transcode_audio_close  ( sout_stream_t *, sout_stream_id_t * );
00268 static int  transcode_audio_process( sout_stream_t *, sout_stream_id_t *,
00269                                      block_t *, block_t ** );
00270 
00271 static aout_buffer_t *audio_new_buffer( decoder_t *, int );
00272 static void audio_del_buffer( decoder_t *, aout_buffer_t * );
00273 
00274 static int  transcode_video_new    ( sout_stream_t *, sout_stream_id_t * );
00275 static void transcode_video_close  ( sout_stream_t *, sout_stream_id_t * );
00276 static int  transcode_video_encoder_open( sout_stream_t *, sout_stream_id_t *);
00277 static int  transcode_video_process( sout_stream_t *, sout_stream_id_t *,
00278                                      block_t *, block_t ** );
00279 
00280 static void video_del_buffer( vlc_object_t *, picture_t * );
00281 static picture_t *video_new_buffer_decoder( decoder_t * );
00282 static void video_del_buffer_decoder( decoder_t *, picture_t * );
00283 static void video_link_picture_decoder( decoder_t *, picture_t * );
00284 static void video_unlink_picture_decoder( decoder_t *, picture_t * );
00285 static picture_t *video_new_buffer_filter( filter_t * );
00286 static void video_del_buffer_filter( filter_t *, picture_t * );
00287 
00288 static int  transcode_spu_new    ( sout_stream_t *, sout_stream_id_t * );
00289 static void transcode_spu_close  ( sout_stream_t *, sout_stream_id_t * );
00290 static int  transcode_spu_process( sout_stream_t *, sout_stream_id_t *,
00291                                    block_t *, block_t ** );
00292 
00293 static int  transcode_osd_new    ( sout_stream_t *, sout_stream_id_t * );
00294 static void transcode_osd_close  ( sout_stream_t *, sout_stream_id_t * );
00295 static int  transcode_osd_process( sout_stream_t *, sout_stream_id_t *,
00296                                    block_t *, block_t ** );
00297                                    
00298 static int  EncoderThread( struct sout_stream_sys_t * p_sys );
00299 
00300 static int pi_channels_maps[6] =
00301 {
00302     0,
00303     AOUT_CHAN_CENTER,   AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
00304     AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
00305     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
00306      | AOUT_CHAN_REARRIGHT,
00307     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
00308      | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
00309 };
00310 
00311 #define PICTURE_RING_SIZE 64
00312 #define SUBPICTURE_RING_SIZE 20
00313 
00314 struct sout_stream_sys_t
00315 {
00316     VLC_COMMON_MEMBERS
00317 
00318     sout_stream_t   *p_out;
00319     sout_stream_id_t *id_video;
00320     block_t         *p_buffers;
00321     vlc_mutex_t     lock_out;
00322     vlc_cond_t      cond;
00323     picture_t *     pp_pics[PICTURE_RING_SIZE];
00324     int             i_first_pic, i_last_pic;
00325 
00326     /* Audio */
00327     vlc_fourcc_t    i_acodec;   /* codec audio (0 if not transcode) */
00328     char            *psz_aenc;
00329     sout_cfg_t      *p_audio_cfg;
00330     int             i_sample_rate;
00331     int             i_channels;
00332     int             i_abitrate;
00333 
00334     /* Video */
00335     vlc_fourcc_t    i_vcodec;   /* codec video (0 if not transcode) */
00336     char            *psz_venc;
00337     sout_cfg_t      *p_video_cfg;
00338     int             i_vbitrate;
00339     double          f_scale;
00340     double          f_fps;
00341     unsigned int    i_width, i_maxwidth;
00342     unsigned int    i_height, i_maxheight;
00343     vlc_bool_t      b_deinterlace;
00344     char            *psz_deinterlace;
00345     sout_cfg_t      *p_deinterlace_cfg;
00346     int             i_threads;
00347     vlc_bool_t      b_high_priority;
00348     vlc_bool_t      b_hurry_up;
00349     char            *psz_vfilters[10];
00350     sout_cfg_t      *p_vfilters_cfg[10];
00351     int             i_vfilters;
00352 
00353     int             i_crop_top;
00354     int             i_crop_bottom;
00355     int             i_crop_right;
00356     int             i_crop_left;
00357 
00358     /* SPU */
00359     vlc_fourcc_t    i_scodec;   /* codec spu (0 if not transcode) */
00360     char            *psz_senc;
00361     vlc_bool_t      b_soverlay;
00362     sout_cfg_t      *p_spu_cfg;
00363     spu_t           *p_spu;
00364 
00365     /* OSD Menu */
00366     sout_stream_id_t *id_osd;   /* extension for streaming OSD menus */
00367     vlc_fourcc_t    i_osdcodec; /* codec osd menu (0 if not transcode) */
00368     char            *psz_osdenc;
00369     sout_cfg_t      *p_osd_cfg;
00370     vlc_bool_t      b_es_osd;      /* VLC_TRUE when osd es is registered */
00371     vlc_bool_t      b_sout_osd;
00372         
00373     /* Sync */
00374     vlc_bool_t      b_master_sync;
00375     mtime_t         i_master_drift;
00376 };
00377 
00378 struct decoder_owner_sys_t
00379 {
00380     picture_t *pp_pics[PICTURE_RING_SIZE];
00381     sout_stream_sys_t *p_sys;
00382 };
00383 struct filter_owner_sys_t
00384 {
00385     picture_t *pp_pics[PICTURE_RING_SIZE];
00386     sout_stream_sys_t *p_sys;
00387 };
00388 
00389 /*****************************************************************************
00390  * Open:
00391  *****************************************************************************/
00392 static int Open( vlc_object_t *p_this )
00393 {
00394     sout_stream_t     *p_stream = (sout_stream_t*)p_this;
00395     sout_stream_sys_t *p_sys;
00396     vlc_value_t       val;
00397 
00398     p_sys = vlc_object_create( p_this, sizeof( sout_stream_sys_t ) );
00399 
00400     p_sys->p_out = sout_StreamNew( p_stream->p_sout, p_stream->psz_next );
00401     if( !p_sys->p_out )
00402     {
00403         msg_Err( p_stream, "cannot create chain" );
00404         vlc_object_destroy( p_sys );
00405         return VLC_EGENERIC;
00406     }
00407 
00408     p_sys->i_master_drift = 0;
00409 
00410     sout_CfgParse( p_stream, SOUT_CFG_PREFIX, ppsz_sout_options,
00411                    p_stream->p_cfg );
00412 
00413     /* Audio transcoding parameters */
00414     var_Get( p_stream, SOUT_CFG_PREFIX "aenc", &val );
00415     p_sys->psz_aenc = NULL;
00416     p_sys->p_audio_cfg = NULL;
00417     if( val.psz_string && *val.psz_string )
00418     {
00419         char *psz_next;
00420         psz_next = sout_CfgCreate( &p_sys->psz_aenc, &p_sys->p_audio_cfg,
00421                                    val.psz_string );
00422         if( psz_next ) free( psz_next );
00423     }
00424     if( val.psz_string ) free( val.psz_string );
00425 
00426     var_Get( p_stream, SOUT_CFG_PREFIX "acodec", &val );
00427     p_sys->i_acodec = 0;
00428     if( val.psz_string && *val.psz_string )
00429     {
00430         char fcc[4] = "    ";
00431         memcpy( fcc, val.psz_string, __MIN( strlen( val.psz_string ), 4 ) );
00432         p_sys->i_acodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
00433     }
00434     if( val.psz_string ) free( val.psz_string );
00435 
00436     var_Get( p_stream, SOUT_CFG_PREFIX "ab", &val );
00437     p_sys->i_abitrate = val.i_int;
00438     if( p_sys->i_abitrate < 4000 ) p_sys->i_abitrate *= 1000;
00439 
00440     var_Get( p_stream, SOUT_CFG_PREFIX "samplerate", &val );
00441     p_sys->i_sample_rate = val.i_int;
00442 
00443     var_Get( p_stream, SOUT_CFG_PREFIX "channels", &val );
00444     p_sys->i_channels = val.i_int;
00445 
00446     if( p_sys->i_acodec )
00447     {
00448         if( (strncmp( (char *)&p_sys->i_acodec, "mp3", 3) == 0) &&
00449                             (p_sys->i_channels > 2) )
00450         {
00451             msg_Warn( p_stream, "%d channels invalid for mp3, forcing to 2",
00452                       p_sys->i_channels );
00453             p_sys->i_channels = 2;
00454         }                    
00455         msg_Dbg( p_stream, "codec audio=%4.4s %dHz %d channels %dKb/s",
00456                  (char *)&p_sys->i_acodec, p_sys->i_sample_rate,
00457                  p_sys->i_channels, p_sys->i_abitrate / 1000 );
00458     }
00459 
00460     /* Video transcoding parameters */
00461     var_Get( p_stream, SOUT_CFG_PREFIX "venc", &val );
00462     p_sys->psz_venc = NULL;
00463     p_sys->p_video_cfg = NULL;
00464     if( val.psz_string && *val.psz_string )
00465     {
00466         char *psz_next;
00467         psz_next = sout_CfgCreate( &p_sys->psz_venc, &p_sys->p_video_cfg,
00468                                    val.psz_string );
00469         if( psz_next ) free( psz_next );
00470     }
00471     if( val.psz_string ) free( val.psz_string );
00472 
00473     var_Get( p_stream, SOUT_CFG_PREFIX "vcodec", &val );
00474     p_sys->i_vcodec = 0;
00475     if( val.psz_string && *val.psz_string )
00476     {
00477         char fcc[4] = "    ";
00478         memcpy( fcc, val.psz_string, __MIN( strlen( val.psz_string ), 4 ) );
00479         p_sys->i_vcodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
00480     }
00481     if( val.psz_string ) free( val.psz_string );
00482 
00483     var_Get( p_stream, SOUT_CFG_PREFIX "vb", &val );
00484     p_sys->i_vbitrate = val.i_int;
00485     if( p_sys->i_vbitrate < 16000 ) p_sys->i_vbitrate *= 1000;
00486 
00487     var_Get( p_stream, SOUT_CFG_PREFIX "scale", &val );
00488     p_sys->f_scale = val.f_float;
00489 
00490     var_Get( p_stream, SOUT_CFG_PREFIX "fps", &val );
00491     p_sys->f_fps = val.f_float;
00492 
00493     var_Get( p_stream, SOUT_CFG_PREFIX "hurry-up", &val );
00494     p_sys->b_hurry_up = val.b_bool;
00495 
00496     var_Get( p_stream, SOUT_CFG_PREFIX "width", &val );
00497     p_sys->i_width = val.i_int;
00498 
00499     var_Get( p_stream, SOUT_CFG_PREFIX "height", &val );
00500     p_sys->i_height = val.i_int;
00501 
00502     var_Get( p_stream, SOUT_CFG_PREFIX "maxwidth", &val );
00503     p_sys->i_maxwidth = val.i_int;
00504 
00505     var_Get( p_stream, SOUT_CFG_PREFIX "maxheight", &val );
00506     p_sys->i_maxheight = val.i_int;
00507 
00508     var_Get( p_stream, SOUT_CFG_PREFIX "vfilter", &val );
00509     p_sys->i_vfilters = 0;
00510     if( val.psz_string && *val.psz_string )
00511     {
00512         char *psz_parser = val.psz_string;
00513 
00514         while( psz_parser != NULL && *psz_parser != '\0' )
00515         {
00516             psz_parser = sout_CfgCreate(
00517                                    &p_sys->psz_vfilters[p_sys->i_vfilters],
00518                                    &p_sys->p_vfilters_cfg[p_sys->i_vfilters],
00519                                    psz_parser );
00520             p_sys->i_vfilters++;
00521             if( psz_parser != NULL && *psz_parser != '\0' ) psz_parser++;
00522         }
00523     }
00524     if( val.psz_string ) free( val.psz_string );
00525     p_sys->psz_vfilters[p_sys->i_vfilters] = NULL;
00526     p_sys->p_vfilters_cfg[p_sys->i_vfilters] = NULL;
00527 
00528     var_Get( p_stream, SOUT_CFG_PREFIX "deinterlace", &val );
00529     p_sys->b_deinterlace = val.b_bool;
00530 
00531     var_Get( p_stream, SOUT_CFG_PREFIX "deinterlace-module", &val );
00532     p_sys->psz_deinterlace = NULL;
00533     p_sys->p_deinterlace_cfg = NULL;
00534     if( val.psz_string && *val.psz_string )
00535     {
00536         char *psz_next;
00537         psz_next = sout_CfgCreate( &p_sys->psz_deinterlace,
00538                                    &p_sys->p_deinterlace_cfg,
00539                                    val.psz_string );
00540         if( psz_next ) free( psz_next );
00541     }
00542     if( val.psz_string ) free( val.psz_string );
00543 
00544     var_Get( p_stream, SOUT_CFG_PREFIX "croptop", &val );
00545     p_sys->i_crop_top = val.i_int;
00546     var_Get( p_stream, SOUT_CFG_PREFIX "cropbottom", &val );
00547     p_sys->i_crop_bottom = val.i_int;
00548     var_Get( p_stream, SOUT_CFG_PREFIX "cropleft", &val );
00549     p_sys->i_crop_left = val.i_int;
00550     var_Get( p_stream, SOUT_CFG_PREFIX "cropright", &val );
00551     p_sys->i_crop_right = val.i_int;
00552 
00553     var_Get( p_stream, SOUT_CFG_PREFIX "threads", &val );
00554     p_sys->i_threads = val.i_int;
00555     var_Get( p_stream, SOUT_CFG_PREFIX "high-priority", &val );
00556     p_sys->b_high_priority = val.b_bool;
00557 
00558     if( p_sys->i_vcodec )
00559     {
00560         msg_Dbg( p_stream, "codec video=%4.4s %dx%d scaling: %f %dkb/s",
00561                  (char *)&p_sys->i_vcodec, p_sys->i_width, p_sys->i_height,
00562                  p_sys->f_scale, p_sys->i_vbitrate / 1000 );
00563     }
00564 
00565     /* Subpictures transcoding parameters */
00566     p_sys->p_spu = NULL;
00567     p_sys->psz_senc = NULL;
00568     p_sys->p_spu_cfg = NULL;
00569     p_sys->i_scodec = 0;
00570 
00571     var_Get( p_stream, SOUT_CFG_PREFIX "senc", &val );
00572     if( val.psz_string && *val.psz_string )
00573     {
00574         char *psz_next;
00575         psz_next = sout_CfgCreate( &p_sys->psz_senc, &p_sys->p_spu_cfg,
00576                                    val.psz_string );
00577         if( psz_next ) free( psz_next );
00578     }
00579     if( val.psz_string ) free( val.psz_string );
00580 
00581     var_Get( p_stream, SOUT_CFG_PREFIX "scodec", &val );
00582     if( val.psz_string && *val.psz_string )
00583     {
00584         char fcc[4] = "    ";
00585         memcpy( fcc, val.psz_string, __MIN( strlen( val.psz_string ), 4 ) );
00586         p_sys->i_scodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
00587     }
00588     if( val.psz_string ) free( val.psz_string );
00589 
00590     if( p_sys->i_scodec )
00591     {
00592         msg_Dbg( p_stream, "codec spu=%4.4s", (char *)&p_sys->i_scodec );
00593     }
00594 
00595     var_Get( p_stream, SOUT_CFG_PREFIX "soverlay", &val );
00596     p_sys->b_soverlay = val.b_bool;
00597 
00598     var_Get( p_stream, SOUT_CFG_PREFIX "sfilter", &val );
00599     if( val.psz_string && *val.psz_string )
00600     {
00601         p_sys->p_spu = spu_Create( p_stream );
00602         var_Create( p_sys->p_spu, "sub-filter", VLC_VAR_STRING );
00603         var_Set( p_sys->p_spu, "sub-filter", val );
00604         spu_Init( p_sys->p_spu );
00605     }
00606     if( val.psz_string ) free( val.psz_string );
00607 
00608     /* OSD menu transcoding parameters */
00609     p_sys->psz_osdenc = NULL;
00610     p_sys->p_osd_cfg  = NULL;
00611     p_sys->i_osdcodec = 0;
00612     p_sys->b_es_osd   = VLC_FALSE;
00613 
00614     var_Get( p_stream, SOUT_CFG_PREFIX "osd", &val );
00615     p_sys->b_sout_osd = val.b_bool;
00616     if( p_sys->b_sout_osd )
00617     {
00618         vlc_value_t osd_val;
00619         char *psz_next;
00620        
00621         psz_next = sout_CfgCreate( &p_sys->psz_osdenc,
00622                                    &p_sys->p_osd_cfg, strdup( "dvbsub") );
00623         if( psz_next ) free( psz_next );
00624         
00625         p_sys->i_osdcodec = VLC_FOURCC('Y','U','V','P' );        
00626 
00627         msg_Dbg( p_stream, "codec osd=%4.4s", (char *)&p_sys->i_osdcodec );
00628 
00629         if( !p_sys->p_spu )
00630         {
00631             osd_val.psz_string = strdup("osdmenu");
00632             p_sys->p_spu = spu_Create( p_stream );
00633             var_Create( p_sys->p_spu, "sub-filter", VLC_VAR_STRING );
00634             var_Set( p_sys->p_spu, "sub-filter", osd_val );
00635             spu_Init( p_sys->p_spu );
00636             if( osd_val.psz_string ) free( osd_val.psz_string );
00637         }
00638         else
00639         {
00640             osd_val.psz_string = strdup("osdmenu");
00641             var_Set( p_sys->p_spu, "sub-filter", osd_val );
00642             if( osd_val.psz_string ) free( osd_val.psz_string );
00643         }         
00644     }
00645 
00646     /* Audio settings */
00647     var_Get( p_stream, SOUT_CFG_PREFIX "audio-sync", &val );
00648     p_sys->b_master_sync = val.b_bool;
00649     if( p_sys->f_fps > 0 ) p_sys->b_master_sync = VLC_TRUE;
00650 
00651     p_stream->pf_add    = Add;
00652     p_stream->pf_del    = Del;
00653     p_stream->pf_send   = Send;
00654     p_stream->p_sys     = p_sys;
00655 
00656     return VLC_SUCCESS;
00657 }
00658 
00659 /*****************************************************************************
00660  * Close:
00661  *****************************************************************************/
00662 static void Close( vlc_object_t * p_this )
00663 {
00664     sout_stream_t       *p_stream = (sout_stream_t*)p_this;
00665     sout_stream_sys_t   *p_sys = p_stream->p_sys;
00666 
00667     sout_StreamDelete( p_sys->p_out );
00668 
00669     while( p_sys->p_audio_cfg != NULL )
00670     {
00671         sout_cfg_t *p_next = p_sys->p_audio_cfg->p_next;
00672 
00673         if( p_sys->p_audio_cfg->psz_name )
00674             free( p_sys->p_audio_cfg->psz_name );
00675         if( p_sys->p_audio_cfg->psz_value )
00676             free( p_sys->p_audio_cfg->psz_value );
00677         free( p_sys->p_audio_cfg );
00678 
00679         p_sys->p_audio_cfg = p_next;
00680     }
00681     if( p_sys->psz_aenc ) free( p_sys->psz_aenc );
00682 
00683     while( p_sys->p_video_cfg != NULL )
00684     {
00685         sout_cfg_t *p_next = p_sys->p_video_cfg->p_next;
00686 
00687         if( p_sys->p_video_cfg->psz_name )
00688             free( p_sys->p_video_cfg->psz_name );
00689         if( p_sys->p_video_cfg->psz_value )
00690             free( p_sys->p_video_cfg->psz_value );
00691         free( p_sys->p_video_cfg );
00692 
00693         p_sys->p_video_cfg = p_next;
00694     }
00695     if( p_sys->psz_venc ) free( p_sys->psz_venc );
00696 
00697     while( p_sys->p_deinterlace_cfg != NULL )
00698     {
00699         sout_cfg_t *p_next = p_sys->p_deinterlace_cfg->p_next;
00700 
00701         if( p_sys->p_deinterlace_cfg->psz_name )
00702             free( p_sys->p_deinterlace_cfg->psz_name );
00703         if( p_sys->p_deinterlace_cfg->psz_value )
00704             free( p_sys->p_deinterlace_cfg->psz_value );
00705         free( p_sys->p_deinterlace_cfg );
00706 
00707         p_sys->p_deinterlace_cfg = p_next;
00708     }
00709     if( p_sys->psz_deinterlace ) free( p_sys->psz_deinterlace );
00710 
00711     while( p_sys->p_spu_cfg != NULL )
00712     {
00713         sout_cfg_t *p_next = p_sys->p_spu_cfg->p_next;
00714 
00715         if( p_sys->p_spu_cfg->psz_name )
00716             free( p_sys->p_spu_cfg->psz_name );
00717         if( p_sys->p_spu_cfg->psz_value )
00718             free( p_sys->p_spu_cfg->psz_value );
00719         free( p_sys->p_spu_cfg );
00720 
00721         p_sys->p_spu_cfg = p_next;
00722     }
00723     if( p_sys->psz_senc ) free( p_sys->psz_senc );
00724 
00725     if( p_sys->p_spu ) spu_Destroy( p_sys->p_spu );
00726     
00727     while( p_sys->p_osd_cfg != NULL )
00728     {
00729         sout_cfg_t *p_next = p_sys->p_osd_cfg->p_next;
00730 
00731         if( p_sys->p_osd_cfg->psz_name )
00732             free( p_sys->p_osd_cfg->psz_name );
00733         if( p_sys->p_osd_cfg->psz_value )
00734             free( p_sys->p_osd_cfg->psz_value );
00735         free( p_sys->p_osd_cfg );
00736 
00737         p_sys->p_osd_cfg = p_next;
00738     }
00739     if( p_sys->psz_osdenc ) free( p_sys->psz_osdenc );    
00740 
00741     vlc_object_destroy( p_sys );
00742 }
00743 
00744 struct sout_stream_id_t
00745 {
00746     vlc_fourcc_t  b_transcode;
00747 
00748     /* id of the out stream */
00749     void *id;
00750 
00751     /* Decoder */
00752     decoder_t       *p_decoder;
00753 
00754     /* Filters */
00755     filter_t        *pp_filter[10];
00756     int             i_filter;
00757     filter_t        *pp_vfilter[10];
00758     int             i_vfilter;
00759 
00760     /* Encoder */
00761     encoder_t       *p_encoder;
00762 
00763     /* Sync */
00764     date_t          interpolated_pts;
00765 };
00766 
00767 static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt )
00768 {
00769     sout_stream_sys_t *p_sys = p_stream->p_sys;
00770     sout_stream_id_t *id;
00771 
00772     id = malloc( sizeof( sout_stream_id_t ) );
00773     memset( id, 0, sizeof(sout_stream_id_t) );
00774 
00775     id->id = NULL;
00776     id->p_decoder = NULL;
00777     id->p_encoder = NULL;
00778 
00779     /* Create decoder object */
00780     id->p_decoder = vlc_object_create( p_stream, VLC_OBJECT_DECODER );
00781     if( !id->p_decoder )
00782     {
00783         msg_Err( p_stream, "out of memory" );
00784         goto error;
00785     }
00786     vlc_object_attach( id->p_decoder, p_stream );
00787     id->p_decoder->p_module = NULL;
00788     id->p_decoder->fmt_in = *p_fmt;
00789     id->p_decoder->b_pace_control = VLC_TRUE;
00790 
00791     /* Create encoder object */
00792     id->p_encoder = vlc_object_create( p_stream, VLC_OBJECT_ENCODER );
00793     if( !id->p_encoder )
00794     {
00795         msg_Err( p_stream, "out of memory" );
00796         goto error;
00797     }
00798     vlc_object_attach( id->p_encoder, p_stream );
00799     id->p_encoder->p_module = NULL;
00800 
00801     /* Create destination format */
00802     es_format_Init( &id->p_encoder->fmt_out, p_fmt->i_cat, 0 );
00803     id->p_encoder->fmt_out.i_id    = p_fmt->i_id;
00804     id->p_encoder->fmt_out.i_group = p_fmt->i_group;
00805     if( p_fmt->psz_language )
00806         id->p_encoder->fmt_out.psz_language = strdup( p_fmt->psz_language );
00807 
00808     if( p_fmt->i_cat == AUDIO_ES && (p_sys->i_acodec || p_sys->psz_aenc) )
00809     {
00810         msg_Dbg( p_stream,
00811                  "creating audio transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
00812                  (char*)&p_fmt->i_codec, (char*)&p_sys->i_acodec );
00813 
00814         /* Complete destination format */
00815         id->p_encoder->fmt_out.i_codec = p_sys->i_acodec;
00816         id->p_encoder->fmt_out.audio.i_rate = p_sys->i_sample_rate > 0 ?
00817             p_sys->i_sample_rate : (int)p_fmt->audio.i_rate;
00818         id->p_encoder->fmt_out.i_bitrate = p_sys->i_abitrate;
00819         id->p_encoder->fmt_out.audio.i_bitspersample =
00820             p_fmt->audio.i_bitspersample;
00821         id->p_encoder->fmt_out.audio.i_channels = p_sys->i_channels > 0 ?
00822             p_sys->i_channels : p_fmt->audio.i_channels;
00823         /* Sanity check for audio channels */
00824         id->p_encoder->fmt_out.audio.i_channels =
00825             __MIN( id->p_encoder->fmt_out.audio.i_channels,
00826                    id->p_decoder->fmt_in.audio.i_channels );
00827         id->p_encoder->fmt_out.audio.i_original_channels =
00828             id->p_decoder->fmt_in.audio.i_physical_channels;
00829         if( id->p_decoder->fmt_in.audio.i_channels ==
00830             id->p_encoder->fmt_out.audio.i_channels )
00831         {
00832             id->p_encoder->fmt_out.audio.i_physical_channels =
00833                 id->p_decoder->fmt_in.audio.i_physical_channels;
00834         }
00835         else
00836         {
00837             id->p_encoder->fmt_out.audio.i_physical_channels =
00838                 pi_channels_maps[id->p_encoder->fmt_out.audio.i_channels];
00839         }
00840 
00841         /* Build decoder -> filter -> encoder chain */
00842         if( transcode_audio_new( p_stream, id ) )
00843         {
00844             msg_Err( p_stream, "cannot create audio chain" );
00845             goto error;
00846         }
00847 
00848         /* Open output stream */
00849         id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->p_encoder->fmt_out );
00850         id->b_transcode = VLC_TRUE;
00851 
00852         if( !id->id )
00853         {
00854             transcode_audio_close( p_stream, id );
00855             goto error;
00856         }
00857 
00858         date_Init( &id->interpolated_pts, p_fmt->audio.i_rate, 1 );
00859     }
00860     else if( p_fmt->i_cat == VIDEO_ES &&
00861              (p_sys->i_vcodec != 0 || p_sys->psz_venc) )
00862     {
00863         msg_Dbg( p_stream,
00864                  "creating video transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
00865                  (char*)&p_fmt->i_codec, (char*)&p_sys->i_vcodec );
00866 
00867         /* Complete destination format */
00868         id->p_encoder->fmt_out.i_codec = p_sys->i_vcodec;
00869         id->p_encoder->fmt_out.video.i_width  = p_sys->i_width;
00870         id->p_encoder->fmt_out.video.i_height = p_sys->i_height;
00871         id->p_encoder->fmt_out.i_bitrate = p_sys->i_vbitrate;
00872 
00873         /* Build decoder -> filter -> encoder chain */
00874         if( transcode_video_new( p_stream, id ) )
00875         {
00876             msg_Err( p_stream, "cannot create video chain" );
00877             goto error;
00878         }
00879 
00880         /* Stream will be added later on because we don't know
00881          * all the characteristics of the decoded stream yet */
00882         id->b_transcode = VLC_TRUE;
00883 
00884         if( p_sys->f_fps > 0 )
00885         {
00886             id->p_encoder->fmt_out.video.i_frame_rate =
00887                 (p_sys->f_fps * 1001) + 0.5;
00888             id->p_encoder->fmt_out.video.i_frame_rate_base = 1001;
00889         }
00890     }
00891     else if( p_fmt->i_cat == SPU_ES && (p_sys->i_scodec || p_sys->psz_senc) )
00892     {
00893         msg_Dbg( p_stream, "creating subtitles transcoding from fcc=`%4.4s' "
00894                  "to fcc=`%4.4s'", (char*)&p_fmt->i_codec,
00895                  (char*)&p_sys->i_scodec );
00896 
00897         /* Complete destination format */
00898         id->p_encoder->fmt_out.i_codec = p_sys->i_scodec;
00899 
00900         /* build decoder -> filter -> encoder */
00901         if( transcode_spu_new( p_stream, id ) )
00902         {
00903             msg_Err( p_stream, "cannot create subtitles chain" );
00904             goto error;
00905         }
00906 
00907         /* open output stream */
00908         id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->p_encoder->fmt_out );
00909         id->b_transcode = VLC_TRUE;
00910 
00911         if( !id->id )
00912         {
00913             transcode_spu_close( p_stream, id );
00914             goto error;
00915         }
00916     }
00917     else if( p_fmt->i_cat == SPU_ES && p_sys->b_soverlay )
00918     {
00919         msg_Dbg( p_stream, "subtitles (fcc=`%4.4s') overlaying",
00920                  (char*)&p_fmt->i_codec );
00921 
00922         id->b_transcode = VLC_TRUE;
00923 
00924         /* Build decoder -> filter -> overlaying chain */
00925         if( transcode_spu_new( p_stream, id ) )
00926         {
00927             msg_Err( p_stream, "cannot create subtitles chain" );
00928             goto error;
00929         }
00930     }
00931     else
00932     {
00933         msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')",
00934                  (char*)&p_fmt->i_codec );
00935         id->id = p_sys->p_out->pf_add( p_sys->p_out, p_fmt );
00936         id->b_transcode = VLC_FALSE;
00937 
00938         if( !id->id ) goto error;
00939     }
00940 
00941     if( p_sys->b_sout_osd )
00942     {
00943         /* Create a fake OSD menu elementary stream */
00944         if( !p_sys->b_es_osd && (p_sys->i_osdcodec != 0 || p_sys->psz_osdenc) )
00945         {
00946             if( transcode_osd_new( p_stream, p_sys->id_osd ) )
00947             {
00948                 msg_Err( p_stream, "cannot create osd chain" );
00949                 goto error;
00950             }
00951             p_sys->b_es_osd = VLC_TRUE;
00952         }
00953     }
00954     return id;
00955 
00956  error:
00957     if( id->p_decoder )
00958     {
00959         vlc_object_detach( id->p_decoder );
00960         vlc_object_destroy( id->p_decoder );
00961     }
00962 
00963     if( id->p_encoder )
00964     {
00965         vlc_object_detach( id->p_encoder );
00966         es_format_Clean( &id->p_encoder->fmt_out );
00967         vlc_object_destroy( id->p_encoder );
00968     }
00969 
00970     free( id );
00971     return NULL;
00972 }
00973 
00974 static int Del( sout_stream_t *p_stream, sout_stream_id_t *id )
00975 {
00976     sout_stream_sys_t *p_sys = p_stream->p_sys;
00977 
00978     if( p_sys->b_es_osd )
00979         transcode_osd_close( p_stream, p_sys->id_osd );
00980 
00981     if( id->b_transcode )
00982     {
00983         switch( id->p_decoder->fmt_in.i_cat )
00984         {
00985         case AUDIO_ES:
00986             transcode_audio_close( p_stream, id );
00987             break;
00988         case VIDEO_ES:
00989             transcode_video_close( p_stream, id );
00990             break;
00991         case SPU_ES:
00992             transcode_spu_close( p_stream, id );
00993             break;
00994         }
00995     }
00996 
00997     if( id->id ) p_sys->p_out->pf_del( p_sys->p_out, id->id );
00998 
00999     if( id->p_decoder )
01000     {
01001         vlc_object_detach( id->p_decoder );
01002         vlc_object_destroy( id->p_decoder );
01003     }
01004 
01005     if( id->p_encoder )
01006     {
01007         vlc_object_detach( id->p_encoder );
01008         es_format_Clean( &id->p_encoder->fmt_out );
01009         vlc_object_destroy( id->p_encoder );
01010     }
01011 
01012     free( id );
01013 
01014     return VLC_SUCCESS;
01015 }
01016 
01017 static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
01018                  block_t *p_buffer )
01019 {
01020     sout_stream_sys_t *p_sys = p_stream->p_sys;
01021     block_t *p_out = NULL;
01022 
01023     if( !id->b_transcode && id->id )
01024     {
01025         /* Transcode OSD menu pictures. */
01026         if( p_sys->b_es_osd )
01027         {
01028             transcode_osd_process( p_stream, id, p_buffer, &p_out );                
01029         }
01030         return p_sys->p_out->pf_send( p_sys->p_out, id->id, p_buffer );
01031     }
01032     else if( !id->b_transcode )
01033     {
01034         block_Release( p_buffer );
01035         return VLC_EGENERIC;
01036     }
01037 
01038     switch( id->p_decoder->fmt_in.i_cat )
01039     {
01040     case AUDIO_ES:
01041         transcode_audio_process( p_stream, id, p_buffer, &p_out );
01042         break;
01043 
01044     case VIDEO_ES:
01045         if( transcode_video_process( p_stream, id, p_buffer, &p_out )
01046             != VLC_SUCCESS )
01047         {
01048             return VLC_EGENERIC;
01049         }
01050         break;
01051 
01052     case SPU_ES:
01053         if( transcode_spu_process( p_stream, id, p_buffer, &p_out ) !=
01054             VLC_SUCCESS )
01055         {
01056             return VLC_EGENERIC;
01057         }
01058         break;
01059 
01060     default:
01061         p_out = NULL;
01062         block_Release( p_buffer );
01063         break;
01064     }
01065 
01066     if( p_out ) return p_sys->p_out->pf_send( p_sys->p_out, id->id, p_out );
01067     return VLC_SUCCESS;
01068 }
01069 
01070 /****************************************************************************
01071  * decoder reencoder part
01072  ****************************************************************************/
01073 int audio_BitsPerSample( vlc_fourcc_t i_format )
01074 {
01075     switch( i_format )
01076     {
01077     case VLC_FOURCC('u','8',' ',' '):
01078     case VLC_FOURCC('s','8',' ',' '):
01079         return 8;
01080 
01081     case VLC_FOURCC('u','1','6','l'):
01082     case VLC_FOURCC('s','1','6','l'):
01083     case VLC_FOURCC('u','1','6','b'):
01084     case VLC_FOURCC('s','1','6','b'):
01085         return 16;
01086 
01087     case VLC_FOURCC('u','2','4','l'):
01088     case VLC_FOURCC('s','2','4','l'):
01089     case VLC_FOURCC('u','2','4','b'):
01090     case VLC_FOURCC('s','2','4','b'):
01091         return 24;
01092 
01093     case VLC_FOURCC('u','3','2','l'):
01094     case VLC_FOURCC('s','3','2','l'):
01095     case VLC_FOURCC('u','3','2','b'):
01096     case VLC_FOURCC('s','3','2','b'):
01097     case VLC_FOURCC('f','l','3','2'):
01098     case VLC_FOURCC('f','i','3','2'):
01099         return 32;
01100 
01101     case VLC_FOURCC('f','l','6','4'):
01102         return 64;
01103     }
01104 
01105     return 0;
01106 }
01107 
01108 static filter_t *transcode_audio_filter_new( sout_stream_t *p_stream,
01109                                              sout_stream_id_t *id,
01110                                              es_format_t *p_fmt_in,
01111                                              es_format_t *p_fmt_out )
01112 {
01113     filter_t *p_filter = vlc_object_create( p_stream, VLC_OBJECT_FILTER );
01114 
01115     vlc_object_attach( p_filter, p_stream );
01116     p_filter->pf_audio_buffer_new = (block_t* (*) (filter_t*, int))__block_New;
01117 
01118     p_filter->fmt_in = *p_fmt_in;
01119     p_filter->fmt_out = *p_fmt_out;
01120 
01121     p_filter->p_module = module_Need( p_filter, "audio filter2", 0, 0 );
01122     if( p_filter->p_module )
01123     {
01124         p_filter->fmt_out.audio.i_bitspersample = 
01125             audio_BitsPerSample( p_filter->fmt_out.i_codec );
01126         *p_fmt_in = p_filter->fmt_out;
01127     }
01128     else
01129     {
01130         vlc_object_detach( p_filter );
01131         vlc_object_destroy( p_filter );
01132         p_filter = 0;
01133     }
01134 
01135     return p_filter;
01136 }
01137 
01138 static int transcode_audio_new( sout_stream_t *p_stream,
01139                                 sout_stream_id_t *id )
01140 {
01141     sout_stream_sys_t *p_sys = p_stream->p_sys;
01142     es_format_t fmt_last;
01143     int i_pass = 6;
01144 
01145     /*
01146      * Open decoder
01147      */
01148 
01149     /* Initialization of decoder structures */
01150     id->p_decoder->fmt_out = id->p_decoder->fmt_in;
01151     id->p_decoder->fmt_out.i_extra = 0;
01152     id->p_decoder->fmt_out.p_extra = 0;
01153     id->p_decoder->pf_decode_audio = 0;
01154     id->p_decoder->pf_aout_buffer_new = audio_new_buffer;
01155     id->p_decoder->pf_aout_buffer_del = audio_del_buffer;
01156     /* id->p_decoder->p_cfg = p_sys->p_audio_cfg; */
01157 
01158     id->p_decoder->p_module =
01159         module_Need( id->p_decoder, "decoder", "$codec", 0 );
01160 
01161     if( !id->p_decoder->p_module )
01162     {
01163         msg_Err( p_stream, "cannot find decoder" );
01164         return VLC_EGENERIC;
01165     }
01166     id->p_decoder->fmt_out.audio.i_bitspersample = 
01167         audio_BitsPerSample( id->p_decoder->fmt_out.i_codec );
01168     fmt_last = id->p_decoder->fmt_out;
01169     /* FIX decoders so we don't have to do this */
01170     fmt_last.audio.i_rate = id->p_decoder->fmt_in.audio.i_rate;
01171 
01172     /*
01173      * Open encoder
01174      */
01175 
01176     /* Initialization of encoder format structures */
01177     es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
01178                     id->p_decoder->fmt_out.i_codec );
01179     id->p_encoder->fmt_in.audio.i_format = id->p_decoder->fmt_out.i_codec;
01180 
01181     /* Initialization of encoder format structures */
01182     es_format_Init( &id->p_encoder->fmt_in, AUDIO_ES, AOUT_FMT_S16_NE );
01183     id->p_encoder->fmt_in.audio.i_format = AOUT_FMT_S16_NE;
01184     id->p_encoder->fmt_in.audio.i_rate = id->p_encoder->fmt_out.audio.i_rate;
01185     id->p_encoder->fmt_in.audio.i_physical_channels =
01186         id->p_encoder->fmt_out.audio.i_physical_channels;
01187     id->p_encoder->fmt_in.audio.i_original_channels =
01188         id->p_encoder->fmt_out.audio.i_original_channels;
01189     id->p_encoder->fmt_in.audio.i_channels =
01190         id->p_encoder->fmt_out.audio.i_channels;
01191     id->p_encoder->fmt_in.audio.i_bitspersample =
01192         audio_BitsPerSample( id->p_encoder->fmt_in.i_codec );
01193 
01194     id->p_encoder->p_cfg = p_stream->p_sys->p_audio_cfg;
01195 
01196     id->p_encoder->p_module =
01197         module_Need( id->p_encoder, "encoder", p_sys->psz_aenc, VLC_TRUE );
01198     if( !id->p_encoder->p_module )
01199     {
01200         msg_Err( p_stream, "cannot find encoder" );
01201         module_Unneed( id->p_decoder, id->p_decoder->p_module );
01202         id->p_decoder->p_module = 0;
01203         return VLC_EGENERIC;
01204     }
01205     id->p_encoder->fmt_in.audio.i_format = id->p_encoder->fmt_in.i_codec;
01206     id->p_encoder->fmt_in.audio.i_bitspersample =
01207         audio_BitsPerSample( id->p_encoder->fmt_in.i_codec );
01208 
01209     /* Load conversion filters */
01210     if( fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels ||
01211         fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate )
01212     {
01213         /* We'll have to go through fl32 first */
01214         es_format_t fmt_out = id->p_encoder->fmt_in;
01215         fmt_out.i_codec = fmt_out.audio.i_format = VLC_FOURCC('f','l','3','2');
01216 
01217         id->pp_filter[id->i_filter] =
01218             transcode_audio_filter_new( p_stream, id, &fmt_last, &fmt_out );
01219 
01220         if( id->pp_filter[id->i_filter] ) id->i_filter++;
01221     }
01222 
01223     while( i_pass-- )
01224     {
01225         if( fmt_last.audio.i_channels !=
01226             id->p_encoder->fmt_in.audio.i_channels ||
01227             fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate ||
01228             fmt_last.i_codec != id->p_encoder->fmt_in.i_codec )
01229         {
01230             id->pp_filter[id->i_filter] =
01231                 transcode_audio_filter_new( p_stream, id, &fmt_last,
01232                                             &id->p_encoder->fmt_in );
01233 
01234             if( id->pp_filter[id->i_filter] ) id->i_filter++;
01235             else break;
01236         }
01237     }
01238 
01239     /* Final checks to see if conversions were successful */
01240     if( fmt_last.i_codec != id->p_encoder->fmt_in.i_codec )
01241     {
01242         msg_Err( p_stream, "no audio filter found (%4.4s->%4.4s)",
01243                  (char *)&fmt_last.i_codec,
01244                  (char *)&id->p_encoder->fmt_in.i_codec );
01245         transcode_audio_close( p_stream, id );
01246         return VLC_EGENERIC;
01247     }
01248 
01249     if( fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels )
01250     {
01251         msg_Err( p_stream, "no audio filter found for mixing from"
01252                  " %i to %i channels", fmt_last.audio.i_channels,
01253                  id->p_encoder->fmt_in.audio.i_channels );
01254 #if 0
01255         /* FIXME : this might work, but only if the encoder is restarted */
01256         id->p_encoder->fmt_in.audio.i_channels = fmt_last.audio.i_channels;
01257         id->p_encoder->fmt_out.audio.i_channels = fmt_last.audio.i_channels;
01258 
01259         id->p_encoder->fmt_in.audio.i_physical_channels =
01260             id->p_encoder->fmt_in.audio.i_original_channels =
01261                 fmt_last.audio.i_physical_channels;
01262         id->p_encoder->fmt_out.audio.i_physical_channels =
01263             id->p_encoder->fmt_out.audio.i_original_channels =
01264                 fmt_last.audio.i_physical_channels;
01265 #else
01266         transcode_audio_close( p_stream, id );
01267         return VLC_EGENERIC;
01268 #endif
01269     }
01270 
01271     if( fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate )
01272     {
01273         msg_Err( p_stream, "no audio filter found for resampling from"
01274                  " %iHz to %iHz", fmt_last.audio.i_rate,
01275                  id->p_encoder->fmt_in.audio.i_rate );
01276 #if 0
01277         /* FIXME : this might work, but only if the encoder is restarted */
01278         id->p_encoder->fmt_in.audio.i_rate = fmt_last.audio.i_rate;
01279         id->p_encoder->fmt_out.audio.i_rate = fmt_last.audio.i_rate;
01280 #else
01281         transcode_audio_close( p_stream, id );
01282         return VLC_EGENERIC;
01283 #endif
01284     }
01285 
01286     /* FIXME: Hack for mp3 transcoding support */
01287     if( id->p_encoder->fmt_out.i_codec == VLC_FOURCC( 'm','p','3',' ' ) )
01288         id->p_encoder->fmt_out.i_codec = VLC_FOURCC( 'm','p','g','a' );
01289 
01290     return VLC_SUCCESS;
01291 }
01292 
01293 static void transcode_audio_close( sout_stream_t *p_stream,
01294                                    sout_stream_id_t *id )
01295 {
01296     int i;
01297 
01298     /* Close decoder */
01299     if( id->p_decoder->p_module )
01300         module_Unneed( id->p_decoder, id->p_decoder->p_module );
01301     id->p_decoder->p_module = 0;
01302 
01303     /* Close encoder */
01304     if( id->p_encoder->p_module )
01305         module_Unneed( id->p_encoder, id->p_encoder->p_module );
01306     id->p_encoder->p_module = 0;
01307 
01308     /* Close filters */
01309     for( i = 0; i < id->i_filter; i++ )
01310     {
01311         vlc_object_detach( id->pp_filter[i] );
01312         if( id->pp_filter[i]->p_module )
01313             module_Unneed( id->pp_filter[i], id->pp_filter[i]->p_module );
01314         vlc_object_destroy( id->pp_filter[i] );
01315     }
01316 }
01317 
01318 static int transcode_audio_process( sout_stream_t *p_stream,
01319                                     sout_stream_id_t *id,
01320                                     block_t *in, block_t **out )
01321 {
01322     sout_stream_sys_t *p_sys = p_stream->p_sys;
01323     aout_buffer_t *p_audio_buf;
01324     block_t *p_block, *p_audio_block;
01325     int i;
01326     *out = NULL;
01327 
01328     while( (p_audio_buf = id->p_decoder->pf_decode_audio( id->p_decoder,
01329                                                           &in )) )
01330     {
01331         if( p_sys->b_master_sync )
01332         {
01333             mtime_t i_dts = date_Get( &id->interpolated_pts ) + 1;
01334             if ( p_audio_buf->start_date - i_dts > MASTER_SYNC_MAX_DRIFT
01335                   || p_audio_buf->start_date - i_dts < -MASTER_SYNC_MAX_DRIFT )
01336             {
01337                 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
01338                 date_Set( &id->interpolated_pts, p_audio_buf->start_date );
01339                 i_dts = p_audio_buf->start_date + 1;
01340             }
01341             p_sys->i_master_drift = p_audio_buf->start_date - i_dts;
01342             date_Increment( &id->interpolated_pts, p_audio_buf->i_nb_samples );
01343             p_audio_buf->start_date -= p_sys->i_master_drift;
01344             p_audio_buf->end_date -= p_sys->i_master_drift;
01345         }
01346 
01347         p_audio_block = p_audio_buf->p_sys;
01348         p_audio_block->i_buffer = p_audio_buf->i_nb_bytes;
01349         p_audio_block->i_dts = p_audio_block->i_pts =
01350             p_audio_buf->start_date;
01351         p_audio_block->i_length = p_audio_buf->end_date -
01352             p_audio_buf->start_date;
01353         p_audio_block->i_samples = p_audio_buf->i_nb_samples;
01354 
01355         /* Run filter chain */
01356         for( i = 0; i < id->i_filter; i++ )
01357         {
01358             p_audio_block =
01359                 id->pp_filter[i]->pf_audio_filter( id->pp_filter[i],
01360                                                    p_audio_block );
01361         }
01362 
01363         p_audio_buf->p_buffer = p_audio_block->p_buffer;
01364         p_audio_buf->i_nb_bytes = p_audio_block->i_buffer;
01365         p_audio_buf->i_nb_samples = p_audio_block->i_samples;
01366         p_audio_buf->start_date = p_audio_block->i_dts;
01367         p_audio_buf->end_date = p_audio_block->i_dts + p_audio_block->i_length;
01368 
01369         p_block = id->p_encoder->pf_encode_audio( id->p_encoder, p_audio_buf );
01370         block_ChainAppend( out, p_block );
01371         block_Release( p_audio_block );
01372         free( p_audio_buf );
01373     }
01374 
01375     return VLC_SUCCESS;
01376 }
01377 
01378 static void audio_release_buffer( aout_buffer_t *p_buffer )
01379 {
01380     if( p_buffer && p_buffer->p_sys ) block_Release( p_buffer->p_sys );
01381     if( p_buffer ) free( p_buffer );
01382 }
01383 
01384 static aout_buffer_t *audio_new_buffer( decoder_t *p_dec, int i_samples )
01385 {
01386     aout_buffer_t *p_buffer;
01387     block_t *p_block;
01388     int i_size;
01389 
01390     if( p_dec->fmt_out.audio.i_bitspersample )
01391     {
01392         i_size = i_samples * p_dec->fmt_out.audio.i_bitspersample / 8 *
01393             p_dec->fmt_out.audio.i_channels;
01394     }
01395     else if( p_dec->fmt_out.audio.i_bytes_per_frame &&
01396              p_dec->fmt_out.audio.i_frame_length )
01397     {
01398         i_size = i_samples * p_dec->fmt_out.audio.i_bytes_per_frame /
01399             p_dec->fmt_out.audio.i_frame_length;
01400     }
01401     else
01402     {
01403         i_size = i_samples * 4 * p_dec->fmt_out.audio.i_channels;
01404     }
01405 
01406     p_buffer = malloc( sizeof(aout_buffer_t) );
01407     p_buffer->pf_release = audio_release_buffer;
01408     p_buffer->p_sys = p_block = block_New( p_dec, i_size );
01409 
01410     p_buffer->p_buffer = p_block->p_buffer;
01411     p_buffer->i_size = p_buffer->i_nb_bytes = p_block->i_buffer;
01412     p_buffer->i_nb_samples = i_samples;
01413     p_block->i_samples = i_samples;
01414 
01415     return p_buffer;
01416 }
01417 
01418 static void audio_del_buffer( decoder_t *p_dec, aout_buffer_t *p_buffer )
01419 {
01420     if( p_buffer && p_buffer->p_sys ) block_Release( p_buffer->p_sys );
01421     if( p_buffer ) free( p_buffer );
01422 }
01423 
01424 /*
01425  * video
01426  */
01427 static int transcode_video_new( sout_stream_t *p_stream, sout_stream_id_t *id )
01428 {
01429     sout_stream_sys_t *p_sys = p_stream->p_sys;
01430     int i;
01431 
01432     /*
01433      * Open decoder
01434      */
01435 
01436     /* Initialization of decoder structures */
01437     id->p_decoder->fmt_out = id->p_decoder->fmt_in;
01438     id->p_decoder->fmt_out.i_extra = 0;
01439     id->p_decoder->fmt_out.p_extra = 0;
01440     id->p_decoder->pf_decode_video = 0;
01441     id->p_decoder->pf_vout_buffer_new = video_new_buffer_decoder;
01442     id->p_decoder->pf_vout_buffer_del = video_del_buffer_decoder;
01443     id->p_decoder->pf_picture_link    = video_link_picture_decoder;
01444     id->p_decoder->pf_picture_unlink  = video_unlink_picture_decoder;
01445     id->p_decoder->p_owner = malloc( sizeof(decoder_owner_sys_t) );
01446     for( i = 0; i < PICTURE_RING_SIZE; i++ )
01447         id->p_decoder->p_owner->pp_pics[i] = 0;
01448     id->p_decoder->p_owner->p_sys = p_sys;
01449     /* id->p_decoder->p_cfg = p_sys->p_video_cfg; */
01450 
01451     id->p_decoder->p_module =
01452         module_Need( id->p_decoder, "decoder", "$codec", 0 );
01453 
01454     if( !id->p_decoder->p_module )
01455     {
01456         msg_Err( p_stream, "cannot find decoder" );
01457         return VLC_EGENERIC;
01458     }
01459 
01460     /*
01461      * Open encoder.
01462      * Because some info about the decoded input will only be available
01463      * once the first frame is decoded, we actually only test the availability
01464      * of the encoder here.
01465      */
01466 
01467     /* Initialization of encoder format structures */
01468     es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
01469                     id->p_decoder->fmt_out.i_codec );
01470     id->p_encoder->fmt_in.video.i_chroma = id->p_decoder->fmt_out.i_codec;
01471 
01472     /* The dimensions will be set properly later on.
01473      * Just put sensible values so we can test an encoder is available. */
01474     id->p_encoder->fmt_in.video.i_width =
01475         id->p_encoder->fmt_out.video.i_width ?
01476         id->p_encoder->fmt_out.video.i_width :
01477         id->p_decoder->fmt_in.video.i_width ?
01478         id->p_decoder->fmt_in.video.i_width : 16;
01479     id->p_encoder->fmt_in.video.i_height =
01480         id->p_encoder->fmt_out.video.i_height ?
01481         id->p_encoder->fmt_out.video.i_height :
01482         id->p_decoder->fmt_in.video.i_height ?
01483         id->p_decoder->fmt_in.video.i_height : 16;
01484     id->p_encoder->fmt_in.video.i_frame_rate = 25;
01485     id->p_encoder->fmt_in.video.i_frame_rate_base = 1;
01486 
01487     id->p_encoder->i_threads = p_sys->i_threads;
01488     id->p_encoder->p_cfg = p_sys->p_video_cfg;
01489 
01490     id->p_encoder->p_module =
01491         module_Need( id->p_encoder, "encoder", p_sys->psz_venc, VLC_TRUE );
01492     if( !id->p_encoder->p_module )
01493     {
01494         msg_Err( p_stream, "cannot find encoder" );
01495         module_Unneed( id->p_decoder, id->p_decoder->p_module );
01496         id->p_decoder->p_module = 0;
01497         return VLC_EGENERIC;
01498     }
01499 
01500     /* Close the encoder.
01501      * We'll open it only when we have the first frame. */
01502     module_Unneed( id->p_encoder, id->p_encoder->p_module );
01503     if( id->p_encoder->fmt_out.p_extra )
01504         free( id->p_encoder->fmt_out.p_extra );
01505     id->p_encoder->p_module = NULL;
01506 
01507     if( p_sys->i_threads >= 1 )
01508     {
01509         int i_priority = p_sys->b_high_priority ? VLC_THREAD_PRIORITY_OUTPUT :
01510                            VLC_THREAD_PRIORITY_VIDEO;
01511         p_sys->id_video = id;
01512         vlc_mutex_init( p_stream, &p_sys->lock_out );
01513         vlc_cond_init( p_stream, &p_sys->cond );
01514         memset( p_sys->pp_pics, 0, sizeof(p_sys->pp_pics) );
01515         p_sys->i_first_pic = 0;
01516         p_sys->i_last_pic = 0;
01517         p_sys->p_buffers = NULL;
01518         p_sys->b_die = p_sys->b_error = 0;
01519         if( vlc_thread_create( p_sys, "encoder", EncoderThread, i_priority,
01520                                VLC_FALSE ) )
01521         {
01522             msg_Err( p_stream, "cannot spawn encoder thread" );
01523             module_Unneed( id->p_decoder, id->p_decoder->p_module );
01524             id->p_decoder->p_module = 0;
01525             return VLC_EGENERIC;
01526         }
01527     }
01528 
01529     return VLC_SUCCESS;
01530 }
01531 
01532 static int transcode_video_encoder_open( sout_stream_t *p_stream,
01533                                          sout_stream_id_t *id )
01534 {
01535     sout_stream_sys_t *p_sys = p_stream->p_sys;
01536 
01537     /* Hack because of the copy packetizer which can fail to detect the
01538      * proper size (which forces us to wait until the 1st frame
01539      * is decoded) */
01540     int i_width = id->p_decoder->fmt_out.video.i_width -
01541         p_sys->i_crop_left - p_sys->i_crop_right;
01542     int i_height = id->p_decoder->fmt_out.video.i_height -
01543         p_sys->i_crop_top - p_sys->i_crop_bottom;
01544 
01545     if( id->p_encoder->fmt_out.video.i_width <= 0 &&
01546         id->p_encoder->fmt_out.video.i_height <= 0 && p_sys->f_scale )
01547     {
01548         /* Apply the scaling */
01549         id->p_encoder->fmt_out.video.i_width = i_width * p_sys->f_scale;
01550         id->p_encoder->fmt_out.video.i_height = i_height * p_sys->f_scale;
01551     }
01552     else if( id->p_encoder->fmt_out.video.i_width > 0 &&
01553              id->p_encoder->fmt_out.video.i_height <= 0 )
01554     {
01555         id->p_encoder->fmt_out.video.i_height =
01556             id->p_encoder->fmt_out.video.i_width / (double)i_width * i_height;
01557     }
01558     else if( id->p_encoder->fmt_out.video.i_width <= 0 &&
01559              id->p_encoder->fmt_out.video.i_height > 0 )
01560     {
01561         id->p_encoder->fmt_out.video.i_width =
01562             id->p_encoder->fmt_out.video.i_height / (double)i_height * i_width;
01563     }
01564 
01565     if( p_sys->i_maxwidth
01566          && id->p_encoder->fmt_out.video.i_width > p_sys->i_maxwidth )
01567         id->p_encoder->fmt_out.video.i_width = p_sys->i_maxwidth;
01568     if( p_sys->i_maxheight
01569          && id->p_encoder->fmt_out.video.i_height > p_sys->i_maxheight )
01570         id->p_encoder->fmt_out.video.i_height = p_sys->i_maxheight;
01571 
01572     /* Make sure the size is at least a multiple of 2 */
01573     id->p_encoder->fmt_out.video.i_width =
01574         (id->p_encoder->fmt_out.video.i_width + 1) >> 1 << 1;
01575     id->p_encoder->fmt_out.video.i_height =
01576         (id->p_encoder->fmt_out.video.i_height + 1) >> 1 << 1;
01577 
01578     id->p_encoder->fmt_in.video.i_width =
01579         id->p_encoder->fmt_out.video.i_width;
01580     id->p_encoder->fmt_in.video.i_height =
01581         id->p_encoder->fmt_out.video.i_height;
01582 
01583     if( !id->p_encoder->fmt_out.video.i_frame_rate ||
01584         !id->p_encoder->fmt_out.video.i_frame_rate_base )
01585     {
01586         if( id->p_decoder->fmt_out.video.i_frame_rate &&
01587             id->p_decoder->fmt_out.video.i_frame_rate_base )
01588         {
01589             id->p_encoder->fmt_out.video.i_frame_rate =
01590                 id->p_decoder->fmt_out.video.i_frame_rate;
01591             id->p_encoder->fmt_out.video.i_frame_rate_base =
01592                 id->p_decoder->fmt_out.video.i_frame_rate_base;
01593         }
01594         else
01595         {
01596             /* Pick a sensible default value */
01597             id->p_encoder->fmt_out.video.i_frame_rate = 25;
01598             id->p_encoder->fmt_out.video.i_frame_rate_base = 1;
01599         }
01600     }
01601 
01602     id->p_encoder->fmt_in.video.i_frame_rate =
01603         id->p_encoder->fmt_out.video.i_frame_rate;
01604     id->p_encoder->fmt_in.video.i_frame_rate_base =
01605         id->p_encoder->fmt_out.video.i_frame_rate_base;
01606 
01607     date_Init( &id->interpolated_pts,
01608                id->p_encoder->fmt_out.video.i_frame_rate,
01609                id->p_encoder->fmt_out.video.i_frame_rate_base );
01610 
01611     /* Check whether a particular aspect ratio was requested */
01612     if( !id->p_encoder->fmt_out.video.i_aspect )
01613     {
01614         id->p_encoder->fmt_out.video.i_aspect =
01615             id->p_decoder->fmt_out.video.i_aspect;
01616     }
01617     id->p_encoder->fmt_in.video.i_aspect =
01618         id->p_encoder->fmt_out.video.i_aspect;
01619 
01620     id->p_encoder->p_module =
01621         module_Need( id->p_encoder, "encoder", p_sys->psz_venc, VLC_TRUE );
01622     if( !id->p_encoder->p_module )
01623     {
01624         msg_Err( p_stream, "cannot find encoder" );
01625         return VLC_EGENERIC;
01626     }
01627 
01628     id->p_encoder->fmt_in.video.i_chroma = id->p_encoder->fmt_in.i_codec;
01629 
01630     /* Hack for mp2v/mp1v transcoding support */
01631     if( id->p_encoder->fmt_out.i_codec == VLC_FOURCC('m','p','1','v') ||
01632         id->p_encoder->fmt_out.i_codec == VLC_FOURCC('m','p','2','v') )
01633     {
01634         id->p_encoder->fmt_out.i_codec = VLC_FOURCC('m','p','g','v');
01635     }
01636 
01637     id->id = p_stream->p_sys->p_out->pf_add( p_stream->p_sys->p_out,
01638                                              &id->p_encoder->fmt_out );
01639     if( !id->id )
01640     {
01641         msg_Err( p_stream, "cannot add this stream" );
01642         return VLC_EGENERIC;
01643     }
01644 
01645     return VLC_SUCCESS;
01646 }
01647 
01648 static void transcode_video_close( sout_stream_t *p_stream,
01649                                    sout_stream_id_t *id )
01650 {
01651     int i, j;
01652 
01653     if( p_stream->p_sys->i_threads >= 1 )
01654     {
01655         vlc_mutex_lock( &p_stream->p_sys->lock_out );
01656         p_stream->p_sys->b_die = 1;
01657         vlc_cond_signal( &p_stream->p_sys->cond );
01658         vlc_mutex_unlock( &p_stream->p_sys->lock_out );
01659         vlc_thread_join( p_stream->p_sys );
01660         vlc_mutex_destroy( &p_stream->p_sys->lock_out );
01661         vlc_cond_destroy( &p_stream->p_sys->cond );
01662     }
01663 
01664     /* Close decoder */
01665     if( id->p_decoder->p_module )
01666         module_Unneed( id->p_decoder, id->p_decoder->p_module );
01667 
01668     if( id->p_decoder->p_owner )
01669     {
01670         /* Clean-up pictures ring buffer */
01671         for( i = 0; i < PICTURE_RING_SIZE; i++ )
01672         {
01673             if( id->p_decoder->p_owner->pp_pics[i] )
01674                 video_del_buffer( VLC_OBJECT(id->p_decoder),
01675                                   id->p_decoder->p_owner->pp_pics[i] );
01676         }
01677         free( id->p_decoder->p_owner );
01678     }
01679 
01680     /* Close encoder */
01681     if( id->p_encoder->p_module )
01682         module_Unneed( id->p_encoder, id->p_encoder->p_module );
01683 
01684     /* Close filters */
01685     for( i = 0; i < id->i_filter; i++ )
01686     {
01687         vlc_object_detach( id->pp_filter[i] );
01688         if( id->pp_filter[i]->p_module )
01689             module_Unneed( id->pp_filter[i], id->pp_filter[i]->p_module );
01690 
01691         /* Clean-up pictures ring buffer */
01692         for( j = 0; j < PICTURE_RING_SIZE; j++ )
01693         {
01694             if( id->pp_filter[i]->p_owner->pp_pics[j] )
01695                 video_del_buffer( VLC_OBJECT(id->pp_filter[i]),
01696                                   id->pp_filter[i]->p_owner->pp_pics[j] );
01697         }
01698         free( id->pp_filter[i]->p_owner );
01699 
01700         vlc_object_destroy( id->pp_filter[i] );
01701     }
01702     for( i = 0; i < id->i_vfilter; i++ )
01703     {
01704         vlc_object_detach( id->pp_vfilter[i] );
01705         if( id->pp_vfilter[i]->p_module )
01706             module_Unneed( id->pp_vfilter[i], id->pp_vfilter[i]->p_module );
01707 
01708         /* Clean-up pictures ring buffer */
01709         for( j = 0; j < PICTURE_RING_SIZE; j++ )
01710         {
01711             if( id->pp_vfilter[i]->p_owner->pp_pics[j] )
01712                 video_del_buffer( VLC_OBJECT(id->pp_vfilter[i]),
01713                                   id->pp_vfilter[i]->p_owner->pp_pics[j] );
01714         }
01715         free( id->pp_vfilter[i]->p_owner );
01716 
01717         vlc_object_destroy( id->pp_vfilter[i] );
01718     }
01719 }
01720 
01721 static int transcode_video_process( sout_stream_t *p_stream,
01722                                     sout_stream_id_t *id,
01723                                     block_t *in, block_t **out )
01724 {
01725     sout_stream_sys_t *p_sys = p_stream->p_sys;
01726     int i_duplicate = 1, i;
01727     picture_t *p_pic, *p_pic2 = NULL;
01728     *out = NULL;
01729 
01730     while( (p_pic = id->p_decoder->pf_decode_video( id->p_decoder, &in )) )
01731     {
01732         subpicture_t *p_subpic = 0;
01733 
01734         if( p_stream->p_sout->i_out_pace_nocontrol && p_sys->b_hurry_up )
01735         {
01736             mtime_t current_date = mdate();
01737             if( current_date + 50000 > p_pic->date )
01738             {
01739                 msg_Dbg( p_stream, "late picture skipped ("I64Fd")",
01740                          current_date + 50000 - p_pic->date );
01741                 p_pic->pf_release( p_pic );
01742                 continue;
01743             }
01744         }
01745 
01746         if( p_sys->b_master_sync )
01747         {
01748             mtime_t i_video_drift;
01749             mtime_t i_master_drift = p_sys->i_master_drift;
01750             mtime_t i_pts;
01751 
01752             i_pts = date_Get( &id->interpolated_pts ) + 1;
01753             if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
01754                   || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
01755             {
01756                 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
01757                 date_Set( &id->interpolated_pts, p_pic->date );
01758                 i_pts = p_pic->date + 1;
01759             }
01760             i_video_drift = p_pic->date - i_pts;
01761             i_duplicate = 1;
01762 
01763             /* Set the pts of the frame being encoded */
01764             p_pic->date = i_pts;
01765 
01766             if( i_video_drift < i_master_drift - 50000 )
01767             {
01768 #if 0
01769                 msg_Dbg( p_stream, "dropping frame (%i)",
01770                          (int)(i_video_drift - i_master_drift) );
01771 #endif
01772                 p_pic->pf_release( p_pic );
01773                 continue;
01774             }
01775             else if( i_video_drift > i_master_drift + 50000 )
01776             {
01777 #if 0
01778                 msg_Dbg( p_stream, "adding frame (%i)",
01779                          (int)(i_video_drift - i_master_drift) );
01780 #endif
01781                 i_duplicate = 2;
01782             }
01783         }
01784 
01785         if( !id->p_encoder->p_module )
01786         {
01787             if( transcode_video_encoder_open( p_stream, id ) != VLC_SUCCESS )
01788             {
01789                 p_pic->pf_release( p_pic );
01790                 transcode_video_close( p_stream, id );
01791                 id->b_transcode = VLC_FALSE;
01792                 return VLC_EGENERIC;
01793             }
01794 
01795             /* Deinterlace */
01796             if( p_stream->p_sys->b_deinterlace )
01797             {
01798                 id->pp_filter[id->i_filter] =
01799                     vlc_object_create( p_stream, VLC_OBJECT_FILTER );
01800                 vlc_object_attach( id->pp_filter[id->i_filter], p_stream );
01801 
01802                 id->pp_filter[id->i_filter]->pf_vout_buffer_new =
01803                     video_new_buffer_filter;
01804                 id->pp_filter[id->i_filter]->pf_vout_buffer_del =
01805                     video_del_buffer_filter;
01806 
01807                 id->pp_filter[id->i_filter]->fmt_in = id->p_decoder->fmt_out;
01808                 id->pp_filter[id->i_filter]->fmt_out = id->p_decoder->fmt_out;
01809                 id->pp_filter[id->i_filter]->p_cfg = p_sys->p_deinterlace_cfg;
01810                 id->pp_filter[id->i_filter]->p_module =
01811                     module_Need( id->pp_filter[id->i_filter],
01812                                  "video filter2", p_sys->psz_deinterlace, 0 );
01813                 if( id->pp_filter[id->i_filter]->p_module )
01814                 {
01815                     id->pp_filter[id->i_filter]->p_owner =
01816                         malloc( sizeof(filter_owner_sys_t) );
01817                     for( i = 0; i < PICTURE_RING_SIZE; i++ )
01818                         id->pp_filter[id->i_filter]->p_owner->pp_pics[i] = 0;
01819                     id->pp_filter[id->i_filter]->p_owner->p_sys = p_sys;
01820 
01821                     id->i_filter++;
01822                 }
01823                 else
01824                 {
01825                     msg_Dbg( p_stream, "no video filter found" );
01826                     vlc_object_detach( id->pp_filter[id->i_filter] );
01827                     vlc_object_destroy( id->pp_filter[id->i_filter] );
01828                 }
01829             }
01830 
01831             /* Check if we need a filter for chroma conversion or resizing */
01832             if( id->p_decoder->fmt_out.video.i_chroma !=
01833                 id->p_encoder->fmt_in.video.i_chroma ||
01834                 id->p_decoder->fmt_out.video.i_width !=
01835                 id->p_encoder->fmt_out.video.i_width ||
01836                 id->p_decoder->fmt_out.video.i_height !=
01837                 id->p_encoder->fmt_out.video.i_height ||
01838                 p_sys->i_crop_top > 0 || p_sys->i_crop_bottom > 0 ||
01839                 p_sys->i_crop_left > 0 || p_sys->i_crop_right > 0 )
01840             {
01841                 id->pp_filter[id->i_filter] =
01842                     vlc_object_create( p_stream, VLC_OBJECT_FILTER );
01843                 vlc_object_attach( id->pp_filter[id->i_filter], p_stream );
01844 
01845                 id->pp_filter[id->i_filter]->pf_vout_buffer_new =
01846                     video_new_buffer_filter;
01847                 id->pp_filter[id->i_filter]->pf_vout_buffer_del =
01848                     video_del_buffer_filter;
01849 
01850                 id->pp_filter[id->i_filter]->fmt_in = id->p_decoder->fmt_out;
01851                 id->pp_filter[id->i_filter]->fmt_out = id->p_encoder->fmt_in;
01852                 id->pp_filter[id->i_filter]->p_cfg = NULL;
01853                 id->pp_filter[id->i_filter]->p_module =
01854                     module_Need( id->pp_filter[id->i_filter],
01855                                  "video filter2", 0, 0 );
01856                 if( id->pp_filter[id->i_filter]->p_module )
01857                 {
01858                     id->pp_filter[id->i_filter]->p_owner =
01859                         malloc( sizeof(filter_owner_sys_t) );
01860                     for( i = 0; i < PICTURE_RING_SIZE; i++ )
01861                         id->pp_filter[id->i_filter]->p_owner->pp_pics[i] = 0;
01862                     id->pp_filter[id->i_filter]->p_owner->p_sys = p_sys;
01863 
01864                     id->i_filter++;
01865                 }
01866                 else
01867                 {
01868                     msg_Dbg( p_stream, "no video filter found" );
01869                     vlc_object_detach( id->pp_filter[id->i_filter] );
01870                     vlc_object_destroy( id->pp_filter[id->i_filter] );
01871 
01872                     p_pic->pf_release( p_pic );
01873                     transcode_video_close( p_stream, id );
01874                     id->b_transcode = VLC_FALSE;
01875                     return VLC_EGENERIC;
01876                 }
01877             }
01878 
01879             for( i = 0; i < p_sys->i_vfilters; i++ )
01880             {
01881                 id->pp_vfilter[id->i_vfilter] =
01882                     vlc_object_create( p_stream, VLC_OBJECT_FILTER );
01883                 vlc_object_attach( id->pp_vfilter[id->i_vfilter], p_stream );
01884 
01885                 id->pp_vfilter[id->i_vfilter]->pf_vout_buffer_new =
01886                     video_new_buffer_filter;
01887                 id->pp_vfilter[id->i_vfilter]->pf_vout_buffer_del =
01888                     video_del_buffer_filter;
01889 
01890                 id->pp_vfilter[id->i_vfilter]->fmt_in = id->p_encoder->fmt_in;
01891                 id->pp_vfilter[id->i_vfilter]->fmt_out = id->p_encoder->fmt_in;
01892                 id->pp_vfilter[id->i_vfilter]->p_cfg = p_sys->p_vfilters_cfg[i];
01893                 id->pp_vfilter[id->i_vfilter]->p_module =
01894                     module_Need( id->pp_vfilter[id->i_vfilter],
01895                           "video filter2", p_sys->psz_vfilters[i], 0 );
01896                 if( id->pp_vfilter[id->i_vfilter]->p_module )
01897                 {
01898                     id->pp_vfilter[id->i_vfilter]->p_owner =
01899                         malloc( sizeof(filter_owner_sys_t) );
01900                     for( i = 0; i < PICTURE_RING_SIZE; i++ )
01901                         id->pp_vfilter[id->i_vfilter]->p_owner->pp_pics[i] = 0;
01902                     id->pp_vfilter[id->i_vfilter]->p_owner->p_sys = p_sys;
01903 
01904                     id->i_vfilter++;
01905                 }
01906                 else
01907                 {
01908                     msg_Dbg( p_stream, "no video filter found" );
01909                     vlc_object_detach( id->pp_vfilter[id->i_vfilter] );
01910                     vlc_object_destroy( id->pp_vfilter[id->i_vfilter] );
01911                 }
01912             }
01913         }
01914 
01915         /* Run filter chain */
01916         for( i = 0; i < id->i_filter; i++ )
01917         {
01918             p_pic = id->pp_filter[i]->pf_video_filter(id->pp_filter[i], p_pic);
01919         }
01920 
01921         /*
01922          * Encoding
01923          */
01924 
01925         /* Check if we have a subpicture to overlay */
01926         if( p_sys->p_spu )
01927         {
01928             p_subpic = spu_SortSubpictures( p_sys->p_spu, p_pic->date );
01929             /* TODO: get another pic */
01930         }
01931 
01932         /* Overlay subpicture */
01933         if( p_subpic )
01934         {
01935             int i_scale_width, i_scale_height;
01936             video_format_t *p_fmt;
01937 
01938             i_scale_width = id->p_encoder->fmt_in.video.i_width * 1000 /
01939                 id->p_decoder->fmt_out.video.i_width;
01940             i_scale_height = id->p_encoder->fmt_in.video.i_height * 1000 /
01941                 id->p_decoder->fmt_out.video.i_height;
01942 
01943             if( p_pic->i_refcount && !id->i_filter )
01944             {
01945                 /* We can't modify the picture, we need to duplicate it */
01946                 picture_t *p_tmp = video_new_buffer_decoder( id->p_decoder );
01947                 if( p_tmp )
01948                 {
01949                     vout_CopyPicture( p_stream, p_tmp, p_pic );
01950                     p_pic->pf_release( p_pic );
01951                     p_pic = p_tmp;
01952                 }
01953             }
01954 
01955             if( id->i_filter )
01956                 p_fmt = &id->pp_filter[id->i_filter -1]->fmt_out.video;
01957             else
01958                 p_fmt = &id->p_decoder->fmt_out.video;
01959 
01960             /* FIXME (shouldn't have to be done here) */
01961             p_fmt->i_sar_num = p_fmt->i_aspect *
01962                 p_fmt->i_height / p_fmt->i_width;
01963             p_fmt->i_sar_den = VOUT_ASPECT_FACTOR;
01964 
01965             spu_RenderSubpictures( p_sys->p_spu, p_fmt, p_pic, p_pic, p_subpic,
01966                                    i_scale_width, i_scale_height );
01967         }
01968 
01969         /* Run vfilter chain */
01970         for( i = 0; i < id->i_vfilter; i++ )
01971         {
01972             p_pic = id->pp_vfilter[i]->pf_video_filter(id->pp_vfilter[i], p_pic);
01973         }
01974 
01975         if( p_sys->i_threads == 0 )
01976         {
01977             block_t *p_block;
01978             p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
01979             block_ChainAppend( out, p_block );
01980         }
01981 
01982         if( p_sys->b_master_sync )
01983         {
01984             mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
01985             if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
01986                   || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
01987             {
01988                 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
01989                 date_Set( &id->interpolated_pts, p_pic->date );
01990                 i_pts = p_pic->date + 1;
01991             }
01992             date_Increment( &id->interpolated_pts, 1 );
01993         }
01994 
01995         if( p_sys->b_master_sync && i_duplicate > 1 )
01996         {
01997             mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
01998             if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
01999                   || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
02000             {
02001                 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
02002                 date_Set( &id->interpolated_pts, p_pic->date );
02003                 i_pts = p_pic->date + 1;
02004             }
02005             date_Increment( &id->interpolated_pts, 1 );
02006 
02007             if( p_sys->i_threads >= 1 )
02008             {
02009                 /* We can't modify the picture, we need to duplicate it */
02010                 p_pic2 = video_new_buffer_decoder( id->p_decoder );
02011                 if( p_pic2 != NULL )
02012                 {
02013                     vout_CopyPicture( p_stream, p_pic2, p_pic );
02014                     p_pic2->date = i_pts;
02015                 }
02016             }
02017             else
02018             {
02019                 block_t *p_block;
02020                 p_pic->date = i_pts;
02021                 p_block = id->p_encoder->pf_encode_video(id->p_encoder, p_pic);
02022                 block_ChainAppend( out, p_block );
02023             }
02024         }
02025 
02026         if( p_sys->i_threads == 0 )
02027         {
02028             p_pic->pf_release( p_pic );
02029         }
02030         else
02031         {
02032             vlc_mutex_lock( &p_sys->lock_out );
02033             p_sys->pp_pics[p_sys->i_last_pic++] = p_pic;
02034             p_sys->i_last_pic %= PICTURE_RING_SIZE;
02035             *out = p_sys->p_buffers;
02036             p_sys->p_buffers = NULL;
02037             if( p_pic2 != NULL )
02038             {
02039                 p_sys->pp_pics[p_sys->i_last_pic++] = p_pic2;
02040                 p_sys->i_last_pic %= PICTURE_RING_SIZE;
02041             }
02042             vlc_cond_signal( &p_sys->cond );
02043             vlc_mutex_unlock( &p_sys->lock_out );
02044         }
02045 
02046     }
02047 
02048     return VLC_SUCCESS;
02049 }
02050 
02051 static int EncoderThread( sout_stream_sys_t *p_sys )
02052 {
02053     sout_stream_id_t *id = p_sys->id_video;
02054     picture_t *p_pic;
02055 
02056     while( !p_sys->b_die && !p_sys->b_error )
02057     {
02058         block_t *p_block;
02059 
02060         vlc_mutex_lock( &p_sys->lock_out );
02061         while( p_sys->i_last_pic == p_sys->i_first_pic )
02062         {
02063             vlc_cond_wait( &p_sys->cond, &p_sys->lock_out );
02064             if( p_sys->b_die || p_sys->b_error ) break;
02065         }
02066         if( p_sys->b_die || p_sys->b_error )
02067         {
02068             vlc_mutex_unlock( &p_sys->lock_out );
02069             break;
02070         }
02071 
02072         p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
02073         p_sys->i_first_pic %= PICTURE_RING_SIZE;
02074         vlc_mutex_unlock( &p_sys->lock_out );
02075 
02076         p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
02077         vlc_mutex_lock( &p_sys->lock_out );
02078         block_ChainAppend( &p_sys->p_buffers, p_block );
02079 
02080         vlc_mutex_unlock( &p_sys->lock_out );
02081 
02082         p_pic->pf_release( p_pic );
02083     }
02084 
02085     while( p_sys->i_last_pic != p_sys->i_first_pic )
02086     {
02087         p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
02088         p_sys->i_first_pic %= PICTURE_RING_SIZE;
02089 
02090         p_pic->pf_release( p_pic );
02091     }
02092 
02093     block_ChainRelease( p_sys->p_buffers );
02094 
02095     return 0;
02096 }
02097 
02098 struct picture_sys_t
02099 {
02100     vlc_object_t *p_owner;
02101 };
02102 
02103 static void video_release_buffer( picture_t *p_pic )
02104 {
02105     if( p_pic && !p_pic->i_refcount && p_pic->pf_release && p_pic->p_sys )
02106     {
02107         video_del_buffer_decoder( (decoder_t *)p_pic->p_sys->p_owner, p_pic );
02108     }
02109     else if( p_pic && p_pic->i_refcount > 0 ) p_pic->i_refcount--;
02110 }
02111 
02112 static picture_t *video_new_buffer( vlc_object_t *p_this, picture_t **pp_ring,
02113                                     sout_stream_sys_t *p_sys )
02114 {
02115     decoder_t *p_dec = (decoder_t *)p_this;
02116     picture_t *p_pic;
02117     int i;
02118 
02119     /* Find an empty space in the picture ring buffer */
02120     for( i = 0; i < PICTURE_RING_SIZE; i++ )
02121     {
02122         if( pp_ring[i] != 0 && pp_ring[i]->i_status == DESTROYED_PICTURE )
02123         {
02124             pp_ring[i]->i_status = RESERVED_PICTURE;
02125             return pp_ring[i];
02126         }
02127     }
02128     for( i = 0; i < PICTURE_RING_SIZE; i++ )
02129     {
02130         if( pp_ring[i] == 0 ) break;
02131     }
02132 
02133     if( i == PICTURE_RING_SIZE && p_sys->i_threads >= 1 )
02134     {
02135         int i_first_pic = p_sys->i_first_pic;
02136 
02137         if( p_sys->i_first_pic != p_sys->i_last_pic )
02138         {
02139             /* Encoder still has stuff to encode, wait to clear-up the list */
02140             while( p_sys->i_first_pic == i_first_pic )
02141                 msleep( 100000 );
02142         }
02143 
02144         /* Find an empty space in the picture ring buffer */
02145         for( i = 0; i < PICTURE_RING_SIZE; i++ )
02146         {
02147             if( pp_ring[i] != 0 && pp_ring[i]->i_status == DESTROYED_PICTURE )
02148             {
02149                 pp_ring[i]->i_status = RESERVED_PICTURE;
02150                 return pp_ring[i];
02151             }
02152         }
02153         for( i = 0; i < PICTURE_RING_SIZE; i++ )
02154         {
02155             if( pp_ring[i] == 0 ) break;
02156         }
02157     }
02158 
02159     if( i == PICTURE_RING_SIZE )
02160     {
02161         msg_Err( p_this, "decoder/filter is leaking pictures, "
02162                  "resetting its ring buffer" );
02163 
02164         for( i = 0; i < PICTURE_RING_SIZE; i++ )
02165         {
02166             pp_ring[i]->pf_release( pp_ring[i] );
02167         }
02168 
02169         i = 0;
02170     }
02171 
02172     p_pic = malloc( sizeof(picture_t) );
02173     p_dec->fmt_out.video.i_chroma = p_dec->fmt_out.i_codec;
02174     vout_AllocatePicture( VLC_OBJECT(p_dec), p_pic,
02175                           p_dec->fmt_out.video.i_chroma,
02176                           p_dec->fmt_out.video.i_width,
02177                           p_dec->fmt_out.video.i_height,
02178                           p_dec->fmt_out.video.i_aspect );
02179 
02180     if( !p_pic->i_planes )
02181     {
02182         free( p_pic );
02183         return 0;
02184     }
02185 
02186     p_pic->pf_release = video_release_buffer;
02187     p_pic->p_sys = malloc( sizeof(picture_sys_t) );
02188     p_pic->p_sys->p_owner = p_this;
02189     p_pic->i_status = RESERVED_PICTURE;
02190 
02191     pp_ring[i] = p_pic;
02192 
02193     return p_pic;
02194 }
02195 
02196 static picture_t *video_new_buffer_decoder( decoder_t *p_dec )
02197 {
02198     return video_new_buffer( VLC_OBJECT(p_dec),
02199                              p_dec->p_owner->pp_pics, p_dec->p_owner->p_sys );
02200 }
02201 
02202 static picture_t *video_new_buffer_filter( filter_t *p_filter )
02203 {
02204     return video_new_buffer( VLC_OBJECT(p_filter),
02205                              p_filter->p_owner->pp_pics,
02206                              p_filter->p_owner->p_sys );
02207 }
02208 
02209 static void video_del_buffer( vlc_object_t *p_this, picture_t *p_pic )
02210 {
02211     if( p_pic && p_pic->p_data_orig ) free( p_pic->p_data_orig );
02212     if( p_pic && p_pic->p_sys ) free( p_pic->p_sys );
02213     if( p_pic ) free( p_pic );
02214 }
02215 
02216 static void video_del_buffer_decoder( decoder_t *p_decoder, picture_t *p_pic )
02217 {
02218     p_pic->i_refcount = 0;
02219     p_pic->i_status = DESTROYED_PICTURE;
02220 }
02221 
02222 static void video_del_buffer_filter( filter_t *p_filter, picture_t *p_pic )
02223 {
02224     p_pic->i_refcount = 0;
02225     p_pic->i_status = DESTROYED_PICTURE;
02226 }
02227 
02228 static void video_link_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
02229 {
02230     p_pic->i_refcount++;
02231 }
02232 
02233 static void video_unlink_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
02234 {
02235     video_release_buffer( p_pic );
02236 }
02237 
02238 /*
02239  * SPU
02240  */
02241 static subpicture_t *spu_new_buffer( decoder_t * );
02242 static void spu_del_buffer( decoder_t *, subpicture_t * );
02243 
02244 static int transcode_spu_new( sout_stream_t *p_stream, sout_stream_id_t *id )
02245 {
02246     sout_stream_sys_t *p_sys = p_stream->p_sys;
02247 
02248     /*
02249      * Open decoder
02250      */
02251 
02252     /* Initialization of decoder structures */
02253     id->p_decoder->pf_spu_buffer_new = spu_new_buffer;
02254     id->p_decoder->pf_spu_buffer_del = spu_del_buffer;
02255     id->p_decoder->p_owner = (decoder_owner_sys_t *)p_stream;
02256     /* id->p_decoder->p_cfg = p_sys->p_spu_cfg; */
02257 
02258     id->p_decoder->p_module =
02259         module_Need( id->p_decoder, "decoder", "$codec", 0 );
02260 
02261     if( !id->p_decoder->p_module )
02262     {
02263         msg_Err( p_stream, "cannot find decoder" );
02264         return VLC_EGENERIC;
02265     }
02266 
02267     if( !p_sys->b_soverlay )
02268     {
02269         /*
02270          * Open encoder
02271          */
02272 
02273         /* Initialization of encoder format structures */
02274         es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
02275                         id->p_decoder->fmt_in.i_codec );
02276 
02277         id->p_encoder->p_cfg = p_sys->p_spu_cfg;
02278 
02279         id->p_encoder->p_module =
02280             module_Need( id->p_encoder, "encoder", p_sys->psz_senc, VLC_TRUE );
02281 
02282         if( !id->p_encoder->p_module )
02283         {
02284             module_Unneed( id->p_decoder, id->p_decoder->p_module );
02285             msg_Err( p_stream, "cannot find encoder" );
02286             return VLC_EGENERIC;
02287         }
02288     }
02289 
02290     if( !p_sys->p_spu )
02291     {
02292         p_sys->p_spu = spu_Create( p_stream );
02293         spu_Init( p_sys->p_spu );
02294     }
02295 
02296     return VLC_SUCCESS;
02297 }
02298 
02299 static void transcode_spu_close( sout_stream_t *p_stream, sout_stream_id_t *id)
02300 {
02301     /* Close decoder */
02302     if( id->p_decoder->p_module )
02303         module_Unneed( id->p_decoder, id->p_decoder->p_module );
02304 
02305     /* Close encoder */
02306     if( id->p_encoder->p_module )
02307         module_Unneed( id->p_encoder, id->p_encoder->p_module );
02308 }
02309 
02310 static int transcode_spu_process( sout_stream_t *p_stream,
02311                                   sout_stream_id_t *id,
02312                                   block_t *in, block_t **out )
02313 {
02314     sout_stream_sys_t *p_sys = p_stream->p_sys;
02315     subpicture_t *p_subpic;
02316     *out = NULL;
02317 
02318     p_subpic = id->p_decoder->pf_decode_sub( id->p_decoder, &in );
02319     if( !p_subpic ) return VLC_EGENERIC;
02320 
02321     if( p_sys->b_master_sync && p_sys->i_master_drift )
02322     {
02323         p_subpic->i_start -= p_sys->i_master_drift;
02324         if( p_subpic->i_stop ) p_subpic->i_stop -= p_sys->i_master_drift;
02325     }
02326 
02327     if( p_sys->b_soverlay )
02328     {
02329         spu_DisplaySubpicture( p_sys->p_spu, p_subpic );
02330     }
02331     else
02332     {
02333         block_t *p_block;
02334 
02335         p_block = id->p_encoder->pf_encode_sub( id->p_encoder, p_subpic );
02336         spu_del_buffer( id->p_decoder, p_subpic );
02337 
02338         if( p_block )
02339         {
02340             block_ChainAppend( out, p_block );
02341             return VLC_SUCCESS;
02342         }
02343     }
02344 
02345     return VLC_EGENERIC;
02346 }
02347 
02348 static subpicture_t *spu_new_buffer( decoder_t *p_dec )
02349 {
02350     sout_stream_t *p_stream = (sout_stream_t *)p_dec->p_owner;
02351     return spu_CreateSubpicture( p_stream->p_sys->p_spu );
02352 }
02353 
02354 static void spu_del_buffer( decoder_t *p_dec, subpicture_t *p_subpic )
02355 {
02356     sout_stream_t *p_stream = (sout_stream_t *)p_dec->p_owner;
02357     spu_DestroySubpicture( p_stream->p_sys->p_spu, p_subpic );
02358 }
02359 
02360 /*
02361  * OSD menu
02362  */
02363 static int transcode_osd_new( sout_stream_t *p_stream, sout_stream_id_t *id )
02364 {
02365     sout_stream_sys_t *p_sys = p_stream->p_sys;
02366     es_format_t fmt;
02367 
02368     fmt.i_cat = SPU_ES;
02369     fmt.i_id = 0xbd1f; /* pid ?? */
02370     fmt.i_group = 3;   /* pmt entry ?? */
02371     fmt.i_codec = VLC_FOURCC( 'Y', 'U', 'V', 'A' );
02372     fmt.psz_language = strdup( "osd" );
02373 
02374     id = malloc( sizeof( sout_stream_id_t ) );
02375     memset( id, 0, sizeof(sout_stream_id_t) );
02376 
02377     id->id = NULL;
02378     id->p_decoder = NULL;
02379     id->p_encoder = NULL;
02380 
02381     /* Create encoder object */
02382     id->p_encoder = vlc_object_create( p_stream, VLC_OBJECT_ENCODER );
02383     if( !id->p_encoder )
02384     {
02385         msg_Err( p_stream, "out of memory" );
02386         goto error;
02387     }
02388     vlc_object_attach( id->p_encoder, p_stream );
02389     id->p_encoder->p_module = NULL;
02390 
02391     /* Create fake destination format */
02392     es_format_Init( &id->p_encoder->fmt_out, fmt.i_cat, 0 );
02393     id->p_encoder->fmt_out.i_id    = fmt.i_id;
02394     id->p_encoder->fmt_out.i_group = fmt.i_group;
02395     id->p_encoder->fmt_out.psz_language = strdup( fmt.psz_language );
02396     
02397     if( p_sys->i_osdcodec != 0 || p_sys->psz_osdenc )
02398     {
02399         msg_Dbg( p_stream, "creating osdmenu transcoding from fcc=`%4.4s' "
02400                  "to fcc=`%4.4s'", (char*)&fmt.i_codec,
02401                  (char*)&p_sys->i_osdcodec );
02402 
02403         /* Complete destination format */
02404         id->p_encoder->fmt_out.i_codec = p_sys->i_osdcodec;
02405         
02406         /*
02407          * Open encoder
02408          */
02409         
02410         /* Initialization of encoder format structures */
02411         es_format_Init( &id->p_encoder->fmt_in, fmt.i_cat, fmt.i_codec );
02412         id->p_encoder->fmt_in.psz_language = strdup( fmt.psz_language );
02413 
02414         id->p_encoder->p_cfg = p_sys->p_osd_cfg;
02415 
02416         id->p_encoder->p_module =
02417             module_Need( id->p_encoder, "encoder", p_sys->psz_osdenc, VLC_TRUE );
02418 
02419         if( !id->p_encoder->p_module )
02420         {
02421             msg_Err( p_stream, "cannot find encoder" );
02422             goto error;
02423         }
02424         
02425         /* open output stream */
02426         id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->p_encoder->fmt_out );
02427         id->b_transcode = VLC_TRUE;
02428 
02429         if( !id->id ) goto error;
02430     }
02431     else
02432     {
02433         msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')",
02434                  (char*)&fmt.i_codec );
02435         id->id = p_sys->p_out->pf_add( p_sys->p_out, &fmt );
02436         id->b_transcode = VLC_FALSE;
02437 
02438         if( !id->id ) goto error;
02439     }
02440 
02441     p_sys->id_osd = id;
02442     p_sys->b_es_osd = VLC_TRUE;
02443 
02444     if( !p_sys->p_spu )
02445     {
02446         p_sys->p_spu = spu_Create( p_stream );
02447         if( spu_Init( p_sys->p_spu ) != VLC_SUCCESS )
02448             msg_Err( p_sys, "spu initialisation failed" );
02449     }
02450     
02451     if( fmt.psz_language )
02452         free( fmt.psz_language );
02453         
02454     return VLC_SUCCESS;
02455     
02456  error:
02457     msg_Err( p_stream, "starting osd encoding thread failed" );
02458     if( id->p_encoder->p_module )
02459             module_Unneed( id->p_encoder, id->p_encoder->p_module );
02460     if( id->p_encoder )
02461     {
02462         vlc_object_detach( id->p_encoder );
02463         vlc_object_destroy( id->p_encoder );
02464     }
02465     if( fmt.psz_language ) free( fmt.psz_language );
02466     if( id ) free( id );
02467     p_sys->id_osd = NULL;
02468     p_sys->b_es_osd = VLC_FALSE;
02469     return VLC_EGENERIC;
02470 }
02471     
02472 static void transcode_osd_close( sout_stream_t *p_stream, sout_stream_id_t *id)
02473 {    
02474     sout_stream_sys_t *p_sys = p_stream->p_sys;
02475     
02476     /* Close encoder */
02477     if( p_sys->b_es_osd && id )
02478     {
02479         if( id->p_encoder->p_module )
02480             module_Unneed( id->p_encoder, id->p_encoder->p_module );
02481         
02482         if( id->id ) p_sys->p_out->pf_del( p_sys->p_out, id->id );
02483     
02484         if( id->p_encoder )
02485         {
02486             vlc_object_detach( id->p_encoder );
02487             vlc_object_destroy( id->p_encoder );
02488         }
02489     }
02490     p_sys->b_es_osd = VLC_FALSE;
02491     if( id ) free( id );
02492 }
02493 
02494 static int transcode_osd_process( sout_stream_t *p_stream,
02495                                   sout_stream_id_t *id,
02496                                   block_t *in, block_t **out )
02497 {
02498     sout_stream_sys_t *p_sys = p_stream->p_sys;
02499     subpicture_t *p_subpic = NULL;
02500     
02501     /* Check if we have a subpicture to send */
02502     if( p_sys->p_spu && in->i_dts > 0)
02503     {
02504         p_subpic = spu_SortSubpictures( p_sys->p_spu, in->i_dts );
02505     }
02506     else
02507     {
02508         msg_Warn( p_stream, "spu channel not initialized, doing it now" );
02509         if( !p_sys->p_spu )
02510         {
02511             p_sys->p_spu = spu_Create( p_stream );
02512             if( spu_Init( p_sys->p_spu ) != VLC_SUCCESS )
02513                 msg_Err( p_stream, "spu initialisation failed" );
02514         }
02515     }
02516         
02517     if( p_subpic )
02518     {
02519         block_t *p_block = NULL;
02520         
02521         if( p_sys->b_master_sync && p_sys->i_master_drift )
02522         {
02523             p_subpic->i_start -= p_sys->i_master_drift;
02524             if( p_subpic->i_stop ) p_subpic->i_stop -= p_sys->i_master_drift;
02525         }
02526     
02527         p_block = p_sys->id_osd->p_encoder->pf_encode_sub( p_sys->id_osd->p_encoder, p_subpic );
02528         if( p_block )
02529         {
02530             p_block->i_dts = p_block->i_pts = in->i_dts;
02531             block_ChainAppend( out, p_block );
02532             if( *out )
02533             {
02534                 if( p_sys->p_out->pf_send( p_sys->p_out, p_sys->id_osd->id, *out ) == VLC_SUCCESS )
02535                     spu_DestroySubpicture( p_sys->p_spu, p_subpic );
02536             }            
02537             return VLC_SUCCESS;            
02538         }
02539     }
02540     return VLC_EGENERIC;
02541 }

Generated on Tue Dec 20 10:14:50 2005 for vlc-0.8.4a by  doxygen 1.4.2