[FFmpeg-devel] [PATCH] LVF demuxer

Paul B Mahol onemda at gmail.com
Fri Oct 19 01:33:03 CEST 2012


Signed-off-by: Paul B Mahol <onemda at gmail.com>
---
 Changelog                |   1 +
 doc/general.texi         |   1 +
 libavformat/Makefile     |   1 +
 libavformat/allformats.c |   1 +
 libavformat/lvfdec.c     | 148 +++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 152 insertions(+)
 create mode 100644 libavformat/lvfdec.c

diff --git a/Changelog b/Changelog
index 22cf813..1462801 100644
--- a/Changelog
+++ b/Changelog
@@ -14,6 +14,7 @@ version <next>:
 - X-Face image encoder and decoder
 - metadata (INFO tag) support in WAV muxer
 - subtitles raw text decoder
+- LVF demuxer
 
 
 version 1.0:
diff --git a/doc/general.texi b/doc/general.texi
index b4176d5..8ec1d28 100644
--- a/doc/general.texi
+++ b/doc/general.texi
@@ -232,6 +232,7 @@ library:
     @tab Used by Linux Media Labs MPEG-4 PCI boards
 @item LOAS                      @tab   @tab X
     @tab contains LATM multiplexed AAC audio
+ at item LVF                       @tab   @tab X
 @item LXF                       @tab   @tab X
     @tab VR native stream format, used by Leitch/Harris' video servers.
 @item Matroska                  @tab X @tab X
diff --git a/libavformat/Makefile b/libavformat/Makefile
index 50be0cf..dc8e271 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -151,6 +151,7 @@ OBJS-$(CONFIG_LATM_DEMUXER)              += rawdec.o
 OBJS-$(CONFIG_LATM_MUXER)                += latmenc.o rawenc.o
 OBJS-$(CONFIG_LMLM4_DEMUXER)             += lmlm4.o
 OBJS-$(CONFIG_LOAS_DEMUXER)              += loasdec.o
+OBJS-$(CONFIG_LVF_DEMUXER)               += lvfdec.o
 OBJS-$(CONFIG_LXF_DEMUXER)               += lxfdec.o
 OBJS-$(CONFIG_M4V_DEMUXER)               += m4vdec.o rawdec.o
 OBJS-$(CONFIG_M4V_MUXER)                 += rawenc.o
diff --git a/libavformat/allformats.c b/libavformat/allformats.c
index 00f11f4..3551394 100644
--- a/libavformat/allformats.c
+++ b/libavformat/allformats.c
@@ -133,6 +133,7 @@ void av_register_all(void)
     REGISTER_MUXDEMUX (LATM, latm);
     REGISTER_DEMUXER  (LMLM4, lmlm4);
     REGISTER_DEMUXER  (LOAS, loas);
+    REGISTER_DEMUXER  (LVF, lvf);
     REGISTER_DEMUXER  (LXF, lxf);
     REGISTER_MUXDEMUX (M4V, m4v);
     REGISTER_MUXER    (MD5, md5);
diff --git a/libavformat/lvfdec.c b/libavformat/lvfdec.c
new file mode 100644
index 0000000..7aac6ef
--- /dev/null
+++ b/libavformat/lvfdec.c
@@ -0,0 +1,148 @@
+/*
+ * LVF demuxer
+ * Copyright (c) 2012 Paul B Mahol
+ *
+ * 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
+ */
+
+#include "libavutil/intreadwrite.h"
+#include "avformat.h"
+#include "riff.h"
+
+static int lvf_probe(AVProbeData *p)
+{
+    if (AV_RL32(p->buf) == MKTAG('L', 'V', 'F', 'F'))
+        return AVPROBE_SCORE_MAX / 2;
+    return 0;
+}
+
+static int lvf_read_header(AVFormatContext *s)
+{
+    AVStream *st;
+    int64_t next_offset;
+    unsigned size, nb_streams, id;
+
+    avio_skip(s->pb, 16);
+    nb_streams = avio_rl32(s->pb);
+    if (!nb_streams)
+        return AVERROR_INVALIDDATA;
+    if (nb_streams > 2) {
+        av_log_ask_for_sample(s, "too many streams\n");
+        return AVERROR_PATCHWELCOME;
+    }
+
+    avio_skip(s->pb, 1012);
+
+    while (!url_feof(s->pb)) {
+        id          = avio_rl32(s->pb);
+        size        = avio_rl32(s->pb);
+        next_offset = avio_tell(s->pb) + size;
+
+        switch (id) {
+        case MKTAG('0', '0', 'f', 'm'):
+            st = avformat_new_stream(s, 0);
+            if (!st)
+                return AVERROR(ENOMEM);
+
+            st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
+            avio_skip(s->pb, 4);
+            st->codec->width      = avio_rl32(s->pb);
+            st->codec->height     = avio_rl32(s->pb);
+            avio_skip(s->pb, 4);
+            st->codec->codec_tag  = avio_rl32(s->pb);
+            st->codec->codec_id   = ff_codec_get_id(ff_codec_bmp_tags,
+                                                    st->codec->codec_tag);
+            avpriv_set_pts_info(st, 32, 1, 1000);
+            break;
+        case MKTAG('0', '1', 'f', 'm'):
+            st = avformat_new_stream(s, 0);
+            if (!st)
+                return AVERROR(ENOMEM);
+
+            st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
+            st->codec->codec_tag   = avio_rl16(s->pb);
+            st->codec->channels    = avio_rl16(s->pb);
+            st->codec->sample_rate = avio_rl16(s->pb);
+            avio_skip(s->pb, 8);
+            st->codec->bits_per_coded_sample = avio_r8(s->pb);
+            st->codec->codec_id    = ff_codec_get_id(ff_codec_wav_tags,
+                                                     st->codec->codec_tag);
+            avpriv_set_pts_info(st, 32, 1, 1000);
+            break;
+        case 0:
+            avio_seek(s->pb, 2048 + 8, SEEK_SET);
+            return 0;
+        default:
+            av_log_ask_for_sample(s, "unknown id\n");
+            return AVERROR_PATCHWELCOME;
+        }
+
+        avio_seek(s->pb, next_offset, SEEK_SET);
+    }
+
+    return AVERROR_EOF;
+}
+
+static int lvf_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+    unsigned size, flags, timestamp, id;
+    int64_t pos;
+    int ret, is_video = 0;
+
+    pos = avio_tell(s->pb);
+    while (!url_feof(s->pb)) {
+        id    = avio_rl32(s->pb);
+        size  = avio_rl32(s->pb);
+
+        if (size == 0xFFFFFFFFu)
+            return AVERROR_EOF;
+
+        switch (id) {
+        case MKTAG('0', '0', 'd', 'c'):
+            is_video = 1;
+        case MKTAG('0', '1', 'w', 'b'):
+            if (size < 8)
+                return AVERROR_INVALIDDATA;
+            timestamp = avio_rl32(s->pb);
+            flags = avio_rl32(s->pb);
+            ret = av_get_packet(s->pb, pkt, size - 8);
+            if (flags & (1 << 12))
+                pkt->flags |= AV_PKT_FLAG_KEY;
+            pkt->stream_index = is_video ? 0 : 1;
+            pkt->pts          = timestamp;
+            pkt->pos          = pos;
+            return ret;
+        default:
+            ret = avio_skip(s->pb, size);
+        }
+
+        if (ret < 0)
+              return ret;
+    }
+
+    return AVERROR_EOF;
+}
+
+AVInputFormat ff_lvf_demuxer = {
+    .name        = "lvf",
+    .long_name   = NULL_IF_CONFIG_SMALL("LVF"),
+    .read_probe  = lvf_probe,
+    .read_header = lvf_read_header,
+    .read_packet = lvf_read_packet,
+    .extensions  = "lvf",
+    .flags       = AVFMT_GENERIC_INDEX,
+};
-- 
1.7.11.2



More information about the ffmpeg-devel mailing list