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