int64_t data_end;
} XWMAContext;
-static int xwma_probe(AVProbeData *p)
+static int xwma_probe(const AVProbeData *p)
{
if (!memcmp(p->buf, "RIFF", 4) && !memcmp(p->buf + 8, "XWMA", 4))
return AVPROBE_SCORE_MAX;
/* check RIFF header */
tag = avio_rl32(pb);
if (tag != MKTAG('R', 'I', 'F', 'F'))
- return -1;
+ return AVERROR_INVALIDDATA;
avio_rl32(pb); /* file size */
tag = avio_rl32(pb);
if (tag != MKTAG('X', 'W', 'M', 'A'))
- return -1;
+ return AVERROR_INVALIDDATA;
/* parse fmt header */
tag = avio_rl32(pb);
if (tag != MKTAG('f', 'm', 't', ' '))
- return -1;
+ return AVERROR_INVALIDDATA;
size = avio_rl32(pb);
st = avformat_new_stream(s, NULL);
if (!st)
return ret;
st->need_parsing = AVSTREAM_PARSE_NONE;
- /* All xWMA files I have seen contained WMAv2 data. If there are files
- * using WMA Pro or some other codec, then we need to figure out the right
- * extradata for that. Thus, ask the user for feedback, but try to go on
- * anyway.
- */
+ /* XWMA encoder only allows a few channel/sample rate/bitrate combinations,
+ * but some create identical files with fake bitrate (1ch 22050hz at
+ * 20/48/192kbps are all 20kbps, with the exact same codec data).
+ * Decoder needs correct bitrate to work, so it's normalized here. */
+ if (st->codecpar->codec_id == AV_CODEC_ID_WMAV2) {
+ int ch = st->codecpar->channels;
+ int sr = st->codecpar->sample_rate;
+ int br = st->codecpar->bit_rate;
+
+ if (ch == 1) {
+ if (sr == 22050 && (br==48000 || br==192000))
+ br = 20000;
+ else if (sr == 32000 && (br==48000 || br==192000))
+ br = 20000;
+ else if (sr == 44100 && (br==96000 || br==192000))
+ br = 48000;
+ }
+ else if (ch == 2) {
+ if (sr == 22050 && (br==48000 || br==192000))
+ br = 32000;
+ else if (sr == 32000 && (br==192000))
+ br = 48000;
+ }
+
+ st->codecpar->bit_rate = br;
+ }
+
+ /* Normally xWMA can only contain WMAv2 with 1/2 channels,
+ * and WMAPRO with 6 channels. */
if (st->codecpar->codec_id != AV_CODEC_ID_WMAV2 &&
st->codecpar->codec_id != AV_CODEC_ID_WMAPRO) {
avpriv_request_sample(s, "Unexpected codec (tag %s; id %d)",
av_fourcc2str(st->codecpar->codec_tag),
st->codecpar->codec_id);
} else {
- /* In all xWMA files I have seen, there is no extradata. But the WMA
- * codecs require extradata, so we provide our own fake extradata.
+ /* xWMA shouldn't have extradata. But the WMA codecs require it,
+ * so we provide our own fake extradata.
*
* First, check that there really was no extradata in the header. If
* there was, then try to use it, after asking the user to provide a
avpriv_request_sample(s, "Unexpected extradata (%d bytes)",
st->codecpar->extradata_size);
} else if (st->codecpar->codec_id == AV_CODEC_ID_WMAPRO) {
- if (ff_alloc_extradata(st->codecpar, 18))
- return AVERROR(ENOMEM);
+ if ((ret = ff_alloc_extradata(st->codecpar, 18)) < 0)
+ return ret;
memset(st->codecpar->extradata, 0, st->codecpar->extradata_size);
st->codecpar->extradata[ 0] = st->codecpar->bits_per_coded_sample;
st->codecpar->extradata[14] = 224;
} else {
- if (ff_alloc_extradata(st->codecpar, 6))
- return AVERROR(ENOMEM);
+ if ((ret = ff_alloc_extradata(st->codecpar, 6)) < 0)
+ return ret;
memset(st->codecpar->extradata, 0, st->codecpar->extradata_size);
/* setup extradata with our experimentally obtained value */
}
for (i = 0; i < dpds_table_size; ++i) {
+ if (avio_feof(pb)) {
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
dpds_table[i] = avio_rl32(pb);
size -= 4;
}