ty.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:69k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * ty.c - TiVo ty stream video demuxer for VLC
  3.  *****************************************************************************
  4.  * Copyright (C) 2005 the VideoLAN team
  5.  * Copyright (C) 2005 by Neal Symms (tivo@freakinzoo.com) - February 2005
  6.  * based on code by Christopher Wingert for tivo-mplayer
  7.  * tivo(at)wingert.org, February 2003
  8.  *
  9.  * $Id: 8ead0bf3fa4aab9ab568edc54086657f4cc4bc44 $
  10.  *
  11.  * This program is free software; you can redistribute it and/or modify
  12.  * it under the terms of the GNU General Public License as published by
  13.  * the Free Software Foundation; either version 2 of the License, or
  14.  * (at your option) any later version.
  15.  *
  16.  * This program is distributed in the hope that it will be useful,
  17.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  * GNU General Public License for more details.
  20.  *
  21.  * You should have received a copy of the GNU General Public License
  22.  * along with this program; if not, write to the Free Software
  23.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  24.  *
  25.  * CODE CHANGES:
  26.  * v1.0.0 - 24-Feb-2005 - Initial release - Series 1 support ONLY!
  27.  * v1.0.1 - 25-Feb-2005 - Added fix for bad GOP headers - Neal
  28.  * v1.0.2 - 26-Feb-2005 - No longer require "seekable" input stream - Neal
  29.  * v2.0.0 - 21-Mar-2005 - Series 2 support!  No AC-3 on S2 DTivo yet.
  30.  * v2.1.0 - 22-Mar-2005 - Support for AC-3 on S2 DTivo (long ac3 packets)
  31.  * v3.0.0 - 14-Jul-2005 - Support for skipping fwd/back via VLC hotkeys
  32.  *****************************************************************************/
  33. /*****************************************************************************
  34.  * Preamble
  35.  *****************************************************************************/
  36. #ifdef HAVE_CONFIG_H
  37. # include "config.h"
  38. #endif
  39. #include <vlc_common.h>
  40. #include <vlc_plugin.h>
  41. #include <vlc_demux.h>
  42. #include "vlc_codec.h"
  43. #include "vlc_meta.h"
  44. #include "vlc_input.h"
  45. #include "../codec/cc.h"
  46. #include <assert.h>
  47. /*****************************************************************************
  48.  * Module descriptor
  49.  *****************************************************************************/
  50. static int  Open ( vlc_object_t * );
  51. static void Close( vlc_object_t * );
  52. vlc_module_begin ()
  53.     set_shortname( N_("TY") )
  54.     set_description(N_("TY Stream audio/video demux"))
  55.     set_category( CAT_INPUT )
  56.     set_subcategory( SUBCAT_INPUT_DEMUX )
  57.     set_capability("demux", 6)
  58.     /* FIXME: there seems to be a segfault when using PVR access
  59.      * and TY demux has a bigger priority than PS
  60.      * Something must be wrong.
  61.      */
  62.     set_callbacks( Open, Close )
  63.     add_shortcut("ty")
  64.     add_shortcut("tivo")
  65. vlc_module_end ()
  66. /*****************************************************************************
  67.  * Local prototypes
  68.  *****************************************************************************/
  69. static int Demux  ( demux_t * );
  70. static int Control( demux_t *, int, va_list );
  71. #define SERIES1_PES_LENGTH  (11)    /* length of audio PES hdr on S1 */
  72. #define SERIES2_PES_LENGTH  (16)    /* length of audio PES hdr on S2 */
  73. #define AC3_PES_LENGTH      (14)    /* length of audio PES hdr for AC3 */
  74. #define VIDEO_PES_LENGTH    (16)    /* length of video PES header */
  75. #define DTIVO_PTS_OFFSET    (6)     /* offs into PES for MPEG PTS on DTivo */
  76. #define SA_PTS_OFFSET       (9)     /* offset into PES for MPEG PTS on SA */
  77. #define AC3_PTS_OFFSET      (9)     /* offset into PES for AC3 PTS on DTivo */
  78. #define VIDEO_PTS_OFFSET    (9)     /* offset into PES for video PTS on all */
  79. #define AC3_PKT_LENGTH      (1536)  /* size of TiVo AC3 pkts (w/o PES hdr) */
  80. static const uint8_t ty_VideoPacket[] = { 0x00, 0x00, 0x01, 0xe0 };
  81. static const uint8_t ty_MPEGAudioPacket[] = { 0x00, 0x00, 0x01, 0xc0 };
  82. static const uint8_t ty_AC3AudioPacket[] = { 0x00, 0x00, 0x01, 0xbd };
  83. #define CHUNK_PEEK_COUNT    (3)         /* number of chunks to probe */
  84. /* packet types for reference:
  85.  2/c0: audio data continued
  86.  3/c0: audio packet header (PES header)
  87.  4/c0: audio data (S/A only?)
  88.  9/c0: audio packet header, AC-3 audio
  89.  2/e0: video data continued
  90.  6/e0: video packet header (PES header)
  91.  7/e0: video sequence header start
  92.  8/e0: video I-frame header start
  93.  a/e0: video P-frame header start
  94.  b/e0: video B-frame header start
  95.  c/e0: video GOP header start
  96.  e/01: closed-caption data
  97.  e/02: Extended data services data 
  98.  e/03: ipreview data ("thumbs up to record" signal)
  99.  e/05: UK Teletext
  100. */
  101. #define TIVO_PES_FILEID   ( 0xf5467abd )
  102. #define TIVO_PART_LENGTH  ( 0x20000000 )    /* 536,870,912 bytes */
  103. #define CHUNK_SIZE        ( 128 * 1024 )
  104. typedef struct
  105. {
  106.   long l_rec_size;
  107.   uint8_t ex[2];
  108.   uint8_t rec_type;
  109.   uint8_t subrec_type;
  110.   bool b_ext;
  111.   uint64_t l_ty_pts;            /* TY PTS in the record header */
  112. } ty_rec_hdr_t;
  113. typedef struct
  114. {
  115.     uint64_t l_timestamp;
  116.     uint8_t chunk_bitmask[8];
  117. } ty_seq_table_t;
  118. typedef enum
  119. {
  120.     TIVO_TYPE_UNKNOWN,
  121.     TIVO_TYPE_SA,
  122.     TIVO_TYPE_DTIVO
  123. } tivo_type_t;
  124. typedef enum
  125. {
  126.     TIVO_SERIES_UNKNOWN,
  127.     TIVO_SERIES1,
  128.     TIVO_SERIES2
  129. } tivo_series_t;
  130. typedef enum
  131. {
  132.     TIVO_AUDIO_UNKNOWN,
  133.     TIVO_AUDIO_AC3,
  134.     TIVO_AUDIO_MPEG
  135. } tivo_audio_t;
  136. #define XDS_MAX_DATA_SIZE (32)
  137. typedef enum
  138. {
  139.     XDS_CLASS_CURRENT        = 0,
  140.     XDS_CLASS_FUTURE         = 1,
  141.     XDS_CLASS_CHANNEL        = 2,
  142.     XDS_CLASS_MISCELLANEOUS  = 3,
  143.     XDS_CLASS_PUBLIC_SERVICE = 4,
  144.     XDS_CLASS_RESERVED       = 5,
  145.     XDS_CLASS_UNDEFINED      = 6,
  146.     XDS_CLASS_OTHER          = 7,
  147.     XDS_MAX_CLASS_COUNT
  148. } xds_class_t;
  149. typedef struct
  150. {
  151.     bool b_started;
  152.     int        i_data;
  153.     uint8_t    p_data[XDS_MAX_DATA_SIZE];
  154.     int        i_sum;
  155. } xds_packet_t;
  156. typedef enum
  157. {
  158.     XDS_META_PROGRAM_RATING_NONE,
  159.     XDS_META_PROGRAM_RATING_MPAA,
  160.     XDS_META_PROGRAM_RATING_TPG,
  161.     /* TODO add CA/CE rating */
  162. } xds_meta_program_rating_t;
  163. typedef struct
  164. {
  165.     char *psz_name;
  166.     xds_meta_program_rating_t rating;
  167.     char *psz_rating;
  168.     /* Add the other fields once I have the samples */
  169. } xds_meta_program_t;
  170. typedef struct
  171. {
  172.     char *psz_channel_name;
  173.     char *psz_channel_call_letter;
  174.     char *psz_channel_number;
  175.     xds_meta_program_t  current;
  176.     xds_meta_program_t  future;
  177. } xds_meta_t;
  178. typedef struct
  179. {
  180.     /* Are we in XDS mode */
  181.     bool b_xds;
  182.     /* Current class type */
  183.     xds_class_t i_class;
  184.     int         i_type;
  185.     bool  b_future;
  186.     /* */
  187.     xds_packet_t pkt[XDS_MAX_CLASS_COUNT][128]; /* XXX it is way too much, but simpler */
  188.     /* */
  189.     bool  b_meta_changed;
  190.     xds_meta_t  meta;
  191. } xds_t;
  192. struct demux_sys_t
  193. {
  194.   es_out_id_t *p_video;               /* ptr to video codec */
  195.   es_out_id_t *p_audio;               /* holds either ac3 or mpeg codec ptr */
  196.   cc_data_t   cc;
  197.   es_out_id_t *p_cc[4];
  198.   xds_t       xds;
  199.   int             i_cur_chunk;
  200.   int             i_stuff_cnt;
  201.   size_t          i_stream_size;      /* size of input stream (if known) */
  202.   //uint64_t        l_program_len;      /* length of this stream in msec */
  203.   bool      b_seekable;         /* is this stream seekable? */
  204.   bool      b_have_master;      /* are master chunks present? */
  205.   tivo_type_t     tivo_type;          /* tivo type (SA / DTiVo) */
  206.   tivo_series_t   tivo_series;        /* Series1 or Series2 */
  207.   tivo_audio_t    audio_type;         /* AC3 or MPEG */
  208.   int             i_Pes_Length;       /* Length of Audio PES header */
  209.   int             i_Pts_Offset;       /* offset into audio PES of PTS */
  210.   uint8_t         pes_buffer[20];     /* holds incomplete pes headers */
  211.   int             i_pes_buf_cnt;      /* how many bytes in our buffer */
  212.   size_t          l_ac3_pkt_size;     /* len of ac3 pkt we've seen so far */
  213.   uint64_t        l_last_ty_pts;      /* last TY timestamp we've seen */
  214.   //mtime_t         l_last_ty_pts_sync; /* audio PTS at time of last TY PTS */
  215.   uint64_t        l_first_ty_pts;     /* first TY PTS in this master chunk */
  216.   uint64_t        l_final_ty_pts;     /* final TY PTS in this master chunk */
  217.   unsigned        i_seq_table_size;   /* number of entries in SEQ table */
  218.   unsigned        i_bits_per_seq_entry; /* # of bits in SEQ table bitmask */
  219.   mtime_t         firstAudioPTS;
  220.   mtime_t         lastAudioPTS;
  221.   mtime_t         lastVideoPTS;
  222.   ty_rec_hdr_t    *rec_hdrs;          /* record headers array */
  223.   int             i_cur_rec;          /* current record in this chunk */
  224.   int             i_num_recs;         /* number of recs in this chunk */
  225.   int             i_seq_rec;          /* record number where seq start is */
  226.   ty_seq_table_t  *seq_table;         /* table of SEQ entries from mstr chk */
  227.   bool      eof;
  228.   bool      b_first_chunk;
  229. };
  230. static int get_chunk_header(demux_t *);
  231. static mtime_t get_pts( const uint8_t *buf );
  232. static int find_es_header( const uint8_t *header,
  233.                            const uint8_t *buffer, int i_search_len );
  234. static int ty_stream_seek_pct(demux_t *p_demux, double seek_pct);
  235. static int ty_stream_seek_time(demux_t *, uint64_t);
  236. static ty_rec_hdr_t *parse_chunk_headers( const uint8_t *p_buf,
  237.                                           int i_num_recs, int *pi_payload_size);
  238. static int probe_stream(demux_t *p_demux);
  239. static void analyze_chunk(demux_t *p_demux, const uint8_t *p_chunk);
  240. static void parse_master(demux_t *p_demux);
  241. static int DemuxRecVideo( demux_t *p_demux, ty_rec_hdr_t *rec_hdr, block_t *p_block_in );
  242. static int DemuxRecAudio( demux_t *p_demux, ty_rec_hdr_t *rec_hdr, block_t *p_block_in );
  243. static int DemuxRecCc( demux_t *p_demux, ty_rec_hdr_t *rec_hdr, block_t *p_block_in );
  244. static void DemuxDecodeXds( demux_t *p_demux, uint8_t d1, uint8_t d2 );
  245. static void XdsInit( xds_t * );
  246. static void XdsExit( xds_t * );
  247. #define TY_ES_GROUP (1)
  248. /*
  249.  * Open: check file and initialize demux structures
  250.  *
  251.  * here's what we do:
  252.  * 1. peek at the first 12 bytes of the stream for the
  253.  *    magic TiVo PART header & stream type & chunk size
  254.  * 2. if it's not there, error with VLC_EGENERIC
  255.  * 3. set up video (mpgv) codec
  256.  * 4. return VLC_SUCCESS
  257.  */
  258. static int Open(vlc_object_t *p_this)
  259. {
  260.     demux_t *p_demux = (demux_t *)p_this;
  261.     demux_sys_t *p_sys;
  262.     es_format_t fmt;
  263.     const uint8_t *p_peek;
  264.     int i;
  265.     /* peek at the first 12 bytes. */
  266.     /* for TY streams, they're always the same */
  267.     if( stream_Peek( p_demux->s, &p_peek, 12 ) < 12 )
  268.         return VLC_EGENERIC;
  269.     if ( U32_AT(p_peek) != TIVO_PES_FILEID ||
  270.          U32_AT(&p_peek[4]) != 0x02 ||
  271.          U32_AT(&p_peek[8]) != CHUNK_SIZE )
  272.     {
  273.         if( !p_demux->b_force &&
  274.             !demux_IsPathExtension( p_demux, ".ty" ) &&
  275.             !demux_IsPathExtension( p_demux, ".ty+" ) )
  276.             return VLC_EGENERIC;
  277.         msg_Warn( p_demux, "this does not look like a TY file, "
  278.                            "continuing anyway..." );
  279.     }
  280. /* at this point, we assume we have a valid TY stream */  
  281.     msg_Dbg( p_demux, "valid TY stream detected" );
  282.     /* Set exported functions */
  283.     p_demux->pf_demux = Demux;
  284.     p_demux->pf_control = Control;
  285.     /* create our structure that will hold all data */
  286.     p_demux->p_sys = p_sys = malloc(sizeof(demux_sys_t));
  287.     memset(p_sys, 0, sizeof(demux_sys_t));
  288.     /* set up our struct (most were zero'd out with the memset above) */
  289.     p_sys->b_first_chunk = true;
  290.     p_sys->b_have_master = (U32_AT(p_peek) == TIVO_PES_FILEID);
  291.     p_sys->firstAudioPTS = -1;
  292.     p_sys->i_stream_size = stream_Size(p_demux->s);
  293.     p_sys->tivo_type = TIVO_TYPE_UNKNOWN;
  294.     p_sys->audio_type = TIVO_AUDIO_UNKNOWN;
  295.     p_sys->tivo_series = TIVO_SERIES_UNKNOWN;
  296.     p_sys->i_Pes_Length = 0;
  297.     p_sys->i_Pts_Offset = 0;
  298.     p_sys->l_ac3_pkt_size = 0;
  299.   
  300.     /* see if this stream is seekable */
  301.     stream_Control( p_demux->s, STREAM_CAN_SEEK, &p_sys->b_seekable );
  302.     if (probe_stream(p_demux) != VLC_SUCCESS) {
  303.         //TyClose(p_demux);
  304.         return VLC_EGENERIC;
  305.     }
  306.     if (!p_sys->b_have_master)
  307.       msg_Warn(p_demux, "No master chunk found; seeking will be limited.");
  308.     /* register the proper audio codec */
  309.     if (p_sys->audio_type == TIVO_AUDIO_MPEG) {
  310.         es_format_Init( &fmt, AUDIO_ES, VLC_FOURCC( 'm', 'p', 'g', 'a' ) );
  311.     } else {
  312.         es_format_Init( &fmt, AUDIO_ES, VLC_FOURCC( 'a', '5', '2', ' ' ) );
  313.     }
  314.     fmt.i_group = TY_ES_GROUP;
  315.     p_sys->p_audio = es_out_Add( p_demux->out, &fmt );
  316.     /* register the video stream */
  317.     es_format_Init( &fmt, VIDEO_ES, VLC_FOURCC( 'm', 'p', 'g', 'v' ) );
  318.     fmt.i_group = TY_ES_GROUP;
  319.     p_sys->p_video = es_out_Add( p_demux->out, &fmt );
  320.     /* */
  321.     for( i = 0; i < 4; i++ )
  322.         p_sys->p_cc[i] = NULL;
  323.     cc_Init( &p_sys->cc );
  324.     XdsInit( &p_sys->xds );
  325.     return VLC_SUCCESS;
  326. }
  327. /* =========================================================================== */
  328. /* Demux: Read & Demux one record from the chunk
  329.  *
  330.  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
  331.  *
  332.  * NOTE: I think we can return the number of packets sent instead of just 1.
  333.  * that means we can demux an entire chunk and shoot it back (may be more efficient)
  334.  * -- should try that some day :) --
  335.  */
  336. static int Demux( demux_t *p_demux )
  337. {
  338.     demux_sys_t  *p_sys = p_demux->p_sys;
  339.     ty_rec_hdr_t *p_rec;
  340.     block_t      *p_block_in = NULL;
  341.     /*msg_Dbg(p_demux, "ty demux processing" );*/
  342.    
  343.     /* did we hit EOF earlier? */
  344.     if( p_sys->eof )
  345.         return 0;
  346.     /*
  347.      * what we do (1 record now.. maybe more later):
  348.     * - use stream_Read() to read the chunk header & record headers
  349.     * - discard entire chunk if it is a PART header chunk
  350.     * - parse all the headers into record header array
  351.     * - keep a pointer of which record we're on
  352.     * - use stream_Block() to fetch each record
  353.     * - parse out PTS from PES headers
  354.     * - set PTS for data packets
  355.     * - pass the data on to the proper codec via es_out_Send()
  356.     * if this is the first time or  
  357.     * if we're at the end of this chunk, start a new one
  358.     */
  359.     /* parse the next chunk's record headers */
  360.     if( p_sys->b_first_chunk || p_sys->i_cur_rec >= p_sys->i_num_recs )
  361.     {
  362.         if( get_chunk_header(p_demux) == 0 )
  363.             return 0;
  364.     }
  365.     /*======================================================================
  366.      * parse & send one record of the chunk
  367.      *====================================================================== */
  368.     p_rec = &p_sys->rec_hdrs[p_sys->i_cur_rec];
  369.     if( !p_rec->b_ext )
  370.     {
  371.         const long l_rec_size = p_rec->l_rec_size;
  372.         /*msg_Dbg(p_demux, "Record Type 0x%x/%02x %ld bytes",
  373.                     subrec_type, p_rec->rec_type, l_rec_size );*/
  374.   
  375.         /* some normal records are 0 length, so check for that... */
  376.         if( l_rec_size <= 0 )
  377.         {
  378.             /* no data in payload; we're done */
  379.             p_sys->i_cur_rec++;
  380.             return 1;
  381.         }
  382.         /* read in this record's payload */
  383.         if( !( p_block_in = stream_Block( p_demux->s, l_rec_size ) ) )
  384.             return 0;
  385.         /* set these as 'unknown' for now */
  386.         p_block_in->i_pts =
  387.         p_block_in->i_dts = 0;
  388.     }
  389.     /*else
  390.     {
  391.         -- don't read any data from the stream, data was in the record header --
  392.         msg_Dbg(p_demux,
  393.                "Record Type 0x%02x/%02x, ext data = %02x, %02x", subrec_type,
  394.                 p_rec->rec_type, p_rec->ex1, p_rec->ex2);
  395.     }*/
  396.     if( p_rec->rec_type == 0xe0 )
  397.     {
  398.         /* Video */
  399.         DemuxRecVideo( p_demux, p_rec, p_block_in );
  400.     }
  401.     else if ( p_rec->rec_type == 0xc0 )
  402.     {
  403.         /* Audio */
  404.         DemuxRecAudio( p_demux, p_rec, p_block_in );
  405.     }
  406.     else if( p_rec->rec_type == 0x01 || p_rec->rec_type == 0x02 )
  407.     {
  408.         /* Closed Captions/XDS */
  409.         DemuxRecCc( p_demux, p_rec, p_block_in );
  410.     }
  411.     else if ( p_rec->rec_type == 0x03 )
  412.     {
  413.         /* Tivo data services (e.g. "thumbs-up to record!")  useless for us */
  414.         if( p_block_in )
  415.             block_Release(p_block_in);
  416.     }
  417.     else if ( p_rec->rec_type == 0x05 )
  418.     {
  419.         /* Unknown, but seen regularly */
  420.         if( p_block_in )
  421.             block_Release(p_block_in);
  422.     }
  423.     else
  424.     {
  425.         msg_Dbg(p_demux, "Invalid record type 0x%02x", p_rec->rec_type );
  426.         if( p_block_in )
  427.             block_Release(p_block_in);
  428.     }
  429.     /* */
  430.     p_sys->i_cur_rec++;
  431.     return 1;
  432. }
  433. /* Control */
  434. static int Control(demux_t *p_demux, int i_query, va_list args)
  435. {
  436.     demux_sys_t *p_sys = p_demux->p_sys;
  437.     double f, *pf;
  438.     int64_t i64, *p_i64;
  439.     /*msg_Info(p_demux, "control cmd %d", i_query);*/
  440.     switch( i_query )
  441.     {
  442.     case DEMUX_GET_POSITION:
  443.         /* arg is 0.0 - 1.0 percent of overall file position */
  444.         if( ( i64 = p_sys->i_stream_size ) > 0 )
  445.         {
  446.             pf = (double*) va_arg( args, double* );
  447.             *pf = ((double)1.0) * stream_Tell( p_demux->s ) / (double) i64;
  448.             return VLC_SUCCESS;
  449.         }
  450.         return VLC_EGENERIC;
  451.     case DEMUX_SET_POSITION:
  452.         /* arg is 0.0 - 1.0 percent of overall file position */
  453.         f = (double) va_arg( args, double );
  454.         /* msg_Dbg(p_demux, "Control - set position to %2.3f", f); */
  455.         if ((i64 = p_sys->i_stream_size) > 0)
  456.             return ty_stream_seek_pct(p_demux, f);
  457.         return VLC_EGENERIC;
  458.     case DEMUX_GET_TIME:
  459.         /* return TiVo timestamp */
  460.         p_i64 = (int64_t *) va_arg(args, int64_t *);
  461.         //*p_i64 = p_sys->lastAudioPTS - p_sys->firstAudioPTS;
  462.         //*p_i64 = (p_sys->l_last_ty_pts / 1000) + (p_sys->lastAudioPTS -
  463.         //    p_sys->l_last_ty_pts_sync);
  464.         *p_i64 = (p_sys->l_last_ty_pts / 1000);
  465.         return VLC_SUCCESS;
  466.     case DEMUX_GET_LENGTH:    /* length of program in microseconds, 0 if unk */
  467.         /* size / bitrate */
  468.         p_i64 = (int64_t *) va_arg(args, int64_t *);
  469.         *p_i64 = 0;
  470.         return VLC_SUCCESS;
  471.     case DEMUX_SET_TIME:      /* arg is time in microsecs */
  472.         i64 = (int64_t) va_arg( args, int64_t );
  473.         return ty_stream_seek_time(p_demux, i64 * 1000);
  474.     case DEMUX_GET_FPS:
  475.     default:
  476.         return VLC_EGENERIC;
  477.     }
  478. }
  479. /* Close */
  480. static void Close( vlc_object_t *p_this )
  481. {
  482.     demux_t *p_demux = (demux_t*)p_this;
  483.     demux_sys_t *p_sys = p_demux->p_sys;
  484.     XdsExit( &p_sys->xds );
  485.     cc_Exit( &p_sys->cc );
  486.     free( p_sys->rec_hdrs );
  487.     free( p_sys->seq_table );
  488.     free(p_sys);
  489. }
  490. /* =========================================================================== */
  491. /* Compute Presentation Time Stamp (PTS)
  492.  * Assume buf points to beginning of PTS */
  493. static mtime_t get_pts( const uint8_t *buf )
  494. {
  495.     mtime_t i_pts;
  496.     i_pts = ((mtime_t)(buf[0]&0x0e ) << 29)|
  497.              (mtime_t)(buf[1] << 22)|
  498.             ((mtime_t)(buf[2]&0xfe) << 14)|
  499.              (mtime_t)(buf[3] << 7)|
  500.              (mtime_t)(buf[4] >> 1);
  501.     i_pts *= 100 / 9;   /* convert PTS (90Khz clock) to microseconds */
  502.     return i_pts;
  503. }
  504. /* =========================================================================== */
  505. static int find_es_header( const uint8_t *header,
  506.                            const uint8_t *buffer, int i_search_len )
  507. {
  508.     int count;
  509.     for( count = 0; count < i_search_len; count++ )
  510.     {
  511.         if( !memcmp( &buffer[count], header, 4 ) )
  512.             return count;
  513.     }
  514.     return -1;
  515. }
  516. /* =========================================================================== */
  517. /* check if we have a full PES header, if not, then save what we have.
  518.  * this is called when audio-start packets are encountered.
  519.  * Returns:
  520.  *     1 partial PES hdr found, some audio data found (buffer adjusted),
  521.  *    -1 partial PES hdr found, no audio data found
  522.  *     0 otherwise (complete PES found, pts extracted, pts set, buffer adjusted) */
  523. /* TODO: HD support -- nothing known about those streams */
  524. static int check_sync_pes( demux_t *p_demux, block_t *p_block,
  525.                            int32_t offset, int32_t rec_len )
  526. {
  527.     demux_sys_t *p_sys = p_demux->p_sys;
  528.     if ( offset < 0 || offset + p_sys->i_Pes_Length > rec_len )
  529.     {
  530.         /* entire PES header not present */
  531.         msg_Dbg( p_demux, "PES header at %d not complete in record. storing.",
  532.                  offset );
  533.         /* save the partial pes header */
  534.         if( offset < 0 )
  535.         {
  536.             /* no header found, fake some 00's (this works, believe me) */
  537.             memset( p_sys->pes_buffer, 0, 4 );
  538.             p_sys->i_pes_buf_cnt = 4;
  539.             if( rec_len > 4 )
  540.                 msg_Err( p_demux, "PES header not found in record of %d bytes!",
  541.                          rec_len );
  542.             return -1;
  543.         }
  544.         /* copy the partial pes header we found */
  545.         memcpy( p_sys->pes_buffer, p_block->p_buffer + offset,
  546.                 rec_len - offset );
  547.         p_sys->i_pes_buf_cnt = rec_len - offset;
  548.         if( offset > 0 )
  549.         {
  550.             /* PES Header was found, but not complete, so trim the end of this record */
  551.             p_block->i_buffer -= rec_len - offset;
  552.             return 1;
  553.         }
  554.         return -1;    /* partial PES, no audio data */
  555.     }
  556.     /* full PES header present, extract PTS */
  557.     p_sys->lastAudioPTS = get_pts( &p_block->p_buffer[ offset +
  558.             p_sys->i_Pts_Offset ] );
  559.     if (p_sys->firstAudioPTS < 0)
  560.         p_sys->firstAudioPTS = p_sys->lastAudioPTS;
  561.     p_block->i_pts = p_sys->lastAudioPTS;
  562.     /*msg_Dbg(p_demux, "Audio PTS %lld", p_sys->lastAudioPTS );*/
  563.     /* adjust audio record to remove PES header */
  564.     memmove(p_block->p_buffer + offset, p_block->p_buffer + offset +
  565.             p_sys->i_Pes_Length, rec_len - p_sys->i_Pes_Length);
  566.     p_block->i_buffer -= p_sys->i_Pes_Length;
  567. #if 0
  568.     msg_Dbg(p_demux, "pes hdr removed; buffer len=%d and has "
  569.              "%02x %02x %02x %02x %02x %02x %02x %02x "
  570.              "%02x %02x %02x %02x %02x %02x %02x %02x", p_block->i_buffer,
  571.              p_block->p_buffer[0], p_block->p_buffer[1],
  572.              p_block->p_buffer[2], p_block->p_buffer[3],
  573.              p_block->p_buffer[4], p_block->p_buffer[5],
  574.              p_block->p_buffer[6], p_block->p_buffer[7],
  575.              p_block->p_buffer[8], p_block->p_buffer[9],
  576.              p_block->p_buffer[10], p_block->p_buffer[11],
  577.              p_block->p_buffer[12], p_block->p_buffer[13],
  578.              p_block->p_buffer[14], p_block->p_buffer[15]);
  579. #endif
  580.     return 0;
  581. }
  582. static int DemuxRecVideo( demux_t *p_demux, ty_rec_hdr_t *rec_hdr, block_t *p_block_in )
  583. {
  584.     demux_sys_t *p_sys = p_demux->p_sys;
  585.     const int subrec_type = rec_hdr->subrec_type;
  586.     const long l_rec_size = rec_hdr->l_rec_size;    // p_block_in->i_buffer might be better
  587.     int esOffset1;
  588.     int i;
  589.     assert( rec_hdr->rec_type == 0xe0 );
  590.     if( !p_block_in )
  591.         return -1;
  592. #if 0
  593.     msg_Dbg(p_demux, "packet buffer has "
  594.             "%02x %02x %02x %02x %02x %02x %02x %02x "
  595.             "%02x %02x %02x %02x %02x %02x %02x %02x",
  596.             p_block_in->p_buffer[0], p_block_in->p_buffer[1],
  597.             p_block_in->p_buffer[2], p_block_in->p_buffer[3],
  598.             p_block_in->p_buffer[4], p_block_in->p_buffer[5],
  599.             p_block_in->p_buffer[6], p_block_in->p_buffer[7],
  600.             p_block_in->p_buffer[8], p_block_in->p_buffer[9],
  601.             p_block_in->p_buffer[10], p_block_in->p_buffer[11],
  602.             p_block_in->p_buffer[12], p_block_in->p_buffer[13],
  603.             p_block_in->p_buffer[14], p_block_in->p_buffer[15]);
  604. #endif
  605.     //if( subrec_type == 0x06 || subrec_type == 0x07 )
  606.     if( subrec_type != 0x02 && subrec_type != 0x0c &&
  607.         subrec_type != 0x08 && l_rec_size > 4 )
  608.     {
  609.         /* get the PTS from this packet if it has one.
  610.          * on S1, only 0x06 has PES.  On S2, however, most all do.
  611.          * Do NOT Pass the PES Header to the MPEG2 codec */
  612.         esOffset1 = find_es_header( ty_VideoPacket, p_block_in->p_buffer, 5 );
  613.         if( esOffset1 != -1 )
  614.         {
  615.             //msg_Dbg(p_demux, "Video PES hdr in pkt type 0x%02x at offset %d",
  616.                 //subrec_type, esOffset1);
  617.             p_sys->lastVideoPTS = get_pts(
  618.                     &p_block_in->p_buffer[ esOffset1 + VIDEO_PTS_OFFSET ] );
  619.             /*msg_Dbg(p_demux, "Video rec %d PTS %"PRId64, p_sys->i_cur_rec,
  620.                         p_sys->lastVideoPTS );*/
  621.             if (subrec_type != 0x06) {
  622.                 /* if we found a PES, and it's not type 6, then we're S2 */
  623.                 /* The packet will have video data (& other headers) so we
  624.                  * chop out the PES header and send the rest */
  625.                 if (l_rec_size >= VIDEO_PES_LENGTH) {
  626.                     p_block_in->p_buffer += VIDEO_PES_LENGTH + esOffset1;
  627.                     p_block_in->i_buffer -= VIDEO_PES_LENGTH + esOffset1;
  628.                 } else {
  629.                     msg_Dbg(p_demux, "video rec type 0x%02x has short PES"
  630.                         " (%ld bytes)", subrec_type, l_rec_size);
  631.                     /* nuke this block; it's too short, but has PES marker */
  632.                     p_block_in->i_buffer = 0;
  633.                 }
  634.             }
  635.         }/* else
  636.             msg_Dbg(p_demux, "No Video PES hdr in pkt type 0x%02x",
  637.                 subrec_type); */
  638.     }
  639.     if(subrec_type == 0x06 )
  640.     {
  641.         /* type 6 (S1 DTivo) has no data, so we're done */
  642.         block_Release(p_block_in);
  643.         return 0;
  644.     }
  645.     /* if it's not a continue blk, then set PTS */
  646.     if( subrec_type != 0x02 )
  647.     {
  648.         /*msg_Dbg(p_demux, "Video rec %d type 0x%02X", p_sys->i_cur_rec,
  649.                    subrec_type);*/
  650.         /* if it's a GOP header, make sure it's legal
  651.          * (if we have enough data) */
  652.         /* Some ty files don't have this bit set
  653.          * and it causes problems */
  654.         if (subrec_type == 0x0c && l_rec_size >= 6)
  655.             p_block_in->p_buffer[5] |= 0x08;
  656.         /* store the TY PTS if there is one */
  657.         if (subrec_type == 0x07) {
  658.             p_sys->l_last_ty_pts = rec_hdr->l_ty_pts;
  659.             /* should we use audio or video PTS? */
  660.             //p_sys->l_last_ty_pts_sync = p_sys->lastAudioPTS;
  661.         } else {
  662.             /* yes I know this is a cheap hack.  It's the timestamp
  663.                used for display and skipping fwd/back, so it
  664.                doesn't have to be accurate to the millisecond.
  665.                I adjust it here by roughly one 1/30 sec.  Yes it
  666.                will be slightly off for UK streams, but it's OK.
  667.              */
  668.             p_sys->l_last_ty_pts += 35000000;
  669.             //p_sys->l_last_ty_pts += 33366667;
  670.         }
  671.         /* set PTS for this block before we send */
  672.         if (p_sys->lastVideoPTS > 0)
  673.         {
  674.             p_block_in->i_pts = p_sys->lastVideoPTS;
  675.             /* PTS gets used ONCE. 
  676.              * Any subsequent frames we get BEFORE next PES
  677.              * header will have their PTS computed in the codec */
  678.             p_sys->lastVideoPTS = 0;
  679.         }
  680.     }
  681.     /* Register the CC decoders when needed */
  682.     for( i = 0; i < 4; i++ )
  683.     {
  684.         static const vlc_fourcc_t fcc[4] = {
  685.             VLC_FOURCC('c', 'c', '1', ' '),
  686.             VLC_FOURCC('c', 'c', '2', ' '),
  687.             VLC_FOURCC('c', 'c', '3', ' '),
  688.             VLC_FOURCC('c', 'c', '4', ' ')
  689.         };
  690.         static const char *ppsz_description[4] = {
  691.             N_("Closed captions 1"),
  692.             N_("Closed captions 2"),
  693.             N_("Closed captions 3"),
  694.             N_("Closed captions 4"),
  695.         };
  696.         es_format_t fmt;
  697.         if( !p_sys->cc.pb_present[i] || p_sys->p_cc[i] )
  698.             continue;
  699.         es_format_Init( &fmt, SPU_ES, fcc[i] );
  700.         fmt.psz_description = strdup( vlc_gettext(ppsz_description[i]) );
  701.         fmt.i_group = TY_ES_GROUP;
  702.         p_sys->p_cc[i] = es_out_Add( p_demux->out, &fmt );
  703.         es_format_Clean( &fmt );
  704.     }
  705.     /* Send the CC data */
  706.     if( p_block_in->i_pts > 0 && p_sys->cc.i_data > 0 )
  707.     {
  708.         for( i = 0; i < 4; i++ )
  709.         {
  710.             if( p_sys->p_cc[i] )
  711.             {
  712.                 block_t *p_cc = block_New( p_demux, p_sys->cc.i_data );
  713.                 p_cc->i_flags |= BLOCK_FLAG_TYPE_I;
  714.                 p_cc->i_pts = p_block_in->i_pts;
  715.                 memcpy( p_cc->p_buffer, p_sys->cc.p_data, p_sys->cc.i_data );
  716.                 es_out_Send( p_demux->out, p_sys->p_cc[i], p_cc );
  717.             }
  718.         }
  719.         cc_Flush( &p_sys->cc );
  720.     }
  721.     //msg_Dbg(p_demux, "sending rec %d as video type 0x%02x",
  722.             //p_sys->i_cur_rec, subrec_type);
  723.     es_out_Send(p_demux->out, p_sys->p_video, p_block_in);
  724.     return 0;
  725. }
  726. static int DemuxRecAudio( demux_t *p_demux, ty_rec_hdr_t *rec_hdr, block_t *p_block_in )
  727. {
  728.     demux_sys_t *p_sys = p_demux->p_sys;
  729.     const int subrec_type = rec_hdr->subrec_type;
  730.     const long l_rec_size = rec_hdr->l_rec_size;
  731.     int esOffset1;
  732.     assert( rec_hdr->rec_type == 0xc0 );
  733.     if( !p_block_in )
  734.         return -1;
  735. #if 0
  736.         int i;
  737.         fprintf( stderr, "Audio Packet Header " );
  738.         for( i = 0 ; i < 24 ; i++ )
  739.             fprintf( stderr, "%2.2x ", p_block_in->p_buffer[i] );
  740.         fprintf( stderr, "n" );
  741. #endif
  742.     if( subrec_type == 2 )
  743.     {
  744.         /* SA or DTiVo Audio Data, no PES (continued block)
  745.          * ================================================
  746.          */
  747.         /* continue PES if previous was incomplete */
  748.         if (p_sys->i_pes_buf_cnt > 0)
  749.         {
  750.             const int i_need = p_sys->i_Pes_Length - p_sys->i_pes_buf_cnt;
  751.             msg_Dbg(p_demux, "continuing PES header");
  752.             /* do we have enough data to complete? */
  753.             if (i_need >= l_rec_size)
  754.             {
  755.                 /* don't have complete PES hdr; save what we have and return */
  756.                 memcpy(&p_sys->pes_buffer[p_sys->i_pes_buf_cnt],
  757.                         p_block_in->p_buffer, l_rec_size);
  758.                 p_sys->i_pes_buf_cnt += l_rec_size;
  759.                 /* */
  760.                 block_Release(p_block_in);
  761.                 return 0;
  762.             }
  763.             /* we have enough; reconstruct this p_frame with the new hdr */
  764.             memcpy(&p_sys->pes_buffer[p_sys->i_pes_buf_cnt],
  765.                    p_block_in->p_buffer, i_need);
  766.             /* advance the block past the PES header (don't want to send it) */
  767.             p_block_in->p_buffer += i_need;
  768.             p_block_in->i_buffer -= i_need;
  769.             /* get the PTS out of this PES header (MPEG or AC3) */
  770.             if (p_sys->audio_type == TIVO_AUDIO_MPEG)
  771.                 esOffset1 = find_es_header(ty_MPEGAudioPacket,
  772.                         p_sys->pes_buffer, 5);
  773.             else
  774.                 esOffset1 = find_es_header(ty_AC3AudioPacket,
  775.                         p_sys->pes_buffer, 5);
  776.             if (esOffset1 < 0)
  777.             {
  778.                 /* god help us; something's really wrong */
  779.                 msg_Err(p_demux, "can't find audio PES header in packet");
  780.             }
  781.             else
  782.             {
  783.                 p_sys->lastAudioPTS = get_pts( 
  784.                     &p_sys->pes_buffer[ esOffset1 + p_sys->i_Pts_Offset ] );
  785.                 p_block_in->i_pts = p_sys->lastAudioPTS;
  786.             }
  787.             p_sys->i_pes_buf_cnt = 0;
  788.         }
  789.         /* S2 DTivo has AC3 packets with 2 padding bytes at end.  This is
  790.          * not allowed in the AC3 spec and will cause problems.  So here
  791.          * we try to trim things. */
  792.         /* Also, S1 DTivo has alternating short / long AC3 packets.  That
  793.          * is, one packet is short (incomplete) and the next packet has
  794.          * the first one's missing data, plus all of its own.  Strange. */
  795.         if (p_sys->audio_type == TIVO_AUDIO_AC3 &&
  796.                 p_sys->tivo_series == TIVO_SERIES2) {
  797.             if (p_sys->l_ac3_pkt_size + p_block_in->i_buffer >
  798.                     AC3_PKT_LENGTH) {
  799.                 p_block_in->i_buffer -= 2;
  800.                 p_sys->l_ac3_pkt_size = 0;
  801.             } else {
  802.                 p_sys->l_ac3_pkt_size += p_block_in->i_buffer;
  803.             }
  804.         }
  805.     }
  806.     else if( subrec_type == 0x03 )
  807.     {
  808.         /* MPEG Audio with PES Header, either SA or DTiVo   */
  809.         /* ================================================ */
  810.         esOffset1 = find_es_header( ty_MPEGAudioPacket,
  811.                 p_block_in->p_buffer, 5 );
  812.         /*msg_Dbg(p_demux, "buffer has %#02x %#02x %#02x %#02x",
  813.            p_block_in->p_buffer[0], p_block_in->p_buffer[1],
  814.            p_block_in->p_buffer[2], p_block_in->p_buffer[3]);
  815.         msg_Dbg(p_demux, "audio ES hdr at offset %d", esOffset1);*/
  816.         /* SA PES Header, No Audio Data                     */
  817.         /* ================================================ */
  818.         if ( ( esOffset1 == 0 ) && ( l_rec_size == 16 ) )
  819.         {
  820.             p_sys->lastAudioPTS = get_pts( &p_block_in->p_buffer[
  821.                         SA_PTS_OFFSET ] );
  822.             if (p_sys->firstAudioPTS < 0)
  823.                 p_sys->firstAudioPTS = p_sys->lastAudioPTS;
  824.             block_Release(p_block_in);
  825.             return 0;
  826.             /*msg_Dbg(p_demux, "SA Audio PTS %lld",
  827.                        p_sys->lastAudioPTS );*/
  828.         }
  829.         /* DTiVo Audio with PES Header                      */
  830.         /* ================================================ */
  831.         /* Check for complete PES */
  832.         if (check_sync_pes(p_demux, p_block_in, esOffset1,
  833.                             l_rec_size) == -1)
  834.         {
  835.             /* partial PES header found, nothing else. 
  836.              * we're done. */
  837.             block_Release(p_block_in);
  838.             return 0;
  839.         }
  840. #if 0
  841.         msg_Dbg(p_demux, "packet buffer has "
  842.                  "%02x %02x %02x %02x %02x %02x %02x %02x "
  843.                  "%02x %02x %02x %02x %02x %02x %02x %02x",
  844.                  p_block_in->p_buffer[0], p_block_in->p_buffer[1],
  845.                  p_block_in->p_buffer[2], p_block_in->p_buffer[3],
  846.                  p_block_in->p_buffer[4], p_block_in->p_buffer[5],
  847.                  p_block_in->p_buffer[6], p_block_in->p_buffer[7],
  848.                  p_block_in->p_buffer[8], p_block_in->p_buffer[9],
  849.                  p_block_in->p_buffer[10], p_block_in->p_buffer[11],
  850.                  p_block_in->p_buffer[12], p_block_in->p_buffer[13],
  851.                  p_block_in->p_buffer[14], p_block_in->p_buffer[15]);
  852. #endif
  853.     }
  854.     else if( subrec_type == 0x04 )
  855.     {
  856.         /* SA Audio with no PES Header                      */
  857.         /* ================================================ */
  858.         /*msg_Dbg(p_demux,
  859.                 "Adding SA Audio Packet Size %ld", l_rec_size ); */
  860.         if (p_sys->lastAudioPTS > 0)
  861.             p_block_in->i_pts = p_sys->lastAudioPTS;
  862.     }
  863.     else if( subrec_type == 0x09 )
  864.     {
  865.         /* DTiVo AC3 Audio Data with PES Header             */
  866.         /* ================================================ */
  867.         esOffset1 = find_es_header( ty_AC3AudioPacket,
  868.                 p_block_in->p_buffer, 5 );
  869. #if 0
  870.         msg_Dbg(p_demux, "buffer has "
  871.                  "%02x %02x %02x %02x %02x %02x %02x %02x "
  872.                  "%02x %02x %02x %02x %02x %02x %02x %02x",
  873.                  p_block_in->p_buffer[0], p_block_in->p_buffer[1],
  874.                  p_block_in->p_buffer[2], p_block_in->p_buffer[3],
  875.                  p_block_in->p_buffer[4], p_block_in->p_buffer[5],
  876.                  p_block_in->p_buffer[6], p_block_in->p_buffer[7],
  877.                  p_block_in->p_buffer[8], p_block_in->p_buffer[9],
  878.                  p_block_in->p_buffer[10], p_block_in->p_buffer[11],
  879.                  p_block_in->p_buffer[12], p_block_in->p_buffer[13],
  880.                  p_block_in->p_buffer[14], p_block_in->p_buffer[15]);
  881.         msg_Dbg(p_demux, "audio ES AC3 hdr at offset %d", esOffset1);
  882. #endif
  883.         /* Check for complete PES */
  884.         if (check_sync_pes(p_demux, p_block_in, esOffset1,
  885.                             l_rec_size) == -1)
  886.         {
  887.             /* partial PES header found, nothing else.  we're done. */
  888.             block_Release(p_block_in);
  889.             return 0;
  890.         }
  891.         /* S2 DTivo has invalid long AC3 packets */
  892.         if (p_sys->tivo_series == TIVO_SERIES2) {
  893.             if (p_block_in->i_buffer > AC3_PKT_LENGTH) {
  894.                 p_block_in->i_buffer -= 2;
  895.                 p_sys->l_ac3_pkt_size = 0;
  896.             } else {
  897.                 p_sys->l_ac3_pkt_size = p_block_in->i_buffer;
  898.             }
  899.         }
  900.     }
  901.     else
  902.     {
  903.         /* Unsupported/Unknown */
  904.         block_Release(p_block_in);
  905.         return 0;
  906.     }
  907.     /* set PCR before we send (if PTS found) */
  908.     if( p_block_in->i_pts > 0 )
  909.         es_out_Control( p_demux->out, ES_OUT_SET_PCR,
  910.                         p_block_in->i_pts );
  911.     /* Send data */
  912.     es_out_Send( p_demux->out, p_sys->p_audio, p_block_in );
  913.     return 0;
  914. }
  915. static int DemuxRecCc( demux_t *p_demux, ty_rec_hdr_t *rec_hdr, block_t *p_block_in )
  916. {
  917.     demux_sys_t *p_sys = p_demux->p_sys;
  918.     int i_field;
  919.     if( p_block_in )
  920.         block_Release(p_block_in);
  921.     if( rec_hdr->rec_type == 0x01 )
  922.         i_field = 0;
  923.     else if( rec_hdr->rec_type == 0x02 )
  924.         i_field = 1;
  925.     else
  926.         return 0;
  927.     /* XDS data (extract programs infos) transmitted on field 2 only */
  928.     if( i_field == 1 )
  929.         DemuxDecodeXds( p_demux, rec_hdr->ex[0], rec_hdr->ex[1] );
  930.     if( p_sys->cc.i_data + 3 > CC_MAX_DATA_SIZE )
  931.         return 0;
  932.     cc_AppendData( &p_sys->cc, i_field, rec_hdr->ex );
  933.     return 0;
  934. }
  935. /* seek to a position within the stream, if possible */
  936. static int ty_stream_seek_pct(demux_t *p_demux, double seek_pct)
  937. {
  938.     demux_sys_t *p_sys = p_demux->p_sys;
  939.     int64_t seek_pos = p_sys->i_stream_size * seek_pct;
  940.     long l_skip_amt;
  941.     int i;
  942.     unsigned i_cur_part;
  943.     /* if we're not seekable, there's nothing to do */
  944.     if (!p_sys->b_seekable)
  945.         return VLC_EGENERIC;
  946.     /* figure out which part & chunk we want & go there */
  947.     i_cur_part = seek_pos / TIVO_PART_LENGTH;
  948.     p_sys->i_cur_chunk = seek_pos / CHUNK_SIZE;
  949.     
  950.     /* try to read the part header (master chunk) if it's there */
  951.     if ( stream_Seek( p_demux->s, i_cur_part * TIVO_PART_LENGTH ))
  952.     {
  953.         /* can't seek stream */
  954.         return VLC_EGENERIC;
  955.     }
  956.     parse_master(p_demux);
  957.     /* now for the actual chunk */
  958.     if ( stream_Seek( p_demux->s, p_sys->i_cur_chunk * CHUNK_SIZE))
  959.     {
  960.         /* can't seek stream */
  961.         return VLC_EGENERIC;
  962.     }
  963.     /* load the chunk */
  964.     p_sys->i_stuff_cnt = 0;
  965.     get_chunk_header(p_demux);
  966.   
  967.     /* seek within the chunk to get roughly to where we want */
  968.     p_sys->i_cur_rec = (int)
  969.       ((double) ((seek_pos % CHUNK_SIZE) / (double) (CHUNK_SIZE)) * p_sys->i_num_recs);
  970.     msg_Dbg(p_demux, "Seeked to file pos %"PRId64, seek_pos);
  971.     msg_Dbg(p_demux, " (chunk %d, record %d)",
  972.              p_sys->i_cur_chunk - 1, p_sys->i_cur_rec);
  973.     /* seek to the start of this record's data.
  974.      * to do that, we have to skip past all prior records */
  975.     l_skip_amt = 0;
  976.     for (i=0; i<p_sys->i_cur_rec; i++)
  977.         l_skip_amt += p_sys->rec_hdrs[i].l_rec_size;
  978.     stream_Seek(p_demux->s, ((p_sys->i_cur_chunk-1) * CHUNK_SIZE) +
  979.                  (p_sys->i_num_recs * 16) + l_skip_amt + 4);
  980.     /* to hell with syncing any audio or video, just start reading records... :) */
  981.     /*p_sys->lastAudioPTS = p_sys->lastVideoPTS = 0;*/
  982.     return VLC_SUCCESS;
  983. }
  984. /* XDS decoder */
  985. //#define TY_XDS_DEBUG
  986. static void XdsInit( xds_t *h )
  987. {
  988.     int i, j;
  989.     h->b_xds = false;
  990.     h->i_class = XDS_MAX_CLASS_COUNT;
  991.     h->i_type = 0;
  992.     h->b_future = false;
  993.     for( i = 0; i < XDS_MAX_CLASS_COUNT; i++ )
  994.     {
  995.         for( j = 0; j < 128; j++ )
  996.             h->pkt[i][j].b_started = false;
  997.     }
  998.     h->b_meta_changed = false;
  999.     memset( &h->meta, 0, sizeof(h->meta) );
  1000. }
  1001. static void XdsExit( xds_t *h )
  1002. {
  1003.     /* */
  1004.     free( h->meta.psz_channel_name );
  1005.     free( h->meta.psz_channel_call_letter );
  1006.     free( h->meta.psz_channel_number );
  1007.     /* */
  1008.     free( h->meta.current.psz_name );
  1009.     free( h->meta.current.psz_rating );
  1010.     /* */
  1011.     free( h->meta.future.psz_name );
  1012.     free( h->meta.future.psz_rating );
  1013. }
  1014. static void XdsStringUtf8( char dst[2*32+1], const uint8_t *p_src, int i_src )
  1015. {
  1016.     int i;
  1017.     int i_dst;
  1018.     for( i = 0, i_dst = 0; i < i_src; i++ )
  1019.     {
  1020.         switch( p_src[i] )
  1021.         {
  1022. #define E2( c, u1, u2 ) case c: dst[i_dst++] = u1; dst[i_dst++] = u2; break
  1023.         E2( 0x2a, 0xc3,0xa1); // lowercase a, acute accent
  1024.         E2( 0x5c, 0xc3,0xa9); // lowercase e, acute accent
  1025.         E2( 0x5e, 0xc3,0xad); // lowercase i, acute accent
  1026.         E2( 0x5f, 0xc3,0xb3); // lowercase o, acute accent
  1027.         E2( 0x60, 0xc3,0xba); // lowercase u, acute accent
  1028.         E2( 0x7b, 0xc3,0xa7); // lowercase c with cedilla
  1029.         E2( 0x7c, 0xc3,0xb7); // division symbol
  1030.         E2( 0x7d, 0xc3,0x91); // uppercase N tilde
  1031.         E2( 0x7e, 0xc3,0xb1); // lowercase n tilde
  1032. #undef E2
  1033.         default:
  1034.             dst[i_dst++] = p_src[i];
  1035.             break;
  1036.         }
  1037.     }
  1038.     dst[i_dst++] = '';
  1039. }
  1040. static bool XdsChangeString( xds_t *h, char **ppsz_dst, const char *psz_new )
  1041. {
  1042.     if( *ppsz_dst && psz_new && !strcmp( *ppsz_dst, psz_new ) )
  1043.         return false;
  1044.     if( *ppsz_dst == NULL && psz_new == NULL )
  1045.         return false;
  1046.     free( *ppsz_dst );
  1047.     if( psz_new )
  1048.         *ppsz_dst = strdup( psz_new );
  1049.     else
  1050.         *ppsz_dst = NULL;
  1051.     h->b_meta_changed = true;
  1052.     return true;
  1053. }
  1054. static void XdsDecodeCurrentFuture( xds_t *h, xds_packet_t *pk )
  1055. {
  1056.     xds_meta_program_t *p_prg = h->b_future ? &h->meta.future : &h->meta.current;
  1057.     char name[2*32+1];
  1058.     int i_rating;
  1059.     switch( h->i_type )
  1060.     {
  1061.     case 0x03:
  1062.         XdsStringUtf8( name, pk->p_data, pk->i_data );
  1063.         if( XdsChangeString( h, &p_prg->psz_name, name ) )
  1064.         {
  1065.             //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: class 'Current/Future (Program Name) %d'n", pk->i_data );
  1066.             //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: ====> program name %sn", name );
  1067.         }
  1068.         break;
  1069.     case 0x05:
  1070.         i_rating = (pk->p_data[0] & 0x18);
  1071.         if( i_rating == 0x08 )
  1072.         {
  1073.             /* TPG */
  1074.             static const char *pppsz_ratings[8][2] = {
  1075.                 { "None",   "No rating (no content advisory)" },
  1076.                 { "TV-Y",   "All Children (no content advisory)" },
  1077.                 { "TV-Y7",  "Directed to Older Children (V = Fantasy Violence)" },
  1078.                 { "TV-G",   "General Audience (no content advisory)" },
  1079.                 { "TV-PG",  "Parental Guidance Suggested" },
  1080.                 { "TV-14",  "Parents Strongly Cautioned" },
  1081.                 { "TV-MA",  "Mature Audience Only" },
  1082.                 { "None",   "No rating (no content advisory)" }
  1083.             };
  1084.             p_prg->rating = XDS_META_PROGRAM_RATING_TPG;
  1085.             if( XdsChangeString( h, &p_prg->psz_rating, pppsz_ratings[pk->p_data[1]&0x07][0] ) )
  1086.             {
  1087.                 //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: class 'Current/Future (Rating) %d'n", pk->i_data );
  1088.                 //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: ====> TPG Rating %s (%s)n",
  1089.                 //         pppsz_ratings[pk->p_data[1]&0x07][0], pppsz_ratings[pk->p_data[1]&0x07][1] );
  1090.             }
  1091.         }
  1092.         else if( i_rating == 0x00 || i_rating == 0x10 )
  1093.         {
  1094.             /* MPAA */
  1095.             static const char *pppsz_ratings[8][2] = {
  1096.                 { "N/A",    "N/A" },
  1097.                 { "G",      "General Audiences" },
  1098.                 { "PG",     "Parental Guidance Suggested" },
  1099.                 { "PG-13",  "Parents Strongly Cautioned" },
  1100.                 { "R",      "Restricted" },
  1101.                 { "NC-17",  "No one 17 and under admitted" },
  1102.                 { "X",      "No one under 17 admitted" },
  1103.                 { "NR",     "Not Rated" },
  1104.             };
  1105.             p_prg->rating = XDS_META_PROGRAM_RATING_MPAA;
  1106.             if( XdsChangeString( h, &p_prg->psz_rating, pppsz_ratings[pk->p_data[0]&0x07][0] ) )
  1107.             {
  1108.                 //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: class 'Current/Future (Rating) %d'n", pk->i_data );
  1109.                 //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: ====> TPG Rating %s (%s)n",
  1110.                 //         pppsz_ratings[pk->p_data[0]&0x07][0], pppsz_ratings[pk->p_data[0]&0x07][1] );
  1111.             }
  1112.         }
  1113.         else
  1114.         {
  1115.             /* Non US Rating TODO */
  1116.             assert( i_rating == 0x18 ); // only left value possible */
  1117.             p_prg->rating = XDS_META_PROGRAM_RATING_NONE;
  1118.             if( XdsChangeString( h, &p_prg->psz_rating, NULL ) )
  1119.             {
  1120.                 //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: class 'Current/Future (Rating) %d'n", pk->i_data );
  1121.                 //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: ====> 0x%2.2x 0x%2.2xn", pk->p_data[0], pk->p_data[1] );
  1122.             }
  1123.         }
  1124.         break;
  1125.     default:
  1126. #ifdef TY_XDS_DEBUG
  1127.         fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: class 'Current/Future (Unknown 0x%x)'n", h->i_type );
  1128. #endif
  1129.         break;
  1130.     }
  1131. }
  1132. static void XdsDecodeChannel( xds_t *h, xds_packet_t *pk )
  1133. {
  1134.     char name[2*32+1];
  1135.     char chan[2*32+1];
  1136.     switch( h->i_type )
  1137.     {
  1138.     case 0x01:
  1139.         if( pk->i_data < 2 )
  1140.             return;
  1141.         XdsStringUtf8( name, pk->p_data, pk->i_data );
  1142.         if( XdsChangeString( h, &h->meta.psz_channel_name, name ) )
  1143.         {
  1144.             //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: class 'Channel (Network Name) %d'n", pk->i_data );
  1145.             //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: ====> %sn", name );
  1146.         }
  1147.         break;
  1148.     case 0x02:
  1149.         if( pk->i_data < 4 )
  1150.             return;
  1151.         XdsStringUtf8( name, pk->p_data, 4 );
  1152.         if( XdsChangeString( h, &h->meta.psz_channel_call_letter, name ) )
  1153.         {
  1154.             //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: class 'Channel (Network Call Letter)' %dn", pk->i_data );
  1155.             //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: ====> call letter %sn", name );
  1156.         }
  1157.         if( pk->i_data >= 6 )
  1158.         {
  1159.             XdsStringUtf8( chan, &pk->p_data[4], 2 );
  1160.             if( XdsChangeString( h, &h->meta.psz_channel_number, chan ) )
  1161.             {
  1162.                 //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: class 'Channel (Network Call Letter)' %dn", pk->i_data );
  1163.                 //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: ====> channel number %sn", chan );
  1164.             }
  1165.         }
  1166.         else
  1167.         {
  1168.             if( XdsChangeString( h, &h->meta.psz_channel_number, NULL ) )
  1169.             {
  1170.                 //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: class 'Channel (Network Call Letter)' %dn", pk->i_data );
  1171.                 //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: ====> no channel number letter anymoren" );
  1172.             }
  1173.         }
  1174.         break;
  1175.     case 0x03:
  1176.         //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: class 'Channel (Channel Tape Delay)'n" );
  1177.         break;
  1178.     case 0x04:
  1179.         //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: class 'Channel (Transmission Signal Identifier)'n" );
  1180.         break;
  1181.     default:
  1182. #ifdef TY_XDS_DEBUG
  1183.         fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: class 'Channel (Unknown 0x%x)'n", h->i_type );
  1184. #endif
  1185.         break;
  1186.     }
  1187. }
  1188. static void XdsDecode( xds_t *h, xds_packet_t *pk )
  1189. {
  1190.     switch( h->i_class )
  1191.     {
  1192.     case XDS_CLASS_CURRENT:
  1193.     case XDS_CLASS_FUTURE:
  1194.         XdsDecodeCurrentFuture( h, pk );
  1195.         break;
  1196.     case XDS_CLASS_CHANNEL:
  1197.         XdsDecodeChannel( h, pk );
  1198.         break;
  1199.     case XDS_CLASS_MISCELLANEOUS:
  1200. #ifdef TY_XDS_DEBUG
  1201.         fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: class 'Miscellaneous'n" );
  1202. #endif
  1203.         break;
  1204.     case XDS_CLASS_PUBLIC_SERVICE:
  1205. #ifdef TY_XDS_DEBUG
  1206.         fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: class 'Public Service'n" );
  1207. #endif
  1208.         break;
  1209.     default:
  1210.         //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: unknown classn" );
  1211.         break;
  1212.     }
  1213. }
  1214. static void XdsParse( xds_t *h, uint8_t d1, uint8_t d2 )
  1215. {
  1216.     /* TODO check parity */
  1217.     d1 &= 0x7f;
  1218.     d2 &= 0x7f;
  1219.     /* */
  1220.     if( d1 >= 0x01 && d1 <= 0x0e )
  1221.     {
  1222.         const xds_class_t i_class = ( d1 - 1 ) >> 1;
  1223.         const int i_type = d2;
  1224.         const bool b_start = d1 & 0x01;
  1225.         xds_packet_t *pk = &h->pkt[i_class][i_type];
  1226.         if( !b_start && !pk->b_started )
  1227.         {
  1228.             //fprintf( stderr, "xxxxxxxxxxxxxxxXDS Continuying a non started packet, ignoringn" );
  1229.             h->b_xds = false;
  1230.             return;
  1231.         }
  1232.         h->b_xds = true;
  1233.         h->i_class = i_class;
  1234.         h->i_type  = i_type;
  1235.         h->b_future = !b_start;
  1236.         pk->b_started = true;
  1237.         if( b_start )
  1238.         {
  1239.             pk->i_data = 0;
  1240.             pk->i_sum = d1 + d2;
  1241.         }
  1242.     }
  1243.     else if( d1 == 0x0f && h->b_xds )
  1244.     {
  1245.         xds_packet_t *pk = &h->pkt[h->i_class][h->i_type];
  1246.         /* TODO checksum and decode */
  1247.         pk->i_sum += d1 + d2;
  1248.         if( pk->i_sum & 0x7f )
  1249.         {
  1250.             //fprintf( stderr, "xxxxxxxxxxxxxxxXDS invalid checksum, ignoring ---------------------------------n" );
  1251.             pk->b_started = false;
  1252.             return;
  1253.         }
  1254.         if( pk->i_data <= 0 )
  1255.         {
  1256.             //fprintf( stderr, "xxxxxxxxxxxxxxxXDS empty packet, ignoring ---------------------------------n" );
  1257.             pk->b_started = false;
  1258.             return;
  1259.         }
  1260.         //if( pk->p_data[pk->i_data-1] == 0x40 ) /* Padding byte */
  1261.         //    pk->i_data--;
  1262.         XdsDecode( h, pk );
  1263.         /* Reset it */
  1264.         pk->b_started = false;
  1265.     }
  1266.     else if( d1 >= 0x20 && h->b_xds )
  1267.     {
  1268.         xds_packet_t *pk = &h->pkt[h->i_class][h->i_type];
  1269.         if( pk->i_data+2 > XDS_MAX_DATA_SIZE )
  1270.         {
  1271.             /* Broken -> reinit */
  1272.             //fprintf( stderr, "xxxxxxxxxxxxxxxXDS broken, resetn" );
  1273.             h->b_xds = false;
  1274.             pk->b_started = false;
  1275.             return;
  1276.         }
  1277.         /* TODO check parity bit */
  1278.         pk->p_data[pk->i_data++] = d1 & 0x7f;
  1279.         pk->p_data[pk->i_data++] = d2 & 0x7f;
  1280.         pk->i_sum += d1+d2;
  1281.     }
  1282.     else
  1283.     {
  1284.         h->b_xds = false;
  1285.     }
  1286. }
  1287. static void DemuxDecodeXds( demux_t *p_demux, uint8_t d1, uint8_t d2 )
  1288. {
  1289.     demux_sys_t *p_sys = p_demux->p_sys;
  1290.     XdsParse( &p_demux->p_sys->xds, d1, d2 );
  1291.     if( p_demux->p_sys->xds.b_meta_changed )
  1292.     {
  1293.         xds_meta_t *m = &p_sys->xds.meta;
  1294.         vlc_meta_t *p_meta;
  1295.         vlc_epg_t *p_epg;
  1296.         /* Channel meta data */
  1297.         p_meta = vlc_meta_New();
  1298.         if( m->psz_channel_name )
  1299.             vlc_meta_SetPublisher( p_meta, m->psz_channel_name );
  1300.         if( m->psz_channel_call_letter )
  1301.             vlc_meta_SetTitle( p_meta, m->psz_channel_call_letter );
  1302.         if( m->psz_channel_number )
  1303.             vlc_meta_AddExtra( p_meta, "Channel number", m->psz_channel_number );
  1304.         es_out_Control( p_demux->out, ES_OUT_SET_GROUP_META, TY_ES_GROUP, p_meta );
  1305.         vlc_meta_Delete( p_meta );
  1306.         /* Event meta data (current/future) */
  1307.         p_epg = vlc_epg_New( NULL );
  1308.         if( m->current.psz_name )
  1309.         {
  1310.             vlc_epg_AddEvent( p_epg, 0, 0, m->current.psz_name, NULL, NULL );
  1311.             //if( m->current.psz_rating )
  1312.             //  TODO but VLC cannot yet handle rating per epg event
  1313.             vlc_epg_SetCurrent( p_epg, 0 );
  1314.         }
  1315.         if( m->future.psz_name )
  1316.         {
  1317.         }
  1318.         if( p_epg->i_event > 0 )
  1319.             es_out_Control( p_demux->out, ES_OUT_SET_GROUP_EPG, TY_ES_GROUP, p_epg );
  1320.         vlc_epg_Delete( p_epg );
  1321.     }
  1322.     p_demux->p_sys->xds.b_meta_changed = false;
  1323. }
  1324. /* seek to an exact time position within the stream, if possible.
  1325.  * l_seek_time is in nanoseconds, the TIVO time standard.
  1326.  */
  1327. static int ty_stream_seek_time(demux_t *p_demux, uint64_t l_seek_time)
  1328. {
  1329.     demux_sys_t *p_sys = p_demux->p_sys;
  1330.     int i_seq_entry = 0;
  1331.     int i_skip_cnt;
  1332.     unsigned i;
  1333.     long l_cur_pos = stream_Tell(p_demux->s);
  1334.     unsigned i_cur_part = l_cur_pos / TIVO_PART_LENGTH;
  1335.     long l_seek_secs = l_seek_time / 1000000000;
  1336.     uint64_t l_fwd_stamp = 1;
  1337.     /* if we're not seekable, there's nothing to do */
  1338.     if (!p_sys->b_seekable || !p_sys->b_have_master)
  1339.         return VLC_EGENERIC;
  1340.     msg_Dbg(p_demux, "Skipping to time %02ld:%02ld:%02ld",
  1341.             l_seek_secs / 3600, (l_seek_secs / 60) % 60, l_seek_secs % 60);
  1342.     /* seek to the proper segment if necessary */
  1343.     /* first see if we need to go back */
  1344.     while (l_seek_time < p_sys->l_first_ty_pts) {
  1345.         msg_Dbg(p_demux, "skipping to prior segment.");
  1346.         /* load previous part */
  1347.         if (i_cur_part == 0) {
  1348.             stream_Seek(p_demux->s, l_cur_pos);
  1349.             msg_Err(p_demux, "Attempt to seek past BOF");
  1350.             return VLC_EGENERIC;
  1351.         }
  1352.         stream_Seek(p_demux->s, (i_cur_part - 1) * TIVO_PART_LENGTH);
  1353.         i_cur_part--;
  1354.         parse_master(p_demux);
  1355.     }
  1356.     /* maybe we need to go forward */
  1357.     while (l_seek_time > p_sys->l_final_ty_pts) {
  1358.         msg_Dbg(p_demux, "skipping to next segment.");
  1359.         /* load next part */
  1360.         if ((i_cur_part + 1) * TIVO_PART_LENGTH > p_sys->i_stream_size) {
  1361.             /* error; restore previous file position */
  1362.             stream_Seek(p_demux->s, l_cur_pos);
  1363.             msg_Err(p_demux, "seek error");
  1364.             return VLC_EGENERIC;
  1365.         }
  1366.         stream_Seek(p_demux->s, (i_cur_part + 1) * TIVO_PART_LENGTH);
  1367.         i_cur_part++;
  1368.         parse_master(p_demux);
  1369.     }
  1370.     /* our target is somewhere within this part;
  1371.        find the proper chunk using seq_table */
  1372.     for (i=1; i<p_sys->i_seq_table_size; i++) {
  1373.         if (p_sys->seq_table[i].l_timestamp > l_seek_time) {
  1374.             /* i-1 is the section we want; remember the next timestamp in case
  1375.                we have to use it (this section may not have a proper SEQ hdr
  1376.                for the time we're seeking) */
  1377.             msg_Dbg(p_demux, "stopping at seq entry %d.", i);
  1378.             l_fwd_stamp = p_sys->seq_table[i].l_timestamp;
  1379.             i_seq_entry = i-1;
  1380.             break;
  1381.         }
  1382.     }
  1383.     
  1384.     /* if we went through the entire last loop and didn't find our target,
  1385.        then we skip to the next part.  What has happened is that the actual
  1386.        time we're seeking is within this part, but there isn't a SEQ hdr
  1387.        for it here.  So we skip to the next part */
  1388.     if (i == p_sys->i_seq_table_size) {
  1389.         if ((i_cur_part + 1) * TIVO_PART_LENGTH > p_sys->i_stream_size) {
  1390.             /* error; restore previous file position */
  1391.             stream_Seek(p_demux->s, l_cur_pos);
  1392.             msg_Err(p_demux, "seek error");
  1393.             return VLC_EGENERIC;
  1394.         }
  1395.         stream_Seek(p_demux->s, (i_cur_part + 1) * TIVO_PART_LENGTH);
  1396.         i_cur_part++;
  1397.         parse_master(p_demux);
  1398.         i_seq_entry = 0;
  1399.     }     
  1400.      
  1401.     /* determine which chunk has our seek_time */
  1402.     for (i=0; i<p_sys->i_bits_per_seq_entry; i++) {
  1403.         long l_chunk_nr = i_seq_entry * p_sys->i_bits_per_seq_entry + i;
  1404.         long l_chunk_offset = (l_chunk_nr + 1) * CHUNK_SIZE;
  1405.         msg_Dbg(p_demux, "testing part %d chunk %ld mask 0x%02X bit %d",
  1406.             i_cur_part, l_chunk_nr,
  1407.             p_sys->seq_table[i_seq_entry].chunk_bitmask[i/8], i%8);
  1408.         if (p_sys->seq_table[i_seq_entry].chunk_bitmask[i/8] & (1 << (i%8))) {
  1409.             /* check this chunk's SEQ header timestamp */
  1410.             msg_Dbg(p_demux, "has SEQ. seeking to chunk at 0x%lX",
  1411.                 (i_cur_part * TIVO_PART_LENGTH) + l_chunk_offset);
  1412.             stream_Seek(p_demux->s, (i_cur_part * TIVO_PART_LENGTH) +
  1413.                 l_chunk_offset);
  1414.             // TODO: we don't have to parse the full header set;
  1415.             // just test the seq_rec entry for its timestamp
  1416.             p_sys->i_stuff_cnt = 0;
  1417.             get_chunk_header(p_demux);
  1418.             // check ty PTS for the SEQ entry in this chunk
  1419.             if (p_sys->i_seq_rec < 0 || p_sys->i_seq_rec > p_sys->i_num_recs) {
  1420.                 msg_Err(p_demux, "no SEQ hdr in chunk; table had one.");
  1421.                 /* Seek to beginning of original chunk & reload it */
  1422.                 stream_Seek(p_demux->s, (l_cur_pos / CHUNK_SIZE) * CHUNK_SIZE);
  1423.                 p_sys->i_stuff_cnt = 0;
  1424.                 get_chunk_header(p_demux);
  1425.                 return VLC_EGENERIC;
  1426.             }
  1427.             l_seek_secs = p_sys->rec_hdrs[p_sys->i_seq_rec].l_ty_pts /
  1428.                 1000000000;
  1429.             msg_Dbg(p_demux, "found SEQ hdr for timestamp %02ld:%02ld:%02ld",
  1430.                 l_seek_secs / 3600,
  1431.                 (l_seek_secs / 60) % 60, l_seek_secs % 60);
  1432.             if (p_sys->rec_hdrs[p_sys->i_seq_rec].l_ty_pts >= l_seek_time) {
  1433.                 // keep this one?  go back?
  1434.                 /* for now, we take this one.  it's the first SEQ hdr AFTER
  1435.                    the time we were searching for. */
  1436.                 msg_Dbg(p_demux, "seek target found.");
  1437.                 break;
  1438.             }
  1439.             msg_Dbg(p_demux, "timestamp too early. still scanning.");
  1440.         }
  1441.     }
  1442.     /* if we made it through this entire loop without finding our target,
  1443.        then we skip to the next section.  What has happened is that the actual
  1444.        time we're seeking is within this section, but there isn't a SEQ hdr
  1445.        for it here.  So we skip to the next closest one (l_fwd_stamp) */
  1446.     if (i == p_sys->i_bits_per_seq_entry)
  1447.         return ty_stream_seek_time(p_demux, l_fwd_stamp);
  1448.     /* current stream ptr is at beginning of data for this chunk,
  1449.        so we need to skip past any stream data prior to the seq_rec
  1450.        in this chunk */
  1451.     i_skip_cnt = 0;
  1452.     for (int j=0; j<p_sys->i_seq_rec; j++)
  1453.         i_skip_cnt += p_sys->rec_hdrs[j].l_rec_size;
  1454.     stream_Read(p_demux->s, NULL, i_skip_cnt);
  1455.     p_sys->i_cur_rec = p_sys->i_seq_rec;
  1456.     //p_sys->l_last_ty_pts = p_sys->rec_hdrs[p_sys->i_seq_rec].l_ty_pts;
  1457.     //p_sys->l_last_ty_pts_sync = p_sys->lastAudioPTS;
  1458.     return VLC_SUCCESS;
  1459. }
  1460. /* parse a master chunk, filling the SEQ table and other variables.
  1461.  * We assume the stream is currently pointing to it.
  1462.  */
  1463. static void parse_master(demux_t *p_demux)
  1464. {
  1465.     demux_sys_t *p_sys = p_demux->p_sys;
  1466.     uint8_t mst_buf[32];
  1467.     uint32_t i, i_map_size;
  1468.     int64_t i_save_pos = stream_Tell(p_demux->s);
  1469.     int64_t i_pts_secs;
  1470.     /* Note that the entries in the SEQ table in the stream may have
  1471.        different sizes depending on the bits per entry.  We store them
  1472.        all in the same size structure, so we have to parse them out one
  1473.        by one.  If we had a dynamic structure, we could simply read the
  1474.        entire table directly from the stream into memory in place. */
  1475.     /* clear the SEQ table */
  1476.     free(p_sys->seq_table);
  1477.     
  1478.     /* parse header info */
  1479.     stream_Read(p_demux->s, mst_buf, 32);
  1480.     i_map_size = U32_AT(&mst_buf[20]);  /* size of bitmask, in bytes */
  1481.     p_sys->i_bits_per_seq_entry = i_map_size * 8;
  1482.     i = U32_AT(&mst_buf[28]);   /* size of SEQ table, in bytes */
  1483.     p_sys->i_seq_table_size = i / (8 + i_map_size);
  1484.     /* parse all the entries */
  1485.     p_sys->seq_table = calloc(p_sys->i_seq_table_size, sizeof(ty_seq_table_t));
  1486.     if (p_sys->seq_table == NULL)
  1487.     {
  1488.         p_sys->i_seq_table_size = 0;
  1489.         return;
  1490.     }
  1491.     for (unsigned i=0; i<p_sys->i_seq_table_size; i++) {
  1492.         stream_Read(p_demux->s, mst_buf, 8);
  1493.         p_sys->seq_table[i].l_timestamp = U64_AT(&mst_buf[0]);
  1494.         if (i_map_size > 8) {
  1495.             msg_Err(p_demux, "Unsupported SEQ bitmap size in master chunk");
  1496.             stream_Read(p_demux->s, NULL, i_map_size);
  1497.         } else {
  1498.             stream_Read(p_demux->s, mst_buf + 8, i_map_size);
  1499.             memcpy(p_sys->seq_table[i].chunk_bitmask, &mst_buf[8], i_map_size);
  1500.         }
  1501.     }
  1502.     /* set up a few of our variables */
  1503.     p_sys->l_first_ty_pts = p_sys->seq_table[0].l_timestamp;
  1504.     p_sys->l_final_ty_pts =
  1505.         p_sys->seq_table[p_sys->i_seq_table_size - 1].l_timestamp;
  1506.     p_sys->b_have_master = true;
  1507.     i_pts_secs = p_sys->l_first_ty_pts / 1000000000;
  1508.     msg_Dbg( p_demux,
  1509.              "first TY pts in master is %02"PRId64":%02"PRId64":%02"PRId64,
  1510.              i_pts_secs / 3600, (i_pts_secs / 60) % 60, i_pts_secs % 60 );
  1511.     i_pts_secs = p_sys->l_final_ty_pts / 1000000000;
  1512.     msg_Dbg( p_demux,
  1513.              "final TY pts in master is %02"PRId64":%02"PRId64":%02"PRId64,
  1514.              i_pts_secs / 3600, (i_pts_secs / 60) % 60, i_pts_secs % 60 );
  1515.     /* seek past this chunk */
  1516.     stream_Seek(p_demux->s, i_save_pos + CHUNK_SIZE);
  1517. }
  1518. /* ======================================================================== */
  1519. /* "Peek" at some chunks.  Skip over the Part header if we find it.
  1520.  * We parse the peeked data and determine audio type,
  1521.  * SA vs. DTivo, & Tivo Series.
  1522.  * Set global vars i_Pes_Length, i_Pts_Offset,
  1523.  * p_sys->tivo_series, p_sys->tivo_type, p_sys->audio_type */
  1524. static int probe_stream(demux_t *p_demux)
  1525. {
  1526.     demux_sys_t *p_sys = p_demux->p_sys;
  1527.     const uint8_t *p_buf;
  1528.     int i;
  1529.     bool b_probe_error = false;
  1530.     /* we need CHUNK_PEEK_COUNT chunks of data, first one might be a Part header, so ... */
  1531.     if (stream_Peek( p_demux->s, &p_buf, CHUNK_PEEK_COUNT * CHUNK_SIZE ) <
  1532.             CHUNK_PEEK_COUNT * CHUNK_SIZE) {
  1533.         msg_Err(p_demux, "Can't peek %d chunks", CHUNK_PEEK_COUNT);
  1534.         /* TODO: if seekable, then loop reading chunks into a temp buffer */
  1535.         return VLC_EGENERIC;
  1536.     }
  1537.     
  1538.     /* the real work: analyze this chunk */
  1539.     for (i = 0; i < CHUNK_PEEK_COUNT; i++) {
  1540.         analyze_chunk(p_demux, p_buf);
  1541.         if (p_sys->tivo_series != TIVO_SERIES_UNKNOWN &&
  1542.             p_sys->audio_type  != TIVO_AUDIO_UNKNOWN &&
  1543.             p_sys->tivo_type   != TIVO_TYPE_UNKNOWN)
  1544.             break;
  1545.         p_buf += CHUNK_SIZE;
  1546.     }
  1547.     
  1548.     /* the final tally */
  1549.     if (p_sys->tivo_series == TIVO_SERIES_UNKNOWN) {
  1550.         msg_Err(p_demux, "Can't determine Tivo Series.");
  1551.         b_probe_error = true;
  1552.     }
  1553.     if (p_sys->audio_type == TIVO_AUDIO_UNKNOWN) {
  1554.         msg_Err(p_demux, "Can't determine Tivo Audio Type.");
  1555.         b_probe_error = true;
  1556.     }
  1557.     if (p_sys->tivo_type == TIVO_TYPE_UNKNOWN) {
  1558.         msg_Err(p_demux, "Can't determine Tivo Type (SA/DTivo).");
  1559.         b_probe_error = true;
  1560.     }
  1561.     return b_probe_error?VLC_EGENERIC:VLC_SUCCESS;
  1562. }
  1563. /* ======================================================================== */
  1564. /* gather statistics for this chunk & set our tivo-type vars accordingly */
  1565. static void analyze_chunk(demux_t *p_demux, const uint8_t *p_chunk)
  1566. {
  1567.     demux_sys_t *p_sys = p_demux->p_sys;
  1568.     int i_num_recs, i;
  1569.     ty_rec_hdr_t *p_hdrs;
  1570.     int i_num_6e0, i_num_be0, i_num_9c0, i_num_3c0;
  1571.     int i_payload_size;
  1572.     /* skip if it's a Part header */
  1573.     if( U32_AT( &p_chunk[ 0 ] ) == TIVO_PES_FILEID )
  1574.         return;
  1575.     /* number of records in chunk (we ignore high order byte;
  1576.      * rarely are there > 256 chunks & we don't need that many anyway) */
  1577.     i_num_recs = p_chunk[0];
  1578.     if (i_num_recs < 5) {
  1579.         /* try again with the next chunk.  Sometimes there are dead ones */
  1580.         return;
  1581.     }
  1582.     
  1583.     p_chunk += 4;       /* skip past rec count & SEQ bytes */
  1584.     //msg_Dbg(p_demux, "probe: chunk has %d recs", i_num_recs);
  1585.     p_hdrs = parse_chunk_headers(p_chunk, i_num_recs, &i_payload_size);
  1586.     /* scan headers.
  1587.      * 1. check video packets.  Presence of 0x6e0 means S1.
  1588.      *    No 6e0 but have be0 means S2.
  1589.      * 2. probe for audio 0x9c0 vs 0x3c0 (AC3 vs Mpeg)
  1590.      *    If AC-3, then we have DTivo.
  1591.      *    If MPEG, search for PTS offset.  This will determine SA vs. DTivo.
  1592.      */
  1593.     i_num_6e0 = i_num_be0 = i_num_9c0 = i_num_3c0 = 0;
  1594.     for (i=0; i<i_num_recs; i++) {
  1595.         //msg_Dbg(p_demux, "probe: rec is %d/%d = 0x%04x", p_hdrs[i].subrec_type,
  1596.             //p_hdrs[i].rec_type,
  1597.             //p_hdrs[i].subrec_type << 8 | p_hdrs[i].rec_type);
  1598.         switch (p_hdrs[i].subrec_type << 8 | p_hdrs[i].rec_type) {
  1599.             case 0x6e0:
  1600.                 i_num_6e0++;
  1601.                 break;
  1602.             case 0xbe0:
  1603.                 i_num_be0++;
  1604.                 break;
  1605.             case 0x3c0:
  1606.                 i_num_3c0++;
  1607.                 break;
  1608.             case 0x9c0:
  1609.                 i_num_9c0++;
  1610.                 break;
  1611.         }
  1612.     }
  1613.     msg_Dbg(p_demux, "probe: chunk has %d 0x6e0 recs, %d 0xbe0 recs.",
  1614.         i_num_6e0, i_num_be0);
  1615.     /* set up our variables */
  1616.     if (i_num_6e0 > 0) {
  1617.         msg_Dbg(p_demux, "detected Series 1 Tivo");
  1618.         p_sys->tivo_series = TIVO_SERIES1;
  1619.         p_sys->i_Pes_Length = SERIES1_PES_LENGTH;
  1620.     } else if (i_num_be0 > 0) {
  1621.         msg_Dbg(p_demux, "detected Series 2 Tivo");
  1622.         p_sys->tivo_series = TIVO_SERIES2;
  1623.         p_sys->i_Pes_Length = SERIES2_PES_LENGTH;
  1624.     }
  1625.     if (i_num_9c0 > 0) {
  1626.         msg_Dbg(p_demux, "detected AC-3 Audio (DTivo)" );
  1627.         p_sys->audio_type = TIVO_AUDIO_AC3;
  1628.         p_sys->tivo_type = TIVO_TYPE_DTIVO;
  1629.         p_sys->i_Pts_Offset = AC3_PTS_OFFSET;
  1630.         p_sys->i_Pes_Length = AC3_PES_LENGTH;
  1631.     } else if (i_num_3c0 > 0) {
  1632.         p_sys->audio_type = TIVO_AUDIO_MPEG;
  1633.         msg_Dbg(p_demux, "detected MPEG Audio" );
  1634.     }
  1635.     /* if tivo_type still unknown, we can check PTS location
  1636.      * in MPEG packets to determine tivo_type */
  1637.     if (p_sys->tivo_type == TIVO_TYPE_UNKNOWN) {
  1638.         uint32_t i_data_offset = (16 * i_num_recs);
  1639.         for (i=0; i<i_num_recs; i++) {
  1640.             if ((p_hdrs[i].subrec_type << 0x08 | p_hdrs[i].rec_type) == 0x3c0 &&
  1641.                     p_hdrs[i].l_rec_size > 15) {
  1642.                 /* first make sure we're aligned */
  1643.                 int i_pes_offset = find_es_header(ty_MPEGAudioPacket,
  1644.                         &p_chunk[i_data_offset], 5);
  1645.                 if (i_pes_offset >= 0) {
  1646.                     /* pes found. on SA, PES has hdr data at offset 6, not PTS. */
  1647.                     //msg_Dbg(p_demux, "probe: mpeg es header found in rec %d at offset %d",
  1648.                             //i, i_pes_offset);
  1649.                     if ((p_chunk[i_data_offset + 6 + i_pes_offset] & 0x80) == 0x80) {
  1650.                         /* S1SA or S2(any) Mpeg Audio (PES hdr, not a PTS start) */
  1651.                         if (p_sys->tivo_series == TIVO_SERIES1)
  1652.                             msg_Dbg(p_demux, "detected Stand-Alone Tivo" );
  1653.                         p_sys->tivo_type = TIVO_TYPE_SA;
  1654.                         p_sys->i_Pts_Offset = SA_PTS_OFFSET;
  1655.                     } else {
  1656.                         if (p_sys->tivo_series == TIVO_SERIES1)
  1657.                             msg_Dbg(p_demux, "detected DirecTV Tivo" );
  1658.                         p_sys->tivo_type = TIVO_TYPE_DTIVO;
  1659.                         p_sys->i_Pts_Offset = DTIVO_PTS_OFFSET;
  1660.                     }
  1661.                     break;
  1662.                 }
  1663.             }
  1664.             i_data_offset += p_hdrs[i].l_rec_size;
  1665.         }
  1666.     }
  1667.     free(p_hdrs);
  1668. }
  1669. /* =========================================================================== */
  1670. static int get_chunk_header(demux_t *p_demux)
  1671. {
  1672.     int i_readSize, i_num_recs;
  1673.     uint8_t *p_hdr_buf;
  1674.     const uint8_t *p_peek;
  1675.     demux_sys_t *p_sys = p_demux->p_sys;
  1676.     int i_payload_size;             /* sum of all records' sizes */
  1677.     msg_Dbg(p_demux, "parsing ty chunk #%d", p_sys->i_cur_chunk );
  1678.     /* if we have left-over filler space from the last chunk, get that */
  1679.     if (p_sys->i_stuff_cnt > 0) {
  1680.         stream_Read( p_demux->s, NULL, p_sys->i_stuff_cnt);
  1681.         p_sys->i_stuff_cnt = 0;
  1682.     }
  1683.     /* read the TY packet header */
  1684.     i_readSize = stream_Peek( p_demux->s, &p_peek, 4 );
  1685.     p_sys->i_cur_chunk++;
  1686.   
  1687.     if ( (i_readSize < 4) || ( U32_AT(&p_peek[ 0 ] ) == 0 ))
  1688.     {
  1689.         /* EOF */
  1690.         p_sys->eof = 1;
  1691.         return 0;
  1692.     }
  1693.   
  1694.     /* check if it's a PART Header */
  1695.     if( U32_AT( &p_peek[ 0 ] ) == TIVO_PES_FILEID )
  1696.     {
  1697.         /* parse master chunk */
  1698.         parse_master(p_demux);
  1699.         return get_chunk_header(p_demux);
  1700.     }
  1701.     
  1702.     /* number of records in chunk (8- or 16-bit number) */
  1703.     if (p_peek[3] & 0x80)
  1704.     {
  1705.         /* 16 bit rec cnt */
  1706.         p_sys->i_num_recs = i_num_recs = (p_peek[1] << 8) + p_peek[0];
  1707.         p_sys->i_seq_rec = (p_peek[3] << 8) + p_peek[2];
  1708.         if (p_sys->i_seq_rec != 0xffff)
  1709.         {
  1710.             p_sys->i_seq_rec &= ~0x8000;
  1711.         }
  1712.     }
  1713.     else
  1714.     {
  1715.         /* 8 bit reclen - tivo 1.3 format */
  1716.         p_sys->i_num_recs = i_num_recs = p_peek[0];
  1717.         p_sys->i_seq_rec = p_peek[1];
  1718.     }
  1719.     p_sys->i_cur_rec = 0;
  1720.     p_sys->b_first_chunk = false;
  1721.   
  1722.     /*msg_Dbg( p_demux, "chunk has %d records", i_num_recs );*/
  1723.     free(p_sys->rec_hdrs);
  1724.     /* skip past the 4 bytes we "peeked" earlier */
  1725.     stream_Read( p_demux->s, NULL, 4 );
  1726.     /* read the record headers into a temp buffer */
  1727.     p_hdr_buf = malloc(i_num_recs * 16);
  1728.     if (stream_Read(p_demux->s, p_hdr_buf, i_num_recs * 16) < i_num_recs * 16) {
  1729.         free( p_hdr_buf );
  1730.         p_sys->eof = true;
  1731.         return 0;
  1732.     }
  1733.     /* parse them */
  1734.     p_sys->rec_hdrs = parse_chunk_headers(p_hdr_buf, i_num_recs,
  1735.             &i_payload_size);
  1736.     free(p_hdr_buf);
  1737.     p_sys->i_stuff_cnt = CHUNK_SIZE - 4 -
  1738.         (p_sys->i_num_recs * 16) - i_payload_size;
  1739.     if (p_sys->i_stuff_cnt > 0)
  1740.         msg_Dbg( p_demux, "chunk has %d stuff bytes at end",
  1741.                  p_sys->i_stuff_cnt );
  1742.     return 1;
  1743. }
  1744. static ty_rec_hdr_t *parse_chunk_headers( const uint8_t *p_buf,
  1745.                                           int i_num_recs, int *pi_payload_size)
  1746. {
  1747.     int i;
  1748.     ty_rec_hdr_t *p_hdrs, *p_rec_hdr;
  1749.     *pi_payload_size = 0;
  1750.     p_hdrs = malloc(i_num_recs * sizeof(ty_rec_hdr_t));
  1751.     for (i = 0; i < i_num_recs; i++)
  1752.     {
  1753.         const uint8_t *record_header = p_buf + (i * 16);
  1754.         p_rec_hdr = &p_hdrs[i];     /* for brevity */
  1755.         p_rec_hdr->rec_type = record_header[3];
  1756.         p_rec_hdr->subrec_type = record_header[2] & 0x0f;
  1757.         if ((record_header[ 0 ] & 0x80) == 0x80)
  1758.         {
  1759.             uint8_t b1, b2;
  1760.             /* marker bit 2 set, so read extended data */
  1761.             b1 = ( ( ( record_header[ 0 ] & 0x0f ) << 4 ) | 
  1762.                    ( ( record_header[ 1 ] & 0xf0 ) >> 4 ) );
  1763.             b2 = ( ( ( record_header[ 1 ] & 0x0f ) << 4 ) | 
  1764.                    ( ( record_header[ 2 ] & 0xf0 ) >> 4 ) );
  1765.             p_rec_hdr->ex[0] = b1;
  1766.             p_rec_hdr->ex[1] = b2;
  1767.             p_rec_hdr->l_rec_size = 0;
  1768.             p_rec_hdr->l_ty_pts = 0;
  1769.             p_rec_hdr->b_ext = true;
  1770.         }
  1771.         else
  1772.         {
  1773.             p_rec_hdr->l_rec_size = ( record_header[ 0 ] << 8 |
  1774.                 record_header[ 1 ] ) << 4 | ( record_header[ 2 ] >> 4 );
  1775.             *pi_payload_size += p_rec_hdr->l_rec_size;
  1776.             p_rec_hdr->b_ext = false;
  1777.             p_rec_hdr->l_ty_pts = U64_AT( &record_header[ 8 ] );
  1778.         }
  1779.         //fprintf( stderr, "parse_chunk_headers[%d] t=0x%x s=%dn", i, p_rec_hdr->rec_type, p_rec_hdr->subrec_type );
  1780.     } /* end of record-header loop */
  1781.     return p_hdrs;
  1782. }