📄 es_out.c
字号:
/***************************************************************************** * es_out.c: Es Out handler for input. ***************************************************************************** * Copyright (C) 2003-2004 the VideoLAN team * $Id: f1b4f3810e4c05982c2a328b9cda4acec28773c3 $ * * Authors: Laurent Aimar <fenrir@via.ecp.fr> * Jean-Paul Saman <jpsaman #_at_# m2x dot nl> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#ifdef HAVE_CONFIG_H# include "config.h"#endif#include <vlc_common.h>#include <stdio.h>#include <vlc_input.h>#include <vlc_es_out.h>#include <vlc_block.h>#include <vlc_aout.h>#include "input_internal.h"#include <vlc_iso_lang.h>/* FIXME we should find a better way than including that */#include "../text/iso-639_def.h"/***************************************************************************** * Local prototypes *****************************************************************************/typedef struct{ /* Program ID */ int i_id; /* Number of es for this pgrm */ int i_es; bool b_selected; /* Clock for this program */ input_clock_t clock; char *psz_name; char *psz_now_playing; char *psz_publisher; vlc_epg_t *p_epg;} es_out_pgrm_t;struct es_out_id_t{ /* ES ID */ int i_id; es_out_pgrm_t *p_pgrm; /* Misc. */ int64_t i_preroll_end; /* Channel in the track type */ int i_channel; es_format_t fmt; char *psz_language; char *psz_language_code; decoder_t *p_dec; /* Fields for Video with CC */ bool pb_cc_present[4]; es_out_id_t *pp_cc_es[4]; /* Field for CC track from a master video */ es_out_id_t *p_master;};struct es_out_sys_t{ input_thread_t *p_input; /* all programs */ int i_pgrm; es_out_pgrm_t **pgrm; es_out_pgrm_t **pp_selected_pgrm; /* --programs */ es_out_pgrm_t *p_pgrm; /* Master program */ /* all es */ int i_id; int i_es; es_out_id_t **es; /* mode gestion */ bool b_active; int i_mode; /* es count */ int i_audio; int i_video; int i_sub; /* es to select */ int i_audio_last, i_audio_id; int i_sub_last, i_sub_id; int i_default_sub_id; /* As specified in container; if applicable */ char **ppsz_audio_language; char **ppsz_sub_language; /* current main es */ es_out_id_t *p_es_audio; es_out_id_t *p_es_video; es_out_id_t *p_es_sub; /* delay */ int64_t i_audio_delay; int64_t i_spu_delay; /* Rate used to rescale ES ts */ int i_rate;};static es_out_id_t *EsOutAdd ( es_out_t *, es_format_t * );static int EsOutSend ( es_out_t *, es_out_id_t *, block_t * );static void EsOutDel ( es_out_t *, es_out_id_t * );static void EsOutSelect( es_out_t *out, es_out_id_t *es, bool b_force );static int EsOutControl( es_out_t *, int i_query, va_list );static void EsOutAddInfo( es_out_t *, es_out_id_t *es );static bool EsIsSelected( es_out_id_t *es );static void EsSelect( es_out_t *out, es_out_id_t *es );static void EsUnselect( es_out_t *out, es_out_id_t *es, bool b_update );static char *LanguageGetName( const char *psz_code );static char *LanguageGetCode( const char *psz_lang );static char **LanguageSplit( const char *psz_langs );static int LanguageArrayIndex( char **ppsz_langs, char *psz_lang );static char *EsOutProgramGetMetaName( es_out_pgrm_t *p_pgrm );static const vlc_fourcc_t EsOutFourccClosedCaptions[4] = { VLC_FOURCC('c', 'c', '1', ' '), VLC_FOURCC('c', 'c', '2', ' '), VLC_FOURCC('c', 'c', '3', ' '), VLC_FOURCC('c', 'c', '4', ' '),};static inline int EsOutGetClosedCaptionsChannel( vlc_fourcc_t fcc ){ int i; for( i = 0; i < 4; i++ ) { if( fcc == EsOutFourccClosedCaptions[i] ) return i; } return -1;}/***************************************************************************** * input_EsOutNew: *****************************************************************************/es_out_t *input_EsOutNew( input_thread_t *p_input, int i_rate ){ vlc_value_t val; int i; es_out_t *out = malloc( sizeof( es_out_t ) ); if( !out ) return NULL; es_out_sys_t *p_sys = malloc( sizeof( es_out_sys_t ) ); if( !p_sys ) { free( out ); return NULL; } out->pf_add = EsOutAdd; out->pf_send = EsOutSend; out->pf_del = EsOutDel; out->pf_control = EsOutControl; out->p_sys = p_sys; out->b_sout = p_input->p->p_sout != NULL; p_sys->p_input = p_input; p_sys->b_active = false; p_sys->i_mode = ES_OUT_MODE_AUTO; TAB_INIT( p_sys->i_pgrm, p_sys->pgrm ); p_sys->p_pgrm = NULL; p_sys->i_id = 0; TAB_INIT( p_sys->i_es, p_sys->es ); p_sys->i_audio = 0; p_sys->i_video = 0; p_sys->i_sub = 0; /* */ var_Get( p_input, "audio-track", &val ); p_sys->i_audio_last = val.i_int; var_Get( p_input, "sub-track", &val ); p_sys->i_sub_last = val.i_int; p_sys->i_default_sub_id = -1; if( !p_input->b_preparsing ) { var_Get( p_input, "audio-language", &val ); p_sys->ppsz_audio_language = LanguageSplit(val.psz_string); if( p_sys->ppsz_audio_language ) { for( i = 0; p_sys->ppsz_audio_language[i]; i++ ) msg_Dbg( p_input, "selected audio language[%d] %s", i, p_sys->ppsz_audio_language[i] ); } free( val.psz_string ); var_Get( p_input, "sub-language", &val ); p_sys->ppsz_sub_language = LanguageSplit(val.psz_string); if( p_sys->ppsz_sub_language ) { for( i = 0; p_sys->ppsz_sub_language[i]; i++ ) msg_Dbg( p_input, "selected subtitle language[%d] %s", i, p_sys->ppsz_sub_language[i] ); } free( val.psz_string ); } else { p_sys->ppsz_sub_language = NULL; p_sys->ppsz_audio_language = NULL; } var_Get( p_input, "audio-track-id", &val ); p_sys->i_audio_id = val.i_int; var_Get( p_input, "sub-track-id", &val ); p_sys->i_sub_id = val.i_int; p_sys->p_es_audio = NULL; p_sys->p_es_video = NULL; p_sys->p_es_sub = NULL; p_sys->i_audio_delay= 0; p_sys->i_spu_delay = 0; p_sys->i_rate = i_rate; return out;}/***************************************************************************** * input_EsOutDelete: *****************************************************************************/void input_EsOutDelete( es_out_t *out ){ es_out_sys_t *p_sys = out->p_sys; int i; for( i = 0; i < p_sys->i_es; i++ ) { if( p_sys->es[i]->p_dec ) { input_DecoderDelete( p_sys->es[i]->p_dec ); } free( p_sys->es[i]->psz_language ); free( p_sys->es[i]->psz_language_code ); es_format_Clean( &p_sys->es[i]->fmt ); free( p_sys->es[i] ); } if( p_sys->ppsz_audio_language ) { for( i = 0; p_sys->ppsz_audio_language[i]; i++ ) free( p_sys->ppsz_audio_language[i] ); free( p_sys->ppsz_audio_language ); } if( p_sys->ppsz_sub_language ) { for( i = 0; p_sys->ppsz_sub_language[i]; i++ ) free( p_sys->ppsz_sub_language[i] ); free( p_sys->ppsz_sub_language ); } free( p_sys->es ); /* FIXME duplicate work EsOutProgramDel (but we cannot use it) add a EsOutProgramClean ? */ for( i = 0; i < p_sys->i_pgrm; i++ ) { es_out_pgrm_t *p_pgrm = p_sys->pgrm[i]; free( p_pgrm->psz_now_playing ); free( p_pgrm->psz_publisher ); free( p_pgrm->psz_name ); if( p_pgrm->p_epg ) vlc_epg_Delete( p_pgrm->p_epg ); free( p_pgrm ); } TAB_CLEAN( p_sys->i_pgrm, p_sys->pgrm ); free( p_sys ); free( out );}es_out_id_t *input_EsOutGetFromID( es_out_t *out, int i_id ){ int i; if( i_id < 0 ) { /* Special HACK, -i_id is tha cat of the stream */ return (es_out_id_t*)((uint8_t*)NULL-i_id); } for( i = 0; i < out->p_sys->i_es; i++ ) { if( out->p_sys->es[i]->i_id == i_id ) return out->p_sys->es[i]; } return NULL;}static void EsOutDiscontinuity( es_out_t *out, bool b_flush, bool b_audio ){ es_out_sys_t *p_sys = out->p_sys; int i; for( i = 0; i < p_sys->i_es; i++ ) { es_out_id_t *es = p_sys->es[i]; /* Send a dummy block to let decoder know that * there is a discontinuity */ if( es->p_dec && ( !b_audio || es->fmt.i_cat == AUDIO_ES ) ) input_DecoderDiscontinuity( es->p_dec, b_flush ); }}void input_EsOutChangeRate( es_out_t *out, int i_rate ){ es_out_sys_t *p_sys = out->p_sys; int i; p_sys->i_rate = i_rate; EsOutDiscontinuity( out, false, false ); for( i = 0; i < p_sys->i_pgrm; i++ ) input_ClockSetRate( &p_sys->pgrm[i]->clock, i_rate );}void input_EsOutSetDelay( es_out_t *out, int i_cat, int64_t i_delay ){ es_out_sys_t *p_sys = out->p_sys; if( i_cat == AUDIO_ES ) p_sys->i_audio_delay = i_delay; else if( i_cat == SPU_ES ) p_sys->i_spu_delay = i_delay;}void input_EsOutChangeState( es_out_t *out ){ es_out_sys_t *p_sys = out->p_sys; input_thread_t *p_input = p_sys->p_input; if( p_input->i_state == PAUSE_S ) { /* Send discontinuity to decoders (it will allow them to flush * * if implemented */ EsOutDiscontinuity( out, false, false ); } else { /* Out of pause, reset pcr */ es_out_Control( out, ES_OUT_RESET_PCR ); }}void input_EsOutChangePosition( es_out_t *out ){ //es_out_sys_t *p_sys = out->p_sys; es_out_Control( out, ES_OUT_RESET_PCR ); EsOutDiscontinuity( out, true, false );}bool input_EsOutDecodersEmpty( es_out_t *out ){ es_out_sys_t *p_sys = out->p_sys; int i; for( i = 0; i < p_sys->i_es; i++ ) { es_out_id_t *es = p_sys->es[i]; if( es->p_dec && !input_DecoderEmpty( es->p_dec ) ) return false; } return true;}/***************************************************************************** * *****************************************************************************/static void EsOutESVarUpdateGeneric( es_out_t *out, int i_id, es_format_t *fmt, const char *psz_language, bool b_delete ){ es_out_sys_t *p_sys = out->p_sys; input_thread_t *p_input = p_sys->p_input; const bool b_teletext = fmt->i_cat == SPU_ES && fmt->i_codec == VLC_FOURCC( 't', 'e', 'l', 'x' );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -