]> git.sesse.net Git - ffmpeg/blob - libavformat/ty.c
avcodec/dvbsubdec: prefer to use variable instead of type for sizeof
[ffmpeg] / libavformat / ty.c
1 /*
2  * TiVo ty stream demuxer
3  * Copyright (c) 2005 VLC authors and VideoLAN
4  * Copyright (c) 2005 by Neal Symms (tivo@freakinzoo.com) - February 2005
5  * based on code by Christopher Wingert for tivo-mplayer
6  * tivo(at)wingert.org, February 2003
7  * Copyright (c) 2017 Paul B Mahol
8  *
9  * This file is part of FFmpeg.
10  *
11  * FFmpeg is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation; either
14  * version 2.1 of the License, or (at your option) any later version.
15  *
16  * FFmpeg 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 GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with FFmpeg; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24  */
25
26 #include "libavutil/intreadwrite.h"
27 #include "avformat.h"
28 #include "internal.h"
29 #include "mpeg.h"
30
31 #define SERIES1_PES_LENGTH  11    /* length of audio PES hdr on S1 */
32 #define SERIES2_PES_LENGTH  16    /* length of audio PES hdr on S2 */
33 #define AC3_PES_LENGTH      14    /* length of audio PES hdr for AC3 */
34 #define VIDEO_PES_LENGTH    16    /* length of video PES header */
35 #define DTIVO_PTS_OFFSET    6     /* offs into PES for MPEG PTS on DTivo */
36 #define SA_PTS_OFFSET       9     /* offset into PES for MPEG PTS on SA */
37 #define AC3_PTS_OFFSET      9     /* offset into PES for AC3 PTS on DTivo */
38 #define VIDEO_PTS_OFFSET    9     /* offset into PES for video PTS on all */
39 #define AC3_PKT_LENGTH      1536  /* size of TiVo AC3 pkts (w/o PES hdr) */
40
41 static const uint8_t ty_VideoPacket[]     = { 0x00, 0x00, 0x01, 0xe0 };
42 static const uint8_t ty_MPEGAudioPacket[] = { 0x00, 0x00, 0x01, 0xc0 };
43 static const uint8_t ty_AC3AudioPacket[]  = { 0x00, 0x00, 0x01, 0xbd };
44
45 #define TIVO_PES_FILEID   0xf5467abd
46 #define CHUNK_SIZE        (128 * 1024)
47 #define CHUNK_PEEK_COUNT  3      /* number of chunks to probe */
48
49 typedef struct TyRecHdr {
50     int64_t   rec_size;
51     uint8_t   ex[2];
52     uint8_t   rec_type;
53     uint8_t   subrec_type;
54     uint64_t  ty_pts;            /* TY PTS in the record header */
55 } TyRecHdr;
56
57 typedef enum {
58     TIVO_TYPE_UNKNOWN,
59     TIVO_TYPE_SA,
60     TIVO_TYPE_DTIVO
61 } TiVo_type;
62
63 typedef enum {
64     TIVO_SERIES_UNKNOWN,
65     TIVO_SERIES1,
66     TIVO_SERIES2
67 } TiVo_series;
68
69 typedef enum {
70     TIVO_AUDIO_UNKNOWN,
71     TIVO_AUDIO_AC3,
72     TIVO_AUDIO_MPEG
73 } TiVo_audio;
74
75 typedef struct TySeqTable {
76     uint64_t    timestamp;
77     uint8_t     chunk_bitmask[8];
78 } TySeqTable;
79
80 typedef struct TYDemuxContext {
81     unsigned        cur_chunk;
82     unsigned        cur_chunk_pos;
83     int64_t         cur_pos;
84     TiVo_type       tivo_type;        /* TiVo type (SA / DTiVo) */
85     TiVo_series     tivo_series;      /* Series1 or Series2 */
86     TiVo_audio      audio_type;       /* AC3 or MPEG */
87     int             pes_length;       /* Length of Audio PES header */
88     int             pts_offset;       /* offset into audio PES of PTS */
89     uint8_t         pes_buffer[20];   /* holds incomplete pes headers */
90     int             pes_buf_cnt;      /* how many bytes in our buffer */
91     size_t          ac3_pkt_size;     /* length of ac3 pkt we've seen so far */
92     uint64_t        last_ty_pts;      /* last TY timestamp we've seen */
93     unsigned        seq_table_size;   /* number of entries in SEQ table */
94
95     int64_t         first_audio_pts;
96     int64_t         last_audio_pts;
97     int64_t         last_video_pts;
98
99     TyRecHdr       *rec_hdrs;         /* record headers array */
100     int             cur_rec;          /* current record in this chunk */
101     int             num_recs;         /* number of recs in this chunk */
102     int             seq_rec;          /* record number where seq start is */
103     TySeqTable     *seq_table;        /* table of SEQ entries from mstr chk */
104     int             first_chunk;
105
106     uint8_t         chunk[CHUNK_SIZE];
107 } TYDemuxContext;
108
109 static int ty_probe(const AVProbeData *p)
110 {
111     int i;
112
113     for (i = 0; i + 12 < p->buf_size; i += CHUNK_SIZE) {
114         if (AV_RB32(p->buf + i) == TIVO_PES_FILEID &&
115             AV_RB32(p->buf + i + 4) == 0x02 &&
116             AV_RB32(p->buf + i + 8) == CHUNK_SIZE) {
117             return AVPROBE_SCORE_MAX;
118         }
119     }
120
121     return 0;
122 }
123
124 static TyRecHdr *parse_chunk_headers(const uint8_t *buf,
125                                      int num_recs)
126 {
127     TyRecHdr *hdrs, *rec_hdr;
128     int i;
129
130     hdrs = av_calloc(num_recs, sizeof(TyRecHdr));
131     if (!hdrs)
132         return NULL;
133
134     for (i = 0; i < num_recs; i++) {
135         const uint8_t *record_header = buf + (i * 16);
136
137         rec_hdr = &hdrs[i];     /* for brevity */
138         rec_hdr->rec_type = record_header[3];
139         rec_hdr->subrec_type = record_header[2] & 0x0f;
140         if ((record_header[0] & 0x80) == 0x80) {
141             uint8_t b1, b2;
142
143             /* marker bit 2 set, so read extended data */
144             b1 = (((record_header[0] & 0x0f) << 4) |
145                   ((record_header[1] & 0xf0) >> 4));
146             b2 = (((record_header[1] & 0x0f) << 4) |
147                   ((record_header[2] & 0xf0) >> 4));
148
149             rec_hdr->ex[0] = b1;
150             rec_hdr->ex[1] = b2;
151             rec_hdr->rec_size = 0;
152             rec_hdr->ty_pts = 0;
153         } else {
154             rec_hdr->rec_size = (record_header[0] << 8 |
155                                  record_header[1]) << 4 |
156                                 (record_header[2] >> 4);
157             rec_hdr->ty_pts = AV_RB64(&record_header[8]);
158         }
159     }
160     return hdrs;
161 }
162
163 static int find_es_header(const uint8_t *header,
164                           const uint8_t *buffer, int search_len)
165 {
166     int count;
167
168     for (count = 0; count < search_len; count++) {
169         if (!memcmp(&buffer[count], header, 4))
170             return count;
171     }
172     return -1;
173 }
174
175 static int analyze_chunk(AVFormatContext *s, const uint8_t *chunk)
176 {
177     TYDemuxContext *ty = s->priv_data;
178     int num_recs, i;
179     TyRecHdr *hdrs;
180     int num_6e0, num_be0, num_9c0, num_3c0;
181
182     /* skip if it's a Part header */
183     if (AV_RB32(&chunk[0]) == TIVO_PES_FILEID)
184         return 0;
185
186     /* number of records in chunk (we ignore high order byte;
187      * rarely are there > 256 chunks & we don't need that many anyway) */
188     num_recs = chunk[0];
189     if (num_recs < 5) {
190         /* try again with the next chunk.  Sometimes there are dead ones */
191         return 0;
192     }
193
194     chunk += 4;       /* skip past rec count & SEQ bytes */
195     ff_dlog(s, "probe: chunk has %d recs\n", num_recs);
196     hdrs = parse_chunk_headers(chunk, num_recs);
197     if (!hdrs)
198         return AVERROR(ENOMEM);
199
200     /* scan headers.
201      * 1. check video packets.  Presence of 0x6e0 means S1.
202      *    No 6e0 but have be0 means S2.
203      * 2. probe for audio 0x9c0 vs 0x3c0 (AC3 vs Mpeg)
204      *    If AC-3, then we have DTivo.
205      *    If MPEG, search for PTS offset.  This will determine SA vs. DTivo.
206      */
207     num_6e0 = num_be0 = num_9c0 = num_3c0 = 0;
208     for (i = 0; i < num_recs; i++) {
209         switch (hdrs[i].subrec_type << 8 | hdrs[i].rec_type) {
210         case 0x6e0:
211             num_6e0++;
212             break;
213         case 0xbe0:
214             num_be0++;
215             break;
216         case 0x3c0:
217             num_3c0++;
218             break;
219         case 0x9c0:
220             num_9c0++;
221             break;
222         }
223     }
224     ff_dlog(s, "probe: chunk has %d 0x6e0 recs, %d 0xbe0 recs.\n",
225             num_6e0, num_be0);
226
227     /* set up our variables */
228     if (num_6e0 > 0) {
229         ff_dlog(s, "detected Series 1 Tivo\n");
230         ty->tivo_series = TIVO_SERIES1;
231         ty->pes_length = SERIES1_PES_LENGTH;
232     } else if (num_be0 > 0) {
233         ff_dlog(s, "detected Series 2 Tivo\n");
234         ty->tivo_series = TIVO_SERIES2;
235         ty->pes_length = SERIES2_PES_LENGTH;
236     }
237     if (num_9c0 > 0) {
238         ff_dlog(s, "detected AC-3 Audio (DTivo)\n");
239         ty->audio_type = TIVO_AUDIO_AC3;
240         ty->tivo_type = TIVO_TYPE_DTIVO;
241         ty->pts_offset = AC3_PTS_OFFSET;
242         ty->pes_length = AC3_PES_LENGTH;
243     } else if (num_3c0 > 0) {
244         ty->audio_type = TIVO_AUDIO_MPEG;
245         ff_dlog(s, "detected MPEG Audio\n");
246     }
247
248     /* if tivo_type still unknown, we can check PTS location
249      * in MPEG packets to determine tivo_type */
250     if (ty->tivo_type == TIVO_TYPE_UNKNOWN) {
251         uint32_t data_offset = 16 * num_recs;
252
253         for (i = 0; i < num_recs; i++) {
254             if (data_offset + hdrs[i].rec_size > CHUNK_SIZE)
255                 break;
256
257             if ((hdrs[i].subrec_type << 8 | hdrs[i].rec_type) == 0x3c0 && hdrs[i].rec_size > 15) {
258                 /* first make sure we're aligned */
259                 int pes_offset = find_es_header(ty_MPEGAudioPacket,
260                         &chunk[data_offset], 5);
261                 if (pes_offset >= 0) {
262                     /* pes found. on SA, PES has hdr data at offset 6, not PTS. */
263                     if ((chunk[data_offset + 6 + pes_offset] & 0x80) == 0x80) {
264                         /* S1SA or S2(any) Mpeg Audio (PES hdr, not a PTS start) */
265                         if (ty->tivo_series == TIVO_SERIES1)
266                             ff_dlog(s, "detected Stand-Alone Tivo\n");
267                         ty->tivo_type = TIVO_TYPE_SA;
268                         ty->pts_offset = SA_PTS_OFFSET;
269                     } else {
270                         if (ty->tivo_series == TIVO_SERIES1)
271                             ff_dlog(s, "detected DirecTV Tivo\n");
272                         ty->tivo_type = TIVO_TYPE_DTIVO;
273                         ty->pts_offset = DTIVO_PTS_OFFSET;
274                     }
275                     break;
276                 }
277             }
278             data_offset += hdrs[i].rec_size;
279         }
280     }
281     av_free(hdrs);
282
283     return 0;
284 }
285
286 static int ty_read_header(AVFormatContext *s)
287 {
288     TYDemuxContext *ty = s->priv_data;
289     AVIOContext *pb = s->pb;
290     AVStream *st, *ast;
291     int i, ret = 0;
292
293     ty->first_audio_pts = AV_NOPTS_VALUE;
294     ty->last_audio_pts = AV_NOPTS_VALUE;
295     ty->last_video_pts = AV_NOPTS_VALUE;
296
297     for (i = 0; i < CHUNK_PEEK_COUNT; i++) {
298         avio_read(pb, ty->chunk, CHUNK_SIZE);
299
300         ret = analyze_chunk(s, ty->chunk);
301         if (ret < 0)
302             return ret;
303         if (ty->tivo_series != TIVO_SERIES_UNKNOWN &&
304             ty->audio_type  != TIVO_AUDIO_UNKNOWN &&
305             ty->tivo_type   != TIVO_TYPE_UNKNOWN)
306             break;
307     }
308
309     if (ty->tivo_series == TIVO_SERIES_UNKNOWN ||
310         ty->audio_type == TIVO_AUDIO_UNKNOWN ||
311         ty->tivo_type == TIVO_TYPE_UNKNOWN)
312         return AVERROR(EIO);
313
314     st = avformat_new_stream(s, NULL);
315     if (!st)
316         return AVERROR(ENOMEM);
317     st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
318     st->codecpar->codec_id   = AV_CODEC_ID_MPEG2VIDEO;
319     st->need_parsing         = AVSTREAM_PARSE_FULL_RAW;
320     avpriv_set_pts_info(st, 64, 1, 90000);
321
322     ast = avformat_new_stream(s, NULL);
323     if (!ast)
324         return AVERROR(ENOMEM);
325     ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
326
327     if (ty->audio_type == TIVO_AUDIO_MPEG) {
328         ast->codecpar->codec_id = AV_CODEC_ID_MP2;
329         ast->need_parsing       = AVSTREAM_PARSE_FULL_RAW;
330     } else {
331         ast->codecpar->codec_id = AV_CODEC_ID_AC3;
332     }
333     avpriv_set_pts_info(ast, 64, 1, 90000);
334
335     ty->first_chunk = 1;
336
337     avio_seek(pb, 0, SEEK_SET);
338
339     return 0;
340 }
341
342 /* parse a master chunk, filling the SEQ table and other variables.
343  * We assume the stream is currently pointing to it.
344  */
345 static void parse_master(AVFormatContext *s)
346 {
347     TYDemuxContext *ty = s->priv_data;
348     unsigned map_size;  /* size of bitmask, in bytes */
349     unsigned i, j;
350
351     /* Note that the entries in the SEQ table in the stream may have
352        different sizes depending on the bits per entry.  We store them
353        all in the same size structure, so we have to parse them out one
354        by one.  If we had a dynamic structure, we could simply read the
355        entire table directly from the stream into memory in place. */
356
357     /* clear the SEQ table */
358     av_freep(&ty->seq_table);
359
360     /* parse header info */
361
362     map_size = AV_RB32(ty->chunk + 20);  /* size of bitmask, in bytes */
363     i = AV_RB32(ty->chunk + 28);   /* size of SEQ table, in bytes */
364
365     ty->seq_table_size = i / (8LL + map_size);
366
367     if (ty->seq_table_size == 0) {
368         ty->seq_table = NULL;
369         return;
370     }
371
372     /* parse all the entries */
373     ty->seq_table = av_calloc(ty->seq_table_size, sizeof(TySeqTable));
374     if (ty->seq_table == NULL) {
375         ty->seq_table_size = 0;
376         return;
377     }
378
379     ty->cur_chunk_pos = 32;
380     for (j = 0; j < ty->seq_table_size; j++) {
381         if (ty->cur_chunk_pos >= CHUNK_SIZE - 8)
382             return;
383         ty->seq_table[j].timestamp = AV_RB64(ty->chunk + ty->cur_chunk_pos);
384         ty->cur_chunk_pos += 8;
385         if (map_size > 8) {
386             av_log(s, AV_LOG_ERROR, "Unsupported SEQ bitmap size in master chunk.\n");
387             ty->cur_chunk_pos += map_size;
388         } else {
389             memcpy(ty->seq_table[j].chunk_bitmask, ty->chunk + ty->cur_chunk_pos, map_size);
390         }
391     }
392 }
393
394 static int get_chunk(AVFormatContext *s)
395 {
396     TYDemuxContext *ty = s->priv_data;
397     AVIOContext *pb = s->pb;
398     int read_size, num_recs;
399
400     ff_dlog(s, "parsing ty chunk #%d\n", ty->cur_chunk);
401
402     /* if we have left-over filler space from the last chunk, get that */
403     if (avio_feof(pb))
404         return AVERROR_EOF;
405
406     /* read the TY packet header */
407     read_size = avio_read(pb, ty->chunk, CHUNK_SIZE);
408     ty->cur_chunk++;
409
410     if ((read_size < 4) || (AV_RB32(ty->chunk) == 0)) {
411         return AVERROR_EOF;
412     }
413
414     /* check if it's a PART Header */
415     if (AV_RB32(ty->chunk) == TIVO_PES_FILEID) {
416         parse_master(s); /* parse master chunk */
417         return get_chunk(s);
418     }
419
420     /* number of records in chunk (8- or 16-bit number) */
421     if (ty->chunk[3] & 0x80) {
422         /* 16 bit rec cnt */
423         ty->num_recs = num_recs = (ty->chunk[1] << 8) + ty->chunk[0];
424         ty->seq_rec = (ty->chunk[3] << 8) + ty->chunk[2];
425         if (ty->seq_rec != 0xffff) {
426             ty->seq_rec &= ~0x8000;
427         }
428     } else {
429         /* 8 bit reclen - TiVo 1.3 format */
430         ty->num_recs = num_recs = ty->chunk[0];
431         ty->seq_rec = ty->chunk[1];
432     }
433     ty->cur_rec = 0;
434     ty->first_chunk = 0;
435
436     ff_dlog(s, "chunk has %d records\n", num_recs);
437     ty->cur_chunk_pos = 4;
438
439     av_freep(&ty->rec_hdrs);
440
441     if (num_recs * 16 >= CHUNK_SIZE - 4)
442         return AVERROR_INVALIDDATA;
443
444     ty->rec_hdrs = parse_chunk_headers(ty->chunk + 4, num_recs);
445     if (!ty->rec_hdrs)
446         return AVERROR(ENOMEM);
447     ty->cur_chunk_pos += 16 * num_recs;
448
449     return 0;
450 }
451
452 static int demux_video(AVFormatContext *s, TyRecHdr *rec_hdr, AVPacket *pkt)
453 {
454     TYDemuxContext *ty = s->priv_data;
455     const int subrec_type = rec_hdr->subrec_type;
456     const int64_t rec_size = rec_hdr->rec_size;
457     int es_offset1, ret;
458     int got_packet = 0;
459
460     if (subrec_type != 0x02 && subrec_type != 0x0c &&
461         subrec_type != 0x08 && rec_size > 4) {
462         /* get the PTS from this packet if it has one.
463          * on S1, only 0x06 has PES.  On S2, however, most all do.
464          * Do NOT Pass the PES Header to the MPEG2 codec */
465         es_offset1 = find_es_header(ty_VideoPacket, ty->chunk + ty->cur_chunk_pos, 5);
466         if (es_offset1 != -1) {
467             ty->last_video_pts = ff_parse_pes_pts(
468                     ty->chunk + ty->cur_chunk_pos + es_offset1 + VIDEO_PTS_OFFSET);
469             if (subrec_type != 0x06) {
470                 /* if we found a PES, and it's not type 6, then we're S2 */
471                 /* The packet will have video data (& other headers) so we
472                  * chop out the PES header and send the rest */
473                 if (rec_size >= VIDEO_PES_LENGTH + es_offset1) {
474                     int size = rec_hdr->rec_size - VIDEO_PES_LENGTH - es_offset1;
475
476                     ty->cur_chunk_pos += VIDEO_PES_LENGTH + es_offset1;
477                     if ((ret = av_new_packet(pkt, size)) < 0)
478                         return ret;
479                     memcpy(pkt->data, ty->chunk + ty->cur_chunk_pos, size);
480                     ty->cur_chunk_pos += size;
481                     pkt->stream_index = 0;
482                     got_packet = 1;
483                 } else {
484                     ff_dlog(s, "video rec type 0x%02x has short PES"
485                         " (%"PRId64" bytes)\n", subrec_type, rec_size);
486                     /* nuke this block; it's too short, but has PES marker */
487                     ty->cur_chunk_pos += rec_size;
488                     return 0;
489                 }
490             }
491         }
492     }
493
494     if (subrec_type == 0x06) {
495         /* type 6 (S1 DTivo) has no data, so we're done */
496         ty->cur_chunk_pos += rec_size;
497         return 0;
498     }
499
500     if (!got_packet) {
501         if ((ret = av_new_packet(pkt, rec_size)) < 0)
502             return ret;
503         memcpy(pkt->data, ty->chunk + ty->cur_chunk_pos, rec_size);
504         ty->cur_chunk_pos += rec_size;
505         pkt->stream_index = 0;
506         got_packet = 1;
507     }
508
509     /* if it's not a continue blk, then set PTS */
510     if (subrec_type != 0x02) {
511         if (subrec_type == 0x0c && pkt->size >= 6)
512             pkt->data[5] |= 0x08;
513         if (subrec_type == 0x07) {
514             ty->last_ty_pts = rec_hdr->ty_pts;
515         } else {
516             /* yes I know this is a cheap hack.  It's the timestamp
517                used for display and skipping fwd/back, so it
518                doesn't have to be accurate to the millisecond.
519                I adjust it here by roughly one 1/30 sec.  Yes it
520                will be slightly off for UK streams, but it's OK.
521              */
522             ty->last_ty_pts += 35000000;
523             //ty->last_ty_pts += 33366667;
524         }
525         /* set PTS for this block before we send */
526         if (ty->last_video_pts > AV_NOPTS_VALUE) {
527             pkt->pts = ty->last_video_pts;
528             /* PTS gets used ONCE.
529              * Any subsequent frames we get BEFORE next PES
530              * header will have their PTS computed in the codec */
531             ty->last_video_pts = AV_NOPTS_VALUE;
532         }
533     }
534
535     return got_packet;
536 }
537
538 static int check_sync_pes(AVFormatContext *s, AVPacket *pkt,
539                           int32_t offset, int32_t rec_len)
540 {
541     TYDemuxContext *ty = s->priv_data;
542
543     if (offset < 0 || offset + ty->pes_length > rec_len) {
544         /* entire PES header not present */
545         ff_dlog(s, "PES header at %"PRId32" not complete in record. storing.\n", offset);
546         /* save the partial pes header */
547         if (offset < 0) {
548             /* no header found, fake some 00's (this works, believe me) */
549             memset(ty->pes_buffer, 0, 4);
550             ty->pes_buf_cnt = 4;
551             if (rec_len > 4)
552                 ff_dlog(s, "PES header not found in record of %"PRId32" bytes!\n", rec_len);
553             return -1;
554         }
555         /* copy the partial pes header we found */
556         memcpy(ty->pes_buffer, pkt->data + offset, rec_len - offset);
557         ty->pes_buf_cnt = rec_len - offset;
558
559         if (offset > 0) {
560             /* PES Header was found, but not complete, so trim the end of this record */
561             pkt->size -= rec_len - offset;
562             return 1;
563         }
564         return -1;    /* partial PES, no audio data */
565     }
566     /* full PES header present, extract PTS */
567     ty->last_audio_pts = ff_parse_pes_pts(&pkt->data[ offset + ty->pts_offset]);
568     if (ty->first_audio_pts == AV_NOPTS_VALUE)
569         ty->first_audio_pts = ty->last_audio_pts;
570     pkt->pts = ty->last_audio_pts;
571     memmove(pkt->data + offset, pkt->data + offset + ty->pes_length, rec_len - ty->pes_length);
572     pkt->size -= ty->pes_length;
573     return 0;
574 }
575
576 static int demux_audio(AVFormatContext *s, TyRecHdr *rec_hdr, AVPacket *pkt)
577 {
578     TYDemuxContext *ty = s->priv_data;
579     const int subrec_type = rec_hdr->subrec_type;
580     const int64_t rec_size = rec_hdr->rec_size;
581     int es_offset1, ret;
582
583     if (subrec_type == 2) {
584         int need = 0;
585         /* SA or DTiVo Audio Data, no PES (continued block)
586          * ================================================
587          */
588
589         /* continue PES if previous was incomplete */
590         if (ty->pes_buf_cnt > 0) {
591             need = ty->pes_length - ty->pes_buf_cnt;
592
593             ff_dlog(s, "continuing PES header\n");
594             /* do we have enough data to complete? */
595             if (need >= rec_size) {
596                 /* don't have complete PES hdr; save what we have and return */
597                 memcpy(ty->pes_buffer + ty->pes_buf_cnt, ty->chunk + ty->cur_chunk_pos, rec_size);
598                 ty->cur_chunk_pos += rec_size;
599                 ty->pes_buf_cnt += rec_size;
600                 return 0;
601             }
602
603             /* we have enough; reconstruct this frame with the new hdr */
604             memcpy(ty->pes_buffer + ty->pes_buf_cnt, ty->chunk + ty->cur_chunk_pos, need);
605             ty->cur_chunk_pos += need;
606             /* get the PTS out of this PES header (MPEG or AC3) */
607             if (ty->audio_type == TIVO_AUDIO_MPEG) {
608                 es_offset1 = find_es_header(ty_MPEGAudioPacket,
609                         ty->pes_buffer, 5);
610             } else {
611                 es_offset1 = find_es_header(ty_AC3AudioPacket,
612                         ty->pes_buffer, 5);
613             }
614             if (es_offset1 < 0) {
615                 ff_dlog(s, "Can't find audio PES header in packet.\n");
616             } else {
617                 ty->last_audio_pts = ff_parse_pes_pts(
618                     &ty->pes_buffer[es_offset1 + ty->pts_offset]);
619                 pkt->pts = ty->last_audio_pts;
620             }
621             ty->pes_buf_cnt = 0;
622
623         }
624         if ((ret = av_new_packet(pkt, rec_size - need)) < 0)
625             return ret;
626         memcpy(pkt->data, ty->chunk + ty->cur_chunk_pos, rec_size - need);
627         ty->cur_chunk_pos += rec_size - need;
628         pkt->stream_index = 1;
629
630         /* S2 DTivo has AC3 packets with 2 padding bytes at end.  This is
631          * not allowed in the AC3 spec and will cause problems.  So here
632          * we try to trim things. */
633         /* Also, S1 DTivo has alternating short / long AC3 packets.  That
634          * is, one packet is short (incomplete) and the next packet has
635          * the first one's missing data, plus all of its own.  Strange. */
636         if (ty->audio_type == TIVO_AUDIO_AC3 &&
637                 ty->tivo_series == TIVO_SERIES2) {
638             if (ty->ac3_pkt_size + pkt->size > AC3_PKT_LENGTH) {
639                 pkt->size -= 2;
640                 ty->ac3_pkt_size = 0;
641             } else {
642                 ty->ac3_pkt_size += pkt->size;
643             }
644         }
645     } else if (subrec_type == 0x03) {
646         if ((ret = av_new_packet(pkt, rec_size)) < 0)
647             return ret;
648         memcpy(pkt->data, ty->chunk + ty->cur_chunk_pos, rec_size);
649         ty->cur_chunk_pos += rec_size;
650         pkt->stream_index = 1;
651         /* MPEG Audio with PES Header, either SA or DTiVo   */
652         /* ================================================ */
653         es_offset1 = find_es_header(ty_MPEGAudioPacket, pkt->data, 5);
654
655         /* SA PES Header, No Audio Data                     */
656         /* ================================================ */
657         if ((es_offset1 == 0) && (rec_size == 16)) {
658             ty->last_audio_pts = ff_parse_pes_pts(&pkt->data[SA_PTS_OFFSET]);
659             if (ty->first_audio_pts == AV_NOPTS_VALUE)
660                 ty->first_audio_pts = ty->last_audio_pts;
661             av_packet_unref(pkt);
662             return 0;
663         }
664         /* DTiVo Audio with PES Header                      */
665         /* ================================================ */
666
667         /* Check for complete PES */
668         if (check_sync_pes(s, pkt, es_offset1, rec_size) == -1) {
669             /* partial PES header found, nothing else.
670              * we're done. */
671             av_packet_unref(pkt);
672             return 0;
673         }
674     } else if (subrec_type == 0x04) {
675         /* SA Audio with no PES Header                      */
676         /* ================================================ */
677         if ((ret = av_new_packet(pkt, rec_size)) < 0)
678             return ret;
679         memcpy(pkt->data, ty->chunk + ty->cur_chunk_pos, rec_size);
680         ty->cur_chunk_pos += rec_size;
681         pkt->stream_index = 1;
682         pkt->pts = ty->last_audio_pts;
683     } else if (subrec_type == 0x09) {
684         if ((ret = av_new_packet(pkt, rec_size)) < 0)
685             return ret;
686         memcpy(pkt->data, ty->chunk + ty->cur_chunk_pos, rec_size);
687         ty->cur_chunk_pos += rec_size ;
688         pkt->stream_index = 1;
689
690         /* DTiVo AC3 Audio Data with PES Header             */
691         /* ================================================ */
692         es_offset1 = find_es_header(ty_AC3AudioPacket, pkt->data, 5);
693
694         /* Check for complete PES */
695         if (check_sync_pes(s, pkt, es_offset1, rec_size) == -1) {
696             /* partial PES header found, nothing else.  we're done. */
697             av_packet_unref(pkt);
698             return 0;
699         }
700         /* S2 DTivo has invalid long AC3 packets */
701         if (ty->tivo_series == TIVO_SERIES2) {
702             if (pkt->size > AC3_PKT_LENGTH) {
703                 pkt->size -= 2;
704                 ty->ac3_pkt_size = 0;
705             } else {
706                 ty->ac3_pkt_size = pkt->size;
707             }
708         }
709     } else {
710         /* Unsupported/Unknown */
711         ty->cur_chunk_pos += rec_size;
712         return 0;
713     }
714
715     return 1;
716 }
717
718 static int ty_read_packet(AVFormatContext *s, AVPacket *pkt)
719 {
720     TYDemuxContext *ty = s->priv_data;
721     AVIOContext *pb = s->pb;
722     TyRecHdr *rec;
723     int64_t rec_size = 0;
724     int ret = 0;
725
726     if (avio_feof(pb))
727         return AVERROR_EOF;
728
729     while (ret <= 0) {
730         if (!ty->rec_hdrs || ty->first_chunk || ty->cur_rec >= ty->num_recs) {
731             if (get_chunk(s) < 0 || ty->num_recs <= 0)
732                 return AVERROR_EOF;
733         }
734
735         rec = &ty->rec_hdrs[ty->cur_rec];
736         rec_size = rec->rec_size;
737         ty->cur_rec++;
738
739         if (rec_size <= 0)
740             continue;
741
742         if (ty->cur_chunk_pos + rec->rec_size > CHUNK_SIZE)
743             return AVERROR_INVALIDDATA;
744
745         if (avio_feof(pb))
746             return AVERROR_EOF;
747
748         switch (rec->rec_type) {
749         case VIDEO_ID:
750             ret = demux_video(s, rec, pkt);
751             break;
752         case AUDIO_ID:
753             ret = demux_audio(s, rec, pkt);
754             break;
755         default:
756             ff_dlog(s, "Invalid record type 0x%02x\n", rec->rec_type);
757         case 0x01:
758         case 0x02:
759         case 0x03: /* TiVo data services */
760         case 0x05: /* unknown, but seen regularly */
761             ty->cur_chunk_pos += rec->rec_size;
762             break;
763         }
764     }
765
766     return 0;
767 }
768
769 static int ty_read_close(AVFormatContext *s)
770 {
771     TYDemuxContext *ty = s->priv_data;
772
773     av_freep(&ty->seq_table);
774     av_freep(&ty->rec_hdrs);
775
776     return 0;
777 }
778
779 AVInputFormat ff_ty_demuxer = {
780     .name           = "ty",
781     .long_name      = NULL_IF_CONFIG_SMALL("TiVo TY Stream"),
782     .priv_data_size = sizeof(TYDemuxContext),
783     .read_probe     = ty_probe,
784     .read_header    = ty_read_header,
785     .read_packet    = ty_read_packet,
786     .read_close     = ty_read_close,
787     .extensions     = "ty,ty+",
788     .flags          = AVFMT_TS_DISCONT,
789 };