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