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