Commit 7f2f2b4d authored by Laurent Aimar's avatar Laurent Aimar

Updated codec informations on decoder output change.

 It allows to have more complete informations but only on currently
decoded tracks.
parent a34f0730
...@@ -100,6 +100,10 @@ struct decoder_owner_sys_t ...@@ -100,6 +100,10 @@ struct decoder_owner_sys_t
audio_format_t audio; audio_format_t audio;
es_format_t sout; es_format_t sout;
/* */
bool b_fmt_description;
es_format_t fmt_description;
/* fifo */ /* fifo */
block_fifo_t *p_fifo; block_fifo_t *p_fifo;
...@@ -573,6 +577,7 @@ void input_DecoderWaitBuffering( decoder_t *p_dec ) ...@@ -573,6 +577,7 @@ void input_DecoderWaitBuffering( decoder_t *p_dec )
vlc_mutex_unlock( &p_owner->lock ); vlc_mutex_unlock( &p_owner->lock );
} }
void input_DecoderFrameNext( decoder_t *p_dec, mtime_t *pi_duration ) void input_DecoderFrameNext( decoder_t *p_dec, mtime_t *pi_duration )
{ {
decoder_owner_sys_t *p_owner = p_dec->p_owner; decoder_owner_sys_t *p_owner = p_dec->p_owner;
...@@ -597,6 +602,23 @@ void input_DecoderFrameNext( decoder_t *p_dec, mtime_t *pi_duration ) ...@@ -597,6 +602,23 @@ void input_DecoderFrameNext( decoder_t *p_dec, mtime_t *pi_duration )
vlc_mutex_unlock( &p_owner->lock ); vlc_mutex_unlock( &p_owner->lock );
} }
bool input_DecoderHasFormatChanged( decoder_t *p_dec, es_format_t *p_fmt )
{
decoder_owner_sys_t *p_owner = p_dec->p_owner;
bool b_changed;
vlc_mutex_lock( &p_owner->lock );
b_changed = p_owner->b_fmt_description;
if( b_changed )
{
if( p_fmt )
es_format_Copy( p_fmt, &p_owner->fmt_description );
p_owner->b_fmt_description = false;
}
vlc_mutex_unlock( &p_owner->lock );
return b_changed;
}
/***************************************************************************** /*****************************************************************************
* Internal functions * Internal functions
*****************************************************************************/ *****************************************************************************/
...@@ -775,6 +797,9 @@ static decoder_t * CreateDecoder( input_thread_t *p_input, ...@@ -775,6 +797,9 @@ static decoder_t * CreateDecoder( input_thread_t *p_input,
vlc_mutex_init( &p_owner->lock ); vlc_mutex_init( &p_owner->lock );
vlc_cond_init( &p_owner->wait ); vlc_cond_init( &p_owner->wait );
p_owner->b_fmt_description = false;
es_format_Init( &p_owner->fmt_description, UNKNOWN_ES, 0 );
p_owner->b_paused = false; p_owner->b_paused = false;
p_owner->pause.i_date = 0; p_owner->pause.i_date = 0;
p_owner->pause.i_ignore = 0; p_owner->pause.i_ignore = 0;
...@@ -2030,6 +2055,8 @@ static void DeleteDecoder( decoder_t * p_dec ) ...@@ -2030,6 +2055,8 @@ static void DeleteDecoder( decoder_t * p_dec )
vlc_object_release( p_owner->p_packetizer ); vlc_object_release( p_owner->p_packetizer );
} }
es_format_Clean( &p_owner->fmt_description );
vlc_cond_destroy( &p_owner->wait ); vlc_cond_destroy( &p_owner->wait );
vlc_mutex_destroy( &p_owner->lock ); vlc_mutex_destroy( &p_owner->lock );
...@@ -2041,6 +2068,17 @@ static void DeleteDecoder( decoder_t * p_dec ) ...@@ -2041,6 +2068,17 @@ static void DeleteDecoder( decoder_t * p_dec )
/***************************************************************************** /*****************************************************************************
* Buffers allocation callbacks for the decoders * Buffers allocation callbacks for the decoders
*****************************************************************************/ *****************************************************************************/
static void DecoderUpdateFormatLocked( decoder_t *p_dec )
{
decoder_owner_sys_t *p_owner = p_dec->p_owner;
vlc_assert_locked( &p_owner->lock );
es_format_Clean( &p_owner->fmt_description );
p_owner->b_fmt_description = true;
es_format_Copy( &p_owner->fmt_description, &p_dec->fmt_out );
}
static vout_thread_t *aout_request_vout( void *p_private, static vout_thread_t *aout_request_vout( void *p_private,
vout_thread_t *p_vout, video_format_t *p_fmt ) vout_thread_t *p_vout, video_format_t *p_fmt )
{ {
...@@ -2113,8 +2151,11 @@ static aout_buffer_t *aout_new_buffer( decoder_t *p_dec, int i_samples ) ...@@ -2113,8 +2151,11 @@ static aout_buffer_t *aout_new_buffer( decoder_t *p_dec, int i_samples )
&format, &p_dec->fmt_out.audio_replay_gain, &request_vout ); &format, &p_dec->fmt_out.audio_replay_gain, &request_vout );
vlc_mutex_lock( &p_owner->lock ); vlc_mutex_lock( &p_owner->lock );
p_owner->p_aout = p_aout; p_owner->p_aout = p_aout;
p_owner->p_aout_input = p_aout_input; p_owner->p_aout_input = p_aout_input;
DecoderUpdateFormatLocked( p_dec );
vlc_mutex_unlock( &p_owner->lock ); vlc_mutex_unlock( &p_owner->lock );
if( p_owner->p_aout_input == NULL ) if( p_owner->p_aout_input == NULL )
...@@ -2221,6 +2262,9 @@ static picture_t *vout_new_buffer( decoder_t *p_dec ) ...@@ -2221,6 +2262,9 @@ static picture_t *vout_new_buffer( decoder_t *p_dec )
vlc_mutex_lock( &p_owner->lock ); vlc_mutex_lock( &p_owner->lock );
p_owner->p_vout = p_vout; p_owner->p_vout = p_vout;
DecoderUpdateFormatLocked( p_dec );
vlc_mutex_unlock( &p_owner->lock ); vlc_mutex_unlock( &p_owner->lock );
input_SendEventVout( p_owner->p_input ); input_SendEventVout( p_owner->p_input );
......
...@@ -89,4 +89,12 @@ void input_DecoderIsCcPresent( decoder_t *, bool pb_present[4] ); ...@@ -89,4 +89,12 @@ void input_DecoderIsCcPresent( decoder_t *, bool pb_present[4] );
*/ */
void input_DecoderFrameNext( decoder_t *p_dec, mtime_t *pi_duration ); void input_DecoderFrameNext( decoder_t *p_dec, mtime_t *pi_duration );
/**
* This function will return true if the ES format has changed since the last call
* and will do a copy of the current es_format_t if p_fmt is not NULL. This copy
* MUST be free by es_format_Clean.
* Otherwise it will return false and will not initialize p_fmt.
*/
bool input_DecoderHasFormatChanged( decoder_t *p_dec, es_format_t *p_fmt );
#endif #endif
...@@ -94,6 +94,9 @@ struct es_out_id_t ...@@ -94,6 +94,9 @@ struct es_out_id_t
/* Field for CC track from a master video */ /* Field for CC track from a master video */
es_out_id_t *p_master; es_out_id_t *p_master;
/* ID for the meta data */
int i_meta_id;
}; };
struct es_out_sys_t struct es_out_sys_t
...@@ -165,7 +168,7 @@ static int EsOutControl( es_out_t *, int i_query, va_list ); ...@@ -165,7 +168,7 @@ static int EsOutControl( es_out_t *, int i_query, va_list );
static void EsOutDelete ( es_out_t * ); static void EsOutDelete ( es_out_t * );
static void EsOutSelect( es_out_t *, es_out_id_t *es, bool b_force ); static void EsOutSelect( es_out_t *, es_out_id_t *es, bool b_force );
static void EsOutAddInfo( es_out_t *, es_out_id_t *es ); static void EsOutUpdateInfo( es_out_t *, es_out_id_t *es, const es_format_t * );
static int EsOutSetRecord( es_out_t *, bool b_record ); static int EsOutSetRecord( es_out_t *, bool b_record );
static bool EsIsSelected( es_out_id_t *es ); static bool EsIsSelected( es_out_id_t *es );
...@@ -1312,6 +1315,7 @@ static es_out_id_t *EsOutAdd( es_out_t *out, const es_format_t *fmt ) ...@@ -1312,6 +1315,7 @@ static es_out_id_t *EsOutAdd( es_out_t *out, const es_format_t *fmt )
if( es->fmt.i_id < 0 ) if( es->fmt.i_id < 0 )
es->fmt.i_id = out->p_sys->i_id; es->fmt.i_id = out->p_sys->i_id;
es->i_id = es->fmt.i_id; es->i_id = es->fmt.i_id;
es->i_meta_id = out->p_sys->i_id;
switch( es->fmt.i_cat ) switch( es->fmt.i_cat )
{ {
...@@ -1389,7 +1393,7 @@ static es_out_id_t *EsOutAdd( es_out_t *out, const es_format_t *fmt ) ...@@ -1389,7 +1393,7 @@ static es_out_id_t *EsOutAdd( es_out_t *out, const es_format_t *fmt )
break; break;
} }
EsOutAddInfo( out, es ); EsOutUpdateInfo( out, es, &es->fmt );
vlc_mutex_unlock( &p_sys->lock ); vlc_mutex_unlock( &p_sys->lock );
...@@ -1794,6 +1798,13 @@ static int EsOutSend( es_out_t *out, es_out_id_t *es, block_t *p_block ) ...@@ -1794,6 +1798,13 @@ static int EsOutSend( es_out_t *out, es_out_id_t *es, block_t *p_block )
} }
input_DecoderDecode( es->p_dec, p_block ); input_DecoderDecode( es->p_dec, p_block );
es_format_t fmt_dsc;
if( input_DecoderHasFormatChanged( es->p_dec, &fmt_dsc ) )
{
EsOutUpdateInfo( out, es, &fmt_dsc );
es_format_Clean( &fmt_dsc );
}
/* Check CC status */ /* Check CC status */
bool pb_cc[4]; bool pb_cc[4];
...@@ -2444,35 +2455,69 @@ static int LanguageArrayIndex( char **ppsz_langs, char *psz_lang ) ...@@ -2444,35 +2455,69 @@ static int LanguageArrayIndex( char **ppsz_langs, char *psz_lang )
} }
/**************************************************************************** /****************************************************************************
* EsOutAddInfo: * EsOutUpdateInfo:
* - add meta info to the playlist item * - add meta info to the playlist item
****************************************************************************/ ****************************************************************************/
static void EsOutAddInfo( es_out_t *out, es_out_id_t *es ) static void EsOutUpdateInfo( es_out_t *out, es_out_id_t *es, const es_format_t *fmt )
{ {
es_out_sys_t *p_sys = out->p_sys; es_out_sys_t *p_sys = out->p_sys;
input_thread_t *p_input = p_sys->p_input; input_thread_t *p_input = p_sys->p_input;
es_format_t *fmt = &es->fmt; const es_format_t *p_fmt_es = &es->fmt;
char *psz_cat; char *psz_cat;
lldiv_t div; lldiv_t div;
/* Add stream info */ /* Create category name */
if( asprintf( &psz_cat, _("Stream %d"), out->p_sys->i_id - 1 ) == -1 ) if( asprintf( &psz_cat, _("Stream %d"), es->i_meta_id ) == -1 )
return; return;
/* Remove previous information */
input_Control( p_input, INPUT_DEL_INFO, psz_cat );
/* Add informations */
const char *psz_type;
switch( fmt->i_cat )
{
case AUDIO_ES:
psz_type = _("Audio");
break;
case VIDEO_ES:
psz_type = _("Video");
break;
case SPU_ES:
psz_type = _("Subtitle");
break;
default:
psz_type = NULL;
break;
}
if( psz_type )
input_Control( p_input, INPUT_ADD_INFO, psz_cat, _("Type"), psz_type );
if( es->i_meta_id != es->i_id )
input_Control( p_input, INPUT_ADD_INFO, psz_cat, _("Original ID"),
"%d", es->i_id );
input_Control( p_input, INPUT_ADD_INFO, psz_cat, _("Codec"), input_Control( p_input, INPUT_ADD_INFO, psz_cat, _("Codec"),
"%.4s", (char*)&fmt->i_codec ); "%.4s", (char*)&p_fmt_es->i_codec );
input_Control( p_input, INPUT_ADD_INFO, psz_cat, _("Language"), if( es->psz_language && *es->psz_language )
"%s", es->psz_language ); input_Control( p_input, INPUT_ADD_INFO, psz_cat, _("Language"),
"%s", es->psz_language );
if( fmt->psz_description && *fmt->psz_description )
input_Control( p_input, INPUT_ADD_INFO, psz_cat, _("Description"),
"%s", fmt->psz_description );
/* Add information */
switch( fmt->i_cat ) switch( fmt->i_cat )
{ {
case AUDIO_ES: case AUDIO_ES:
input_Control( p_input, INPUT_ADD_INFO, psz_cat, input_Control( p_input, INPUT_ADD_INFO, psz_cat,
_("Type"), _("Audio") ); _("Type"), _("Audio") );
if( fmt->audio.i_channels > 0 ) if( fmt->audio.i_physical_channels & AOUT_CHAN_PHYSMASK )
input_Control( p_input, INPUT_ADD_INFO, psz_cat, _("Channels"),
"%s", aout_FormatPrintChannels( &fmt->audio ) );
else if( fmt->audio.i_channels > 0 )
input_Control( p_input, INPUT_ADD_INFO, psz_cat, _("Channels"), input_Control( p_input, INPUT_ADD_INFO, psz_cat, _("Channels"),
"%u", fmt->audio.i_channels ); "%u", fmt->audio.i_channels );
...@@ -2484,10 +2529,13 @@ static void EsOutAddInfo( es_out_t *out, es_out_id_t *es ) ...@@ -2484,10 +2529,13 @@ static void EsOutAddInfo( es_out_t *out, es_out_id_t *es )
var_SetInteger( p_input, "sample-rate", fmt->audio.i_rate ); var_SetInteger( p_input, "sample-rate", fmt->audio.i_rate );
} }
if( fmt->audio.i_bitspersample > 0 ) unsigned int i_bitspersample = fmt->audio.i_bitspersample;
if( i_bitspersample <= 0 )
i_bitspersample = aout_BitsPerSample( p_fmt_es->i_codec );
if( i_bitspersample > 0 )
input_Control( p_input, INPUT_ADD_INFO, psz_cat, input_Control( p_input, INPUT_ADD_INFO, psz_cat,
_("Bits per sample"), "%u", _("Bits per sample"), "%u",
fmt->audio.i_bitspersample ); i_bitspersample );
if( fmt->i_bitrate > 0 ) if( fmt->i_bitrate > 0 )
{ {
...@@ -2496,6 +2544,19 @@ static void EsOutAddInfo( es_out_t *out, es_out_id_t *es ) ...@@ -2496,6 +2544,19 @@ static void EsOutAddInfo( es_out_t *out, es_out_id_t *es )
/* FIXME that should be removed or improved ! (used by text/strings.c) */ /* FIXME that should be removed or improved ! (used by text/strings.c) */
var_SetInteger( p_input, "bit-rate", fmt->i_bitrate ); var_SetInteger( p_input, "bit-rate", fmt->i_bitrate );
} }
for( int i = 0; i < AUDIO_REPLAY_GAIN_MAX; i++ )
{
const audio_replay_gain_t *p_rg = &fmt->audio_replay_gain;
if( !p_rg->pb_gain[i] )
continue;
const char *psz_name;
if( i == AUDIO_REPLAY_GAIN_TRACK )
psz_name = _("Track replay gain");
else
psz_name = _("Album replay gain");
input_Control( p_input, INPUT_ADD_INFO, psz_cat,
psz_name, _("%.2f dB"), p_rg->pf_gain[i] );
}
break; break;
case VIDEO_ES: case VIDEO_ES:
...@@ -2519,9 +2580,13 @@ static void EsOutAddInfo( es_out_t *out, es_out_id_t *es ) ...@@ -2519,9 +2580,13 @@ static void EsOutAddInfo( es_out_t *out, es_out_id_t *es )
div = lldiv( (float)fmt->video.i_frame_rate / div = lldiv( (float)fmt->video.i_frame_rate /
fmt->video.i_frame_rate_base * 1000000, fmt->video.i_frame_rate_base * 1000000,
1000000 ); 1000000 );
input_Control( p_input, INPUT_ADD_INFO, psz_cat, if( div.rem > 0 )
_("Frame rate"), "%"PRId64".%06u", input_Control( p_input, INPUT_ADD_INFO, psz_cat,
div.quot, (unsigned int )div.rem ); _("Frame rate"), "%"PRId64".%06u",
div.quot, (unsigned int )div.rem );
else
input_Control( p_input, INPUT_ADD_INFO, psz_cat,
_("Frame rate"), "%"PRId64, div.quot );
} }
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment