Statistics
| Branch: | Revision:

ffmpeg / libavformat / ogg2.c @ 4b65d88f

History | View | Annotate | Download (14.3 KB)

1 9146ca37 Måns Rullgård
/*
2
 * Ogg bitstream support
3
 * Luca Barbato <lu_zero@gentoo.org>
4
 * Based on tcvp implementation
5 115329f1 Diego Biurrun
 *
6 9146ca37 Måns Rullgård
 */
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 1ed923ea Måns Rullgård
    &theora_codec,
43 bcfc40ae Måns Rullgård
    &flac_codec,
44 e1203ac0 Måns Rullgård
    &ogm_video_codec,
45
    &ogm_audio_codec,
46
    &ogm_old_codec,
47 9146ca37 Måns Rullgård
    NULL
48
};
49
50 a9e35095 Diego Biurrun
#if 0                           // CONFIG_MUXERS
51 9146ca37 Måns Rullgård
static int
52
ogg_write_header (AVFormatContext * avfcontext)
53
{
54
}
55

56
static int
57
ogg_write_packet (AVFormatContext * avfcontext, AVPacket * pkt)
58
{
59
}
60

61

62
static int
63
ogg_write_trailer (AVFormatContext * avfcontext)
64
{
65
}
66

67

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

640
    if (*pos_arg < 0)
641
        return AV_NOPTS_VALUE;
642

643
    pos = *pos_arg;
644
}
645
#endif
646
647 2e70e4aa Måns Rullgård
static int ogg_probe(AVProbeData *p)
648
{
649
    if (p->buf_size < 6)
650
        return 0;
651
    if (p->buf[0] == 'O' && p->buf[1] == 'g' &&
652
        p->buf[2] == 'g' && p->buf[3] == 'S' &&
653
        p->buf[4] == 0x0 && p->buf[5] <= 0x7 )
654
        return AVPROBE_SCORE_MAX;
655
    else
656
        return 0;
657
}
658
659 ff70e601 Måns Rullgård
AVInputFormat ogg_demuxer = {
660 9146ca37 Måns Rullgård
    "ogg",
661
    "Ogg",
662
    sizeof (ogg_t),
663 2e70e4aa Måns Rullgård
    ogg_probe,
664 9146ca37 Måns Rullgård
    ogg_read_header,
665
    ogg_read_packet,
666
    ogg_read_close,
667
    ogg_read_seek,
668 115329f1 Diego Biurrun
// ogg_read_timestamp,
669 9146ca37 Måns Rullgård
    .extensions = "ogg",
670
};