]> git.sesse.net Git - ffmpeg/blob - libavformat/oggdec.c
mov: Wrap stsc index and count compare in a separate function
[ffmpeg] / libavformat / oggdec.c
1 /*
2  * Ogg bitstream support
3  * Luca Barbato <lu_zero@gentoo.org>
4  * Based on tcvp implementation
5  */
6
7 /*
8     Copyright (C) 2005  Michael Ahlberg, Måns Rullgård
9
10     Permission is hereby granted, free of charge, to any person
11     obtaining a copy of this software and associated documentation
12     files (the "Software"), to deal in the Software without
13     restriction, including without limitation the rights to use, copy,
14     modify, merge, publish, distribute, sublicense, and/or sell copies
15     of the Software, and to permit persons to whom the Software is
16     furnished to do so, subject to the following conditions:
17
18     The above copyright notice and this permission notice shall be
19     included in all copies or substantial portions of the Software.
20
21     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28     DEALINGS IN THE SOFTWARE.
29  */
30
31
32 #include <stdio.h>
33 #include "oggdec.h"
34 #include "avformat.h"
35 #include "internal.h"
36 #include "vorbiscomment.h"
37
38 #define MAX_PAGE_SIZE 65307
39 #define DECODER_BUFFER_SIZE MAX_PAGE_SIZE
40
41 static const struct ogg_codec * const ogg_codecs[] = {
42     &ff_skeleton_codec,
43     &ff_dirac_codec,
44     &ff_speex_codec,
45     &ff_vorbis_codec,
46     &ff_theora_codec,
47     &ff_flac_codec,
48     &ff_celt_codec,
49     &ff_opus_codec,
50     &ff_vp8_codec,
51     &ff_old_dirac_codec,
52     &ff_old_flac_codec,
53     &ff_ogm_video_codec,
54     &ff_ogm_audio_codec,
55     &ff_ogm_text_codec,
56     &ff_ogm_old_codec,
57     NULL
58 };
59
60 //FIXME We could avoid some structure duplication
61 static int ogg_save(AVFormatContext *s)
62 {
63     struct ogg *ogg = s->priv_data;
64     struct ogg_state *ost =
65         av_malloc(sizeof(*ost) + (ogg->nstreams - 1) * sizeof(*ogg->streams));
66     int i;
67     if (!ost)
68         return AVERROR(ENOMEM);
69     ost->pos      = avio_tell(s->pb);
70     ost->curidx   = ogg->curidx;
71     ost->next     = ogg->state;
72     ost->nstreams = ogg->nstreams;
73     memcpy(ost->streams, ogg->streams, ogg->nstreams * sizeof(*ogg->streams));
74
75     for (i = 0; i < ogg->nstreams; i++) {
76         struct ogg_stream *os = ogg->streams + i;
77         os->buf = av_mallocz(os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE);
78         memcpy(os->buf, ost->streams[i].buf, os->bufpos);
79     }
80
81     ogg->state = ost;
82
83     return 0;
84 }
85
86 static int ogg_restore(AVFormatContext *s, int discard)
87 {
88     struct ogg *ogg = s->priv_data;
89     AVIOContext *bc = s->pb;
90     struct ogg_state *ost = ogg->state;
91     int i, err;
92
93     if (!ost)
94         return 0;
95
96     ogg->state = ost->next;
97
98     if (!discard) {
99
100         for (i = 0; i < ogg->nstreams; i++)
101             av_free(ogg->streams[i].buf);
102
103         avio_seek(bc, ost->pos, SEEK_SET);
104         ogg->curidx   = ost->curidx;
105         ogg->nstreams = ost->nstreams;
106         if ((err = av_reallocp_array(&ogg->streams, ogg->nstreams,
107                                      sizeof(*ogg->streams))) < 0) {
108             ogg->nstreams = 0;
109             return err;
110         } else
111             memcpy(ogg->streams, ost->streams,
112                    ost->nstreams * sizeof(*ogg->streams));
113     }
114
115     av_free(ost);
116
117     return 0;
118 }
119
120 static int ogg_reset(struct ogg *ogg)
121 {
122     int i;
123
124     for (i = 0; i < ogg->nstreams; i++) {
125         struct ogg_stream *os = ogg->streams + i;
126         os->bufpos     = 0;
127         os->pstart     = 0;
128         os->psize      = 0;
129         os->granule    = -1;
130         os->lastpts    = AV_NOPTS_VALUE;
131         os->lastdts    = AV_NOPTS_VALUE;
132         os->sync_pos   = -1;
133         os->page_pos   = 0;
134         os->nsegs      = 0;
135         os->segp       = 0;
136         os->incomplete = 0;
137     }
138
139     ogg->curidx = -1;
140
141     return 0;
142 }
143
144 static const struct ogg_codec *ogg_find_codec(uint8_t *buf, int size)
145 {
146     int i;
147
148     for (i = 0; ogg_codecs[i]; i++)
149         if (size >= ogg_codecs[i]->magicsize &&
150             !memcmp(buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize))
151             return ogg_codecs[i];
152
153     return NULL;
154 }
155
156 static int ogg_new_stream(AVFormatContext *s, uint32_t serial, int new_avstream)
157 {
158     struct ogg *ogg = s->priv_data;
159     int idx         = ogg->nstreams++;
160     AVStream *st;
161     struct ogg_stream *os;
162
163     os = av_realloc(ogg->streams, ogg->nstreams * sizeof(*ogg->streams));
164
165     if (!os)
166         return AVERROR(ENOMEM);
167
168     ogg->streams = os;
169
170     memset(ogg->streams + idx, 0, sizeof(*ogg->streams));
171
172     os                = ogg->streams + idx;
173     os->serial        = serial;
174     os->bufsize       = DECODER_BUFFER_SIZE;
175     os->buf           = av_malloc(os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE);
176     os->header        = -1;
177     os->start_granule = OGG_NOGRANULE_VALUE;
178
179     if (new_avstream) {
180         st = avformat_new_stream(s, NULL);
181         if (!st)
182             return AVERROR(ENOMEM);
183
184         st->id = idx;
185         avpriv_set_pts_info(st, 64, 1, 1000000);
186     }
187
188     return idx;
189 }
190
191 static int ogg_new_buf(struct ogg *ogg, int idx)
192 {
193     struct ogg_stream *os = ogg->streams + idx;
194     uint8_t *nb = av_malloc(os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE);
195     int size = os->bufpos - os->pstart;
196
197     if (!nb)
198         return AVERROR(ENOMEM);
199
200     if (os->buf) {
201         memcpy(nb, os->buf + os->pstart, size);
202         av_free(os->buf);
203     }
204
205     os->buf    = nb;
206     os->bufpos = size;
207     os->pstart = 0;
208
209     return 0;
210 }
211
212 static int ogg_read_page(AVFormatContext *s, int *str)
213 {
214     AVIOContext *bc = s->pb;
215     struct ogg *ogg = s->priv_data;
216     struct ogg_stream *os;
217     int ret, i = 0;
218     int flags, nsegs;
219     uint64_t gp;
220     uint32_t serial;
221     int size, idx;
222     uint8_t sync[4];
223     int sp = 0;
224
225     ret = avio_read(bc, sync, 4);
226     if (ret < 4)
227         return ret < 0 ? ret : AVERROR_EOF;
228
229     do {
230         int c;
231
232         if (sync[sp & 3] == 'O' &&
233             sync[(sp + 1) & 3] == 'g' &&
234             sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
235             break;
236
237         c = avio_r8(bc);
238
239         if (bc->eof_reached)
240             return AVERROR_EOF;
241
242         sync[sp++ & 3] = c;
243     } while (i++ < MAX_PAGE_SIZE);
244
245     if (i >= MAX_PAGE_SIZE) {
246         av_log(s, AV_LOG_INFO, "cannot find sync word\n");
247         return AVERROR_INVALIDDATA;
248     }
249
250     if (avio_r8(bc) != 0)      /* version */
251         return AVERROR_INVALIDDATA;
252
253     flags  = avio_r8(bc);
254     gp     = avio_rl64(bc);
255     serial = avio_rl32(bc);
256     avio_skip(bc, 8); /* seq, crc */
257     nsegs  = avio_r8(bc);
258
259     idx = ogg_find_stream(ogg, serial);
260     if (idx < 0) {
261         if (ogg->headers) {
262             int n;
263
264             for (n = 0; n < ogg->nstreams; n++) {
265                 av_freep(&ogg->streams[n].buf);
266                 if (!ogg->state ||
267                     ogg->state->streams[n].private != ogg->streams[n].private)
268                     av_freep(&ogg->streams[n].private);
269             }
270
271             ogg->curidx   = -1;
272             ogg->nstreams = 0;
273
274             idx = ogg_new_stream(s, serial, 0);
275         } else {
276             idx = ogg_new_stream(s, serial, 1);
277         }
278         if (idx < 0)
279             return idx;
280     }
281
282     os = ogg->streams + idx;
283     os->page_pos = avio_tell(bc) - 27;
284
285     if (os->psize > 0) {
286         ret = ogg_new_buf(ogg, idx);
287         if (ret < 0)
288             return ret;
289     }
290
291     ret = avio_read(bc, os->segments, nsegs);
292     if (ret < nsegs)
293         return ret < 0 ? ret : AVERROR_EOF;
294
295     os->nsegs = nsegs;
296     os->segp  = 0;
297
298     size = 0;
299     for (i = 0; i < nsegs; i++)
300         size += os->segments[i];
301
302     if (flags & OGG_FLAG_CONT || os->incomplete) {
303         if (!os->psize) {
304             while (os->segp < os->nsegs) {
305                 int seg = os->segments[os->segp++];
306                 os->pstart += seg;
307                 if (seg < 255)
308                     break;
309             }
310             os->sync_pos = os->page_pos;
311         }
312     } else {
313         os->psize    = 0;
314         os->sync_pos = os->page_pos;
315     }
316
317     if (os->bufsize - os->bufpos < size) {
318         uint8_t *nb = av_malloc((os->bufsize *= 2) + AV_INPUT_BUFFER_PADDING_SIZE);
319         if (!nb)
320             return AVERROR(ENOMEM);
321         memcpy(nb, os->buf, os->bufpos);
322         av_free(os->buf);
323         os->buf = nb;
324     }
325
326     ret = avio_read(bc, os->buf + os->bufpos, size);
327     if (ret < size)
328         return ret < 0 ? ret : AVERROR_EOF;
329
330     os->bufpos += size;
331     os->granule = gp;
332     os->flags   = flags;
333
334     memset(os->buf + os->bufpos, 0, AV_INPUT_BUFFER_PADDING_SIZE);
335     if (str)
336         *str = idx;
337
338     return 0;
339 }
340
341 static int ogg_packet(AVFormatContext *s, int *str, int *dstart, int *dsize,
342                       int64_t *fpos)
343 {
344     struct ogg *ogg = s->priv_data;
345     int idx, i, ret;
346     struct ogg_stream *os;
347     int complete = 0;
348     int segp     = 0, psize = 0;
349
350     av_log(s, AV_LOG_TRACE, "ogg_packet: curidx=%i\n", ogg->curidx);
351
352     do {
353         idx = ogg->curidx;
354
355         while (idx < 0) {
356             ret = ogg_read_page(s, &idx);
357             if (ret < 0)
358                 return ret;
359         }
360
361         os = ogg->streams + idx;
362
363         av_log(s, AV_LOG_TRACE, "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
364                 idx, os->pstart, os->psize, os->segp, os->nsegs);
365
366         if (!os->codec) {
367             if (os->header < 0) {
368                 os->codec = ogg_find_codec(os->buf, os->bufpos);
369                 if (!os->codec) {
370                     av_log(s, AV_LOG_WARNING, "Codec not found\n");
371                     os->header = 0;
372                     return 0;
373                 }
374             } else {
375                 return 0;
376             }
377         }
378
379         segp  = os->segp;
380         psize = os->psize;
381
382         while (os->segp < os->nsegs) {
383             int ss = os->segments[os->segp++];
384             os->psize += ss;
385             if (ss < 255) {
386                 complete = 1;
387                 break;
388             }
389         }
390
391         if (!complete && os->segp == os->nsegs) {
392             ogg->curidx    = -1;
393             // Do not set incomplete for empty packets.
394             // Together with the code in ogg_read_page
395             // that discards all continuation of empty packets
396             // we would get an infinite loop.
397             os->incomplete = !!os->psize;
398         }
399     } while (!complete);
400
401     av_log(s, AV_LOG_TRACE, "ogg_packet: idx %i, frame size %i, start %i\n",
402             idx, os->psize, os->pstart);
403
404     if (os->granule == -1)
405         av_log(s, AV_LOG_WARNING,
406                "Page at %"PRId64" is missing granule\n",
407                os->page_pos);
408
409     ogg->curidx    = idx;
410     os->incomplete = 0;
411
412     if (os->header) {
413         os->header = os->codec->header(s, idx);
414         if (!os->header) {
415             os->segp  = segp;
416             os->psize = psize;
417
418             // We have reached the first non-header packet in this stream.
419             // Unfortunately more header packets may still follow for others,
420             // but if we continue with header parsing we may lose data packets.
421             ogg->headers = 1;
422
423             // Update the header state for all streams and
424             // compute the data_offset.
425             if (!s->internal->data_offset)
426                 s->internal->data_offset = os->sync_pos;
427
428             for (i = 0; i < ogg->nstreams; i++) {
429                 struct ogg_stream *cur_os = ogg->streams + i;
430
431                 // if we have a partial non-header packet, its start is
432                 // obviously at or after the data start
433                 if (cur_os->incomplete)
434                     s->internal->data_offset = FFMIN(s->internal->data_offset, cur_os->sync_pos);
435             }
436         } else {
437             os->nb_header++;
438             os->pstart += os->psize;
439             os->psize   = 0;
440         }
441     } else {
442         os->pflags    = 0;
443         os->pduration = 0;
444         if (os->codec && os->codec->packet)
445             os->codec->packet(s, idx);
446         if (str)
447             *str = idx;
448         if (dstart)
449             *dstart = os->pstart;
450         if (dsize)
451             *dsize = os->psize;
452         if (fpos)
453             *fpos = os->sync_pos;
454         os->pstart  += os->psize;
455         os->psize    = 0;
456         os->sync_pos = os->page_pos;
457     }
458
459     // determine whether there are more complete packets in this page
460     // if not, the page's granule will apply to this packet
461     os->page_end = 1;
462     for (i = os->segp; i < os->nsegs; i++)
463         if (os->segments[i] < 255) {
464             os->page_end = 0;
465             break;
466         }
467
468     if (os->segp == os->nsegs)
469         ogg->curidx = -1;
470
471     return 0;
472 }
473
474 static int ogg_get_headers(AVFormatContext *s)
475 {
476     struct ogg *ogg = s->priv_data;
477     int ret, i;
478
479     do {
480         ret = ogg_packet(s, NULL, NULL, NULL, NULL);
481         if (ret < 0)
482             return ret;
483     } while (!ogg->headers);
484
485     for (i = 0; i < ogg->nstreams; i++) {
486         struct ogg_stream *os = ogg->streams + i;
487
488         if (os->codec && os->codec->nb_header &&
489             os->nb_header < os->codec->nb_header) {
490             av_log(s, AV_LOG_ERROR,
491                    "Headers mismatch for stream %d: "
492                    "expected %d received %d.\n",
493                    i, os->codec->nb_header, os->nb_header);
494             if (s->error_recognition & AV_EF_EXPLODE)
495                 return AVERROR_INVALIDDATA;
496         }
497         if (os->start_granule != OGG_NOGRANULE_VALUE)
498             os->lastpts = s->streams[i]->start_time =
499                 ogg_gptopts(s, i, os->start_granule, NULL);
500     }
501     av_log(s, AV_LOG_TRACE, "found headers\n");
502
503     return 0;
504 }
505
506 static int ogg_get_length(AVFormatContext *s)
507 {
508     struct ogg *ogg = s->priv_data;
509     int i, ret;
510     int64_t size, end;
511
512     if (!s->pb->seekable)
513         return 0;
514
515 // already set
516     if (s->duration != AV_NOPTS_VALUE)
517         return 0;
518
519     size = avio_size(s->pb);
520     if (size < 0)
521         return 0;
522     end = size > MAX_PAGE_SIZE ? size - MAX_PAGE_SIZE : 0;
523
524     ret = ogg_save(s);
525     if (ret < 0)
526         return ret;
527     avio_seek(s->pb, end, SEEK_SET);
528
529     while (!ogg_read_page(s, &i)) {
530         if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
531             ogg->streams[i].codec) {
532             s->streams[i]->duration =
533                 ogg_gptopts(s, i, ogg->streams[i].granule, NULL);
534             if (s->streams[i]->start_time != AV_NOPTS_VALUE)
535                 s->streams[i]->duration -= s->streams[i]->start_time;
536         }
537     }
538
539     ogg_restore(s, 0);
540
541     return 0;
542 }
543
544 static int ogg_read_close(AVFormatContext *s)
545 {
546     struct ogg *ogg = s->priv_data;
547     int i;
548
549     for (i = 0; i < ogg->nstreams; i++) {
550         av_free(ogg->streams[i].buf);
551         if (ogg->streams[i].codec &&
552             ogg->streams[i].codec->cleanup) {
553             ogg->streams[i].codec->cleanup(s, i);
554         }
555         av_free(ogg->streams[i].private);
556     }
557     av_free(ogg->streams);
558     return 0;
559 }
560
561 static int ogg_read_header(AVFormatContext *s)
562 {
563     struct ogg *ogg = s->priv_data;
564     int ret, i;
565     ogg->curidx = -1;
566     //linear headers seek from start
567     ret = ogg_get_headers(s);
568     if (ret < 0) {
569         ogg_read_close(s);
570         return ret;
571     }
572
573     for (i = 0; i < ogg->nstreams; i++)
574         if (ogg->streams[i].header < 0)
575             ogg->streams[i].codec = NULL;
576
577     //linear granulepos seek from end
578     ret = ogg_get_length(s);
579     if (ret < 0) {
580         ogg_read_close(s);
581         return ret;
582     }
583
584     //fill the extradata in the per codec callbacks
585     return 0;
586 }
587
588 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
589 {
590     struct ogg *ogg       = s->priv_data;
591     struct ogg_stream *os = ogg->streams + idx;
592     int64_t pts           = AV_NOPTS_VALUE;
593
594     if (dts)
595         *dts = AV_NOPTS_VALUE;
596
597     if (os->lastpts != AV_NOPTS_VALUE) {
598         pts         = os->lastpts;
599         os->lastpts = AV_NOPTS_VALUE;
600     }
601     if (os->lastdts != AV_NOPTS_VALUE) {
602         if (dts)
603             *dts = os->lastdts;
604         os->lastdts = AV_NOPTS_VALUE;
605     }
606     if (os->page_end) {
607         if (os->granule != -1LL) {
608             if (os->codec && os->codec->granule_is_start)
609                 pts = ogg_gptopts(s, idx, os->granule, dts);
610             else
611                 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
612             os->granule = -1LL;
613         }
614     }
615     return pts;
616 }
617
618 static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
619 {
620     struct ogg *ogg;
621     struct ogg_stream *os;
622     int idx = -1, ret;
623     int pstart, psize;
624     int64_t fpos, pts, dts;
625
626     //Get an ogg packet
627 retry:
628     do {
629         ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
630         if (ret < 0)
631             return ret;
632     } while (idx < 0 || !s->streams[idx]);
633
634     ogg = s->priv_data;
635     os  = ogg->streams + idx;
636
637     // pflags might not be set until after this
638     pts = ogg_calc_pts(s, idx, &dts);
639
640     if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
641         goto retry;
642     os->keyframe_seek = 0;
643
644     //Alloc a pkt
645     ret = av_new_packet(pkt, psize);
646     if (ret < 0)
647         return ret;
648     pkt->stream_index = idx;
649     memcpy(pkt->data, os->buf + pstart, psize);
650
651     pkt->pts      = pts;
652     pkt->dts      = dts;
653     pkt->flags    = os->pflags;
654     pkt->duration = os->pduration;
655     pkt->pos      = fpos;
656
657     return psize;
658 }
659
660 static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
661                                   int64_t *pos_arg, int64_t pos_limit)
662 {
663     struct ogg *ogg = s->priv_data;
664     AVIOContext *bc = s->pb;
665     int64_t pts     = AV_NOPTS_VALUE;
666     int i           = -1;
667     avio_seek(bc, *pos_arg, SEEK_SET);
668     ogg_reset(ogg);
669
670     while (avio_tell(bc) < pos_limit &&
671            !ogg_packet(s, &i, NULL, NULL, pos_arg)) {
672         if (i == stream_index) {
673             struct ogg_stream *os = ogg->streams + stream_index;
674             pts = ogg_calc_pts(s, i, NULL);
675             if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
676                 pts = AV_NOPTS_VALUE;
677         }
678         if (pts != AV_NOPTS_VALUE)
679             break;
680     }
681     ogg_reset(ogg);
682     return pts;
683 }
684
685 static int ogg_read_seek(AVFormatContext *s, int stream_index,
686                          int64_t timestamp, int flags)
687 {
688     struct ogg *ogg       = s->priv_data;
689     struct ogg_stream *os = ogg->streams + stream_index;
690     int ret;
691
692     // Try seeking to a keyframe first. If this fails (very possible),
693     // av_seek_frame will fall back to ignoring keyframes
694     if (s->streams[stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO
695         && !(flags & AVSEEK_FLAG_ANY))
696         os->keyframe_seek = 1;
697
698     ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
699     os  = ogg->streams + stream_index;
700     if (ret < 0)
701         os->keyframe_seek = 0;
702     return ret;
703 }
704
705 static int ogg_probe(AVProbeData *p)
706 {
707     if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
708         return AVPROBE_SCORE_MAX;
709     return 0;
710 }
711
712 AVInputFormat ff_ogg_demuxer = {
713     .name           = "ogg",
714     .long_name      = NULL_IF_CONFIG_SMALL("Ogg"),
715     .priv_data_size = sizeof(struct ogg),
716     .read_probe     = ogg_probe,
717     .read_header    = ogg_read_header,
718     .read_packet    = ogg_read_packet,
719     .read_close     = ogg_read_close,
720     .read_seek      = ogg_read_seek,
721     .read_timestamp = ogg_read_timestamp,
722     .extensions     = "ogg",
723     .flags          = AVFMT_GENERIC_INDEX | AVFMT_NOBINSEARCH,
724 };