Statistics
| Branch: | Revision:

ffmpeg / libavformat / oggdec.c @ 47dec30e

History | View | Annotate | Download (16.6 KB)

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
#include "vorbiscomment.h"
37

    
38
#define MAX_PAGE_SIZE 65307
39
#define DECODER_BUFFER_SIZE MAX_PAGE_SIZE
40

    
41
static const struct ogg_codec * const ogg_codecs[] = {
42
    &ff_skeleton_codec,
43
    &ff_dirac_codec,
44
    &ff_speex_codec,
45
    &ff_vorbis_codec,
46
    &ff_theora_codec,
47
    &ff_flac_codec,
48
    &ff_old_dirac_codec,
49
    &ff_old_flac_codec,
50
    &ff_ogm_video_codec,
51
    &ff_ogm_audio_codec,
52
    &ff_ogm_text_codec,
53
    &ff_ogm_old_codec,
54
    NULL
55
};
56

    
57
//FIXME We could avoid some structure duplication
58
static int
59
ogg_save (AVFormatContext * s)
60
{
61
    struct ogg *ogg = s->priv_data;
62
    struct ogg_state *ost =
63
        av_malloc(sizeof (*ost) + (ogg->nstreams-1) * sizeof (*ogg->streams));
64
    int i;
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));
70

    
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);
76
    }
77

    
78
    ogg->state = ost;
79

    
80
    return 0;
81
}
82

    
83
static int
84
ogg_restore (AVFormatContext * s, int discard)
85
{
86
    struct ogg *ogg = s->priv_data;
87
    AVIOContext *bc = s->pb;
88
    struct ogg_state *ost = ogg->state;
89
    int i;
90

    
91
    if (!ost)
92
        return 0;
93

    
94
    ogg->state = ost->next;
95

    
96
    if (!discard){
97
        for (i = 0; i < ogg->nstreams; i++)
98
            av_free (ogg->streams[i].buf);
99

    
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));
105
    }
106

    
107
    av_free (ost);
108

    
109
    return 0;
110
}
111

    
112
static int
113
ogg_reset (struct ogg * ogg)
114
{
115
    int i;
116

    
117
    for (i = 0; i < ogg->nstreams; i++){
118
        struct ogg_stream *os = ogg->streams + i;
119
        os->bufpos = 0;
120
        os->pstart = 0;
121
        os->psize = 0;
122
        os->granule = -1;
123
        os->lastpts = AV_NOPTS_VALUE;
124
        os->lastdts = AV_NOPTS_VALUE;
125
        os->sync_pos = -1;
126
        os->page_pos = 0;
127
        os->nsegs = 0;
128
        os->segp = 0;
129
        os->incomplete = 0;
130
    }
131

    
132
    ogg->curidx = -1;
133

    
134
    return 0;
135
}
136

    
137
static const struct ogg_codec *
138
ogg_find_codec (uint8_t * buf, int size)
139
{
140
    int i;
141

    
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];
146

    
147
    return NULL;
148
}
149

    
150
static int
151
ogg_new_stream (AVFormatContext * s, uint32_t serial)
152
{
153

    
154
    struct ogg *ogg = s->priv_data;
155
    int idx = ogg->nstreams++;
156
    AVStream *st;
157
    struct ogg_stream *os;
158

    
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;
163
    os->serial = serial;
164
    os->bufsize = DECODER_BUFFER_SIZE;
165
    os->buf = av_malloc(os->bufsize);
166
    os->header = -1;
167
    os->page_begin = 1;
168

    
169
    st = av_new_stream (s, idx);
170
    if (!st)
171
        return AVERROR(ENOMEM);
172

    
173
    av_set_pts_info(st, 64, 1, 1000000);
174

    
175
    return idx;
176
}
177

    
178
static int
179
ogg_new_buf(struct ogg *ogg, int idx)
180
{
181
    struct ogg_stream *os = ogg->streams + idx;
182
    uint8_t *nb = av_malloc(os->bufsize);
183
    int size = os->bufpos - os->pstart;
184
    if(os->buf){
185
        memcpy(nb, os->buf + os->pstart, size);
186
        av_free(os->buf);
187
    }
188
    os->buf = nb;
189
    os->bufpos = size;
190
    os->pstart = 0;
191

    
192
    return 0;
193
}
194

    
195
static int
196
ogg_read_page (AVFormatContext * s, int *str)
197
{
198
    AVIOContext *bc = s->pb;
199
    struct ogg *ogg = s->priv_data;
200
    struct ogg_stream *os;
201
    int i = 0;
202
    int flags, nsegs;
203
    uint64_t gp;
204
    uint32_t serial;
205
    uint32_t seq;
206
    uint32_t crc;
207
    int size, idx;
208
    uint8_t sync[4];
209
    int sp = 0;
210

    
211
    if (avio_read (bc, sync, 4) < 4)
212
        return -1;
213

    
214
    do{
215
        int c;
216

    
217
        if (sync[sp & 3] == 'O' &&
218
            sync[(sp + 1) & 3] == 'g' &&
219
            sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
220
            break;
221

    
222
        c = avio_r8(bc);
223
        if (bc->eof_reached)
224
            return -1;
225
        sync[sp++ & 3] = c;
226
    }while (i++ < MAX_PAGE_SIZE);
227

    
228
    if (i >= MAX_PAGE_SIZE){
229
        av_log (s, AV_LOG_INFO, "ogg, can't find sync word\n");
230
        return -1;
231
    }
232

    
233
    if (avio_r8(bc) != 0)      /* version */
234
        return -1;
235

    
236
    flags = avio_r8(bc);
237
    gp = avio_rl64 (bc);
238
    serial = avio_rl32 (bc);
239
    seq = avio_rl32 (bc);
240
    crc = avio_rl32 (bc);
241
    nsegs = avio_r8(bc);
242

    
243
    idx = ogg_find_stream (ogg, serial);
244
    if (idx < 0){
245
        for (i = 0; i < ogg->nstreams; i++) {
246
            if (!ogg->streams[i].page_begin) {
247
                int n;
248

    
249
                for (n = 0; n < ogg->nstreams; n++) {
250
                    av_free(ogg->streams[n].buf);
251
                    av_free(ogg->streams[n].private);
252
                }
253
                ogg->curidx   = -1;
254
                ogg->nstreams = 0;
255
                break;
256
            }
257
        }
258
        idx = ogg_new_stream (s, serial);
259
        if (idx < 0)
260
            return -1;
261
    }
262

    
263
    os = ogg->streams + idx;
264
    if (!(flags & OGG_FLAG_BOS))
265
        os->page_begin = 0;
266
    os->page_pos = avio_tell(bc) - 27;
267

    
268
    if(os->psize > 0)
269
        ogg_new_buf(ogg, idx);
270

    
271
    if (avio_read (bc, os->segments, nsegs) < nsegs)
272
        return -1;
273

    
274
    os->nsegs = nsegs;
275
    os->segp = 0;
276

    
277
    size = 0;
278
    for (i = 0; i < nsegs; i++)
279
        size += os->segments[i];
280

    
281
    if (flags & OGG_FLAG_CONT || os->incomplete){
282
        if (!os->psize){
283
            while (os->segp < os->nsegs){
284
                int seg = os->segments[os->segp++];
285
                os->pstart += seg;
286
                if (seg < 255)
287
                    break;
288
            }
289
            os->sync_pos = os->page_pos;
290
        }
291
    }else{
292
        os->psize = 0;
293
        os->sync_pos = os->page_pos;
294
    }
295

    
296
    if (os->bufsize - os->bufpos < size){
297
        uint8_t *nb = av_malloc (os->bufsize *= 2);
298
        memcpy (nb, os->buf, os->bufpos);
299
        av_free (os->buf);
300
        os->buf = nb;
301
    }
302

    
303
    if (avio_read (bc, os->buf + os->bufpos, size) < size)
304
        return -1;
305

    
306
    os->bufpos += size;
307
    os->granule = gp;
308
    os->flags = flags;
309

    
310
    if (str)
311
        *str = idx;
312

    
313
    return 0;
314
}
315

    
316
static int
317
ogg_packet (AVFormatContext * s, int *str, int *dstart, int *dsize, int64_t *fpos)
318
{
319
    struct ogg *ogg = s->priv_data;
320
    int idx, i;
321
    struct ogg_stream *os;
322
    int complete = 0;
323
    int segp = 0, psize = 0;
324

    
325
#if 0
326
    av_log (s, AV_LOG_DEBUG, "ogg_packet: curidx=%i\n", ogg->curidx);
327
#endif
328

    
329
    do{
330
        idx = ogg->curidx;
331

    
332
        while (idx < 0){
333
            if (ogg_read_page (s, &idx) < 0)
334
                return -1;
335
        }
336

    
337
        os = ogg->streams + idx;
338

    
339
#if 0
340
        av_log (s, AV_LOG_DEBUG,
341
                "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
342
                idx, os->pstart, os->psize, os->segp, os->nsegs);
343
#endif
344

    
345
        if (!os->codec){
346
            if (os->header < 0){
347
                os->codec = ogg_find_codec (os->buf, os->bufpos);
348
                if (!os->codec){
349
                    os->header = 0;
350
                    return 0;
351
                }
352
            }else{
353
                return 0;
354
            }
355
        }
356

    
357
        segp = os->segp;
358
        psize = os->psize;
359

    
360
        while (os->segp < os->nsegs){
361
            int ss = os->segments[os->segp++];
362
            os->psize += ss;
363
            if (ss < 255){
364
                complete = 1;
365
                break;
366
            }
367
        }
368

    
369
        if (!complete && os->segp == os->nsegs){
370
            ogg->curidx = -1;
371
            os->incomplete = 1;
372
        }
373
    }while (!complete);
374

    
375
#if 0
376
    av_log (s, AV_LOG_DEBUG,
377
            "ogg_packet: idx %i, frame size %i, start %i\n",
378
            idx, os->psize, os->pstart);
379
#endif
380

    
381
    if (os->granule == -1)
382
        av_log(s, AV_LOG_WARNING, "Page at %"PRId64" is missing granule\n", os->page_pos);
383

    
384
    ogg->curidx = idx;
385
    os->incomplete = 0;
386

    
387
    if (os->header) {
388
        os->header = os->codec->header (s, idx);
389
        if (!os->header){
390
            os->segp = segp;
391
            os->psize = psize;
392

    
393
            // We have reached the first non-header packet in this stream.
394
            // Unfortunately more header packets may still follow for others,
395
            // so we reset this later unless we are done with the headers
396
            // for all streams.
397
            ogg->headers = 1;
398

    
399
            // Update the header state for all streams and
400
            // compute the data_offset.
401
            if (!s->data_offset)
402
                s->data_offset = os->sync_pos;
403
            for (i = 0; i < ogg->nstreams; i++) {
404
                struct ogg_stream *cur_os = ogg->streams + i;
405
                if (cur_os->header > 0)
406
                    ogg->headers = 0;
407

    
408
                // if we have a partial non-header packet, its start is
409
                // obviously at or after the data start
410
                if (cur_os->incomplete)
411
                    s->data_offset = FFMIN(s->data_offset, cur_os->sync_pos);
412
            }
413
        }else{
414
            os->pstart += os->psize;
415
            os->psize = 0;
416
        }
417
    } else {
418
        os->pflags = 0;
419
        os->pduration = 0;
420
        if (os->codec && os->codec->packet)
421
            os->codec->packet (s, idx);
422
        if (str)
423
            *str = idx;
424
        if (dstart)
425
            *dstart = os->pstart;
426
        if (dsize)
427
            *dsize = os->psize;
428
        if (fpos)
429
            *fpos = os->sync_pos;
430
        os->pstart += os->psize;
431
        os->psize = 0;
432
        os->sync_pos = os->page_pos;
433
    }
434

    
435
    // determine whether there are more complete packets in this page
436
    // if not, the page's granule will apply to this packet
437
    os->page_end = 1;
438
    for (i = os->segp; i < os->nsegs; i++)
439
        if (os->segments[i] < 255) {
440
            os->page_end = 0;
441
            break;
442
        }
443

    
444
    if (os->segp == os->nsegs)
445
        ogg->curidx = -1;
446

    
447
    return 0;
448
}
449

    
450
static int
451
ogg_get_headers (AVFormatContext * s)
452
{
453
    struct ogg *ogg = s->priv_data;
454

    
455
    do{
456
        if (ogg_packet (s, NULL, NULL, NULL, NULL) < 0)
457
            return -1;
458
    }while (!ogg->headers);
459

    
460
#if 0
461
    av_log (s, AV_LOG_DEBUG, "found headers\n");
462
#endif
463

    
464
    return 0;
465
}
466

    
467
static int
468
ogg_get_length (AVFormatContext * s)
469
{
470
    struct ogg *ogg = s->priv_data;
471
    int i;
472
    int64_t size, end;
473

    
474
    if(!s->pb->seekable)
475
        return 0;
476

    
477
// already set
478
    if (s->duration != AV_NOPTS_VALUE)
479
        return 0;
480

    
481
    size = avio_size(s->pb);
482
    if(size < 0)
483
        return 0;
484
    end = size > MAX_PAGE_SIZE? size - MAX_PAGE_SIZE: 0;
485

    
486
    ogg_save (s);
487
    avio_seek (s->pb, end, SEEK_SET);
488

    
489
    while (!ogg_read_page (s, &i)){
490
        if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
491
            ogg->streams[i].codec) {
492
            s->streams[i]->duration =
493
                ogg_gptopts (s, i, ogg->streams[i].granule, NULL);
494
            if (s->streams[i]->start_time != AV_NOPTS_VALUE)
495
                s->streams[i]->duration -= s->streams[i]->start_time;
496
        }
497
    }
498

    
499
    ogg_restore (s, 0);
500

    
501
    return 0;
502
}
503

    
504

    
505
static int
506
ogg_read_header (AVFormatContext * s, AVFormatParameters * ap)
507
{
508
    struct ogg *ogg = s->priv_data;
509
    int i;
510
    ogg->curidx = -1;
511
    //linear headers seek from start
512
    if (ogg_get_headers (s) < 0){
513
        return -1;
514
    }
515

    
516
    for (i = 0; i < ogg->nstreams; i++)
517
        if (ogg->streams[i].header < 0)
518
            ogg->streams[i].codec = NULL;
519

    
520
    //linear granulepos seek from end
521
    ogg_get_length (s);
522

    
523
    //fill the extradata in the per codec callbacks
524
    return 0;
525
}
526

    
527
static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
528
{
529
    struct ogg *ogg = s->priv_data;
530
    struct ogg_stream *os = ogg->streams + idx;
531
    int64_t pts = AV_NOPTS_VALUE;
532

    
533
    if (dts)
534
        *dts = AV_NOPTS_VALUE;
535

    
536
    if (os->lastpts != AV_NOPTS_VALUE) {
537
        pts = os->lastpts;
538
        os->lastpts = AV_NOPTS_VALUE;
539
    }
540
    if (os->lastdts != AV_NOPTS_VALUE) {
541
        if (dts)
542
            *dts = os->lastdts;
543
        os->lastdts = AV_NOPTS_VALUE;
544
    }
545
    if (os->page_end) {
546
        if (os->granule != -1LL) {
547
            if (os->codec && os->codec->granule_is_start)
548
                pts = ogg_gptopts(s, idx, os->granule, dts);
549
            else
550
                os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
551
            os->granule = -1LL;
552
        }
553
    }
554
    return pts;
555
}
556

    
557
static int
558
ogg_read_packet (AVFormatContext * s, AVPacket * pkt)
559
{
560
    struct ogg *ogg;
561
    struct ogg_stream *os;
562
    int idx = -1;
563
    int pstart, psize;
564
    int64_t fpos, pts, dts;
565

    
566
    //Get an ogg packet
567
retry:
568
    do{
569
        if (ogg_packet (s, &idx, &pstart, &psize, &fpos) < 0)
570
            return AVERROR(EIO);
571
    }while (idx < 0 || !s->streams[idx]);
572

    
573
    ogg = s->priv_data;
574
    os = ogg->streams + idx;
575

    
576
    // pflags might not be set until after this
577
    pts = ogg_calc_pts(s, idx, &dts);
578

    
579
    if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
580
        goto retry;
581
    os->keyframe_seek = 0;
582

    
583
    //Alloc a pkt
584
    if (av_new_packet (pkt, psize) < 0)
585
        return AVERROR(EIO);
586
    pkt->stream_index = idx;
587
    memcpy (pkt->data, os->buf + pstart, psize);
588

    
589
    pkt->pts = pts;
590
    pkt->dts = dts;
591
    pkt->flags = os->pflags;
592
    pkt->duration = os->pduration;
593
    pkt->pos = fpos;
594

    
595
    return psize;
596
}
597

    
598

    
599
static int
600
ogg_read_close (AVFormatContext * s)
601
{
602
    struct ogg *ogg = s->priv_data;
603
    int i;
604

    
605
    for (i = 0; i < ogg->nstreams; i++){
606
        av_free (ogg->streams[i].buf);
607
        av_free (ogg->streams[i].private);
608
    }
609
    av_free (ogg->streams);
610
    return 0;
611
}
612

    
613

    
614
static int64_t
615
ogg_read_timestamp (AVFormatContext * s, int stream_index, int64_t * pos_arg,
616
                    int64_t pos_limit)
617
{
618
    struct ogg *ogg = s->priv_data;
619
    struct ogg_stream *os = ogg->streams + stream_index;
620
    AVIOContext *bc = s->pb;
621
    int64_t pts = AV_NOPTS_VALUE;
622
    int i;
623
    avio_seek(bc, *pos_arg, SEEK_SET);
624
    ogg_reset(ogg);
625

    
626
    while (avio_tell(bc) < pos_limit && !ogg_packet(s, &i, NULL, NULL, pos_arg)) {
627
        if (i == stream_index) {
628
            pts = ogg_calc_pts(s, i, NULL);
629
            if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
630
                pts = AV_NOPTS_VALUE;
631
        }
632
        if (pts != AV_NOPTS_VALUE)
633
            break;
634
    }
635
    ogg_reset(ogg);
636
    return pts;
637
}
638

    
639
static int ogg_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
640
{
641
    struct ogg *ogg = s->priv_data;
642
    struct ogg_stream *os = ogg->streams + stream_index;
643
    int ret;
644

    
645
    // Try seeking to a keyframe first. If this fails (very possible),
646
    // av_seek_frame will fall back to ignoring keyframes
647
    if (s->streams[stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO
648
        && !(flags & AVSEEK_FLAG_ANY))
649
        os->keyframe_seek = 1;
650

    
651
    ret = av_seek_frame_binary(s, stream_index, timestamp, flags);
652
    if (ret < 0)
653
        os->keyframe_seek = 0;
654
    return ret;
655
}
656

    
657
static int ogg_probe(AVProbeData *p)
658
{
659
    if (p->buf[0] == 'O' && p->buf[1] == 'g' &&
660
        p->buf[2] == 'g' && p->buf[3] == 'S' &&
661
        p->buf[4] == 0x0 && p->buf[5] <= 0x7 )
662
        return AVPROBE_SCORE_MAX;
663
    else
664
        return 0;
665
}
666

    
667
AVInputFormat ff_ogg_demuxer = {
668
    "ogg",
669
    NULL_IF_CONFIG_SMALL("Ogg"),
670
    sizeof (struct ogg),
671
    ogg_probe,
672
    ogg_read_header,
673
    ogg_read_packet,
674
    ogg_read_close,
675
    ogg_read_seek,
676
    ogg_read_timestamp,
677
    .extensions = "ogg",
678
    .flags = AVFMT_GENERIC_INDEX,
679
};