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