aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul B Mahol <onemda@gmail.com>2020-09-12 14:45:31 +0200
committerPaul B Mahol <onemda@gmail.com>2020-09-12 14:52:31 +0200
commit3382b0290a31a9e462d3f19e9590fa091b23fd4f (patch)
tree781e1a656733077474e7b598b00d1079f6152300
parent61d767f3a3a9b6c7cdeb509d1839b40233c2115d (diff)
downloadffmpeg-3382b0290a31a9e462d3f19e9590fa091b23fd4f.tar.gz
avformat/brstm: fix decoding brstm with custom coeff offsets
-rw-r--r--libavformat/brstm.c31
1 files changed, 30 insertions, 1 deletions
diff --git a/libavformat/brstm.c b/libavformat/brstm.c
index a63c7ee5ab..c4230a63bf 100644
--- a/libavformat/brstm.c
+++ b/libavformat/brstm.c
@@ -24,6 +24,11 @@
#include "avformat.h"
#include "internal.h"
+typedef struct BRSTMCoeffOffset {
+ uint8_t channel;
+ uint32_t offset;
+} BRSTMCoeffOffset;
+
typedef struct BRSTMDemuxContext {
uint32_t block_size;
uint32_t block_count;
@@ -35,6 +40,7 @@ typedef struct BRSTMDemuxContext {
uint32_t data_start;
uint8_t *table;
uint8_t *adpc;
+ BRSTMCoeffOffset offsets[256];
int little_endian;
} BRSTMDemuxContext;
@@ -67,6 +73,13 @@ static int read_close(AVFormatContext *s)
return 0;
}
+static int sort_offsets(const void *a, const void *b)
+{
+ const BRSTMCoeffOffset *s1 = a;
+ const BRSTMCoeffOffset *s2 = b;
+ return FFDIFFSIGN(s1->offset, s2->offset);
+}
+
static av_always_inline unsigned int read16(AVFormatContext *s)
{
BRSTMDemuxContext *b = s->priv_data;
@@ -259,17 +272,33 @@ static int read_header(AVFormatContext *s)
if (toffset > size)
return AVERROR_INVALIDDATA;
+ if (!bfstm) {
+ avio_skip(s->pb, pos + toffset - avio_tell(s->pb) - 8LL * (st->codecpar->channels + 1));
+ for (ch = 0; ch < st->codecpar->channels; ch++) {
+ avio_skip(s->pb, 4);
+ b->offsets[ch].channel = ch;
+ b->offsets[ch].offset = read32(s);
+ }
+
+ qsort(b->offsets, st->codecpar->channels, sizeof(*b->offsets), sort_offsets);
+ }
+
avio_skip(s->pb, pos + toffset - avio_tell(s->pb));
b->table = av_mallocz(32 * st->codecpar->channels);
if (!b->table)
return AVERROR(ENOMEM);
for (ch = 0; ch < st->codecpar->channels; ch++) {
+ if (!bfstm)
+ avio_skip(s->pb, pos + 16LL + b->offsets[ch].offset - avio_tell(s->pb));
+
if (avio_read(s->pb, b->table + ch * 32, 32) != 32) {
ret = AVERROR_INVALIDDATA;
goto fail;
}
- avio_skip(s->pb, bfstm ? 14 : 24);
+
+ if (bfstm)
+ avio_skip(s->pb, 14);
}
}