avformat/xwma: fix WMAv2 with incorrect bit rate

Fixes trac issue #7215

Output for files created by xWMAEncode and various videogames is correct now.

1ch 32000hz files are still broken, would need fixes in WMA decoder.

Signed-off-by: bnnm <bananaman255@gmail.com>
This commit is contained in:
bnnm 2018-10-03 22:32:04 +02:00 committed by Paul B Mahol
parent 57f312a34d
commit 02ea060b29
1 changed files with 31 additions and 7 deletions

View File

@ -80,19 +80,43 @@ static int xwma_read_header(AVFormatContext *s)
return ret; return ret;
st->need_parsing = AVSTREAM_PARSE_NONE; st->need_parsing = AVSTREAM_PARSE_NONE;
/* All xWMA files I have seen contained WMAv2 data. If there are files /* XWMA encoder only allows a few channel/sample rate/bitrate combinations,
* using WMA Pro or some other codec, then we need to figure out the right * but some create identical files with fake bitrate (1ch 22050hz at
* extradata for that. Thus, ask the user for feedback, but try to go on * 20/48/192kbps are all 20kbps, with the exact same codec data).
* anyway. * 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 && if (st->codecpar->codec_id != AV_CODEC_ID_WMAV2 &&
st->codecpar->codec_id != AV_CODEC_ID_WMAPRO) { st->codecpar->codec_id != AV_CODEC_ID_WMAPRO) {
avpriv_request_sample(s, "Unexpected codec (tag %s; id %d)", avpriv_request_sample(s, "Unexpected codec (tag %s; id %d)",
av_fourcc2str(st->codecpar->codec_tag), av_fourcc2str(st->codecpar->codec_tag),
st->codecpar->codec_id); st->codecpar->codec_id);
} else { } else {
/* In all xWMA files I have seen, there is no extradata. But the WMA /* xWMA shouldn't have extradata. But the WMA codecs require it,
* codecs require extradata, so we provide our own fake extradata. * so we provide our own fake extradata.
* *
* First, check that there really was no extradata in the header. If * 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 * there was, then try to use it, after asking the user to provide a