/*****************************************************************************
* Preamble
*****************************************************************************/
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-
#include <vlc/vlc.h>
-#include <vlc/input.h>
-#include <vlc/sout.h>
-#include <vlc/vout.h>
-#include <vlc/decoder.h>
+#include <vlc_input.h>
+#include <vlc_sout.h>
+#include <vlc_aout.h>
+#include <vlc_vout.h>
+#include <vlc_codec.h>
+#include <vlc_block.h>
#include <vlc_filter.h>
#include <vlc_osd.h>
+#include <math.h>
+
#define MASTER_SYNC_MAX_DRIFT 100000
+/* FIXME Ugly */
+#include "../../src/input/input_internal.h"
+
/*****************************************************************************
* Module descriptor
*****************************************************************************/
"associated options)." )
#define SCODEC_TEXT N_("Destination subtitles codec")
#define SCODEC_LONGTEXT N_( \
- "This is the subtitles coded that will be used." )
+ "This is the subtitles codec that will be used." )
#define SFILTER_TEXT N_("Overlays")
#define SFILTER_LONGTEXT N_( \
#define HURRYUP_LONGTEXT N_( "The transcoder will drop frames if your CPU " \
"can't keep up with the encoding rate." )
-static char *ppsz_deinterlace_type[] =
+static const char *ppsz_deinterlace_type[] =
{
"deinterlace", "ffmpeg-deinterlace"
};
MAXWIDTH_LONGTEXT, VLC_TRUE );
add_integer( SOUT_CFG_PREFIX "maxheight", 0, NULL, MAXHEIGHT_TEXT,
MAXHEIGHT_LONGTEXT, VLC_TRUE );
- add_module_list_cat( SOUT_CFG_PREFIX "vfilter", SUBCAT_VIDEO_VFILTER2,
+ add_module_list( SOUT_CFG_PREFIX "vfilter", "video filter2",
NULL, NULL,
VFILTER_TEXT, VFILTER_LONGTEXT, VLC_FALSE );
static const char *ppsz_sout_options[] = {
"venc", "vcodec", "vb", "croptop", "cropbottom", "cropleft", "cropright",
- "paddtop", "paddbottom", "paddleft", "paddright",
- "canvas-width", "canvas-height", "canvas-aspect",
+ "paddtop", "paddbottom", "paddleft", "paddright",
+ "canvas-width", "canvas-height", "canvas-aspect",
"scale", "fps", "width", "height", "vfilter", "deinterlace",
"deinterlace-module", "threads", "hurry-up", "aenc", "acodec", "ab",
"afilter", "samplerate", "channels", "senc", "scodec", "soverlay",
/* Audio */
vlc_fourcc_t i_acodec; /* codec audio (0 if not transcode) */
char *psz_aenc;
- sout_cfg_t *p_audio_cfg;
+ config_chain_t *p_audio_cfg;
int i_sample_rate;
int i_channels;
int i_abitrate;
char *psz_afilters[TRANSCODE_FILTERS];
- sout_cfg_t *p_afilters_cfg[TRANSCODE_FILTERS];
+ config_chain_t *p_afilters_cfg[TRANSCODE_FILTERS];
int i_afilters;
/* Video */
vlc_fourcc_t i_vcodec; /* codec video (0 if not transcode) */
char *psz_venc;
- sout_cfg_t *p_video_cfg;
+ config_chain_t *p_video_cfg;
int i_vbitrate;
double f_scale;
double f_fps;
unsigned int i_height, i_maxheight;
vlc_bool_t b_deinterlace;
char *psz_deinterlace;
- sout_cfg_t *p_deinterlace_cfg;
+ config_chain_t *p_deinterlace_cfg;
int i_threads;
vlc_bool_t b_high_priority;
vlc_bool_t b_hurry_up;
char *psz_vfilters[TRANSCODE_FILTERS];
- sout_cfg_t *p_vfilters_cfg[TRANSCODE_FILTERS];
+ config_chain_t *p_vfilters_cfg[TRANSCODE_FILTERS];
int i_vfilters;
int i_crop_top;
vlc_fourcc_t i_scodec; /* codec spu (0 if not transcode) */
char *psz_senc;
vlc_bool_t b_soverlay;
- sout_cfg_t *p_spu_cfg;
+ config_chain_t *p_spu_cfg;
spu_t *p_spu;
/* OSD Menu */
sout_stream_id_t *id_osd; /* extension for streaming OSD menus */
vlc_fourcc_t i_osdcodec; /* codec osd menu (0 if not transcode) */
char *psz_osdenc;
- sout_cfg_t *p_osd_cfg;
+ config_chain_t *p_osd_cfg;
vlc_bool_t b_es_osd; /* VLC_TRUE when osd es is registered */
vlc_bool_t b_sout_osd;
p_sys->i_master_drift = 0;
- sout_CfgParse( p_stream, SOUT_CFG_PREFIX, ppsz_sout_options,
+ config_ChainParse( p_stream, SOUT_CFG_PREFIX, ppsz_sout_options,
p_stream->p_cfg );
/* Audio transcoding parameters */
if( val.psz_string && *val.psz_string )
{
char *psz_next;
- psz_next = sout_CfgCreate( &p_sys->psz_aenc, &p_sys->p_audio_cfg,
- val.psz_string );
+ psz_next = config_ChainCreate( &p_sys->psz_aenc, &p_sys->p_audio_cfg,
+ val.psz_string );
if( psz_next ) free( psz_next );
}
if( val.psz_string ) free( val.psz_string );
while( (psz_parser != NULL) && (*psz_parser != '\0')
&& (p_sys->i_afilters < TRANSCODE_FILTERS) )
{
- psz_parser = sout_CfgCreate(
+ psz_parser = config_ChainCreate(
&p_sys->psz_afilters[p_sys->i_afilters],
&p_sys->p_afilters_cfg[p_sys->i_afilters],
psz_parser );
if( val.psz_string && *val.psz_string )
{
char *psz_next;
- psz_next = sout_CfgCreate( &p_sys->psz_venc, &p_sys->p_video_cfg,
+ psz_next = config_ChainCreate( &p_sys->psz_venc, &p_sys->p_video_cfg,
val.psz_string );
if( psz_next ) free( psz_next );
}
while( (psz_parser != NULL) && (*psz_parser != '\0')
&& (p_sys->i_vfilters < TRANSCODE_FILTERS) )
{
- psz_parser = sout_CfgCreate(
+ psz_parser = config_ChainCreate(
&p_sys->psz_vfilters[p_sys->i_vfilters],
&p_sys->p_vfilters_cfg[p_sys->i_vfilters],
psz_parser );
if( val.psz_string && *val.psz_string )
{
char *psz_next;
- psz_next = sout_CfgCreate( &p_sys->psz_deinterlace,
+ psz_next = config_ChainCreate( &p_sys->psz_deinterlace,
&p_sys->p_deinterlace_cfg,
val.psz_string );
if( psz_next ) free( psz_next );
if( val.psz_string && *val.psz_string )
{
char *psz_next;
- psz_next = sout_CfgCreate( &p_sys->psz_senc, &p_sys->p_spu_cfg,
+ psz_next = config_ChainCreate( &p_sys->psz_senc, &p_sys->p_spu_cfg,
val.psz_string );
if( psz_next ) free( psz_next );
}
vlc_value_t osd_val;
char *psz_next;
- psz_next = sout_CfgCreate( &p_sys->psz_osdenc,
+ psz_next = config_ChainCreate( &p_sys->psz_osdenc,
&p_sys->p_osd_cfg, strdup( "dvbsub") );
if( psz_next ) free( psz_next );
sout_StreamDelete( p_sys->p_out );
+ while( p_sys->i_afilters )
+ {
+ p_sys->i_afilters--;
+ if( p_sys->psz_afilters[p_sys->i_afilters] )
+ free( p_sys->psz_afilters[p_sys->i_afilters] );
+ if( p_sys->p_afilters_cfg[p_sys->i_afilters] )
+ free( p_sys->p_afilters_cfg[p_sys->i_afilters] );
+ }
+
while( p_sys->p_audio_cfg != NULL )
{
- sout_cfg_t *p_next = p_sys->p_audio_cfg->p_next;
+ config_chain_t *p_next = p_sys->p_audio_cfg->p_next;
if( p_sys->p_audio_cfg->psz_name )
free( p_sys->p_audio_cfg->psz_name );
}
if( p_sys->psz_aenc ) free( p_sys->psz_aenc );
+ while( p_sys->i_vfilters )
+ {
+ p_sys->i_vfilters--;
+ if( p_sys->psz_vfilters[p_sys->i_vfilters] )
+ free( p_sys->psz_vfilters[p_sys->i_vfilters] );
+ if( p_sys->p_vfilters_cfg[p_sys->i_vfilters] )
+ free( p_sys->p_vfilters_cfg[p_sys->i_vfilters] );
+ }
+
while( p_sys->p_video_cfg != NULL )
{
- sout_cfg_t *p_next = p_sys->p_video_cfg->p_next;
+ config_chain_t *p_next = p_sys->p_video_cfg->p_next;
if( p_sys->p_video_cfg->psz_name )
free( p_sys->p_video_cfg->psz_name );
while( p_sys->p_deinterlace_cfg != NULL )
{
- sout_cfg_t *p_next = p_sys->p_deinterlace_cfg->p_next;
+ config_chain_t *p_next = p_sys->p_deinterlace_cfg->p_next;
if( p_sys->p_deinterlace_cfg->psz_name )
free( p_sys->p_deinterlace_cfg->psz_name );
while( p_sys->p_spu_cfg != NULL )
{
- sout_cfg_t *p_next = p_sys->p_spu_cfg->p_next;
+ config_chain_t *p_next = p_sys->p_spu_cfg->p_next;
if( p_sys->p_spu_cfg->psz_name )
free( p_sys->p_spu_cfg->psz_name );
while( p_sys->p_osd_cfg != NULL )
{
- sout_cfg_t *p_next = p_sys->p_osd_cfg->p_next;
+ config_chain_t *p_next = p_sys->p_osd_cfg->p_next;
if( p_sys->p_osd_cfg->psz_name )
free( p_sys->p_osd_cfg->psz_name );
{
vlc_object_detach( id->p_decoder );
vlc_object_destroy( id->p_decoder );
+ id->p_decoder = NULL;
}
if( id->p_encoder )
vlc_object_detach( id->p_encoder );
es_format_Clean( &id->p_encoder->fmt_out );
vlc_object_destroy( id->p_encoder );
+ id->p_encoder = NULL;
}
free( id );
{
vlc_object_detach( id->p_decoder );
vlc_object_destroy( id->p_decoder );
+ id->p_decoder = NULL;
}
if( id->p_encoder )
vlc_object_detach( id->p_encoder );
es_format_Clean( &id->p_encoder->fmt_out );
vlc_object_destroy( id->p_encoder );
+ id->p_encoder = NULL;
}
-
free( id );
return VLC_SUCCESS;
if( psz_name )
p_filter->p_cfg = p_sys->p_afilters_cfg[id->i_ufilter];
- p_filter->p_module = module_Need( p_filter, "audio filter2", psz_name, 0 );
+ p_filter->p_module = module_Need( p_filter, "audio filter2", psz_name,
+ VLC_TRUE );
if( p_filter->p_module )
{
p_filter->fmt_out.audio.i_bitspersample =
id->p_decoder->p_module =
module_Need( id->p_decoder, "decoder", "$codec", 0 );
-
if( !id->p_decoder->p_module )
{
msg_Err( p_stream, "cannot find decoder" );
return VLC_EGENERIC;
}
- id->p_decoder->fmt_out.audio.i_bitspersample =
+ id->p_decoder->fmt_out.audio.i_bitspersample =
audio_BitsPerSample( id->p_decoder->fmt_out.i_codec );
fmt_last = id->p_decoder->fmt_out;
- /* FIX decoders so we don't have to do this */
- fmt_last.audio.i_rate = id->p_decoder->fmt_in.audio.i_rate;
+ /* Fix AAC SBR changing number of channels and sampling rate */
+ if( !(id->p_decoder->fmt_in.i_codec == VLC_FOURCC('m','p','4','a') &&
+ fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate &&
+ fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels) )
+ fmt_last.audio.i_rate = id->p_decoder->fmt_in.audio.i_rate;
/*
* Open encoder
id->p_encoder->fmt_in.audio.i_format = id->p_decoder->fmt_out.i_codec;
/* Initialization of encoder format structures */
- es_format_Init( &id->p_encoder->fmt_in, AUDIO_ES, AOUT_FMT_S16_NE );
- id->p_encoder->fmt_in.audio.i_format = AOUT_FMT_S16_NE;
+ es_format_Init( &id->p_encoder->fmt_in, AUDIO_ES, VLC_FOURCC('f','l','3','2') );
+ id->p_encoder->fmt_in.audio.i_format = VLC_FOURCC('f','l','3','2');
+
id->p_encoder->fmt_in.audio.i_rate = id->p_encoder->fmt_out.audio.i_rate;
id->p_encoder->fmt_in.audio.i_physical_channels =
id->p_encoder->fmt_out.audio.i_physical_channels;
audio_BitsPerSample( id->p_encoder->fmt_in.i_codec );
id->p_encoder->p_cfg = p_stream->p_sys->p_audio_cfg;
-
id->p_encoder->p_module =
module_Need( id->p_encoder, "encoder", p_sys->psz_aenc, VLC_TRUE );
if( !id->p_encoder->p_module )
{
msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_aenc );
module_Unneed( id->p_decoder, id->p_decoder->p_module );
- id->p_decoder->p_module = 0;
+ id->p_decoder->p_module = NULL;
return VLC_EGENERIC;
}
id->p_encoder->fmt_in.audio.i_format = id->p_encoder->fmt_in.i_codec;
id->p_encoder->fmt_in.audio.i_bitspersample =
audio_BitsPerSample( id->p_encoder->fmt_in.i_codec );
+ /* Fix AAC SBR changing number of channels and sampling rate */
+ if( id->p_decoder->fmt_in.i_codec == VLC_FOURCC('m','p','4','a') &&
+ fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate &&
+ fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels )
+ {
+ id->p_encoder->fmt_in.audio.i_rate = fmt_last.audio.i_rate;
+ id->p_encoder->fmt_out.audio.i_rate = fmt_last.audio.i_rate;
+ }
+
/* Load conversion filters */
if( fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels ||
fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate )
if( fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels )
{
- msg_Err( p_stream, "no audio filter found for mixing from"
- " %i to %i channels", fmt_last.audio.i_channels,
- id->p_encoder->fmt_in.audio.i_channels );
-#if 0
- /* FIXME : this might work, but only if the encoder is restarted */
+#if 1
+ module_Unneed( id->p_encoder, id->p_encoder->p_module );
+ id->p_encoder->p_module = NULL;
+
+ /* This might work, but only if the encoder is restarted */
id->p_encoder->fmt_in.audio.i_channels = fmt_last.audio.i_channels;
id->p_encoder->fmt_out.audio.i_channels = fmt_last.audio.i_channels;
id->p_encoder->fmt_out.audio.i_physical_channels =
id->p_encoder->fmt_out.audio.i_original_channels =
fmt_last.audio.i_physical_channels;
+
+ msg_Dbg( p_stream, "number of audio channels for mixing changed, "
+ "trying to reopen the encoder for mixing %i to %i channels",
+ fmt_last.audio.i_channels,
+ id->p_encoder->fmt_in.audio.i_channels );
+
+ /* reload encoder */
+ id->p_encoder->p_cfg = p_stream->p_sys->p_audio_cfg;
+ id->p_encoder->p_module =
+ module_Need( id->p_encoder, "encoder", p_sys->psz_aenc, VLC_TRUE );
+ if( !id->p_encoder->p_module )
+ {
+ msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_aenc );
+ transcode_audio_close( p_stream, id );
+ return VLC_EGENERIC;
+ }
+ id->p_encoder->fmt_in.audio.i_format = id->p_encoder->fmt_in.i_codec;
+ id->p_encoder->fmt_in.audio.i_bitspersample =
+ audio_BitsPerSample( id->p_encoder->fmt_in.i_codec );
#else
+ msg_Err( p_stream, "no audio filter found for mixing from"
+ " %i to %i channels", fmt_last.audio.i_channels,
+ id->p_encoder->fmt_in.audio.i_channels );
+
transcode_audio_close( p_stream, id );
return VLC_EGENERIC;
#endif
/* Close decoder */
if( id->p_decoder->p_module )
module_Unneed( id->p_decoder, id->p_decoder->p_module );
- id->p_decoder->p_module = 0;
+ id->p_decoder->p_module = NULL;
/* Close encoder */
if( id->p_encoder->p_module )
module_Unneed( id->p_encoder, id->p_encoder->p_module );
- id->p_encoder->p_module = 0;
+ id->p_encoder->p_module = NULL;
/* Close filters */
for( i = 0; i < id->i_filter; i++ )
&in )) )
{
if( p_input )
- stats_UpdateInteger( p_input, p_input->counters.p_decoded_audio,
+ stats_UpdateInteger( p_input, p_input->p->counters.p_decoded_audio,
1, NULL );
if( p_sys->b_master_sync )
{
}
p_buffer = malloc( sizeof(aout_buffer_t) );
+ p_buffer->b_discontinuity = VLC_FALSE;
p_buffer->pf_release = audio_release_buffer;
p_buffer->p_sys = p_block = block_New( p_dec, i_size );
* We'll open it only when we have the first frame. */
module_Unneed( id->p_encoder, id->p_encoder->p_module );
if( id->p_encoder->fmt_out.p_extra )
+ {
free( id->p_encoder->fmt_out.p_extra );
+ id->p_encoder->fmt_out.p_extra = NULL;
+ id->p_encoder->fmt_out.i_extra = 0;
+ }
id->p_encoder->p_module = NULL;
if( p_sys->i_threads >= 1 )
if( p_stream->p_sys->i_threads >= 1 )
{
vlc_mutex_lock( &p_stream->p_sys->lock_out );
- p_stream->p_sys->b_die = 1;
+ vlc_object_kill( p_stream->p_sys );
vlc_cond_signal( &p_stream->p_sys->cond );
vlc_mutex_unlock( &p_stream->p_sys->lock_out );
vlc_thread_join( p_stream->p_sys );
while( (p_pic = id->p_decoder->pf_decode_video( id->p_decoder, &in )) )
{
- subpicture_t *p_subpic = 0;
+ subpicture_t *p_subpic = NULL;
if( p_input )
- stats_UpdateInteger( p_input, p_input->counters.p_decoded_video,
+ stats_UpdateInteger( p_input, p_input->p->counters.p_decoded_video,
1, NULL );
if( p_stream->p_sout->i_out_pace_nocontrol && p_sys->b_hurry_up )
/* Set the pts of the frame being encoded */
p_pic->date = i_pts;
- if( i_video_drift < i_master_drift - 50000 )
+ if( i_video_drift < (i_master_drift - 50000) )
{
#if 0
msg_Dbg( p_stream, "dropping frame (%i)",
p_pic->pf_release( p_pic );
continue;
}
- else if( i_video_drift > i_master_drift + 50000 )
+ else if( i_video_drift > (i_master_drift + 50000) )
{
#if 0
msg_Dbg( p_stream, "adding frame (%i)",
id->pp_filter[id->i_filter]->p_cfg = p_sys->p_deinterlace_cfg;
id->pp_filter[id->i_filter]->p_module =
module_Need( id->pp_filter[id->i_filter],
- "video filter2", p_sys->psz_deinterlace, 0 );
+ "video filter2", p_sys->psz_deinterlace,
+ VLC_TRUE );
if( id->pp_filter[id->i_filter]->p_module )
{
id->pp_filter[id->i_filter]->p_owner =
id->pp_ufilter[id->i_ufilter]->p_cfg = p_sys->p_vfilters_cfg[i];
id->pp_ufilter[id->i_ufilter]->p_module =
module_Need( id->pp_ufilter[id->i_ufilter],
- "video filter2", p_sys->psz_vfilters[i], 0 );
+ "video filter2", p_sys->psz_vfilters[i], VLC_TRUE );
if( id->pp_ufilter[id->i_ufilter]->p_module )
{
id->pp_ufilter[id->i_ufilter]->p_owner =
msg_Dbg( p_stream, "no video filter found" );
vlc_object_detach( id->pp_ufilter[id->i_ufilter] );
vlc_object_destroy( id->pp_ufilter[id->i_ufilter] );
+ id->pp_ufilter[id->i_ufilter] = NULL;
}
}
}
/* Check if we have a subpicture to overlay */
if( p_sys->p_spu )
{
- p_subpic = spu_SortSubpictures( p_sys->p_spu, p_pic->date );
+ p_subpic = spu_SortSubpictures( p_sys->p_spu, p_pic->date,
+ VLC_FALSE /* Fixme: check if stream is paused */ );
/* TODO: get another pic */
}
/* Run user specified filter chain */
for( i = 0; i < id->i_ufilter; i++ )
{
- p_pic = id->pp_ufilter[i]->pf_video_filter(id->pp_ufilter[i], p_pic);
+ p_pic = id->pp_ufilter[i]->pf_video_filter( id->pp_ufilter[i],
+ p_pic );
}
if( p_sys->i_threads == 0 )
if( p_sys->b_master_sync && i_duplicate > 1 )
{
mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
- if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
- || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
+ if( (p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT)
+ || ((p_pic->date - i_pts) < -MASTER_SYNC_MAX_DRIFT) )
{
msg_Dbg( p_stream, "drift is too high, resetting master sync" );
date_Set( &id->interpolated_pts, p_pic->date );
/* Check if we have a subpicture to send */
if( p_sys->p_spu && in->i_dts > 0)
{
- p_subpic = spu_SortSubpictures( p_sys->p_spu, in->i_dts );
+ p_subpic = spu_SortSubpictures( p_sys->p_spu, in->i_dts, VLC_FALSE );
}
else
{