]> git.sesse.net Git - ffmpeg/blob - libavformat/oggdec.c
mpegts vbr muxing, activated when muxing rate is not supplied by the
[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 /**
9     Copyright (C) 2005  Michael Ahlberg, Måns Rullgård
10
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:
18
19     The above copyright notice and this permission notice shall be
20     included in all copies or substantial portions of the Software.
21
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.
30 **/
31
32
33 #include <stdio.h>
34 #include "oggdec.h"
35 #include "avformat.h"
36
37 #define MAX_PAGE_SIZE 65307
38 #define DECODER_BUFFER_SIZE MAX_PAGE_SIZE
39
40 static const struct ogg_codec * const ogg_codecs[] = {
41     &ff_dirac_codec,
42     &ff_speex_codec,
43     &ff_vorbis_codec,
44     &ff_theora_codec,
45     &ff_flac_codec,
46     &ff_old_dirac_codec,
47     &ff_old_flac_codec,
48     &ff_ogm_video_codec,
49     &ff_ogm_audio_codec,
50     &ff_ogm_text_codec,
51     &ff_ogm_old_codec,
52     NULL
53 };
54
55 //FIXME We could avoid some structure duplication
56 static int
57 ogg_save (AVFormatContext * s)
58 {
59     struct ogg *ogg = s->priv_data;
60     struct ogg_state *ost =
61         av_malloc(sizeof (*ost) + (ogg->nstreams-1) * sizeof (*ogg->streams));
62     int i;
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));
68
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);
74     }
75
76     ogg->state = ost;
77
78     return 0;
79 }
80
81 static int
82 ogg_restore (AVFormatContext * s, int discard)
83 {
84     struct ogg *ogg = s->priv_data;
85     ByteIOContext *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         for (i = 0; i < ogg->nstreams; i++)
96             av_free (ogg->streams[i].buf);
97
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));
103     }
104
105     av_free (ost);
106
107     return 0;
108 }
109
110 static int
111 ogg_reset (struct ogg * ogg)
112 {
113     int i;
114
115     for (i = 0; i < ogg->nstreams; i++){
116         struct ogg_stream *os = ogg->streams + i;
117         os->bufpos = 0;
118         os->pstart = 0;
119         os->psize = 0;
120         os->granule = -1;
121         os->lastpts = AV_NOPTS_VALUE;
122         os->lastdts = AV_NOPTS_VALUE;
123         os->nsegs = 0;
124         os->segp = 0;
125         os->incomplete = 0;
126     }
127
128     ogg->curidx = -1;
129
130     return 0;
131 }
132
133 static const struct ogg_codec *
134 ogg_find_codec (uint8_t * buf, int size)
135 {
136     int i;
137
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];
142
143     return NULL;
144 }
145
146 static int
147 ogg_find_stream (struct ogg * ogg, int serial)
148 {
149     int i;
150
151     for (i = 0; i < ogg->nstreams; i++)
152         if (ogg->streams[i].serial == serial)
153             return i;
154
155     return -1;
156 }
157
158 static int
159 ogg_new_stream (AVFormatContext * s, uint32_t serial)
160 {
161
162     struct ogg *ogg = s->priv_data;
163     int idx = ogg->nstreams++;
164     AVStream *st;
165     struct ogg_stream *os;
166
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;
171     os->serial = serial;
172     os->bufsize = DECODER_BUFFER_SIZE;
173     os->buf = av_malloc(os->bufsize);
174     os->header = -1;
175
176     st = av_new_stream (s, idx);
177     if (!st)
178         return AVERROR(ENOMEM);
179
180     av_set_pts_info(st, 64, 1, 1000000);
181
182     return idx;
183 }
184
185 static int
186 ogg_new_buf(struct ogg *ogg, int idx)
187 {
188     struct ogg_stream *os = ogg->streams + idx;
189     uint8_t *nb = av_malloc(os->bufsize);
190     int size = os->bufpos - os->pstart;
191     if(os->buf){
192         memcpy(nb, os->buf + os->pstart, size);
193         av_free(os->buf);
194     }
195     os->buf = nb;
196     os->bufpos = size;
197     os->pstart = 0;
198
199     return 0;
200 }
201
202 static int
203 ogg_read_page (AVFormatContext * s, int *str)
204 {
205     ByteIOContext *bc = s->pb;
206     struct ogg *ogg = s->priv_data;
207     struct ogg_stream *os;
208     int i = 0;
209     int flags, nsegs;
210     uint64_t gp;
211     uint32_t serial;
212     uint32_t seq;
213     uint32_t crc;
214     int size, idx;
215     uint8_t sync[4];
216     int sp = 0;
217
218     if (get_buffer (bc, sync, 4) < 4)
219         return -1;
220
221     do{
222         int c;
223
224         if (sync[sp & 3] == 'O' &&
225             sync[(sp + 1) & 3] == 'g' &&
226             sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
227             break;
228
229         c = url_fgetc (bc);
230         if (c < 0)
231             return -1;
232         sync[sp++ & 3] = c;
233     }while (i++ < MAX_PAGE_SIZE);
234
235     if (i >= MAX_PAGE_SIZE){
236         av_log (s, AV_LOG_INFO, "ogg, can't find sync word\n");
237         return -1;
238     }
239
240     if (url_fgetc (bc) != 0)      /* version */
241         return -1;
242
243     flags = url_fgetc (bc);
244     gp = get_le64 (bc);
245     serial = get_le32 (bc);
246     seq = get_le32 (bc);
247     crc = get_le32 (bc);
248     nsegs = url_fgetc (bc);
249
250     idx = ogg_find_stream (ogg, serial);
251     if (idx < 0){
252         idx = ogg_new_stream (s, serial);
253         if (idx < 0)
254             return -1;
255     }
256
257     os = ogg->streams + idx;
258
259     if(os->psize > 0)
260         ogg_new_buf(ogg, idx);
261
262     if (get_buffer (bc, os->segments, nsegs) < nsegs)
263         return -1;
264
265     os->nsegs = nsegs;
266     os->segp = 0;
267
268     size = 0;
269     for (i = 0; i < nsegs; i++)
270         size += os->segments[i];
271
272     if (flags & OGG_FLAG_CONT || os->incomplete){
273         if (!os->psize){
274             while (os->segp < os->nsegs){
275                 int seg = os->segments[os->segp++];
276                 os->pstart += seg;
277                 if (seg < 255)
278                     break;
279             }
280         }
281     }else{
282         os->psize = 0;
283     }
284
285     if (os->bufsize - os->bufpos < size){
286         uint8_t *nb = av_malloc (os->bufsize *= 2);
287         memcpy (nb, os->buf, os->bufpos);
288         av_free (os->buf);
289         os->buf = nb;
290     }
291
292     if (get_buffer (bc, os->buf + os->bufpos, size) < size)
293         return -1;
294
295     os->bufpos += size;
296     os->granule = gp;
297     os->flags = flags;
298
299     if (str)
300         *str = idx;
301
302     return 0;
303 }
304
305 static int
306 ogg_packet (AVFormatContext * s, int *str, int *dstart, int *dsize)
307 {
308     struct ogg *ogg = s->priv_data;
309     int idx, i;
310     struct ogg_stream *os;
311     int complete = 0;
312     int segp = 0, psize = 0;
313
314 #if 0
315     av_log (s, AV_LOG_DEBUG, "ogg_packet: curidx=%i\n", ogg->curidx);
316 #endif
317
318     do{
319         idx = ogg->curidx;
320
321         while (idx < 0){
322             if (ogg_read_page (s, &idx) < 0)
323                 return -1;
324         }
325
326         os = ogg->streams + idx;
327
328 #if 0
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);
332 #endif
333
334         if (!os->codec){
335             if (os->header < 0){
336                 os->codec = ogg_find_codec (os->buf, os->bufpos);
337                 if (!os->codec){
338                     os->header = 0;
339                     return 0;
340                 }
341             }else{
342                 return 0;
343             }
344         }
345
346         segp = os->segp;
347         psize = os->psize;
348
349         while (os->segp < os->nsegs){
350             int ss = os->segments[os->segp++];
351             os->psize += ss;
352             if (ss < 255){
353                 complete = 1;
354                 break;
355             }
356         }
357
358         if (!complete && os->segp == os->nsegs){
359             ogg->curidx = -1;
360             os->incomplete = 1;
361         }
362     }while (!complete);
363
364 #if 0
365     av_log (s, AV_LOG_DEBUG,
366             "ogg_packet: idx %i, frame size %i, start %i\n",
367             idx, os->psize, os->pstart);
368 #endif
369
370     ogg->curidx = idx;
371     os->incomplete = 0;
372
373     if (!ogg->headers){
374         int hdr = os->codec->header (s, idx);
375         os->header = os->seq;
376         if (!hdr){
377             os->segp = segp;
378             os->psize = psize;
379             ogg->headers = 1;
380         }else{
381             os->pstart += os->psize;
382             os->psize = 0;
383         }
384     }
385
386     if (os->header > -1 && os->seq > os->header){
387         os->pflags = 0;
388         os->pduration = 0;
389         if (os->codec && os->codec->packet)
390             os->codec->packet (s, idx);
391         if (str)
392             *str = idx;
393         if (dstart)
394             *dstart = os->pstart;
395         if (dsize)
396             *dsize = os->psize;
397         os->pstart += os->psize;
398         os->psize = 0;
399     }
400
401     // determine whether there are more complete packets in this page
402     // if not, the page's granule will apply to this packet
403     os->page_end = 1;
404     for (i = os->segp; i < os->nsegs; i++)
405         if (os->segments[i] < 255) {
406             os->page_end = 0;
407             break;
408         }
409
410     os->seq++;
411     if (os->segp == os->nsegs)
412         ogg->curidx = -1;
413
414     return 0;
415 }
416
417 static int
418 ogg_get_headers (AVFormatContext * s)
419 {
420     struct ogg *ogg = s->priv_data;
421
422     do{
423         if (ogg_packet (s, NULL, NULL, NULL) < 0)
424             return -1;
425     }while (!ogg->headers);
426
427 #if 0
428     av_log (s, AV_LOG_DEBUG, "found headers\n");
429 #endif
430
431     return 0;
432 }
433
434 static uint64_t
435 ogg_gptopts (AVFormatContext * s, int i, uint64_t gp, int64_t *dts)
436 {
437     struct ogg *ogg = s->priv_data;
438     struct ogg_stream *os = ogg->streams + i;
439     uint64_t pts = AV_NOPTS_VALUE;
440
441     if(os->codec->gptopts){
442         pts = os->codec->gptopts(s, i, gp, dts);
443     } else {
444         pts = gp;
445         if (dts)
446             *dts = pts;
447     }
448
449     return pts;
450 }
451
452
453 static int
454 ogg_get_length (AVFormatContext * s)
455 {
456     struct ogg *ogg = s->priv_data;
457     int idx = -1, i;
458     int64_t size, end;
459
460     if(url_is_streamed(s->pb))
461         return 0;
462
463 // already set
464     if (s->duration != AV_NOPTS_VALUE)
465         return 0;
466
467     size = url_fsize(s->pb);
468     if(size < 0)
469         return 0;
470     end = size > MAX_PAGE_SIZE? size - MAX_PAGE_SIZE: 0;
471
472     ogg_save (s);
473     url_fseek (s->pb, end, SEEK_SET);
474
475     while (!ogg_read_page (s, &i)){
476         if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
477             ogg->streams[i].codec)
478             idx = i;
479     }
480
481     if (idx != -1){
482         s->streams[idx]->duration =
483             ogg_gptopts (s, idx, ogg->streams[idx].granule, NULL);
484     }
485
486     ogg->size = size;
487     ogg_restore (s, 0);
488
489     return 0;
490 }
491
492
493 static int
494 ogg_read_header (AVFormatContext * s, AVFormatParameters * ap)
495 {
496     struct ogg *ogg = s->priv_data;
497     int i;
498     ogg->curidx = -1;
499     //linear headers seek from start
500     if (ogg_get_headers (s) < 0){
501         return -1;
502     }
503
504     for (i = 0; i < ogg->nstreams; i++)
505         if (ogg->streams[i].header < 0)
506             ogg->streams[i].codec = NULL;
507
508     //linear granulepos seek from end
509     ogg_get_length (s);
510
511     //fill the extradata in the per codec callbacks
512     return 0;
513 }
514
515
516 static int
517 ogg_read_packet (AVFormatContext * s, AVPacket * pkt)
518 {
519     struct ogg *ogg;
520     struct ogg_stream *os;
521     int idx = -1;
522     int pstart, psize;
523
524     //Get an ogg packet
525     do{
526         if (ogg_packet (s, &idx, &pstart, &psize) < 0)
527             return AVERROR(EIO);
528     }while (idx < 0 || !s->streams[idx]);
529
530     ogg = s->priv_data;
531     os = ogg->streams + idx;
532
533     //Alloc a pkt
534     if (av_new_packet (pkt, psize) < 0)
535         return AVERROR(EIO);
536     pkt->stream_index = idx;
537     memcpy (pkt->data, os->buf + pstart, psize);
538
539     if (os->lastpts != AV_NOPTS_VALUE) {
540         pkt->pts = os->lastpts;
541         os->lastpts = AV_NOPTS_VALUE;
542     }
543     if (os->lastdts != AV_NOPTS_VALUE) {
544         pkt->dts = os->lastdts;
545         os->lastdts = AV_NOPTS_VALUE;
546     }
547     if (os->page_end) {
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);
551             else
552                 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
553             os->granule = -1LL;
554         } else
555             av_log(s, AV_LOG_WARNING, "Packet is missing granule\n");
556     }
557
558     pkt->flags = os->pflags;
559     pkt->duration = os->pduration;
560
561     return psize;
562 }
563
564
565 static int
566 ogg_read_close (AVFormatContext * s)
567 {
568     struct ogg *ogg = s->priv_data;
569     int i;
570
571     for (i = 0; i < ogg->nstreams; i++){
572         av_free (ogg->streams[i].buf);
573         av_free (ogg->streams[i].private);
574     }
575     av_free (ogg->streams);
576     return 0;
577 }
578
579
580 static int64_t
581 ogg_read_timestamp (AVFormatContext * s, int stream_index, int64_t * pos_arg,
582                     int64_t pos_limit)
583 {
584     struct ogg *ogg = s->priv_data;
585     ByteIOContext *bc = s->pb;
586     int64_t pts = AV_NOPTS_VALUE;
587     int i;
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
594             // pts.
595             *pos_arg = url_ftell(bc);
596             break;
597         }
598     }
599     ogg_reset(ogg);
600     return pts;
601 }
602
603 static int ogg_probe(AVProbeData *p)
604 {
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;
609     else
610         return 0;
611 }
612
613 AVInputFormat ogg_demuxer = {
614     "ogg",
615     NULL_IF_CONFIG_SMALL("Ogg"),
616     sizeof (struct ogg),
617     ogg_probe,
618     ogg_read_header,
619     ogg_read_packet,
620     ogg_read_close,
621     NULL,
622     ogg_read_timestamp,
623     .extensions = "ogg",
624     .metadata_conv = ff_vorbiscomment_metadata_conv,
625 };