Ticket #1343: 0001-Xiph-IETF-Opus-decoder-using-libopus.patch
| File 0001-Xiph-IETF-Opus-decoder-using-libopus.patch, 14.5 KB (added by haxar, 13 months ago) |
|---|
-
configure
From 9ec266a5b67b221d828edc8d4e526460d973859f Mon Sep 17 00:00:00 2001 From: haxar <grezski@gmail.com> Date: Tue, 22 May 2012 14:47:37 -0700 Subject: [PATCH] Xiph/IETF Opus decoder using libopus. --- configure | 5 ++ libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/avcodec.h | 1 + libavcodec/libopusdec.c | 129 ++++++++++++++++++++++++++++++++++++++++++++ libavformat/Makefile | 1 + libavformat/oggdec.c | 1 + libavformat/oggdec.h | 1 + libavformat/oggparseopus.c | 103 +++++++++++++++++++++++++++++++++++ 9 files changed, 243 insertions(+) create mode 100644 libavcodec/libopusdec.c create mode 100644 libavformat/oggparseopus.c diff --git a/configure b/configure index e070c0b..4df63ad 100755
a b External library support: 188 188 --enable-libnut enable NUT (de)muxing via libnut, 189 189 native (de)muxer exists [no] 190 190 --enable-libopenjpeg enable JPEG 2000 encoding/decoding via OpenJPEG [no] 191 --enable-libopus enable Opus decoding via libopus [no] 191 192 --enable-libpulse enable Pulseaudio input via libpulse [no] 192 193 --enable-librtmp enable RTMP[E] support via librtmp [no] 193 194 --enable-libschroedinger enable Dirac support via libschroedinger [no] … … CONFIG_LIST=" 1046 1047 libopencore_amrwb 1047 1048 libopencv 1048 1049 libopenjpeg 1050 libopus 1049 1051 libpulse 1050 1052 librtmp 1051 1053 libschroedinger … … libopencore_amrnb_encoder_deps="libopencore_amrnb" 1571 1573 libopencore_amrwb_decoder_deps="libopencore_amrwb" 1572 1574 libopenjpeg_decoder_deps="libopenjpeg" 1573 1575 libopenjpeg_encoder_deps="libopenjpeg" 1576 libopus_decoder_deps="libopus" 1574 1577 libschroedinger_decoder_deps="libschroedinger" 1575 1578 libschroedinger_encoder_deps="libschroedinger" 1576 1579 libspeex_decoder_deps="libspeex" … … enabled libopencore_amrnb && require libopencore_amrnb opencore-amrnb/interf_de 3219 3222 enabled libopencore_amrwb && require libopencore_amrwb opencore-amrwb/dec_if.h D_IF_init -lopencore-amrwb 3220 3223 enabled libopencv && require_pkg_config opencv opencv/cxcore.h cvCreateImageHeader 3221 3224 enabled libopenjpeg && require libopenjpeg openjpeg.h opj_version -lopenjpeg 3225 enabled libopus && require libopus opus/opus.h opus_decode -lopus 3222 3226 enabled libpulse && require_pkg_config libpulse-simple pulse/simple.h pa_simple_new 3223 3227 enabled librtmp && require_pkg_config librtmp librtmp/rtmp.h RTMP_Socket 3224 3228 enabled libschroedinger && require_pkg_config schroedinger-1.0 schroedinger/schro.h schro_init … … echo "libopencore-amrnb support ${libopencore_amrnb-no}" 3588 3592 echo "libopencore-amrwb support ${libopencore_amrwb-no}" 3589 3593 echo "libopencv support ${libopencv-no}" 3590 3594 echo "libopenjpeg enabled ${libopenjpeg-no}" 3595 echo "libopus enabled ${libopus-no}" 3591 3596 echo "libpulse enabled ${libpulse-no}" 3592 3597 echo "librtmp enabled ${librtmp-no}" 3593 3598 echo "libschroedinger enabled ${libschroedinger-no}" -
libavcodec/Makefile
diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 0a3b351..12ca3f5 100644
a b OBJS-$(CONFIG_LIBOPENCORE_AMRNB_ENCODER) += libopencore-amr.o \ 660 660 OBJS-$(CONFIG_LIBOPENCORE_AMRWB_DECODER) += libopencore-amr.o 661 661 OBJS-$(CONFIG_LIBOPENJPEG_DECODER) += libopenjpegdec.o 662 662 OBJS-$(CONFIG_LIBOPENJPEG_ENCODER) += libopenjpegenc.o 663 OBJS-$(CONFIG_LIBOPUS_DECODER) += libopusdec.o 663 664 OBJS-$(CONFIG_LIBSCHROEDINGER_DECODER) += libschroedingerdec.o \ 664 665 libschroedinger.o 665 666 OBJS-$(CONFIG_LIBSCHROEDINGER_ENCODER) += libschroedingerenc.o \ -
libavcodec/allcodecs.c
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index ac05b9b..4ae000b 100644
a b void avcodec_register_all(void) 413 413 REGISTER_ENCDEC (LIBOPENCORE_AMRNB, libopencore_amrnb); 414 414 REGISTER_DECODER (LIBOPENCORE_AMRWB, libopencore_amrwb); 415 415 REGISTER_ENCDEC (LIBOPENJPEG, libopenjpeg); 416 REGISTER_DECODER (LIBOPUS, libopus); 416 417 REGISTER_ENCDEC (LIBSCHROEDINGER, libschroedinger); 417 418 REGISTER_ENCDEC (LIBSPEEX, libspeex); 418 419 REGISTER_DECODER (LIBSTAGEFRIGHT_H264, libstagefright_h264); -
libavcodec/avcodec.h
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 9dfb64b..4ebf94b 100644
a b enum CodecID { 400 400 CODEC_ID_AAC_LATM, 401 401 CODEC_ID_QDMC, 402 402 CODEC_ID_CELT, 403 CODEC_ID_OPUS, 403 404 CODEC_ID_G723_1, 404 405 CODEC_ID_G729, 405 406 CODEC_ID_8SVX_EXP, -
new file libavcodec/libopusdec.c
diff --git a/libavcodec/libopusdec.c b/libavcodec/libopusdec.c new file mode 100644 index 0000000..428583d
- + 1 /* 2 * Xiph/IETF Opus decoder using libopus 3 * Copyright (c) 2011 Nicolas George 4 * 5 * This file is part of FFmpeg. 6 * 7 * FFmpeg is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * FFmpeg is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with FFmpeg; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22 #include <opus/opus.h> 23 #include "avcodec.h" 24 #include "libavutil/intreadwrite.h" 25 26 struct libopus_context { 27 OpusDecoder *dec; 28 AVFrame frame; 29 uint16_t preskip; 30 }; 31 32 static int ff_opus_error_to_averror(int err) 33 { 34 switch (err) { 35 case OPUS_BAD_ARG: return AVERROR(EINVAL); 36 case OPUS_BUFFER_TOO_SMALL: return AVERROR(ENOBUFS); 37 case OPUS_INTERNAL_ERROR: return AVERROR(EFAULT); 38 case OPUS_INVALID_PACKET: return AVERROR_INVALIDDATA; 39 case OPUS_UNIMPLEMENTED: return AVERROR(ENOSYS); 40 #ifdef ENOTRECOVERABLE 41 case OPUS_INVALID_STATE: return AVERROR(ENOTRECOVERABLE); 42 #endif 43 case OPUS_ALLOC_FAIL: return AVERROR(ENOMEM); 44 default: return AVERROR(EINVAL); 45 } 46 } 47 48 static av_cold int libopus_dec_init(AVCodecContext *c) 49 { 50 struct libopus_context *opus = c->priv_data; 51 int err; 52 53 if (!c->channels || !c->frame_size || 54 c->frame_size > INT_MAX / sizeof(int16_t) / c->channels) 55 return AVERROR(EINVAL); 56 opus->dec = opus_decoder_create(48000, c->channels, &err); 57 av_log(c, AV_LOG_DEBUG, 58 "opus_decoder_create: dec=%p channels=%d err=%d\n", 59 opus->dec, c->channels, err); 60 if (!opus->dec) 61 return ff_opus_error_to_averror(err); 62 if (c->extradata_size >= 2) { 63 opus->preskip = AV_RL16(c->extradata); 64 if (opus->preskip >= c->frame_size) { 65 av_log(c, AV_LOG_WARNING, 66 "Invalid preskip (%d), ignored.\n", opus->preskip); 67 opus->preskip = 0; 68 } 69 } 70 avcodec_get_frame_defaults(&opus->frame); 71 c->coded_frame = &opus->frame; 72 return 0; 73 } 74 75 static av_cold int libopus_dec_close(AVCodecContext *c) 76 { 77 struct libopus_context *opus = c->priv_data; 78 79 opus_decoder_destroy(opus->dec); 80 return 0; 81 } 82 83 static int libopus_dec_decode(AVCodecContext *c, void *frame, 84 int *got_frame_ptr, AVPacket *pkt) 85 { 86 struct libopus_context *opus = c->priv_data; 87 int16_t *pcm; 88 int ret; 89 90 opus->frame.nb_samples = c->frame_size; 91 ret = c->get_buffer(c, &opus->frame); 92 if (ret < 0) { 93 av_log(c, AV_LOG_ERROR, "get_buffer() failed\n"); 94 return ret; 95 } 96 pcm = (int16_t *)opus->frame.data[0]; 97 ret = opus_decode(opus->dec, pkt->data, pkt->size, pcm, c->frame_size, 0); 98 av_log(c, AV_LOG_DEBUG, 99 "opus_decode: dec=%p data=%p size=%d pcm=%p frame_size=%d ret=%d\n", 100 opus->dec, pkt->data, pkt->size, pcm, c->frame_size, ret); 101 if (ret < 0) 102 return ff_opus_error_to_averror(ret); 103 opus->frame.nb_samples = ret; 104 av_log(c, AV_LOG_DEBUG, 105 "preskip=%d nb_samples=%d\n", opus->preskip, opus->frame.nb_samples); 106 if (opus->preskip) { 107 if (opus->preskip < opus->frame.nb_samples) { 108 opus->frame.nb_samples -= opus->preskip; 109 memmove(pcm, pcm + opus->preskip * c->channels, 110 opus->frame.nb_samples * c->channels * sizeof(int16_t)); 111 } 112 opus->preskip = 0; 113 } 114 *got_frame_ptr = 1; 115 *(AVFrame *)frame = opus->frame; 116 return pkt->size; 117 } 118 119 AVCodec ff_libopus_decoder = { 120 .name = "libopus", 121 .type = AVMEDIA_TYPE_AUDIO, 122 .id = CODEC_ID_OPUS, 123 .priv_data_size = sizeof(struct libopus_context), 124 .init = libopus_dec_init, 125 .close = libopus_dec_close, 126 .decode = libopus_dec_decode, 127 .capabilities = CODEC_CAP_DR1, 128 .long_name = NULL_IF_CONFIG_SMALL("libopus Xiph/IETF Opus"), 129 }; -
libavformat/Makefile
diff --git a/libavformat/Makefile b/libavformat/Makefile index 18a0e19..e5e08ee 100644
a b OBJS-$(CONFIG_OGG_DEMUXER) += oggdec.o \ 197 197 oggparsedirac.o \ 198 198 oggparseflac.o \ 199 199 oggparseogm.o \ 200 oggparseopus.o \ 200 201 oggparseskeleton.o \ 201 202 oggparsespeex.o \ 202 203 oggparsetheora.o \ -
libavformat/oggdec.c
diff --git a/libavformat/oggdec.c b/libavformat/oggdec.c index 6f3a565..b781e0f 100644
a b static const struct ogg_codec * const ogg_codecs[] = { 46 46 &ff_theora_codec, 47 47 &ff_flac_codec, 48 48 &ff_celt_codec, 49 &ff_opus_codec, 49 50 &ff_old_dirac_codec, 50 51 &ff_old_flac_codec, 51 52 &ff_ogm_video_codec, -
libavformat/oggdec.h
diff --git a/libavformat/oggdec.h b/libavformat/oggdec.h index 7f5452f..aa94db5 100644
a b extern const struct ogg_codec ff_ogm_text_codec; 108 108 extern const struct ogg_codec ff_ogm_video_codec; 109 109 extern const struct ogg_codec ff_old_dirac_codec; 110 110 extern const struct ogg_codec ff_old_flac_codec; 111 extern const struct ogg_codec ff_opus_codec; 111 112 extern const struct ogg_codec ff_skeleton_codec; 112 113 extern const struct ogg_codec ff_speex_codec; 113 114 extern const struct ogg_codec ff_theora_codec; -
new file libavformat/oggparseopus.c
diff --git a/libavformat/oggparseopus.c b/libavformat/oggparseopus.c new file mode 100644 index 0000000..5d8779b
- + 1 /* 2 * Xiph/IETF Opus parser for Ogg 3 * Copyright (c) 2011 Nicolas George 4 * 5 * This file is part of FFmpeg. 6 * 7 * FFmpeg is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * FFmpeg is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with FFmpeg; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22 #include <string.h> 23 24 #include "libavutil/intreadwrite.h" 25 #include "avformat.h" 26 #include "internal.h" 27 #include "oggdec.h" 28 29 struct oggopus_private { 30 int extra_headers_left; 31 }; 32 33 static int opus_header(AVFormatContext *s, int idx) 34 { 35 struct ogg *ogg = s->priv_data; 36 struct ogg_stream *os = ogg->streams + idx; 37 AVStream *st = s->streams[idx]; 38 struct oggopus_private *priv = os->private; 39 uint8_t *p = os->buf + os->pstart; 40 41 if (os->psize == 19 && 42 !memcmp(p, ff_opus_codec.magic, ff_opus_codec.magicsize)) { 43 /* Main header */ 44 45 uint8_t version, nb_channels, channel_map; 46 uint16_t preskip, output_gain; 47 uint32_t sample_rate; 48 uint8_t *extradata; 49 int extradata_size = sizeof(preskip) + sizeof(output_gain) + sizeof(version); 50 51 extradata = av_malloc(extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); 52 priv = av_malloc(sizeof(struct oggopus_private)); 53 if (!extradata || !priv) { 54 av_free(extradata); 55 av_free(priv); 56 return AVERROR(ENOMEM); 57 } 58 version = AV_RL8(p + 8); 59 nb_channels = AV_RL8(p + 9); 60 preskip = AV_RL16(p + 10); 61 sample_rate = AV_RL32(p + 12); 62 output_gain = AV_RL16(p + 16); 63 channel_map = AV_RL8(p + 18); 64 st->codec->codec_type = AVMEDIA_TYPE_AUDIO; 65 st->codec->codec_id = CODEC_ID_OPUS; 66 st->codec->sample_fmt = AV_SAMPLE_FMT_S16; 67 st->codec->sample_rate = 48000; 68 st->codec->channels = nb_channels; 69 /* allocate with maximum frame size (120ms) */ 70 st->codec->frame_size = 960 * 6; 71 av_free(st->codec->extradata); 72 st->codec->extradata = extradata; 73 st->codec->extradata_size = extradata_size; 74 avpriv_set_pts_info(st, 64, 1, 48000); 75 priv->extra_headers_left = 1; 76 av_free(os->private); 77 os->private = priv; 78 AV_WL16(extradata + 0, preskip); 79 AV_WL16(extradata + 2, output_gain); 80 AV_WL8(extradata + 3, version); 81 av_log(s, AV_LOG_DEBUG, 82 "opus_header: OpusHead: version=%hhu nb_channels=%hhu preskip=%hu " 83 "sample_rate=%u output_gain=%hu channel_map=%hhu\n", 84 version, nb_channels, preskip, sample_rate, output_gain, 85 channel_map); 86 return 1; 87 } else if (priv && priv->extra_headers_left && 88 !memcmp(p, "OpusTags", 8)) { 89 /* Extra headers (vorbiscomment) */ 90 91 ff_vorbis_comment(s, &st->metadata, p + 8, os->psize - 8); 92 priv->extra_headers_left--; 93 av_log(s, AV_LOG_DEBUG, "opus_header: OpusTags\n"); 94 return 1; 95 } 96 return 0; 97 } 98 99 const struct ogg_codec ff_opus_codec = { 100 .magic = "OpusHead", 101 .magicsize = 8, 102 .header = opus_header, 103 };
