Browse code

RedSpark demuxer

Signed-off-by: James Almer <jamrial@gmail.com>

James Almer authored on 2013/05/11 04:53:02
Showing 8 changed files
... ...
@@ -43,6 +43,7 @@ version <next>:
43 43
 - ADPCM DTK decoder
44 44
 - ADP demuxer
45 45
 - RSD demuxer
46
+- RedSpark demuxer
46 47
 
47 48
 
48 49
 version 1.2:
... ...
@@ -350,6 +350,7 @@ library:
350 350
     @tab File format used by RED Digital cameras, contains JPEG 2000 frames and PCM audio.
351 351
 @item RealMedia                 @tab X @tab X
352 352
 @item Redirector                @tab   @tab X
353
+@item RedSpark                  @tab   @tab X
353 354
 @item Renderware TeXture Dictionary @tab   @tab X
354 355
 @item RL2                       @tab   @tab X
355 356
     @tab Audio and video format used in some games by Entertainment Software Partners.
... ...
@@ -308,6 +308,7 @@ OBJS-$(CONFIG_R3D_DEMUXER)               += r3d.o
308 308
 OBJS-$(CONFIG_RAWVIDEO_DEMUXER)          += rawvideodec.o
309 309
 OBJS-$(CONFIG_RAWVIDEO_MUXER)            += rawenc.o
310 310
 OBJS-$(CONFIG_REALTEXT_DEMUXER)          += realtextdec.o subtitles.o
311
+OBJS-$(CONFIG_REDSPARK_DEMUXER)          += redspark.o
311 312
 OBJS-$(CONFIG_RL2_DEMUXER)               += rl2.o
312 313
 OBJS-$(CONFIG_RM_DEMUXER)                += rmdec.o rm.o rmsipr.o
313 314
 OBJS-$(CONFIG_RM_MUXER)                  += rmenc.o rm.o
... ...
@@ -233,6 +233,7 @@ void av_register_all(void)
233 233
     REGISTER_DEMUXER (R3D,              r3d);
234 234
     REGISTER_MUXDEMUX(RAWVIDEO,         rawvideo);
235 235
     REGISTER_DEMUXER (REALTEXT,         realtext);
236
+    REGISTER_DEMUXER (REDSPARK,         redspark);
236 237
     REGISTER_DEMUXER (RL2,              rl2);
237 238
     REGISTER_MUXDEMUX(RM,               rm);
238 239
     REGISTER_MUXDEMUX(ROQ,              roq);
239 240
new file mode 100644
... ...
@@ -0,0 +1,157 @@
0
+/*
1
+ * RedSpark demuxer
2
+ * Copyright (c) 2013 James Almer
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 "libavcodec/bytestream.h"
22
+#include "libavutil/intreadwrite.h"
23
+#include "avformat.h"
24
+#include "avio.h"
25
+#include "internal.h"
26
+
27
+#define HEADER_SIZE 4096
28
+
29
+typedef struct RedSparkContext {
30
+    int         samples_count;
31
+} RedSparkContext;
32
+
33
+static int redspark_probe(AVProbeData *p)
34
+{
35
+    uint32_t key, data;
36
+    uint8_t header[8];
37
+
38
+    /* Decrypt first 8 bytes of the header */
39
+    data = AV_RB32(p->buf);
40
+    data = data ^ (key = data ^ 0x52656453);
41
+    AV_WB32(header, data);
42
+    key = (key << 11) | (key >> 21);
43
+
44
+    data = AV_RB32(p->buf + 4) ^ (((key << 3) | (key >> 29)) + key);
45
+    AV_WB32(header + 4, data);
46
+
47
+    if (AV_RB64(header) == AV_RB64("RedSpark"))
48
+        return AVPROBE_SCORE_MAX;
49
+
50
+    return 0;
51
+}
52
+
53
+static int redspark_read_header(AVFormatContext *s)
54
+{
55
+    AVIOContext *pb = s->pb;
56
+    RedSparkContext *redspark = s->priv_data;
57
+    AVCodecContext *codec;
58
+    GetByteContext gbc;
59
+    int i, coef_off;
60
+    uint32_t key, data;
61
+    uint8_t *header, *pbc;
62
+    AVStream *st;
63
+
64
+    st = avformat_new_stream(s, NULL);
65
+    if (!st)
66
+        return AVERROR(ENOMEM);
67
+    codec = st->codec;
68
+
69
+    header = av_malloc(HEADER_SIZE);
70
+    if (!header)
71
+        return AVERROR(ENOMEM);
72
+    pbc = header;
73
+
74
+    /* Decrypt header */
75
+    data = avio_rb32(pb);
76
+    data = data ^ (key = data ^ 0x52656453);
77
+    bytestream_put_be32(&pbc, data);
78
+    key = (key << 11) | (key >> 21);
79
+
80
+    for (i = 4; i < HEADER_SIZE; i += 4) {
81
+        data = avio_rb32(pb) ^ (key = ((key << 3) | (key >> 29)) + key);
82
+        bytestream_put_be32(&pbc, data);
83
+    }
84
+
85
+    codec->codec_id    = AV_CODEC_ID_ADPCM_THP;
86
+    codec->codec_type  = AVMEDIA_TYPE_AUDIO;
87
+
88
+    bytestream2_init(&gbc, header, HEADER_SIZE);
89
+    bytestream2_seek(&gbc, 0x3c, SEEK_SET);
90
+    codec->sample_rate = bytestream2_get_be32u(&gbc);
91
+    if (codec->sample_rate <= 0 || codec->sample_rate > 96000) {
92
+        av_log(s, AV_LOG_ERROR, "Invalid sample rate: %d\n", codec->sample_rate);
93
+        return AVERROR_INVALIDDATA;
94
+    }
95
+
96
+    st->duration = bytestream2_get_be32u(&gbc) * 14;
97
+    redspark->samples_count = 0;
98
+    bytestream2_skipu(&gbc, 10);
99
+    codec->channels = bytestream2_get_byteu(&gbc);
100
+    if (!codec->channels)
101
+        return AVERROR_INVALIDDATA;
102
+
103
+    coef_off = 0x54 + codec->channels * 8;
104
+    if (bytestream2_get_byteu(&gbc)) // Loop flag
105
+        coef_off += 16;
106
+
107
+    codec->extradata_size = 32 * codec->channels;
108
+    codec->extradata = av_malloc(codec->extradata_size);
109
+    if (!codec->extradata)
110
+        return AVERROR(ENOMEM);
111
+
112
+    /* Get the ADPCM table */
113
+    bytestream2_seek(&gbc, coef_off, SEEK_SET);
114
+    for (i = 0; i < codec->channels; i++) {
115
+        if (bytestream2_get_bufferu(&gbc, codec->extradata + i * 32, 32) != 32)
116
+            return AVERROR_INVALIDDATA;
117
+        bytestream2_skipu(&gbc, 14);
118
+    }
119
+
120
+    avpriv_set_pts_info(st, 64, 1, codec->sample_rate);
121
+
122
+    return 0;
123
+}
124
+
125
+static int redspark_read_packet(AVFormatContext *s, AVPacket *pkt)
126
+{
127
+    AVCodecContext *codec = s->streams[0]->codec;
128
+    RedSparkContext *redspark = s->priv_data;
129
+    uint32_t size = 8 * codec->channels;
130
+    int ret;
131
+
132
+    if (url_feof(s->pb) || redspark->samples_count == s->streams[0]->duration)
133
+        return AVERROR_EOF;
134
+
135
+    ret = av_get_packet(s->pb, pkt, size);
136
+    if (ret != size) {
137
+        av_free_packet(pkt);
138
+        return AVERROR(EIO);
139
+    }
140
+
141
+    pkt->duration = 14;
142
+    redspark->samples_count += pkt->duration;
143
+    pkt->stream_index = 0;
144
+
145
+    return ret;
146
+}
147
+
148
+AVInputFormat ff_redspark_demuxer = {
149
+    .name           =   "redspark",
150
+    .long_name      =   NULL_IF_CONFIG_SMALL("RedSpark"),
151
+    .priv_data_size =   sizeof(RedSparkContext),
152
+    .read_probe     =   redspark_probe,
153
+    .read_header    =   redspark_read_header,
154
+    .read_packet    =   redspark_read_packet,
155
+    .extensions     =   "rsd",
156
+};
... ...
@@ -30,7 +30,7 @@
30 30
 #include "libavutil/avutil.h"
31 31
 
32 32
 #define LIBAVFORMAT_VERSION_MAJOR 55
33
-#define LIBAVFORMAT_VERSION_MINOR  6
33
+#define LIBAVFORMAT_VERSION_MINOR  7
34 34
 #define LIBAVFORMAT_VERSION_MICRO 100
35 35
 
36 36
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
... ...
@@ -70,6 +70,9 @@ fate-pmp-demux: CMD = framecrc -i $(SAMPLES)/pmp/demo.pmp -vn -c:a copy
70 70
 FATE_SAMPLES_DEMUX-$(CONFIG_RSD_DEMUXER) += fate-rsd-demux
71 71
 fate-rsd-demux: CMD = crc -i $(SAMPLES)/rsd/hum01_partial.rsd -c:a copy
72 72
 
73
+FATE_SAMPLES_DEMUX-$(CONFIG_REDSPARK_DEMUXER) += fate-redspark-demux
74
+fate-redspark-demux: CMD = crc -i $(SAMPLES)/redspark/jingle04_partial.rsd -c:a copy
75
+
73 76
 FATE_SAMPLES_DEMUX-$(CONFIG_STR_DEMUXER) += fate-psx-str-demux
74 77
 fate-psx-str-demux: CMD = framecrc -i $(SAMPLES)/psx-str/descent-partial.str -c copy
75 78
 
76 79
new file mode 100644
... ...
@@ -0,0 +1 @@
0
+CRC=0xc0fd1aa2