Browse code

RSD demuxer

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

James Almer authored on 2013/05/11 04:52:10
Showing 8 changed files
... ...
@@ -42,6 +42,7 @@ version <next>:
42 42
 - avectorscope filter
43 43
 - ADPCM DTK decoder
44 44
 - ADP demuxer
45
+- RSD demuxer
45 46
 
46 47
 
47 48
 version 1.2:
... ...
@@ -355,6 +355,7 @@ library:
355 355
     @tab Audio and video format used in some games by Entertainment Software Partners.
356 356
 @item RPL/ARMovie               @tab   @tab X
357 357
 @item Lego Mindstorms RSO       @tab X @tab X
358
+@item RSD                       @tab   @tab X
358 359
 @item RTMP                      @tab X @tab X
359 360
     @tab Output is performed by publishing stream to RTMP server
360 361
 @item RTP                       @tab X @tab X
... ...
@@ -313,6 +313,7 @@ OBJS-$(CONFIG_RM_DEMUXER)                += rmdec.o rm.o rmsipr.o
313 313
 OBJS-$(CONFIG_RM_MUXER)                  += rmenc.o rm.o
314 314
 OBJS-$(CONFIG_ROQ_DEMUXER)               += idroqdec.o
315 315
 OBJS-$(CONFIG_ROQ_MUXER)                 += idroqenc.o rawenc.o
316
+OBJS-$(CONFIG_RSD_DEMUXER)               += rsd.o
316 317
 OBJS-$(CONFIG_RSO_DEMUXER)               += rsodec.o rso.o pcm.o
317 318
 OBJS-$(CONFIG_RSO_MUXER)                 += rsoenc.o rso.o
318 319
 OBJS-$(CONFIG_RPL_DEMUXER)               += rpl.o
... ...
@@ -237,6 +237,7 @@ void av_register_all(void)
237 237
     REGISTER_MUXDEMUX(RM,               rm);
238 238
     REGISTER_MUXDEMUX(ROQ,              roq);
239 239
     REGISTER_DEMUXER (RPL,              rpl);
240
+    REGISTER_DEMUXER (RSD,              rsd);
240 241
     REGISTER_MUXDEMUX(RSO,              rso);
241 242
     REGISTER_MUXDEMUX(RTP,              rtp);
242 243
     REGISTER_MUXDEMUX(RTSP,             rtsp);
243 244
new file mode 100644
... ...
@@ -0,0 +1,161 @@
0
+/*
1
+ * RSD 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
+static const AVCodecTag rsd_tags[] = {
28
+    { AV_CODEC_ID_ADPCM_THP,       MKTAG('G','A','D','P') },
29
+    { AV_CODEC_ID_PCM_S16BE,       MKTAG('P','C','M','B') },
30
+    { AV_CODEC_ID_PCM_S16LE,       MKTAG('P','C','M',' ') },
31
+    { AV_CODEC_ID_NONE, 0 },
32
+};
33
+
34
+static const uint32_t rsd_unsupported_tags[] = {
35
+    MKTAG('O','G','G',' '),
36
+    MKTAG('R','A','D','P'),
37
+    MKTAG('V','A','G',' '),
38
+    MKTAG('W','A','D','P'),
39
+    MKTAG('X','A','D','P'),
40
+    MKTAG('X','M','A',' '),
41
+};
42
+
43
+static int rsd_probe(AVProbeData *p)
44
+{
45
+    if (!memcmp(p->buf, "RSD", 3) &&
46
+        p->buf[3] - '0' >= 2 && p->buf[3] - '0' <= 6)
47
+        return AVPROBE_SCORE_EXTENSION;
48
+    return 0;
49
+}
50
+
51
+static int rsd_read_header(AVFormatContext *s)
52
+{
53
+    AVIOContext *pb = s->pb;
54
+    int i, version, start = 0x800;
55
+    AVCodecContext *codec;
56
+    AVStream *st = avformat_new_stream(s, NULL);
57
+
58
+    if (!st)
59
+        return AVERROR(ENOMEM);
60
+
61
+    avio_skip(pb, 3); // "RSD"
62
+    version = avio_r8(pb) - '0';
63
+
64
+    codec = st->codec;
65
+    codec->codec_type = AVMEDIA_TYPE_AUDIO;
66
+    codec->codec_tag  = avio_rl32(pb);
67
+    codec->codec_id   = ff_codec_get_id(rsd_tags, codec->codec_tag);
68
+    if (!codec->codec_id) {
69
+        char tag_buf[5];
70
+
71
+        av_get_codec_tag_string(tag_buf, sizeof(tag_buf), codec->codec_tag);
72
+        for (i=0; i < FF_ARRAY_ELEMS(rsd_unsupported_tags); i++) {
73
+            if (codec->codec_tag == rsd_unsupported_tags[i]) {
74
+                avpriv_request_sample(s, "Codec tag: %s", tag_buf);
75
+                return AVERROR_PATCHWELCOME;
76
+            }
77
+        }
78
+        av_log(s, AV_LOG_ERROR, "Unknown codec tag: %s\n", tag_buf);
79
+        return AVERROR_INVALIDDATA;
80
+    }
81
+
82
+    codec->channels = avio_rl32(pb);
83
+    if (!codec->channels)
84
+        return AVERROR_INVALIDDATA;
85
+
86
+    avio_skip(pb, 4); // Bit depth
87
+    codec->sample_rate = avio_rl32(pb);
88
+    if (!codec->sample_rate)
89
+        return AVERROR_INVALIDDATA;
90
+
91
+    avio_skip(pb, 4); // Unknown
92
+
93
+    switch (codec->codec_id) {
94
+    case AV_CODEC_ID_ADPCM_THP:
95
+        /* RSD3GADP is mono, so only alloc enough memory
96
+           to store the coeff table for a single channel. */
97
+
98
+        codec->extradata_size = 32;
99
+        codec->extradata = av_malloc(codec->extradata_size);
100
+        if (!codec->extradata)
101
+            return AVERROR(ENOMEM);
102
+
103
+        start = avio_rl32(pb);
104
+
105
+        if (avio_read(s->pb, codec->extradata, 32) != 32)
106
+            return AVERROR_INVALIDDATA;
107
+
108
+        for (i = 0; i < 16; i++)
109
+            AV_WB16(codec->extradata + i * 2, AV_RL16(codec->extradata + i * 2));
110
+
111
+        if (pb->seekable)
112
+            st->duration = (avio_size(pb) - start) / 8 * 14;
113
+        break;
114
+    case AV_CODEC_ID_PCM_S16LE:
115
+    case AV_CODEC_ID_PCM_S16BE:
116
+        if (version != 4)
117
+            start = avio_rl32(pb);
118
+
119
+        if (pb->seekable)
120
+            st->duration = (avio_size(pb) - start) / 2 / codec->channels;
121
+        break;
122
+    }
123
+
124
+    avio_skip(pb, start - avio_tell(pb));
125
+
126
+    avpriv_set_pts_info(st, 64, 1, codec->sample_rate);
127
+
128
+    return 0;
129
+}
130
+
131
+static int rsd_read_packet(AVFormatContext *s, AVPacket *pkt)
132
+{
133
+    int ret, size = 1024;
134
+
135
+    if (url_feof(s->pb))
136
+        return AVERROR_EOF;
137
+
138
+    ret = av_get_packet(s->pb, pkt, size);
139
+
140
+    if (ret != size) {
141
+        if (ret < 0) {
142
+            av_free_packet(pkt);
143
+            return ret;
144
+        }
145
+        av_shrink_packet(pkt, ret);
146
+    }
147
+    pkt->stream_index = 0;
148
+
149
+    return ret;
150
+}
151
+
152
+AVInputFormat ff_rsd_demuxer = {
153
+    .name           =   "rsd",
154
+    .long_name      =   NULL_IF_CONFIG_SMALL("GameCube RSD"),
155
+    .read_probe     =   rsd_probe,
156
+    .read_header    =   rsd_read_header,
157
+    .read_packet    =   rsd_read_packet,
158
+    .extensions     =   "rsd",
159
+    .codec_tag      =   (const AVCodecTag* const []){rsd_tags, 0},
160
+};
... ...
@@ -30,7 +30,7 @@
30 30
 #include "libavutil/avutil.h"
31 31
 
32 32
 #define LIBAVFORMAT_VERSION_MAJOR 55
33
-#define LIBAVFORMAT_VERSION_MINOR  5
33
+#define LIBAVFORMAT_VERSION_MINOR  6
34 34
 #define LIBAVFORMAT_VERSION_MICRO 100
35 35
 
36 36
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
... ...
@@ -67,6 +67,9 @@ fate-paf-demux: CMD = framecrc -i $(SAMPLES)/paf/hod1-partial.paf -vcodec copy -
67 67
 FATE_SAMPLES_DEMUX-$(CONFIG_PMP_DEMUXER) += fate-pmp-demux
68 68
 fate-pmp-demux: CMD = framecrc -i $(SAMPLES)/pmp/demo.pmp -vn -c:a copy
69 69
 
70
+FATE_SAMPLES_DEMUX-$(CONFIG_RSD_DEMUXER) += fate-rsd-demux
71
+fate-rsd-demux: CMD = crc -i $(SAMPLES)/rsd/hum01_partial.rsd -c:a copy
72
+
70 73
 FATE_SAMPLES_DEMUX-$(CONFIG_STR_DEMUXER) += fate-psx-str-demux
71 74
 fate-psx-str-demux: CMD = framecrc -i $(SAMPLES)/psx-str/descent-partial.str -c copy
72 75
 
73 76
new file mode 100644
... ...
@@ -0,0 +1 @@
0
+CRC=0x7b7807d8