3 * Copyright (c) 2012 Paul B Mahol
5 * This file is part of FFmpeg.
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.
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.
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
22 #include "libavutil/intreadwrite.h"
23 #include "libavcodec/bytestream.h"
27 typedef struct BRSTMDemuxContext
{
30 uint32_t current_block
;
31 uint32_t samples_per_block
;
32 uint32_t last_block_used_bytes
;
37 static int probe(AVProbeData
*p
)
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;
46 static int read_close(AVFormatContext
*s
)
48 BRSTMDemuxContext
*b
= s
->priv_data
;
56 static int read_header(AVFormatContext
*s
)
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
;
63 int ret
= AVERROR_EOF
;
65 st
= avformat_new_stream(s
, NULL
);
67 return AVERROR(ENOMEM
);
68 st
->codec
->codec_type
= AVMEDIA_TYPE_AUDIO
;
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
;
78 avpriv_request_sample(s
, "little endian byte order");
79 return AVERROR_PATCHWELCOME
;
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
);
87 return AVERROR_INVALIDDATA
;
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
);
95 return AVERROR_INVALIDDATA
;
96 avio_skip(s
->pb
, 4); // unknown
97 h1offset
= avio_rb32(s
->pb
);
99 return AVERROR_INVALIDDATA
;
100 avio_skip(s
->pb
, 12);
101 toffset
= avio_rb32(s
->pb
) + 16LL;
103 return AVERROR_INVALIDDATA
;
105 avio_skip(s
->pb
, pos
+ h1offset
+ 8 - avio_tell(s
->pb
));
106 codec
= avio_r8(s
->pb
);
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;
113 avpriv_request_sample(s
, "codec %d", codec
);
114 return AVERROR_PATCHWELCOME
;
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
;
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
;
128 avio_skip(s
->pb
, 2); // padding
129 avio_skip(s
->pb
, 4); // loop start sample
131 st
->duration
= avio_rb32(s
->pb
);
132 avpriv_set_pts_info(st
, 64, 1, st
->codec
->sample_rate
);
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
;
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
;
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
;
153 avio_skip(s
->pb
, 4); // last block samples
154 avio_skip(s
->pb
, 4); // last block size
156 if (codec
== AV_CODEC_ID_ADPCM_THP
) {
159 avio_skip(s
->pb
, pos
+ toffset
- avio_tell(s
->pb
));
160 toffset
= avio_rb32(s
->pb
) + 16LL;
162 return AVERROR_INVALIDDATA
;
164 avio_skip(s
->pb
, pos
+ toffset
- avio_tell(s
->pb
));
165 b
->table
= av_mallocz(32 * st
->codec
->channels
);
167 return AVERROR(ENOMEM
);
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
;
174 avio_skip(s
->pb
, 24);
178 if (size
< (avio_tell(s
->pb
) - pos
)) {
179 ret
= AVERROR_INVALIDDATA
;
182 avio_skip(s
->pb
, size
- (avio_tell(s
->pb
) - pos
));
184 while (!avio_feof(s
->pb
)) {
185 chunk
= avio_rl32(s
->pb
);
186 size
= avio_rb32(s
->pb
);
188 ret
= AVERROR_INVALIDDATA
;
193 case MKTAG('A','D','P','C'):
194 if (codec
!= AV_CODEC_ID_ADPCM_THP
)
197 asize
= b
->block_count
* st
->codec
->channels
* 4;
199 ret
= AVERROR_INVALIDDATA
;
203 av_log(s
, AV_LOG_WARNING
, "skipping additional ADPC chunk\n");
206 b
->adpc
= av_mallocz(asize
);
208 ret
= AVERROR(ENOMEM
);
211 avio_read(s
->pb
, b
->adpc
, asize
);
212 avio_skip(s
->pb
, size
- asize
);
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
;
221 avio_skip(s
->pb
, start
- avio_tell(s
->pb
));
223 if (major
!= 1 || minor
)
224 avpriv_request_sample(s
, "Version %d.%d", major
, minor
);
228 av_log(s
, AV_LOG_WARNING
, "skipping unknown chunk: %X\n", chunk
);
230 avio_skip(s
->pb
, size
);
240 static int read_packet(AVFormatContext
*s
, AVPacket
*pkt
)
242 AVCodecContext
*codec
= s
->streams
[0]->codec
;
243 BRSTMDemuxContext
*b
= s
->priv_data
;
244 uint32_t samples
, size
;
247 if (avio_feof(s
->pb
))
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
;
260 if (codec
->codec_id
== AV_CODEC_ID_ADPCM_THP
) {
263 if (av_new_packet(pkt
, 8 + (32 + 4) * codec
->channels
+ size
) < 0)
264 return AVERROR(ENOMEM
);
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
);
272 ret
= avio_read(s
->pb
, dst
, size
);
275 pkt
->duration
= samples
;
277 ret
= av_get_packet(s
->pb
, pkt
, size
);
280 pkt
->stream_index
= 0;
288 AVInputFormat ff_brstm_demuxer
= {
290 .long_name
= NULL_IF_CONFIG_SMALL("BRSTM (Binary Revolution Stream)"),
291 .priv_data_size
= sizeof(BRSTMDemuxContext
),
293 .read_header
= read_header
,
294 .read_packet
= read_packet
,
295 .read_close
= read_close
,
296 .extensions
= "brstm",