⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ty.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 5 页
字号:
/***************************************************************************** * ty.c - TiVo ty stream video demuxer for VLC ***************************************************************************** * Copyright (C) 2005 the VideoLAN team * Copyright (C) 2005 by Neal Symms (tivo@freakinzoo.com) - February 2005 * based on code by Christopher Wingert for tivo-mplayer * tivo(at)wingert.org, February 2003 * * $Id$ * * 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. * * CODE CHANGES: * v1.0.0 - 24-Feb-2005 - Initial release - Series 1 support ONLY! * v1.0.1 - 25-Feb-2005 - Added fix for bad GOP headers - Neal * v1.0.2 - 26-Feb-2005 - No longer require "seekable" input stream - Neal * v2.0.0 - 21-Mar-2005 - Series 2 support!  No AC-3 on S2 DTivo yet. * v2.1.0 - 22-Mar-2005 - Support for AC-3 on S2 DTivo (long ac3 packets) * v3.0.0 - 14-Jul-2005 - Support for skipping fwd/back via VLC hotkeys *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#ifdef HAVE_CONFIG_H# include "config.h"#endif#include <vlc_common.h>#include <vlc_plugin.h>#include <vlc_demux.h>#include "vlc_codec.h"#include "vlc_meta.h"#include "vlc_input.h"#include "../codec/cc.h"#include <assert.h>/***************************************************************************** * Module descriptor *****************************************************************************/static int  Open ( vlc_object_t * );static void Close( vlc_object_t * );vlc_module_begin();    set_shortname( N_("TY") );    set_description(N_("TY Stream audio/video demux"));    set_category( CAT_INPUT );    set_subcategory( SUBCAT_INPUT_DEMUX );    set_capability("demux", 6);    /* FIXME: there seems to be a segfault when using PVR access     * and TY demux has a bigger priority than PS     * Something must be wrong.     */    set_callbacks( Open, Close );    add_shortcut("ty");    add_shortcut("tivo");vlc_module_end();/***************************************************************************** * Local prototypes *****************************************************************************/static int Demux  ( demux_t * );static int Control( demux_t *, int, va_list );#define SERIES1_PES_LENGTH  (11)    /* length of audio PES hdr on S1 */#define SERIES2_PES_LENGTH  (16)    /* length of audio PES hdr on S2 */#define AC3_PES_LENGTH      (14)    /* length of audio PES hdr for AC3 */#define VIDEO_PES_LENGTH    (16)    /* length of video PES header */#define DTIVO_PTS_OFFSET    (6)     /* offs into PES for MPEG PTS on DTivo */#define SA_PTS_OFFSET       (9)     /* offset into PES for MPEG PTS on SA */#define AC3_PTS_OFFSET      (9)     /* offset into PES for AC3 PTS on DTivo */#define VIDEO_PTS_OFFSET    (9)     /* offset into PES for video PTS on all */#define AC3_PKT_LENGTH      (1536)  /* size of TiVo AC3 pkts (w/o PES hdr) */static const uint8_t ty_VideoPacket[] = { 0x00, 0x00, 0x01, 0xe0 };static const uint8_t ty_MPEGAudioPacket[] = { 0x00, 0x00, 0x01, 0xc0 };static const uint8_t ty_AC3AudioPacket[] = { 0x00, 0x00, 0x01, 0xbd };#define CHUNK_PEEK_COUNT    (3)         /* number of chunks to probe *//* packet types for reference: 2/c0: audio data continued 3/c0: audio packet header (PES header) 4/c0: audio data (S/A only?) 9/c0: audio packet header, AC-3 audio 2/e0: video data continued 6/e0: video packet header (PES header) 7/e0: video sequence header start 8/e0: video I-frame header start a/e0: video P-frame header start b/e0: video B-frame header start c/e0: video GOP header start e/01: closed-caption data e/02: Extended data services data  e/03: ipreview data ("thumbs up to record" signal) e/05: UK Teletext*/#define TIVO_PES_FILEID   ( 0xf5467abd )#define TIVO_PART_LENGTH  ( 0x20000000 )    /* 536,870,912 bytes */#define CHUNK_SIZE        ( 128 * 1024 )typedef struct{  long l_rec_size;  uint8_t ex1, ex2;  uint8_t rec_type;  uint8_t subrec_type;  bool b_ext;  uint64_t l_ty_pts;            /* TY PTS in the record header */} ty_rec_hdr_t;typedef struct{    uint64_t l_timestamp;    uint8_t chunk_bitmask[8];} ty_seq_table_t;typedef enum{    TIVO_TYPE_UNKNOWN,    TIVO_TYPE_SA,    TIVO_TYPE_DTIVO} tivo_type_t;typedef enum{    TIVO_SERIES_UNKNOWN,    TIVO_SERIES1,    TIVO_SERIES2} tivo_series_t;typedef enum{    TIVO_AUDIO_UNKNOWN,    TIVO_AUDIO_AC3,    TIVO_AUDIO_MPEG} tivo_audio_t;#define XDS_MAX_DATA_SIZE (32)typedef enum{    XDS_CLASS_CURRENT        = 0,    XDS_CLASS_FUTURE         = 1,    XDS_CLASS_CHANNEL        = 2,    XDS_CLASS_MISCELLANEOUS  = 3,    XDS_CLASS_PUBLIC_SERVICE = 4,    XDS_CLASS_RESERVED       = 5,    XDS_CLASS_UNDEFINED      = 6,    XDS_CLASS_OTHER          = 7,    XDS_MAX_CLASS_COUNT} xds_class_t;typedef struct{    bool b_started;    int        i_data;    uint8_t    p_data[XDS_MAX_DATA_SIZE];    int        i_sum;} xds_packet_t;typedef enum{    XDS_META_PROGRAM_RATING_NONE,    XDS_META_PROGRAM_RATING_MPAA,    XDS_META_PROGRAM_RATING_TPG,    /* TODO add CA/CE rating */} xds_meta_program_rating_t;typedef struct{    char *psz_name;    xds_meta_program_rating_t rating;    char *psz_rating;    /* Add the other fields once I have the samples */} xds_meta_program_t;typedef struct{    char *psz_channel_name;    char *psz_channel_call_letter;    char *psz_channel_number;    xds_meta_program_t  current;    xds_meta_program_t  future;} xds_meta_t;typedef struct{    /* Are we in XDS mode */    bool b_xds;    /* Current class type */    xds_class_t i_class;    int         i_type;    bool  b_future;    /* */    xds_packet_t pkt[XDS_MAX_CLASS_COUNT][128]; /* XXX it is way too much, but simpler */    /* */    bool  b_meta_changed;    xds_meta_t  meta;} xds_t;struct demux_sys_t{  es_out_id_t *p_video;               /* ptr to video codec */  es_out_id_t *p_audio;               /* holds either ac3 or mpeg codec ptr */  cc_data_t   cc;  es_out_id_t *p_cc[4];  xds_t       xds;  int             i_cur_chunk;  int             i_stuff_cnt;  size_t          i_stream_size;      /* size of input stream (if known) */  //uint64_t        l_program_len;      /* length of this stream in msec */  bool      b_seekable;         /* is this stream seekable? */  bool      b_have_master;      /* are master chunks present? */  tivo_type_t     tivo_type;          /* tivo type (SA / DTiVo) */  tivo_series_t   tivo_series;        /* Series1 or Series2 */  tivo_audio_t    audio_type;         /* AC3 or MPEG */  int             i_Pes_Length;       /* Length of Audio PES header */  int             i_Pts_Offset;       /* offset into audio PES of PTS */  uint8_t         pes_buffer[20];     /* holds incomplete pes headers */  int             i_pes_buf_cnt;      /* how many bytes in our buffer */  size_t          l_ac3_pkt_size;     /* len of ac3 pkt we've seen so far */  uint64_t        l_last_ty_pts;      /* last TY timestamp we've seen */  //mtime_t         l_last_ty_pts_sync; /* audio PTS at time of last TY PTS */  uint64_t        l_first_ty_pts;     /* first TY PTS in this master chunk */  uint64_t        l_final_ty_pts;     /* final TY PTS in this master chunk */  int             i_seq_table_size;   /* number of entries in SEQ table */  int             i_bits_per_seq_entry; /* # of bits in SEQ table bitmask */  mtime_t         firstAudioPTS;  mtime_t         lastAudioPTS;  mtime_t         lastVideoPTS;  ty_rec_hdr_t    *rec_hdrs;          /* record headers array */  int             i_cur_rec;          /* current record in this chunk */  int             i_num_recs;         /* number of recs in this chunk */  int             i_seq_rec;          /* record number where seq start is */  ty_seq_table_t  *seq_table;         /* table of SEQ entries from mstr chk */  bool      eof;  bool      b_first_chunk;};static int get_chunk_header(demux_t *);static mtime_t get_pts( const uint8_t *buf );static int find_es_header( const uint8_t *header,                           const uint8_t *buffer, int i_search_len );static int ty_stream_seek_pct(demux_t *p_demux, double seek_pct);static int ty_stream_seek_time(demux_t *, uint64_t);static ty_rec_hdr_t *parse_chunk_headers( const uint8_t *p_buf,                                          int i_num_recs, int *pi_payload_size);static int probe_stream(demux_t *p_demux);static void analyze_chunk(demux_t *p_demux, const uint8_t *p_chunk);static void parse_master(demux_t *p_demux);static int DemuxRecVideo( demux_t *p_demux, ty_rec_hdr_t *rec_hdr, block_t *p_block_in );static int DemuxRecAudio( demux_t *p_demux, ty_rec_hdr_t *rec_hdr, block_t *p_block_in );static int DemuxRecCc( demux_t *p_demux, ty_rec_hdr_t *rec_hdr, block_t *p_block_in );static void DemuxDecodeXds( demux_t *p_demux, uint8_t d1, uint8_t d2 );static void XdsInit( xds_t * );static void XdsExit( xds_t * );#define TY_ES_GROUP (1)/* * Open: check file and initialize demux structures * * here's what we do: * 1. peek at the first 12 bytes of the stream for the *    magic TiVo PART header & stream type & chunk size * 2. if it's not there, error with VLC_EGENERIC * 3. set up video (mpgv) codec * 4. return VLC_SUCCESS */static int Open(vlc_object_t *p_this){    demux_t *p_demux = (demux_t *)p_this;    demux_sys_t *p_sys;    es_format_t fmt;    const uint8_t *p_peek;    int i;    /* peek at the first 12 bytes. */    /* for TY streams, they're always the same */    if( stream_Peek( p_demux->s, &p_peek, 12 ) < 12 )        return VLC_EGENERIC;    if ( U32_AT(p_peek) != TIVO_PES_FILEID ||         U32_AT(&p_peek[4]) != 0x02 ||         U32_AT(&p_peek[8]) != CHUNK_SIZE )    {        if( !p_demux->b_force &&            !demux_IsPathExtension( p_demux, ".ty" ) &&            !demux_IsPathExtension( p_demux, ".ty+" ) )            return VLC_EGENERIC;        msg_Warn( p_demux, "this does not look like a TY file, "                           "continuing anyway..." );    }	/* at this point, we assume we have a valid TY stream */      msg_Dbg( p_demux, "valid TY stream detected" );    /* Set exported functions */    p_demux->pf_demux = Demux;    p_demux->pf_control = Control;    /* create our structure that will hold all data */    p_demux->p_sys = p_sys = malloc(sizeof(demux_sys_t));    memset(p_sys, 0, sizeof(demux_sys_t));    /* set up our struct (most were zero'd out with the memset above) */    p_sys->b_first_chunk = true;    p_sys->b_have_master = (U32_AT(p_peek) == TIVO_PES_FILEID);    p_sys->firstAudioPTS = -1;    p_sys->i_stream_size = stream_Size(p_demux->s);    p_sys->tivo_type = TIVO_TYPE_UNKNOWN;    p_sys->audio_type = TIVO_AUDIO_UNKNOWN;    p_sys->tivo_series = TIVO_SERIES_UNKNOWN;    p_sys->i_Pes_Length = 0;    p_sys->i_Pts_Offset = 0;    p_sys->l_ac3_pkt_size = 0;      /* see if this stream is seekable */    stream_Control( p_demux->s, STREAM_CAN_SEEK, &p_sys->b_seekable );    if (probe_stream(p_demux) != VLC_SUCCESS) {        //TyClose(p_demux);        return VLC_EGENERIC;    }    if (!p_sys->b_have_master)      msg_Warn(p_demux, "No master chunk found; seeking will be limited.");    /* register the proper audio codec */    if (p_sys->audio_type == TIVO_AUDIO_MPEG) {        es_format_Init( &fmt, AUDIO_ES, VLC_FOURCC( 'm', 'p', 'g', 'a' ) );    } else {        es_format_Init( &fmt, AUDIO_ES, VLC_FOURCC( 'a', '5', '2', ' ' ) );    }    fmt.i_group = TY_ES_GROUP;    p_sys->p_audio = es_out_Add( p_demux->out, &fmt );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -