~ubuntu-branches/ubuntu/saucy/gst-libav1.0/saucy-proposed

« back to all changes in this revision

Viewing changes to gst-libs/ext/libav/libavformat/oggdec.c

  • Committer: Package Import Robot
  • Author(s): Sebastian Dröge
  • Date: 2013-07-30 09:00:15 UTC
  • mfrom: (1.1.16) (7.1.7 experimental)
  • Revision ID: package-import@ubuntu.com-20130730090015-sc1ou2yssu7q5w4e
Tags: 1.1.3-1
* New upstream development snapshot:
  + debian/control:
    - Build depend on GStreamer and gst-plugins-base >= 1.1.3.

Show diffs side-by-side

added added

removed removed

Lines of Context:
60
60
{
61
61
    struct ogg *ogg = s->priv_data;
62
62
    struct ogg_state *ost =
63
 
        av_malloc(sizeof (*ost) + (ogg->nstreams-1) * sizeof (*ogg->streams));
 
63
        av_malloc(sizeof(*ost) + (ogg->nstreams - 1) * sizeof(*ogg->streams));
64
64
    int i;
65
 
    ost->pos = avio_tell (s->pb);
66
 
    ost->curidx = ogg->curidx;
67
 
    ost->next = ogg->state;
 
65
    ost->pos      = avio_tell(s->pb);
 
66
    ost->curidx   = ogg->curidx;
 
67
    ost->next     = ogg->state;
68
68
    ost->nstreams = ogg->nstreams;
69
69
    memcpy(ost->streams, ogg->streams, ogg->nstreams * sizeof(*ogg->streams));
70
70
 
71
 
    for (i = 0; i < ogg->nstreams; i++){
 
71
    for (i = 0; i < ogg->nstreams; i++) {
72
72
        struct ogg_stream *os = ogg->streams + i;
73
 
        os->buf = av_mallocz (os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE);
74
 
        memcpy (os->buf, ost->streams[i].buf, os->bufpos);
 
73
        os->buf = av_mallocz(os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE);
 
74
        memcpy(os->buf, ost->streams[i].buf, os->bufpos);
75
75
    }
76
76
 
77
77
    ogg->state = ost;
91
91
 
92
92
    ogg->state = ost->next;
93
93
 
94
 
    if (!discard){
 
94
    if (!discard) {
95
95
        struct ogg_stream *old_streams = ogg->streams;
96
96
 
97
97
        for (i = 0; i < ogg->nstreams; i++)
98
 
            av_free (ogg->streams[i].buf);
 
98
            av_free(ogg->streams[i].buf);
99
99
 
100
 
        avio_seek (bc, ost->pos, SEEK_SET);
101
 
        ogg->curidx = ost->curidx;
 
100
        avio_seek(bc, ost->pos, SEEK_SET);
 
101
        ogg->curidx   = ost->curidx;
102
102
        ogg->nstreams = ost->nstreams;
103
 
        ogg->streams = av_realloc (ogg->streams,
104
 
                                   ogg->nstreams * sizeof (*ogg->streams));
 
103
        ogg->streams  = av_realloc(ogg->streams,
 
104
                                   ogg->nstreams * sizeof(*ogg->streams));
105
105
 
106
106
        if (ogg->streams) {
107
107
            memcpy(ogg->streams, ost->streams,
112
112
        }
113
113
    }
114
114
 
115
 
    av_free (ost);
 
115
    av_free(ost);
116
116
 
117
117
    return 0;
118
118
}
121
121
{
122
122
    int i;
123
123
 
124
 
    for (i = 0; i < ogg->nstreams; i++){
 
124
    for (i = 0; i < ogg->nstreams; i++) {
125
125
        struct ogg_stream *os = ogg->streams + i;
126
 
        os->bufpos = 0;
127
 
        os->pstart = 0;
128
 
        os->psize = 0;
129
 
        os->granule = -1;
130
 
        os->lastpts = AV_NOPTS_VALUE;
131
 
        os->lastdts = AV_NOPTS_VALUE;
132
 
        os->sync_pos = -1;
133
 
        os->page_pos = 0;
134
 
        os->nsegs = 0;
135
 
        os->segp = 0;
 
126
        os->bufpos     = 0;
 
127
        os->pstart     = 0;
 
128
        os->psize      = 0;
 
129
        os->granule    = -1;
 
130
        os->lastpts    = AV_NOPTS_VALUE;
 
131
        os->lastdts    = AV_NOPTS_VALUE;
 
132
        os->sync_pos   = -1;
 
133
        os->page_pos   = 0;
 
134
        os->nsegs      = 0;
 
135
        os->segp       = 0;
136
136
        os->incomplete = 0;
137
137
    }
138
138
 
147
147
 
148
148
    for (i = 0; ogg_codecs[i]; i++)
149
149
        if (size >= ogg_codecs[i]->magicsize &&
150
 
            !memcmp (buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize))
 
150
            !memcmp(buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize))
151
151
            return ogg_codecs[i];
152
152
 
153
153
    return NULL;
155
155
 
156
156
static int ogg_new_stream(AVFormatContext *s, uint32_t serial, int new_avstream)
157
157
{
158
 
 
159
158
    struct ogg *ogg = s->priv_data;
160
 
    int idx = ogg->nstreams++;
 
159
    int idx         = ogg->nstreams++;
161
160
    AVStream *st;
162
161
    struct ogg_stream *os;
163
162
 
164
 
    os = av_realloc (ogg->streams, ogg->nstreams * sizeof (*ogg->streams));
 
163
    os = av_realloc(ogg->streams, ogg->nstreams * sizeof(*ogg->streams));
165
164
 
166
165
    if (!os)
167
166
        return AVERROR(ENOMEM);
168
167
 
169
168
    ogg->streams = os;
170
169
 
171
 
    memset (ogg->streams + idx, 0, sizeof (*ogg->streams));
172
 
    os = ogg->streams + idx;
173
 
    os->serial = serial;
174
 
    os->bufsize = DECODER_BUFFER_SIZE;
175
 
    os->buf = av_malloc(os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE);
176
 
    os->header = -1;
 
170
    memset(ogg->streams + idx, 0, sizeof(*ogg->streams));
 
171
 
 
172
    os                = ogg->streams + idx;
 
173
    os->serial        = serial;
 
174
    os->bufsize       = DECODER_BUFFER_SIZE;
 
175
    os->buf           = av_malloc(os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE);
 
176
    os->header        = -1;
 
177
    os->start_granule = OGG_NOGRANULE_VALUE;
177
178
 
178
179
    if (new_avstream) {
179
180
        st = avformat_new_stream(s, NULL);
192
193
    struct ogg_stream *os = ogg->streams + idx;
193
194
    uint8_t *nb = av_malloc(os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE);
194
195
    int size = os->bufpos - os->pstart;
195
 
    if(os->buf){
 
196
 
 
197
    if (os->buf) {
196
198
        memcpy(nb, os->buf + os->pstart, size);
197
199
        av_free(os->buf);
198
200
    }
199
 
    os->buf = nb;
 
201
 
 
202
    os->buf    = nb;
200
203
    os->bufpos = size;
201
204
    os->pstart = 0;
202
205
 
220
223
    if (ret < 4)
221
224
        return ret < 0 ? ret : AVERROR_EOF;
222
225
 
223
 
    do{
 
226
    do {
224
227
        int c;
225
228
 
226
229
        if (sync[sp & 3] == 'O' &&
229
232
            break;
230
233
 
231
234
        c = avio_r8(bc);
 
235
 
232
236
        if (bc->eof_reached)
233
237
            return AVERROR_EOF;
 
238
 
234
239
        sync[sp++ & 3] = c;
235
 
    }while (i++ < MAX_PAGE_SIZE);
 
240
    } while (i++ < MAX_PAGE_SIZE);
236
241
 
237
 
    if (i >= MAX_PAGE_SIZE){
238
 
        av_log (s, AV_LOG_INFO, "ogg, can't find sync word\n");
 
242
    if (i >= MAX_PAGE_SIZE) {
 
243
        av_log(s, AV_LOG_INFO, "cannot find sync word\n");
239
244
        return AVERROR_INVALIDDATA;
240
245
    }
241
246
 
242
247
    if (avio_r8(bc) != 0)      /* version */
243
248
        return AVERROR_INVALIDDATA;
244
249
 
245
 
    flags = avio_r8(bc);
246
 
    gp = avio_rl64 (bc);
247
 
    serial = avio_rl32 (bc);
 
250
    flags  = avio_r8(bc);
 
251
    gp     = avio_rl64(bc);
 
252
    serial = avio_rl32(bc);
248
253
    avio_skip(bc, 8); /* seq, crc */
249
 
    nsegs = avio_r8(bc);
 
254
    nsegs  = avio_r8(bc);
250
255
 
251
 
    idx = ogg_find_stream (ogg, serial);
252
 
    if (idx < 0){
 
256
    idx = ogg_find_stream(ogg, serial);
 
257
    if (idx < 0) {
253
258
        if (ogg->headers) {
254
259
            int n;
255
260
 
256
261
            for (n = 0; n < ogg->nstreams; n++) {
257
262
                av_freep(&ogg->streams[n].buf);
258
 
                if (!ogg->state || ogg->state->streams[n].private != ogg->streams[n].private)
 
263
                if (!ogg->state ||
 
264
                    ogg->state->streams[n].private != ogg->streams[n].private)
259
265
                    av_freep(&ogg->streams[n].private);
260
266
            }
 
267
 
261
268
            ogg->curidx   = -1;
262
269
            ogg->nstreams = 0;
 
270
 
263
271
            idx = ogg_new_stream(s, serial, 0);
264
272
        } else {
265
273
            idx = ogg_new_stream(s, serial, 1);
271
279
    os = ogg->streams + idx;
272
280
    os->page_pos = avio_tell(bc) - 27;
273
281
 
274
 
    if(os->psize > 0)
 
282
    if (os->psize > 0)
275
283
        ogg_new_buf(ogg, idx);
276
284
 
277
285
    ret = avio_read(bc, os->segments, nsegs);
279
287
        return ret < 0 ? ret : AVERROR_EOF;
280
288
 
281
289
    os->nsegs = nsegs;
282
 
    os->segp = 0;
 
290
    os->segp  = 0;
283
291
 
284
292
    size = 0;
285
293
    for (i = 0; i < nsegs; i++)
286
294
        size += os->segments[i];
287
295
 
288
 
    if (flags & OGG_FLAG_CONT || os->incomplete){
289
 
        if (!os->psize){
290
 
            while (os->segp < os->nsegs){
 
296
    if (flags & OGG_FLAG_CONT || os->incomplete) {
 
297
        if (!os->psize) {
 
298
            while (os->segp < os->nsegs) {
291
299
                int seg = os->segments[os->segp++];
292
300
                os->pstart += seg;
293
301
                if (seg < 255)
295
303
            }
296
304
            os->sync_pos = os->page_pos;
297
305
        }
298
 
    }else{
299
 
        os->psize = 0;
 
306
    } else {
 
307
        os->psize    = 0;
300
308
        os->sync_pos = os->page_pos;
301
309
    }
302
310
 
303
 
    if (os->bufsize - os->bufpos < size){
304
 
        uint8_t *nb = av_malloc ((os->bufsize *= 2) + FF_INPUT_BUFFER_PADDING_SIZE);
 
311
    if (os->bufsize - os->bufpos < size) {
 
312
        uint8_t *nb = av_malloc((os->bufsize *= 2) + FF_INPUT_BUFFER_PADDING_SIZE);
305
313
        if (!nb)
306
314
            return AVERROR(ENOMEM);
307
 
        memcpy (nb, os->buf, os->bufpos);
308
 
        av_free (os->buf);
 
315
        memcpy(nb, os->buf, os->bufpos);
 
316
        av_free(os->buf);
309
317
        os->buf = nb;
310
318
    }
311
319
 
315
323
 
316
324
    os->bufpos += size;
317
325
    os->granule = gp;
318
 
    os->flags = flags;
 
326
    os->flags   = flags;
319
327
 
320
328
    memset(os->buf + os->bufpos, 0, FF_INPUT_BUFFER_PADDING_SIZE);
321
329
    if (str)
331
339
    int idx, i, ret;
332
340
    struct ogg_stream *os;
333
341
    int complete = 0;
334
 
    int segp = 0, psize = 0;
 
342
    int segp     = 0, psize = 0;
335
343
 
336
344
    av_dlog(s, "ogg_packet: curidx=%i\n", ogg->curidx);
337
345
 
338
 
    do{
 
346
    do {
339
347
        idx = ogg->curidx;
340
348
 
341
 
        while (idx < 0){
 
349
        while (idx < 0) {
342
350
            ret = ogg_read_page(s, &idx);
343
351
            if (ret < 0)
344
352
                return ret;
349
357
        av_dlog(s, "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
350
358
                idx, os->pstart, os->psize, os->segp, os->nsegs);
351
359
 
352
 
        if (!os->codec){
353
 
            if (os->header < 0){
354
 
                os->codec = ogg_find_codec (os->buf, os->bufpos);
355
 
                if (!os->codec){
 
360
        if (!os->codec) {
 
361
            if (os->header < 0) {
 
362
                os->codec = ogg_find_codec(os->buf, os->bufpos);
 
363
                if (!os->codec) {
356
364
                    av_log(s, AV_LOG_WARNING, "Codec not found\n");
357
365
                    os->header = 0;
358
366
                    return 0;
359
367
                }
360
 
            }else{
 
368
            } else {
361
369
                return 0;
362
370
            }
363
371
        }
364
372
 
365
 
        segp = os->segp;
 
373
        segp  = os->segp;
366
374
        psize = os->psize;
367
375
 
368
 
        while (os->segp < os->nsegs){
 
376
        while (os->segp < os->nsegs) {
369
377
            int ss = os->segments[os->segp++];
370
378
            os->psize += ss;
371
 
            if (ss < 255){
 
379
            if (ss < 255) {
372
380
                complete = 1;
373
381
                break;
374
382
            }
375
383
        }
376
384
 
377
 
        if (!complete && os->segp == os->nsegs){
378
 
            ogg->curidx = -1;
 
385
        if (!complete && os->segp == os->nsegs) {
 
386
            ogg->curidx    = -1;
379
387
            os->incomplete = 1;
380
388
        }
381
 
    }while (!complete);
 
389
    } while (!complete);
382
390
 
383
391
    av_dlog(s, "ogg_packet: idx %i, frame size %i, start %i\n",
384
392
            idx, os->psize, os->pstart);
385
393
 
386
394
    if (os->granule == -1)
387
 
        av_log(s, AV_LOG_WARNING, "Page at %"PRId64" is missing granule\n", os->page_pos);
 
395
        av_log(s, AV_LOG_WARNING,
 
396
               "Page at %"PRId64" is missing granule\n",
 
397
               os->page_pos);
388
398
 
389
 
    ogg->curidx = idx;
 
399
    ogg->curidx    = idx;
390
400
    os->incomplete = 0;
391
401
 
392
402
    if (os->header) {
393
 
        os->header = os->codec->header (s, idx);
394
 
        if (!os->header){
395
 
            os->segp = segp;
 
403
        os->header = os->codec->header(s, idx);
 
404
        if (!os->header) {
 
405
            os->segp  = segp;
396
406
            os->psize = psize;
397
407
 
398
408
            // We have reached the first non-header packet in this stream.
404
414
            // compute the data_offset.
405
415
            if (!s->data_offset)
406
416
                s->data_offset = os->sync_pos;
 
417
 
407
418
            for (i = 0; i < ogg->nstreams; i++) {
408
419
                struct ogg_stream *cur_os = ogg->streams + i;
409
420
 
412
423
                if (cur_os->incomplete)
413
424
                    s->data_offset = FFMIN(s->data_offset, cur_os->sync_pos);
414
425
            }
415
 
        }else{
 
426
        } else {
 
427
            os->nb_header++;
416
428
            os->pstart += os->psize;
417
 
            os->psize = 0;
 
429
            os->psize   = 0;
418
430
        }
419
431
    } else {
420
 
        os->pflags = 0;
 
432
        os->pflags    = 0;
421
433
        os->pduration = 0;
422
434
        if (os->codec && os->codec->packet)
423
 
            os->codec->packet (s, idx);
 
435
            os->codec->packet(s, idx);
424
436
        if (str)
425
437
            *str = idx;
426
438
        if (dstart)
429
441
            *dsize = os->psize;
430
442
        if (fpos)
431
443
            *fpos = os->sync_pos;
432
 
        os->pstart += os->psize;
433
 
        os->psize = 0;
 
444
        os->pstart  += os->psize;
 
445
        os->psize    = 0;
434
446
        os->sync_pos = os->page_pos;
435
447
    }
436
448
 
452
464
static int ogg_get_headers(AVFormatContext *s)
453
465
{
454
466
    struct ogg *ogg = s->priv_data;
455
 
    int ret;
 
467
    int ret, i;
456
468
 
457
 
    do{
 
469
    do {
458
470
        ret = ogg_packet(s, NULL, NULL, NULL, NULL);
459
471
        if (ret < 0)
460
472
            return ret;
461
 
    }while (!ogg->headers);
462
 
 
 
473
    } while (!ogg->headers);
 
474
 
 
475
    for (i = 0; i < ogg->nstreams; i++) {
 
476
        struct ogg_stream *os = ogg->streams + i;
 
477
 
 
478
        if (os->codec && os->codec->nb_header &&
 
479
            os->nb_header < os->codec->nb_header) {
 
480
            av_log(s, AV_LOG_ERROR,
 
481
                   "Headers mismatch for stream %d\n", i);
 
482
            return AVERROR_INVALIDDATA;
 
483
        }
 
484
        if (os->start_granule != OGG_NOGRANULE_VALUE)
 
485
            os->lastpts = s->streams[i]->start_time =
 
486
                ogg_gptopts(s, i, os->start_granule, NULL);
 
487
    }
463
488
    av_dlog(s, "found headers\n");
464
489
 
465
490
    return 0;
471
496
    int i;
472
497
    int64_t size, end;
473
498
 
474
 
    if(!s->pb->seekable)
 
499
    if (!s->pb->seekable)
475
500
        return 0;
476
501
 
477
502
// already set
479
504
        return 0;
480
505
 
481
506
    size = avio_size(s->pb);
482
 
    if(size < 0)
 
507
    if (size < 0)
483
508
        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)){
 
509
    end = size > MAX_PAGE_SIZE ? size - MAX_PAGE_SIZE : 0;
 
510
 
 
511
    ogg_save(s);
 
512
    avio_seek(s->pb, end, SEEK_SET);
 
513
 
 
514
    while (!ogg_read_page(s, &i)) {
490
515
        if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
491
516
            ogg->streams[i].codec) {
492
517
            s->streams[i]->duration =
493
 
                ogg_gptopts (s, i, ogg->streams[i].granule, NULL);
 
518
                ogg_gptopts(s, i, ogg->streams[i].granule, NULL);
494
519
            if (s->streams[i]->start_time != AV_NOPTS_VALUE)
495
520
                s->streams[i]->duration -= s->streams[i]->start_time;
496
521
        }
497
522
    }
498
523
 
499
 
    ogg_restore (s, 0);
 
524
    ogg_restore(s, 0);
500
525
 
501
526
    return 0;
502
527
}
535
560
            ogg->streams[i].codec = NULL;
536
561
 
537
562
    //linear granulepos seek from end
538
 
    ogg_get_length (s);
 
563
    ogg_get_length(s);
539
564
 
540
565
    //fill the extradata in the per codec callbacks
541
566
    return 0;
543
568
 
544
569
static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
545
570
{
546
 
    struct ogg *ogg = s->priv_data;
 
571
    struct ogg *ogg       = s->priv_data;
547
572
    struct ogg_stream *os = ogg->streams + idx;
548
 
    int64_t pts = AV_NOPTS_VALUE;
 
573
    int64_t pts           = AV_NOPTS_VALUE;
549
574
 
550
575
    if (dts)
551
576
        *dts = AV_NOPTS_VALUE;
552
577
 
553
578
    if (os->lastpts != AV_NOPTS_VALUE) {
554
 
        pts = os->lastpts;
 
579
        pts         = os->lastpts;
555
580
        os->lastpts = AV_NOPTS_VALUE;
556
581
    }
557
582
    if (os->lastdts != AV_NOPTS_VALUE) {
581
606
 
582
607
    //Get an ogg packet
583
608
retry:
584
 
    do{
 
609
    do {
585
610
        ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
586
611
        if (ret < 0)
587
612
            return ret;
588
 
    }while (idx < 0 || !s->streams[idx]);
 
613
    } while (idx < 0 || !s->streams[idx]);
589
614
 
590
615
    ogg = s->priv_data;
591
 
    os = ogg->streams + idx;
 
616
    os  = ogg->streams + idx;
592
617
 
593
618
    // pflags might not be set until after this
594
619
    pts = ogg_calc_pts(s, idx, &dts);
602
627
    if (ret < 0)
603
628
        return ret;
604
629
    pkt->stream_index = idx;
605
 
    memcpy (pkt->data, os->buf + pstart, psize);
 
630
    memcpy(pkt->data, os->buf + pstart, psize);
606
631
 
607
 
    pkt->pts = pts;
608
 
    pkt->dts = dts;
609
 
    pkt->flags = os->pflags;
 
632
    pkt->pts      = pts;
 
633
    pkt->dts      = dts;
 
634
    pkt->flags    = os->pflags;
610
635
    pkt->duration = os->pduration;
611
 
    pkt->pos = fpos;
 
636
    pkt->pos      = fpos;
612
637
 
613
638
    return psize;
614
639
}
618
643
{
619
644
    struct ogg *ogg = s->priv_data;
620
645
    AVIOContext *bc = s->pb;
621
 
    int64_t pts = AV_NOPTS_VALUE;
622
 
    int i = -1;
 
646
    int64_t pts     = AV_NOPTS_VALUE;
 
647
    int i           = -1;
623
648
    avio_seek(bc, *pos_arg, SEEK_SET);
624
649
    ogg_reset(ogg);
625
650
 
626
 
    while (avio_tell(bc) < pos_limit && !ogg_packet(s, &i, NULL, NULL, pos_arg)) {
 
651
    while (avio_tell(bc) < pos_limit &&
 
652
           !ogg_packet(s, &i, NULL, NULL, pos_arg)) {
627
653
        if (i == stream_index) {
628
654
            struct ogg_stream *os = ogg->streams + stream_index;
629
655
            pts = ogg_calc_pts(s, i, NULL);
640
666
static int ogg_read_seek(AVFormatContext *s, int stream_index,
641
667
                         int64_t timestamp, int flags)
642
668
{
643
 
    struct ogg *ogg = s->priv_data;
 
669
    struct ogg *ogg       = s->priv_data;
644
670
    struct ogg_stream *os = ogg->streams + stream_index;
645
671
    int ret;
646
672
 
651
677
        os->keyframe_seek = 1;
652
678
 
653
679
    ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
654
 
    os = ogg->streams + stream_index;
 
680
    os  = ogg->streams + stream_index;
655
681
    if (ret < 0)
656
682
        os->keyframe_seek = 0;
657
683
    return ret;