[FFmpeg-devel] [PATCH] IRCAM Sound Format demuxer

Daniel Verkamp daniel
Tue Apr 20 05:59:35 CEST 2010


---
 Changelog                |    1 +
 doc/general.texi         |    1 +
 libavformat/Makefile     |    1 +
 libavformat/allformats.c |    1 +
 libavformat/avformat.h   |    2 +-
 libavformat/ircamsf.c    |  200 ++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 205 insertions(+), 1 deletions(-)
 create mode 100644 libavformat/ircamsf.c

diff --git a/Changelog b/Changelog
index c454c15..7ad100f 100644
--- a/Changelog
+++ b/Changelog
@@ -70,6 +70,7 @@ version <next>:
 - Psygnosis YOP demuxer and video decoder
 - spectral extension support in the E-AC-3 decoder
 - unsharp video filter
+- IRCAM Sound Format (.sf) demuxer
 
 
 
diff --git a/doc/general.texi b/doc/general.texi
index 1bfde02..8dfb07c 100644
--- a/doc/general.texi
+++ b/doc/general.texi
@@ -107,6 +107,7 @@ library:
     @tab Interchange File Format
 @item Interplay MVE             @tab   @tab X
     @tab Format used in various Interplay computer games.
+ at item IRCAM Sound Format (.sf)  @tab   @tab X
 @item IV8                       @tab   @tab X
     @tab A format generated by IndigoVision 8000 video server.
 @item LMLM4                     @tab   @tab X
diff --git a/libavformat/Makefile b/libavformat/Makefile
index 43a4a2e..43ff8b4 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -96,6 +96,7 @@ OBJS-$(CONFIG_IMAGE2PIPE_DEMUXER)        += img2.o
 OBJS-$(CONFIG_IMAGE2PIPE_MUXER)          += img2.o
 OBJS-$(CONFIG_INGENIENT_DEMUXER)         += raw.o
 OBJS-$(CONFIG_IPMOVIE_DEMUXER)           += ipmovie.o
+OBJS-$(CONFIG_IRCAMSF_DEMUXER)           += ircamsf.o
 OBJS-$(CONFIG_ISS_DEMUXER)               += iss.o
 OBJS-$(CONFIG_IV8_DEMUXER)               += iv8.o
 OBJS-$(CONFIG_LMLM4_DEMUXER)             += lmlm4.o
diff --git a/libavformat/allformats.c b/libavformat/allformats.c
index 27dba10..d048549 100644
--- a/libavformat/allformats.c
+++ b/libavformat/allformats.c
@@ -102,6 +102,7 @@ void av_register_all(void)
     REGISTER_DEMUXER  (INGENIENT, ingenient);
     REGISTER_DEMUXER  (IPMOVIE, ipmovie);
     REGISTER_MUXER    (IPOD, ipod);
+    REGISTER_DEMUXER  (IRCAMSF, ircamsf);
     REGISTER_DEMUXER  (ISS, iss);
     REGISTER_DEMUXER  (IV8, iv8);
     REGISTER_DEMUXER  (LMLM4, lmlm4);
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index 5ff08c0..09d176d 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -22,7 +22,7 @@
 #define AVFORMAT_AVFORMAT_H
 
 #define LIBAVFORMAT_VERSION_MAJOR 52
-#define LIBAVFORMAT_VERSION_MINOR 61
+#define LIBAVFORMAT_VERSION_MINOR 62
 #define LIBAVFORMAT_VERSION_MICRO  0
 
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
diff --git a/libavformat/ircamsf.c b/libavformat/ircamsf.c
new file mode 100644
index 0000000..3ce97f6
--- /dev/null
+++ b/libavformat/ircamsf.c
@@ -0,0 +1,200 @@
+/*
+ * IRCAM SF demuxer
+ * Copyright (c) 2010 Daniel Verkamp
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg 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.
+ *
+ * FFmpeg 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 FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * IRCAM SF demuxer
+ * @file libavformat/ircamsf.c
+ * @author Daniel Verkamp
+ * @sa http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/IRCAM/IRCAM.html
+ */
+
+#include "avformat.h"
+#include "raw.h"
+#include "riff.h"
+#include "libavutil/intreadwrite.h"
+
+static const AVCodecTag generic_codec_tags[] = {
+    { CODEC_ID_PCM_S8,    0x00001 },
+    { CODEC_ID_PCM_ALAW,  0x10001 },
+    { CODEC_ID_PCM_MULAW, 0x20001 },
+};
+
+static const AVCodecTag le_codec_tags[] = {
+    { CODEC_ID_PCM_S16LE, 0x00002 },
+    { CODEC_ID_PCM_S24LE, 0x00003 },
+    { CODEC_ID_PCM_S32LE, 0x40004 },
+    { CODEC_ID_PCM_F32LE, 0x00004 },
+    { CODEC_ID_PCM_F64LE, 0x00008 },
+};
+
+static const AVCodecTag be_codec_tags[] = {
+    { CODEC_ID_PCM_S16BE, 0x00002 },
+    { CODEC_ID_PCM_S24BE, 0x00003 },
+    { CODEC_ID_PCM_S32BE, 0x40004 },
+    { CODEC_ID_PCM_F32BE, 0x00004 },
+    { CODEC_ID_PCM_F64BE, 0x00008 },
+};
+
+static const uint32_t be_tags[] = {
+    0x64A30200, // Sun (native)
+    0x64A30400, // NeXT
+    0x0001A364, // VAX
+    0x0003A364, // MIPS (SGI)
+};
+
+static const uint32_t le_tags[] = {
+    0x64A30100, // VAX (native)
+    0x64A30300, // MIPS (DECstation)
+    0x0002A364, // Sun
+};
+
+static int identify(uint32_t tag)
+{
+    int i;
+
+    for (i = 0; i < sizeof(be_tags) / sizeof(*be_tags); i++)
+        if (be_tags[i] == tag)
+            return 1;
+
+    for (i = 0; i < sizeof(le_tags) / sizeof(*le_tags); i++)
+        if (le_tags[i] == tag)
+            return 0;
+
+    return -1;
+}
+
+static int probe(AVProbeData *p)
+{
+    unsigned char *buf = p->buf;
+    if (p->buf_size <= 16)
+        return 0;
+
+    if (identify(AV_RB32(buf)) < 0)
+        return 0;
+
+    if (!AV_RB32(buf + 4) || !AV_RB32(buf + 8) || !AV_RB32(buf + 12))
+        return 0;
+
+    return AVPROBE_SCORE_MAX;
+}
+
+static int read_header(AVFormatContext *s, AVFormatParameters *ap)
+{
+    ByteIOContext *pb = s->pb;
+    AVStream *st;
+    AVCodecContext *dec;
+    const AVCodecTag *tags;
+    uint32_t tag;
+    int be, bits_per_frame, chunk, sz;
+    char *comment;
+
+    be = identify(get_be32(pb));
+    if (be < 0)
+        return AVERROR_INVALIDDATA;
+
+    st = av_new_stream(s, 0);
+    if (!st)
+        return AVERROR(ENOMEM);
+
+    dec = st->codec;
+    dec->codec_type = AVMEDIA_TYPE_AUDIO;
+
+    if (be) {
+        dec->sample_rate = av_int2flt(get_be32(pb));
+        dec->channels    = get_be32(pb);
+        tag              = get_be32(pb);
+        tags             = be_codec_tags;
+    } else {
+        dec->sample_rate = av_int2flt(get_le32(pb));
+        dec->channels    = get_le32(pb);
+        tag              = get_le32(pb);
+        tags             = le_codec_tags;
+    }
+
+    if (dec->sample_rate <= 0) {
+        av_log(s, AV_LOG_ERROR, "invalid sample rate %d\n", dec->sample_rate);
+        return AVERROR_INVALIDDATA;
+    }
+
+    dec->codec_id = ff_codec_get_id(tags, tag);
+    if (dec->codec_id == CODEC_ID_NONE)
+        dec->codec_id = ff_codec_get_id(generic_codec_tags, tag);
+
+    av_set_pts_info(st, 64, 1, dec->sample_rate);
+
+    while (url_ftell(pb) < 1024) {
+        if (be) {
+            chunk = get_be16(pb);
+            sz    = get_be16(pb);
+        } else {
+            chunk = get_le16(pb);
+            sz    = get_le16(pb);
+        }
+
+        if (!chunk) // end chunk
+            break;
+
+        switch (chunk) {
+        case 2: // comment
+            comment = av_malloc(sz + 1);
+            if (get_buffer(pb, comment, sz) != sz) {
+                av_freep(&comment);
+                return AVERROR(EIO);
+            }
+            comment[sz] = 0;
+            av_metadata_set2(&s->metadata, "comment", comment,
+                             AV_METADATA_DONT_STRDUP_VAL);
+            break;
+        default:
+            url_fskip(pb, sz);
+            break;
+        }
+    }
+
+    url_fseek(pb, 1024, SEEK_SET);
+
+    dec->bits_per_coded_sample = av_get_bits_per_sample(dec->codec_id);
+    bits_per_frame   = dec->channels * dec->bits_per_coded_sample;
+    dec->block_align = bits_per_frame >> 3;
+    dec->bit_rate    = bits_per_frame * dec->sample_rate;
+
+    return 0;
+}
+
+#define NUM_SAMPLES 1024
+
+static int read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+    return av_get_packet(s->pb, pkt,
+                         NUM_SAMPLES * s->streams[0]->codec->block_align);
+}
+
+AVInputFormat ircamsf_demuxer = {
+    "ircamsf",
+    NULL_IF_CONFIG_SMALL("IRCAM Sound Format"),
+    0,
+    probe,
+    read_header,
+    read_packet,
+    NULL,
+    pcm_read_seek,
+    .flags = AVFMT_GENERIC_INDEX,
+};
-- 
1.7.0.2




More information about the ffmpeg-devel mailing list