audio_format_t audio;
es_format_t sout;
+ /* */
+ bool b_fmt_description;
+ es_format_t fmt_description;
+
/* fifo */
block_fifo_t *p_fifo;
vlc_mutex_unlock( &p_owner->lock );
}
+
void input_DecoderFrameNext( decoder_t *p_dec, mtime_t *pi_duration )
{
decoder_owner_sys_t *p_owner = p_dec->p_owner;
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
*****************************************************************************/
vlc_mutex_init( &p_owner->lock );
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->pause.i_date = 0;
p_owner->pause.i_ignore = 0;
vlc_object_release( p_owner->p_packetizer );
}
+ es_format_Clean( &p_owner->fmt_description );
+
vlc_cond_destroy( &p_owner->wait );
vlc_mutex_destroy( &p_owner->lock );
/*****************************************************************************
* 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,
vout_thread_t *p_vout, video_format_t *p_fmt )
{
&format, &p_dec->fmt_out.audio_replay_gain, &request_vout );
vlc_mutex_lock( &p_owner->lock );
+
p_owner->p_aout = p_aout;
p_owner->p_aout_input = p_aout_input;
+ DecoderUpdateFormatLocked( p_dec );
+
vlc_mutex_unlock( &p_owner->lock );
if( p_owner->p_aout_input == NULL )
vlc_mutex_lock( &p_owner->lock );
p_owner->p_vout = p_vout;
+
+ DecoderUpdateFormatLocked( p_dec );
+
vlc_mutex_unlock( &p_owner->lock );
input_SendEventVout( p_owner->p_input );
/* Field for CC track from a master video */
es_out_id_t *p_master;
+
+ /* ID for the meta data */
+ int i_meta_id;
};
struct es_out_sys_t
static void EsOutDelete ( es_out_t * );
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 bool EsIsSelected( es_out_id_t *es );
if( es->fmt.i_id < 0 )
es->fmt.i_id = out->p_sys->i_id;
es->i_id = es->fmt.i_id;
+ es->i_meta_id = out->p_sys->i_id;
switch( es->fmt.i_cat )
{
break;
}
- EsOutAddInfo( out, es );
+ EsOutUpdateInfo( out, es, &es->fmt );
vlc_mutex_unlock( &p_sys->lock );
}
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 */
bool pb_cc[4];
}
/****************************************************************************
- * EsOutAddInfo:
+ * EsOutUpdateInfo:
* - 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;
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;
lldiv_t div;
- /* Add stream info */
- if( asprintf( &psz_cat, _("Stream %d"), out->p_sys->i_id - 1 ) == -1 )
+ /* Create category name */
+ if( asprintf( &psz_cat, _("Stream %d"), es->i_meta_id ) == -1 )
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"),
- "%.4s", (char*)&fmt->i_codec );
+ "%.4s", (char*)&p_fmt_es->i_codec );
- input_Control( p_input, INPUT_ADD_INFO, psz_cat, _("Language"),
- "%s", es->psz_language );
+ if( es->psz_language && *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 )
{
case AUDIO_ES:
input_Control( p_input, INPUT_ADD_INFO, psz_cat,
_("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"),
"%u", fmt->audio.i_channels );
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,
_("Bits per sample"), "%u",
- fmt->audio.i_bitspersample );
+ i_bitspersample );
if( fmt->i_bitrate > 0 )
{
/* FIXME that should be removed or improved ! (used by text/strings.c) */
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;
case VIDEO_ES:
div = lldiv( (float)fmt->video.i_frame_rate /
fmt->video.i_frame_rate_base * 1000000,
1000000 );
- input_Control( p_input, INPUT_ADD_INFO, psz_cat,
- _("Frame rate"), "%"PRId64".%06u",
- div.quot, (unsigned int )div.rem );
+ if( div.rem > 0 )
+ input_Control( p_input, INPUT_ADD_INFO, psz_cat,
+ _("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;