summaryrefslogtreecommitdiffstats
path: root/libavformat/oggenc.c
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2012-09-28 04:54:38 +0200
committerMichael Niedermayer <michaelni@gmx.at>2012-09-28 05:11:19 +0200
commit7ed9ec033f5f8da5c06ec5f53847dbdbbf8e9dbb (patch)
treefa7298f52d823bdcb8c81243c85ea18b7b947432 /libavformat/oggenc.c
parentac7d0c79c3f6b4ca5a9d1b333107684453191811 (diff)
parent4e5b7f31f7aa7a40ef6d255db2cd65ebab7b74db (diff)
downloadffmpeg-streaming-7ed9ec033f5f8da5c06ec5f53847dbdbbf8e9dbb.zip
ffmpeg-streaming-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/oggenc.c')
-rw-r--r--libavformat/oggenc.c56
1 files changed, 51 insertions, 5 deletions
diff --git a/libavformat/oggenc.c b/libavformat/oggenc.c
index ae38688..4871a0e 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,
OpenPOWER on IntegriCloud