📄 es_out.c
字号:
/* We don't try to reselect */ if( es->p_dec ) EsUnselect( out, es, es->p_pgrm == p_sys->p_pgrm ); if( es->p_pgrm == p_sys->p_pgrm ) EsOutESVarUpdate( out, es, VLC_TRUE ); TAB_REMOVE( p_sys->i_es, p_sys->es, es ); es->p_pgrm->i_es--; if( es->p_pgrm->i_es == 0 ) { msg_Dbg( p_sys->p_input, "Program doesn't contain anymore ES" ); } if( p_sys->p_es_audio == es ) p_sys->p_es_audio = NULL; if( p_sys->p_es_video == es ) p_sys->p_es_video = NULL; if( p_sys->p_es_sub == es ) p_sys->p_es_sub = NULL; switch( es->fmt.i_cat ) { case AUDIO_ES: p_sys->i_audio--; break; case SPU_ES: p_sys->i_sub--; break; case VIDEO_ES: p_sys->i_video--; break; } if( es->psz_language ) free( es->psz_language ); if( es->psz_language_code ) free( es->psz_language_code ); es_format_Clean( &es->fmt ); free( es );}/** * Control query handler * * \param out the es_out to control * \param i_query A es_out query as defined in include/ninput.h * \param args a variable list of arguments for the query * \return VLC_SUCCESS or an error code */static int EsOutControl( es_out_t *out, int i_query, va_list args ){ es_out_sys_t *p_sys = out->p_sys; vlc_bool_t b, *pb; int i, *pi; es_out_id_t *es; switch( i_query ) { case ES_OUT_SET_ES_STATE: es = (es_out_id_t*) va_arg( args, es_out_id_t * ); b = (vlc_bool_t) va_arg( args, vlc_bool_t ); if( b && es->p_dec == NULL ) { EsSelect( out, es ); return es->p_dec ? VLC_SUCCESS : VLC_EGENERIC; } else if( !b && es->p_dec ) { EsUnselect( out, es, es->p_pgrm == p_sys->p_pgrm ); return VLC_SUCCESS; } return VLC_SUCCESS; case ES_OUT_GET_ES_STATE: es = (es_out_id_t*) va_arg( args, es_out_id_t * ); pb = (vlc_bool_t*) va_arg( args, vlc_bool_t * ); *pb = es->p_dec ? VLC_TRUE : VLC_FALSE; return VLC_SUCCESS; case ES_OUT_SET_ACTIVE: { b = (vlc_bool_t) va_arg( args, vlc_bool_t ); p_sys->b_active = b; /* Needed ? */ if( b ) var_SetBool( p_sys->p_input, "intf-change", VLC_TRUE ); return VLC_SUCCESS; } case ES_OUT_GET_ACTIVE: pb = (vlc_bool_t*) va_arg( args, vlc_bool_t * ); *pb = p_sys->b_active; return VLC_SUCCESS; case ES_OUT_SET_MODE: i = (int) va_arg( args, int ); if( i == ES_OUT_MODE_NONE || i == ES_OUT_MODE_ALL || i == ES_OUT_MODE_AUTO || i == ES_OUT_MODE_PARTIAL ) { p_sys->i_mode = i; /* Reapply policy mode */ for( i = 0; i < p_sys->i_es; i++ ) { if( p_sys->es[i]->p_dec ) { EsUnselect( out, p_sys->es[i], p_sys->es[i]->p_pgrm == p_sys->p_pgrm ); } } for( i = 0; i < p_sys->i_es; i++ ) { EsOutSelect( out, p_sys->es[i], VLC_FALSE ); } return VLC_SUCCESS; } return VLC_EGENERIC; case ES_OUT_GET_MODE: pi = (int*) va_arg( args, int* ); *pi = p_sys->i_mode; return VLC_SUCCESS; case ES_OUT_SET_ES: 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( p_sys->es[i]->p_dec ) EsUnselect( out, p_sys->es[i], p_sys->es[i]->p_pgrm == p_sys->p_pgrm ); } } 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]->p_dec && p_sys->es[i]->fmt.i_cat == AUDIO_ES ) EsUnselect( out, p_sys->es[i], p_sys->es[i]->p_pgrm == p_sys->p_pgrm ); } } 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]->p_dec && p_sys->es[i]->fmt.i_cat == VIDEO_ES ) EsUnselect( out, p_sys->es[i], p_sys->es[i]->p_pgrm == p_sys->p_pgrm ); } } 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]->p_dec && p_sys->es[i]->fmt.i_cat == SPU_ES ) EsUnselect( out, p_sys->es[i], p_sys->es[i]->p_pgrm == p_sys->p_pgrm ); } } else { for( i = 0; i < p_sys->i_es; i++ ) { if( es == p_sys->es[i] ) { EsOutSelect( out, es, VLC_TRUE ); break; } } } return VLC_SUCCESS; case ES_OUT_SET_PCR: case ES_OUT_SET_GROUP_PCR: { es_out_pgrm_t *p_pgrm = NULL; int i_group = 0; int64_t i_pcr; if( i_query == ES_OUT_SET_PCR ) { p_pgrm = p_sys->p_pgrm; } else { int i; i_group = (int)va_arg( args, int ); for( i = 0; i < p_sys->i_pgrm; i++ ) { if( p_sys->pgrm[i]->i_id == i_group ) { p_pgrm = p_sys->pgrm[i]; break; } } } if( p_pgrm == NULL ) p_pgrm = EsOutProgramAdd( out, i_group ); /* Create it */ i_pcr = (int64_t)va_arg( args, int64_t ); /* search program */ /* 11 is a vodoo trick to avoid non_pcr*9/100 to be null */ input_ClockSetPCR( p_sys->p_input, &p_pgrm->clock, (i_pcr + 11 ) * 9 / 100); return VLC_SUCCESS; } case ES_OUT_RESET_PCR: for( i = 0; i < p_sys->i_pgrm; i++ ) { p_sys->pgrm[i]->clock.i_synchro_state = SYNCHRO_REINIT; p_sys->pgrm[i]->clock.last_pts = 0; } return VLC_SUCCESS; case ES_OUT_GET_TS: if( p_sys->p_pgrm ) { int64_t i_ts = (int64_t)va_arg( args, int64_t ); int64_t *pi_ts = (int64_t *)va_arg( args, int64_t * ); *pi_ts = input_ClockGetTS( p_sys->p_input, &p_sys->p_pgrm->clock, ( i_ts + 11 ) * 9 / 100 ); return VLC_SUCCESS; } return VLC_EGENERIC; case ES_OUT_GET_GROUP: pi = (int*) va_arg( args, int* ); if( p_sys->p_pgrm ) *pi = p_sys->p_pgrm->i_id; else *pi = -1; /* FIXME */ return VLC_SUCCESS; case ES_OUT_SET_GROUP: { int j; i = (int) va_arg( args, int ); for( j = 0; j < p_sys->i_pgrm; j++ ) { es_out_pgrm_t *p_pgrm = p_sys->pgrm[j]; if( p_pgrm->i_id == i ) { EsOutProgramSelect( out, p_pgrm ); return VLC_SUCCESS; } } return VLC_EGENERIC; } case ES_OUT_SET_FMT: { /* This ain't pretty but is need by some demuxers (eg. Ogg ) * to update the p_extra data */ 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( p_fmt->i_extra ) { es->fmt.i_extra = 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 1 input_DecoderDelete( es->p_dec ); es->p_dec = input_DecoderNew( p_sys->p_input, &es->fmt, VLC_FALSE );#else es->p_dec->fmt_in.i_extra = p_fmt->i_extra; es->p_dec->fmt_in.p_extra = realloc( es->p_dec->fmt_in.p_extra, p_fmt->i_extra ); memcpy( es->p_dec->fmt_in.p_extra, p_fmt->p_extra, p_fmt->i_extra );#endif } return VLC_SUCCESS; } case ES_OUT_SET_NEXT_DISPLAY_TIME: { int64_t i_date; es = (es_out_id_t*) va_arg( args, es_out_id_t * ); i_date = (int64_t)va_arg( args, int64_t ); if( !es || !es->p_dec ) return VLC_EGENERIC; es->i_preroll_end = i_date; input_DecoderPreroll( es->p_dec, i_date ); return VLC_SUCCESS; } case ES_OUT_SET_GROUP_META: { int i_group = (int)va_arg( args, int ); vlc_meta_t *p_meta = (vlc_meta_t*)va_arg( args, vlc_meta_t * ); EsOutProgramMeta( out, i_group, p_meta ); return VLC_SUCCESS; } case ES_OUT_DEL_GROUP: { int i_group = (int)va_arg( args, int ); return EsOutProgramDel( out, i_group ); } default: msg_Err( p_sys->p_input, "unknown query in es_out_Control" ); return VLC_EGENERIC; }}/**************************************************************************** * LanguageGetName: try to expend iso639 into plain name ****************************************************************************/static char *LanguageGetName( const char *psz_code ){ const iso639_lang_t *pl; if( psz_code == NULL ) { return strdup( "" ); } if( strlen( psz_code ) == 2 ) { pl = GetLang_1( psz_code ); } else if( strlen( psz_code ) == 3 ) { pl = GetLang_2B( psz_code ); if( !strcmp( pl->psz_iso639_1, "??" ) ) { pl = GetLang_2T( psz_code ); } } else { return strdup( psz_code ); } if( !strcmp( pl->psz_iso639_1, "??" ) ) { return strdup( psz_code ); } else { if( *pl->psz_native_name ) { return strdup( pl->psz_native_name ); } return strdup( pl->psz_eng_name ); }}/* Get a 2 char code */static char *LanguageGetCode( const char *psz_lang ){ const iso639_lang_t *pl; if( psz_lang == NULL || *psz_lang == '\0' ) return strdup("??"); for( pl = p_languages; pl->psz_iso639_1 != NULL; pl++ ) { if( !strcasecmp( pl->psz_eng_name, psz_lang ) || !strcasecmp( pl->psz_native_name, psz_lang ) || !strcasecmp( pl->psz_iso639_1, psz_lang ) || !strcasecmp( pl->psz_iso639_2T, psz_lang ) || !strcasecmp( pl->psz_iso639_2B, psz_lang ) ) break; } if( pl->psz_iso639_1 != NULL ) return strdup( pl->psz_iso639_1 ); return strdup("??");}static char **LanguageSplit( const char *psz_langs ){ char *psz_dup; char *psz_parser; char **ppsz = NULL; int i_psz = 0; if( psz_langs == NULL ) return NULL; psz_parser = psz_dup = strdup(psz_langs); while( psz_parser && *psz_parser ) { char *psz; char *psz_code; psz = strchr(psz_parser, ',' ); if( psz ) *psz++ = '\0'; psz_code = LanguageGetCode( psz_parser ); if( strcmp( psz_code, "??" ) ) { TAB_APPEND( i_psz, ppsz, psz_code ); } psz_parser = psz; } if( i_psz ) { TAB_APPEND( i_psz, ppsz, NULL ); } free( psz_dup ); return ppsz;}static int LanguageArrayIndex( char **ppsz_langs, char *psz_lang ){ int i; if( !ppsz_langs || !psz_lang ) return -1; for( i = 0; ppsz_langs[i]; i++ ) if( !strcasecmp( ppsz_langs[i], psz_lang ) ) return i; return -1;}/**************************************************************************** * EsOutAddInfo: * - add meta info to the playlist item ****************************************************************************/static void EsOutAddInfo( es_out_t *out, es_out_id_t *es ){ es_out_sys_t *p_sys = out->p_sys; input_thread_t *p_input = p_sys->p_input; es_format_t *fmt = &es->fmt; char *psz_cat; /* Add stream info */ asprintf( &psz_cat, _("Stream %d"), out->p_sys->i_id - 1 ); input_Control( p_input, INPUT_ADD_INFO, psz_cat, _("Codec"), "%.4s", (char*)&fmt->i_codec ); input_Control( p_input, INPUT_ADD_INFO, psz_cat, _("Language"), "%s", es->psz_language ); /* 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 ) input_Control( p_input, INPUT_ADD_INFO, psz_cat, _("Channels"), "%d", fmt->audio.i_channels ); if( fmt->audio.i_rate > 0 ) input_Control( p_input, INPUT_ADD_INFO, psz_cat, _("Sample rate"), _("%d Hz"), fmt->audio.i_rate ); if( fmt->audio.i_bitspersample > 0 ) input_Control( p_input, INPUT_ADD_INFO, psz_cat, _("Bits per sample"), "%d", fmt->audio.i_bitspersample ); if( fmt->i_bitrate > 0 ) input_Control( p_input, INPUT_ADD_INFO, psz_cat, _("Bitrate"), _("%d kb/s"), fmt->i_bitrate / 1000 ); break; case VIDEO_ES: input_Control( p_input, INPUT_ADD_INFO, psz_cat, _("Type"), _("Video") ); if( fmt->video.i_width > 0 && fmt->video.i_height > 0 ) input_Control( p_input, INPUT_ADD_INFO, psz_cat, _("Resolution"), "%dx%d", fmt->video.i_width, fmt->video.i_height ); if( fmt->video.i_visible_width > 0 && fmt->video.i_visible_height > 0 ) input_Control( p_input, INPUT_ADD_INFO, psz_cat, _("Display resolution"), "%dx%d", fmt->video.i_visible_width, fmt->video.i_visible_height); if( fmt->video.i_frame_rate > 0 && fmt->video.i_frame_rate_base > 0 ) input_Control( p_input, INPUT_ADD_INFO, psz_cat, _("Frame rate"), "%f", (float)fmt->video.i_frame_rate / fmt->video.i_frame_rate_base ); break; case SPU_ES: input_Control( p_input, INPUT_ADD_INFO, psz_cat, _("Type"), _("Subtitle") ); break; default: break; } free( psz_cat );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -