summaryrefslogtreecommitdiffstats
path: root/audio/out/ao_wasapi_utils.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2014-09-23 21:12:28 +0200
committerwm4 <wm4@nowhere>2014-09-23 23:09:29 +0200
commit308d72a02ee673fc56b637b6134dd63ea258580c (patch)
tree48f7d3388ca7534fd9545828428c383f75bf39e6 /audio/out/ao_wasapi_utils.c
parentb745c2d0050468580aec0a4e12aec854fefd1796 (diff)
downloadmpv-308d72a02ee673fc56b637b6134dd63ea258580c.tar.bz2
mpv-308d72a02ee673fc56b637b6134dd63ea258580c.tar.xz
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.
Diffstat (limited to 'audio/out/ao_wasapi_utils.c')
-rwxr-xr-xaudio/out/ao_wasapi_utils.c47
1 files changed, 19 insertions, 28 deletions
diff --git a/audio/out/ao_wasapi_utils.c b/audio/out/ao_wasapi_utils.c
index c12f3baf61..c39eb6fea2 100755
--- a/audio/out/ao_wasapi_utils.c
+++ b/audio/out/ao_wasapi_utils.c
@@ -142,47 +142,36 @@ static void set_format(WAVEFORMATEXTENSIBLE *wformat, WORD bytepersample,
wformat->dwChannelMask = chanmask;
}
-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
- }
-
+static int format_set_bits(int old_format, int bits, int fp)
+{
if (fp) {
- format |= AF_FORMAT_F;
- } else {
- format |= AF_FORMAT_I;
+ switch (bits) {
+ case 64: return AF_FORMAT_DOUBLE;
+ 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,
struct ao *const ao,
- 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);
-
+ WAVEFORMATEXTENSIBLE wformat)
+{
if (wformat.SubFormat.Data1 != 1 && wformat.SubFormat.Data1 != 3) {
MP_ERR(ao, "unknown SubFormat %"PRIu32"\n",
(uint32_t)wformat.SubFormat.Data1);
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->bps = wformat.Format.nAvgBytesPerSec;
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));
int af_format = format_set_bits(ao->format, bits, bits == 32);
+ if (!af_format)
+ return 0;
MP_VERBOSE(ao, "trying %dch %s @ %dhz\n",
channels.num, af_fmt_to_str(af_format), samplerate);