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:
wm4 2014-09-23 21:12:28 +02:00
parent b745c2d005
commit 308d72a02e
1 changed files with 19 additions and 28 deletions

View File

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