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 Sun Mar 23 2014 23:50:10 for FFmpeg by
1.8.2