FFmpeg
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
Examples
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
libavformat
brstm.c
Go to the documentation of this file.
1
/*
2
* BRSTM demuxer
3
* Copyright (c) 2012 Paul B Mahol
4
*
5
* This file is part of FFmpeg.
6
*
7
* FFmpeg is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU Lesser General Public
9
* License as published by the Free Software Foundation; either
10
* version 2.1 of the License, or (at your option) any later version.
11
*
12
* FFmpeg is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* Lesser General Public License for more details.
16
*
17
* You should have received a copy of the GNU Lesser General Public
18
* License along with FFmpeg; if not, write to the Free Software
19
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
*/
21
22
#include "
libavutil/intreadwrite.h
"
23
#include "
libavcodec/bytestream.h
"
24
#include "
avformat.h
"
25
#include "
internal.h
"
26
27
typedef
struct
BRSTMDemuxContext
{
28
uint32_t
block_size
;
29
uint32_t
block_count
;
30
uint32_t
current_block
;
31
uint32_t
samples_per_block
;
32
uint32_t
last_block_used_bytes
;
33
uint8_t
*
table
;
34
uint8_t
*
adpc
;
35
}
BRSTMDemuxContext
;
36
37
static
int
probe
(
AVProbeData
*p)
38
{
39
if
(
AV_RL32
(p->
buf
) ==
MKTAG
(
'R'
,
'S'
,
'T'
,
'M'
) &&
40
(
AV_RL16
(p->
buf
+ 4) == 0xFFFE ||
41
AV_RL16
(p->
buf
+ 4) == 0xFEFF))
42
return
AVPROBE_SCORE_MAX
/ 3 * 2;
43
return
0;
44
}
45
46
static
int
read_close
(
AVFormatContext
*
s
)
47
{
48
BRSTMDemuxContext
*
b
= s->
priv_data
;
49
50
av_freep
(&b->
table
);
51
av_freep
(&b->
adpc
);
52
53
return
0;
54
}
55
56
static
int
read_header
(
AVFormatContext
*
s
)
57
{
58
BRSTMDemuxContext
*
b
= s->
priv_data
;
59
int
bom, major, minor, codec, chunk;
60
int64_t pos, h1offset, toffset;
61
uint32_t
size
,
start
, asize;
62
AVStream
*st;
63
int
ret
=
AVERROR_EOF
;
64
65
st =
avformat_new_stream
(s, NULL);
66
if
(!st)
67
return
AVERROR
(ENOMEM);
68
st->
codec
->
codec_type
=
AVMEDIA_TYPE_AUDIO
;
69
70
avio_skip
(s->
pb
, 4);
71
72
bom =
avio_rb16
(s->
pb
);
73
if
(bom != 0xFEFF && bom != 0xFFFE) {
74
av_log
(s,
AV_LOG_ERROR
,
"invalid byte order: %X\n"
, bom);
75
return
AVERROR_INVALIDDATA
;
76
}
77
if
(bom == 0xFFFE) {
78
avpriv_request_sample
(s,
"little endian byte order"
);
79
return
AVERROR_PATCHWELCOME
;
80
}
81
82
major =
avio_r8
(s->
pb
);
83
minor =
avio_r8
(s->
pb
);
84
avio_skip
(s->
pb
, 4);
// size of file
85
size =
avio_rb16
(s->
pb
);
86
if
(size < 14)
87
return
AVERROR_INVALIDDATA
;
88
89
avio_skip
(s->
pb
, size - 14);
90
pos =
avio_tell
(s->
pb
);
91
if
(
avio_rl32
(s->
pb
) !=
MKTAG
(
'H'
,
'E'
,
'A'
,
'D'
))
92
return
AVERROR_INVALIDDATA
;
93
size =
avio_rb32
(s->
pb
);
94
if
(size < 256)
95
return
AVERROR_INVALIDDATA
;
96
avio_skip
(s->
pb
, 4);
// unknown
97
h1offset =
avio_rb32
(s->
pb
);
98
if
(h1offset > size)
99
return
AVERROR_INVALIDDATA
;
100
avio_skip
(s->
pb
, 12);
101
toffset =
avio_rb32
(s->
pb
) + 16LL;
102
if
(toffset > size)
103
return
AVERROR_INVALIDDATA
;
104
105
avio_skip
(s->
pb
, pos + h1offset + 8 -
avio_tell
(s->
pb
));
106
codec =
avio_r8
(s->
pb
);
107
108
switch
(codec) {
109
case
0: codec =
AV_CODEC_ID_PCM_S8_PLANAR
;
break
;
110
case
1: codec =
AV_CODEC_ID_PCM_S16BE_PLANAR
;
break
;
111
case
2: codec =
AV_CODEC_ID_ADPCM_THP
;
break
;
112
default
:
113
avpriv_request_sample
(s,
"codec %d"
, codec);
114
return
AVERROR_PATCHWELCOME
;
115
}
116
117
avio_skip
(s->
pb
, 1);
// loop flag
118
st->
codec
->
codec_id
= codec;
119
st->
codec
->
channels
=
avio_r8
(s->
pb
);
120
if
(!st->
codec
->
channels
)
121
return
AVERROR_INVALIDDATA
;
122
123
avio_skip
(s->
pb
, 1);
// padding
124
st->
codec
->
sample_rate
=
avio_rb16
(s->
pb
);
125
if
(!st->
codec
->
sample_rate
)
126
return
AVERROR_INVALIDDATA
;
127
128
avio_skip
(s->
pb
, 2);
// padding
129
avio_skip
(s->
pb
, 4);
// loop start sample
130
st->
start_time
= 0;
131
st->
duration
=
avio_rb32
(s->
pb
);
132
avpriv_set_pts_info
(st, 64, 1, st->
codec
->
sample_rate
);
133
134
start =
avio_rb32
(s->
pb
);
135
b->
current_block
= 0;
136
b->
block_count
=
avio_rb32
(s->
pb
);
137
if
(b->
block_count
> UINT16_MAX) {
138
av_log
(s,
AV_LOG_WARNING
,
"too many blocks: %u\n"
, b->
block_count
);
139
return
AVERROR_INVALIDDATA
;
140
}
141
142
b->
block_size
=
avio_rb32
(s->
pb
);
143
if
(b->
block_size
> UINT16_MAX / st->
codec
->
channels
)
144
return
AVERROR_INVALIDDATA
;
145
b->
block_size
*= st->
codec
->
channels
;
146
147
b->
samples_per_block
=
avio_rb32
(s->
pb
);
148
b->
last_block_used_bytes
=
avio_rb32
(s->
pb
);
149
if
(b->
last_block_used_bytes
> UINT16_MAX / st->
codec
->
channels
)
150
return
AVERROR_INVALIDDATA
;
151
b->
last_block_used_bytes
*= st->
codec
->
channels
;
152
153
avio_skip
(s->
pb
, 4);
// last block samples
154
avio_skip
(s->
pb
, 4);
// last block size
155
156
if
(codec ==
AV_CODEC_ID_ADPCM_THP
) {
157
int
ch;
158
159
avio_skip
(s->
pb
, pos + toffset -
avio_tell
(s->
pb
));
160
toffset =
avio_rb32
(s->
pb
) + 16LL;
161
if
(toffset > size)
162
return
AVERROR_INVALIDDATA
;
163
164
avio_skip
(s->
pb
, pos + toffset -
avio_tell
(s->
pb
));
165
b->
table
=
av_mallocz
(32 * st->
codec
->
channels
);
166
if
(!b->
table
)
167
return
AVERROR
(ENOMEM);
168
169
for
(ch = 0; ch < st->
codec
->
channels
; ch++) {
170
if
(
avio_read
(s->
pb
, b->
table
+ ch * 32, 32) != 32) {
171
ret =
AVERROR_INVALIDDATA
;
172
goto
fail;
173
}
174
avio_skip
(s->
pb
, 24);
175
}
176
}
177
178
if
(size < (
avio_tell
(s->
pb
) - pos)) {
179
ret =
AVERROR_INVALIDDATA
;
180
goto
fail;
181
}
182
avio_skip
(s->
pb
, size - (
avio_tell
(s->
pb
) - pos));
183
184
while
(!
url_feof
(s->
pb
)) {
185
chunk =
avio_rl32
(s->
pb
);
186
size =
avio_rb32
(s->
pb
);
187
if
(size < 8) {
188
ret =
AVERROR_INVALIDDATA
;
189
goto
fail;
190
}
191
size -= 8;
192
switch
(chunk) {
193
case
MKTAG
(
'A'
,
'D'
,
'P'
,
'C'
):
194
if
(codec !=
AV_CODEC_ID_ADPCM_THP
)
195
goto
skip;
196
197
asize = b->
block_count
* st->
codec
->
channels
* 4;
198
if
(size < asize) {
199
ret =
AVERROR_INVALIDDATA
;
200
goto
fail;
201
}
202
if
(b->
adpc
) {
203
av_log
(s,
AV_LOG_WARNING
,
"skipping additonal ADPC chunk\n"
);
204
goto
skip;
205
}
else
{
206
b->
adpc
=
av_mallocz
(asize);
207
if
(!b->
adpc
) {
208
ret =
AVERROR
(ENOMEM);
209
goto
fail;
210
}
211
avio_read
(s->
pb
, b->
adpc
, asize);
212
avio_skip
(s->
pb
, size - asize);
213
}
214
break
;
215
case
MKTAG
(
'D'
,
'A'
,
'T'
,
'A'
):
216
if
((start <
avio_tell
(s->
pb
)) ||
217
(!b->
adpc
&& codec ==
AV_CODEC_ID_ADPCM_THP
)) {
218
ret =
AVERROR_INVALIDDATA
;
219
goto
fail;
220
}
221
avio_skip
(s->
pb
, start -
avio_tell
(s->
pb
));
222
223
if
(major != 1 || minor)
224
avpriv_request_sample
(s,
"Version %d.%d"
, major, minor);
225
226
return
0;
227
default
:
228
av_log
(s,
AV_LOG_WARNING
,
"skipping unknown chunk: %X\n"
, chunk);
229
skip:
230
avio_skip
(s->
pb
, size);
231
}
232
}
233
234
fail:
235
read_close
(s);
236
237
return
ret
;
238
}
239
240
static
int
read_packet
(
AVFormatContext
*
s
,
AVPacket
*
pkt
)
241
{
242
AVCodecContext
*codec = s->
streams
[0]->
codec
;
243
BRSTMDemuxContext
*
b
= s->
priv_data
;
244
uint32_t samples,
size
;
245
int
ret
;
246
247
if
(
url_feof
(s->
pb
))
248
return
AVERROR_EOF
;
249
b->
current_block
++;
250
if
(b->
current_block
== b->
block_count
) {
251
size = b->
last_block_used_bytes
;
252
samples = size / (8 * codec->
channels
) * 14;
253
}
else
if
(b->
current_block
< b->
block_count
) {
254
size = b->
block_size
;
255
samples = b->
samples_per_block
;
256
}
else
{
257
return
AVERROR_EOF
;
258
}
259
260
if
(codec->
codec_id
==
AV_CODEC_ID_ADPCM_THP
) {
261
uint8_t
*dst;
262
263
if
(
av_new_packet
(pkt, 8 + (32 + 4) * codec->
channels
+ size) < 0)
264
return
AVERROR
(ENOMEM);
265
dst = pkt->
data
;
266
bytestream_put_be32(&dst, size);
267
bytestream_put_be32(&dst, samples);
268
bytestream_put_buffer
(&dst, b->
table
, 32 * codec->
channels
);
269
bytestream_put_buffer
(&dst, b->
adpc
+ 4 * codec->
channels
*
270
(b->
current_block
- 1), 4 * codec->
channels
);
271
272
ret =
avio_read
(s->
pb
, dst, size);
273
if
(ret != size)
274
av_free_packet
(pkt);
275
pkt->
duration
= samples;
276
}
else
{
277
ret =
av_get_packet
(s->
pb
, pkt, size);
278
}
279
280
pkt->
stream_index
= 0;
281
282
if
(ret != size)
283
ret =
AVERROR
(EIO);
284
285
return
ret
;
286
}
287
288
AVInputFormat
ff_brstm_demuxer
= {
289
.
name
=
"brstm"
,
290
.long_name =
NULL_IF_CONFIG_SMALL
(
"BRSTM (Binary Revolution Stream)"
),
291
.priv_data_size =
sizeof
(
BRSTMDemuxContext
),
292
.
read_probe
=
probe
,
293
.
read_header
=
read_header
,
294
.
read_packet
=
read_packet
,
295
.
read_close
=
read_close
,
296
.extensions =
"brstm"
,
297
};
Generated on Sat Jan 25 2014 19:52:02 for FFmpeg by
1.8.2