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.
37 #define MAX_PAGE_SIZE 65307
38 #define DECODER_BUFFER_SIZE MAX_PAGE_SIZE
40 static const struct ogg_codec * const ogg_codecs[] = {
55 //FIXME We could avoid some structure duplication
57 ogg_save (AVFormatContext * s)
59 struct ogg *ogg = s->priv_data;
60 struct ogg_state *ost =
61 av_malloc(sizeof (*ost) + (ogg->nstreams-1) * sizeof (*ogg->streams));
63 ost->pos = url_ftell (s->pb);
64 ost->curidx = ogg->curidx;
65 ost->next = ogg->state;
66 ost->nstreams = ogg->nstreams;
67 memcpy(ost->streams, ogg->streams, ogg->nstreams * sizeof(*ogg->streams));
69 for (i = 0; i < ogg->nstreams; i++){
70 struct ogg_stream *os = ogg->streams + i;
71 os->buf = av_malloc (os->bufsize);
72 memset (os->buf, 0, os->bufsize);
73 memcpy (os->buf, ost->streams[i].buf, os->bufpos);
82 ogg_restore (AVFormatContext * s, int discard)
84 struct ogg *ogg = s->priv_data;
85 ByteIOContext *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 url_fseek (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));
111 ogg_reset (struct ogg * ogg)
115 for (i = 0; i < ogg->nstreams; i++){
116 struct ogg_stream *os = ogg->streams + i;
121 os->lastpts = AV_NOPTS_VALUE;
122 os->lastdts = AV_NOPTS_VALUE;
133 static const struct ogg_codec *
134 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];
147 ogg_find_stream (struct ogg * ogg, int serial)
151 for (i = 0; i < ogg->nstreams; i++)
152 if (ogg->streams[i].serial == serial)
159 ogg_new_stream (AVFormatContext * s, uint32_t serial)
162 struct ogg *ogg = s->priv_data;
163 int idx = ogg->nstreams++;
165 struct ogg_stream *os;
167 ogg->streams = av_realloc (ogg->streams,
168 ogg->nstreams * sizeof (*ogg->streams));
169 memset (ogg->streams + idx, 0, sizeof (*ogg->streams));
170 os = ogg->streams + idx;
172 os->bufsize = DECODER_BUFFER_SIZE;
173 os->buf = av_malloc(os->bufsize);
176 st = av_new_stream (s, idx);
178 return AVERROR(ENOMEM);
180 av_set_pts_info(st, 64, 1, 1000000);
186 ogg_new_buf(struct ogg *ogg, int idx)
188 struct ogg_stream *os = ogg->streams + idx;
189 uint8_t *nb = av_malloc(os->bufsize);
190 int size = os->bufpos - os->pstart;
192 memcpy(nb, os->buf + os->pstart, size);
203 ogg_read_page (AVFormatContext * s, int *str)
205 ByteIOContext *bc = s->pb;
206 struct ogg *ogg = s->priv_data;
207 struct ogg_stream *os;
218 if (get_buffer (bc, sync, 4) < 4)
224 if (sync[sp & 3] == 'O' &&
225 sync[(sp + 1) & 3] == 'g' &&
226 sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
233 }while (i++ < MAX_PAGE_SIZE);
235 if (i >= MAX_PAGE_SIZE){
236 av_log (s, AV_LOG_INFO, "ogg, can't find sync word\n");
240 if (url_fgetc (bc) != 0) /* version */
243 flags = url_fgetc (bc);
245 serial = get_le32 (bc);
248 nsegs = url_fgetc (bc);
250 idx = ogg_find_stream (ogg, serial);
252 idx = ogg_new_stream (s, serial);
257 os = ogg->streams + idx;
260 ogg_new_buf(ogg, idx);
262 if (get_buffer (bc, os->segments, nsegs) < nsegs)
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++];
285 if (os->bufsize - os->bufpos < size){
286 uint8_t *nb = av_malloc (os->bufsize *= 2);
287 memcpy (nb, os->buf, os->bufpos);
292 if (get_buffer (bc, os->buf + os->bufpos, size) < size)
306 ogg_packet (AVFormatContext * s, int *str, int *dstart, int *dsize)
308 struct ogg *ogg = s->priv_data;
310 struct ogg_stream *os;
312 int segp = 0, psize = 0;
315 av_log (s, AV_LOG_DEBUG, "ogg_packet: curidx=%i\n", ogg->curidx);
322 if (ogg_read_page (s, &idx) < 0)
326 os = ogg->streams + idx;
329 av_log (s, AV_LOG_DEBUG,
330 "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
331 idx, os->pstart, os->psize, os->segp, os->nsegs);
336 os->codec = ogg_find_codec (os->buf, os->bufpos);
349 while (os->segp < os->nsegs){
350 int ss = os->segments[os->segp++];
358 if (!complete && os->segp == os->nsegs){
365 av_log (s, AV_LOG_DEBUG,
366 "ogg_packet: idx %i, frame size %i, start %i\n",
367 idx, os->psize, os->pstart);
374 int hdr = os->codec->header (s, idx);
375 os->header = os->seq;
381 os->pstart += os->psize;
386 if (os->header > -1 && os->seq > os->header){
389 if (os->codec && os->codec->packet)
390 os->codec->packet (s, idx);
394 *dstart = os->pstart;
397 os->pstart += os->psize;
401 // determine whether there are more complete packets in this page
402 // if not, the page's granule will apply to this packet
404 for (i = os->segp; i < os->nsegs; i++)
405 if (os->segments[i] < 255) {
411 if (os->segp == os->nsegs)
418 ogg_get_headers (AVFormatContext * s)
420 struct ogg *ogg = s->priv_data;
423 if (ogg_packet (s, NULL, NULL, NULL) < 0)
425 }while (!ogg->headers);
428 av_log (s, AV_LOG_DEBUG, "found headers\n");
435 ogg_gptopts (AVFormatContext * s, int i, uint64_t gp, int64_t *dts)
437 struct ogg *ogg = s->priv_data;
438 struct ogg_stream *os = ogg->streams + i;
439 uint64_t pts = AV_NOPTS_VALUE;
441 if(os->codec->gptopts){
442 pts = os->codec->gptopts(s, i, gp, dts);
454 ogg_get_length (AVFormatContext * s)
456 struct ogg *ogg = s->priv_data;
460 if(url_is_streamed(s->pb))
464 if (s->duration != AV_NOPTS_VALUE)
467 size = url_fsize(s->pb);
470 end = size > MAX_PAGE_SIZE? size - MAX_PAGE_SIZE: 0;
473 url_fseek (s->pb, end, SEEK_SET);
475 while (!ogg_read_page (s, &i)){
476 if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
477 ogg->streams[i].codec)
482 s->streams[idx]->duration =
483 ogg_gptopts (s, idx, ogg->streams[idx].granule, NULL);
494 ogg_read_header (AVFormatContext * s, AVFormatParameters * ap)
496 struct ogg *ogg = s->priv_data;
499 //linear headers seek from start
500 if (ogg_get_headers (s) < 0){
504 for (i = 0; i < ogg->nstreams; i++)
505 if (ogg->streams[i].header < 0)
506 ogg->streams[i].codec = NULL;
508 //linear granulepos seek from end
511 //fill the extradata in the per codec callbacks
517 ogg_read_packet (AVFormatContext * s, AVPacket * pkt)
520 struct ogg_stream *os;
526 if (ogg_packet (s, &idx, &pstart, &psize) < 0)
528 }while (idx < 0 || !s->streams[idx]);
531 os = ogg->streams + idx;
534 if (av_new_packet (pkt, psize) < 0)
536 pkt->stream_index = idx;
537 memcpy (pkt->data, os->buf + pstart, psize);
539 if (os->lastpts != AV_NOPTS_VALUE) {
540 pkt->pts = os->lastpts;
541 os->lastpts = AV_NOPTS_VALUE;
543 if (os->lastdts != AV_NOPTS_VALUE) {
544 pkt->dts = os->lastdts;
545 os->lastdts = AV_NOPTS_VALUE;
548 if (os->granule != -1LL) {
549 if (os->codec && os->codec->granule_is_start)
550 pkt->pts = ogg_gptopts(s, idx, os->granule, &pkt->dts);
552 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
555 av_log(s, AV_LOG_WARNING, "Packet is missing granule\n");
558 pkt->flags = os->pflags;
559 pkt->duration = os->pduration;
566 ogg_read_close (AVFormatContext * s)
568 struct ogg *ogg = s->priv_data;
571 for (i = 0; i < ogg->nstreams; i++){
572 av_free (ogg->streams[i].buf);
573 av_free (ogg->streams[i].private);
575 av_free (ogg->streams);
581 ogg_read_timestamp (AVFormatContext * s, int stream_index, int64_t * pos_arg,
584 struct ogg *ogg = s->priv_data;
585 ByteIOContext *bc = s->pb;
586 int64_t pts = AV_NOPTS_VALUE;
588 url_fseek(bc, *pos_arg, SEEK_SET);
589 while (url_ftell(bc) < pos_limit && !ogg_read_page (s, &i)) {
590 if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
591 ogg->streams[i].codec && i == stream_index) {
592 pts = ogg_gptopts(s, i, ogg->streams[i].granule, NULL);
593 // FIXME: this is the position of the packet after the one with above
595 *pos_arg = url_ftell(bc);
603 static int ogg_probe(AVProbeData *p)
605 if (p->buf[0] == 'O' && p->buf[1] == 'g' &&
606 p->buf[2] == 'g' && p->buf[3] == 'S' &&
607 p->buf[4] == 0x0 && p->buf[5] <= 0x7 )
608 return AVPROBE_SCORE_MAX;
613 AVInputFormat ogg_demuxer = {
615 NULL_IF_CONFIG_SMALL("Ogg"),
624 .metadata_conv = ff_vorbiscomment_metadata_conv,