diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2012-09-28 04:54:38 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2012-09-28 05:11:19 +0200 |
commit | 7ed9ec033f5f8da5c06ec5f53847dbdbbf8e9dbb (patch) | |
tree | fa7298f52d823bdcb8c81243c85ea18b7b947432 /libavformat | |
parent | ac7d0c79c3f6b4ca5a9d1b333107684453191811 (diff) | |
parent | 4e5b7f31f7aa7a40ef6d255db2cd65ebab7b74db (diff) | |
download | ffmpeg-7ed9ec033f5f8da5c06ec5f53847dbdbbf8e9dbb.tar.gz |
Merge remote-tracking branch 'qatar/master'
* qatar/master:
dwt: Drop unused functions spatial_compose{53|97}i()
nutdec: Remove unused and broken debug function stub
avcodec: Drop long-deprecated imgconvert.h header
Add Opus support to the Ogg muxer.
Add Opus codec id and codec description.
avformat: Identify anonymous AVIO typedef structs.
Conflicts:
libavcodec/avcodec.h
libavcodec/codec_desc.c
libavcodec/imgconvert.h
libavcodec/version.h
libavformat/oggenc.c
libavformat/version.h
Merged-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavformat')
-rw-r--r-- | libavformat/avio.h | 4 | ||||
-rw-r--r-- | libavformat/oggenc.c | 56 | ||||
-rw-r--r-- | libavformat/version.h | 2 |
3 files changed, 54 insertions, 8 deletions
diff --git a/libavformat/avio.h b/libavformat/avio.h index 08e9dd3659..b16d26f044 100644 --- a/libavformat/avio.h +++ b/libavformat/avio.h @@ -48,7 +48,7 @@ * new elements have been added after this struct in AVFormatContext * or AVIOContext. */ -typedef struct { +typedef struct AVIOInterruptCB { int (*callback)(void*); void *opaque; } AVIOInterruptCB; @@ -65,7 +65,7 @@ typedef struct { * when implementing custom I/O. Normally these are set to the * function pointers specified in avio_alloc_context() */ -typedef struct { +typedef struct AVIOContext { /** * A class for private options. * diff --git a/libavformat/oggenc.c b/libavformat/oggenc.c index ae386884c7..4871a0e34f 100644 --- a/libavformat/oggenc.c +++ b/libavformat/oggenc.c @@ -349,6 +349,35 @@ static int ogg_build_speex_headers(AVCodecContext *avctx, return 0; } +#define OPUS_HEADER_SIZE 19 + +static int ogg_build_opus_headers(AVCodecContext *avctx, + OGGStreamContext *oggstream, int bitexact, + AVDictionary **m) +{ + uint8_t *p; + + if (avctx->extradata_size < OPUS_HEADER_SIZE) + return -1; + + /* first packet: Opus header */ + p = av_mallocz(avctx->extradata_size); + if (!p) + return AVERROR(ENOMEM); + oggstream->header[0] = p; + oggstream->header_len[0] = avctx->extradata_size; + bytestream_put_buffer(&p, avctx->extradata, avctx->extradata_size); + + /* second packet: VorbisComment */ + p = ogg_write_vorbiscomment(8, bitexact, &oggstream->header_len[1], m, 0); + if (!p) + return AVERROR(ENOMEM); + oggstream->header[1] = p; + bytestream_put_buffer(&p, "OpusTags", 8); + + return 0; +} + static int ogg_write_header(AVFormatContext *s) { OGGStreamContext *oggstream; @@ -359,13 +388,18 @@ static int ogg_write_header(AVFormatContext *s) unsigned serial_num = i; if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) - avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); + if (st->codec->codec_id == AV_CODEC_ID_OPUS) + /* Opus requires a fixed 48kHz clock */ + avpriv_set_pts_info(st, 64, 1, 48000); + else + avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) avpriv_set_pts_info(st, 64, st->codec->time_base.num, st->codec->time_base.den); if (st->codec->codec_id != AV_CODEC_ID_VORBIS && st->codec->codec_id != AV_CODEC_ID_THEORA && st->codec->codec_id != AV_CODEC_ID_SPEEX && - st->codec->codec_id != AV_CODEC_ID_FLAC) { + st->codec->codec_id != AV_CODEC_ID_FLAC && + st->codec->codec_id != AV_CODEC_ID_OPUS) { av_log(s, AV_LOG_ERROR, "Unsupported codec id in stream %d\n", i); return -1; } @@ -407,6 +441,15 @@ static int ogg_write_header(AVFormatContext *s) av_freep(&st->priv_data); return err; } + } else if (st->codec->codec_id == AV_CODEC_ID_OPUS) { + int err = ogg_build_opus_headers(st->codec, oggstream, + st->codec->flags & CODEC_FLAG_BITEXACT, + &s->metadata); + if (err) { + av_log(s, AV_LOG_ERROR, "Error writing Opus headers\n"); + av_freep(&st->priv_data); + return err; + } } else { uint8_t *p; const char *cstr = st->codec->codec_id == AV_CODEC_ID_VORBIS ? "vorbis" : "theora"; @@ -503,7 +546,9 @@ static int ogg_write_packet(AVFormatContext *s, AVPacket *pkt) pframe_count = 0; } granule = (oggstream->last_kf_pts<<oggstream->kfgshift) | pframe_count; - } else + } else if (st->codec->codec_id == AV_CODEC_ID_OPUS) + granule = pkt->pts + pkt->duration + av_rescale_q(st->codec->delay, (AVRational){ 1, st->codec->sample_rate }, st->time_base); + else granule = pkt->pts + pkt->duration; ret = ogg_buffer_data(s, st, pkt->data, pkt->size, granule, 0); @@ -531,7 +576,8 @@ static int ogg_write_trailer(AVFormatContext *s) AVStream *st = s->streams[i]; OGGStreamContext *oggstream = st->priv_data; if (st->codec->codec_id == AV_CODEC_ID_FLAC || - st->codec->codec_id == AV_CODEC_ID_SPEEX) { + st->codec->codec_id == AV_CODEC_ID_SPEEX || + st->codec->codec_id == AV_CODEC_ID_OPUS) { av_freep(&oggstream->header[0]); } av_freep(&oggstream->header[1]); @@ -544,7 +590,7 @@ AVOutputFormat ff_ogg_muxer = { .name = "ogg", .long_name = NULL_IF_CONFIG_SMALL("Ogg"), .mime_type = "application/ogg", - .extensions = "ogg,ogv,spx", + .extensions = "ogg,ogv,spx,opus", .priv_data_size = sizeof(OGGContext), .audio_codec = AV_CODEC_ID_FLAC, .video_codec = AV_CODEC_ID_THEORA, diff --git a/libavformat/version.h b/libavformat/version.h index 26cbbcfe42..32a70d2792 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -31,7 +31,7 @@ #define LIBAVFORMAT_VERSION_MAJOR 54 #define LIBAVFORMAT_VERSION_MINOR 29 -#define LIBAVFORMAT_VERSION_MICRO 104 +#define LIBAVFORMAT_VERSION_MICRO 105 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \ |