Statistics
| Branch: | Revision:

ffmpeg / libavformat / oggdec.c @ b3bbc6fd

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_freep(&ogg->streams[n].buf);
249
                av_freep(&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
    av_dlog(s, AV_LOG_DEBUG, "ogg_packet: curidx=%i\n", ogg->curidx);
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
        av_dlog(s, AV_LOG_DEBUG,
332
                "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
333
                idx, os->pstart, os->psize, os->segp, os->nsegs);
334

    
335
        if (!os->codec){
336
            if (os->header < 0){
337
                os->codec = ogg_find_codec (os->buf, os->bufpos);
338
                if (!os->codec){
339
                    os->header = 0;
340
                    return 0;
341
                }
342
            }else{
343
                return 0;
344
            }
345
        }
346

    
347
        segp = os->segp;
348
        psize = os->psize;
349

    
350
        while (os->segp < os->nsegs){
351
            int ss = os->segments[os->segp++];
352
            os->psize += ss;
353
            if (ss < 255){
354
                complete = 1;
355
                break;
356
            }
357
        }
358

    
359
        if (!complete && os->segp == os->nsegs){
360
            ogg->curidx = -1;
361
            os->incomplete = 1;
362
        }
363
    }while (!complete);
364

    
365
    av_dlog(s, AV_LOG_DEBUG,
366
            "ogg_packet: idx %i, frame size %i, start %i\n",
367
            idx, os->psize, os->pstart);
368

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

    
372
    ogg->curidx = idx;
373
    os->incomplete = 0;
374

    
375
    if (os->header) {
376
        os->header = os->codec->header (s, idx);
377
        if (!os->header){
378
            os->segp = segp;
379
            os->psize = psize;
380

    
381
            // We have reached the first non-header packet in this stream.
382
            // Unfortunately more header packets may still follow for others,
383
            // so we reset this later unless we are done with the headers
384
            // for all streams.
385
            ogg->headers = 1;
386

    
387
            // Update the header state for all streams and
388
            // compute the data_offset.
389
            if (!s->data_offset)
390
                s->data_offset = os->sync_pos;
391
            for (i = 0; i < ogg->nstreams; i++) {
392
                struct ogg_stream *cur_os = ogg->streams + i;
393
                if (cur_os->header > 0)
394
                    ogg->headers = 0;
395

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

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

    
432
    if (os->segp == os->nsegs)
433
        ogg->curidx = -1;
434

    
435
    return 0;
436
}
437

    
438
static int
439
ogg_get_headers (AVFormatContext * s)
440
{
441
    struct ogg *ogg = s->priv_data;
442

    
443
    do{
444
        if (ogg_packet (s, NULL, NULL, NULL, NULL) < 0)
445
            return -1;
446
    }while (!ogg->headers);
447

    
448
    av_dlog(s, AV_LOG_DEBUG, "found headers\n");
449

    
450
    return 0;
451
}
452

    
453
static int
454
ogg_get_length (AVFormatContext * s)
455
{
456
    struct ogg *ogg = s->priv_data;
457
    int i;
458
    int64_t size, end;
459

    
460
    if(!s->pb->seekable)
461
        return 0;
462

    
463
// already set
464
    if (s->duration != AV_NOPTS_VALUE)
465
        return 0;
466

    
467
    size = avio_size(s->pb);
468
    if(size < 0)
469
        return 0;
470
    end = size > MAX_PAGE_SIZE? size - MAX_PAGE_SIZE: 0;
471

    
472
    ogg_save (s);
473
    avio_seek (s->pb, end, SEEK_SET);
474

    
475
    while (!ogg_read_page (s, &i)){
476
        if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
477
            ogg->streams[i].codec) {
478
            s->streams[i]->duration =
479
                ogg_gptopts (s, i, ogg->streams[i].granule, NULL);
480
            if (s->streams[i]->start_time != AV_NOPTS_VALUE)
481
                s->streams[i]->duration -= s->streams[i]->start_time;
482
        }
483
    }
484

    
485
    ogg_restore (s, 0);
486

    
487
    return 0;
488
}
489

    
490

    
491
static int
492
ogg_read_header (AVFormatContext * s, AVFormatParameters * ap)
493
{
494
    struct ogg *ogg = s->priv_data;
495
    int i;
496
    ogg->curidx = -1;
497
    //linear headers seek from start
498
    if (ogg_get_headers (s) < 0){
499
        return -1;
500
    }
501

    
502
    for (i = 0; i < ogg->nstreams; i++)
503
        if (ogg->streams[i].header < 0)
504
            ogg->streams[i].codec = NULL;
505

    
506
    //linear granulepos seek from end
507
    ogg_get_length (s);
508

    
509
    //fill the extradata in the per codec callbacks
510
    return 0;
511
}
512

    
513
static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
514
{
515
    struct ogg *ogg = s->priv_data;
516
    struct ogg_stream *os = ogg->streams + idx;
517
    int64_t pts = AV_NOPTS_VALUE;
518

    
519
    if (dts)
520
        *dts = AV_NOPTS_VALUE;
521

    
522
    if (os->lastpts != AV_NOPTS_VALUE) {
523
        pts = os->lastpts;
524
        os->lastpts = AV_NOPTS_VALUE;
525
    }
526
    if (os->lastdts != AV_NOPTS_VALUE) {
527
        if (dts)
528
            *dts = os->lastdts;
529
        os->lastdts = AV_NOPTS_VALUE;
530
    }
531
    if (os->page_end) {
532
        if (os->granule != -1LL) {
533
            if (os->codec && os->codec->granule_is_start)
534
                pts = ogg_gptopts(s, idx, os->granule, dts);
535
            else
536
                os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
537
            os->granule = -1LL;
538
        }
539
    }
540
    return pts;
541
}
542

    
543
static int
544
ogg_read_packet (AVFormatContext * s, AVPacket * pkt)
545
{
546
    struct ogg *ogg;
547
    struct ogg_stream *os;
548
    int idx = -1;
549
    int pstart, psize;
550
    int64_t fpos, pts, dts;
551

    
552
    //Get an ogg packet
553
retry:
554
    do{
555
        if (ogg_packet (s, &idx, &pstart, &psize, &fpos) < 0)
556
            return AVERROR(EIO);
557
    }while (idx < 0 || !s->streams[idx]);
558

    
559
    ogg = s->priv_data;
560
    os = ogg->streams + idx;
561

    
562
    // pflags might not be set until after this
563
    pts = ogg_calc_pts(s, idx, &dts);
564

    
565
    if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
566
        goto retry;
567
    os->keyframe_seek = 0;
568

    
569
    //Alloc a pkt
570
    if (av_new_packet (pkt, psize) < 0)
571
        return AVERROR(EIO);
572
    pkt->stream_index = idx;
573
    memcpy (pkt->data, os->buf + pstart, psize);
574

    
575
    pkt->pts = pts;
576
    pkt->dts = dts;
577
    pkt->flags = os->pflags;
578
    pkt->duration = os->pduration;
579
    pkt->pos = fpos;
580

    
581
    return psize;
582
}
583

    
584

    
585
static int
586
ogg_read_close (AVFormatContext * s)
587
{
588
    struct ogg *ogg = s->priv_data;
589
    int i;
590

    
591
    for (i = 0; i < ogg->nstreams; i++){
592
        av_free (ogg->streams[i].buf);
593
        av_free (ogg->streams[i].private);
594
    }
595
    av_free (ogg->streams);
596
    return 0;
597
}
598

    
599

    
600
static int64_t
601
ogg_read_timestamp (AVFormatContext * s, int stream_index, int64_t * pos_arg,
602
                    int64_t pos_limit)
603
{
604
    struct ogg *ogg = s->priv_data;
605
    struct ogg_stream *os = ogg->streams + stream_index;
606
    AVIOContext *bc = s->pb;
607
    int64_t pts = AV_NOPTS_VALUE;
608
    int i;
609
    avio_seek(bc, *pos_arg, SEEK_SET);
610
    ogg_reset(ogg);
611

    
612
    while (avio_tell(bc) < pos_limit && !ogg_packet(s, &i, NULL, NULL, pos_arg)) {
613
        if (i == stream_index) {
614
            pts = ogg_calc_pts(s, i, NULL);
615
            if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
616
                pts = AV_NOPTS_VALUE;
617
        }
618
        if (pts != AV_NOPTS_VALUE)
619
            break;
620
    }
621
    ogg_reset(ogg);
622
    return pts;
623
}
624

    
625
static int ogg_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
626
{
627
    struct ogg *ogg = s->priv_data;
628
    struct ogg_stream *os = ogg->streams + stream_index;
629
    int ret;
630

    
631
    // Try seeking to a keyframe first. If this fails (very possible),
632
    // av_seek_frame will fall back to ignoring keyframes
633
    if (s->streams[stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO
634
        && !(flags & AVSEEK_FLAG_ANY))
635
        os->keyframe_seek = 1;
636

    
637
    ret = av_seek_frame_binary(s, stream_index, timestamp, flags);
638
    if (ret < 0)
639
        os->keyframe_seek = 0;
640
    return ret;
641
}
642

    
643
static int ogg_probe(AVProbeData *p)
644
{
645
    if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
646
        return AVPROBE_SCORE_MAX;
647
    return 0;
648
}
649

    
650
AVInputFormat ff_ogg_demuxer = {
651
    .name           = "ogg",
652
    .long_name      = NULL_IF_CONFIG_SMALL("Ogg"),
653
    .priv_data_size = sizeof(struct ogg),
654
    .read_probe     = ogg_probe,
655
    .read_header    = ogg_read_header,
656
    .read_packet    = ogg_read_packet,
657
    .read_close     = ogg_read_close,
658
    .read_seek      = ogg_read_seek,
659
    .read_timestamp = ogg_read_timestamp,
660
    .extensions     = "ogg",
661
    .flags          = AVFMT_GENERIC_INDEX,
662
};