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
59 ogg_save (AVFormatContext
* s
)
61 struct ogg
*ogg
= s
->priv_data
;
62 struct ogg_state
*ost
=
63 av_malloc(sizeof (*ost
) + (ogg
->nstreams
-1) * sizeof (*ogg
->streams
));
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
));
71 for (i
= 0; i
< ogg
->nstreams
; i
++){
72 struct ogg_stream
*os
= ogg
->streams
+ i
;
73 os
->buf
= av_malloc (os
->bufsize
);
74 memset (os
->buf
, 0, os
->bufsize
);
75 memcpy (os
->buf
, ost
->streams
[i
].buf
, os
->bufpos
);
84 ogg_restore (AVFormatContext
* s
, int discard
)
86 struct ogg
*ogg
= s
->priv_data
;
87 AVIOContext
*bc
= s
->pb
;
88 struct ogg_state
*ost
= ogg
->state
;
94 ogg
->state
= ost
->next
;
97 for (i
= 0; i
< ogg
->nstreams
; i
++)
98 av_free (ogg
->streams
[i
].buf
);
100 avio_seek (bc
, ost
->pos
, SEEK_SET
);
101 ogg
->curidx
= ost
->curidx
;
102 ogg
->nstreams
= ost
->nstreams
;
103 memcpy(ogg
->streams
, ost
->streams
,
104 ost
->nstreams
* sizeof(*ogg
->streams
));
113 ogg_reset (struct ogg
* ogg
)
117 for (i
= 0; i
< ogg
->nstreams
; i
++){
118 struct ogg_stream
*os
= ogg
->streams
+ i
;
123 os
->lastpts
= AV_NOPTS_VALUE
;
124 os
->lastdts
= AV_NOPTS_VALUE
;
137 static const struct ogg_codec
*
138 ogg_find_codec (uint8_t * buf
, int size
)
142 for (i
= 0; ogg_codecs
[i
]; i
++)
143 if (size
>= ogg_codecs
[i
]->magicsize
&&
144 !memcmp (buf
, ogg_codecs
[i
]->magic
, ogg_codecs
[i
]->magicsize
))
145 return ogg_codecs
[i
];
151 ogg_new_stream (AVFormatContext
* s
, uint32_t serial
)
154 struct ogg
*ogg
= s
->priv_data
;
155 int idx
= ogg
->nstreams
++;
157 struct ogg_stream
*os
;
159 ogg
->streams
= av_realloc (ogg
->streams
,
160 ogg
->nstreams
* sizeof (*ogg
->streams
));
161 memset (ogg
->streams
+ idx
, 0, sizeof (*ogg
->streams
));
162 os
= ogg
->streams
+ idx
;
164 os
->bufsize
= DECODER_BUFFER_SIZE
;
165 os
->buf
= av_malloc(os
->bufsize
);
168 st
= av_new_stream (s
, idx
);
170 return AVERROR(ENOMEM
);
172 av_set_pts_info(st
, 64, 1, 1000000);
178 ogg_new_buf(struct ogg
*ogg
, int idx
)
180 struct ogg_stream
*os
= ogg
->streams
+ idx
;
181 uint8_t *nb
= av_malloc(os
->bufsize
);
182 int size
= os
->bufpos
- os
->pstart
;
184 memcpy(nb
, os
->buf
+ os
->pstart
, size
);
195 ogg_read_page (AVFormatContext
* s
, int *str
)
197 AVIOContext
*bc
= s
->pb
;
198 struct ogg
*ogg
= s
->priv_data
;
199 struct ogg_stream
*os
;
210 if (avio_read (bc
, sync
, 4) < 4)
216 if (sync
[sp
& 3] == 'O' &&
217 sync
[(sp
+ 1) & 3] == 'g' &&
218 sync
[(sp
+ 2) & 3] == 'g' && sync
[(sp
+ 3) & 3] == 'S')
225 }while (i
++ < MAX_PAGE_SIZE
);
227 if (i
>= MAX_PAGE_SIZE
){
228 av_log (s
, AV_LOG_INFO
, "ogg, can't find sync word\n");
232 if (avio_r8(bc
) != 0) /* version */
237 serial
= avio_rl32 (bc
);
238 seq
= avio_rl32 (bc
);
239 crc
= avio_rl32 (bc
);
242 idx
= ogg_find_stream (ogg
, serial
);
247 for (n
= 0; n
< ogg
->nstreams
; n
++) {
248 av_freep(&ogg
->streams
[n
].buf
);
249 av_freep(&ogg
->streams
[n
].private);
254 idx
= ogg_new_stream (s
, serial
);
259 os
= ogg
->streams
+ idx
;
260 os
->page_pos
= avio_tell(bc
) - 27;
263 ogg_new_buf(ogg
, idx
);
265 if (avio_read (bc
, os
->segments
, nsegs
) < nsegs
)
272 for (i
= 0; i
< nsegs
; i
++)
273 size
+= os
->segments
[i
];
275 if (flags
& OGG_FLAG_CONT
|| os
->incomplete
){
277 while (os
->segp
< os
->nsegs
){
278 int seg
= os
->segments
[os
->segp
++];
283 os
->sync_pos
= os
->page_pos
;
287 os
->sync_pos
= os
->page_pos
;
290 if (os
->bufsize
- os
->bufpos
< size
){
291 uint8_t *nb
= av_malloc (os
->bufsize
*= 2);
292 memcpy (nb
, os
->buf
, os
->bufpos
);
297 if (avio_read (bc
, os
->buf
+ os
->bufpos
, size
) < size
)
311 ogg_packet (AVFormatContext
* s
, int *str
, int *dstart
, int *dsize
, int64_t *fpos
)
313 struct ogg
*ogg
= s
->priv_data
;
315 struct ogg_stream
*os
;
317 int segp
= 0, psize
= 0;
320 av_log (s
, AV_LOG_DEBUG
, "ogg_packet: curidx=%i\n", ogg
->curidx
);
327 if (ogg_read_page (s
, &idx
) < 0)
331 os
= ogg
->streams
+ idx
;
334 av_log (s
, AV_LOG_DEBUG
,
335 "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
336 idx
, os
->pstart
, os
->psize
, os
->segp
, os
->nsegs
);
341 os
->codec
= ogg_find_codec (os
->buf
, os
->bufpos
);
354 while (os
->segp
< os
->nsegs
){
355 int ss
= os
->segments
[os
->segp
++];
363 if (!complete
&& os
->segp
== os
->nsegs
){
370 av_log (s
, AV_LOG_DEBUG
,
371 "ogg_packet: idx %i, frame size %i, start %i\n",
372 idx
, os
->psize
, os
->pstart
);
375 if (os
->granule
== -1)
376 av_log(s
, AV_LOG_WARNING
, "Page at %"PRId64
" is missing granule\n", os
->page_pos
);
382 os
->header
= os
->codec
->header (s
, idx
);
387 // We have reached the first non-header packet in this stream.
388 // Unfortunately more header packets may still follow for others,
389 // so we reset this later unless we are done with the headers
393 // Update the header state for all streams and
394 // compute the data_offset.
396 s
->data_offset
= os
->sync_pos
;
397 for (i
= 0; i
< ogg
->nstreams
; i
++) {
398 struct ogg_stream
*cur_os
= ogg
->streams
+ i
;
399 if (cur_os
->header
> 0)
402 // if we have a partial non-header packet, its start is
403 // obviously at or after the data start
404 if (cur_os
->incomplete
)
405 s
->data_offset
= FFMIN(s
->data_offset
, cur_os
->sync_pos
);
408 os
->pstart
+= os
->psize
;
414 if (os
->codec
&& os
->codec
->packet
)
415 os
->codec
->packet (s
, idx
);
419 *dstart
= os
->pstart
;
423 *fpos
= os
->sync_pos
;
424 os
->pstart
+= os
->psize
;
426 os
->sync_pos
= os
->page_pos
;
429 // determine whether there are more complete packets in this page
430 // if not, the page's granule will apply to this packet
432 for (i
= os
->segp
; i
< os
->nsegs
; i
++)
433 if (os
->segments
[i
] < 255) {
438 if (os
->segp
== os
->nsegs
)
445 ogg_get_headers (AVFormatContext
* s
)
447 struct ogg
*ogg
= s
->priv_data
;
450 if (ogg_packet (s
, NULL
, NULL
, NULL
, NULL
) < 0)
452 }while (!ogg
->headers
);
455 av_log (s
, AV_LOG_DEBUG
, "found headers\n");
462 ogg_get_length (AVFormatContext
* s
)
464 struct ogg
*ogg
= s
->priv_data
;
472 if (s
->duration
!= AV_NOPTS_VALUE
)
475 size
= avio_size(s
->pb
);
478 end
= size
> MAX_PAGE_SIZE? size
- MAX_PAGE_SIZE
: 0;
481 avio_seek (s
->pb
, end
, SEEK_SET
);
483 while (!ogg_read_page (s
, &i
)){
484 if (ogg
->streams
[i
].granule
!= -1 && ogg
->streams
[i
].granule
!= 0 &&
485 ogg
->streams
[i
].codec
) {
486 s
->streams
[i
]->duration
=
487 ogg_gptopts (s
, i
, ogg
->streams
[i
].granule
, NULL
);
488 if (s
->streams
[i
]->start_time
!= AV_NOPTS_VALUE
)
489 s
->streams
[i
]->duration
-= s
->streams
[i
]->start_time
;
500 ogg_read_header (AVFormatContext
* s
, AVFormatParameters
* ap
)
502 struct ogg
*ogg
= s
->priv_data
;
505 //linear headers seek from start
506 if (ogg_get_headers (s
) < 0){
510 for (i
= 0; i
< ogg
->nstreams
; i
++)
511 if (ogg
->streams
[i
].header
< 0)
512 ogg
->streams
[i
].codec
= NULL
;
514 //linear granulepos seek from end
517 //fill the extradata in the per codec callbacks
521 static int64_t ogg_calc_pts(AVFormatContext
*s
, int idx
, int64_t *dts
)
523 struct ogg
*ogg
= s
->priv_data
;
524 struct ogg_stream
*os
= ogg
->streams
+ idx
;
525 int64_t pts
= AV_NOPTS_VALUE
;
528 *dts
= AV_NOPTS_VALUE
;
530 if (os
->lastpts
!= AV_NOPTS_VALUE
) {
532 os
->lastpts
= AV_NOPTS_VALUE
;
534 if (os
->lastdts
!= AV_NOPTS_VALUE
) {
537 os
->lastdts
= AV_NOPTS_VALUE
;
540 if (os
->granule
!= -1LL) {
541 if (os
->codec
&& os
->codec
->granule_is_start
)
542 pts
= ogg_gptopts(s
, idx
, os
->granule
, dts
);
544 os
->lastpts
= ogg_gptopts(s
, idx
, os
->granule
, &os
->lastdts
);
552 ogg_read_packet (AVFormatContext
* s
, AVPacket
* pkt
)
555 struct ogg_stream
*os
;
558 int64_t fpos
, pts
, dts
;
563 if (ogg_packet (s
, &idx
, &pstart
, &psize
, &fpos
) < 0)
565 }while (idx
< 0 || !s
->streams
[idx
]);
568 os
= ogg
->streams
+ idx
;
570 // pflags might not be set until after this
571 pts
= ogg_calc_pts(s
, idx
, &dts
);
573 if (os
->keyframe_seek
&& !(os
->pflags
& AV_PKT_FLAG_KEY
))
575 os
->keyframe_seek
= 0;
578 if (av_new_packet (pkt
, psize
) < 0)
580 pkt
->stream_index
= idx
;
581 memcpy (pkt
->data
, os
->buf
+ pstart
, psize
);
585 pkt
->flags
= os
->pflags
;
586 pkt
->duration
= os
->pduration
;
594 ogg_read_close (AVFormatContext
* s
)
596 struct ogg
*ogg
= s
->priv_data
;
599 for (i
= 0; i
< ogg
->nstreams
; i
++){
600 av_free (ogg
->streams
[i
].buf
);
601 av_free (ogg
->streams
[i
].private);
603 av_free (ogg
->streams
);
609 ogg_read_timestamp (AVFormatContext
* s
, int stream_index
, int64_t * pos_arg
,
612 struct ogg
*ogg
= s
->priv_data
;
613 struct ogg_stream
*os
= ogg
->streams
+ stream_index
;
614 AVIOContext
*bc
= s
->pb
;
615 int64_t pts
= AV_NOPTS_VALUE
;
617 avio_seek(bc
, *pos_arg
, SEEK_SET
);
620 while (avio_tell(bc
) < pos_limit
&& !ogg_packet(s
, &i
, NULL
, NULL
, pos_arg
)) {
621 if (i
== stream_index
) {
622 pts
= ogg_calc_pts(s
, i
, NULL
);
623 if (os
->keyframe_seek
&& !(os
->pflags
& AV_PKT_FLAG_KEY
))
624 pts
= AV_NOPTS_VALUE
;
626 if (pts
!= AV_NOPTS_VALUE
)
633 static int ogg_read_seek(AVFormatContext
*s
, int stream_index
, int64_t timestamp
, int flags
)
635 struct ogg
*ogg
= s
->priv_data
;
636 struct ogg_stream
*os
= ogg
->streams
+ stream_index
;
639 // Try seeking to a keyframe first. If this fails (very possible),
640 // av_seek_frame will fall back to ignoring keyframes
641 if (s
->streams
[stream_index
]->codec
->codec_type
== AVMEDIA_TYPE_VIDEO
642 && !(flags
& AVSEEK_FLAG_ANY
))
643 os
->keyframe_seek
= 1;
645 ret
= av_seek_frame_binary(s
, stream_index
, timestamp
, flags
);
647 os
->keyframe_seek
= 0;
651 static int ogg_probe(AVProbeData
*p
)
653 if (p
->buf
[0] == 'O' && p
->buf
[1] == 'g' &&
654 p
->buf
[2] == 'g' && p
->buf
[3] == 'S' &&
655 p
->buf
[4] == 0x0 && p
->buf
[5] <= 0x7 )
656 return AVPROBE_SCORE_MAX
;
661 AVInputFormat ff_ogg_demuxer
= {
663 NULL_IF_CONFIG_SMALL("Ogg"),
672 .flags
= AVFMT_GENERIC_INDEX
,