[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