2 * Ogg bitstream support
3 * Luca Barbato <lu_zero@gentoo.org>
4 * Based on tcvp implementation
9 Copyright (C) 2005 Michael Ahlberg, Måns Rullgård
11 Permission is hereby granted, free of charge, to any person
12 obtaining a copy of this software and associated documentation
13 files (the "Software"), to deal in the Software without
14 restriction, including without limitation the rights to use, copy,
15 modify, merge, publish, distribute, sublicense, and/or sell copies
16 of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
19 The above copyright notice and this permission notice shall be
20 included in all copies or substantial portions of the Software.
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
26 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
27 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 DEALINGS IN THE SOFTWARE.
36 #include "vorbiscomment.h"
38 #define MAX_PAGE_SIZE 65307
39 #define DECODER_BUFFER_SIZE MAX_PAGE_SIZE
41 static const struct ogg_codec * const ogg_codecs[] = {
57 //FIXME We could avoid some structure duplication
58 static int ogg_save(AVFormatContext *s)
60 struct ogg *ogg = s->priv_data;
61 struct ogg_state *ost =
62 av_malloc(sizeof (*ost) + (ogg->nstreams-1) * sizeof (*ogg->streams));
64 ost->pos = avio_tell (s->pb);
65 ost->curidx = ogg->curidx;
66 ost->next = ogg->state;
67 ost->nstreams = ogg->nstreams;
68 memcpy(ost->streams, ogg->streams, ogg->nstreams * sizeof(*ogg->streams));
70 for (i = 0; i < ogg->nstreams; i++){
71 struct ogg_stream *os = ogg->streams + i;
72 os->buf = av_malloc (os->bufsize);
73 memset (os->buf, 0, os->bufsize);
74 memcpy (os->buf, ost->streams[i].buf, os->bufpos);
82 static int ogg_restore(AVFormatContext *s, int discard)
84 struct ogg *ogg = s->priv_data;
85 AVIOContext *bc = s->pb;
86 struct ogg_state *ost = ogg->state;
92 ogg->state = ost->next;
95 for (i = 0; i < ogg->nstreams; i++)
96 av_free (ogg->streams[i].buf);
98 avio_seek (bc, ost->pos, SEEK_SET);
99 ogg->curidx = ost->curidx;
100 ogg->nstreams = ost->nstreams;
101 memcpy(ogg->streams, ost->streams,
102 ost->nstreams * sizeof(*ogg->streams));
110 static int ogg_reset(struct ogg *ogg)
114 for (i = 0; i < ogg->nstreams; i++){
115 struct ogg_stream *os = ogg->streams + i;
120 os->lastpts = AV_NOPTS_VALUE;
121 os->lastdts = AV_NOPTS_VALUE;
134 static const struct ogg_codec *ogg_find_codec(uint8_t *buf, int size)
138 for (i = 0; ogg_codecs[i]; i++)
139 if (size >= ogg_codecs[i]->magicsize &&
140 !memcmp (buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize))
141 return ogg_codecs[i];
146 static int ogg_new_stream(AVFormatContext *s, uint32_t serial, int new_avstream)
149 struct ogg *ogg = s->priv_data;
150 int idx = ogg->nstreams++;
152 struct ogg_stream *os;
154 ogg->streams = av_realloc (ogg->streams,
155 ogg->nstreams * sizeof (*ogg->streams));
156 memset (ogg->streams + idx, 0, sizeof (*ogg->streams));
157 os = ogg->streams + idx;
159 os->bufsize = DECODER_BUFFER_SIZE;
160 os->buf = av_malloc(os->bufsize);
164 st = av_new_stream(s, idx);
166 return AVERROR(ENOMEM);
168 av_set_pts_info(st, 64, 1, 1000000);
174 static int ogg_new_buf(struct ogg *ogg, int idx)
176 struct ogg_stream *os = ogg->streams + idx;
177 uint8_t *nb = av_malloc(os->bufsize);
178 int size = os->bufpos - os->pstart;
180 memcpy(nb, os->buf + os->pstart, size);
190 static int ogg_read_page(AVFormatContext *s, int *str)
192 AVIOContext *bc = s->pb;
193 struct ogg *ogg = s->priv_data;
194 struct ogg_stream *os;
203 ret = avio_read(bc, sync, 4);
205 return ret < 0 ? ret : AVERROR_EOF;
210 if (sync[sp & 3] == 'O' &&
211 sync[(sp + 1) & 3] == 'g' &&
212 sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
219 }while (i++ < MAX_PAGE_SIZE);
221 if (i >= MAX_PAGE_SIZE){
222 av_log (s, AV_LOG_INFO, "ogg, can't find sync word\n");
223 return AVERROR_INVALIDDATA;
226 if (avio_r8(bc) != 0) /* version */
227 return AVERROR_INVALIDDATA;
231 serial = avio_rl32 (bc);
232 avio_skip(bc, 8); /* seq, crc */
235 idx = ogg_find_stream (ogg, serial);
240 for (n = 0; n < ogg->nstreams; n++) {
241 av_freep(&ogg->streams[n].buf);
242 if (!ogg->state || ogg->state->streams[n].private != ogg->streams[n].private)
243 av_freep(&ogg->streams[n].private);
247 idx = ogg_new_stream(s, serial, 0);
249 idx = ogg_new_stream(s, serial, 1);
255 os = ogg->streams + idx;
256 os->page_pos = avio_tell(bc) - 27;
259 ogg_new_buf(ogg, idx);
261 ret = avio_read(bc, os->segments, nsegs);
263 return ret < 0 ? ret : AVERROR_EOF;
269 for (i = 0; i < nsegs; i++)
270 size += os->segments[i];
272 if (flags & OGG_FLAG_CONT || os->incomplete){
274 while (os->segp < os->nsegs){
275 int seg = os->segments[os->segp++];
280 os->sync_pos = os->page_pos;
284 os->sync_pos = os->page_pos;
287 if (os->bufsize - os->bufpos < size){
288 uint8_t *nb = av_malloc (os->bufsize *= 2);
289 memcpy (nb, os->buf, os->bufpos);
294 ret = avio_read(bc, os->buf + os->bufpos, size);
296 return ret < 0 ? ret : AVERROR_EOF;
308 static int ogg_packet(AVFormatContext *s, int *str, int *dstart, int *dsize,
311 struct ogg *ogg = s->priv_data;
313 struct ogg_stream *os;
315 int segp = 0, psize = 0;
317 av_dlog(s, "ogg_packet: curidx=%i\n", ogg->curidx);
323 ret = ogg_read_page(s, &idx);
328 os = ogg->streams + idx;
330 av_dlog(s, "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
331 idx, os->pstart, os->psize, os->segp, os->nsegs);
335 os->codec = ogg_find_codec (os->buf, os->bufpos);
337 av_log(s, AV_LOG_WARNING, "Codec not found\n");
349 while (os->segp < os->nsegs){
350 int ss = os->segments[os->segp++];
358 if (!complete && os->segp == os->nsegs){
364 av_dlog(s, "ogg_packet: idx %i, frame size %i, start %i\n",
365 idx, os->psize, os->pstart);
367 if (os->granule == -1)
368 av_log(s, AV_LOG_WARNING, "Page at %"PRId64" is missing granule\n", os->page_pos);
374 os->header = os->codec->header (s, idx);
379 // We have reached the first non-header packet in this stream.
380 // Unfortunately more header packets may still follow for others,
381 // but if we continue with header parsing we may lose data packets.
384 // Update the header state for all streams and
385 // compute the data_offset.
387 s->data_offset = os->sync_pos;
388 for (i = 0; i < ogg->nstreams; i++) {
389 struct ogg_stream *cur_os = ogg->streams + i;
391 // if we have a partial non-header packet, its start is
392 // obviously at or after the data start
393 if (cur_os->incomplete)
394 s->data_offset = FFMIN(s->data_offset, cur_os->sync_pos);
397 os->pstart += os->psize;
403 if (os->codec && os->codec->packet)
404 os->codec->packet (s, idx);
408 *dstart = os->pstart;
412 *fpos = os->sync_pos;
413 os->pstart += os->psize;
415 os->sync_pos = os->page_pos;
418 // determine whether there are more complete packets in this page
419 // if not, the page's granule will apply to this packet
421 for (i = os->segp; i < os->nsegs; i++)
422 if (os->segments[i] < 255) {
427 if (os->segp == os->nsegs)
433 static int ogg_get_headers(AVFormatContext *s)
435 struct ogg *ogg = s->priv_data;
439 ret = ogg_packet(s, NULL, NULL, NULL, NULL);
442 }while (!ogg->headers);
444 av_dlog(s, "found headers\n");
449 static int ogg_get_length(AVFormatContext *s)
451 struct ogg *ogg = s->priv_data;
459 if (s->duration != AV_NOPTS_VALUE)
462 size = avio_size(s->pb);
465 end = size > MAX_PAGE_SIZE? size - MAX_PAGE_SIZE: 0;
468 avio_seek (s->pb, end, SEEK_SET);
470 while (!ogg_read_page (s, &i)){
471 if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
472 ogg->streams[i].codec) {
473 s->streams[i]->duration =
474 ogg_gptopts (s, i, ogg->streams[i].granule, NULL);
475 if (s->streams[i]->start_time != AV_NOPTS_VALUE)
476 s->streams[i]->duration -= s->streams[i]->start_time;
485 static int ogg_read_header(AVFormatContext *s, AVFormatParameters *ap)
487 struct ogg *ogg = s->priv_data;
490 //linear headers seek from start
491 ret = ogg_get_headers(s);
495 for (i = 0; i < ogg->nstreams; i++)
496 if (ogg->streams[i].header < 0)
497 ogg->streams[i].codec = NULL;
499 //linear granulepos seek from end
502 //fill the extradata in the per codec callbacks
506 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
508 struct ogg *ogg = s->priv_data;
509 struct ogg_stream *os = ogg->streams + idx;
510 int64_t pts = AV_NOPTS_VALUE;
513 *dts = AV_NOPTS_VALUE;
515 if (os->lastpts != AV_NOPTS_VALUE) {
517 os->lastpts = AV_NOPTS_VALUE;
519 if (os->lastdts != AV_NOPTS_VALUE) {
522 os->lastdts = AV_NOPTS_VALUE;
525 if (os->granule != -1LL) {
526 if (os->codec && os->codec->granule_is_start)
527 pts = ogg_gptopts(s, idx, os->granule, dts);
529 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
536 static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
539 struct ogg_stream *os;
542 int64_t fpos, pts, dts;
547 ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
550 }while (idx < 0 || !s->streams[idx]);
553 os = ogg->streams + idx;
555 // pflags might not be set until after this
556 pts = ogg_calc_pts(s, idx, &dts);
558 if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
560 os->keyframe_seek = 0;
563 ret = av_new_packet(pkt, psize);
566 pkt->stream_index = idx;
567 memcpy (pkt->data, os->buf + pstart, psize);
571 pkt->flags = os->pflags;
572 pkt->duration = os->pduration;
578 static int ogg_read_close(AVFormatContext *s)
580 struct ogg *ogg = s->priv_data;
583 for (i = 0; i < ogg->nstreams; i++){
584 av_free (ogg->streams[i].buf);
585 av_free (ogg->streams[i].private);
587 av_free (ogg->streams);
591 static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
592 int64_t *pos_arg, int64_t pos_limit)
594 struct ogg *ogg = s->priv_data;
595 AVIOContext *bc = s->pb;
596 int64_t pts = AV_NOPTS_VALUE;
598 avio_seek(bc, *pos_arg, SEEK_SET);
601 while (avio_tell(bc) < pos_limit && !ogg_packet(s, &i, NULL, NULL, pos_arg)) {
602 if (i == stream_index) {
603 struct ogg_stream *os = ogg->streams + stream_index;
604 pts = ogg_calc_pts(s, i, NULL);
605 if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
606 pts = AV_NOPTS_VALUE;
608 if (pts != AV_NOPTS_VALUE)
615 static int ogg_read_seek(AVFormatContext *s, int stream_index,
616 int64_t timestamp, int flags)
618 struct ogg *ogg = s->priv_data;
619 struct ogg_stream *os = ogg->streams + stream_index;
622 // Try seeking to a keyframe first. If this fails (very possible),
623 // av_seek_frame will fall back to ignoring keyframes
624 if (s->streams[stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO
625 && !(flags & AVSEEK_FLAG_ANY))
626 os->keyframe_seek = 1;
628 ret = av_seek_frame_binary(s, stream_index, timestamp, flags);
629 os = ogg->streams + stream_index;
631 os->keyframe_seek = 0;
635 static int ogg_probe(AVProbeData *p)
637 if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
638 return AVPROBE_SCORE_MAX;
642 AVInputFormat ff_ogg_demuxer = {
644 .long_name = NULL_IF_CONFIG_SMALL("Ogg"),
645 .priv_data_size = sizeof(struct ogg),
646 .read_probe = ogg_probe,
647 .read_header = ogg_read_header,
648 .read_packet = ogg_read_packet,
649 .read_close = ogg_read_close,
650 .read_seek = ogg_read_seek,
651 .read_timestamp = ogg_read_timestamp,
653 .flags = AVFMT_GENERIC_INDEX,