📄 ts.c
字号:
/***************************************************************************** * ts.c: Transport Stream input module for VLC. ***************************************************************************** * Copyright (C) 2004 VideoLAN * $Id: ts.c 11057 2005-05-18 15:50:50Z fenrir $ * * Authors: Laurent Aimar <fenrir@via.ecp.fr> * * 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#include <stdlib.h> /* malloc(), free() */#include <ctype.h>#include <vlc/vlc.h>#include <vlc/input.h>#include "iso_lang.h"#include "network.h"#include "../mux/mpeg/csa.h"/* Include dvbpsi headers */#ifdef HAVE_DVBPSI_DR_H# include <dvbpsi/dvbpsi.h># include <dvbpsi/demux.h># include <dvbpsi/descriptor.h># include <dvbpsi/pat.h># include <dvbpsi/pmt.h># include <dvbpsi/sdt.h># include <dvbpsi/dr.h># include <dvbpsi/psi.h>#else# include "dvbpsi.h"# include "demux.h"# include "descriptor.h"# include "tables/pat.h"# include "tables/pmt.h"# include "tables/sdt.h"# include "descriptors/dr.h"# include "psi.h"#endif/* EIT support */#ifdef _DVBPSI_DR_4D_H_# define TS_USE_DVB_SI 1# ifdef HAVE_DVBPSI_DR_H# include <dvbpsi/eit.h># else# include "tables/eit.h"# endif#endif/* TODO: * - XXX: do not mark options message to be translated, they are too osbcure for now ... * - test it * - ... *//***************************************************************************** * Module descriptor *****************************************************************************/static int Open ( vlc_object_t * );static void Close ( vlc_object_t * );#define PMT_TEXT N_("Extra PMT")#define PMT_LONGTEXT N_( \ "Allows a user to specify an extra pmt (pmt_pid=pid:stream_type[,...])" )#define PID_TEXT N_("Set id of ES to PID")#define PID_LONGTEXT N_("set id of es to pid")#define TSOUT_TEXT N_("Fast udp streaming")#define TSOUT_LONGTEXT N_( \ "Sends TS to specific ip:port by udp (you must know what you are doing)")#define MTUOUT_TEXT N_("MTU for out mode")#define MTUOUT_LONGTEXT N_("MTU for out mode")#define CSA_TEXT N_("CSA ck")#define CSA_LONGTEXT N_("CSA ck")#define SILENT_TEXT N_("Silent mode")#define SILENT_LONGTEXT N_("do not complain on encrypted PES")#define CAPMT_SYSID_TEXT N_("CAPMT System ID")#define CAPMT_SYSID_LONGTEXT N_("only forward descriptors from this SysID to the CAM")vlc_module_begin(); set_description( _("MPEG Transport Stream demuxer") ); set_shortname ( "MPEG-TS" ); set_category( CAT_INPUT ); set_subcategory( SUBCAT_INPUT_DEMUX ); add_string( "ts-extra-pmt", NULL, NULL, PMT_TEXT, PMT_LONGTEXT, VLC_TRUE ); add_bool( "ts-es-id-pid", 0, NULL, PID_TEXT, PID_LONGTEXT, VLC_TRUE ); add_string( "ts-out", NULL, NULL, TSOUT_TEXT, TSOUT_LONGTEXT, VLC_TRUE ); add_integer( "ts-out-mtu", 1500, NULL, MTUOUT_TEXT, MTUOUT_LONGTEXT, VLC_TRUE ); add_string( "ts-csa-ck", NULL, NULL, CSA_TEXT, CSA_LONGTEXT, VLC_TRUE ); add_bool( "ts-silent", 0, NULL, SILENT_TEXT, SILENT_LONGTEXT, VLC_TRUE ); set_capability( "demux2", 10 ); set_callbacks( Open, Close ); add_shortcut( "ts" );vlc_module_end();/***************************************************************************** * Local prototypes *****************************************************************************/typedef struct{ uint8_t i_objectTypeIndication; uint8_t i_streamType; vlc_bool_t b_upStream; uint32_t i_bufferSizeDB; uint32_t i_maxBitrate; uint32_t i_avgBitrate; int i_decoder_specific_info_len; uint8_t *p_decoder_specific_info;} decoder_config_descriptor_t;typedef struct{ vlc_bool_t b_useAccessUnitStartFlag; vlc_bool_t b_useAccessUnitEndFlag; vlc_bool_t b_useRandomAccessPointFlag; vlc_bool_t b_useRandomAccessUnitsOnlyFlag; vlc_bool_t b_usePaddingFlag; vlc_bool_t b_useTimeStampsFlags; vlc_bool_t b_useIdleFlag; vlc_bool_t b_durationFlag; uint32_t i_timeStampResolution; uint32_t i_OCRResolution; uint8_t i_timeStampLength; uint8_t i_OCRLength; uint8_t i_AU_Length; uint8_t i_instantBitrateLength; uint8_t i_degradationPriorityLength; uint8_t i_AU_seqNumLength; uint8_t i_packetSeqNumLength; uint32_t i_timeScale; uint16_t i_accessUnitDuration; uint16_t i_compositionUnitDuration; uint64_t i_startDecodingTimeStamp; uint64_t i_startCompositionTimeStamp;} sl_config_descriptor_t;typedef struct{ vlc_bool_t b_ok; uint16_t i_es_id; vlc_bool_t b_streamDependenceFlag; vlc_bool_t b_OCRStreamFlag; uint8_t i_streamPriority; char *psz_url; uint16_t i_dependOn_es_id; uint16_t i_OCR_es_id; decoder_config_descriptor_t dec_descr; sl_config_descriptor_t sl_descr;} es_mpeg4_descriptor_t;typedef struct{ uint8_t i_iod_label, i_iod_label_scope; /* IOD */ uint16_t i_od_id; char *psz_url; uint8_t i_ODProfileLevelIndication; uint8_t i_sceneProfileLevelIndication; uint8_t i_audioProfileLevelIndication; uint8_t i_visualProfileLevelIndication; uint8_t i_graphicsProfileLevelIndication; es_mpeg4_descriptor_t es_descr[255];} iod_descriptor_t;typedef struct{ dvbpsi_handle handle; int i_version; int i_number; int i_pid_pcr; int i_pid_pmt; /* IOD stuff (mpeg4) */ iod_descriptor_t *iod;} ts_prg_psi_t;typedef struct{ /* for special PAT/SDT case */ dvbpsi_handle handle; /* PAT/SDT/EIT */ int i_pat_version; int i_sdt_version; /* For PMT */ int i_prg; ts_prg_psi_t **prg;} ts_psi_t;typedef struct{ es_format_t fmt; es_out_id_t *id; int i_pes_size; int i_pes_gathered; block_t *p_pes; block_t **pp_last; es_mpeg4_descriptor_t *p_mpeg4desc; int b_gather;} ts_es_t;typedef struct{ int i_pid; vlc_bool_t b_seen; vlc_bool_t b_valid; int i_cc; /* countinuity counter */ /* PSI owner (ie PMT -> PAT, ES -> PMT */ ts_psi_t *p_owner; int i_owner_number; /* */ ts_psi_t *psi; ts_es_t *es; /* Some private streams encapsulate several ES (eg. DVB subtitles)*/ ts_es_t **extra_es; int i_extra_es;} ts_pid_t;struct demux_sys_t{ /* TS packet size (188, 192, 204) */ int i_packet_size; /* how many TS packet we read at once */ int i_ts_read; /* All pid */ ts_pid_t pid[8192]; /* All PMT */ int i_pmt; ts_pid_t **pmt; /* */ vlc_bool_t b_es_id_pid; csa_t *csa; vlc_bool_t b_silent; vlc_bool_t b_udp_out; int fd; /* udp socket */ uint8_t *buffer; vlc_bool_t b_dvb_control; int i_dvb_program; vlc_list_t *p_programs_list; /* */ vlc_bool_t b_meta;};static int Demux ( demux_t *p_demux );static int Control( demux_t *p_demux, int i_query, va_list args );static void PIDInit ( ts_pid_t *pid, vlc_bool_t b_psi, ts_psi_t *p_owner );static void PIDClean( es_out_t *out, ts_pid_t *pid );static int PIDFillFormat( ts_pid_t *pid, int i_stream_type );static void PATCallBack( demux_t *, dvbpsi_pat_t * );static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt );#ifdef TS_USE_DVB_SIstatic void PSINewTableCallBack( demux_t *, dvbpsi_handle, uint8_t i_table_id, uint16_t i_extension );#endifstatic inline int PIDGet( block_t *p ){ return ( (p->p_buffer[1]&0x1f)<<8 )|p->p_buffer[2];}static vlc_bool_t GatherPES( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk );static void PCRHandle( demux_t *p_demux, ts_pid_t *, block_t * );static iod_descriptor_t *IODNew( int , uint8_t * );static void IODFree( iod_descriptor_t * );#define TS_PACKET_SIZE_188 188#define TS_PACKET_SIZE_192 192#define TS_PACKET_SIZE_204 204#define TS_PACKET_SIZE_MAX 204/***************************************************************************** * Open *****************************************************************************/static int Open( vlc_object_t *p_this ){ demux_t *p_demux = (demux_t*)p_this; demux_sys_t *p_sys; uint8_t *p_peek; int i_sync, i_peek, i; int i_packet_size; ts_pid_t *pat; vlc_value_t val; if( stream_Peek( p_demux->s, &p_peek, TS_PACKET_SIZE_MAX ) < TS_PACKET_SIZE_MAX ) return VLC_EGENERIC; /* Search first sync byte */ for( i_sync = 0; i_sync < TS_PACKET_SIZE_MAX; i_sync++ ) { if( p_peek[i_sync] == 0x47 ) break; } if( i_sync >= TS_PACKET_SIZE_MAX ) { if( strcmp( p_demux->psz_demux, "ts" ) ) return VLC_EGENERIC; msg_Warn( p_demux, "this does not look like a TS stream, continuing" ); } /* Check next 3 sync bytes */ i_peek = TS_PACKET_SIZE_MAX * 3 + i_sync + 1; if( ( stream_Peek( p_demux->s, &p_peek, i_peek ) ) < i_peek ) { msg_Err( p_demux, "cannot peek" ); return VLC_EGENERIC; } if( p_peek[i_sync + TS_PACKET_SIZE_188] == 0x47 && p_peek[i_sync + 2 * TS_PACKET_SIZE_188] == 0x47 && p_peek[i_sync + 3 * TS_PACKET_SIZE_188] == 0x47 ) { i_packet_size = TS_PACKET_SIZE_188; } else if( p_peek[i_sync + TS_PACKET_SIZE_192] == 0x47 && p_peek[i_sync + 2 * TS_PACKET_SIZE_192] == 0x47 && p_peek[i_sync + 3 * TS_PACKET_SIZE_192] == 0x47 ) { i_packet_size = TS_PACKET_SIZE_192; } else if( p_peek[i_sync + TS_PACKET_SIZE_204] == 0x47 && p_peek[i_sync + 2 * TS_PACKET_SIZE_204] == 0x47 && p_peek[i_sync + 3 * TS_PACKET_SIZE_204] == 0x47 ) { i_packet_size = TS_PACKET_SIZE_204; } else if( !strcmp( p_demux->psz_demux, "ts" ) ) { i_packet_size = TS_PACKET_SIZE_188; } else { msg_Warn( p_demux, "TS module discarded (lost sync)" ); return VLC_EGENERIC; } /* Fill p_demux field */ p_demux->pf_demux = Demux; p_demux->pf_control = Control; p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) ); memset( p_sys, 0, sizeof( demux_sys_t ) );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -