22f1d4f80de1ac5e4bd403510604411d8f62eb99
[vlc.git] / modules / demux / ty.c
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$
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 /*****************************************************************************
35  * Preamble
36  *****************************************************************************/
37
38 #include <vlc/vlc.h>
39 #include <vlc_demux.h>
40 #include "vlc_codec.h"
41
42 /*****************************************************************************
43  * Module descriptor
44  *****************************************************************************/
45 static int  Open ( vlc_object_t * );
46 static void Close( vlc_object_t * );
47
48 vlc_module_begin();
49     set_shortname( _("TY") );
50     set_description(_("TY Stream audio/video demux"));
51     set_category( CAT_INPUT );
52     set_subcategory( SUBCAT_INPUT_DEMUX );
53     set_capability("demux2", 6);
54     /* FIXME: there seems to be a segfault when using PVR access
55      * and TY demux has a bigger priority than PS
56      * Something must be wrong.
57      */
58     set_callbacks( Open, Close );
59     add_shortcut("ty");
60     add_shortcut("tivo");
61 vlc_module_end();
62
63 /*****************************************************************************
64  * Local prototypes
65  *****************************************************************************/
66 static int Demux  ( demux_t * );
67 static int Control( demux_t *, int, va_list );
68
69 #define SERIES1_PES_LENGTH  (11)    /* length of audio PES hdr on S1 */
70 #define SERIES2_PES_LENGTH  (16)    /* length of audio PES hdr on S2 */
71 #define AC3_PES_LENGTH      (14)    /* length of audio PES hdr for AC3 */
72 #define VIDEO_PES_LENGTH    (16)    /* length of video PES header */
73 #define DTIVO_PTS_OFFSET    (6)     /* offs into PES for MPEG PTS on DTivo */
74 #define SA_PTS_OFFSET       (9)     /* offset into PES for MPEG PTS on SA */
75 #define AC3_PTS_OFFSET      (9)     /* offset into PES for AC3 PTS on DTivo */
76 #define VIDEO_PTS_OFFSET    (9)     /* offset into PES for video PTS on all */
77 #define AC3_PKT_LENGTH      (1536)  /* size of TiVo AC3 pkts (w/o PES hdr) */
78 static const uint8_t ty_VideoPacket[] = { 0x00, 0x00, 0x01, 0xe0 };
79 static const uint8_t ty_MPEGAudioPacket[] = { 0x00, 0x00, 0x01, 0xc0 };
80 static const uint8_t ty_AC3AudioPacket[] = { 0x00, 0x00, 0x01, 0xbd };
81
82 #define CHUNK_PEEK_COUNT    (3)         /* number of chunks to probe */
83
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
102 #define TIVO_PES_FILEID   ( 0xf5467abd )
103 #define TIVO_PART_LENGTH  ( 0x20000000 )    /* 536,870,912 bytes */
104 #define CHUNK_SIZE        ( 128 * 1024 )
105
106 typedef struct
107 {
108   long l_rec_size;
109   uint8_t ex1, ex2;
110   uint8_t rec_type;
111   uint8_t subrec_type;
112   vlc_bool_t b_ext;
113   uint64_t l_ty_pts;            /* TY PTS in the record header */
114 } ty_rec_hdr_t;
115
116 typedef struct
117 {
118     uint64_t l_timestamp;
119     uint8_t chunk_bitmask[8];
120 } ty_seq_table_t;
121
122 typedef enum
123 {
124     TIVO_TYPE_UNKNOWN,
125     TIVO_TYPE_SA,
126     TIVO_TYPE_DTIVO
127 } tivo_type_t;
128
129 typedef enum
130 {
131     TIVO_SERIES_UNKNOWN,
132     TIVO_SERIES1,
133     TIVO_SERIES2
134 } tivo_series_t;
135
136 typedef enum
137 {
138     TIVO_AUDIO_UNKNOWN,
139     TIVO_AUDIO_AC3,
140     TIVO_AUDIO_MPEG
141 } tivo_audio_t;
142
143 struct demux_sys_t
144 {
145   es_out_id_t *p_video;               /* ptr to video codec */
146   es_out_id_t *p_audio;               /* holds either ac3 or mpeg codec ptr */
147
148   int             i_cur_chunk;
149   int             i_stuff_cnt;
150   size_t          i_stream_size;      /* size of input stream (if known) */
151   //uint64_t        l_program_len;      /* length of this stream in msec */
152   vlc_bool_t      b_seekable;         /* is this stream seekable? */
153   vlc_bool_t      b_have_master;      /* are master chunks present? */
154   tivo_type_t     tivo_type;          /* tivo type (SA / DTiVo) */
155   tivo_series_t   tivo_series;        /* Series1 or Series2 */
156   tivo_audio_t    audio_type;         /* AC3 or MPEG */
157   int             i_Pes_Length;       /* Length of Audio PES header */
158   int             i_Pts_Offset;       /* offset into audio PES of PTS */
159   uint8_t         pes_buffer[20];     /* holds incomplete pes headers */
160   int             i_pes_buf_cnt;      /* how many bytes in our buffer */
161   size_t          l_ac3_pkt_size;     /* len of ac3 pkt we've seen so far */
162   uint64_t        l_last_ty_pts;      /* last TY timestamp we've seen */
163   //mtime_t         l_last_ty_pts_sync; /* audio PTS at time of last TY PTS */
164   uint64_t        l_first_ty_pts;     /* first TY PTS in this master chunk */
165   uint64_t        l_final_ty_pts;     /* final TY PTS in this master chunk */
166   int             i_seq_table_size;   /* number of entries in SEQ table */
167   int             i_bits_per_seq_entry; /* # of bits in SEQ table bitmask */
168
169   mtime_t         firstAudioPTS;
170   mtime_t         lastAudioPTS;
171   mtime_t         lastVideoPTS;
172
173   ty_rec_hdr_t    *rec_hdrs;          /* record headers array */
174   int             i_cur_rec;          /* current record in this chunk */
175   int             i_num_recs;         /* number of recs in this chunk */
176   int             i_seq_rec;          /* record number where seq start is */
177   ty_seq_table_t  *seq_table;         /* table of SEQ entries from mstr chk */
178   vlc_bool_t      eof;
179   vlc_bool_t      b_first_chunk;
180 };
181
182 static int get_chunk_header(demux_t *);
183 static mtime_t get_pts( const uint8_t *buf );
184 static int find_es_header( const uint8_t *header,
185                            const uint8_t *buffer, int i_search_len );
186 static int ty_stream_seek_pct(demux_t *p_demux, double seek_pct);
187 static int ty_stream_seek_time(demux_t *, uint64_t);
188
189 static ty_rec_hdr_t *parse_chunk_headers( demux_t *p_demux, const uint8_t *p_buf,
190                                           int i_num_recs, int *pi_payload_size);
191 static int probe_stream(demux_t *p_demux);
192 static void analyze_chunk(demux_t *p_demux, const uint8_t *p_chunk);
193 static void parse_master(demux_t *p_demux);
194
195 /*
196  * Open: check file and initialize demux structures
197  *
198  * here's what we do:
199  * 1. peek at the first 12 bytes of the stream for the
200  *    magic TiVo PART header & stream type & chunk size
201  * 2. if it's not there, error with VLC_EGENERIC
202  * 3. set up video (mpgv) codec
203  * 4. return VLC_SUCCESS
204  */
205 static int Open(vlc_object_t *p_this)
206 {
207     demux_t *p_demux = (demux_t *)p_this;
208     demux_sys_t *p_sys;
209     es_format_t fmt;
210     const uint8_t *p_peek;
211
212     /* peek at the first 12 bytes. */
213     /* for TY streams, they're always the same */
214     if( stream_Peek( p_demux->s, &p_peek, 12 ) < 12 )
215         return VLC_EGENERIC;
216
217     if ( U32_AT(p_peek) != TIVO_PES_FILEID ||
218          U32_AT(&p_peek[4]) != 0x02 ||
219          U32_AT(&p_peek[8]) != CHUNK_SIZE )
220     {
221         if( !p_demux->b_force )
222             return VLC_EGENERIC;
223         msg_Warn( p_demux, "this does not look like a TY file, "
224                            "continuing anyway..." );
225     }
226
227         /* at this point, we assume we have a valid TY stream */  
228     msg_Dbg( p_demux, "valid TY stream detected" );
229
230     /* Set exported functions */
231     p_demux->pf_demux = Demux;
232     p_demux->pf_control = Control;
233
234     /* create our structure that will hold all data */
235     p_demux->p_sys = p_sys = malloc(sizeof(demux_sys_t));
236     memset(p_sys, 0, sizeof(demux_sys_t));
237
238     /* set up our struct (most were zero'd out with the memset above) */
239     p_sys->b_first_chunk = VLC_TRUE;
240     p_sys->b_have_master = (U32_AT(p_peek) == TIVO_PES_FILEID);
241     p_sys->firstAudioPTS = -1;
242     p_sys->i_stream_size = stream_Size(p_demux->s);
243     p_sys->tivo_type = TIVO_TYPE_UNKNOWN;
244     p_sys->audio_type = TIVO_AUDIO_UNKNOWN;
245     p_sys->tivo_series = TIVO_SERIES_UNKNOWN;
246     p_sys->i_Pes_Length = 0;
247     p_sys->i_Pts_Offset = 0;
248     p_sys->l_ac3_pkt_size = 0;
249   
250     /* see if this stream is seekable */
251     stream_Control( p_demux->s, STREAM_CAN_SEEK, &p_sys->b_seekable );
252
253     if (probe_stream(p_demux) != VLC_SUCCESS) {
254         //TyClose(p_demux);
255         return VLC_EGENERIC;
256     }
257
258     if (!p_sys->b_have_master)
259       msg_Warn(p_demux, "No master chunk found; seeking will be limited.");
260
261     /* register the proper audio codec */
262     if (p_sys->audio_type == TIVO_AUDIO_MPEG) {
263         es_format_Init( &fmt, AUDIO_ES, VLC_FOURCC( 'm', 'p', 'g', 'a' ) );
264     } else {
265         es_format_Init( &fmt, AUDIO_ES, VLC_FOURCC( 'a', '5', '2', ' ' ) );
266     }
267     p_sys->p_audio = es_out_Add( p_demux->out, &fmt );
268
269     /* register the video stream */
270     es_format_Init( &fmt, VIDEO_ES, VLC_FOURCC( 'm', 'p', 'g', 'v' ) );
271     p_sys->p_video = es_out_Add( p_demux->out, &fmt );
272
273 #if 0
274     /* register the CC decoder */
275     es_format_Init( &fmt, SPU_ES, VLC_FOURCC('s', 'u', 'b', 't'));
276     p_sys->p_subt_es = es_out_Add(p_demux->out, &fmt);
277 #endif
278
279     return VLC_SUCCESS;
280 }
281
282
283 /* =========================================================================== */
284 /* Compute Presentation Time Stamp (PTS)
285  * Assume buf points to beginning of PTS */
286 static mtime_t get_pts( const uint8_t *buf )
287 {
288     mtime_t i_pts;
289
290     i_pts = ((mtime_t)(buf[0]&0x0e ) << 29)|
291              (mtime_t)(buf[1] << 22)|
292             ((mtime_t)(buf[2]&0xfe) << 14)|
293              (mtime_t)(buf[3] << 7)|
294              (mtime_t)(buf[4] >> 1);
295     i_pts *= 100 / 9;   /* convert PTS (90Khz clock) to microseconds */
296     return i_pts;
297 }
298
299
300 /* =========================================================================== */
301 static int find_es_header( const uint8_t *header,
302                            const uint8_t *buffer, int i_search_len )
303 {
304     int count;
305
306     for( count = 0; count < i_search_len; count++ )
307     {
308         if( !memcmp( &buffer[count], header, 4 ) )
309             return count;
310     }
311     return -1;
312 }
313
314
315 /* =========================================================================== */
316 /* check if we have a full PES header, if not, then save what we have.
317  * this is called when audio-start packets are encountered.
318  * Returns:
319  *     1 partial PES hdr found, some audio data found (buffer adjusted),
320  *    -1 partial PES hdr found, no audio data found
321  *     0 otherwise (complete PES found, pts extracted, pts set, buffer adjusted) */
322 /* TODO: HD support -- nothing known about those streams */
323 static int check_sync_pes( demux_t *p_demux, block_t *p_block,
324                            int32_t offset, int32_t rec_len )
325 {
326     demux_sys_t *p_sys = p_demux->p_sys;
327
328     if ( offset < 0 || offset + p_sys->i_Pes_Length > rec_len )
329     {
330         /* entire PES header not present */
331         msg_Dbg( p_demux, "PES header at %d not complete in record. storing.",
332                  offset );
333         /* save the partial pes header */
334         if( offset < 0 )
335         {
336             /* no header found, fake some 00's (this works, believe me) */
337             memset( p_sys->pes_buffer, 4, 0 );
338             p_sys->i_pes_buf_cnt = 4;
339             if( rec_len > 4 )
340                 msg_Err( p_demux, "PES header not found in record of %d bytes!",
341                          rec_len );
342             return -1;
343         }
344         /* copy the partial pes header we found */
345         memcpy( p_sys->pes_buffer, p_block->p_buffer + offset,
346                 rec_len - offset );
347         p_sys->i_pes_buf_cnt = rec_len - offset;
348
349         if( offset > 0 )
350         {
351             /* PES Header was found, but not complete, so trim the end of this record */
352             p_block->i_buffer -= rec_len - offset;
353             return 1;
354         }
355         return -1;    /* partial PES, no audio data */
356     }
357     /* full PES header present, extract PTS */
358     p_sys->lastAudioPTS = get_pts( &p_block->p_buffer[ offset +
359             p_sys->i_Pts_Offset ] );
360     if (p_sys->firstAudioPTS < 0)
361         p_sys->firstAudioPTS = p_sys->lastAudioPTS;
362     p_block->i_pts = p_sys->lastAudioPTS;
363     /*msg_Dbg(p_demux, "Audio PTS %lld", p_sys->lastAudioPTS );*/
364     /* adjust audio record to remove PES header */
365     memmove(p_block->p_buffer + offset, p_block->p_buffer + offset +
366             p_sys->i_Pes_Length, rec_len - p_sys->i_Pes_Length);
367     p_block->i_buffer -= p_sys->i_Pes_Length;
368 #if 0
369     msg_Dbg(p_demux, "pes hdr removed; buffer len=%d and has "
370              "%02x %02x %02x %02x %02x %02x %02x %02x "
371              "%02x %02x %02x %02x %02x %02x %02x %02x", p_block->i_buffer,
372              p_block->p_buffer[0], p_block->p_buffer[1],
373              p_block->p_buffer[2], p_block->p_buffer[3],
374              p_block->p_buffer[4], p_block->p_buffer[5],
375              p_block->p_buffer[6], p_block->p_buffer[7],
376              p_block->p_buffer[8], p_block->p_buffer[9],
377              p_block->p_buffer[10], p_block->p_buffer[11],
378              p_block->p_buffer[12], p_block->p_buffer[13],
379              p_block->p_buffer[14], p_block->p_buffer[15]);
380 #endif
381     return 0;
382 }
383
384
385 /* =========================================================================== */
386 /* Demux: Read & Demux one record from the chunk
387  *
388  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
389  *
390  * NOTE: I think we can return the number of packets sent instead of just 1.
391  * that means we can demux an entire chunk and shoot it back (may be more efficient)
392  * -- should try that some day :) --
393  */
394 static int Demux( demux_t *p_demux )
395 {
396     demux_sys_t      *p_sys = p_demux->p_sys;
397
398     int              invalidType = 0;
399     int              recordsDecoded = 0;
400
401     int              rec_type;
402     long             l_rec_size;
403     int              i_cur_rec;
404     int              subrec_type;
405     ty_rec_hdr_t     *rec_hdr;
406
407     block_t          *p_block_in = NULL;
408     int              esOffset1;
409
410     uint8_t          lastCC[ 16 ];
411     uint8_t          lastXDS[ 16 ];
412
413     /*msg_Dbg(p_demux, "ty demux processing" );*/
414    
415     /* did we hit EOF earlier? */
416     if (p_sys->eof) return 0;
417
418     /*
419      * what we do (1 record now.. maybe more later):
420     * - use stream_Read() to read the chunk header & record headers
421     * - discard entire chunk if it is a PART header chunk
422     * - parse all the headers into record header array
423     * - keep a pointer of which record we're on
424     * - use stream_Block() to fetch each record
425     * - parse out PTS from PES headers
426     * - set PTS for data packets
427     * - pass the data on to the proper codec via es_out_Send()
428
429     * if this is the first time or  
430     * if we're at the end of this chunk, start a new one
431     */
432     /* parse the next chunk's record headers */
433     if (p_sys->b_first_chunk || p_sys->i_cur_rec >= p_sys->i_num_recs)
434         if (get_chunk_header(p_demux) == 0)
435             return 0;
436
437     /*======================================================================
438      * parse & send one record of the chunk
439      *====================================================================== */
440     i_cur_rec = p_sys->i_cur_rec;
441     recordsDecoded++;
442     rec_hdr = &p_sys->rec_hdrs[ i_cur_rec ];
443     subrec_type = rec_hdr->subrec_type;
444     rec_type = rec_hdr->rec_type;
445     l_rec_size = rec_hdr->l_rec_size;
446
447     if (!rec_hdr->b_ext)
448     {
449         /*msg_Dbg(p_demux, "Record Type 0x%x/%02x %ld bytes",
450                     subrec_type, rec_type, l_rec_size );*/
451   
452         /* some normal records are 0 length, so check for that... */
453         if (l_rec_size > 0)
454         {
455             /* read in this record's payload */
456             if( !( p_block_in = stream_Block( p_demux->s, l_rec_size ) ) )
457             {
458                 /* EOF */
459                 p_sys->eof = 1;
460                 return 0;
461             }
462             /* set these as 'unknown' for now */
463             p_block_in->i_pts = p_block_in->i_dts = 0;
464         }
465         else
466         {
467             /* no data in payload; we're done */
468             p_sys->i_cur_rec++;
469             return 1;
470         }
471     }
472     /*else
473     {
474         -- don't read any data from the stream, data was in the record header --
475         msg_Dbg(p_demux,
476                "Record Type 0x%02x/%02x, ext data = %02x, %02x", subrec_type,
477                 rec_type, rec_hdr->ex1, rec_hdr->ex2);
478     }*/
479
480     /*================================================================*
481      * Video Parsing
482      *================================================================*/
483     if ( rec_type == 0xe0 )
484     {
485 #if 0
486         msg_Dbg(p_demux, "packet buffer has "
487                 "%02x %02x %02x %02x %02x %02x %02x %02x "
488                 "%02x %02x %02x %02x %02x %02x %02x %02x",
489                 p_block_in->p_buffer[0], p_block_in->p_buffer[1],
490                 p_block_in->p_buffer[2], p_block_in->p_buffer[3],
491                 p_block_in->p_buffer[4], p_block_in->p_buffer[5],
492                 p_block_in->p_buffer[6], p_block_in->p_buffer[7],
493                 p_block_in->p_buffer[8], p_block_in->p_buffer[9],
494                 p_block_in->p_buffer[10], p_block_in->p_buffer[11],
495                 p_block_in->p_buffer[12], p_block_in->p_buffer[13],
496                 p_block_in->p_buffer[14], p_block_in->p_buffer[15]);
497 #endif
498         //if( subrec_type == 0x06 || subrec_type == 0x07 )
499         if( subrec_type != 0x02 && subrec_type != 0x0c
500             && subrec_type != 0x08 && l_rec_size > 4 )
501         {
502             /* get the PTS from this packet if it has one.
503              * on S1, only 0x06 has PES.  On S2, however, most all do.
504              * Do NOT Pass the PES Header to the MPEG2 codec */
505             esOffset1 = find_es_header( ty_VideoPacket, p_block_in->p_buffer,
506                     5 );
507             if ( esOffset1 != -1 )
508             {
509                 //msg_Dbg(p_demux, "Video PES hdr in pkt type 0x%02x at offset %d",
510                     //subrec_type, esOffset1);
511                 p_sys->lastVideoPTS = get_pts(
512                         &p_block_in->p_buffer[ esOffset1 + VIDEO_PTS_OFFSET ] );
513                 /*msg_Dbg(p_demux, "Video rec %d PTS "I64Fd, p_sys->i_cur_rec,
514                             p_sys->lastVideoPTS );*/
515                 if (subrec_type != 0x06) {
516                     /* if we found a PES, and it's not type 6, then we're S2 */
517                     /* The packet will have video data (& other headers) so we
518                      * chop out the PES header and send the rest */
519                     if (l_rec_size >= VIDEO_PES_LENGTH) {
520                         p_block_in->p_buffer += VIDEO_PES_LENGTH + esOffset1;
521                         p_block_in->i_buffer -= VIDEO_PES_LENGTH + esOffset1;
522                     } else {
523                         msg_Dbg(p_demux, "video rec type 0x%02x has short PES"
524                             " (%ld bytes)", subrec_type, l_rec_size);
525                         /* nuke this block; it's too short, but has PES marker */
526                         p_block_in->i_buffer = 0;
527                     }
528                 }
529             }/* else
530                 msg_Dbg(p_demux, "No Video PES hdr in pkt type 0x%02x",
531                     subrec_type); */
532         }
533         if (subrec_type == 0x06) {
534             /* type 6 (S1 DTivo) has no data, so we're done */
535             block_Release(p_block_in);
536         } else {
537             /* if it's not a continue blk, then set PTS */
538             if (subrec_type != 0x02)
539             {
540                 /*msg_Dbg(p_demux, "Video rec %d type 0x%02X", p_sys->i_cur_rec,
541                            subrec_type);*/
542                 /* if it's a GOP header, make sure it's legal
543                  * (if we have enough data) */
544                 /* Some ty files don't have this bit set
545                  * and it causes problems */
546                 if (subrec_type == 0x0c && l_rec_size >= 6)
547                     p_block_in->p_buffer[5] |= 0x08;
548                 /* store the TY PTS if there is one */
549                 if (subrec_type == 0x07) {
550                     p_sys->l_last_ty_pts = rec_hdr->l_ty_pts;
551                     /* should we use audio or video PTS? */
552                     //p_sys->l_last_ty_pts_sync = p_sys->lastAudioPTS;
553                 } else {
554                     /* yes I know this is a cheap hack.  It's the timestamp
555                        used for display and skipping fwd/back, so it
556                        doesn't have to be accurate to the millisecond.
557                        I adjust it here by roughly one 1/30 sec.  Yes it
558                        will be slightly off for UK streams, but it's OK.
559                      */
560                     p_sys->l_last_ty_pts += 35000000;
561                     //p_sys->l_last_ty_pts += 33366667;
562                 }
563                 /* set PTS for this block before we send */
564                 if (p_sys->lastVideoPTS > 0)
565                 {
566                     p_block_in->i_pts = p_sys->lastVideoPTS;
567                     /* PTS gets used ONCE. 
568                      * Any subsequent frames we get BEFORE next PES
569                      * header will have their PTS computed in the codec */
570                     p_sys->lastVideoPTS = 0;
571                 }
572             }
573             //msg_Dbg(p_demux, "sending rec %d as video type 0x%02x",
574                     //p_sys->i_cur_rec, subrec_type);
575             es_out_Send(p_demux->out, p_sys->p_video, p_block_in);
576         }
577     } /* end if video rec type */
578     /* ================================================================
579      * Audio Parsing
580      * ================================================================
581      * parse PES headers and send the rest to the codec
582      */
583     else if ( rec_type == 0xc0 )
584     {
585 #if 0
586         int i;
587         printf( "Audio Packet Header " );
588         for( i = 0 ; i < 24 ; i++ )
589             printf( "%2.2x ", p_block_in->p_buffer[i] );
590         printf( "\n" );
591 #endif
592
593         /* SA or DTiVo Audio Data, no PES (continued block)
594          * ================================================
595          */
596         if ( subrec_type == 2 )
597         {
598             /* continue PES if previous was incomplete */
599             if (p_sys->i_pes_buf_cnt > 0)
600             {
601                 int i_need = p_sys->i_Pes_Length - p_sys->i_pes_buf_cnt;
602
603                 msg_Dbg(p_demux, "continuing PES header");
604                 /* do we have enough data to complete? */
605                 if (i_need < l_rec_size)
606                 {
607                     /* we have enough; reconstruct this p_frame with the new hdr */
608                     memcpy(&p_sys->pes_buffer[p_sys->i_pes_buf_cnt],
609                            p_block_in->p_buffer, i_need);
610                     /* advance the block past the PES header (don't want to send it) */
611                     p_block_in->p_buffer += i_need;
612                     p_block_in->i_buffer -= i_need;
613                     /* get the PTS out of this PES header (MPEG or AC3) */
614                     if (p_sys->audio_type == TIVO_AUDIO_MPEG)
615                         esOffset1 = find_es_header(ty_MPEGAudioPacket,
616                                 p_sys->pes_buffer, 5);
617                     else
618                         esOffset1 = find_es_header(ty_AC3AudioPacket,
619                                 p_sys->pes_buffer, 5);
620                     if (esOffset1 < 0)
621                     {
622                         /* god help us; something's really wrong */
623                         msg_Err(p_demux, "can't find audio PES header in packet");
624                     }
625                     else
626                     {
627                         p_sys->lastAudioPTS = get_pts( 
628                             &p_sys->pes_buffer[ esOffset1 + p_sys->i_Pts_Offset ] );
629                         p_block_in->i_pts = p_sys->lastAudioPTS;
630                     }
631                     p_sys->i_pes_buf_cnt = 0;
632                 }
633                 else
634                 {
635                     /* don't have complete PES hdr; save what we have and return */
636                     memcpy(&p_sys->pes_buffer[p_sys->i_pes_buf_cnt],
637                             p_block_in->p_buffer, l_rec_size);
638                     p_sys->i_pes_buf_cnt += l_rec_size;
639                     p_sys->i_cur_rec++;
640                     block_Release(p_block_in);
641                     return 1;
642                 }
643             }
644             /* S2 DTivo has AC3 packets with 2 padding bytes at end.  This is
645              * not allowed in the AC3 spec and will cause problems.  So here
646              * we try to trim things. */
647             /* Also, S1 DTivo has alternating short / long AC3 packets.  That
648              * is, one packet is short (incomplete) and the next packet has
649              * the first one's missing data, plus all of its own.  Strange. */
650             if (p_sys->audio_type == TIVO_AUDIO_AC3 &&
651                     p_sys->tivo_series == TIVO_SERIES2) {
652                 if (p_sys->l_ac3_pkt_size + p_block_in->i_buffer >
653                         AC3_PKT_LENGTH) {
654                     p_block_in->i_buffer -= 2;
655                     p_sys->l_ac3_pkt_size = 0;
656                 } else {
657                     p_sys->l_ac3_pkt_size += p_block_in->i_buffer;
658                 }
659             }
660             es_out_Send( p_demux->out, p_sys->p_audio, p_block_in );
661         } /* subrec == 2 */
662
663         /* MPEG Audio with PES Header, either SA or DTiVo   */
664         /* ================================================ */
665         if ( subrec_type == 0x03 )
666         {
667             esOffset1 = find_es_header( ty_MPEGAudioPacket,
668                     p_block_in->p_buffer, 5 );
669
670             /*msg_Dbg(p_demux, "buffer has %#02x %#02x %#02x %#02x",
671                p_block_in->p_buffer[0], p_block_in->p_buffer[1],
672                p_block_in->p_buffer[2], p_block_in->p_buffer[3]);
673             msg_Dbg(p_demux, "audio ES hdr at offset %d", esOffset1);*/
674
675             /* SA PES Header, No Audio Data                     */
676             /* ================================================ */
677             if ( ( esOffset1 == 0 ) && ( l_rec_size == 16 ) )
678             {
679                 p_sys->lastAudioPTS = get_pts( &p_block_in->p_buffer[
680                             SA_PTS_OFFSET ] );
681                 if (p_sys->firstAudioPTS < 0)
682                     p_sys->firstAudioPTS = p_sys->lastAudioPTS;
683                 block_Release(p_block_in);
684                 /*msg_Dbg(p_demux, "SA Audio PTS %lld",
685                            p_sys->lastAudioPTS );*/
686             }
687             else
688             /* DTiVo Audio with PES Header                      */
689             /* ================================================ */
690             {
691                 /* Check for complete PES */
692                 if (check_sync_pes(p_demux, p_block_in, esOffset1,
693                                     l_rec_size) == -1)
694                 {
695                     /* partial PES header found, nothing else. 
696                      * we're done. */
697                     p_sys->i_cur_rec++;
698                     block_Release(p_block_in);
699                     return 1;
700                 }
701 #if 0
702                 msg_Dbg(p_demux, "packet buffer has "
703                          "%02x %02x %02x %02x %02x %02x %02x %02x "
704                          "%02x %02x %02x %02x %02x %02x %02x %02x",
705                          p_block_in->p_buffer[0], p_block_in->p_buffer[1],
706                          p_block_in->p_buffer[2], p_block_in->p_buffer[3],
707                          p_block_in->p_buffer[4], p_block_in->p_buffer[5],
708                          p_block_in->p_buffer[6], p_block_in->p_buffer[7],
709                          p_block_in->p_buffer[8], p_block_in->p_buffer[9],
710                          p_block_in->p_buffer[10], p_block_in->p_buffer[11],
711                          p_block_in->p_buffer[12], p_block_in->p_buffer[13],
712                          p_block_in->p_buffer[14], p_block_in->p_buffer[15]);
713 #endif
714                 /* set PCR before we send */
715                 if( p_block_in->i_pts > 0 )
716                     es_out_Control( p_demux->out, ES_OUT_SET_PCR,
717                                     p_block_in->i_pts );
718                 es_out_Send( p_demux->out, p_sys->p_audio, p_block_in );
719             }   /* if DTiVo */
720         }   /* if subrec == 0x03 */
721
722         /* SA Audio with no PES Header                      */
723         /* ================================================ */
724         if ( subrec_type == 0x04 )
725         {
726             /*msg_Dbg(p_demux,
727                     "Adding SA Audio Packet Size %ld", l_rec_size ); */
728
729             /* set PCR before we send */
730             if (p_sys->lastAudioPTS > 0)
731             {
732                 p_block_in->i_pts = p_sys->lastAudioPTS;
733                 es_out_Control( p_demux->out, ES_OUT_SET_PCR,
734                                 p_block_in->i_pts );
735             }
736             es_out_Send( p_demux->out, p_sys->p_audio, p_block_in );
737         }
738
739         /* DTiVo AC3 Audio Data with PES Header             */
740         /* ================================================ */
741         if ( subrec_type == 0x09 )
742         {
743             esOffset1 = find_es_header( ty_AC3AudioPacket,
744                     p_block_in->p_buffer, 5 );
745
746 #if 0
747             msg_Dbg(p_demux, "buffer has "
748                      "%02x %02x %02x %02x %02x %02x %02x %02x "
749                      "%02x %02x %02x %02x %02x %02x %02x %02x",
750                      p_block_in->p_buffer[0], p_block_in->p_buffer[1],
751                      p_block_in->p_buffer[2], p_block_in->p_buffer[3],
752                      p_block_in->p_buffer[4], p_block_in->p_buffer[5],
753                      p_block_in->p_buffer[6], p_block_in->p_buffer[7],
754                      p_block_in->p_buffer[8], p_block_in->p_buffer[9],
755                      p_block_in->p_buffer[10], p_block_in->p_buffer[11],
756                      p_block_in->p_buffer[12], p_block_in->p_buffer[13],
757                      p_block_in->p_buffer[14], p_block_in->p_buffer[15]);
758             msg_Dbg(p_demux, "audio ES AC3 hdr at offset %d", esOffset1);
759 #endif
760
761             /* Check for complete PES */
762             if (check_sync_pes(p_demux, p_block_in, esOffset1,
763                                 l_rec_size) == -1)
764             {
765                 /* partial PES header found, nothing else.  we're done. */
766                 p_sys->i_cur_rec++;
767                 return 1;
768             }
769             /* set PCR before we send (if PTS found) */
770             if( p_block_in->i_pts > 0 )
771             {
772                 es_out_Control( p_demux->out, ES_OUT_SET_PCR,
773                                 p_block_in->i_pts );
774             }
775             /* S2 DTivo has invalid long AC3 packets */
776             if (p_sys->tivo_series == TIVO_SERIES2) {
777                 if (p_block_in->i_buffer > AC3_PKT_LENGTH) {
778                     p_block_in->i_buffer -= 2;
779                     p_sys->l_ac3_pkt_size = 0;
780                 } else {
781                     p_sys->l_ac3_pkt_size = p_block_in->i_buffer;
782                 }
783             }
784             es_out_Send( p_demux->out, p_sys->p_audio, p_block_in );
785         }
786     } /* end "if audio" */
787     /* ================================================================ */
788     /* Closed Caption                                                   */
789     /* ================================================================ */
790     else if ( rec_type == 0x01 )
791     {
792         /*msg_Dbg(p_demux, "CC1 %02x %02x [%c%c]", rec_hdr->ex1,
793                    rec_hdr->ex2, rec_hdr->ex1, rec_hdr->ex2 );*/
794
795         /* construct a 'user-data' MPEG packet */
796         lastCC[ 0x00 ] = 0x00;
797         lastCC[ 0x01 ] = 0x00;
798         lastCC[ 0x02 ] = 0x01;
799         lastCC[ 0x03 ] = 0xb2;
800         lastCC[ 0x04 ] = 'T';    /* vcdimager code says this byte should be 0x11 */
801         lastCC[ 0x05 ] = 'Y';    /* (no other notes there) */
802         lastCC[ 0x06 ] = 0x01;
803         lastCC[ 0x07 ] = rec_hdr->ex1;
804         lastCC[ 0x08 ] = rec_hdr->ex2;
805         /* not sure what to send, because VLC doesn't yet support
806          * teletext type of subtitles (only supports the full-sentence type) */
807         /*p_block_in = block_NewEmpty(); ????
808         es_out_Send( p_demux->out, p_sys->p_subt_es, p_block_in );*/
809     }
810     else if ( rec_type == 0x02 )
811     {
812         /*msg_Dbg(p_demux, "CC2 %02x %02x", rec_hdr->ex1, rec_hdr->ex2 );*/
813
814         /* construct a 'user-data' MPEG packet */
815         lastXDS[ 0x00 ] = 0x00;
816         lastXDS[ 0x01 ] = 0x00;
817         lastXDS[ 0x02 ] = 0x01;
818         lastXDS[ 0x03 ] = 0xb2;
819         lastXDS[ 0x04 ] = 'T';    /* vcdimager code says this byte should be 0x11 */
820         lastXDS[ 0x05 ] = 'Y';    /* (no other notes there) */
821         lastXDS[ 0x06 ] = 0x02;
822         lastXDS[ 0x07 ] = rec_hdr->ex1;
823         lastXDS[ 0x08 ] = rec_hdr->ex2;
824         /* not sure what to send, because VLC doesn't support this?? */
825         /*p_block_in = block_NewEmpty(); ????
826         es_out_Send( p_demux->out, p_sys->p_audio, p_block_in );*/
827     }
828     /* ================================================================ */
829     /* Tivo data services (e.g. "thumbs-up to record!")  useless for us */
830     /* ================================================================ */
831     else if ( rec_type == 0x03 )
832     {
833     }
834     /* ================================================================ */
835     /* Unknown, but seen regularly */
836     /* ================================================================ */
837     else if ( rec_type == 0x05 )
838     {
839     }
840     else
841     {
842         msg_Dbg(p_demux, "Invalid record type 0x%02x", rec_type );
843         if (p_block_in) block_Release(p_block_in);
844             invalidType++;
845     }
846     p_sys->i_cur_rec++;
847     return 1;
848 }
849
850
851 /* seek to a position within the stream, if possible */
852 static int ty_stream_seek_pct(demux_t *p_demux, double seek_pct)
853 {
854     demux_sys_t *p_sys = p_demux->p_sys;
855     int64_t seek_pos = p_sys->i_stream_size * seek_pct;
856     int i, i_cur_part;
857     long l_skip_amt;
858
859     /* if we're not seekable, there's nothing to do */
860     if (!p_sys->b_seekable)
861         return VLC_EGENERIC;
862
863     /* figure out which part & chunk we want & go there */
864     i_cur_part = seek_pos / TIVO_PART_LENGTH;
865     p_sys->i_cur_chunk = seek_pos / CHUNK_SIZE;
866     
867     /* try to read the part header (master chunk) if it's there */
868     if ( stream_Seek( p_demux->s, i_cur_part * TIVO_PART_LENGTH ))
869     {
870         /* can't seek stream */
871         return VLC_EGENERIC;
872     }
873     parse_master(p_demux);
874
875     /* now for the actual chunk */
876     if ( stream_Seek( p_demux->s, p_sys->i_cur_chunk * CHUNK_SIZE))
877     {
878         /* can't seek stream */
879         return VLC_EGENERIC;
880     }
881     /* load the chunk */
882     p_sys->i_stuff_cnt = 0;
883     get_chunk_header(p_demux);
884   
885     /* seek within the chunk to get roughly to where we want */
886     p_sys->i_cur_rec = (int)
887       ((double) ((seek_pos % CHUNK_SIZE) / (double) (CHUNK_SIZE)) * p_sys->i_num_recs);
888     msg_Dbg(p_demux, "Seeked to file pos " I64Fd, seek_pos);
889     msg_Dbg(p_demux, " (chunk %d, record %d)",
890              p_sys->i_cur_chunk - 1, p_sys->i_cur_rec);
891
892     /* seek to the start of this record's data.
893      * to do that, we have to skip past all prior records */
894     l_skip_amt = 0;
895     for (i=0; i<p_sys->i_cur_rec; i++)
896         l_skip_amt += p_sys->rec_hdrs[i].l_rec_size;
897     stream_Seek(p_demux->s, ((p_sys->i_cur_chunk-1) * CHUNK_SIZE) +
898                  (p_sys->i_num_recs * 16) + l_skip_amt + 4);
899
900     /* to hell with syncing any audio or video, just start reading records... :) */
901     /*p_sys->lastAudioPTS = p_sys->lastVideoPTS = 0;*/
902     es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
903     return VLC_SUCCESS;
904 }
905
906
907 /* seek to an exact time position within the stream, if possible.
908  * l_seek_time is in nanoseconds, the TIVO time standard.
909  */
910 static int ty_stream_seek_time(demux_t *p_demux, uint64_t l_seek_time)
911 {
912     demux_sys_t *p_sys = p_demux->p_sys;
913     int i, i_seq_entry = 0;
914     int i_skip_cnt;
915     long l_cur_pos = stream_Tell(p_demux->s);
916     int i_cur_part = l_cur_pos / TIVO_PART_LENGTH;
917     long l_seek_secs = l_seek_time / 1000000000;
918     uint64_t l_fwd_stamp = 1;
919
920     /* if we're not seekable, there's nothing to do */
921     if (!p_sys->b_seekable || !p_sys->b_have_master)
922         return VLC_EGENERIC;
923
924     msg_Dbg(p_demux, "Skipping to time %02ld:%02ld:%02ld",
925             l_seek_secs / 3600, (l_seek_secs / 60) % 60, l_seek_secs % 60);
926
927     /* seek to the proper segment if necessary */
928     /* first see if we need to go back */
929     while (l_seek_time < p_sys->l_first_ty_pts) {
930         msg_Dbg(p_demux, "skipping to prior segment.");
931         /* load previous part */
932         if (i_cur_part == 0) {
933             stream_Seek(p_demux->s, l_cur_pos);
934             msg_Err(p_demux, "Attempt to seek past BOF");
935             return VLC_EGENERIC;
936         }
937         stream_Seek(p_demux->s, (i_cur_part - 1) * TIVO_PART_LENGTH);
938         i_cur_part--;
939         parse_master(p_demux);
940     }
941     /* maybe we need to go forward */
942     while (l_seek_time > p_sys->l_final_ty_pts) {
943         msg_Dbg(p_demux, "skipping to next segment.");
944         /* load next part */
945         if ((i_cur_part + 1) * TIVO_PART_LENGTH > p_sys->i_stream_size) {
946             /* error; restore previous file position */
947             stream_Seek(p_demux->s, l_cur_pos);
948             msg_Err(p_demux, "seek error");
949             return VLC_EGENERIC;
950         }
951         stream_Seek(p_demux->s, (i_cur_part + 1) * TIVO_PART_LENGTH);
952         i_cur_part++;
953         parse_master(p_demux);
954     }
955
956     /* our target is somewhere within this part;
957        find the proper chunk using seq_table */
958     for (i=1; i<p_sys->i_seq_table_size; i++) {
959         if (p_sys->seq_table[i].l_timestamp > l_seek_time) {
960             /* i-1 is the section we want; remember the next timestamp in case
961                we have to use it (this section may not have a proper SEQ hdr
962                for the time we're seeking) */
963             msg_Dbg(p_demux, "stopping at seq entry %d.", i);
964             l_fwd_stamp = p_sys->seq_table[i].l_timestamp;
965             i_seq_entry = i-1;
966             break;
967         }
968     }
969     
970     /* if we went through the entire last loop and didn't find our target,
971        then we skip to the next part.  What has happened is that the actual
972        time we're seeking is within this part, but there isn't a SEQ hdr
973        for it here.  So we skip to the next part */
974     if (i == p_sys->i_seq_table_size) {
975         if ((i_cur_part + 1) * TIVO_PART_LENGTH > p_sys->i_stream_size) {
976             /* error; restore previous file position */
977             stream_Seek(p_demux->s, l_cur_pos);
978             msg_Err(p_demux, "seek error");
979             return VLC_EGENERIC;
980         }
981         stream_Seek(p_demux->s, (i_cur_part + 1) * TIVO_PART_LENGTH);
982         i_cur_part++;
983         parse_master(p_demux);
984         i_seq_entry = 0;
985     }     
986      
987     /* determine which chunk has our seek_time */
988     for (i=0; i<p_sys->i_bits_per_seq_entry; i++) {
989         long l_chunk_nr = i_seq_entry * p_sys->i_bits_per_seq_entry + i;
990         long l_chunk_offset = (l_chunk_nr + 1) * CHUNK_SIZE;
991         msg_Dbg(p_demux, "testing part %d chunk %ld mask 0x%02X bit %d",
992             i_cur_part, l_chunk_nr,
993             p_sys->seq_table[i_seq_entry].chunk_bitmask[i/8], i%8);
994         if (p_sys->seq_table[i_seq_entry].chunk_bitmask[i/8] & (1 << (i%8))) {
995             /* check this chunk's SEQ header timestamp */
996             msg_Dbg(p_demux, "has SEQ. seeking to chunk at 0x%lX",
997                 (i_cur_part * TIVO_PART_LENGTH) + l_chunk_offset);
998             stream_Seek(p_demux->s, (i_cur_part * TIVO_PART_LENGTH) +
999                 l_chunk_offset);
1000             // TODO: we don't have to parse the full header set;
1001             // just test the seq_rec entry for its timestamp
1002             p_sys->i_stuff_cnt = 0;
1003             get_chunk_header(p_demux);
1004             // check ty PTS for the SEQ entry in this chunk
1005             if (p_sys->i_seq_rec < 0 || p_sys->i_seq_rec > p_sys->i_num_recs) {
1006                 msg_Err(p_demux, "no SEQ hdr in chunk; table had one.");
1007                 /* Seek to beginning of original chunk & reload it */
1008                 stream_Seek(p_demux->s, (l_cur_pos / CHUNK_SIZE) * CHUNK_SIZE);
1009                 p_sys->i_stuff_cnt = 0;
1010                 get_chunk_header(p_demux);
1011                 return VLC_EGENERIC;
1012             }
1013             l_seek_secs = p_sys->rec_hdrs[p_sys->i_seq_rec].l_ty_pts /
1014                 1000000000;
1015             msg_Dbg(p_demux, "found SEQ hdr for timestamp %02ld:%02ld:%02ld",
1016                 l_seek_secs / 3600,
1017                 (l_seek_secs / 60) % 60, l_seek_secs % 60);
1018             if (p_sys->rec_hdrs[p_sys->i_seq_rec].l_ty_pts >= l_seek_time) {
1019                 // keep this one?  go back?
1020                 /* for now, we take this one.  it's the first SEQ hdr AFTER
1021                    the time we were searching for. */
1022                 msg_Dbg(p_demux, "seek target found.");
1023                 break;
1024             }
1025             msg_Dbg(p_demux, "timestamp too early. still scanning.");
1026         }
1027     }
1028     /* if we made it through this entire loop without finding our target,
1029        then we skip to the next section.  What has happened is that the actual
1030        time we're seeking is within this section, but there isn't a SEQ hdr
1031        for it here.  So we skip to the next closest one (l_fwd_stamp) */
1032     if (i == p_sys->i_bits_per_seq_entry)
1033         return ty_stream_seek_time(p_demux, l_fwd_stamp);
1034
1035     /* current stream ptr is at beginning of data for this chunk,
1036        so we need to skip past any stream data prior to the seq_rec
1037        in this chunk */
1038     i_skip_cnt = 0;
1039     for (i=0; i<p_sys->i_seq_rec; i++)
1040         i_skip_cnt += p_sys->rec_hdrs[i].l_rec_size;
1041     stream_Read(p_demux->s, NULL, i_skip_cnt);
1042     p_sys->i_cur_rec = p_sys->i_seq_rec;
1043     //p_sys->l_last_ty_pts = p_sys->rec_hdrs[p_sys->i_seq_rec].l_ty_pts;
1044     //p_sys->l_last_ty_pts_sync = p_sys->lastAudioPTS;
1045
1046     return VLC_SUCCESS;
1047 }
1048
1049
1050 /* parse a master chunk, filling the SEQ table and other variables.
1051  * We assume the stream is currently pointing to it.
1052  */
1053 static void parse_master(demux_t *p_demux)
1054 {
1055     demux_sys_t *p_sys = p_demux->p_sys;
1056     uint8_t mst_buf[32];
1057     int i, i_map_size;
1058     int64_t i_save_pos = stream_Tell(p_demux->s);
1059     int64_t i_pts_secs;
1060
1061     /* Note that the entries in the SEQ table in the stream may have
1062        different sizes depending on the bits per entry.  We store them
1063        all in the same size structure, so we have to parse them out one
1064        by one.  If we had a dynamic structure, we could simply read the
1065        entire table directly from the stream into memory in place. */
1066
1067     /* clear the SEQ table */
1068     if (p_sys->seq_table != NULL)
1069         free(p_sys->seq_table);
1070     
1071     /* parse header info */
1072     stream_Read(p_demux->s, mst_buf, 32);
1073     i_map_size = U32_AT(&mst_buf[20]);  /* size of bitmask, in bytes */
1074     p_sys->i_bits_per_seq_entry = i_map_size * 8;
1075     i = U32_AT(&mst_buf[28]);   /* size of SEQ table, in bytes */
1076     p_sys->i_seq_table_size = i / (8 + i_map_size);
1077
1078     /* parse all the entries */
1079     p_sys->seq_table = malloc(p_sys->i_seq_table_size * sizeof(ty_seq_table_t));
1080     for (i=0; i<p_sys->i_seq_table_size; i++) {
1081         stream_Read(p_demux->s, mst_buf, 8 + i_map_size);
1082         p_sys->seq_table[i].l_timestamp = U64_AT(&mst_buf[0]);
1083         if (i_map_size > 8) {
1084             msg_Err(p_demux, "Unsupported SEQ bitmap size in master chunk");
1085             memset(p_sys->seq_table[i].chunk_bitmask, i_map_size, 0);
1086         } else {
1087             memcpy(p_sys->seq_table[i].chunk_bitmask, &mst_buf[8], i_map_size);
1088         }
1089     }
1090
1091     /* set up a few of our variables */
1092     p_sys->l_first_ty_pts = p_sys->seq_table[0].l_timestamp;
1093     p_sys->l_final_ty_pts =
1094         p_sys->seq_table[p_sys->i_seq_table_size - 1].l_timestamp;
1095     p_sys->b_have_master = VLC_TRUE;
1096
1097     i_pts_secs = p_sys->l_first_ty_pts / 1000000000;
1098     msg_Dbg( p_demux, "first TY pts in master is %02d:%02d:%02d",
1099              (int)(i_pts_secs / 3600), (int)((i_pts_secs / 60) % 60), (int)(i_pts_secs % 60) );
1100     i_pts_secs = p_sys->l_final_ty_pts / 1000000000;
1101     msg_Dbg( p_demux, "final TY pts in master is %02d:%02d:%02d",
1102              (int)(i_pts_secs / 3600), (int)((i_pts_secs / 60) % 60), (int)(i_pts_secs % 60) );
1103
1104     /* seek past this chunk */
1105     stream_Seek(p_demux->s, i_save_pos + CHUNK_SIZE);
1106 }
1107
1108
1109 static int Control(demux_t *p_demux, int i_query, va_list args)
1110 {
1111     demux_sys_t *p_sys = p_demux->p_sys;
1112     double f, *pf;
1113     int64_t i64, *p_i64;
1114
1115     /*msg_Info(p_demux, "control cmd %d", i_query);*/
1116     switch( i_query )
1117     {
1118     case DEMUX_GET_POSITION:
1119         /* arg is 0.0 - 1.0 percent of overall file position */
1120         if( ( i64 = p_sys->i_stream_size ) > 0 )
1121         {
1122             pf = (double*) va_arg( args, double* );
1123             *pf = (double)stream_Tell( p_demux->s ) / (double) i64;
1124             return VLC_SUCCESS;
1125         }
1126         return VLC_EGENERIC;
1127
1128     case DEMUX_SET_POSITION:
1129         /* arg is 0.0 - 1.0 percent of overall file position */
1130         f = (double) va_arg( args, double );
1131         /* msg_Dbg(p_demux, "Control - set position to %2.3f", f); */
1132         if ((i64 = p_sys->i_stream_size) > 0)
1133             return ty_stream_seek_pct(p_demux, f);
1134         return VLC_EGENERIC;
1135     case DEMUX_GET_TIME:
1136         /* return TiVo timestamp */
1137         p_i64 = (int64_t *) va_arg(args, int64_t *);
1138         //*p_i64 = p_sys->lastAudioPTS - p_sys->firstAudioPTS;
1139         //*p_i64 = (p_sys->l_last_ty_pts / 1000) + (p_sys->lastAudioPTS -
1140         //    p_sys->l_last_ty_pts_sync);
1141         *p_i64 = (p_sys->l_last_ty_pts / 1000);
1142         return VLC_SUCCESS;
1143     case DEMUX_GET_LENGTH:    /* length of program in microseconds, 0 if unk */
1144         /* size / bitrate */
1145         p_i64 = (int64_t *) va_arg(args, int64_t *);
1146         *p_i64 = 0;
1147         return VLC_SUCCESS;
1148     case DEMUX_SET_TIME:      /* arg is time in microsecs */
1149         i64 = (int64_t) va_arg( args, int64_t );
1150         return ty_stream_seek_time(p_demux, i64 * 1000);
1151     case DEMUX_GET_FPS:
1152     default:
1153         return VLC_EGENERIC;
1154     }
1155 }
1156
1157
1158 /* ======================================================================== */
1159 static void Close( vlc_object_t *p_this )
1160 {
1161     demux_sys_t *p_sys = ((demux_t *) p_this)->p_sys;
1162
1163     free(p_sys->rec_hdrs);
1164     free(p_sys);
1165 }
1166
1167
1168 /* ======================================================================== */
1169 /* "Peek" at some chunks.  Skip over the Part header if we find it.
1170  * We parse the peeked data and determine audio type,
1171  * SA vs. DTivo, & Tivo Series.
1172  * Set global vars i_Pes_Length, i_Pts_Offset,
1173  * p_sys->tivo_series, p_sys->tivo_type, p_sys->audio_type */
1174 static int probe_stream(demux_t *p_demux)
1175 {
1176     demux_sys_t *p_sys = p_demux->p_sys;
1177     const uint8_t *p_buf;
1178     int i;
1179     vlc_bool_t b_probe_error = VLC_FALSE;
1180
1181     /* we need CHUNK_PEEK_COUNT chunks of data, first one might be a Part header, so ... */
1182     if (stream_Peek( p_demux->s, &p_buf, CHUNK_PEEK_COUNT * CHUNK_SIZE ) <
1183             CHUNK_PEEK_COUNT * CHUNK_SIZE) {
1184         msg_Err(p_demux, "Can't peek %d chunks", CHUNK_PEEK_COUNT);
1185         /* TODO: if seekable, then loop reading chunks into a temp buffer */
1186         return VLC_EGENERIC;
1187     }
1188     
1189     /* the real work: analyze this chunk */
1190     for (i = 0; i < CHUNK_PEEK_COUNT; i++) {
1191         analyze_chunk(p_demux, p_buf);
1192         if (p_sys->tivo_series != TIVO_SERIES_UNKNOWN &&
1193             p_sys->audio_type  != TIVO_AUDIO_UNKNOWN &&
1194             p_sys->tivo_type   != TIVO_TYPE_UNKNOWN)
1195             break;
1196         p_buf += CHUNK_SIZE;
1197     }
1198     
1199     /* the final tally */
1200     if (p_sys->tivo_series == TIVO_SERIES_UNKNOWN) {
1201         msg_Err(p_demux, "Can't determine Tivo Series.");
1202         b_probe_error = VLC_TRUE;
1203     }
1204     if (p_sys->audio_type == TIVO_AUDIO_UNKNOWN) {
1205         msg_Err(p_demux, "Can't determine Tivo Audio Type.");
1206         b_probe_error = VLC_TRUE;
1207     }
1208     if (p_sys->tivo_type == TIVO_TYPE_UNKNOWN) {
1209         msg_Err(p_demux, "Can't determine Tivo Type (SA/DTivo).");
1210         b_probe_error = VLC_TRUE;
1211     }
1212     return b_probe_error?VLC_EGENERIC:VLC_SUCCESS;
1213 }
1214
1215
1216 /* ======================================================================== */
1217 /* gather statistics for this chunk & set our tivo-type vars accordingly */
1218 static void analyze_chunk(demux_t *p_demux, const uint8_t *p_chunk)
1219 {
1220     demux_sys_t *p_sys = p_demux->p_sys;
1221     int i_num_recs, i;
1222     ty_rec_hdr_t *p_hdrs;
1223     int i_num_6e0, i_num_be0, i_num_9c0, i_num_3c0;
1224     uint32_t i_payload_size;
1225
1226     /* skip if it's a Part header */
1227     if( U32_AT( &p_chunk[ 0 ] ) == TIVO_PES_FILEID )
1228         return;
1229
1230     /* number of records in chunk (we ignore high order byte;
1231      * rarely are there > 256 chunks & we don't need that many anyway) */
1232     i_num_recs = p_chunk[0];
1233     if (i_num_recs < 5) {
1234         /* try again with the next chunk.  Sometimes there are dead ones */
1235         return;
1236     }
1237     
1238     p_chunk += 4;       /* skip past rec count & SEQ bytes */
1239     //msg_Dbg(p_demux, "probe: chunk has %d recs", i_num_recs);
1240     p_hdrs = parse_chunk_headers(p_demux, p_chunk, i_num_recs, &i_payload_size);
1241     /* scan headers.
1242      * 1. check video packets.  Presence of 0x6e0 means S1.
1243      *    No 6e0 but have be0 means S2.
1244      * 2. probe for audio 0x9c0 vs 0x3c0 (AC3 vs Mpeg)
1245      *    If AC-3, then we have DTivo.
1246      *    If MPEG, search for PTS offset.  This will determine SA vs. DTivo.
1247      */
1248     i_num_6e0 = i_num_be0 = i_num_9c0 = i_num_3c0 = 0;
1249     for (i=0; i<i_num_recs; i++) {
1250         //msg_Dbg(p_demux, "probe: rec is %d/%d = 0x%04x", p_hdrs[i].subrec_type,
1251             //p_hdrs[i].rec_type,
1252             //p_hdrs[i].subrec_type << 8 | p_hdrs[i].rec_type);
1253         switch (p_hdrs[i].subrec_type << 8 | p_hdrs[i].rec_type) {
1254             case 0x6e0:
1255                 i_num_6e0++;
1256                 break;
1257             case 0xbe0:
1258                 i_num_be0++;
1259                 break;
1260             case 0x3c0:
1261                 i_num_3c0++;
1262                 break;
1263             case 0x9c0:
1264                 i_num_9c0++;
1265                 break;
1266         }
1267     }
1268     msg_Dbg(p_demux, "probe: chunk has %d 0x6e0 recs, %d 0xbe0 recs.",
1269         i_num_6e0, i_num_be0);
1270
1271     /* set up our variables */
1272     if (i_num_6e0 > 0) {
1273         msg_Dbg(p_demux, "detected Series 1 Tivo");
1274         p_sys->tivo_series = TIVO_SERIES1;
1275         p_sys->i_Pes_Length = SERIES1_PES_LENGTH;
1276     } else if (i_num_be0 > 0) {
1277         msg_Dbg(p_demux, "detected Series 2 Tivo");
1278         p_sys->tivo_series = TIVO_SERIES2;
1279         p_sys->i_Pes_Length = SERIES2_PES_LENGTH;
1280     }
1281     if (i_num_9c0 > 0) {
1282         msg_Dbg(p_demux, "detected AC-3 Audio (DTivo)" );
1283         p_sys->audio_type = TIVO_AUDIO_AC3;
1284         p_sys->tivo_type = TIVO_TYPE_DTIVO;
1285         p_sys->i_Pts_Offset = AC3_PTS_OFFSET;
1286         p_sys->i_Pes_Length = AC3_PES_LENGTH;
1287     } else if (i_num_3c0 > 0) {
1288         p_sys->audio_type = TIVO_AUDIO_MPEG;
1289         msg_Dbg(p_demux, "detected MPEG Audio" );
1290     }
1291
1292     /* if tivo_type still unknown, we can check PTS location
1293      * in MPEG packets to determine tivo_type */
1294     if (p_sys->tivo_type == TIVO_TYPE_UNKNOWN) {
1295         uint32_t i_data_offset = (16 * i_num_recs);
1296         for (i=0; i<i_num_recs; i++) {
1297             if ((p_hdrs[i].subrec_type << 0x08 | p_hdrs[i].rec_type) == 0x3c0 &&
1298                     p_hdrs[i].l_rec_size > 15) {
1299                 /* first make sure we're aligned */
1300                 int i_pes_offset = find_es_header(ty_MPEGAudioPacket,
1301                         &p_chunk[i_data_offset], 5);
1302                 if (i_pes_offset >= 0) {
1303                     /* pes found. on SA, PES has hdr data at offset 6, not PTS. */
1304                     //msg_Dbg(p_demux, "probe: mpeg es header found in rec %d at offset %d",
1305                             //i, i_pes_offset);
1306                     if ((p_chunk[i_data_offset + 6 + i_pes_offset] & 0x80) == 0x80) {
1307                         /* S1SA or S2(any) Mpeg Audio (PES hdr, not a PTS start) */
1308                         if (p_sys->tivo_series == TIVO_SERIES1)
1309                             msg_Dbg(p_demux, "detected Stand-Alone Tivo" );
1310                         p_sys->tivo_type = TIVO_TYPE_SA;
1311                         p_sys->i_Pts_Offset = SA_PTS_OFFSET;
1312                     } else {
1313                         if (p_sys->tivo_series == TIVO_SERIES1)
1314                             msg_Dbg(p_demux, "detected DirecTV Tivo" );
1315                         p_sys->tivo_type = TIVO_TYPE_DTIVO;
1316                         p_sys->i_Pts_Offset = DTIVO_PTS_OFFSET;
1317                     }
1318                     break;
1319                 }
1320             }
1321             i_data_offset += p_hdrs[i].l_rec_size;
1322         }
1323     }
1324     free(p_hdrs);
1325 }
1326
1327
1328 /* =========================================================================== */
1329 static int get_chunk_header(demux_t *p_demux)
1330 {
1331     int i_readSize, i_num_recs;
1332     uint8_t *p_hdr_buf;
1333     const uint8_t *p_peek;
1334     demux_sys_t *p_sys = p_demux->p_sys;
1335     int i_payload_size;             /* sum of all records' sizes */
1336
1337     msg_Dbg(p_demux, "parsing ty chunk #%d", p_sys->i_cur_chunk );
1338
1339     /* if we have left-over filler space from the last chunk, get that */
1340     if (p_sys->i_stuff_cnt > 0) {
1341         stream_Read( p_demux->s, NULL, p_sys->i_stuff_cnt);
1342         p_sys->i_stuff_cnt = 0;
1343     }
1344
1345     /* read the TY packet header */
1346     i_readSize = stream_Peek( p_demux->s, &p_peek, 4 );
1347     p_sys->i_cur_chunk++;
1348   
1349     if ( (i_readSize < 4) || ( U32_AT(&p_peek[ 0 ] ) == 0 ))
1350     {
1351         /* EOF */
1352         p_sys->eof = 1;
1353         return 0;
1354     }
1355   
1356     /* check if it's a PART Header */
1357     if( U32_AT( &p_peek[ 0 ] ) == TIVO_PES_FILEID )
1358     {
1359         /* parse master chunk */
1360         parse_master(p_demux);
1361         return get_chunk_header(p_demux);
1362     }
1363     
1364     /* number of records in chunk (8- or 16-bit number) */
1365     if (p_peek[3] & 0x80)
1366     {
1367         /* 16 bit rec cnt */
1368         p_sys->i_num_recs = i_num_recs = (p_peek[1] << 8) + p_peek[0];
1369         p_sys->i_seq_rec = (p_peek[3] << 8) + p_peek[2];
1370         if (p_sys->i_seq_rec != 0xffff)
1371         {
1372             p_sys->i_seq_rec &= ~0x8000;
1373         }
1374     }
1375     else
1376     {
1377         /* 8 bit reclen - tivo 1.3 format */
1378         p_sys->i_num_recs = i_num_recs = p_peek[0];
1379         p_sys->i_seq_rec = p_peek[1];
1380     }
1381     p_sys->i_cur_rec = 0;
1382     p_sys->b_first_chunk = VLC_FALSE;
1383   
1384     /*msg_Dbg( p_demux, "chunk has %d records", i_num_recs );*/
1385
1386     if (p_sys->rec_hdrs)
1387         free(p_sys->rec_hdrs);
1388
1389     /* skip past the 4 bytes we "peeked" earlier */
1390     stream_Read( p_demux->s, NULL, 4 );
1391
1392     /* read the record headers into a temp buffer */
1393     p_hdr_buf = malloc(i_num_recs * 16);
1394     if (stream_Read(p_demux->s, p_hdr_buf, i_num_recs * 16) < i_num_recs * 16) {
1395         p_sys->eof = VLC_TRUE;
1396         return 0;
1397     }
1398     /* parse them */
1399     p_sys->rec_hdrs = parse_chunk_headers(p_demux, p_hdr_buf, i_num_recs,
1400             &i_payload_size);
1401     free(p_hdr_buf);
1402
1403     p_sys->i_stuff_cnt = CHUNK_SIZE - 4 -
1404         (p_sys->i_num_recs * 16) - i_payload_size;
1405     if (p_sys->i_stuff_cnt > 0)
1406         msg_Dbg( p_demux, "chunk has %d stuff bytes at end",
1407                  p_sys->i_stuff_cnt );
1408     return 1;
1409 }
1410
1411
1412 static ty_rec_hdr_t *parse_chunk_headers( demux_t *p_demux, const uint8_t *p_buf,
1413                                           int i_num_recs, int *pi_payload_size)
1414 {
1415     int i;
1416     ty_rec_hdr_t *p_hdrs, *p_rec_hdr;
1417
1418     *pi_payload_size = 0;
1419     p_hdrs = malloc(i_num_recs * sizeof(ty_rec_hdr_t));
1420
1421     for (i = 0; i < i_num_recs; i++)
1422     {
1423         const uint8_t *record_header = p_buf + (i * 16);
1424         p_rec_hdr = &p_hdrs[i];     /* for brevity */
1425         p_rec_hdr->rec_type = record_header[3];
1426         p_rec_hdr->subrec_type = record_header[2] & 0x0f;
1427         if ((record_header[ 0 ] & 0x80) == 0x80)
1428         {
1429             uint8_t b1, b2;
1430             /* marker bit 2 set, so read extended data */
1431             b1 = ( ( ( record_header[ 0 ] & 0x0f ) << 4 ) | 
1432                    ( ( record_header[ 1 ] & 0xf0 ) >> 4 ) );
1433             b1 &= 0x7f;
1434             b2 = ( ( ( record_header[ 1 ] & 0x0f ) << 4 ) | 
1435                    ( ( record_header[ 2 ] & 0xf0 ) >> 4 ) );
1436             b2 &= 0x7f;
1437
1438             p_rec_hdr->ex1 = b1;
1439             p_rec_hdr->ex2 = b2;
1440             p_rec_hdr->l_rec_size = 0;
1441             p_rec_hdr->l_ty_pts = 0;
1442             p_rec_hdr->b_ext = VLC_TRUE;
1443         }
1444         else
1445         {
1446             p_rec_hdr->l_rec_size = ( record_header[ 0 ] << 8 |
1447                 record_header[ 1 ] ) << 4 | ( record_header[ 2 ] >> 4 );
1448             *pi_payload_size += p_rec_hdr->l_rec_size;
1449             p_rec_hdr->b_ext = VLC_FALSE;
1450             p_rec_hdr->l_ty_pts = U64_AT( &record_header[ 8 ] );
1451         }
1452     } /* end of record-header loop */
1453     return p_hdrs;
1454 }