0c036340422aa4fe5647ee985fff4f0492ef1cd5
[ffmpeg.git] / libavformat / ogg2.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 "ogg2.h"
35 #include "avformat.h"
36
37 #define MAX_PAGE_SIZE 65307
38 #define DECODER_BUFFER_SIZE MAX_PAGE_SIZE
39
40 static ogg_codec_t *ogg_codecs[] = {
41     &vorbis_codec,
42     &theora_codec,
43     &flac_codec,
44     &old_flac_codec,
45     &ogm_video_codec,
46     &ogm_audio_codec,
47     &ogm_old_codec,
48     NULL
49 };
50
51 //FIXME We could avoid some structure duplication
52 static int
53 ogg_save (AVFormatContext * s)
54 {
55     ogg_t *ogg = s->priv_data;
56     ogg_state_t *ost =
57         av_malloc(sizeof (*ost) + (ogg->nstreams-1) * sizeof (*ogg->streams));
58     int i;
59     ost->pos = url_ftell (&s->pb);;
60     ost->curidx = ogg->curidx;
61     ost->next = ogg->state;
62     ost->nstreams = ogg->nstreams;
63     memcpy(ost->streams, ogg->streams, ogg->nstreams * sizeof(*ogg->streams));
64
65     for (i = 0; i < ogg->nstreams; i++){
66         ogg_stream_t *os = ogg->streams + i;
67         os->buf = av_malloc (os->bufsize);
68         memset (os->buf, 0, os->bufsize);
69         memcpy (os->buf, ost->streams[i].buf, os->bufpos);
70     }
71
72     ogg->state = ost;
73
74     return 0;
75 }
76
77 static int
78 ogg_restore (AVFormatContext * s, int discard)
79 {
80     ogg_t *ogg = s->priv_data;
81     ByteIOContext *bc = &s->pb;
82     ogg_state_t *ost = ogg->state;
83     int i;
84
85     if (!ost)
86         return 0;
87
88     ogg->state = ost->next;
89
90     if (!discard){
91         for (i = 0; i < ogg->nstreams; i++)
92             av_free (ogg->streams[i].buf);
93
94         url_fseek (bc, ost->pos, SEEK_SET);
95         ogg->curidx = ost->curidx;
96         ogg->nstreams = ost->nstreams;
97         memcpy(ogg->streams, ost->streams,
98                ost->nstreams * sizeof(*ogg->streams));
99     }
100
101     av_free (ost);
102
103     return 0;
104 }
105
106 static int
107 ogg_reset (ogg_t * ogg)
108 {
109     int i;
110
111     for (i = 0; i < ogg->nstreams; i++){
112         ogg_stream_t *os = ogg->streams + i;
113         os->bufpos = 0;
114         os->pstart = 0;
115         os->psize = 0;
116         os->granule = -1;
117         os->lastgp = -1;
118         os->nsegs = 0;
119         os->segp = 0;
120     }
121
122     ogg->curidx = -1;
123
124     return 0;
125 }
126
127 static ogg_codec_t *
128 ogg_find_codec (uint8_t * buf, int size)
129 {
130     int i;
131
132     for (i = 0; ogg_codecs[i]; i++)
133         if (size >= ogg_codecs[i]->magicsize &&
134             !memcmp (buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize))
135             return ogg_codecs[i];
136
137     return NULL;
138 }
139
140 static int
141 ogg_find_stream (ogg_t * ogg, int serial)
142 {
143     int i;
144
145     for (i = 0; i < ogg->nstreams; i++)
146         if (ogg->streams[i].serial == serial)
147             return i;
148
149     return -1;
150 }
151
152 static int
153 ogg_new_stream (AVFormatContext * s, uint32_t serial)
154 {
155
156     ogg_t *ogg = s->priv_data;
157     int idx = ogg->nstreams++;
158     AVStream *st;
159     ogg_stream_t *os;
160
161     ogg->streams = av_realloc (ogg->streams,
162                                ogg->nstreams * sizeof (*ogg->streams));
163     memset (ogg->streams + idx, 0, sizeof (*ogg->streams));
164     os = ogg->streams + idx;
165     os->serial = serial;
166     os->bufsize = DECODER_BUFFER_SIZE;
167     os->buf = av_malloc(os->bufsize);
168     os->header = -1;
169
170     st = av_new_stream (s, idx);
171     if (!st)
172         return AVERROR(ENOMEM);
173
174     av_set_pts_info(st, 64, 1, 1000000);
175
176     return idx;
177 }
178
179 static int
180 ogg_new_buf(ogg_t *ogg, int idx)
181 {
182     ogg_stream_t *os = ogg->streams + idx;
183     uint8_t *nb = av_malloc(os->bufsize);
184     int size = os->bufpos - os->pstart;
185     if(os->buf){
186         memcpy(nb, os->buf + os->pstart, size);
187         av_free(os->buf);
188     }
189     os->buf = nb;
190     os->bufpos = size;
191     os->pstart = 0;
192
193     return 0;
194 }
195
196 static int
197 ogg_read_page (AVFormatContext * s, int *str)
198 {
199     ByteIOContext *bc = &s->pb;
200     ogg_t *ogg = s->priv_data;
201     ogg_stream_t *os;
202     int i = 0;
203     int flags, nsegs;
204     uint64_t gp;
205     uint32_t serial;
206     uint32_t seq;
207     uint32_t crc;
208     int size, idx;
209     uint8_t sync[4];
210     int sp = 0;
211
212     if (get_buffer (bc, sync, 4) < 4)
213         return -1;
214
215     do{
216         int c;
217
218         if (sync[sp & 3] == 'O' &&
219             sync[(sp + 1) & 3] == 'g' &&
220             sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
221             break;
222
223         c = url_fgetc (bc);
224         if (c < 0)
225             return -1;
226         sync[sp++ & 3] = c;
227     }while (i++ < MAX_PAGE_SIZE);
228
229     if (i >= MAX_PAGE_SIZE){
230         av_log (s, AV_LOG_INFO, "ogg, can't find sync word\n");
231         return -1;
232     }
233
234     if (url_fgetc (bc) != 0)      /* version */
235         return -1;
236
237     flags = url_fgetc (bc);
238     gp = get_le64 (bc);
239     serial = get_le32 (bc);
240     seq = get_le32 (bc);
241     crc = get_le32 (bc);
242     nsegs = url_fgetc (bc);
243
244     idx = ogg_find_stream (ogg, serial);
245     if (idx < 0){
246         idx = ogg_new_stream (s, serial);
247         if (idx < 0)
248             return -1;
249     }
250
251     os = ogg->streams + idx;
252
253     if(os->psize > 0)
254         ogg_new_buf(ogg, idx);
255
256     if (get_buffer (bc, os->segments, nsegs) < nsegs)
257         return -1;
258
259     os->nsegs = nsegs;
260     os->segp = 0;
261
262     size = 0;
263     for (i = 0; i < nsegs; i++)
264         size += os->segments[i];
265
266     if (flags & OGG_FLAG_CONT){
267         if (!os->psize){
268             while (os->segp < os->nsegs){
269                 int seg = os->segments[os->segp++];
270                 os->pstart += seg;
271                 if (seg < 255)
272                   break;
273             }
274         }
275     }else{
276       os->psize = 0;
277     }
278
279     if (os->bufsize - os->bufpos < size){
280         uint8_t *nb = av_malloc (os->bufsize *= 2);
281         memcpy (nb, os->buf, os->bufpos);
282         av_free (os->buf);
283         os->buf = nb;
284     }
285
286     if (get_buffer (bc, os->buf + os->bufpos, size) < size)
287         return -1;
288
289     os->lastgp = os->granule;
290     os->bufpos += size;
291     os->granule = gp;
292     os->flags = flags;
293
294     if (str)
295         *str = idx;
296
297     return 0;
298 }
299
300 static int
301 ogg_packet (AVFormatContext * s, int *str, int *dstart, int *dsize)
302 {
303     ogg_t *ogg = s->priv_data;
304     int idx;
305     ogg_stream_t *os;
306     int complete = 0;
307     int segp = 0, psize = 0;
308
309 #if 0
310     av_log (s, AV_LOG_DEBUG, "ogg_packet: curidx=%i\n", ogg->curidx);
311 #endif
312
313     do{
314         idx = ogg->curidx;
315
316         while (idx < 0){
317             if (ogg_read_page (s, &idx) < 0)
318                 return -1;
319         }
320
321         os = ogg->streams + idx;
322
323 #if 0
324         av_log (s, AV_LOG_DEBUG,
325                 "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
326                 idx, os->pstart, os->psize, os->segp, os->nsegs);
327 #endif
328
329         if (!os->codec){
330             if (os->header < 0){
331                 os->codec = ogg_find_codec (os->buf, os->bufpos);
332                 if (!os->codec){
333                     os->header = 0;
334                     return 0;
335                 }
336             }else{
337                 return 0;
338             }
339         }
340
341         segp = os->segp;
342         psize = os->psize;
343
344         while (os->segp < os->nsegs){
345             int ss = os->segments[os->segp++];
346             os->psize += ss;
347             if (ss < 255){
348                 complete = 1;
349                 break;
350             }
351         }
352
353         if (!complete && os->segp == os->nsegs){
354             ogg->curidx = -1;
355         }
356     }while (!complete);
357
358 #if 0
359     av_log (s, AV_LOG_DEBUG,
360             "ogg_packet: idx %i, frame size %i, start %i\n",
361             idx, os->psize, os->pstart);
362 #endif
363
364     ogg->curidx = idx;
365
366     if (os->header < 0){
367         int hdr = os->codec->header (s, idx);
368         if (!hdr){
369           os->header = os->seq;
370           os->segp = segp;
371           os->psize = psize;
372           ogg->headers = 1;
373         }else{
374           os->pstart += os->psize;
375           os->psize = 0;
376         }
377     }
378
379     if (os->header > -1 && os->seq > os->header){
380         if (os->codec && os->codec->packet)
381             os->codec->packet (s, idx);
382         if (str)
383             *str = idx;
384         if (dstart)
385             *dstart = os->pstart;
386         if (dsize)
387             *dsize = os->psize;
388         os->pstart += os->psize;
389         os->psize = 0;
390     }
391
392     os->seq++;
393     if (os->segp == os->nsegs)
394         ogg->curidx = -1;
395
396     return 0;
397 }
398
399 static int
400 ogg_get_headers (AVFormatContext * s)
401 {
402     ogg_t *ogg = s->priv_data;
403
404     do{
405         if (ogg_packet (s, NULL, NULL, NULL) < 0)
406             return -1;
407     }while (!ogg->headers);
408
409 #if 0
410     av_log (s, AV_LOG_DEBUG, "found headers\n");
411 #endif
412
413     return 0;
414 }
415
416 static uint64_t
417 ogg_gptopts (AVFormatContext * s, int i, uint64_t gp)
418 {
419     ogg_t *ogg = s->priv_data;
420     ogg_stream_t *os = ogg->streams + i;
421     uint64_t pts = AV_NOPTS_VALUE;
422
423     if(os->codec->gptopts){
424         pts = os->codec->gptopts(s, i, gp);
425     } else {
426         pts = gp;
427     }
428
429     return pts;
430 }
431
432
433 static int
434 ogg_get_length (AVFormatContext * s)
435 {
436     ogg_t *ogg = s->priv_data;
437     int idx = -1, i;
438     offset_t size, end;
439
440     if(s->pb.is_streamed)
441         return 0;
442
443 // already set
444     if (s->duration != AV_NOPTS_VALUE)
445         return 0;
446
447     size = url_fsize(&s->pb);
448     if(size < 0)
449         return 0;
450     end = size > MAX_PAGE_SIZE? size - MAX_PAGE_SIZE: size;
451
452     ogg_save (s);
453     url_fseek (&s->pb, end, SEEK_SET);
454
455     while (!ogg_read_page (s, &i)){
456         if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
457             ogg->streams[i].codec)
458             idx = i;
459     }
460
461     if (idx != -1){
462         s->streams[idx]->duration =
463             ogg_gptopts (s, idx, ogg->streams[idx].granule);
464     }
465
466     ogg->size = size;
467     ogg_restore (s, 0);
468     ogg_save (s);
469     while (!ogg_read_page (s, &i)) {
470         if (i == idx && ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0)
471             break;
472     }
473     if (i == idx) {
474         s->streams[idx]->start_time = ogg_gptopts (s, idx, ogg->streams[idx].granule);
475         s->streams[idx]->duration -= s->streams[idx]->start_time;
476     }
477     ogg_restore (s, 0);
478
479     return 0;
480 }
481
482
483 static int
484 ogg_read_header (AVFormatContext * s, AVFormatParameters * ap)
485 {
486     ogg_t *ogg = s->priv_data;
487     ogg->curidx = -1;
488     //linear headers seek from start
489     if (ogg_get_headers (s) < 0){
490       return -1;
491     }
492
493     //linear granulepos seek from end
494     ogg_get_length (s);
495
496     //fill the extradata in the per codec callbacks
497     return 0;
498 }
499
500
501 static int
502 ogg_read_packet (AVFormatContext * s, AVPacket * pkt)
503 {
504     ogg_t *ogg;
505     ogg_stream_t *os;
506     int idx = -1;
507     int pstart, psize;
508
509     //Get an ogg packet
510     do{
511         if (ogg_packet (s, &idx, &pstart, &psize) < 0)
512             return AVERROR(EIO);
513     }while (idx < 0 || !s->streams[idx]);
514
515     ogg = s->priv_data;
516     os = ogg->streams + idx;
517
518     //Alloc a pkt
519     if (av_new_packet (pkt, psize) < 0)
520         return AVERROR(EIO);
521     pkt->stream_index = idx;
522     memcpy (pkt->data, os->buf + pstart, psize);
523     if (os->lastgp != -1LL){
524         pkt->pts = ogg_gptopts (s, idx, os->lastgp);
525         os->lastgp = -1;
526     }
527
528     return psize;
529 }
530
531
532 static int
533 ogg_read_close (AVFormatContext * s)
534 {
535     ogg_t *ogg = s->priv_data;
536     int i;
537
538     for (i = 0; i < ogg->nstreams; i++){
539         av_free (ogg->streams[i].buf);
540         av_free (ogg->streams[i].private);
541     }
542     av_free (ogg->streams);
543     return 0;
544 }
545
546
547 static int64_t
548 ogg_read_timestamp (AVFormatContext * s, int stream_index, int64_t * pos_arg,
549                     int64_t pos_limit)
550 {
551     ogg_t *ogg = s->priv_data;
552     ByteIOContext *bc = &s->pb;
553     int64_t pts = AV_NOPTS_VALUE;
554     int i;
555     url_fseek(bc, *pos_arg, SEEK_SET);
556     while (url_ftell(bc) < pos_limit && !ogg_read_page (s, &i)) {
557         if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
558             ogg->streams[i].codec && i == stream_index) {
559             pts = ogg_gptopts(s, i, ogg->streams[i].granule);
560             // FIXME: this is the position of the packet after the one with above
561             // pts.
562             *pos_arg = url_ftell(bc);
563             break;
564         }
565     }
566     ogg_reset(ogg);
567     return pts;
568 }
569
570 static int ogg_probe(AVProbeData *p)
571 {
572     if (p->buf[0] == 'O' && p->buf[1] == 'g' &&
573         p->buf[2] == 'g' && p->buf[3] == 'S' &&
574         p->buf[4] == 0x0 && p->buf[5] <= 0x7 )
575         return AVPROBE_SCORE_MAX;
576     else
577         return 0;
578 }
579
580 AVInputFormat ogg_demuxer = {
581     "ogg",
582     "Ogg",
583     sizeof (ogg_t),
584     ogg_probe,
585     ogg_read_header,
586     ogg_read_packet,
587     ogg_read_close,
588     NULL,
589     ogg_read_timestamp,
590     .extensions = "ogg",
591 };