Browse code

LVF demuxer

Signed-off-by: Paul B Mahol <onemda@gmail.com>

Paul B Mahol authored on 2012/10/18 21:34:46
Showing 6 changed files
... ...
@@ -15,6 +15,7 @@ version <next>:
15 15
 - metadata (INFO tag) support in WAV muxer
16 16
 - subtitles raw text decoder
17 17
 - support for building DLLs using MSVC
18
+- LVF demuxer
18 19
 
19 20
 
20 21
 version 1.0:
... ...
@@ -232,6 +232,7 @@ library:
232 232
     @tab Used by Linux Media Labs MPEG-4 PCI boards
233 233
 @item LOAS                      @tab   @tab X
234 234
     @tab contains LATM multiplexed AAC audio
235
+@item LVF                       @tab   @tab X
235 236
 @item LXF                       @tab   @tab X
236 237
     @tab VR native stream format, used by Leitch/Harris' video servers.
237 238
 @item Matroska                  @tab X @tab X
... ...
@@ -151,6 +151,7 @@ OBJS-$(CONFIG_LATM_DEMUXER)              += rawdec.o
151 151
 OBJS-$(CONFIG_LATM_MUXER)                += latmenc.o rawenc.o
152 152
 OBJS-$(CONFIG_LMLM4_DEMUXER)             += lmlm4.o
153 153
 OBJS-$(CONFIG_LOAS_DEMUXER)              += loasdec.o
154
+OBJS-$(CONFIG_LVF_DEMUXER)               += lvfdec.o
154 155
 OBJS-$(CONFIG_LXF_DEMUXER)               += lxfdec.o
155 156
 OBJS-$(CONFIG_M4V_DEMUXER)               += m4vdec.o rawdec.o
156 157
 OBJS-$(CONFIG_M4V_MUXER)                 += rawenc.o
... ...
@@ -133,6 +133,7 @@ void av_register_all(void)
133 133
     REGISTER_MUXDEMUX (LATM, latm);
134 134
     REGISTER_DEMUXER  (LMLM4, lmlm4);
135 135
     REGISTER_DEMUXER  (LOAS, loas);
136
+    REGISTER_DEMUXER  (LVF, lvf);
136 137
     REGISTER_DEMUXER  (LXF, lxf);
137 138
     REGISTER_MUXDEMUX (M4V, m4v);
138 139
     REGISTER_MUXER    (MD5, md5);
139 140
new file mode 100644
... ...
@@ -0,0 +1,148 @@
0
+/*
1
+ * LVF demuxer
2
+ * Copyright (c) 2012 Paul B Mahol
3
+ *
4
+ * This file is part of FFmpeg.
5
+ *
6
+ * FFmpeg is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * FFmpeg is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with FFmpeg; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+ */
20
+
21
+#include "libavutil/intreadwrite.h"
22
+#include "avformat.h"
23
+#include "riff.h"
24
+
25
+static int lvf_probe(AVProbeData *p)
26
+{
27
+    if (AV_RL32(p->buf) == MKTAG('L', 'V', 'F', 'F'))
28
+        return AVPROBE_SCORE_MAX / 2;
29
+    return 0;
30
+}
31
+
32
+static int lvf_read_header(AVFormatContext *s)
33
+{
34
+    AVStream *st;
35
+    int64_t next_offset;
36
+    unsigned size, nb_streams, id;
37
+
38
+    avio_skip(s->pb, 16);
39
+    nb_streams = avio_rl32(s->pb);
40
+    if (!nb_streams)
41
+        return AVERROR_INVALIDDATA;
42
+    if (nb_streams > 2) {
43
+        av_log_ask_for_sample(s, "too many streams\n");
44
+        return AVERROR_PATCHWELCOME;
45
+    }
46
+
47
+    avio_skip(s->pb, 1012);
48
+
49
+    while (!url_feof(s->pb)) {
50
+        id          = avio_rl32(s->pb);
51
+        size        = avio_rl32(s->pb);
52
+        next_offset = avio_tell(s->pb) + size;
53
+
54
+        switch (id) {
55
+        case MKTAG('0', '0', 'f', 'm'):
56
+            st = avformat_new_stream(s, 0);
57
+            if (!st)
58
+                return AVERROR(ENOMEM);
59
+
60
+            st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
61
+            avio_skip(s->pb, 4);
62
+            st->codec->width      = avio_rl32(s->pb);
63
+            st->codec->height     = avio_rl32(s->pb);
64
+            avio_skip(s->pb, 4);
65
+            st->codec->codec_tag  = avio_rl32(s->pb);
66
+            st->codec->codec_id   = ff_codec_get_id(ff_codec_bmp_tags,
67
+                                                    st->codec->codec_tag);
68
+            avpriv_set_pts_info(st, 32, 1, 1000);
69
+            break;
70
+        case MKTAG('0', '1', 'f', 'm'):
71
+            st = avformat_new_stream(s, 0);
72
+            if (!st)
73
+                return AVERROR(ENOMEM);
74
+
75
+            st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
76
+            st->codec->codec_tag   = avio_rl16(s->pb);
77
+            st->codec->channels    = avio_rl16(s->pb);
78
+            st->codec->sample_rate = avio_rl16(s->pb);
79
+            avio_skip(s->pb, 8);
80
+            st->codec->bits_per_coded_sample = avio_r8(s->pb);
81
+            st->codec->codec_id    = ff_codec_get_id(ff_codec_wav_tags,
82
+                                                     st->codec->codec_tag);
83
+            avpriv_set_pts_info(st, 32, 1, 1000);
84
+            break;
85
+        case 0:
86
+            avio_seek(s->pb, 2048 + 8, SEEK_SET);
87
+            return 0;
88
+        default:
89
+            av_log_ask_for_sample(s, "unknown id\n");
90
+            return AVERROR_PATCHWELCOME;
91
+        }
92
+
93
+        avio_seek(s->pb, next_offset, SEEK_SET);
94
+    }
95
+
96
+    return AVERROR_EOF;
97
+}
98
+
99
+static int lvf_read_packet(AVFormatContext *s, AVPacket *pkt)
100
+{
101
+    unsigned size, flags, timestamp, id;
102
+    int64_t pos;
103
+    int ret, is_video = 0;
104
+
105
+    pos = avio_tell(s->pb);
106
+    while (!url_feof(s->pb)) {
107
+        id    = avio_rl32(s->pb);
108
+        size  = avio_rl32(s->pb);
109
+
110
+        if (size == 0xFFFFFFFFu)
111
+            return AVERROR_EOF;
112
+
113
+        switch (id) {
114
+        case MKTAG('0', '0', 'd', 'c'):
115
+            is_video = 1;
116
+        case MKTAG('0', '1', 'w', 'b'):
117
+            if (size < 8)
118
+                return AVERROR_INVALIDDATA;
119
+            timestamp = avio_rl32(s->pb);
120
+            flags = avio_rl32(s->pb);
121
+            ret = av_get_packet(s->pb, pkt, size - 8);
122
+            if (flags & (1 << 12))
123
+                pkt->flags |= AV_PKT_FLAG_KEY;
124
+            pkt->stream_index = is_video ? 0 : 1;
125
+            pkt->pts          = timestamp;
126
+            pkt->pos          = pos;
127
+            return ret;
128
+        default:
129
+            ret = avio_skip(s->pb, size);
130
+        }
131
+
132
+        if (ret < 0)
133
+              return ret;
134
+    }
135
+
136
+    return AVERROR_EOF;
137
+}
138
+
139
+AVInputFormat ff_lvf_demuxer = {
140
+    .name        = "lvf",
141
+    .long_name   = NULL_IF_CONFIG_SMALL("LVF"),
142
+    .read_probe  = lvf_probe,
143
+    .read_header = lvf_read_header,
144
+    .read_packet = lvf_read_packet,
145
+    .extensions  = "lvf",
146
+    .flags       = AVFMT_GENERIC_INDEX,
147
+};
... ...
@@ -30,7 +30,7 @@
30 30
 #include "libavutil/avutil.h"
31 31
 
32 32
 #define LIBAVFORMAT_VERSION_MAJOR 54
33
-#define LIBAVFORMAT_VERSION_MINOR 33
33
+#define LIBAVFORMAT_VERSION_MINOR 34
34 34
 #define LIBAVFORMAT_VERSION_MICRO 100
35 35
 
36 36
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \