# include "config.h"
#endif
-#include <vlc_common.h>
-
#include <stdio.h>
+#include <assert.h>
+#include <vlc_common.h>
#include <vlc_input.h>
#include <vlc_es_out.h>
#include "input_internal.h"
+#include "../stream_output/stream_output.h"
+
#include <vlc_iso_lang.h>
/* FIXME we should find a better way than including that */
#include "../text/iso-639_def.h"
char *psz_language_code;
decoder_t *p_dec;
+ decoder_t *p_dec_record;
/* Fields for Video with CC */
bool pb_cc_present[4];
/* Rate used to rescale ES ts */
int i_rate;
+
+ /* Record */
+ sout_instance_t *p_sout_record;
};
static es_out_id_t *EsOutAdd ( es_out_t *, es_format_t * );
p_sys->i_rate = i_rate;
+ p_sys->p_sout_record = NULL;
+
return out;
}
es_out_sys_t *p_sys = out->p_sys;
int i;
+ if( p_sys->p_sout_record )
+ input_EsOutSetRecord( out, false );
+
for( i = 0; i < p_sys->i_es; i++ )
{
if( p_sys->es[i]->p_dec )
- {
input_DecoderDelete( p_sys->es[i]->p_dec );
- }
+
free( p_sys->es[i]->psz_language );
free( p_sys->es[i]->psz_language_code );
es_format_Clean( &p_sys->es[i]->fmt );
free( p_sys->ppsz_sub_language[i] );
free( p_sys->ppsz_sub_language );
}
-
free( p_sys->es );
/* FIXME duplicate work EsOutProgramDel (but we cannot use it) add a EsOutProgramClean ? */
/* Send a dummy block to let decoder know that
* there is a discontinuity */
if( es->p_dec && ( !b_audio || es->fmt.i_cat == AUDIO_ES ) )
+ {
input_DecoderDiscontinuity( es->p_dec, b_flush );
+ if( es->p_dec_record )
+ input_DecoderDiscontinuity( es->p_dec_record, b_flush );
+ }
}
}
void input_EsOutChangeRate( es_out_t *out, int i_rate )
input_ClockSetRate( &p_sys->pgrm[i]->clock, i_rate );
}
+int input_EsOutSetRecord( es_out_t *out, bool b_record )
+{
+ es_out_sys_t *p_sys = out->p_sys;
+ input_thread_t *p_input = p_sys->p_input;
+
+ assert( ( b_record && !p_sys->p_sout_record ) || ( !b_record && p_sys->p_sout_record ) );
+
+ if( b_record )
+ {
+ char *psz_path = var_CreateGetString( p_input, "input-record-path" );
+ if( !psz_path || *psz_path == '\0' )
+ {
+ free( psz_path );
+ psz_path = strdup( config_GetHomeDir() );
+ }
+
+ char *psz_sout = NULL; // TODO conf
+
+ if( !psz_sout && psz_path )
+ {
+ char *psz_file = input_CreateFilename( VLC_OBJECT(p_input), psz_path, INPUT_RECORD_PREFIX, NULL );
+ if( psz_file )
+ {
+ if( asprintf( &psz_sout, "#record{dst-prefix='%s'}", psz_file ) < 0 )
+ psz_sout = NULL;
+ free( psz_file );
+ }
+ }
+ free( psz_path );
+
+ if( !psz_sout )
+ return VLC_EGENERIC;
+
+#ifdef ENABLE_SOUT
+ p_sys->p_sout_record = sout_NewInstance( p_input, psz_sout );
+#endif
+ free( psz_sout );
+
+ if( !p_sys->p_sout_record )
+ return VLC_EGENERIC;
+
+ for( int i = 0; i < p_sys->i_es; i++ )
+ {
+ es_out_id_t *p_es = p_sys->es[i];
+
+ if( !p_es->p_dec || p_es->p_master )
+ continue;
+
+ p_es->p_dec_record = input_DecoderNew( p_input, &p_es->fmt, p_sys->p_sout_record );
+ }
+ }
+ else
+ {
+ for( int i = 0; i < p_sys->i_es; i++ )
+ {
+ es_out_id_t *p_es = p_sys->es[i];
+
+ if( !p_es->p_dec_record )
+ continue;
+
+ input_DecoderDelete( p_es->p_dec_record );
+ p_es->p_dec_record = NULL;
+ }
+#ifdef ENABLE_SOUT
+ sout_DeleteInstance( p_sys->p_sout_record );
+#endif
+ p_sys->p_sout_record = NULL;
+ }
+
+ return VLC_SUCCESS;
+}
void input_EsOutSetDelay( es_out_t *out, int i_cat, int64_t i_delay )
{
es_out_sys_t *p_sys = out->p_sys;
if( es->p_dec && !input_DecoderEmpty( es->p_dec ) )
return false;
+ if( es->p_dec_record && !input_DecoderEmpty( es->p_dec_record ) )
+ return false;
}
return true;
}
{
char *psz = NULL;
if( p_pgrm->psz_name )
- asprintf( &psz, _("%s [%s %d]"), p_pgrm->psz_name, _("Program"), p_pgrm->i_id );
+ {
+ if( asprintf( &psz, _("%s [%s %d]"), p_pgrm->psz_name, _("Program"), p_pgrm->i_id ) == -1 )
+ return NULL;
+ }
else
- asprintf( &psz, "%s %d", _("Program"), p_pgrm->i_id );
+ {
+ if( asprintf( &psz, "%s %d", _("Program"), p_pgrm->i_id ) == -1 )
+ return NULL;
+ }
return psz;
}
if( psz_provider && *psz_provider )
{
- asprintf( &text.psz_string, "%s [%s]", psz_title, psz_provider );
- var_Change( p_input, "program", VLC_VAR_ADDCHOICE, &val, &text );
- free( text.psz_string );
+ if( asprintf( &text.psz_string, "%s [%s]", psz_title, psz_provider ) != -1 )
+ {
+ var_Change( p_input, "program", VLC_VAR_ADDCHOICE, &val, &text );
+ free( text.psz_string );
+ }
}
else
{
es->psz_language = LanguageGetName( fmt->psz_language ); /* remember so we only need to do it once */
es->psz_language_code = LanguageGetCode( fmt->psz_language );
es->p_dec = NULL;
+ es->p_dec_record = NULL;
for( i = 0; i < 4; i++ )
es->pb_cc_present[i] = false;
- es->p_master = false;
+ es->p_master = NULL;
if( es->p_pgrm == p_sys->p_pgrm )
EsOutESVarUpdate( out, es, false );
return es->p_dec != NULL;
}
}
+static void EsCreateDecoder( es_out_t *out, es_out_id_t *p_es )
+{
+ es_out_sys_t *p_sys = out->p_sys;
+ input_thread_t *p_input = p_sys->p_input;
+
+ p_es->p_dec = input_DecoderNew( p_input, &p_es->fmt, p_input->p->p_sout );
+ if( p_es->p_dec && !p_es->p_master && p_sys->p_sout_record )
+ p_es->p_dec_record = input_DecoderNew( p_input, &p_es->fmt, p_sys->p_sout_record );
+}
+static void EsDestroyDecoder( es_out_t *out, es_out_id_t *p_es )
+{
+ es_out_sys_t *p_sys = out->p_sys;
+
+ if( !p_es->p_dec )
+ return;
+
+ input_DecoderDelete( p_es->p_dec );
+ p_es->p_dec = NULL;
+
+ if( p_es->p_dec_record )
+ {
+ input_DecoderDelete( p_es->p_dec_record );
+ p_es->p_dec_record = NULL;
+ }
+}
+
static void EsSelect( es_out_t *out, es_out_id_t *es )
{
es_out_sys_t *p_sys = out->p_sys;
}
es->i_preroll_end = -1;
- es->p_dec = input_DecoderNew( p_input, &es->fmt, false );
+ EsCreateDecoder( out, es );
+
if( es->p_dec == NULL || es->p_pgrm != p_sys->p_pgrm )
return;
}
es->pb_cc_present[i] = false;
}
- input_DecoderDelete( es->p_dec );
- es->p_dec = NULL;
+ EsDestroyDecoder( out, es );
}
if( !b_update )
bool pb_cc[4];
bool b_cc_new = false;
int i;
+ if( es->p_dec_record )
+ {
+ block_t *p_dup = block_Duplicate( p_block );
+ if( p_dup )
+ input_DecoderDecode( es->p_dec_record, p_dup );
+ }
input_DecoderDecode( es->p_dec, p_block );
/* Check CC status */
{
while( !out->p_sys->p_input->b_die && es->p_dec )
{
- if( input_DecoderEmpty( es->p_dec ) )
+ if( input_DecoderEmpty( es->p_dec ) &&
+ ( !es->p_dec_record || input_DecoderEmpty( es->p_dec_record ) ))
break;
msleep( 20*1000 );
}
return VLC_SUCCESS;
case ES_OUT_SET_ES:
+ case ES_OUT_RESTART_ES:
+ {
+ int i_cat;
+
es = (es_out_id_t*) va_arg( args, es_out_id_t * );
- /* Special case NULL, NULL+i_cat */
+
if( es == NULL )
- {
- for( i = 0; i < p_sys->i_es; i++ )
- {
- if( EsIsSelected( p_sys->es[i] ) )
- EsUnselect( out, p_sys->es[i],
- p_sys->es[i]->p_pgrm == p_sys->p_pgrm );
- }
- }
+ i_cat = UNKNOWN_ES;
else if( es == (es_out_id_t*)((uint8_t*)NULL+AUDIO_ES) )
- {
- for( i = 0; i < p_sys->i_es; i++ )
- {
- if( p_sys->es[i]->fmt.i_cat == AUDIO_ES &&
- EsIsSelected( p_sys->es[i] ) )
- EsUnselect( out, p_sys->es[i],
- p_sys->es[i]->p_pgrm == p_sys->p_pgrm );
- }
- }
+ i_cat = AUDIO_ES;
else if( es == (es_out_id_t*)((uint8_t*)NULL+VIDEO_ES) )
- {
- for( i = 0; i < p_sys->i_es; i++ )
- {
- if( p_sys->es[i]->fmt.i_cat == VIDEO_ES &&
- EsIsSelected( p_sys->es[i] ) )
- EsUnselect( out, p_sys->es[i],
- p_sys->es[i]->p_pgrm == p_sys->p_pgrm );
- }
- }
+ i_cat = VIDEO_ES;
else if( es == (es_out_id_t*)((uint8_t*)NULL+SPU_ES) )
- {
- for( i = 0; i < p_sys->i_es; i++ )
- {
- if( p_sys->es[i]->fmt.i_cat == SPU_ES &&
- EsIsSelected( p_sys->es[i] ) )
- EsUnselect( out, p_sys->es[i],
- p_sys->es[i]->p_pgrm == p_sys->p_pgrm );
- }
- }
+ i_cat = SPU_ES;
else
+ i_cat = -1;
+
+ for( i = 0; i < p_sys->i_es; i++ )
{
- for( i = 0; i < p_sys->i_es; i++ )
+ if( i_cat == -1 )
{
if( es == p_sys->es[i] )
{
break;
}
}
+ else
+ {
+ if( i_cat == UNKNOWN_ES || p_sys->es[i]->fmt.i_cat == i_cat )
+ {
+ if( EsIsSelected( p_sys->es[i] ) )
+ {
+ if( i_query == ES_OUT_RESTART_ES )
+ {
+ if( p_sys->es[i]->p_dec )
+ {
+ EsDestroyDecoder( out, p_sys->es[i] );
+ EsCreateDecoder( out, p_sys->es[i] );
+ }
+ }
+ else
+ {
+ EsUnselect( out, p_sys->es[i],
+ p_sys->es[i]->p_pgrm == p_sys->p_pgrm );
+ }
+ }
+ }
+ }
}
+ if( i_query == ES_OUT_SET_ES )
{
vlc_event_t event;
event.type = vlc_InputSelectedStreamChanged;
vlc_event_send( &p_sys->p_input->p->event_manager, &event );
}
return VLC_SUCCESS;
+ }
case ES_OUT_SET_DEFAULT:
{
es_format_t *p_fmt;
es = (es_out_id_t*) va_arg( args, es_out_id_t * );
p_fmt = (es_format_t*) va_arg( args, es_format_t * );
- if( es == NULL ) return VLC_EGENERIC;
+ if( es == NULL )
+ return VLC_EGENERIC;
if( p_fmt->i_extra )
{
es->fmt.p_extra = realloc( es->fmt.p_extra, p_fmt->i_extra );
memcpy( es->fmt.p_extra, p_fmt->p_extra, p_fmt->i_extra );
- if( !es->p_dec ) return VLC_SUCCESS;
-
+ if( !es->p_dec )
+ return VLC_SUCCESS;
#if 1
- input_DecoderDelete( es->p_dec );
- es->p_dec = input_DecoderNew( p_sys->p_input,
- &es->fmt, false );
+ EsDestroyDecoder( out, es );
+ EsCreateDecoder( out, es );
#else
es->p_dec->fmt_in.i_extra = p_fmt->i_extra;
es->p_dec->fmt_in.p_extra =
lldiv_t div;
/* Add stream info */
- asprintf( &psz_cat, _("Stream %d"), out->p_sys->i_id - 1 );
+ if( asprintf( &psz_cat, _("Stream %d"), out->p_sys->i_id - 1 ) == -1 )
+ return;
input_Control( p_input, INPUT_ADD_INFO, psz_cat, _("Codec"),
"%.4s", (char*)&fmt->i_codec );