avformat/brstm: fix decoding brstm with custom coeff offsets

This commit is contained in:
Paul B Mahol 2020-09-12 14:45:31 +02:00
parent 61d767f3a3
commit 3382b0290a
1 changed files with 30 additions and 1 deletions

View File

@ -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);
}
}