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

📄 ty.c

📁 video linux conference
💻 C
📖 第 1 页 / 共 3 页
字号:
/***************************************************************************** * ty.c - TiVo ty stream video demuxer for VLC ***************************************************************************** * Copyright (C) 2005 VideoLAN * 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: ty.c 11257 2005-06-02 17:06:00Z fkuehne $ * * 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. * * 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 *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#include <stdlib.h>#include <vlc/vlc.h>#include <vlc/input.h>#include "vlc_codec.h"#define SERIES1_PES_LENGTH  (11)#define SERIES2_PES_LENGTH  (16)#define AC3_PES_LENGTH      (14)#define DTIVO_PTS_OFFSET    (6)#define SA_PTS_OFFSET       (9)#define AC3_PTS_OFFSET      (9)static const unsigned char ty_VideoPacket[] = { 0x00, 0x00, 0x01, 0xe0 };static const unsigned char ty_MPEGAudioPacket[] = { 0x00, 0x00, 0x01, 0xc0 };static const unsigned char ty_AC3AudioPacket[] = { 0x00, 0x00, 0x01, 0xbd };/***************************************************************************** * Local prototypes *****************************************************************************/static int get_chunk_header(demux_t *);static void setup_audio_streams(char, demux_t *);static mtime_t get_pts( unsigned char *buf );static int find_es_header( unsigned const char *header,   unsigned char *buffer, int bufferSize, int *esOffset1 );static int ty_stream_seek(demux_t *p_demux, double seek_pct);static int TyOpen (vlc_object_t *);static void TyClose(vlc_object_t *);static int TyDemux(demux_t *);static int Control(demux_t *, int, va_list);/***************************************************************************** * Module descriptor *****************************************************************************/vlc_module_begin();    set_shortname( "TY" );    set_description(_("TY Stream audio/video demux"));    set_category( CAT_INPUT );    set_subcategory( SUBCAT_INPUT_DEMUX );    set_capability("demux2", 8);    /* 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(TyOpen, TyClose);    add_shortcut("ty");    add_shortcut("tivo");vlc_module_end();/* 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)*/#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;  unsigned char ex1, ex2;  unsigned char rec_type;  unsigned char subrec_type;  char b_ext;} ty_rec_hdr_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 */  int             i_chunk_count;  int             i_stuff_cnt;  size_t          i_stream_size;      /* size of input stream (if known) */  vlc_bool_t      b_seekable;         /* is this stream seekable? */  int             tivoType;           /* 1 = SA, 2 = DTiVo */  vlc_bool_t      b_mpeg_audio;       /* true if we're using MPEG audio */  uint8_t         pes_buffer[20];     /* holds incomplete pes headers */  int             i_pes_buf_cnt;      /* how many bytes in our buffer */  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 */  vlc_bool_t      eof;  vlc_bool_t      b_first_chunk;};/* * TyOpen: 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 TyOpen(vlc_object_t *p_this){    demux_t *p_demux = (demux_t *)p_this;    demux_sys_t *p_sys;    es_format_t fmt;    uint8_t *p_peek;    /* 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 )    {        /* doesn't look like a TY file... */        char *psz_ext = strrchr(p_demux->psz_path, '.');        if( !p_demux->b_force &&            (!psz_ext || strcasecmp(psz_ext, ".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 = TyDemux;    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 = VLC_TRUE;    p_sys->firstAudioPTS = -1;    p_sys->i_stream_size = stream_Size(p_demux->s);    p_sys->b_mpeg_audio = VLC_FALSE;    /* see if this stream is seekable */    stream_Control( p_demux->s, STREAM_CAN_SEEK, &p_sys->b_seekable );    /* TODO: read first chunk & parse first audio PTS, then (if seekable)     *       seek to last chunk & last record; read its PTS and compute     *       overall program time.  Also determine Tivo type.   */    /* NOTE: we wait to create the audio ES until we know what     * audio type we have.   */    p_sys->p_audio = NULL;    /* register the video stream */    es_format_Init( &fmt, VIDEO_ES, VLC_FOURCC( 'm', 'p', 'g', 'v' ) );    p_sys->p_video = es_out_Add( p_demux->out, &fmt );#if 0    /* register the CC decoder */    es_format_Init( &fmt, SPU_ES, VLC_FOURCC('s', 'u', 'b', 't'));    p_sys->p_subt_es = es_out_Add(p_demux->out, &fmt);#endif    return VLC_SUCCESS;}/* set up audio codec. * this will be called once we determine audio type */static void setup_audio_streams(char stream_type, demux_t *p_demux){    demux_sys_t *p_sys = p_demux->p_sys;    es_format_t  fmt;    if (stream_type == 'A') {        /* AC3 audio detected */        es_format_Init( &fmt, AUDIO_ES, VLC_FOURCC( 'a', '5', '2', ' ' ) );        p_sys->tivoType = 2;      /* AC3 is only on dtivo */    } else {        /* assume MPEG */        es_format_Init( &fmt, AUDIO_ES, VLC_FOURCC( 'm', 'p', 'g', 'a' ) );        p_sys->b_mpeg_audio = VLC_TRUE;    }    /* register the chosen audio output codec */    p_sys->p_audio = es_out_Add( p_demux->out, &fmt );}/* =========================================================================== *//* Compute Presentation Time Stamp (PTS) * Assume buf points to beginning of PTS */static mtime_t get_pts( unsigned char *buf ){    mtime_t i_pts;    i_pts = ((mtime_t)(buf[0]&0x0e ) << 29)|             (mtime_t)(buf[1] << 22)|            ((mtime_t)(buf[2]&0xfe) << 14)|             (mtime_t)(buf[3] << 7)|             (mtime_t)(buf[4] >> 1);    i_pts *= 100 / 9;   /* convert PTS (90Khz clock) to microseconds */    return i_pts;}/* =========================================================================== */static int find_es_header( unsigned const char *header,   unsigned char *buffer, int bufferSize, int *esOffset1 ){    int count;    *esOffset1 = -1;    for( count = 0 ; count < bufferSize ; count++ )    {        if ( ( buffer[ count + 0 ] == header[ 0 ] ) &&             ( buffer[ count + 1 ] == header[ 1 ] ) &&             ( buffer[ count + 2 ] == header[ 2 ] ) &&             ( buffer[ count + 3 ] == header[ 3 ] ) )        {            *esOffset1 = count;            return 1;        }    }    return( -1 );}/* =========================================================================== *//* check if we have a full PES header, if not, then save what we have. * this is called when audio-start packets are encountered. * Returns: *     1 partial PES hdr found, some audio data found (buffer adjusted), *    -1 partial PES hdr found, no audio data found *     0 otherwise (complete PES found, pts extracted, pts set, buffer adjusted) *//* TODO: fix it so it works with S2 / SA / DTivo / HD etc... */static int check_sync_pes( demux_t *p_demux, block_t *p_block,                           int32_t offset, int32_t rec_len ){    demux_sys_t *p_sys = p_demux->p_sys;    int pts_offset;    int pes_length = p_sys->b_mpeg_audio?SERIES1_PES_LENGTH:AC3_PES_LENGTH;    if( p_sys->tivoType == 1 )    {        /* SA tivo */        pts_offset = SA_PTS_OFFSET;    }    else    {        /* DTivo */        pts_offset = p_sys->b_mpeg_audio?DTIVO_PTS_OFFSET:AC3_PTS_OFFSET;    }    if ( offset < 0 || offset + pes_length > rec_len )    {        /* entire PES header not present */        msg_Dbg( p_demux, "PES header at %d not complete in record. storing.",                 offset );        /* save the partial pes header */        if( offset < 0 )        {            /* no header found, fake some 00's (this works, believe me) */            memset( p_sys->pes_buffer, 4, 0 );            p_sys->i_pes_buf_cnt = 4;            if( rec_len > 4 )                msg_Err( p_demux, "PES header not found in record of %d bytes!",                         rec_len );            return -1;        }        /* copy the partial pes header we found */        memcpy( p_sys->pes_buffer, p_block->p_buffer + offset,                rec_len - offset );        p_sys->i_pes_buf_cnt = rec_len - offset;

⌨️ 快捷键说明

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