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