summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2017-03-29 14:36:00 +0200
committerwm4 <wm4@nowhere>2017-03-29 15:19:25 +0200
commitc68be80a63f100d1a55d8be7273c89734d6abeeb (patch)
tree3b66b938ab09b8760270a90f6e15b1d17dc40360
parent4d07fce04175bf353e8de538571d3afa2c7b3e00 (diff)
downloadmpv-c68be80a63f100d1a55d8be7273c89734d6abeeb.tar.bz2
mpv-c68be80a63f100d1a55d8be7273c89734d6abeeb.tar.xz
ao_wasapi: do not pass nonsense to drivers with double
This tried to use AF_FORMAT_DOUBLE as KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, with wBitsPerSample==64. This is probably not allowed, and drivers appear to react inconsistently to it. (With one user, the format was accepted during format negotiation, but then rejected on actual init.) Remove it, which essentially forces it to fall back to some other format. (Looks like it'll use af_select_best_samplerate(), which would probably make it try S32 next.) The af_fmt_from_planar() is so that we don't have to care about AF_FORMAT_FLOATP. Wasapi always requires packed data anyway. This should actually handle other potentially unknown sample formats better. This changes that set_waveformat() always set the exact format. Now it might set a "close" format instead. But all callers seem to deal with this well. Although in theory, callers should probably handle the fallback. The next cleanup (if ever) can take care of this.
-rw-r--r--audio/out/ao_wasapi_utils.c28
1 files changed, 23 insertions, 5 deletions
diff --git a/audio/out/ao_wasapi_utils.c b/audio/out/ao_wasapi_utils.c
index a449dbec10..f1895eb49e 100644
--- a/audio/out/ao_wasapi_utils.c
+++ b/audio/out/ao_wasapi_utils.c
@@ -88,10 +88,12 @@ static const GUID *format_to_subtype(int format)
return wasapi_fmt_table[i].subtype;
}
return &KSDATAFORMAT_SPECIFIER_NONE;
- } else if (af_fmt_is_float(format)) {
+ } else if (format == AF_FORMAT_FLOAT) {
return &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
+ } else if (af_fmt_is_int(format)) {
+ return &KSDATAFORMAT_SUBTYPE_PCM;
}
- return &KSDATAFORMAT_SUBTYPE_PCM;
+ return NULL;
}
// "solve" the under-determined inverse of format_to_subtype by assuming the
@@ -124,13 +126,27 @@ static void set_waveformat(WAVEFORMATEXTENSIBLE *wformat,
int format, WORD valid_bits,
DWORD samplerate, struct mp_chmap *channels)
{
+ // First find a format that is actually representable.
+ // (Notably excludes AF_FORMAT_DOUBLE.)
+ const GUID *sub_format = &KSDATAFORMAT_SPECIFIER_NONE;
+ int alt_formats[AF_FORMAT_COUNT];
+ af_get_best_sample_formats(format, alt_formats);
+ for (int n = 0; alt_formats[n]; n++) {
+ const GUID *guid = format_to_subtype(alt_formats[n]);
+ if (guid) {
+ format = alt_formats[n];
+ sub_format = guid;
+ break;
+ }
+ }
+
wformat->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
wformat->Format.nChannels = channels->num;
wformat->Format.nSamplesPerSec = samplerate;
wformat->Format.wBitsPerSample = af_fmt_to_bytes(format) * 8;
wformat->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
- wformat->SubFormat = *format_to_subtype(format);
+ wformat->SubFormat = *sub_format;
wformat->Samples.wValidBitsPerSample =
valid_bits ? valid_bits : wformat->Format.wBitsPerSample;
wformat->dwChannelMask = mp_chmap_to_waveext(channels);
@@ -318,10 +334,10 @@ static bool search_sample_formats(struct ao *ao, WAVEFORMATEXTENSIBLE *wformat,
int samplerate, struct mp_chmap *channels)
{
// some common bit depths / container sizes (requests welcome)
- int try[] = {AF_FORMAT_DOUBLE, AF_FORMAT_FLOAT, AF_FORMAT_S32,
+ int try[] = {AF_FORMAT_FLOAT , AF_FORMAT_S32 ,
AF_FORMAT_S24 , AF_FORMAT_S32 , AF_FORMAT_S16,
AF_FORMAT_U8 , 0};
- unsigned valid[] = {0 , 0, 0,
+ unsigned valid[] = {0 , 0,
0 , 24, 0,
0 };
for (int i = 0; try[i]; i++) {
@@ -596,6 +612,8 @@ static HRESULT fix_format(struct ao *ao)
bufferPeriod = bufferDuration = devicePeriod;
}
+ ao->format = af_fmt_from_planar(ao->format);
+
// handle unsupported buffer size hopefully this shouldn't happen because of
// the above integer device period
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd370875%28v=vs.85%29.aspx