Browse code

add SMJPEG muxer

Signed-off-by: Kostya Shishkov <kostya.shishkov@gmail.com>

Paul B Mahol authored on 2012/01/15 04:29:59
Showing 6 changed files
... ...
@@ -5,6 +5,7 @@ releases are sorted from youngest to oldest.
5 5
 version <next>:
6 6
 
7 7
 - GSM audio parser
8
+- SMJPEG muxer
8 9
 
9 10
 
10 11
 version 0.8_beta2:
... ...
@@ -296,7 +296,7 @@ library:
296 296
     @tab Used in Sierra CD-ROM games.
297 297
 @item Smacker                   @tab   @tab X
298 298
     @tab Multimedia format used by many games.
299
-@item SMJPEG                    @tab   @tab X
299
+@item SMJPEG                    @tab X @tab X
300 300
     @tab Used in certain Loki game ports.
301 301
 @item Sony OpenMG (OMA)         @tab X @tab X
302 302
     @tab Audio format used in Sony Sonic Stage and Sony Vegas.
... ...
@@ -275,6 +275,7 @@ OBJS-$(CONFIG_SHORTEN_DEMUXER)           += rawdec.o
275 275
 OBJS-$(CONFIG_SIFF_DEMUXER)              += siff.o
276 276
 OBJS-$(CONFIG_SMACKER_DEMUXER)           += smacker.o
277 277
 OBJS-$(CONFIG_SMJPEG_DEMUXER)            += smjpegdec.o smjpeg.o
278
+OBJS-$(CONFIG_SMJPEG_MUXER)              += smjpegenc.o smjpeg.o
278 279
 OBJS-$(CONFIG_SOL_DEMUXER)               += sol.o pcm.o
279 280
 OBJS-$(CONFIG_SOX_DEMUXER)               += soxdec.o pcm.o
280 281
 OBJS-$(CONFIG_SOX_MUXER)                 += soxenc.o
... ...
@@ -201,7 +201,7 @@ void av_register_all(void)
201 201
     REGISTER_DEMUXER  (SHORTEN, shorten);
202 202
     REGISTER_DEMUXER  (SIFF, siff);
203 203
     REGISTER_DEMUXER  (SMACKER, smacker);
204
-    REGISTER_DEMUXER  (SMJPEG, smjpeg);
204
+    REGISTER_MUXDEMUX (SMJPEG, smjpeg);
205 205
     REGISTER_DEMUXER  (SOL, sol);
206 206
     REGISTER_MUXDEMUX (SOX, sox);
207 207
     REGISTER_MUXDEMUX (SPDIF, spdif);
208 208
new file mode 100644
... ...
@@ -0,0 +1,149 @@
0
+/*
1
+ * SMJPEG muxer
2
+ * Copyright (c) 2012 Paul B Mahol
3
+ *
4
+ * This file is part of Libav.
5
+ *
6
+ * Libav 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
+ * Libav 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 Libav; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+ */
20
+
21
+/**
22
+ * @file
23
+ * This is a muxer for Loki SDL Motion JPEG files
24
+ */
25
+
26
+#include "avformat.h"
27
+#include "internal.h"
28
+#include "riff.h"
29
+#include "smjpeg.h"
30
+
31
+typedef struct SMJPEGMuxContext {
32
+    uint32_t duration;
33
+} SMJPEGMuxContext;
34
+
35
+static int smjpeg_write_header(AVFormatContext *s)
36
+{
37
+    AVDictionaryEntry *t = NULL;
38
+    AVIOContext *pb = s->pb;
39
+    int n, tag;
40
+
41
+    if (s->nb_streams > 2) {
42
+        av_log(s, AV_LOG_ERROR, "more than >2 streams are not supported\n");
43
+        return AVERROR(EINVAL);
44
+    }
45
+    avio_write(pb, SMJPEG_MAGIC, 8);
46
+    avio_wb32(pb, 0);
47
+    avio_wb32(pb, 0);
48
+
49
+    while ((t = av_dict_get(s->metadata, "", t, AV_DICT_IGNORE_SUFFIX))) {
50
+        avio_wl32(pb, SMJPEG_TXT);
51
+        avio_wb32(pb, strlen(t->key) + strlen(t->value) + 3);
52
+        avio_write(pb, t->key, strlen(t->key));
53
+        avio_write(pb, " = ", 3);
54
+        avio_write(pb, t->value, strlen(t->value));
55
+    }
56
+
57
+    for (n = 0; n < s->nb_streams; n++) {
58
+        AVStream *st = s->streams[n];
59
+        AVCodecContext *codec = st->codec;
60
+        if (codec->codec_type == AVMEDIA_TYPE_AUDIO) {
61
+            tag = ff_codec_get_tag(ff_codec_smjpeg_audio_tags, codec->codec_id);
62
+            if (!tag) {
63
+                av_log(s, AV_LOG_ERROR, "unsupported audio codec\n");
64
+                return AVERROR(EINVAL);
65
+            }
66
+            avio_wl32(pb, SMJPEG_SND);
67
+            avio_wb32(pb, 8);
68
+            avio_wb16(pb, codec->sample_rate);
69
+            avio_w8(pb, av_get_bits_per_sample(codec->codec_id));
70
+            avio_w8(pb, codec->channels);
71
+            avio_wl32(pb, tag);
72
+            avpriv_set_pts_info(st, 32, 1, 1000);
73
+        } else if (codec->codec_type == AVMEDIA_TYPE_VIDEO) {
74
+            tag = ff_codec_get_tag(ff_codec_smjpeg_video_tags, codec->codec_id);
75
+            if (!tag) {
76
+                av_log(s, AV_LOG_ERROR, "unsupported video codec\n");
77
+                return AVERROR(EINVAL);
78
+            }
79
+            avio_wl32(pb, SMJPEG_VID);
80
+            avio_wb32(pb, 12);
81
+            avio_wb32(pb, 0);
82
+            avio_wb16(pb, codec->width);
83
+            avio_wb16(pb, codec->height);
84
+            avio_wl32(pb, tag);
85
+            avpriv_set_pts_info(st, 32, 1, 1000);
86
+        }
87
+    }
88
+
89
+    avio_wl32(pb, SMJPEG_HEND);
90
+    avio_flush(pb);
91
+
92
+    return 0;
93
+}
94
+
95
+static int smjpeg_write_packet(AVFormatContext *s, AVPacket *pkt)
96
+{
97
+    SMJPEGMuxContext *smc = s->priv_data;
98
+    AVIOContext *pb = s->pb;
99
+    AVStream *st = s->streams[pkt->stream_index];
100
+    AVCodecContext *codec = st->codec;
101
+
102
+    if (codec->codec_type == AVMEDIA_TYPE_AUDIO)
103
+        avio_wl32(pb, SMJPEG_SNDD);
104
+    else if (codec->codec_type == AVMEDIA_TYPE_VIDEO)
105
+        avio_wl32(pb, SMJPEG_VIDD);
106
+    else
107
+        return 0;
108
+
109
+    avio_wb32(pb, pkt->pts);
110
+    avio_wb32(pb, pkt->size);
111
+    avio_write(pb, pkt->data, pkt->size);
112
+    avio_flush(pb);
113
+
114
+    smc->duration = FFMAX(smc->duration, pkt->pts + pkt->duration);
115
+    return 0;
116
+}
117
+
118
+static int smjpeg_write_trailer(AVFormatContext *s)
119
+{
120
+    SMJPEGMuxContext *smc = s->priv_data;
121
+    AVIOContext *pb = s->pb;
122
+    int64_t currentpos;
123
+
124
+    if (pb->seekable) {
125
+        currentpos = avio_tell(pb);
126
+        avio_seek(pb, 12, SEEK_SET);
127
+        avio_wb32(pb, smc->duration);
128
+        avio_seek(pb, currentpos, SEEK_SET);
129
+    }
130
+
131
+    avio_wl32(pb, SMJPEG_DONE);
132
+    avio_flush(pb);
133
+
134
+    return 0;
135
+}
136
+
137
+AVOutputFormat ff_smjpeg_muxer = {
138
+    .name           = "smjpeg",
139
+    .long_name      = NULL_IF_CONFIG_SMALL("Loki SDL MJPEG"),
140
+    .priv_data_size = sizeof(SMJPEGMuxContext),
141
+    .audio_codec    = CODEC_ID_PCM_S16LE,
142
+    .video_codec    = CODEC_ID_MJPEG,
143
+    .write_header   = smjpeg_write_header,
144
+    .write_packet   = smjpeg_write_packet,
145
+    .write_trailer  = smjpeg_write_trailer,
146
+    .flags          = AVFMT_GLOBALHEADER,
147
+    .codec_tag      = (const AVCodecTag *const []){ ff_codec_smjpeg_video_tags, ff_codec_smjpeg_audio_tags, 0 },
148
+};
... ...
@@ -30,7 +30,7 @@
30 30
 #include "libavutil/avutil.h"
31 31
 
32 32
 #define LIBAVFORMAT_VERSION_MAJOR 53
33
-#define LIBAVFORMAT_VERSION_MINOR 19
33
+#define LIBAVFORMAT_VERSION_MINOR 20
34 34
 #define LIBAVFORMAT_VERSION_MICRO  0
35 35
 
36 36
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \