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, 4 years 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: 
    188188  --enable-libnut          enable NUT (de)muxing via libnut, 
    189189                           native (de)muxer exists [no] 
    190190  --enable-libopenjpeg     enable JPEG 2000 encoding/decoding via OpenJPEG [no] 
     191  --enable-libopus         enable Opus decoding via libopus [no] 
    191192  --enable-libpulse        enable Pulseaudio input via libpulse [no] 
    192193  --enable-librtmp         enable RTMP[E] support via librtmp [no] 
    193194  --enable-libschroedinger enable Dirac support via libschroedinger [no] 
    CONFIG_LIST=" 
    10461047    libopencore_amrwb 
    10471048    libopencv 
    10481049    libopenjpeg 
     1050    libopus 
    10491051    libpulse 
    10501052    librtmp 
    10511053    libschroedinger 
    libopencore_amrnb_encoder_deps="libopencore_amrnb" 
    15711573libopencore_amrwb_decoder_deps="libopencore_amrwb" 
    15721574libopenjpeg_decoder_deps="libopenjpeg" 
    15731575libopenjpeg_encoder_deps="libopenjpeg" 
     1576libopus_decoder_deps="libopus" 
    15741577libschroedinger_decoder_deps="libschroedinger" 
    15751578libschroedinger_encoder_deps="libschroedinger" 
    15761579libspeex_decoder_deps="libspeex" 
    enabled libopencore_amrnb && require libopencore_amrnb opencore-amrnb/interf_de 
    32193222enabled libopencore_amrwb  && require libopencore_amrwb opencore-amrwb/dec_if.h D_IF_init -lopencore-amrwb 
    32203223enabled libopencv  && require_pkg_config opencv opencv/cxcore.h cvCreateImageHeader 
    32213224enabled libopenjpeg && require libopenjpeg openjpeg.h opj_version -lopenjpeg 
     3225enabled libopus    && require libopus opus/opus.h opus_decode -lopus 
    32223226enabled libpulse && require_pkg_config libpulse-simple pulse/simple.h pa_simple_new 
    32233227enabled librtmp    && require_pkg_config librtmp librtmp/rtmp.h RTMP_Socket 
    32243228enabled libschroedinger && require_pkg_config schroedinger-1.0 schroedinger/schro.h schro_init 
    echo "libopencore-amrnb support ${libopencore_amrnb-no}" 
    35883592echo "libopencore-amrwb support ${libopencore_amrwb-no}" 
    35893593echo "libopencv support         ${libopencv-no}" 
    35903594echo "libopenjpeg enabled       ${libopenjpeg-no}" 
     3595echo "libopus enabled           ${libopus-no}" 
    35913596echo "libpulse enabled          ${libpulse-no}" 
    35923597echo "librtmp enabled           ${librtmp-no}" 
    35933598echo "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 \ 
    660660OBJS-$(CONFIG_LIBOPENCORE_AMRWB_DECODER)  += libopencore-amr.o 
    661661OBJS-$(CONFIG_LIBOPENJPEG_DECODER)        += libopenjpegdec.o 
    662662OBJS-$(CONFIG_LIBOPENJPEG_ENCODER)        += libopenjpegenc.o 
     663OBJS-$(CONFIG_LIBOPUS_DECODER)            += libopusdec.o 
    663664OBJS-$(CONFIG_LIBSCHROEDINGER_DECODER)    += libschroedingerdec.o \ 
    664665                                             libschroedinger.o 
    665666OBJS-$(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) 
    413413    REGISTER_ENCDEC  (LIBOPENCORE_AMRNB, libopencore_amrnb); 
    414414    REGISTER_DECODER (LIBOPENCORE_AMRWB, libopencore_amrwb); 
    415415    REGISTER_ENCDEC  (LIBOPENJPEG, libopenjpeg); 
     416    REGISTER_DECODER (LIBOPUS, libopus); 
    416417    REGISTER_ENCDEC  (LIBSCHROEDINGER, libschroedinger); 
    417418    REGISTER_ENCDEC  (LIBSPEEX, libspeex); 
    418419    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 { 
    400400    CODEC_ID_AAC_LATM, 
    401401    CODEC_ID_QDMC, 
    402402    CODEC_ID_CELT, 
     403    CODEC_ID_OPUS, 
    403404    CODEC_ID_G723_1, 
    404405    CODEC_ID_G729, 
    405406    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 
     26struct libopus_context { 
     27    OpusDecoder *dec; 
     28    AVFrame frame; 
     29    uint16_t preskip; 
     30}; 
     31 
     32static 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 
     48static 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 
     75static 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 
     83static 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 
     119AVCodec 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 \ 
    197197                                            oggparsedirac.o  \ 
    198198                                            oggparseflac.o   \ 
    199199                                            oggparseogm.o    \ 
     200                                            oggparseopus.o   \ 
    200201                                            oggparseskeleton.o \ 
    201202                                            oggparsespeex.o  \ 
    202203                                            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[] = { 
    4646    &ff_theora_codec, 
    4747    &ff_flac_codec, 
    4848    &ff_celt_codec, 
     49    &ff_opus_codec, 
    4950    &ff_old_dirac_codec, 
    5051    &ff_old_flac_codec, 
    5152    &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; 
    108108extern const struct ogg_codec ff_ogm_video_codec; 
    109109extern const struct ogg_codec ff_old_dirac_codec; 
    110110extern const struct ogg_codec ff_old_flac_codec; 
     111extern const struct ogg_codec ff_opus_codec; 
    111112extern const struct ogg_codec ff_skeleton_codec; 
    112113extern const struct ogg_codec ff_speex_codec; 
    113114extern 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 
     29struct oggopus_private { 
     30    int extra_headers_left; 
     31}; 
     32 
     33static 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 
     99const struct ogg_codec ff_opus_codec = { 
     100    .magic     = "OpusHead", 
     101    .magicsize = 8, 
     102    .header    = opus_header, 
     103};