Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Rodger Combs authored on 2015/06/20 19:01:15... | ... |
@@ -33,6 +33,7 @@ typedef struct BRSTMDemuxContext { |
33 | 33 |
uint8_t *table; |
34 | 34 |
uint8_t *adpc; |
35 | 35 |
int bfstm; |
36 |
+ int little_endian; |
|
36 | 37 |
} BRSTMDemuxContext; |
37 | 38 |
|
38 | 39 |
static int probe(AVProbeData *p) |
... | ... |
@@ -46,7 +47,8 @@ static int probe(AVProbeData *p) |
46 | 46 |
|
47 | 47 |
static int probe_bfstm(AVProbeData *p) |
48 | 48 |
{ |
49 |
- if (AV_RL32(p->buf) == MKTAG('F','S','T','M') && |
|
49 |
+ if ((AV_RL32(p->buf) == MKTAG('F','S','T','M') || |
|
50 |
+ AV_RL32(p->buf) == MKTAG('C','S','T','M')) && |
|
50 | 51 |
(AV_RL16(p->buf + 4) == 0xFFFE || |
51 | 52 |
AV_RL16(p->buf + 4) == 0xFEFF)) |
52 | 53 |
return AVPROBE_SCORE_MAX / 3 * 2; |
... | ... |
@@ -63,6 +65,24 @@ static int read_close(AVFormatContext *s) |
63 | 63 |
return 0; |
64 | 64 |
} |
65 | 65 |
|
66 |
+static av_always_inline unsigned int read16(AVFormatContext *s) |
|
67 |
+{ |
|
68 |
+ BRSTMDemuxContext *b = s->priv_data; |
|
69 |
+ if (b->little_endian) |
|
70 |
+ return avio_rl16(s->pb); |
|
71 |
+ else |
|
72 |
+ return avio_rb16(s->pb); |
|
73 |
+} |
|
74 |
+ |
|
75 |
+static av_always_inline unsigned int read32(AVFormatContext *s) |
|
76 |
+{ |
|
77 |
+ BRSTMDemuxContext *b = s->priv_data; |
|
78 |
+ if (b->little_endian) |
|
79 |
+ return avio_rl32(s->pb); |
|
80 |
+ else |
|
81 |
+ return avio_rb32(s->pb); |
|
82 |
+} |
|
83 |
+ |
|
66 | 84 |
static int read_header(AVFormatContext *s) |
67 | 85 |
{ |
68 | 86 |
BRSTMDemuxContext *b = s->priv_data; |
... | ... |
@@ -86,16 +106,15 @@ static int read_header(AVFormatContext *s) |
86 | 86 |
av_log(s, AV_LOG_ERROR, "invalid byte order: %X\n", bom); |
87 | 87 |
return AVERROR_INVALIDDATA; |
88 | 88 |
} |
89 |
- if (bom == 0xFFFE) { |
|
90 |
- avpriv_request_sample(s, "little endian byte order"); |
|
91 |
- return AVERROR_PATCHWELCOME; |
|
92 |
- } |
|
89 |
+ |
|
90 |
+ if (bom == 0xFFFE) |
|
91 |
+ b->little_endian = 1; |
|
93 | 92 |
|
94 | 93 |
if (!b->bfstm) { |
95 | 94 |
major = avio_r8(s->pb); |
96 | 95 |
minor = avio_r8(s->pb); |
97 | 96 |
avio_skip(s->pb, 4); // size of file |
98 |
- size = avio_rb16(s->pb); |
|
97 |
+ size = read16(s); |
|
99 | 98 |
if (size < 14) |
100 | 99 |
return AVERROR_INVALIDDATA; |
101 | 100 |
|
... | ... |
@@ -107,30 +126,31 @@ static int read_header(AVFormatContext *s) |
107 | 107 |
uint32_t info_offset = 0, info_size; |
108 | 108 |
uint16_t section_count, header_size, i; |
109 | 109 |
|
110 |
- header_size = avio_rb16(s->pb); // 6 |
|
110 |
+ header_size = read16(s); // 6 |
|
111 | 111 |
|
112 | 112 |
avio_skip(s->pb, 4); // Unknown constant 0x00030000 |
113 | 113 |
avio_skip(s->pb, 4); // size of file |
114 |
- section_count = avio_rb16(s->pb); |
|
114 |
+ section_count = read16(s); |
|
115 | 115 |
avio_skip(s->pb, 2); // padding |
116 | 116 |
for (i = 0; avio_tell(s->pb) < header_size |
117 | 117 |
&& !(data_offset && info_offset) |
118 | 118 |
&& i < section_count; i++) { |
119 |
- uint32_t flag = avio_rb32(s->pb); |
|
119 |
+ uint16_t flag = read16(s); |
|
120 |
+ avio_skip(s->pb, 2); |
|
120 | 121 |
switch (flag) { |
121 |
- case 0x40000000: |
|
122 |
- info_offset = avio_rb32(s->pb); |
|
123 |
- info_size = avio_rb32(s->pb); |
|
122 |
+ case 0x4000: |
|
123 |
+ info_offset = read32(s); |
|
124 |
+ info_size = read32(s); |
|
124 | 125 |
break; |
125 |
- case 0x40010000: |
|
126 |
+ case 0x4001: |
|
126 | 127 |
avio_skip(s->pb, 4); // seek offset |
127 | 128 |
avio_skip(s->pb, 4); // seek size |
128 | 129 |
break; |
129 |
- case 0x40020000: |
|
130 |
- data_offset = avio_rb32(s->pb); |
|
131 |
- avio_skip(s->pb, 4); //data_size = avio_rb32(s->pb); |
|
130 |
+ case 0x4002: |
|
131 |
+ data_offset = read32(s); |
|
132 |
+ avio_skip(s->pb, 4); //data_size = read32(s); |
|
132 | 133 |
break; |
133 |
- case 0x40030000: |
|
134 |
+ case 0x4003: |
|
134 | 135 |
avio_skip(s->pb, 4); // REGN offset |
135 | 136 |
avio_skip(s->pb, 4); // REGN size |
136 | 137 |
break; |
... | ... |
@@ -148,15 +168,15 @@ static int read_header(AVFormatContext *s) |
148 | 148 |
return AVERROR_INVALIDDATA; |
149 | 149 |
} |
150 | 150 |
|
151 |
- size = avio_rb32(s->pb); |
|
151 |
+ size = read32(s); |
|
152 | 152 |
if (size < 192) |
153 | 153 |
return AVERROR_INVALIDDATA; |
154 | 154 |
avio_skip(s->pb, 4); // unknown |
155 |
- h1offset = avio_rb32(s->pb); |
|
155 |
+ h1offset = read32(s); |
|
156 | 156 |
if (h1offset > size) |
157 | 157 |
return AVERROR_INVALIDDATA; |
158 | 158 |
avio_skip(s->pb, 12); |
159 |
- toffset = avio_rb32(s->pb) + 16LL; |
|
159 |
+ toffset = read32(s) + 16LL; |
|
160 | 160 |
if (toffset > size) |
161 | 161 |
return AVERROR_INVALIDDATA; |
162 | 162 |
|
... | ... |
@@ -166,7 +186,9 @@ static int read_header(AVFormatContext *s) |
166 | 166 |
switch (codec) { |
167 | 167 |
case 0: codec = AV_CODEC_ID_PCM_S8_PLANAR; break; |
168 | 168 |
case 1: codec = AV_CODEC_ID_PCM_S16BE_PLANAR; break; |
169 |
- case 2: codec = AV_CODEC_ID_ADPCM_THP; break; |
|
169 |
+ case 2: codec = b->little_endian ? |
|
170 |
+ AV_CODEC_ID_ADPCM_THP_LE : |
|
171 |
+ AV_CODEC_ID_ADPCM_THP; break; |
|
170 | 172 |
default: |
171 | 173 |
avpriv_request_sample(s, "codec %d", codec); |
172 | 174 |
return AVERROR_PATCHWELCOME; |
... | ... |
@@ -179,10 +201,8 @@ static int read_header(AVFormatContext *s) |
179 | 179 |
return AVERROR_INVALIDDATA; |
180 | 180 |
|
181 | 181 |
avio_skip(s->pb, 1); // padding |
182 |
- if (b->bfstm) |
|
183 |
- avio_skip(s->pb, 2); // padding |
|
184 | 182 |
|
185 |
- st->codec->sample_rate = avio_rb16(s->pb); |
|
183 |
+ st->codec->sample_rate = b->bfstm ? read32(s) : read16(s); |
|
186 | 184 |
if (!st->codec->sample_rate) |
187 | 185 |
return AVERROR_INVALIDDATA; |
188 | 186 |
|
... | ... |
@@ -190,25 +210,25 @@ static int read_header(AVFormatContext *s) |
190 | 190 |
avio_skip(s->pb, 2); // padding |
191 | 191 |
avio_skip(s->pb, 4); // loop start sample |
192 | 192 |
st->start_time = 0; |
193 |
- st->duration = avio_rb32(s->pb); |
|
193 |
+ st->duration = read32(s); |
|
194 | 194 |
avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); |
195 | 195 |
|
196 | 196 |
if (!b->bfstm) |
197 |
- start = avio_rb32(s->pb); |
|
197 |
+ start = read32(s); |
|
198 | 198 |
b->current_block = 0; |
199 |
- b->block_count = avio_rb32(s->pb); |
|
199 |
+ b->block_count = read32(s); |
|
200 | 200 |
if (b->block_count > UINT16_MAX) { |
201 | 201 |
av_log(s, AV_LOG_WARNING, "too many blocks: %u\n", b->block_count); |
202 | 202 |
return AVERROR_INVALIDDATA; |
203 | 203 |
} |
204 | 204 |
|
205 |
- b->block_size = avio_rb32(s->pb); |
|
205 |
+ b->block_size = read32(s); |
|
206 | 206 |
if (b->block_size > UINT16_MAX / st->codec->channels) |
207 | 207 |
return AVERROR_INVALIDDATA; |
208 | 208 |
b->block_size *= st->codec->channels; |
209 | 209 |
|
210 |
- b->samples_per_block = avio_rb32(s->pb); |
|
211 |
- b->last_block_used_bytes = avio_rb32(s->pb); |
|
210 |
+ b->samples_per_block = read32(s); |
|
211 |
+ b->last_block_used_bytes = read32(s); |
|
212 | 212 |
if (b->last_block_used_bytes > UINT16_MAX / st->codec->channels) |
213 | 213 |
return AVERROR_INVALIDDATA; |
214 | 214 |
b->last_block_used_bytes *= st->codec->channels; |
... | ... |
@@ -216,14 +236,14 @@ static int read_header(AVFormatContext *s) |
216 | 216 |
avio_skip(s->pb, 4); // last block samples |
217 | 217 |
avio_skip(s->pb, 4); // last block size |
218 | 218 |
|
219 |
- if (codec == AV_CODEC_ID_ADPCM_THP) { |
|
219 |
+ if (codec == AV_CODEC_ID_ADPCM_THP || codec == AV_CODEC_ID_ADPCM_THP_LE) { |
|
220 | 220 |
int ch; |
221 | 221 |
|
222 | 222 |
avio_skip(s->pb, pos + toffset - avio_tell(s->pb)); |
223 | 223 |
if (!b->bfstm) |
224 |
- toffset = avio_rb32(s->pb) + 16LL; |
|
224 |
+ toffset = read32(s) + 16LL; |
|
225 | 225 |
else |
226 |
- toffset = toffset + avio_rb32(s->pb) + st->codec->channels * 8 - 8; |
|
226 |
+ toffset = toffset + read32(s) + st->codec->channels * 8 - 8; |
|
227 | 227 |
if (toffset > size) |
228 | 228 |
return AVERROR_INVALIDDATA; |
229 | 229 |
|
... | ... |
@@ -261,7 +281,7 @@ static int read_header(AVFormatContext *s) |
261 | 261 |
|
262 | 262 |
while (!avio_feof(s->pb)) { |
263 | 263 |
chunk = avio_rl32(s->pb); |
264 |
- size = avio_rb32(s->pb); |
|
264 |
+ size = read32(s); |
|
265 | 265 |
if (size < 8) { |
266 | 266 |
ret = AVERROR_INVALIDDATA; |
267 | 267 |
goto fail; |
... | ... |
@@ -269,7 +289,8 @@ static int read_header(AVFormatContext *s) |
269 | 269 |
size -= 8; |
270 | 270 |
switch (chunk) { |
271 | 271 |
case MKTAG('A','D','P','C'): |
272 |
- if (codec != AV_CODEC_ID_ADPCM_THP) |
|
272 |
+ if (codec != AV_CODEC_ID_ADPCM_THP && |
|
273 |
+ codec != AV_CODEC_ID_ADPCM_THP_LE) |
|
273 | 274 |
goto skip; |
274 | 275 |
|
275 | 276 |
asize = b->block_count * st->codec->channels * 4; |
... | ... |
@@ -292,7 +313,9 @@ static int read_header(AVFormatContext *s) |
292 | 292 |
break; |
293 | 293 |
case MKTAG('D','A','T','A'): |
294 | 294 |
if ((start < avio_tell(s->pb)) || |
295 |
- (!b->adpc && codec == AV_CODEC_ID_ADPCM_THP && !b->bfstm)) { |
|
295 |
+ (!b->adpc && (codec == AV_CODEC_ID_ADPCM_THP || |
|
296 |
+ codec == AV_CODEC_ID_ADPCM_THP_LE) |
|
297 |
+ && !b->bfstm)) { |
|
296 | 298 |
ret = AVERROR_INVALIDDATA; |
297 | 299 |
goto fail; |
298 | 300 |
} |
... | ... |
@@ -335,7 +358,8 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt) |
335 | 335 |
return AVERROR_EOF; |
336 | 336 |
} |
337 | 337 |
|
338 |
- if (codec->codec_id == AV_CODEC_ID_ADPCM_THP && !codec->extradata) { |
|
338 |
+ if ((codec->codec_id == AV_CODEC_ID_ADPCM_THP || |
|
339 |
+ codec->codec_id == AV_CODEC_ID_ADPCM_THP_LE) && !codec->extradata) { |
|
339 | 340 |
uint8_t *dst; |
340 | 341 |
|
341 | 342 |
if (av_new_packet(pkt, 8 + (32 + 4) * codec->channels + size) < 0) |
... | ... |
@@ -382,5 +406,5 @@ AVInputFormat ff_bfstm_demuxer = { |
382 | 382 |
.read_header = read_header, |
383 | 383 |
.read_packet = read_packet, |
384 | 384 |
.read_close = read_close, |
385 |
- .extensions = "bfstm", |
|
385 |
+ .extensions = "bfstm,bcstm", |
|
386 | 386 |
}; |