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