📄 es_out.c
字号:
TAB_REMOVE( p_sys->i_pgrm, p_sys->pgrm, p_pgrm ); /* If program is selected we need to unselect it */ if( p_sys->p_pgrm == p_pgrm ) p_sys->p_pgrm = 0; if( p_pgrm->psz_now_playing ) free( p_pgrm->psz_now_playing ); free( p_pgrm ); /* Update "program" variable */ val.i_int = i_group; var_Change( p_input, "program", VLC_VAR_DELCHOICE, &val, NULL ); var_SetBool( p_sys->p_input, "intf-change", VLC_TRUE ); return VLC_SUCCESS;}/* EsOutProgramMeta: */static void EsOutProgramMeta( es_out_t *out, int i_group, vlc_meta_t *p_meta ){ es_out_sys_t *p_sys = out->p_sys; es_out_pgrm_t *p_pgrm = NULL; input_thread_t *p_input = p_sys->p_input; char *psz_cat = malloc( strlen(_("Program")) + 10 ); char *psz_name = NULL; char *psz_now_playing = NULL; char *psz_provider = NULL; int i; msg_Dbg( p_input, "EsOutProgramMeta: number=%d", i_group ); sprintf( psz_cat, "%s %d", _("Program"), i_group ); for( i = 0; i < p_meta->i_meta; i++ ) { msg_Dbg( p_input, " - %s = %s", p_meta->name[i], p_meta->value[i] ); input_Control( p_input, INPUT_ADD_INFO, psz_cat, _(p_meta->name[i]), "%s", p_meta->value[i] ); if( !strcasecmp( p_meta->name[i], "Name" ) ) psz_name = p_meta->value[i]; else if( !strcasecmp( p_meta->name[i], "Provider" ) ) psz_provider = p_meta->value[i]; else if( !strcasecmp( p_meta->name[i], VLC_META_NOW_PLAYING ) ) psz_now_playing = p_meta->value[i]; } if( !psz_name && !psz_now_playing ) { free( psz_cat ); return; } 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 ); /* Update the description text of the program */ if( psz_name && *psz_name ) { vlc_value_t val; vlc_value_t text; /* ugly but it works */ val.i_int = i_group; var_Change( p_input, "program", VLC_VAR_DELCHOICE, &val, NULL ); if( psz_provider && *psz_provider ) { asprintf( &text.psz_string, "%s [%s]", psz_name, psz_provider ); var_Change( p_input, "program", VLC_VAR_ADDCHOICE, &val, &text ); free( text.psz_string ); } else { text.psz_string = psz_name; var_Change( p_input, "program", VLC_VAR_ADDCHOICE, &val, &text ); } } if( psz_now_playing ) { p_pgrm->psz_now_playing = strdup(psz_now_playing); if( p_sys->p_pgrm == p_pgrm ) { input_Control( p_input, INPUT_ADD_INFO, _("Meta-information"), VLC_META_NOW_PLAYING, "%s", psz_now_playing ); } } free( psz_cat );}/* EsOutAdd: * Add an es_out */static es_out_id_t *EsOutAdd( es_out_t *out, es_format_t *fmt ){ es_out_sys_t *p_sys = out->p_sys; input_thread_t *p_input = p_sys->p_input; es_out_id_t *es = malloc( sizeof( es_out_id_t ) ); es_out_pgrm_t *p_pgrm = NULL; int i; if( fmt->i_group < 0 ) { msg_Err( p_input, "invalid group number" ); return NULL; } /* Search the program */ for( i = 0; i < p_sys->i_pgrm; i++ ) { if( fmt->i_group == p_sys->pgrm[i]->i_id ) { p_pgrm = p_sys->pgrm[i]; break; } } if( p_pgrm == NULL ) { /* Create a new one */ p_pgrm = EsOutProgramAdd( out, fmt->i_group ); } /* Increase ref count for program */ p_pgrm->i_es++; /* Set up ES */ if( fmt->i_id < 0 ) fmt->i_id = out->p_sys->i_id; es->i_id = fmt->i_id; es->p_pgrm = p_pgrm; es_format_Copy( &es->fmt, fmt ); es->i_preroll_end = -1; switch( fmt->i_cat ) { case AUDIO_ES: es->i_channel = p_sys->i_audio; break; case VIDEO_ES: es->i_channel = p_sys->i_video; if( fmt->video.i_frame_rate && fmt->video.i_frame_rate_base ) vlc_reduce( &es->fmt.video.i_frame_rate, &es->fmt.video.i_frame_rate_base, fmt->video.i_frame_rate, fmt->video.i_frame_rate_base, 0 ); break; case SPU_ES: es->i_channel = p_sys->i_sub; break; default: es->i_channel = 0; break; } 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; if( es->p_pgrm == p_sys->p_pgrm ) EsOutESVarUpdate( out, es, VLC_FALSE ); /* Select it if needed */ EsOutSelect( out, es, VLC_FALSE ); TAB_APPEND( out->p_sys->i_es, out->p_sys->es, es ); p_sys->i_id++; /* always incremented */ switch( 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; } EsOutAddInfo( out, es ); return es;}static void EsSelect( 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; vlc_value_t val; char *psz_var; if( es->p_dec ) { msg_Warn( p_input, "ES 0x%x is already selected", es->i_id ); return; } if( es->fmt.i_cat == VIDEO_ES || es->fmt.i_cat == SPU_ES ) { if( !var_GetBool( p_input, "video" ) || ( p_input->p_sout && !var_GetBool( p_input, "sout-video" ) ) ) { msg_Dbg( p_input, "video is disabled, not selecting ES 0x%x", es->i_id ); return; } } else if( es->fmt.i_cat == AUDIO_ES ) { var_Get( p_input, "audio", &val ); if( !var_GetBool( p_input, "audio" ) || ( p_input->p_sout && !var_GetBool( p_input, "sout-audio" ) ) ) { msg_Dbg( p_input, "audio is disabled, not selecting ES 0x%x", es->i_id ); return; } } es->i_preroll_end = -1; es->p_dec = input_DecoderNew( p_input, &es->fmt, VLC_FALSE ); if( es->p_dec == NULL || es->p_pgrm != p_sys->p_pgrm ) return; if( es->fmt.i_cat == VIDEO_ES ) psz_var = "video-es"; else if( es->fmt.i_cat == AUDIO_ES ) psz_var = "audio-es"; else if( es->fmt.i_cat == SPU_ES ) psz_var = "spu-es"; else return; /* Mark it as selected */ val.i_int = es->i_id; var_Change( p_input, psz_var, VLC_VAR_SETVALUE, &val, NULL ); var_SetBool( p_sys->p_input, "intf-change", VLC_TRUE );}static void EsUnselect( es_out_t *out, es_out_id_t *es, vlc_bool_t b_update ){ es_out_sys_t *p_sys = out->p_sys; input_thread_t *p_input = p_sys->p_input; vlc_value_t val; char *psz_var; if( es->p_dec == NULL ) { msg_Warn( p_input, "ES 0x%x is already unselected", es->i_id ); return; } input_DecoderDelete( es->p_dec ); es->p_dec = NULL; if( !b_update ) return; /* Update var */ if( es->p_dec == NULL ) return; if( es->fmt.i_cat == VIDEO_ES ) psz_var = "video-es"; else if( es->fmt.i_cat == AUDIO_ES ) psz_var = "audio-es"; else if( es->fmt.i_cat == SPU_ES ) psz_var = "spu-es"; else return; /* Mark it as selected */ val.i_int = -1; var_Change( p_input, psz_var, VLC_VAR_SETVALUE, &val, NULL ); var_SetBool( p_sys->p_input, "intf-change", VLC_TRUE );}/** * Select an ES given the current mode * XXX: you need to take a the lock before (stream.stream_lock) * * \param out The es_out structure * \param es es_out_id structure * \param b_force ... * \return nothing */static void EsOutSelect( es_out_t *out, es_out_id_t *es, vlc_bool_t b_force ){ es_out_sys_t *p_sys = out->p_sys; int i_cat = es->fmt.i_cat; if( !p_sys->b_active || ( !b_force && es->fmt.i_priority < 0 ) ) { return; } if( p_sys->i_mode == ES_OUT_MODE_ALL || b_force ) { if( !es->p_dec ) EsSelect( out, es ); } else if( p_sys->i_mode == ES_OUT_MODE_PARTIAL ) { vlc_value_t val; int i; var_Get( p_sys->p_input, "programs", &val ); for ( i = 0; i < val.p_list->i_count; i++ ) { if ( val.p_list->p_values[i].i_int == es->p_pgrm->i_id || b_force ) { if( !es->p_dec ) EsSelect( out, es ); break; } } var_Change( p_sys->p_input, "programs", VLC_VAR_FREELIST, &val, NULL ); } else if( p_sys->i_mode == ES_OUT_MODE_AUTO ) { int i_wanted = -1; if( es->p_pgrm != p_sys->p_pgrm ) return; if( i_cat == AUDIO_ES ) { int idx1 = LanguageArrayIndex( p_sys->ppsz_audio_language, es->psz_language_code ); if( p_sys->p_es_audio && p_sys->p_es_audio->fmt.i_priority >= es->fmt.i_priority ) { int idx2 = LanguageArrayIndex( p_sys->ppsz_audio_language, p_sys->p_es_audio->psz_language_code ); if( idx1 < 0 || ( idx2 >= 0 && idx2 <= idx1 ) ) return; i_wanted = es->i_channel; } else { /* Select audio if (no audio selected yet) * - no audio-language * - no audio code for the ES * - audio code in the requested list */ if( idx1 >= 0 || !strcmp( es->psz_language_code, "??" ) || !p_sys->ppsz_audio_language ) i_wanted = es->i_channel; } if( p_sys->i_audio_last >= 0 ) i_wanted = p_sys->i_audio_last; } 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; } if( p_sys->i_sub_last >= 0 ) i_wanted = p_sys->i_sub_last; } else if( i_cat == VIDEO_ES ) { i_wanted = es->i_channel; } if( i_wanted == es->i_channel && es->p_dec == NULL ) EsSelect( out, es ); } /* FIXME TODO handle priority here */ if( es->p_dec ) { 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 && p_sys->p_es_audio->p_dec ) { EsUnselect( out, p_sys->p_es_audio, VLC_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 && p_sys->p_es_sub->p_dec ) { EsUnselect( out, p_sys->p_es_sub, VLC_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; 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; /* 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; } /* +11 -> avoid null value with non null dts/pts */ if( p_block->i_dts > 0 ) { p_block->i_dts = input_ClockGetTS( p_input, &p_pgrm->clock, ( p_block->i_dts + 11 ) * 9 / 100 ) + i_delay; } if( p_block->i_pts > 0 ) { p_block->i_pts = input_ClockGetTS( p_input, &p_pgrm->clock, ( p_block->i_pts + 11 ) * 9 / 100 ) + i_delay; } if ( 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_input->i_rate; /* TODO handle mute */ if( es->p_dec && ( es->fmt.i_cat != AUDIO_ES || p_input->i_rate == INPUT_RATE_DEFAULT ) ) { input_DecoderDecode( es->p_dec, p_block ); } 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -