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