From: Andrew D'Addesio <modchip...@gmail.com>

Additionally add the codec_id for it.
---

Split out from GSOC repository, voluteers to help me getting at least silk in
would be much appreciated.

 libavcodec/Makefile        |    1 +
 libavcodec/allcodecs.c     |    1 +
 libavcodec/avcodec.h       |    1 +
 libavcodec/codec_desc.c    |    7 ++
 libavformat/Makefile       |    1 +
 libavformat/oggdec.c       |    3 +-
 libavformat/oggdec.h       |    1 +
 libavformat/oggenc.c       |    2 +-
 libavformat/oggparseopus.c |  136 ++++++++++++++++++++++++++++++++++++++++++++
 9 files changed, 151 insertions(+), 2 deletions(-)
 create mode 100644 libavformat/oggparseopus.c

diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index efd1698..d8bad33 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -629,6 +629,7 @@ OBJS-$(CONFIG_MPEGAUDIO_PARSER)        += 
mpegaudio_parser.o \
                                           mpegaudiodecheader.o mpegaudiodata.o
 OBJS-$(CONFIG_MPEGVIDEO_PARSER)        += mpegvideo_parser.o    \
                                           mpeg12.o mpeg12data.o
+OBJS-$(CONFIG_OPUS_DECODER)            += opus.o
 OBJS-$(CONFIG_PNM_PARSER)              += pnm_parser.o pnm.o
 OBJS-$(CONFIG_RV30_PARSER)             += rv34_parser.o
 OBJS-$(CONFIG_RV40_PARSER)             += rv34_parser.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index c6df818..04a85a1 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -286,6 +286,7 @@ void avcodec_register_all(void)
     REGISTER_DECODER (MPC7, mpc7);
     REGISTER_DECODER (MPC8, mpc8);
     REGISTER_ENCDEC  (NELLYMOSER, nellymoser);
+    REGISTER_DECODER (OPUS, opus);
     REGISTER_DECODER (QCELP, qcelp);
     REGISTER_DECODER (QDM2, qdm2);
     REGISTER_ENCDEC  (RA_144, ra_144);
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 8a091bd..c0c66e1 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -405,6 +405,7 @@ enum AVCodecID {
     AV_CODEC_ID_RALF,
     AV_CODEC_ID_IAC,
     AV_CODEC_ID_ILBC,
+    AV_CODEC_ID_OPUS,
 
     /* subtitle codecs */
     AV_CODEC_ID_FIRST_SUBTITLE = 0x17000,          ///< A dummy ID pointing at 
the start of subtitle codecs.
diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
index 51fc171..818a35e 100644
--- a/libavcodec/codec_desc.c
+++ b/libavcodec/codec_desc.c
@@ -2105,6 +2105,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
         .long_name = NULL_IF_CONFIG_SMALL("iLBC (Internet Low Bitrate Codec)"),
         .props     = AV_CODEC_PROP_LOSSY,
     },
+    {
+        .id        = AV_CODEC_ID_OPUS,
+        .type      = AVMEDIA_TYPE_AUDIO,
+        .name      = "opus",
+        .long_name = NULL_IF_CONFIG_SMALL("Opus (Opus Interactive Audio 
Codec)"),
+        .props     = AV_CODEC_PROP_LOSSY,
+    },
 
     /* subtitle codecs */
     {
diff --git a/libavformat/Makefile b/libavformat/Makefile
index 61e1fa1..81be3cc 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -184,6 +184,7 @@ OBJS-$(CONFIG_OGG_DEMUXER)               += oggdec.o        
 \
                                             oggparsedirac.o  \
                                             oggparseflac.o   \
                                             oggparseogm.o    \
+                                                                               
        oggparseopus.o   \
                                             oggparseskeleton.o \
                                             oggparsespeex.o  \
                                             oggparsetheora.o \
diff --git a/libavformat/oggdec.c b/libavformat/oggdec.c
index e04a4e7..dd67115 100644
--- a/libavformat/oggdec.c
+++ b/libavformat/oggdec.c
@@ -46,6 +46,7 @@ static const struct ogg_codec * const ogg_codecs[] = {
     &ff_theora_codec,
     &ff_flac_codec,
     &ff_celt_codec,
+    &ff_opus_codec,
     &ff_old_dirac_codec,
     &ff_old_flac_codec,
     &ff_ogm_video_codec,
@@ -661,6 +662,6 @@ AVInputFormat ff_ogg_demuxer = {
     .read_close     = ogg_read_close,
     .read_seek      = ogg_read_seek,
     .read_timestamp = ogg_read_timestamp,
-    .extensions     = "ogg",
+    .extensions     = "ogg,ogv,oga,spx,opus",
     .flags          = AVFMT_GENERIC_INDEX,
 };
diff --git a/libavformat/oggdec.h b/libavformat/oggdec.h
index 184a628..5dafbd5 100644
--- a/libavformat/oggdec.h
+++ b/libavformat/oggdec.h
@@ -107,6 +107,7 @@ extern const struct ogg_codec ff_ogm_text_codec;
 extern const struct ogg_codec ff_ogm_video_codec;
 extern const struct ogg_codec ff_old_dirac_codec;
 extern const struct ogg_codec ff_old_flac_codec;
+extern const struct ogg_codec ff_opus_codec;
 extern const struct ogg_codec ff_skeleton_codec;
 extern const struct ogg_codec ff_speex_codec;
 extern const struct ogg_codec ff_theora_codec;
diff --git a/libavformat/oggenc.c b/libavformat/oggenc.c
index c23a1ad..4c7f2d8 100644
--- a/libavformat/oggenc.c
+++ b/libavformat/oggenc.c
@@ -531,7 +531,7 @@ AVOutputFormat ff_ogg_muxer = {
     .name              = "ogg",
     .long_name         = NULL_IF_CONFIG_SMALL("Ogg"),
     .mime_type         = "application/ogg",
-    .extensions        = "ogg,ogv,spx",
+    .extensions        = "ogg,ogv,oga,spx",
     .priv_data_size    = sizeof(OGGContext),
     .audio_codec       = AV_CODEC_ID_FLAC,
     .video_codec       = AV_CODEC_ID_THEORA,
diff --git a/libavformat/oggparseopus.c b/libavformat/oggparseopus.c
new file mode 100644
index 0000000..3ce6123
--- /dev/null
+++ b/libavformat/oggparseopus.c
@@ -0,0 +1,136 @@
+/*
+ * Opus parser for Ogg
+ * Copyright (c) 2011 Justin Ruggles
+ *
+ * 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 "libavutil/audioconvert.h"
+#include "libavutil/intreadwrite.h"
+#include "avformat.h"
+#include "internal.h"
+#include "oggdec.h"
+
+struct opus_params {
+    int header_count;
+    int pre_skip;
+};
+
+static const uint64_t opus_channel_layouts[9] = {
+    AV_CH_LAYOUT_MONO,
+    AV_CH_LAYOUT_STEREO,
+    AV_CH_LAYOUT_SURROUND,
+    AV_CH_LAYOUT_QUAD,
+    AV_CH_LAYOUT_5POINT0_BACK,
+    AV_CH_LAYOUT_5POINT1_BACK,
+    AV_CH_LAYOUT_5POINT1|AV_CH_BACK_CENTER,
+    AV_CH_LAYOUT_7POINT1,
+    0
+};
+
+static int opus_header(AVFormatContext *s, int idx) {
+    struct ogg *ogg = s->priv_data;
+    struct ogg_stream *os = ogg->streams + idx;
+    struct opus_params *op = os->private;
+    AVStream *st = s->streams[idx];
+    uint8_t *p = os->buf + os->pstart;
+
+    if (!op) {
+        op = av_mallocz(sizeof(*op));
+        if (!op)
+            return AVERROR(ENOMEM);
+        os->private = op;
+    } else if (op->header_count > 1)
+        return 0;
+
+    if (op->header_count == 0) {
+        // ID header
+        if (os->psize < 19) {
+            av_log(s, AV_LOG_ERROR, "OpusHead header packet is too small\n");
+            return AVERROR_INVALIDDATA;
+        }
+        if (memcmp(p, "OpusHead", 8)) {
+            av_log(s, AV_LOG_ERROR, "first packet must be an id header\n");
+            return AVERROR_INVALIDDATA;
+        }
+        if (AV_RL8(p + 8) != 1) {
+            av_log(s, AV_LOG_ERROR, "unrecognized OggOpus version\n");
+            return AVERROR_INVALIDDATA;
+        }
+
+        st->codec->channels = AV_RL8(p + 9);
+        if (st->codec->channels == 0) {
+            av_log(s, AV_LOG_ERROR, "invalid number of source channels\n");
+            return AVERROR_INVALIDDATA;
+        }
+
+        op->pre_skip = AV_RL16(p + 10);
+
+        st->codec->sample_rate = AV_RL32(p + 12);
+        if (st->codec->sample_rate == 0) {
+            av_log(s, AV_LOG_ERROR, "invalid sample rate\n");
+            return AVERROR_INVALIDDATA;
+        }
+
+        st->codec->codec_type     = AVMEDIA_TYPE_AUDIO;
+        st->codec->codec_id       = AV_CODEC_ID_OPUS;
+        st->codec->channel_layout = (st->codec->channels > 8) ? 0 :
+                                    opus_channel_layouts[st->codec->channels - 
1];
+
+        if (AV_RL8(p + 18) == 0 && st->codec->channels > 2)
+            av_log(s, AV_LOG_WARNING,
+                "RTP channel mapping is undefined for more than one stream\n");
+        if (AV_RL8(p + 18) > 1)
+            av_log(s, AV_LOG_WARNING, "channel mapping unrecognized\n");
+
+        avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+    } else  {
+        // comment header
+        if (os->psize < 8) {
+            av_log(s, AV_LOG_ERROR, "OpusTags header packet is too small\n");
+            return AVERROR_INVALIDDATA;
+        }
+        if (memcmp(p, "OpusTags", 8)) {
+            av_log(s, AV_LOG_ERROR, "second packet must be a comment 
header\n");
+            return AVERROR_INVALIDDATA;
+        }
+        if (ff_vorbis_comment(s, &st->metadata, p + 8, os->psize - 8)) {
+            av_log(s, AV_LOG_ERROR, "invalid OpusTags header packet\n");
+            return AVERROR_INVALIDDATA;
+        }
+    }
+
+    op->header_count++;
+    return 1;
+}
+
+static uint64_t opus_gptopts(AVFormatContext *s, int idx, uint64_t granule,
+                             int64_t *dts_out)
+{
+    struct ogg *ogg = s->priv_data;
+    struct ogg_stream *os = ogg->streams + idx;
+    struct opus_params *op = os->private;
+    AVStream *st = s->streams[idx];
+    return (granule - op->pre_skip)*st->codec->sample_rate/48000;
+}
+
+const struct ogg_codec ff_opus_codec = {
+    .magic     = "OpusHead",
+    .magicsize = 8,
+    .header    = opus_header,
+    .gptopts   = opus_gptopts,
+};
-- 
1.7.8.rc1

_______________________________________________
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to