Statistics
| Branch: | Revision:

ffmpeg / libavformat / oggdec.c @ 8f3eebd6

History | View | Annotate | Download (16.4 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

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

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

    
174
    return idx;
175
}
176

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

    
191
    return 0;
192
}
193

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

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

    
213
    do{
214
        int c;
215

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

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

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

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

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

    
242
    idx = ogg_find_stream (ogg, serial);
243
    if (idx < 0){
244
        if (ogg->headers) {
245
                int n;
246

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

    
259
    os = ogg->streams + idx;
260
    os->page_pos = avio_tell(bc) - 27;
261

    
262
    if(os->psize > 0)
263
        ogg_new_buf(ogg, idx);
264

    
265
    if (avio_read (bc, os->segments, nsegs) < nsegs)
266
        return -1;
267

    
268
    os->nsegs = nsegs;
269
    os->segp = 0;
270

    
271
    size = 0;
272
    for (i = 0; i < nsegs; i++)
273
        size += os->segments[i];
274

    
275
    if (flags & OGG_FLAG_CONT || os->incomplete){
276
        if (!os->psize){
277
            while (os->segp < os->nsegs){
278
                int seg = os->segments[os->segp++];
279
                os->pstart += seg;
280
                if (seg < 255)
281
                    break;
282
            }
283
            os->sync_pos = os->page_pos;
284
        }
285
    }else{
286
        os->psize = 0;
287
        os->sync_pos = os->page_pos;
288
    }
289

    
290
    if (os->bufsize - os->bufpos < size){
291
        uint8_t *nb = av_malloc (os->bufsize *= 2);
292
        memcpy (nb, os->buf, os->bufpos);
293
        av_free (os->buf);
294
        os->buf = nb;
295
    }
296

    
297
    if (avio_read (bc, os->buf + os->bufpos, size) < size)
298
        return -1;
299

    
300
    os->bufpos += size;
301
    os->granule = gp;
302
    os->flags = flags;
303

    
304
    if (str)
305
        *str = idx;
306

    
307
    return 0;
308
}
309

    
310
static int
311
ogg_packet (AVFormatContext * s, int *str, int *dstart, int *dsize, int64_t *fpos)
312
{
313
    struct ogg *ogg = s->priv_data;
314
    int idx, i;
315
    struct ogg_stream *os;
316
    int complete = 0;
317
    int segp = 0, psize = 0;
318

    
319
#if 0
320
    av_log (s, AV_LOG_DEBUG, "ogg_packet: curidx=%i\n", ogg->curidx);
321
#endif
322

    
323
    do{
324
        idx = ogg->curidx;
325

    
326
        while (idx < 0){
327
            if (ogg_read_page (s, &idx) < 0)
328
                return -1;
329
        }
330

    
331
        os = ogg->streams + idx;
332

    
333
#if 0
334
        av_log (s, AV_LOG_DEBUG,
335
                "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
336
                idx, os->pstart, os->psize, os->segp, os->nsegs);
337
#endif
338

    
339
        if (!os->codec){
340
            if (os->header < 0){
341
                os->codec = ogg_find_codec (os->buf, os->bufpos);
342
                if (!os->codec){
343
                    os->header = 0;
344
                    return 0;
345
                }
346
            }else{
347
                return 0;
348
            }
349
        }
350

    
351
        segp = os->segp;
352
        psize = os->psize;
353

    
354
        while (os->segp < os->nsegs){
355
            int ss = os->segments[os->segp++];
356
            os->psize += ss;
357
            if (ss < 255){
358
                complete = 1;
359
                break;
360
            }
361
        }
362

    
363
        if (!complete && os->segp == os->nsegs){
364
            ogg->curidx = -1;
365
            os->incomplete = 1;
366
        }
367
    }while (!complete);
368

    
369
#if 0
370
    av_log (s, AV_LOG_DEBUG,
371
            "ogg_packet: idx %i, frame size %i, start %i\n",
372
            idx, os->psize, os->pstart);
373
#endif
374

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

    
378
    ogg->curidx = idx;
379
    os->incomplete = 0;
380

    
381
    if (os->header) {
382
        os->header = os->codec->header (s, idx);
383
        if (!os->header){
384
            os->segp = segp;
385
            os->psize = psize;
386

    
387
            // We have reached the first non-header packet in this stream.
388
            // Unfortunately more header packets may still follow for others,
389
            // so we reset this later unless we are done with the headers
390
            // for all streams.
391
            ogg->headers = 1;
392

    
393
            // Update the header state for all streams and
394
            // compute the data_offset.
395
            if (!s->data_offset)
396
                s->data_offset = os->sync_pos;
397
            for (i = 0; i < ogg->nstreams; i++) {
398
                struct ogg_stream *cur_os = ogg->streams + i;
399
                if (cur_os->header > 0)
400
                    ogg->headers = 0;
401

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

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

    
438
    if (os->segp == os->nsegs)
439
        ogg->curidx = -1;
440

    
441
    return 0;
442
}
443

    
444
static int
445
ogg_get_headers (AVFormatContext * s)
446
{
447
    struct ogg *ogg = s->priv_data;
448

    
449
    do{
450
        if (ogg_packet (s, NULL, NULL, NULL, NULL) < 0)
451
            return -1;
452
    }while (!ogg->headers);
453

    
454
#if 0
455
    av_log (s, AV_LOG_DEBUG, "found headers\n");
456
#endif
457

    
458
    return 0;
459
}
460

    
461
static int
462
ogg_get_length (AVFormatContext * s)
463
{
464
    struct ogg *ogg = s->priv_data;
465
    int i;
466
    int64_t size, end;
467

    
468
    if(!s->pb->seekable)
469
        return 0;
470

    
471
// already set
472
    if (s->duration != AV_NOPTS_VALUE)
473
        return 0;
474

    
475
    size = avio_size(s->pb);
476
    if(size < 0)
477
        return 0;
478
    end = size > MAX_PAGE_SIZE? size - MAX_PAGE_SIZE: 0;
479

    
480
    ogg_save (s);
481
    avio_seek (s->pb, end, SEEK_SET);
482

    
483
    while (!ogg_read_page (s, &i)){
484
        if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
485
            ogg->streams[i].codec) {
486
            s->streams[i]->duration =
487
                ogg_gptopts (s, i, ogg->streams[i].granule, NULL);
488
            if (s->streams[i]->start_time != AV_NOPTS_VALUE)
489
                s->streams[i]->duration -= s->streams[i]->start_time;
490
        }
491
    }
492

    
493
    ogg_restore (s, 0);
494

    
495
    return 0;
496
}
497

    
498

    
499
static int
500
ogg_read_header (AVFormatContext * s, AVFormatParameters * ap)
501
{
502
    struct ogg *ogg = s->priv_data;
503
    int i;
504
    ogg->curidx = -1;
505
    //linear headers seek from start
506
    if (ogg_get_headers (s) < 0){
507
        return -1;
508
    }
509

    
510
    for (i = 0; i < ogg->nstreams; i++)
511
        if (ogg->streams[i].header < 0)
512
            ogg->streams[i].codec = NULL;
513

    
514
    //linear granulepos seek from end
515
    ogg_get_length (s);
516

    
517
    //fill the extradata in the per codec callbacks
518
    return 0;
519
}
520

    
521
static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
522
{
523
    struct ogg *ogg = s->priv_data;
524
    struct ogg_stream *os = ogg->streams + idx;
525
    int64_t pts = AV_NOPTS_VALUE;
526

    
527
    if (dts)
528
        *dts = AV_NOPTS_VALUE;
529

    
530
    if (os->lastpts != AV_NOPTS_VALUE) {
531
        pts = os->lastpts;
532
        os->lastpts = AV_NOPTS_VALUE;
533
    }
534
    if (os->lastdts != AV_NOPTS_VALUE) {
535
        if (dts)
536
            *dts = os->lastdts;
537
        os->lastdts = AV_NOPTS_VALUE;
538
    }
539
    if (os->page_end) {
540
        if (os->granule != -1LL) {
541
            if (os->codec && os->codec->granule_is_start)
542
                pts = ogg_gptopts(s, idx, os->granule, dts);
543
            else
544
                os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
545
            os->granule = -1LL;
546
        }
547
    }
548
    return pts;
549
}
550

    
551
static int
552
ogg_read_packet (AVFormatContext * s, AVPacket * pkt)
553
{
554
    struct ogg *ogg;
555
    struct ogg_stream *os;
556
    int idx = -1;
557
    int pstart, psize;
558
    int64_t fpos, pts, dts;
559

    
560
    //Get an ogg packet
561
retry:
562
    do{
563
        if (ogg_packet (s, &idx, &pstart, &psize, &fpos) < 0)
564
            return AVERROR(EIO);
565
    }while (idx < 0 || !s->streams[idx]);
566

    
567
    ogg = s->priv_data;
568
    os = ogg->streams + idx;
569

    
570
    // pflags might not be set until after this
571
    pts = ogg_calc_pts(s, idx, &dts);
572

    
573
    if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
574
        goto retry;
575
    os->keyframe_seek = 0;
576

    
577
    //Alloc a pkt
578
    if (av_new_packet (pkt, psize) < 0)
579
        return AVERROR(EIO);
580
    pkt->stream_index = idx;
581
    memcpy (pkt->data, os->buf + pstart, psize);
582

    
583
    pkt->pts = pts;
584
    pkt->dts = dts;
585
    pkt->flags = os->pflags;
586
    pkt->duration = os->pduration;
587
    pkt->pos = fpos;
588

    
589
    return psize;
590
}
591

    
592

    
593
static int
594
ogg_read_close (AVFormatContext * s)
595
{
596
    struct ogg *ogg = s->priv_data;
597
    int i;
598

    
599
    for (i = 0; i < ogg->nstreams; i++){
600
        av_free (ogg->streams[i].buf);
601
        av_free (ogg->streams[i].private);
602
    }
603
    av_free (ogg->streams);
604
    return 0;
605
}
606

    
607

    
608
static int64_t
609
ogg_read_timestamp (AVFormatContext * s, int stream_index, int64_t * pos_arg,
610
                    int64_t pos_limit)
611
{
612
    struct ogg *ogg = s->priv_data;
613
    struct ogg_stream *os = ogg->streams + stream_index;
614
    AVIOContext *bc = s->pb;
615
    int64_t pts = AV_NOPTS_VALUE;
616
    int i;
617
    avio_seek(bc, *pos_arg, SEEK_SET);
618
    ogg_reset(ogg);
619

    
620
    while (avio_tell(bc) < pos_limit && !ogg_packet(s, &i, NULL, NULL, pos_arg)) {
621
        if (i == stream_index) {
622
            pts = ogg_calc_pts(s, i, NULL);
623
            if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
624
                pts = AV_NOPTS_VALUE;
625
        }
626
        if (pts != AV_NOPTS_VALUE)
627
            break;
628
    }
629
    ogg_reset(ogg);
630
    return pts;
631
}
632

    
633
static int ogg_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
634
{
635
    struct ogg *ogg = s->priv_data;
636
    struct ogg_stream *os = ogg->streams + stream_index;
637
    int ret;
638

    
639
    // Try seeking to a keyframe first. If this fails (very possible),
640
    // av_seek_frame will fall back to ignoring keyframes
641
    if (s->streams[stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO
642
        && !(flags & AVSEEK_FLAG_ANY))
643
        os->keyframe_seek = 1;
644

    
645
    ret = av_seek_frame_binary(s, stream_index, timestamp, flags);
646
    if (ret < 0)
647
        os->keyframe_seek = 0;
648
    return ret;
649
}
650

    
651
static int ogg_probe(AVProbeData *p)
652
{
653
    if (p->buf[0] == 'O' && p->buf[1] == 'g' &&
654
        p->buf[2] == 'g' && p->buf[3] == 'S' &&
655
        p->buf[4] == 0x0 && p->buf[5] <= 0x7 )
656
        return AVPROBE_SCORE_MAX;
657
    else
658
        return 0;
659
}
660

    
661
AVInputFormat ff_ogg_demuxer = {
662
    "ogg",
663
    NULL_IF_CONFIG_SMALL("Ogg"),
664
    sizeof (struct ogg),
665
    ogg_probe,
666
    ogg_read_header,
667
    ogg_read_packet,
668
    ogg_read_close,
669
    ogg_read_seek,
670
    ogg_read_timestamp,
671
    .extensions = "ogg",
672
    .flags = AVFMT_GENERIC_INDEX,
673
};