yading@10: /* yading@10: * Opus decoder using libopus yading@10: * Copyright (c) 2012 Nicolas George yading@10: * yading@10: * This file is part of FFmpeg. yading@10: * yading@10: * FFmpeg is free software; you can redistribute it and/or yading@10: * modify it under the terms of the GNU Lesser General Public yading@10: * License as published by the Free Software Foundation; either yading@10: * version 2.1 of the License, or (at your option) any later version. yading@10: * yading@10: * FFmpeg is distributed in the hope that it will be useful, yading@10: * but WITHOUT ANY WARRANTY; without even the implied warranty of yading@10: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU yading@10: * Lesser General Public License for more details. yading@10: * yading@10: * You should have received a copy of the GNU Lesser General Public yading@10: * License along with FFmpeg; if not, write to the Free Software yading@10: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA yading@10: */ yading@10: yading@10: #include yading@10: #include yading@10: yading@10: #include "libavutil/avassert.h" yading@10: #include "libavutil/intreadwrite.h" yading@10: #include "avcodec.h" yading@10: #include "internal.h" yading@10: #include "vorbis.h" yading@10: #include "mathops.h" yading@10: #include "libopus.h" yading@10: yading@10: struct libopus_context { yading@10: OpusMSDecoder *dec; yading@10: int pre_skip; yading@10: #ifndef OPUS_SET_GAIN yading@10: union { int i; double d; } gain; yading@10: #endif yading@10: }; yading@10: yading@10: #define OPUS_HEAD_SIZE 19 yading@10: yading@10: static av_cold int libopus_decode_init(AVCodecContext *avc) yading@10: { yading@10: struct libopus_context *opus = avc->priv_data; yading@10: int ret, channel_map = 0, gain_db = 0, nb_streams, nb_coupled; yading@10: uint8_t mapping_arr[8] = { 0, 1 }, *mapping; yading@10: yading@10: avc->sample_rate = 48000; yading@10: avc->sample_fmt = avc->request_sample_fmt == AV_SAMPLE_FMT_FLT ? yading@10: AV_SAMPLE_FMT_FLT : AV_SAMPLE_FMT_S16; yading@10: avc->channel_layout = avc->channels > 8 ? 0 : yading@10: ff_vorbis_channel_layouts[avc->channels - 1]; yading@10: yading@10: if (avc->extradata_size >= OPUS_HEAD_SIZE) { yading@10: opus->pre_skip = AV_RL16(avc->extradata + 10); yading@10: gain_db = sign_extend(AV_RL16(avc->extradata + 16), 16); yading@10: channel_map = AV_RL8 (avc->extradata + 18); yading@10: } yading@10: if (avc->extradata_size >= OPUS_HEAD_SIZE + 2 + avc->channels) { yading@10: nb_streams = avc->extradata[OPUS_HEAD_SIZE + 0]; yading@10: nb_coupled = avc->extradata[OPUS_HEAD_SIZE + 1]; yading@10: if (nb_streams + nb_coupled != avc->channels) yading@10: av_log(avc, AV_LOG_WARNING, "Inconsistent channel mapping.\n"); yading@10: mapping = avc->extradata + OPUS_HEAD_SIZE + 2; yading@10: } else { yading@10: if (avc->channels > 2 || channel_map) { yading@10: av_log(avc, AV_LOG_ERROR, yading@10: "No channel mapping for %d channels.\n", avc->channels); yading@10: return AVERROR(EINVAL); yading@10: } yading@10: nb_streams = 1; yading@10: nb_coupled = avc->channels > 1; yading@10: mapping = mapping_arr; yading@10: } yading@10: yading@10: if (avc->channels > 2 && avc->channels <= 8) { yading@10: const uint8_t *vorbis_offset = ff_vorbis_channel_layout_offsets[avc->channels - 1]; yading@10: int ch; yading@10: yading@10: /* Remap channels from vorbis order to ffmpeg order */ yading@10: for (ch = 0; ch < avc->channels; ch++) yading@10: mapping_arr[ch] = mapping[vorbis_offset[ch]]; yading@10: mapping = mapping_arr; yading@10: } yading@10: yading@10: opus->dec = opus_multistream_decoder_create(avc->sample_rate, avc->channels, yading@10: nb_streams, nb_coupled, yading@10: mapping, &ret); yading@10: if (!opus->dec) { yading@10: av_log(avc, AV_LOG_ERROR, "Unable to create decoder: %s\n", yading@10: opus_strerror(ret)); yading@10: return ff_opus_error_to_averror(ret); yading@10: } yading@10: yading@10: #ifdef OPUS_SET_GAIN yading@10: ret = opus_multistream_decoder_ctl(opus->dec, OPUS_SET_GAIN(gain_db)); yading@10: if (ret != OPUS_OK) yading@10: av_log(avc, AV_LOG_WARNING, "Failed to set gain: %s\n", yading@10: opus_strerror(ret)); yading@10: #else yading@10: { yading@10: double gain_lin = pow(10, gain_db / (20.0 * 256)); yading@10: if (avc->sample_fmt == AV_SAMPLE_FMT_FLT) yading@10: opus->gain.d = gain_lin; yading@10: else yading@10: opus->gain.i = FFMIN(gain_lin * 65536, INT_MAX); yading@10: } yading@10: #endif yading@10: yading@10: avc->internal->skip_samples = opus->pre_skip; yading@10: avc->delay = 3840; /* Decoder delay (in samples) at 48kHz */ yading@10: yading@10: return 0; yading@10: } yading@10: yading@10: static av_cold int libopus_decode_close(AVCodecContext *avc) yading@10: { yading@10: struct libopus_context *opus = avc->priv_data; yading@10: yading@10: opus_multistream_decoder_destroy(opus->dec); yading@10: return 0; yading@10: } yading@10: yading@10: #define MAX_FRAME_SIZE (960 * 6) yading@10: yading@10: static int libopus_decode(AVCodecContext *avc, void *data, yading@10: int *got_frame_ptr, AVPacket *pkt) yading@10: { yading@10: struct libopus_context *opus = avc->priv_data; yading@10: AVFrame *frame = data; yading@10: int ret, nb_samples; yading@10: yading@10: frame->nb_samples = MAX_FRAME_SIZE; yading@10: if ((ret = ff_get_buffer(avc, frame, 0)) < 0) yading@10: return ret; yading@10: yading@10: if (avc->sample_fmt == AV_SAMPLE_FMT_S16) yading@10: nb_samples = opus_multistream_decode(opus->dec, pkt->data, pkt->size, yading@10: (opus_int16 *)frame->data[0], yading@10: frame->nb_samples, 0); yading@10: else yading@10: nb_samples = opus_multistream_decode_float(opus->dec, pkt->data, pkt->size, yading@10: (float *)frame->data[0], yading@10: frame->nb_samples, 0); yading@10: yading@10: if (nb_samples < 0) { yading@10: av_log(avc, AV_LOG_ERROR, "Decoding error: %s\n", yading@10: opus_strerror(nb_samples)); yading@10: return ff_opus_error_to_averror(nb_samples); yading@10: } yading@10: yading@10: #ifndef OPUS_SET_GAIN yading@10: { yading@10: int i = avc->channels * nb_samples; yading@10: if (avc->sample_fmt == AV_SAMPLE_FMT_FLT) { yading@10: float *pcm = (float *)frame->data[0]; yading@10: for (; i > 0; i--, pcm++) yading@10: *pcm = av_clipf(*pcm * opus->gain.d, -1, 1); yading@10: } else { yading@10: int16_t *pcm = (int16_t *)frame->data[0]; yading@10: for (; i > 0; i--, pcm++) yading@10: *pcm = av_clip_int16(((int64_t)opus->gain.i * *pcm) >> 16); yading@10: } yading@10: } yading@10: #endif yading@10: yading@10: frame->nb_samples = nb_samples; yading@10: *got_frame_ptr = 1; yading@10: yading@10: return pkt->size; yading@10: } yading@10: yading@10: static void libopus_flush(AVCodecContext *avc) yading@10: { yading@10: struct libopus_context *opus = avc->priv_data; yading@10: yading@10: opus_multistream_decoder_ctl(opus->dec, OPUS_RESET_STATE); yading@10: /* The stream can have been extracted by a tool that is not Opus-aware. yading@10: Therefore, any packet can become the first of the stream. */ yading@10: avc->internal->skip_samples = opus->pre_skip; yading@10: } yading@10: yading@10: AVCodec ff_libopus_decoder = { yading@10: .name = "libopus", yading@10: .type = AVMEDIA_TYPE_AUDIO, yading@10: .id = AV_CODEC_ID_OPUS, yading@10: .priv_data_size = sizeof(struct libopus_context), yading@10: .init = libopus_decode_init, yading@10: .close = libopus_decode_close, yading@10: .decode = libopus_decode, yading@10: .flush = libopus_flush, yading@10: .capabilities = CODEC_CAP_DR1, yading@10: .long_name = NULL_IF_CONFIG_SMALL("libopus Opus"), yading@10: .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLT, yading@10: AV_SAMPLE_FMT_S16, yading@10: AV_SAMPLE_FMT_NONE }, yading@10: };