FFmpeg  4.3.6
pp_bnk.c
Go to the documentation of this file.
1 /*
2  * Pro Pinball Series Soundbank (44c, 22c, 11c, 5c) demuxer.
3  *
4  * Copyright (C) 2020 Zane van Iperen (zane@zanevaniperen.com)
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 #include "avformat.h"
23 #include "internal.h"
24 #include "libavutil/intreadwrite.h"
25 #include "libavutil/avassert.h"
26 #include "libavutil/internal.h"
27 
28 #define PP_BNK_MAX_READ_SIZE 4096
29 #define PP_BNK_FILE_HEADER_SIZE 20
30 #define PP_BNK_TRACK_SIZE 20
31 
32 typedef struct PPBnkHeader {
33  uint32_t bank_id; /*< Bank ID, useless for our purposes. */
34  uint32_t sample_rate; /*< Sample rate of the contained tracks. */
35  uint32_t always1; /*< Unknown, always seems to be 1. */
36  uint32_t track_count; /*< Number of tracks in the file. */
37  uint32_t flags; /*< Flags. */
38 } PPBnkHeader;
39 
40 typedef struct PPBnkTrack {
41  uint32_t id; /*< Track ID. Usually track[i].id == track[i-1].id + 1, but not always */
42  uint32_t size; /*< Size of the data in bytes. */
43  uint32_t sample_rate; /*< Sample rate. */
44  uint32_t always1_1; /*< Unknown, always seems to be 1. */
45  uint32_t always1_2; /*< Unknown, always seems to be 1. */
46 } PPBnkTrack;
47 
48 typedef struct PPBnkCtxTrack {
49  int64_t data_offset;
50  uint32_t data_size;
51  uint32_t bytes_read;
53 
54 typedef struct PPBnkCtx {
57  uint32_t current_track;
58 } PPBnkCtx;
59 
60 enum {
61  PP_BNK_FLAG_PERSIST = (1 << 0), /*< This is a large file, keep in memory. */
62  PP_BNK_FLAG_MUSIC = (1 << 1), /*< This is music. */
64 };
65 
66 static void pp_bnk_parse_header(PPBnkHeader *hdr, const uint8_t *buf)
67 {
68  hdr->bank_id = AV_RL32(buf + 0);
69  hdr->sample_rate = AV_RL32(buf + 4);
70  hdr->always1 = AV_RL32(buf + 8);
71  hdr->track_count = AV_RL32(buf + 12);
72  hdr->flags = AV_RL32(buf + 16);
73 }
74 
75 static void pp_bnk_parse_track(PPBnkTrack *trk, const uint8_t *buf)
76 {
77  trk->id = AV_RL32(buf + 0);
78  trk->size = AV_RL32(buf + 4);
79  trk->sample_rate = AV_RL32(buf + 8);
80  trk->always1_1 = AV_RL32(buf + 12);
81  trk->always1_2 = AV_RL32(buf + 16);
82 }
83 
84 static int pp_bnk_probe(const AVProbeData *p)
85 {
86  uint32_t sample_rate = AV_RL32(p->buf + 4);
87  uint32_t track_count = AV_RL32(p->buf + 12);
88  uint32_t flags = AV_RL32(p->buf + 16);
89 
90  if (track_count == 0 || track_count > INT_MAX)
91  return 0;
92 
93  if ((sample_rate != 5512) && (sample_rate != 11025) &&
94  (sample_rate != 22050) && (sample_rate != 44100))
95  return 0;
96 
97  /* Check the first track header. */
98  if (AV_RL32(p->buf + 28) != sample_rate)
99  return 0;
100 
101  if ((flags & ~PP_BNK_FLAG_MASK) != 0)
102  return 0;
103 
104  return AVPROBE_SCORE_MAX / 4 + 1;
105 }
106 
108 {
109  int64_t ret;
110  AVStream *st;
111  AVCodecParameters *par;
112  PPBnkCtx *ctx = s->priv_data;
114  PPBnkHeader hdr;
115 
116  if ((ret = avio_read(s->pb, buf, PP_BNK_FILE_HEADER_SIZE)) < 0)
117  return ret;
118  else if (ret != PP_BNK_FILE_HEADER_SIZE)
119  return AVERROR(EIO);
120 
121  pp_bnk_parse_header(&hdr, buf);
122 
123  if (hdr.track_count == 0 || hdr.track_count > INT_MAX)
124  return AVERROR_INVALIDDATA;
125 
126  if (hdr.sample_rate == 0 || hdr.sample_rate > INT_MAX)
127  return AVERROR_INVALIDDATA;
128 
129  if (hdr.always1 != 1) {
130  avpriv_request_sample(s, "Non-one header value");
131  return AVERROR_PATCHWELCOME;
132  }
133 
134  ctx->track_count = hdr.track_count;
135 
136  if (!(ctx->tracks = av_malloc_array(hdr.track_count, sizeof(PPBnkCtxTrack))))
137  return AVERROR(ENOMEM);
138 
139  /* Parse and validate each track. */
140  for (int i = 0; i < hdr.track_count; i++) {
141  PPBnkTrack e;
142  PPBnkCtxTrack *trk = ctx->tracks + i;
143 
144  ret = avio_read(s->pb, buf, PP_BNK_TRACK_SIZE);
145  if (ret < 0 && ret != AVERROR_EOF)
146  goto fail;
147 
148  /* Short byte-count or EOF, we have a truncated file. */
149  if (ret != PP_BNK_TRACK_SIZE) {
150  av_log(s, AV_LOG_WARNING, "File truncated at %d/%u track(s)\n",
151  i, hdr.track_count);
152  ctx->track_count = i;
153  break;
154  }
155 
156  pp_bnk_parse_track(&e, buf);
157 
158  /* The individual sample rates of all tracks must match that of the file header. */
159  if (e.sample_rate != hdr.sample_rate) {
160  ret = AVERROR_INVALIDDATA;
161  goto fail;
162  }
163 
164  if (e.always1_1 != 1 || e.always1_2 != 1) {
165  avpriv_request_sample(s, "Non-one track header values");
166  ret = AVERROR_PATCHWELCOME;
167  goto fail;
168  }
169 
170  trk->data_offset = avio_tell(s->pb);
171  trk->data_size = e.size;
172  trk->bytes_read = 0;
173 
174  /*
175  * Skip over the data to the next stream header.
176  * Sometimes avio_skip() doesn't detect EOF. If it doesn't, either:
177  * - the avio_read() above will, or
178  * - pp_bnk_read_packet() will read a truncated last track.
179  */
180  if ((ret = avio_skip(s->pb, e.size)) == AVERROR_EOF) {
181  ctx->track_count = i + 1;
183  "Track %d has truncated data, assuming track count == %d\n",
184  i, ctx->track_count);
185  break;
186  } else if (ret < 0) {
187  goto fail;
188  }
189  }
190 
191  /* File is only a header. */
192  if (ctx->track_count == 0) {
193  ret = AVERROR_INVALIDDATA;
194  goto fail;
195  }
196 
197  /* Build the streams. */
198  for (int i = 0; i < ctx->track_count; i++) {
199  if (!(st = avformat_new_stream(s, NULL))) {
200  ret = AVERROR(ENOMEM);
201  goto fail;
202  }
203 
204  par = st->codecpar;
207  par->format = AV_SAMPLE_FMT_S16;
209  par->channels = 1;
210  par->sample_rate = hdr.sample_rate;
211  par->bits_per_coded_sample = 4;
212  par->bits_per_raw_sample = 16;
213  par->block_align = 1;
214  par->bit_rate = par->sample_rate * par->bits_per_coded_sample;
215 
216  avpriv_set_pts_info(st, 64, 1, par->sample_rate);
217  st->start_time = 0;
218  st->duration = ctx->tracks[i].data_size * 2;
219  }
220 
221  return 0;
222 
223 fail:
224  av_freep(&ctx->tracks);
225  return ret;
226 }
227 
229 {
230  PPBnkCtx *ctx = s->priv_data;
231 
232  /*
233  * Read a packet from each track, round-robin style.
234  * This method is nasty, but needed to avoid "Too many packets buffered" errors.
235  */
236  for (int i = 0; i < ctx->track_count; i++, ctx->current_track++)
237  {
238  int64_t ret;
239  int size;
240  PPBnkCtxTrack *trk;
241 
242  ctx->current_track %= ctx->track_count;
243 
244  trk = ctx->tracks + ctx->current_track;
245 
246  if (trk->bytes_read == trk->data_size)
247  continue;
248 
249  if ((ret = avio_seek(s->pb, trk->data_offset + trk->bytes_read, SEEK_SET)) < 0)
250  return ret;
251  else if (ret != trk->data_offset + trk->bytes_read)
252  return AVERROR(EIO);
253 
254  size = FFMIN(trk->data_size - trk->bytes_read, PP_BNK_MAX_READ_SIZE);
255 
256  if ((ret = av_get_packet(s->pb, pkt, size)) == AVERROR_EOF) {
257  /* If we've hit EOF, don't attempt this track again. */
258  trk->data_size = trk->bytes_read;
259  continue;
260  } else if (ret < 0) {
261  return ret;
262  }
263 
264  trk->bytes_read += ret;
265  pkt->flags &= ~AV_PKT_FLAG_CORRUPT;
266  pkt->stream_index = ctx->current_track++;
267  pkt->duration = ret * 2;
268  return 0;
269  }
270 
271  /* If we reach here, we're done. */
272  return AVERROR_EOF;
273 }
274 
276 {
277  PPBnkCtx *ctx = s->priv_data;
278 
279  av_freep(&ctx->tracks);
280 
281  return 0;
282 }
283 
285  .name = "pp_bnk",
286  .long_name = NULL_IF_CONFIG_SMALL("Pro Pinball Series Soundbank"),
287  .priv_data_size = sizeof(PPBnkCtx),
292 };
#define NULL
Definition: coverity.c:32
uint32_t flags
Definition: pp_bnk.c:37
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
int size
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
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.
Definition: utils.c:4948
#define avpriv_request_sample(...)
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: codec_par.h:60
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:241
int64_t avio_skip(AVIOContext *s, int64_t offset)
Skip given number of bytes forward.
Definition: aviobuf.c:329
uint32_t always1_2
Definition: pp_bnk.c:45
static AVPacket pkt
AVInputFormat ff_pp_bnk_demuxer
Definition: pp_bnk.c:284
This struct describes the properties of an encoded stream.
Definition: codec_par.h:52
Format I/O context.
Definition: avformat.h:1351
int track_count
Definition: pp_bnk.c:55
uint32_t always1
Definition: pp_bnk.c:35
uint32_t data_size
Definition: pp_bnk.c:50
uint8_t
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
Definition: packet.h:373
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
Definition: utils.c:4526
uint32_t id
Definition: pp_bnk.c:41
#define AVERROR_EOF
End of file.
Definition: error.h:55
static av_cold int read_close(AVFormatContext *ctx)
Definition: libcdio.c:145
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.
Definition: utils.c:307
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:557
uint32_t current_track
Definition: pp_bnk.c:57
uint64_t channel_layout
Audio only.
Definition: codec_par.h:162
#define av_log(a,...)
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition: aviobuf.c:625
int64_t bit_rate
The average bitrate of the encoded data (in bits per second).
Definition: codec_par.h:89
uint32_t always1_1
Definition: pp_bnk.c:44
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
uint32_t size
Definition: pp_bnk.c:42
#define AVERROR(e)
Definition: error.h:43
static int pp_bnk_probe(const AVProbeData *p)
Definition: pp_bnk.c:84
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:188
enum AVMediaType codec_type
General type of the encoded data.
Definition: codec_par.h:56
simple assert() macros that are a bit more flexible than ISO C assert().
static int pp_bnk_read_close(AVFormatContext *s)
Definition: pp_bnk.c:275
#define FFMAX(a, b)
Definition: common.h:94
#define fail()
Definition: checkasm.h:123
int flags
A combination of AV_PKT_FLAG values.
Definition: packet.h:361
#define PP_BNK_MAX_READ_SIZE
Definition: pp_bnk.c:28
unsigned char * buf
Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero.
Definition: avformat.h:443
common internal API header
static void pp_bnk_parse_track(PPBnkTrack *trk, const uint8_t *buf)
Definition: pp_bnk.c:75
int block_align
Audio only.
Definition: codec_par.h:177
#define FFMIN(a, b)
Definition: common.h:96
uint32_t bank_id
Definition: pp_bnk.c:33
#define PP_BNK_TRACK_SIZE
Definition: pp_bnk.c:30
AVFormatContext * ctx
Definition: movenc.c:48
uint32_t sample_rate
Definition: pp_bnk.c:43
#define s(width, name)
Definition: cbs_vp9.c:257
#define AV_RL32
Definition: intreadwrite.h:146
uint32_t sample_rate
Definition: pp_bnk.c:34
static int read_header(FFV1Context *f)
Definition: ffv1dec.c:545
Stream structure.
Definition: avformat.h:876
#define PP_BNK_FILE_HEADER_SIZE
Definition: pp_bnk.c:29
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:62
static int read_packet(void *opaque, uint8_t *buf, int buf_size)
Definition: avio_reading.c:42
static int pp_bnk_read_header(AVFormatContext *s)
Definition: pp_bnk.c:107
int64_t data_offset
Definition: pp_bnk.c:49
AVIOContext * pb
I/O context.
Definition: avformat.h:1393
static int pp_bnk_read_packet(AVFormatContext *s, AVPacket *pkt)
Definition: pp_bnk.c:228
uint32_t track_count
Definition: pp_bnk.c:36
This structure contains the data a format has to probe a file.
Definition: avformat.h:441
int bits_per_raw_sample
This is the number of valid bits in each output sample.
Definition: codec_par.h:115
static int read_probe(const AVProbeData *pd)
Definition: jvdec.c:55
int64_t duration
Decoding: duration of the stream, in stream time base.
Definition: avformat.h:925
int sample_rate
Audio only.
Definition: codec_par.h:170
#define AVPROBE_SCORE_MAX
maximum score
Definition: avformat.h:453
uint32_t bytes_read
Definition: pp_bnk.c:51
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:915
signed 16 bits
Definition: samplefmt.h:61
#define AV_PKT_FLAG_CORRUPT
The packet content is corrupted.
Definition: packet.h:389
void * priv_data
Format private data.
Definition: avformat.h:1379
int bits_per_coded_sample
The number of bits per sample in the codedwords.
Definition: codec_par.h:102
int channels
Audio only.
Definition: codec_par.h:166
PPBnkCtxTrack * tracks
Definition: pp_bnk.c:56
#define av_freep(p)
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:650
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1023
#define av_malloc_array(a, b)
static void pp_bnk_parse_header(PPBnkHeader *hdr, const uint8_t *buf)
Definition: pp_bnk.c:66
int stream_index
Definition: packet.h:357
#define AV_CH_LAYOUT_MONO
This structure stores compressed data.
Definition: packet.h:332