📄 es_out.c
字号:
return; } } else if( i_cat == SPU_ES ) { int idx1 = LanguageArrayIndex( p_sys->ppsz_sub_language, es->psz_language_code ); if( p_sys->p_es_sub && p_sys->p_es_sub->fmt.i_priority >= es->fmt.i_priority ) { int idx2 = LanguageArrayIndex( p_sys->ppsz_sub_language, p_sys->p_es_sub->psz_language_code ); msg_Dbg( p_sys->p_input, "idx1=%d(%s) idx2=%d(%s)", idx1, es->psz_language_code, idx2, p_sys->p_es_sub->psz_language_code ); if( idx1 < 0 || ( idx2 >= 0 && idx2 <= idx1 ) ) return; /* We found a SPU that matches our language request */ i_wanted = es->i_channel; } else if( idx1 >= 0 ) { msg_Dbg( p_sys->p_input, "idx1=%d(%s)", idx1, es->psz_language_code ); i_wanted = es->i_channel; } else if( p_sys->i_default_sub_id >= 0 ) { if( es->i_id == p_sys->i_default_sub_id ) i_wanted = es->i_channel; } if( p_sys->i_sub_last >= 0 ) i_wanted = p_sys->i_sub_last; if( p_sys->i_sub_id >= 0 ) { if( es->i_id == p_sys->i_sub_id ) i_wanted = es->i_channel; else return; } } else if( i_cat == VIDEO_ES ) { i_wanted = es->i_channel; } if( i_wanted == es->i_channel && !EsIsSelected( es ) ) EsSelect( out, es ); } /* FIXME TODO handle priority here */ if( EsIsSelected( es ) ) { if( i_cat == AUDIO_ES ) { if( p_sys->i_mode == ES_OUT_MODE_AUTO && p_sys->p_es_audio && p_sys->p_es_audio != es && EsIsSelected( p_sys->p_es_audio ) ) { EsUnselect( out, p_sys->p_es_audio, false ); } p_sys->p_es_audio = es; } else if( i_cat == SPU_ES ) { if( p_sys->i_mode == ES_OUT_MODE_AUTO && p_sys->p_es_sub && p_sys->p_es_sub != es && EsIsSelected( p_sys->p_es_sub ) ) { EsUnselect( out, p_sys->p_es_sub, false ); } p_sys->p_es_sub = es; } else if( i_cat == VIDEO_ES ) { p_sys->p_es_video = es; } }}/** * Send a block for the given es_out * * \param out the es_out to send from * \param es the es_out_id * \param p_block the data block to send */static int EsOutSend( es_out_t *out, es_out_id_t *es, block_t *p_block ){ es_out_sys_t *p_sys = out->p_sys; input_thread_t *p_input = p_sys->p_input; es_out_pgrm_t *p_pgrm = es->p_pgrm; int64_t i_delay; int i_total=0; if( es->fmt.i_cat == AUDIO_ES ) i_delay = p_sys->i_audio_delay; else if( es->fmt.i_cat == SPU_ES ) i_delay = p_sys->i_spu_delay; else i_delay = 0; if( libvlc_stats (p_input) ) { vlc_mutex_lock( &p_input->p->counters.counters_lock ); stats_UpdateInteger( p_input, p_input->p->counters.p_demux_read, p_block->i_buffer, &i_total ); stats_UpdateFloat( p_input , p_input->p->counters.p_demux_bitrate, (float)i_total, NULL ); vlc_mutex_unlock( &p_input->p->counters.counters_lock ); } /* Mark preroll blocks */ if( es->i_preroll_end >= 0 ) { int64_t i_date = p_block->i_pts; if( i_date <= 0 ) i_date = p_block->i_dts; if( i_date < es->i_preroll_end ) p_block->i_flags |= BLOCK_FLAG_PREROLL; else es->i_preroll_end = -1; } if( p_block->i_dts > 0 && (p_block->i_flags&BLOCK_FLAG_PREROLL) ) { p_block->i_dts += i_delay; } else if( p_block->i_dts > 0 ) { p_block->i_dts = input_ClockGetTS( p_input, &p_pgrm->clock, p_block->i_dts ) + i_delay; } if( p_block->i_pts > 0 && (p_block->i_flags&BLOCK_FLAG_PREROLL) ) { p_block->i_pts += i_delay; } else if( p_block->i_pts > 0 ) { p_block->i_pts = input_ClockGetTS( p_input, &p_pgrm->clock, p_block->i_pts ) + i_delay; } if ( p_block->i_rate == INPUT_RATE_DEFAULT && es->fmt.i_codec == VLC_FOURCC( 't', 'e', 'l', 'x' ) ) { mtime_t current_date = mdate(); if( !p_block->i_pts || p_block->i_pts > current_date + 10000000 || current_date > p_block->i_pts ) { /* ETSI EN 300 472 Annex A : do not take into account the PTS * for teletext streams. */ p_block->i_pts = current_date + 400000 + p_input->i_pts_delay + i_delay; } } p_block->i_rate = p_sys->i_rate; /* TODO handle mute */ if( es->p_dec && ( es->fmt.i_cat != AUDIO_ES || ( p_sys->i_rate >= INPUT_RATE_DEFAULT/AOUT_MAX_INPUT_RATE && p_sys->i_rate <= INPUT_RATE_DEFAULT*AOUT_MAX_INPUT_RATE ) ) ) { bool pb_cc[4]; bool b_cc_new = false; int i; input_DecoderDecode( es->p_dec, p_block ); /* Check CC status */ input_DecoderIsCcPresent( es->p_dec, pb_cc ); for( i = 0; i < 4; i++ ) { static const vlc_fourcc_t fcc[4] = { VLC_FOURCC('c', 'c', '1', ' '), VLC_FOURCC('c', 'c', '2', ' '), VLC_FOURCC('c', 'c', '3', ' '), VLC_FOURCC('c', 'c', '4', ' '), }; static const char ppsz_description[4][18] = { N_("Closed captions 1"), N_("Closed captions 2"), N_("Closed captions 3"), N_("Closed captions 4"), }; es_format_t fmt; if( es->pb_cc_present[i] || !pb_cc[i] ) continue; msg_Dbg( p_input, "Adding CC track %d for es[%d]", 1+i, es->i_id ); es_format_Init( &fmt, SPU_ES, fcc[i] ); fmt.i_group = es->fmt.i_group; fmt.psz_description = strdup( _(ppsz_description[i] ) ); es->pp_cc_es[i] = EsOutAdd( out, &fmt ); es->pp_cc_es[i]->p_master = es; es_format_Clean( &fmt ); /* */ es->pb_cc_present[i] = true; b_cc_new = true; } if( b_cc_new ) var_SetBool( p_sys->p_input, "intf-change", true ); } else { block_Release( p_block ); } return VLC_SUCCESS;}/***************************************************************************** * EsOutDel: *****************************************************************************/static void EsOutDel( es_out_t *out, es_out_id_t *es ){ es_out_sys_t *p_sys = out->p_sys; bool b_reselect = false; int i; /* We don't try to reselect */ if( es->p_dec ) { while( !out->p_sys->p_input->b_die && es->p_dec ) { if( input_DecoderEmpty( es->p_dec ) ) break; msleep( 20*1000 ); } EsUnselect( out, es, es->p_pgrm == p_sys->p_pgrm ); } if( es->p_pgrm == p_sys->p_pgrm ) EsOutESVarUpdate( out, es, 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_video == es || p_sys->p_es_sub == es ) b_reselect = true; 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; } /* Re-select another track when needed */ if( b_reselect ) for( i = 0; i < p_sys->i_es; i++ ) { if( es->fmt.i_cat == p_sys->es[i]->fmt.i_cat ) EsOutSelect( out, p_sys->es[i], false ); } free( es->psz_language ); 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; bool 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 = (bool) va_arg( args, int ); if( b && !EsIsSelected( es ) ) { EsSelect( out, es ); return EsIsSelected( es ) ? VLC_SUCCESS : VLC_EGENERIC; } else if( !b && EsIsSelected( es ) ) { 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 = (bool*) va_arg( args, bool * ); *pb = EsIsSelected( es ); return VLC_SUCCESS; case ES_OUT_SET_ACTIVE: { b = (bool) va_arg( args, int ); p_sys->b_active = b; /* Needed ? */ if( b ) var_SetBool( p_sys->p_input, "intf-change", true ); return VLC_SUCCESS; } case ES_OUT_GET_ACTIVE: pb = (bool*) va_arg( args, bool * ); *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( EsIsSelected( p_sys->es[i] ) ) { 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], 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( EsIsSelected( p_sys->es[i] ) ) 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]->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 ); } } 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 ); } } 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 ); } } else { for( i = 0; i < p_sys->i_es; i++ ) { if( es == p_sys->es[i] ) { EsOutSelect( out, es, true ); break; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -