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;
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 
47 {
49 
50  av_freep(&b->table);
51  av_freep(&b->adpc);
52 
53  return 0;
54 }
55 
57 {
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);
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);
149  if (b->last_block_used_bytes > UINT16_MAX / st->codec->channels)
150  return AVERROR_INVALIDDATA;
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 
241 {
242  AVCodecContext *codec = s->streams[0]->codec;
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 
289  .name = "brstm",
290  .long_name = NULL_IF_CONFIG_SMALL("BRSTM (Binary Revolution Stream)"),
291  .priv_data_size = sizeof(BRSTMDemuxContext),
292  .read_probe = probe,
296  .extensions = "brstm",
297 };
void * av_mallocz(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:205
const char * s
Definition: avisynth_c.h:668
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
void av_free_packet(AVPacket *pkt)
Free a packet.
Definition: avpacket.c:242
uint32_t block_count
Definition: brstm.c:29
void avpriv_set_pts_info(AVStream *s, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the time base and wrapping info for a given stream.
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:154
#define AV_RL16
int64_t avio_skip(AVIOContext *s, int64_t offset)
Skip given number of bytes forward.
Definition: aviobuf.c:256
unsigned int avio_rb16(AVIOContext *s)
Definition: aviobuf.c:595
void av_freep(void *arg)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc() and set the pointer ...
Definition: mem.c:198
Format I/O context.
Definition: avformat.h:944
void void avpriv_request_sample(void *avc, const char *msg,...) av_printf_format(2
Log a generic warning message about a missing feature.
uint8_t
unsigned int avio_rb32(AVIOContext *s)
Definition: aviobuf.c:610
static AVPacket pkt
Definition: demuxing.c:56
#define b
Definition: input.c:42
uint32_t block_size
Definition: brstm.c:28
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
static int probe(AVProbeData *p)
Definition: brstm.c:37
AVStream ** streams
Definition: avformat.h:992
uint8_t * data
uint32_t samples_per_block
Definition: brstm.c:31
#define AVERROR_EOF
End of file.
Definition: error.h:55
int av_get_packet(AVIOContext *s, AVPacket *pkt, int size)
Allocate and read the payload of a packet and initialize its fields with default values.
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:248
struct BRSTMDemuxContext BRSTMDemuxContext
int duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition: aviobuf.c:478
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
Definition: avpacket.c:73
uint32_t last_block_used_bytes
Definition: brstm.c:32
unsigned int avio_rl32(AVIOContext *s)
Definition: aviobuf.c:579
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
int size
int avio_r8(AVIOContext *s)
Definition: aviobuf.c:469
AVCodecContext * codec
Codec context associated with this stream.
Definition: avformat.h:662
unsigned char * buf
Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero.
Definition: avformat.h:336
uint32_t current_block
Definition: brstm.c:30
static int read_probe(AVProbeData *pd)
ret
Definition: avfilter.c:821
#define AV_RL32
int url_feof(AVIOContext *s)
feof() equivalent for AVIOContext.
Definition: aviobuf.c:280
uint8_t * table
Definition: brstm.c:33
Stream structure.
Definition: avformat.h:643
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:62
uint8_t * adpc
Definition: brstm.c:34
NULL
Definition: eval.c:55
enum AVMediaType codec_type
enum AVCodecID codec_id
int sample_rate
samples per second
AVIOContext * pb
I/O context.
Definition: avformat.h:977
main external API structure.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
This structure contains the data a format has to probe a file.
Definition: avformat.h:334
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Buffer references ownership and permissions
AVInputFormat ff_brstm_demuxer
Definition: brstm.c:288
int64_t duration
Decoding: duration of the stream, in stream time base.
Definition: avformat.h:696
#define AVPROBE_SCORE_MAX
maximum score, half of that is used for file-extension-based detection
Definition: avformat.h:340
Main libavformat public API header.
int64_t start_time
Decoding: pts of the first frame of the stream in presentation order, in stream time base...
Definition: avformat.h:689
static int read_header(AVFormatContext *s)
Definition: brstm.c:56
static av_always_inline void bytestream_put_buffer(uint8_t **b, const uint8_t *src, unsigned int size)
Definition: bytestream.h:337
int channels
number of audio channels
else dst[i][x+y *dst_stride[i]]
Definition: vf_mcdeint.c:160
void * priv_data
Format private data.
Definition: avformat.h:964
static int read_packet(AVFormatContext *s, AVPacket *pkt)
Definition: brstm.c:240
Filter the word “frame” indicates either a video frame or a group of audio samples
void INT64 start
Definition: avisynth_c.h:594
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:461
static int read_close(AVFormatContext *s)
Definition: brstm.c:46
#define MKTAG(a, b, c, d)
Definition: common.h:282
This structure stores compressed data.