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