diff options
author | Paul B Mahol <onemda@gmail.com> | 2020-09-12 14:45:31 +0200 |
---|---|---|
committer | Paul B Mahol <onemda@gmail.com> | 2020-09-12 14:52:31 +0200 |
commit | 3382b0290a31a9e462d3f19e9590fa091b23fd4f (patch) | |
tree | 781e1a656733077474e7b598b00d1079f6152300 /libavformat/brstm.c | |
parent | 61d767f3a3a9b6c7cdeb509d1839b40233c2115d (diff) | |
download | ffmpeg-3382b0290a31a9e462d3f19e9590fa091b23fd4f.tar.gz |
avformat/brstm: fix decoding brstm with custom coeff offsets
Diffstat (limited to 'libavformat/brstm.c')
-rw-r--r-- | libavformat/brstm.c | 31 |
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); } } |