From e00215040ae212522455b55a7bce46c882d43947 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Tue, 25 Sep 2012 19:03:59 +0200 Subject: [PATCH 1/9] get_bits: const correctness for get_bits_trace()/get_xbits_trace() arguments --- libavcodec/get_bits.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/get_bits.h b/libavcodec/get_bits.h index 64393bc9d9..f91441c120 100644 --- a/libavcodec/get_bits.h +++ b/libavcodec/get_bits.h @@ -521,7 +521,7 @@ static inline void print_bin(int bits, int n) av_log(NULL, AV_LOG_DEBUG, " "); } -static inline int get_bits_trace(GetBitContext *s, int n, char *file, +static inline int get_bits_trace(GetBitContext *s, int n, const char *file, const char *func, int line) { int r = get_bits(s, n); @@ -532,7 +532,7 @@ static inline int get_bits_trace(GetBitContext *s, int n, char *file, return r; } static inline int get_vlc_trace(GetBitContext *s, VLC_TYPE (*table)[2], - int bits, int max_depth, char *file, + int bits, int max_depth, const char *file, const char *func, int line) { int show = show_bits(s, 24); @@ -547,7 +547,7 @@ static inline int get_vlc_trace(GetBitContext *s, VLC_TYPE (*table)[2], bits2, len, r, pos, file, func, line); return r; } -static inline int get_xbits_trace(GetBitContext *s, int n, char *file, +static inline int get_xbits_trace(GetBitContext *s, int n, const char *file, const char *func, int line) { int show = show_bits(s, n); From 80412997c868a700fe25eb41ded1c98e80a15164 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Tue, 25 Sep 2012 19:04:47 +0200 Subject: [PATCH 2/9] golomb: const correctness for get_ue()/get_se() function arguments --- libavcodec/golomb.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libavcodec/golomb.h b/libavcodec/golomb.h index b6b8cc8412..3fdec0baec 100644 --- a/libavcodec/golomb.h +++ b/libavcodec/golomb.h @@ -372,7 +372,9 @@ static inline int get_sr_golomb_shorten(GetBitContext* gb, int k) #ifdef TRACE -static inline int get_ue(GetBitContext *s, char *file, const char *func, int line){ +static inline int get_ue(GetBitContext *s, const char *file, const char *func, + int line) +{ int show= show_bits(s, 24); int pos= get_bits_count(s); int i= get_ue_golomb(s); @@ -386,7 +388,9 @@ static inline int get_ue(GetBitContext *s, char *file, const char *func, int lin return i; } -static inline int get_se(GetBitContext *s, char *file, const char *func, int line){ +static inline int get_se(GetBitContext *s, const char *file, const char *func, + int line) +{ int show= show_bits(s, 24); int pos= get_bits_count(s); int i= get_se_golomb(s); From 6c5b0517e00fc22753c5cc0751cba186dd71ed36 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Tue, 25 Sep 2012 19:05:26 +0200 Subject: [PATCH 3/9] h264_refs: Fix debug tprintf argument types --- libavcodec/h264_refs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/h264_refs.c b/libavcodec/h264_refs.c index 273c52b475..2a71ac1f06 100644 --- a/libavcodec/h264_refs.c +++ b/libavcodec/h264_refs.c @@ -146,11 +146,11 @@ int ff_h264_fill_default_ref_list(H264Context *h){ } #ifdef TRACE for (i=0; iref_count[0]; i++) { - tprintf(h->s.avctx, "List0: %s fn:%d 0x%p\n", (h->default_ref_list[0][i].long_ref ? "LT" : "ST"), h->default_ref_list[0][i].pic_id, h->default_ref_list[0][i].data[0]); + tprintf(h->s.avctx, "List0: %s fn:%d 0x%p\n", (h->default_ref_list[0][i].long_ref ? "LT" : "ST"), h->default_ref_list[0][i].pic_id, h->default_ref_list[0][i].f.data[0]); } if(h->slice_type_nos==AV_PICTURE_TYPE_B){ for (i=0; iref_count[1]; i++) { - tprintf(h->s.avctx, "List1: %s fn:%d 0x%p\n", (h->default_ref_list[1][i].long_ref ? "LT" : "ST"), h->default_ref_list[1][i].pic_id, h->default_ref_list[1][i].data[0]); + tprintf(h->s.avctx, "List1: %s fn:%d 0x%p\n", (h->default_ref_list[1][i].long_ref ? "LT" : "ST"), h->default_ref_list[1][i].pic_id, h->default_ref_list[1][i].f.data[0]); } } #endif From bc66827fb1db24796cd1898f4e7dd7407a8c0aca Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Thu, 27 Sep 2012 19:30:37 +0200 Subject: [PATCH 4/9] nutenc: const correctness for ff_put_v_trace/put_s_trace function arguments --- libavformat/nutenc.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libavformat/nutenc.c b/libavformat/nutenc.c index df0301b5e7..29b6dcdaab 100644 --- a/libavformat/nutenc.c +++ b/libavformat/nutenc.c @@ -263,13 +263,17 @@ static void put_s(AVIOContext *bc, int64_t val){ } #ifdef TRACE -static inline void ff_put_v_trace(AVIOContext *bc, uint64_t v, char *file, char *func, int line){ +static inline void ff_put_v_trace(AVIOContext *bc, uint64_t v, const char *file, + const char *func, int line) +{ av_log(NULL, AV_LOG_DEBUG, "ff_put_v %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line); ff_put_v(bc, v); } -static inline void put_s_trace(AVIOContext *bc, int64_t v, char *file, char *func, int line){ +static inline void put_s_trace(AVIOContext *bc, int64_t v, const char *file, + const char *func, int line) +{ av_log(NULL, AV_LOG_DEBUG, "put_s %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line); put_s(bc, v); From 8bd324e9e4b8ceb4d0fff7ebe3c56372949be759 Mon Sep 17 00:00:00 2001 From: Duncan Salerno Date: Sat, 22 Sep 2012 21:17:36 +0100 Subject: [PATCH 5/9] http: Increase buffer sizes to cope with longer URIs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the MAX_URL_SIZE define where applicable. Increase buffer sizes for all buffers that need to fit a long pathname - buffers that need to fit only the hostname (and other short strings, but not the pathname - such as "headers" in http_connect) are kept at 1024 bytes for now. Also increase the max line length in http_read_header, since it might need to contain a full url for Location: redirects. Signed-off-by: Martin Storsjö --- libavformat/http.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/libavformat/http.c b/libavformat/http.c index 041a9b0ff6..43c6cbc032 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -32,8 +32,11 @@ /* XXX: POST protocol is not completely implemented because avconv uses only a subset of it. */ -/* used for protocol handling */ -#define BUFFER_SIZE 1024 +/* The IO buffer size is unrelated to the max URL size in itself, but needs + * to be large enough to fit the full request headers (including long + * path names). + */ +#define BUFFER_SIZE MAX_URL_SIZE #define MAX_REDIRECTS 8 typedef struct { @@ -97,8 +100,8 @@ static int http_open_cnx(URLContext *h) const char *path, *proxy_path, *lower_proto = "tcp", *local_path; char hostname[1024], hoststr[1024], proto[10]; char auth[1024], proxyauth[1024] = ""; - char path1[1024]; - char buf[1024], urlbuf[1024]; + char path1[MAX_URL_SIZE]; + char buf[1024], urlbuf[MAX_URL_SIZE]; int port, use_proxy, err, location_changed = 0, redirects = 0, attempts = 0; HTTPAuthType cur_auth_type, cur_proxy_auth_type; HTTPContext *s = h->priv_data; @@ -349,7 +352,7 @@ static inline int has_header(const char *str, const char *header) static int http_read_header(URLContext *h, int *new_location) { HTTPContext *s = h->priv_data; - char line[1024]; + char line[MAX_URL_SIZE]; int err = 0; s->chunksize = -1; From 4dc8c8386eef942dba35c4f2fb3210e22b511a5b Mon Sep 17 00:00:00 2001 From: Kostya Shishkov Date: Thu, 27 Sep 2012 19:25:06 +0200 Subject: [PATCH 6/9] vc1dec: add flush function for WMV9 and VC-1 decoders CC: libav-stable@libav.org --- libavcodec/vc1dec.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c index 6b2662e8f4..986e4adc5e 100644 --- a/libavcodec/vc1dec.c +++ b/libavcodec/vc1dec.c @@ -5686,6 +5686,7 @@ AVCodec ff_vc1_decoder = { .init = vc1_decode_init, .close = ff_vc1_decode_end, .decode = vc1_decode_frame, + .flush = ff_mpeg_flush, .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY, .long_name = NULL_IF_CONFIG_SMALL("SMPTE VC-1"), .pix_fmts = ff_hwaccel_pixfmt_list_420, @@ -5701,6 +5702,7 @@ AVCodec ff_wmv3_decoder = { .init = vc1_decode_init, .close = ff_vc1_decode_end, .decode = vc1_decode_frame, + .flush = ff_mpeg_flush, .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY, .long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 9"), .pix_fmts = ff_hwaccel_pixfmt_list_420, From e4aa3831b7eda41c51a369f5b98d0a6e76fbbcc7 Mon Sep 17 00:00:00 2001 From: Nathan Caldwell Date: Thu, 27 Sep 2012 22:41:24 -0600 Subject: [PATCH 7/9] avcodec: document the use of AVCodecContext.delay for audio decoding Signed-off-by: Diego Biurrun --- libavcodec/avcodec.h | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index a7aec4e949..59fff22194 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -1449,15 +1449,18 @@ typedef struct AVCodecContext { * encoded input. * * Audio: - * Number of "priming" samples added to the beginning of the stream - * during encoding. The decoded output will be delayed by this many - * samples relative to the input to the encoder. Note that this field is - * purely informational and does not directly affect the pts output by - * the encoder, which should always be based on the actual presentation - * time, including any delay. + * For encoding, this is the number of "priming" samples added to the + * beginning of the stream. The decoded output will be delayed by this + * many samples relative to the input to the encoder. Note that this + * field is purely informational and does not directly affect the pts + * output by the encoder, which should always be based on the actual + * presentation time, including any delay. + * For decoding, this is the number of samples the decoder needs to + * output before the decoder's output is valid. When seeking, you should + * start decoding this many samples prior to your desired seek point. * * - encoding: Set by libavcodec. - * - decoding: unused + * - decoding: Set by libavcodec. */ int delay; From 44617d6ec975b307183d88f0e0b207a9913a8de2 Mon Sep 17 00:00:00 2001 From: Nicolas George Date: Thu, 27 Sep 2012 19:39:23 -0600 Subject: [PATCH 8/9] Opus decoder using libopus Signed-off-by: Diego Biurrun --- Changelog | 1 + configure | 5 + doc/general.texi | 2 + libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/libopusdec.c | 202 ++++++++++++++++++++++++++++++++++++++++ libavcodec/version.h | 2 +- 7 files changed, 213 insertions(+), 1 deletion(-) create mode 100644 libavcodec/libopusdec.c diff --git a/Changelog b/Changelog index 669aa5af75..4cc2f6a826 100644 --- a/Changelog +++ b/Changelog @@ -49,6 +49,7 @@ version : - RTP depacketization of JPEG - Smooth Streaming live segmenter muxer - RTP packetization of JPEG +- Opus decoder using libopus version 0.8: diff --git a/configure b/configure index 4461bdeca2..5080dcf781 100755 --- a/configure +++ b/configure @@ -181,6 +181,7 @@ External library support: --enable-libopencore-amrwb enable AMR-WB decoding via libopencore-amrwb [no] --enable-libopencv enable video filtering via libopencv [no] --enable-libopenjpeg enable JPEG 2000 de/encoding via OpenJPEG [no] + --enable-libopus enable Opus decoding via libopus [no] --enable-libpulse enable Pulseaudio input via libpulse [no] --enable-librtmp enable RTMP[E] support via librtmp [no] --enable-libschroedinger enable Dirac de/encoding via libschroedinger [no] @@ -1009,6 +1010,7 @@ CONFIG_LIST=" libopencore_amrwb libopencv libopenjpeg + libopus libpulse librtmp libschroedinger @@ -1580,6 +1582,7 @@ libopencore_amrnb_encoder_deps="libopencore_amrnb" libopencore_amrwb_decoder_deps="libopencore_amrwb" libopenjpeg_decoder_deps="libopenjpeg" libopenjpeg_encoder_deps="libopenjpeg" +libopus_decoder_deps="libopus" libschroedinger_decoder_deps="libschroedinger" libschroedinger_encoder_deps="libschroedinger" libspeex_decoder_deps="libspeex" @@ -3291,6 +3294,7 @@ enabled libopencore_amrnb && require libopencore_amrnb opencore-amrnb/interf_de enabled libopencore_amrwb && require libopencore_amrwb opencore-amrwb/dec_if.h D_IF_init -lopencore-amrwb enabled libopencv && require_pkg_config opencv opencv/cv.h cvCreateImageHeader enabled libopenjpeg && require libopenjpeg openjpeg.h opj_version -lopenjpeg +enabled libopus && require_pkg_config opus opus_multistream.h opus_multistream_decoder_create enabled libpulse && require_pkg_config libpulse-simple pulse/simple.h pa_simple_new enabled librtmp && require_pkg_config librtmp librtmp/rtmp.h RTMP_Socket enabled libschroedinger && require_pkg_config schroedinger-1.0 schroedinger/schro.h schro_init @@ -3589,6 +3593,7 @@ echo "libopencore-amrnb support ${libopencore_amrnb-no}" echo "libopencore-amrwb support ${libopencore_amrwb-no}" echo "libopencv support ${libopencv-no}" echo "libopenjpeg enabled ${libopenjpeg-no}" +echo "libopus enabled ${libopus-no}" echo "libpulse enabled ${libpulse-no}" echo "librtmp enabled ${librtmp-no}" echo "libschroedinger enabled ${libschroedinger-no}" diff --git a/doc/general.texi b/doc/general.texi index 8415ca3de6..3aeb92b4a5 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -756,6 +756,8 @@ following image formats are supported: @item Musepack SV7 @tab @tab X @item Musepack SV8 @tab @tab X @item Nellymoser Asao @tab X @tab X +@item Opus @tab @tab E + @tab supported through external library libopus @item PCM A-law @tab X @tab X @item PCM mu-law @tab X @tab X @item PCM 16-bit little-endian planar @tab @tab X diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 45c6d6645c..d4537fd4cd 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -581,6 +581,7 @@ OBJS-$(CONFIG_LIBOPENCORE_AMRNB_ENCODER) += libopencore-amr.o OBJS-$(CONFIG_LIBOPENCORE_AMRWB_DECODER) += libopencore-amr.o OBJS-$(CONFIG_LIBOPENJPEG_DECODER) += libopenjpegdec.o OBJS-$(CONFIG_LIBOPENJPEG_ENCODER) += libopenjpegenc.o +OBJS-$(CONFIG_LIBOPUS_DECODER) += libopusdec.o vorbis_data.o OBJS-$(CONFIG_LIBSCHROEDINGER_DECODER) += libschroedingerdec.o \ libschroedinger.o OBJS-$(CONFIG_LIBSCHROEDINGER_ENCODER) += libschroedingerenc.o \ diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index c6df818477..7881831855 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -393,6 +393,7 @@ void avcodec_register_all(void) REGISTER_ENCDEC (LIBOPENCORE_AMRNB, libopencore_amrnb); REGISTER_DECODER (LIBOPENCORE_AMRWB, libopencore_amrwb); REGISTER_ENCDEC (LIBOPENJPEG, libopenjpeg); + REGISTER_DECODER (LIBOPUS, libopus); REGISTER_ENCDEC (LIBSCHROEDINGER, libschroedinger); REGISTER_ENCDEC (LIBSPEEX, libspeex); REGISTER_ENCODER (LIBTHEORA, libtheora); diff --git a/libavcodec/libopusdec.c b/libavcodec/libopusdec.c new file mode 100644 index 0000000000..9d24e6e33b --- /dev/null +++ b/libavcodec/libopusdec.c @@ -0,0 +1,202 @@ +/* + * Opus decoder using libopus + * Copyright (c) 2012 Nicolas George + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "libavutil/common.h" +#include "libavutil/avassert.h" +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "vorbis.h" +#include "mathops.h" + +struct libopus_context { + OpusMSDecoder *dec; + AVFrame frame; +}; + +static int opus_error_to_averror(int err) +{ + switch (err) { + case OPUS_BAD_ARG: + return AVERROR(EINVAL); + case OPUS_BUFFER_TOO_SMALL: + return AVERROR_UNKNOWN; + case OPUS_INTERNAL_ERROR: + return AVERROR(EFAULT); + case OPUS_INVALID_PACKET: + return AVERROR_INVALIDDATA; + case OPUS_UNIMPLEMENTED: + return AVERROR(ENOSYS); + case OPUS_INVALID_STATE: + return AVERROR_UNKNOWN; + case OPUS_ALLOC_FAIL: + return AVERROR(ENOMEM); + default: + return AVERROR(EINVAL); + } +} + +static inline void reorder(uint8_t *data, unsigned channels, unsigned bps, + unsigned samples, const uint8_t *map) +{ + uint8_t tmp[8 * 4]; + unsigned i; + + av_assert1(channels * bps <= sizeof(tmp)); + for (; samples > 0; samples--) { + for (i = 0; i < channels; i++) + memcpy(tmp + bps * i, data + bps * map[i], bps); + memcpy(data, tmp, bps * channels); + data += bps * channels; + } +} + +#define OPUS_HEAD_SIZE 19 + +static av_cold int libopus_decode_init(AVCodecContext *avc) +{ + struct libopus_context *opus = avc->priv_data; + int ret, channel_map = 0, gain_db = 0, nb_streams, nb_coupled; + uint8_t mapping_stereo[] = { 0, 1 }, *mapping; + + avc->sample_rate = 48000; + avc->sample_fmt = avc->request_sample_fmt == AV_SAMPLE_FMT_FLT ? + AV_SAMPLE_FMT_FLT : AV_SAMPLE_FMT_S16; + avc->channel_layout = avc->channels > 8 ? 0 : + ff_vorbis_channel_layouts[avc->channels - 1]; + + if (avc->extradata_size >= OPUS_HEAD_SIZE) { + gain_db = sign_extend(AV_RL16(avc->extradata + 16), 16); + channel_map = AV_RL8 (avc->extradata + 18); + } + if (avc->extradata_size >= OPUS_HEAD_SIZE + 2 + avc->channels) { + nb_streams = avc->extradata[OPUS_HEAD_SIZE + 0]; + nb_coupled = avc->extradata[OPUS_HEAD_SIZE + 1]; + if (nb_streams + nb_coupled != avc->channels) + av_log(avc, AV_LOG_WARNING, "Inconsistent channel mapping.\n"); + mapping = avc->extradata + OPUS_HEAD_SIZE + 2; + } else { + if (avc->channels > 2 || channel_map) { + av_log(avc, AV_LOG_ERROR, + "No channel mapping for %d channels.\n", avc->channels); + return AVERROR(EINVAL); + } + nb_streams = 1; + nb_coupled = avc->channels > 1; + mapping = mapping_stereo; + } + + opus->dec = opus_multistream_decoder_create(avc->sample_rate, avc->channels, + nb_streams, nb_coupled, + mapping, &ret); + if (!opus->dec) { + av_log(avc, AV_LOG_ERROR, "Unable to create decoder: %s\n", + opus_strerror(ret)); + return opus_error_to_averror(ret); + } + + ret = opus_multistream_decoder_ctl(opus->dec, OPUS_SET_GAIN(gain_db)); + if (ret != OPUS_OK) + av_log(avc, AV_LOG_WARNING, "Failed to set gain: %s\n", + opus_strerror(ret)); + + avc->delay = 3840; /* Decoder delay (in samples) at 48kHz */ + avcodec_get_frame_defaults(&opus->frame); + avc->coded_frame = &opus->frame; + return 0; +} + +static av_cold int libopus_decode_close(AVCodecContext *avc) +{ + struct libopus_context *opus = avc->priv_data; + + opus_multistream_decoder_destroy(opus->dec); + return 0; +} + +#define MAX_FRAME_SIZE (960 * 6) + +static int libopus_decode(AVCodecContext *avc, void *frame, + int *got_frame_ptr, AVPacket *pkt) +{ + struct libopus_context *opus = avc->priv_data; + int ret, nb_samples; + + opus->frame.nb_samples = MAX_FRAME_SIZE; + ret = avc->get_buffer(avc, &opus->frame); + if (ret < 0) { + av_log(avc, AV_LOG_ERROR, "get_buffer() failed\n"); + return ret; + } + + if (avc->sample_fmt == AV_SAMPLE_FMT_S16) + nb_samples = opus_multistream_decode(opus->dec, pkt->data, pkt->size, + (opus_int16 *)opus->frame.data[0], + opus->frame.nb_samples, 0); + else + nb_samples = opus_multistream_decode_float(opus->dec, pkt->data, pkt->size, + (float *)opus->frame.data[0], + opus->frame.nb_samples, 0); + + if (nb_samples < 0) { + av_log(avc, AV_LOG_ERROR, "Decoding error: %s\n", + opus_strerror(nb_samples)); + return opus_error_to_averror(nb_samples); + } + + if (avc->channels > 3 && avc->channels <= 8) { + const uint8_t *m = ff_vorbis_channel_layout_offsets[avc->channels - 1]; + if (avc->sample_fmt == AV_SAMPLE_FMT_S16) + reorder(opus->frame.data[0], avc->channels, 2, nb_samples, m); + else + reorder(opus->frame.data[0], avc->channels, 4, nb_samples, m); + } + + opus->frame.nb_samples = nb_samples; + *(AVFrame *)frame = opus->frame; + *got_frame_ptr = 1; + return pkt->size; +} + +static void libopus_flush(AVCodecContext *avc) +{ + struct libopus_context *opus = avc->priv_data; + + opus_multistream_decoder_ctl(opus->dec, OPUS_RESET_STATE); +} + +AVCodec ff_libopus_decoder = { + .name = "libopus", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_OPUS, + .priv_data_size = sizeof(struct libopus_context), + .init = libopus_decode_init, + .close = libopus_decode_close, + .decode = libopus_decode, + .flush = libopus_flush, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("libopus Opus"), + .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLT, + AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_NONE }, +}; diff --git a/libavcodec/version.h b/libavcodec/version.h index ee70842d0e..8844502d58 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -27,7 +27,7 @@ */ #define LIBAVCODEC_VERSION_MAJOR 54 -#define LIBAVCODEC_VERSION_MINOR 29 +#define LIBAVCODEC_VERSION_MINOR 30 #define LIBAVCODEC_VERSION_MICRO 0 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ From d16860a237ae56a21d051df6556c40de9be53faa Mon Sep 17 00:00:00 2001 From: Nathan Caldwell Date: Thu, 27 Sep 2012 02:23:29 -0600 Subject: [PATCH 9/9] libopus: Remap channels using libopus' internal remapping. This way we can directly remap channels from Opus' channel order to libav's internal channel order, instead of mapping channels from Opus' order to Vorbis' order then to libav's order. Signed-off-by: Diego Biurrun --- libavcodec/libopusdec.c | 37 ++++++++++++------------------------- 1 file changed, 12 insertions(+), 25 deletions(-) diff --git a/libavcodec/libopusdec.c b/libavcodec/libopusdec.c index 9d24e6e33b..4335bd6eca 100644 --- a/libavcodec/libopusdec.c +++ b/libavcodec/libopusdec.c @@ -56,28 +56,13 @@ static int opus_error_to_averror(int err) } } -static inline void reorder(uint8_t *data, unsigned channels, unsigned bps, - unsigned samples, const uint8_t *map) -{ - uint8_t tmp[8 * 4]; - unsigned i; - - av_assert1(channels * bps <= sizeof(tmp)); - for (; samples > 0; samples--) { - for (i = 0; i < channels; i++) - memcpy(tmp + bps * i, data + bps * map[i], bps); - memcpy(data, tmp, bps * channels); - data += bps * channels; - } -} - #define OPUS_HEAD_SIZE 19 static av_cold int libopus_decode_init(AVCodecContext *avc) { struct libopus_context *opus = avc->priv_data; int ret, channel_map = 0, gain_db = 0, nb_streams, nb_coupled; - uint8_t mapping_stereo[] = { 0, 1 }, *mapping; + uint8_t mapping_arr[8] = { 0, 1 }, *mapping; avc->sample_rate = 48000; avc->sample_fmt = avc->request_sample_fmt == AV_SAMPLE_FMT_FLT ? @@ -103,7 +88,17 @@ static av_cold int libopus_decode_init(AVCodecContext *avc) } nb_streams = 1; nb_coupled = avc->channels > 1; - mapping = mapping_stereo; + mapping = mapping_arr; + } + + if (avc->channels > 2 && avc->channels <= 8) { + const uint8_t *vorbis_offset = ff_vorbis_channel_layout_offsets[avc->channels - 1]; + int ch; + + /* Remap channels from vorbis order to libav order */ + for (ch = 0; ch < avc->channels; ch++) + mapping_arr[ch] = mapping[vorbis_offset[ch]]; + mapping = mapping_arr; } opus->dec = opus_multistream_decoder_create(avc->sample_rate, avc->channels, @@ -164,14 +159,6 @@ static int libopus_decode(AVCodecContext *avc, void *frame, return opus_error_to_averror(nb_samples); } - if (avc->channels > 3 && avc->channels <= 8) { - const uint8_t *m = ff_vorbis_channel_layout_offsets[avc->channels - 1]; - if (avc->sample_fmt == AV_SAMPLE_FMT_S16) - reorder(opus->frame.data[0], avc->channels, 2, nb_samples, m); - else - reorder(opus->frame.data[0], avc->channels, 4, nb_samples, m); - } - opus->frame.nb_samples = nb_samples; *(AVFrame *)frame = opus->frame; *got_frame_ptr = 1;