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

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): Sebastian Dröge
  • Date: 2013-09-24 17:07:00 UTC
  • mfrom: (1.1.17) (7.1.9 experimental)
  • Revision ID: package-import@ubuntu.com-20130924170700-4dg62s3pwl0pdakz
Tags: 1.2.0-1
* New upstream stable release:
  + debian/control:
    - Build depend on GStreamer and gst-plugins-base >= 1.2.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
 
22
22
#include "libavutil/crc.h"
23
23
#include "libavutil/mathematics.h"
 
24
#include "libavutil/opt.h"
24
25
#include "libavutil/random_seed.h"
25
26
#include "libavcodec/xiph.h"
26
27
#include "libavcodec/bytestream.h"
63
64
} OGGPageList;
64
65
 
65
66
typedef struct {
 
67
    const AVClass *class;
66
68
    OGGPageList *page_list;
 
69
    int pref_size; ///< preferred page size (0 => fill all segments)
67
70
} OGGContext;
68
71
 
 
72
#define OFFSET(x) offsetof(OGGContext, x)
 
73
#define PARAM AV_OPT_FLAG_ENCODING_PARAM
 
74
 
 
75
static const AVOption options[] = {
 
76
    { "pagesize", "preferred page size in bytes",
 
77
        OFFSET(pref_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, MAX_PAGE_SIZE, PARAM },
 
78
    { NULL },
 
79
};
 
80
 
 
81
static const AVClass ogg_muxer_class = {
 
82
    .class_name = "Ogg muxer",
 
83
    .item_name  = av_default_item_name,
 
84
    .option     = options,
 
85
    .version    = LIBAVUTIL_VERSION_INT,
 
86
};
 
87
 
 
88
 
69
89
static void ogg_update_checksum(AVFormatContext *s, AVIOContext *pb, int64_t crc_offset)
70
90
{
71
91
    int64_t pos = avio_tell(pb);
172
192
}
173
193
 
174
194
static int ogg_buffer_data(AVFormatContext *s, AVStream *st,
175
 
                           uint8_t *data, unsigned size, int64_t granule)
 
195
                           uint8_t *data, unsigned size, int64_t granule,
 
196
                           int header)
176
197
{
177
198
    OGGStreamContext *oggstream = st->priv_data;
 
199
    OGGContext *ogg = s->priv_data;
178
200
    int total_segments = size / 255 + 1;
179
201
    uint8_t *p = data;
180
202
    int i, segments, len, flush = 0;
181
203
 
182
204
    // Handles VFR by flushing page because this frame needs to have a timestamp
183
 
    if (st->codec->codec_id == CODEC_ID_THEORA &&
 
205
    if (st->codec->codec_id == AV_CODEC_ID_THEORA && !header &&
184
206
        ogg_granule_to_timestamp(oggstream, granule) >
185
207
        ogg_granule_to_timestamp(oggstream, oggstream->last_granule) + 1) {
186
208
        if (oggstream->page.granule != -1)
210
232
        if (i == total_segments)
211
233
            page->granule = granule;
212
234
 
213
 
        if (page->segments_count == 255) {
214
 
            ogg_buffer_page(s, oggstream);
 
235
        if (!header && (page->segments_count == 255 ||
 
236
            (ogg->pref_size > 0 && page->size >= ogg->pref_size))) {
 
237
           ogg_buffer_page(s, oggstream);
215
238
        }
216
239
    }
217
240
 
313
336
    return 0;
314
337
}
315
338
 
 
339
#define OPUS_HEADER_SIZE 19
 
340
 
 
341
static int ogg_build_opus_headers(AVCodecContext *avctx,
 
342
                                  OGGStreamContext *oggstream, int bitexact,
 
343
                                  AVDictionary **m)
 
344
{
 
345
    uint8_t *p;
 
346
 
 
347
    if (avctx->extradata_size < OPUS_HEADER_SIZE)
 
348
        return -1;
 
349
 
 
350
    /* first packet: Opus header */
 
351
    p = av_mallocz(avctx->extradata_size);
 
352
    if (!p)
 
353
        return AVERROR(ENOMEM);
 
354
    oggstream->header[0] = p;
 
355
    oggstream->header_len[0] = avctx->extradata_size;
 
356
    bytestream_put_buffer(&p, avctx->extradata, avctx->extradata_size);
 
357
 
 
358
    /* second packet: VorbisComment */
 
359
    p = ogg_write_vorbiscomment(8, bitexact, &oggstream->header_len[1], m, 0);
 
360
    if (!p)
 
361
        return AVERROR(ENOMEM);
 
362
    oggstream->header[1] = p;
 
363
    bytestream_put_buffer(&p, "OpusTags", 8);
 
364
 
 
365
    return 0;
 
366
}
 
367
 
316
368
static int ogg_write_header(AVFormatContext *s)
317
369
{
318
370
    OGGStreamContext *oggstream;
323
375
        unsigned serial_num = i;
324
376
 
325
377
        if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO)
326
 
            avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
 
378
            if (st->codec->codec_id == AV_CODEC_ID_OPUS)
 
379
                /* Opus requires a fixed 48kHz clock */
 
380
                avpriv_set_pts_info(st, 64, 1, 48000);
 
381
            else
 
382
                avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
327
383
        else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
328
384
            avpriv_set_pts_info(st, 64, st->codec->time_base.num, st->codec->time_base.den);
329
 
        if (st->codec->codec_id != CODEC_ID_VORBIS &&
330
 
            st->codec->codec_id != CODEC_ID_THEORA &&
331
 
            st->codec->codec_id != CODEC_ID_SPEEX  &&
332
 
            st->codec->codec_id != CODEC_ID_FLAC) {
 
385
        if (st->codec->codec_id != AV_CODEC_ID_VORBIS &&
 
386
            st->codec->codec_id != AV_CODEC_ID_THEORA &&
 
387
            st->codec->codec_id != AV_CODEC_ID_SPEEX  &&
 
388
            st->codec->codec_id != AV_CODEC_ID_FLAC   &&
 
389
            st->codec->codec_id != AV_CODEC_ID_OPUS) {
333
390
            av_log(s, AV_LOG_ERROR, "Unsupported codec id in stream %d\n", i);
334
391
            return -1;
335
392
        }
353
410
        oggstream->serial_num = serial_num;
354
411
 
355
412
        st->priv_data = oggstream;
356
 
        if (st->codec->codec_id == CODEC_ID_FLAC) {
 
413
        if (st->codec->codec_id == AV_CODEC_ID_FLAC) {
357
414
            int err = ogg_build_flac_headers(st->codec, oggstream,
358
415
                                             st->codec->flags & CODEC_FLAG_BITEXACT,
359
416
                                             &s->metadata);
362
419
                av_freep(&st->priv_data);
363
420
                return err;
364
421
            }
365
 
        } else if (st->codec->codec_id == CODEC_ID_SPEEX) {
 
422
        } else if (st->codec->codec_id == AV_CODEC_ID_SPEEX) {
366
423
            int err = ogg_build_speex_headers(st->codec, oggstream,
367
424
                                              st->codec->flags & CODEC_FLAG_BITEXACT,
368
425
                                              &s->metadata);
371
428
                av_freep(&st->priv_data);
372
429
                return err;
373
430
            }
 
431
        } else if (st->codec->codec_id == AV_CODEC_ID_OPUS) {
 
432
            int err = ogg_build_opus_headers(st->codec, oggstream,
 
433
                                             st->codec->flags & CODEC_FLAG_BITEXACT,
 
434
                                             &s->metadata);
 
435
            if (err) {
 
436
                av_log(s, AV_LOG_ERROR, "Error writing Opus headers\n");
 
437
                av_freep(&st->priv_data);
 
438
                return err;
 
439
            }
374
440
        } else {
375
441
            uint8_t *p;
376
 
            const char *cstr = st->codec->codec_id == CODEC_ID_VORBIS ? "vorbis" : "theora";
377
 
            int header_type = st->codec->codec_id == CODEC_ID_VORBIS ? 3 : 0x81;
378
 
            int framing_bit = st->codec->codec_id == CODEC_ID_VORBIS ? 1 : 0;
 
442
            const char *cstr = st->codec->codec_id == AV_CODEC_ID_VORBIS ? "vorbis" : "theora";
 
443
            int header_type = st->codec->codec_id == AV_CODEC_ID_VORBIS ? 3 : 0x81;
 
444
            int framing_bit = st->codec->codec_id == AV_CODEC_ID_VORBIS ? 1 : 0;
379
445
 
380
446
            if (avpriv_split_xiph_headers(st->codec->extradata, st->codec->extradata_size,
381
 
                                      st->codec->codec_id == CODEC_ID_VORBIS ? 30 : 42,
 
447
                                      st->codec->codec_id == AV_CODEC_ID_VORBIS ? 30 : 42,
382
448
                                      oggstream->header, oggstream->header_len) < 0) {
383
449
                av_log(s, AV_LOG_ERROR, "Extradata corrupted\n");
384
450
                av_freep(&st->priv_data);
388
454
            p = ogg_write_vorbiscomment(7, st->codec->flags & CODEC_FLAG_BITEXACT,
389
455
                                        &oggstream->header_len[1], &s->metadata,
390
456
                                        framing_bit);
 
457
            oggstream->header[1] = p;
391
458
            if (!p)
392
459
                return AVERROR(ENOMEM);
393
460
 
394
 
            oggstream->header[1] = p;
395
461
            bytestream_put_byte(&p, header_type);
396
462
            bytestream_put_buffer(&p, cstr, 6);
397
463
 
398
 
            if (st->codec->codec_id == CODEC_ID_THEORA) {
 
464
            if (st->codec->codec_id == AV_CODEC_ID_THEORA) {
399
465
                /** KFGSHIFT is the width of the less significant section of the granule position
400
466
                    The less significant section is the frame count since the last keyframe */
401
467
                oggstream->kfgshift = ((oggstream->header[0][40]&3)<<3)|(oggstream->header[0][41]>>5);
409
475
    for (j = 0; j < s->nb_streams; j++) {
410
476
        OGGStreamContext *oggstream = s->streams[j]->priv_data;
411
477
        ogg_buffer_data(s, s->streams[j], oggstream->header[0],
412
 
                        oggstream->header_len[0], 0);
 
478
                        oggstream->header_len[0], 0, 1);
413
479
        oggstream->page.flags |= 2; // bos
414
480
        ogg_buffer_page(s, oggstream);
415
481
    }
419
485
        for (i = 1; i < 3; i++) {
420
486
            if (oggstream && oggstream->header_len[i])
421
487
                ogg_buffer_data(s, st, oggstream->header[i],
422
 
                                oggstream->header_len[i], 0);
 
488
                                oggstream->header_len[i], 0, 1);
423
489
        }
424
490
        ogg_buffer_page(s, oggstream);
425
491
    }
455
521
    int ret;
456
522
    int64_t granule;
457
523
 
458
 
    if (st->codec->codec_id == CODEC_ID_THEORA) {
 
524
    if (st->codec->codec_id == AV_CODEC_ID_THEORA) {
459
525
        int64_t pts = oggstream->vrev < 1 ? pkt->pts : pkt->pts + pkt->duration;
460
526
        int pframe_count;
461
527
        if (pkt->flags & AV_PKT_FLAG_KEY)
467
533
            pframe_count = 0;
468
534
        }
469
535
        granule = (oggstream->last_kf_pts<<oggstream->kfgshift) | pframe_count;
470
 
    } else
 
536
    } else if (st->codec->codec_id == AV_CODEC_ID_OPUS)
 
537
        granule = pkt->pts + pkt->duration + av_rescale_q(st->codec->delay, (AVRational){ 1, st->codec->sample_rate }, st->time_base);
 
538
    else
471
539
        granule = pkt->pts + pkt->duration;
472
540
 
473
 
    ret = ogg_buffer_data(s, st, pkt->data, pkt->size, granule);
 
541
    ret = ogg_buffer_data(s, st, pkt->data, pkt->size, granule, 0);
474
542
    if (ret < 0)
475
543
        return ret;
476
544
 
494
562
    for (i = 0; i < s->nb_streams; i++) {
495
563
        AVStream *st = s->streams[i];
496
564
        OGGStreamContext *oggstream = st->priv_data;
497
 
        if (st->codec->codec_id == CODEC_ID_FLAC ||
498
 
            st->codec->codec_id == CODEC_ID_SPEEX) {
 
565
        if (st->codec->codec_id == AV_CODEC_ID_FLAC ||
 
566
            st->codec->codec_id == AV_CODEC_ID_SPEEX ||
 
567
            st->codec->codec_id == AV_CODEC_ID_OPUS) {
499
568
            av_free(oggstream->header[0]);
500
 
            av_free(oggstream->header[1]);
501
569
        }
 
570
        av_freep(&oggstream->header[1]);
502
571
        av_freep(&st->priv_data);
503
572
    }
504
573
    return 0;
508
577
    .name              = "ogg",
509
578
    .long_name         = NULL_IF_CONFIG_SMALL("Ogg"),
510
579
    .mime_type         = "application/ogg",
511
 
    .extensions        = "ogg,ogv,spx",
 
580
    .extensions        = "ogg,ogv,spx,opus",
512
581
    .priv_data_size    = sizeof(OGGContext),
513
 
    .audio_codec       = CODEC_ID_FLAC,
514
 
    .video_codec       = CODEC_ID_THEORA,
 
582
    .audio_codec       = AV_CODEC_ID_FLAC,
 
583
    .video_codec       = AV_CODEC_ID_THEORA,
515
584
    .write_header      = ogg_write_header,
516
585
    .write_packet      = ogg_write_packet,
517
586
    .write_trailer     = ogg_write_trailer,
 
587
    .priv_class        = &ogg_muxer_class,
518
588
};