Browse code

avformat: add MIDI Sample Dump Standard demuxer

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

Paul B Mahol authored on 2017/01/21 01:01:31
Showing 6 changed files
... ...
@@ -14,6 +14,7 @@ version <next>:
14 14
 - Apple Pixlet decoder
15 15
 - QDMC audio decoder
16 16
 - NewTek SpeedHQ decoder
17
+- MIDI Sample Dump Standard demuxer
17 18
 
18 19
 version 3.2:
19 20
 - libopenmpt demuxer
... ...
@@ -387,6 +387,7 @@ library:
387 387
     @tab Audio format used on the PS3.
388 388
 @item Mirillis FIC video        @tab   @tab X
389 389
     @tab No cursor rendering.
390
+@item MIDI Sample Dump Standard @tab   @tab X
390 391
 @item MIME multipart JPEG       @tab X @tab
391 392
 @item MSN TCP webcam            @tab   @tab X
392 393
     @tab Used by MSN Messenger webcam streams.
... ...
@@ -436,6 +436,7 @@ OBJS-$(CONFIG_SAP_MUXER)                 += sapenc.o
436 436
 OBJS-$(CONFIG_SBG_DEMUXER)               += sbgdec.o
437 437
 OBJS-$(CONFIG_SDP_DEMUXER)               += rtsp.o
438 438
 OBJS-$(CONFIG_SDR2_DEMUXER)              += sdr2.o
439
+OBJS-$(CONFIG_SDS_DEMUXER)               += sdsdec.o
439 440
 OBJS-$(CONFIG_SEGAFILM_DEMUXER)          += segafilm.o
440 441
 OBJS-$(CONFIG_SEGMENT_MUXER)             += segment.o
441 442
 OBJS-$(CONFIG_SHORTEN_DEMUXER)           += shortendec.o rawdec.o
... ...
@@ -275,6 +275,7 @@ void av_register_all(void)
275 275
     REGISTER_DEMUXER (SBG,              sbg);
276 276
     REGISTER_DEMUXER (SDP,              sdp);
277 277
     REGISTER_DEMUXER (SDR2,             sdr2);
278
+    REGISTER_DEMUXER (SDS,              sds);
278 279
 #if CONFIG_RTPDEC
279 280
     ff_register_rtp_dynamic_payload_handlers();
280 281
     ff_register_rdt_dynamic_payload_handlers();
281 282
new file mode 100644
... ...
@@ -0,0 +1,165 @@
0
+/*
1
+ * MIDI Sample Dump Standard format demuxer
2
+ * Copyright (c) 2017 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 "internal.h"
24
+
25
+typedef struct SDSContext {
26
+    uint8_t data[120];
27
+    int bit_depth;
28
+    int size;
29
+    void (*read_block)(const uint8_t *src, uint32_t *dst);
30
+} SDSContext;
31
+
32
+static int sds_probe(AVProbeData *p)
33
+{
34
+    if (AV_RB32(p->buf) == 0xF07E0001 && p->buf[20] == 0xF7 &&
35
+        p->buf[6] >= 8 && p->buf[6] <= 28)
36
+        return AVPROBE_SCORE_EXTENSION;
37
+    return 0;
38
+}
39
+
40
+static void byte2_read(const uint8_t *src, uint32_t *dst)
41
+{
42
+    int i;
43
+
44
+    for (i = 0; i < 120; i += 2) {
45
+        unsigned sample = (src[i + 0] << 25) + (src[i + 1] << 18);
46
+
47
+        dst[i / 2] = sample;
48
+    }
49
+}
50
+
51
+static void byte3_read(const uint8_t *src, uint32_t *dst)
52
+{
53
+    int i;
54
+
55
+    for (i = 0; i < 120; i += 3) {
56
+        unsigned sample;
57
+
58
+        sample = (src[i + 0] << 25) | (src[i + 1] << 18) | (src[i + 2] << 11);
59
+        dst[i / 3] = sample;
60
+    }
61
+}
62
+
63
+static void byte4_read(const uint8_t *src, uint32_t *dst)
64
+{
65
+    int i;
66
+
67
+    for (i = 0; i < 120; i += 4) {
68
+        unsigned sample;
69
+
70
+        sample = (src[i + 0] << 25) | (src[i + 1] << 18) | (src[i + 2] << 11) | (src[i + 3] << 4);
71
+        dst[i / 4] = sample;
72
+    }
73
+}
74
+
75
+#define SDS_3BYTE_TO_INT_DECODE(x) (((x) & 0x7F) | (((x) & 0x7F00) >> 1) | (((x) & 0x7F0000) >> 2))
76
+
77
+static int sds_read_header(AVFormatContext *ctx)
78
+{
79
+    SDSContext *s = ctx->priv_data;
80
+    unsigned sample_period;
81
+    AVIOContext *pb = ctx->pb;
82
+    AVStream *st;
83
+
84
+    st = avformat_new_stream(ctx, NULL);
85
+    if (!st)
86
+        return AVERROR(ENOMEM);
87
+
88
+    avio_skip(pb, 4);
89
+    avio_skip(pb, 2);
90
+
91
+    s->bit_depth = avio_r8(pb);
92
+    if (s->bit_depth < 8 || s->bit_depth > 28)
93
+        return AVERROR_INVALIDDATA;
94
+
95
+    if (s->bit_depth < 14) {
96
+        s->read_block = byte2_read;
97
+        s->size = 60 * 4;
98
+    } else if (s->bit_depth < 21) {
99
+        s->read_block = byte3_read;
100
+        s->size = 40 * 4;
101
+    } else {
102
+        s->read_block = byte4_read;
103
+        s->size = 30 * 4;
104
+    }
105
+    st->codecpar->codec_id = AV_CODEC_ID_PCM_U32LE;
106
+
107
+    sample_period = avio_rl24(pb);
108
+    sample_period = SDS_3BYTE_TO_INT_DECODE(sample_period);
109
+    avio_skip(pb, 11);
110
+
111
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
112
+    st->codecpar->channels = 1;
113
+    st->codecpar->sample_rate = sample_period ? 1000000000 / sample_period : 16000;
114
+    st->duration = (avio_size(pb) - 21) / (127) * s->size / 4;
115
+
116
+    avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
117
+
118
+    return 0;
119
+}
120
+
121
+static int sds_read_packet(AVFormatContext *ctx, AVPacket *pkt)
122
+{
123
+    SDSContext *s = ctx->priv_data;
124
+    AVIOContext *pb = ctx->pb;
125
+    int64_t pos;
126
+    int ret;
127
+
128
+    if (avio_feof(pb))
129
+        return AVERROR_EOF;
130
+
131
+    pos = avio_tell(pb);
132
+    if (avio_rb16(pb) != 0xF07E)
133
+        return AVERROR_INVALIDDATA;
134
+    avio_skip(pb, 3);
135
+
136
+    ret = av_new_packet(pkt, s->size);
137
+    if (ret < 0)
138
+        return ret;
139
+
140
+    ret = avio_read(pb, s->data, 120);
141
+
142
+    s->read_block(s->data, (uint32_t *)pkt->data);
143
+
144
+    avio_skip(pb, 1); // checksum
145
+    if (avio_r8(pb) != 0xF7)
146
+        return AVERROR_INVALIDDATA;
147
+
148
+    pkt->flags &= ~AV_PKT_FLAG_CORRUPT;
149
+    pkt->stream_index = 0;
150
+    pkt->pos = pos;
151
+
152
+    return ret;
153
+}
154
+
155
+AVInputFormat ff_sds_demuxer = {
156
+    .name           = "sds",
157
+    .long_name      = NULL_IF_CONFIG_SMALL("MIDI Sample Dump Standard"),
158
+    .priv_data_size = sizeof(SDSContext),
159
+    .read_probe     = sds_probe,
160
+    .read_header    = sds_read_header,
161
+    .read_packet    = sds_read_packet,
162
+    .extensions     = "sds",
163
+    .flags          = AVFMT_GENERIC_INDEX,
164
+};
... ...
@@ -32,7 +32,7 @@
32 32
 // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium)
33 33
 // Also please add any ticket numbers that you believe might be affected here
34 34
 #define LIBAVFORMAT_VERSION_MAJOR  57
35
-#define LIBAVFORMAT_VERSION_MINOR  62
35
+#define LIBAVFORMAT_VERSION_MINOR  63
36 36
 #define LIBAVFORMAT_VERSION_MICRO 100
37 37
 
38 38
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \