mirror of https://github.com/mpv-player/mpv
ao_wasapi: fix fragile format-mapping code
This code tried to play with the format bits, and potentially could create invalid formats, or reinterpret obscure formats in unexpected ways. Also there was an abort() call if the winapi or mpv used a format with unexpected bit-width. This could probably easily happen; for example, mpv supports at least one 64 bit format. And what would happen on 8 bit formats anyway? Untested.
This commit is contained in:
parent
b745c2d005
commit
308d72a02e
|
@ -142,47 +142,36 @@ static void set_format(WAVEFORMATEXTENSIBLE *wformat, WORD bytepersample,
|
||||||
wformat->dwChannelMask = chanmask;
|
wformat->dwChannelMask = chanmask;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int format_set_bits(int old_format, int bits, int fp) {
|
static int format_set_bits(int old_format, int bits, int fp)
|
||||||
int format = old_format;
|
{
|
||||||
format &= (~AF_FORMAT_BITS_MASK) & (~AF_FORMAT_POINT_MASK) & (~AF_FORMAT_SIGN_MASK);
|
|
||||||
format |= AF_FORMAT_SI;
|
|
||||||
|
|
||||||
switch (bits) {
|
|
||||||
case 32:
|
|
||||||
format |= AF_FORMAT_32BIT;
|
|
||||||
break;
|
|
||||||
case 24:
|
|
||||||
format |= AF_FORMAT_24BIT;
|
|
||||||
break;
|
|
||||||
case 16:
|
|
||||||
format |= AF_FORMAT_16BIT;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
abort(); // (should be) unreachable
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fp) {
|
if (fp) {
|
||||||
format |= AF_FORMAT_F;
|
switch (bits) {
|
||||||
} else {
|
case 64: return AF_FORMAT_DOUBLE;
|
||||||
format |= AF_FORMAT_I;
|
case 32: return AF_FORMAT_FLOAT;
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return format;
|
return af_fmt_change_bits(old_format, bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int set_ao_format(struct wasapi_state *state,
|
static int set_ao_format(struct wasapi_state *state,
|
||||||
struct ao *const ao,
|
struct ao *const ao,
|
||||||
WAVEFORMATEXTENSIBLE wformat) {
|
WAVEFORMATEXTENSIBLE wformat)
|
||||||
// .Data1 == 1 is PCM, .Data1 == 3 is IEEE_FLOAT
|
{
|
||||||
int format = format_set_bits(ao->format,
|
|
||||||
wformat.Format.wBitsPerSample, wformat.SubFormat.Data1 == 3);
|
|
||||||
|
|
||||||
if (wformat.SubFormat.Data1 != 1 && wformat.SubFormat.Data1 != 3) {
|
if (wformat.SubFormat.Data1 != 1 && wformat.SubFormat.Data1 != 3) {
|
||||||
MP_ERR(ao, "unknown SubFormat %"PRIu32"\n",
|
MP_ERR(ao, "unknown SubFormat %"PRIu32"\n",
|
||||||
(uint32_t)wformat.SubFormat.Data1);
|
(uint32_t)wformat.SubFormat.Data1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// .Data1 == 1 is PCM, .Data1 == 3 is IEEE_FLOAT
|
||||||
|
int format = format_set_bits(ao->format,
|
||||||
|
wformat.Format.wBitsPerSample, wformat.SubFormat.Data1 == 3);
|
||||||
|
|
||||||
|
if (!format)
|
||||||
|
return 0;
|
||||||
|
|
||||||
ao->samplerate = wformat.Format.nSamplesPerSec;
|
ao->samplerate = wformat.Format.nSamplesPerSec;
|
||||||
ao->bps = wformat.Format.nAvgBytesPerSec;
|
ao->bps = wformat.Format.nAvgBytesPerSec;
|
||||||
ao->format = format;
|
ao->format = format;
|
||||||
|
@ -204,6 +193,8 @@ static int try_format(struct wasapi_state *state,
|
||||||
set_format(&wformat, bits / 8, samplerate, channels.num, mp_chmap_to_waveext(&channels));
|
set_format(&wformat, bits / 8, samplerate, channels.num, mp_chmap_to_waveext(&channels));
|
||||||
|
|
||||||
int af_format = format_set_bits(ao->format, bits, bits == 32);
|
int af_format = format_set_bits(ao->format, bits, bits == 32);
|
||||||
|
if (!af_format)
|
||||||
|
return 0;
|
||||||
|
|
||||||
MP_VERBOSE(ao, "trying %dch %s @ %dhz\n",
|
MP_VERBOSE(ao, "trying %dch %s @ %dhz\n",
|
||||||
channels.num, af_fmt_to_str(af_format), samplerate);
|
channels.num, af_fmt_to_str(af_format), samplerate);
|
||||||
|
|
Loading…
Reference in New Issue