diff options
Diffstat (limited to 'libavcodec/libopusenc.c')
-rw-r--r-- | libavcodec/libopusenc.c | 49 |
1 files changed, 37 insertions, 12 deletions
diff --git a/libavcodec/libopusenc.c b/libavcodec/libopusenc.c index 9af8bcda7e..8ceb877f38 100644 --- a/libavcodec/libopusenc.c +++ b/libavcodec/libopusenc.c @@ -2,20 +2,20 @@ * Opus encoder using libopus * Copyright (c) 2012 Nathan Caldwell * - * This file is part of libav. + * This file is part of FFmpeg. * - * libav is free software; you can redistribute it and/or + * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * libav is distributed in the hope that it will be useful, + * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -65,8 +65,8 @@ static const uint8_t opus_vorbis_channel_map[8][8] = { { 0, 6, 1, 2, 3, 4, 5, 7 }, }; -/* libav to libopus channel order mapping, passed to libopus */ -static const uint8_t libav_libopus_channel_map[8][8] = { +/* libavcodec to libopus channel order mapping, passed to libopus */ +static const uint8_t libavcodec_libopus_channel_map[8][8] = { { 0 }, { 0, 1 }, { 0, 1, 2 }, @@ -107,6 +107,13 @@ static int libopus_configure_encoder(AVCodecContext *avctx, OpusMSEncoder *enc, { int ret; + if (avctx->global_quality) { + av_log(avctx, AV_LOG_ERROR, + "Quality-based encoding not supported, " + "please specify a bitrate and VBR setting.\n"); + return AVERROR(EINVAL); + } + ret = opus_multistream_encoder_ctl(enc, OPUS_SET_BITRATE(avctx->bit_rate)); if (ret != OPUS_OK) { av_log(avctx, AV_LOG_ERROR, @@ -149,7 +156,7 @@ static int libopus_configure_encoder(AVCodecContext *avctx, OpusMSEncoder *enc, return OPUS_OK; } -static int av_cold libopus_encode_init(AVCodecContext *avctx) +static av_cold int libopus_encode_init(AVCodecContext *avctx) { LibopusEncContext *opus = avctx->priv_data; const uint8_t *channel_mapping; @@ -159,7 +166,7 @@ static int av_cold libopus_encode_init(AVCodecContext *avctx) coupled_stream_count = opus_coupled_streams[avctx->channels - 1]; opus->stream_count = avctx->channels - coupled_stream_count; - channel_mapping = libav_libopus_channel_map[avctx->channels - 1]; + channel_mapping = libavcodec_libopus_channel_map[avctx->channels - 1]; /* FIXME: Opus can handle up to 255 channels. However, the mapping for * anything greater than 8 is undefined. */ @@ -306,6 +313,7 @@ static int libopus_encode(AVCodecContext *avctx, AVPacket *avpkt, av_get_bytes_per_sample(avctx->sample_fmt); uint8_t *audio; int ret; + int discard_padding; if (frame) { ff_af_queue_add(&opus->afq, frame); @@ -324,10 +332,8 @@ static int libopus_encode(AVCodecContext *avctx, AVPacket *avpkt, /* Maximum packet size taken from opusenc in opus-tools. 60ms packets * consist of 3 frames in one packet. The maximum frame size is 1275 * bytes along with the largest possible packet header of 7 bytes. */ - if (ret = ff_alloc_packet(avpkt, (1275 * 3 + 7) * opus->stream_count)) { - av_log(avctx, AV_LOG_ERROR, "Error getting output packet\n"); + if ((ret = ff_alloc_packet2(avctx, avpkt, (1275 * 3 + 7) * opus->stream_count)) < 0) return ret; - } if (avctx->sample_fmt == AV_SAMPLE_FMT_FLT) ret = opus_multistream_encode_float(opus->enc, (float *)audio, @@ -349,12 +355,31 @@ static int libopus_encode(AVCodecContext *avctx, AVPacket *avpkt, ff_af_queue_remove(&opus->afq, opus->opts.packet_size, &avpkt->pts, &avpkt->duration); + discard_padding = opus->opts.packet_size - avpkt->duration; + // Check if subtraction resulted in an overflow + if ((discard_padding < opus->opts.packet_size) != (avpkt->duration > 0)) { + av_free_packet(avpkt); + av_free(avpkt); + return AVERROR(EINVAL); + } + if (discard_padding > 0) { + uint8_t* side_data = av_packet_new_side_data(avpkt, + AV_PKT_DATA_SKIP_SAMPLES, + 10); + if(side_data == NULL) { + av_free_packet(avpkt); + av_free(avpkt); + return AVERROR(ENOMEM); + } + AV_WL32(side_data + 4, discard_padding); + } + *got_packet_ptr = 1; return 0; } -static int av_cold libopus_encode_close(AVCodecContext *avctx) +static av_cold int libopus_encode_close(AVCodecContext *avctx) { LibopusEncContext *opus = avctx->priv_data; |