1
0
mirror of https://github.com/mpv-player/mpv synced 2024-12-26 00:42:57 +00:00

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.
This commit is contained in:
wm4 2017-03-29 14:36:00 +02:00
parent 4d07fce041
commit c68be80a63

View File

@ -88,10 +88,12 @@ static const GUID *format_to_subtype(int format)
return wasapi_fmt_table[i].subtype; return wasapi_fmt_table[i].subtype;
} }
return &KSDATAFORMAT_SPECIFIER_NONE; return &KSDATAFORMAT_SPECIFIER_NONE;
} else if (af_fmt_is_float(format)) { } else if (format == AF_FORMAT_FLOAT) {
return &KSDATAFORMAT_SUBTYPE_IEEE_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 // "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, int format, WORD valid_bits,
DWORD samplerate, struct mp_chmap *channels) 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.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
wformat->Format.nChannels = channels->num; wformat->Format.nChannels = channels->num;
wformat->Format.nSamplesPerSec = samplerate; wformat->Format.nSamplesPerSec = samplerate;
wformat->Format.wBitsPerSample = af_fmt_to_bytes(format) * 8; wformat->Format.wBitsPerSample = af_fmt_to_bytes(format) * 8;
wformat->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX); wformat->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
wformat->SubFormat = *format_to_subtype(format); wformat->SubFormat = *sub_format;
wformat->Samples.wValidBitsPerSample = wformat->Samples.wValidBitsPerSample =
valid_bits ? valid_bits : wformat->Format.wBitsPerSample; valid_bits ? valid_bits : wformat->Format.wBitsPerSample;
wformat->dwChannelMask = mp_chmap_to_waveext(channels); 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) int samplerate, struct mp_chmap *channels)
{ {
// some common bit depths / container sizes (requests welcome) // 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_S24 , AF_FORMAT_S32 , AF_FORMAT_S16,
AF_FORMAT_U8 , 0}; AF_FORMAT_U8 , 0};
unsigned valid[] = {0 , 0, 0, unsigned valid[] = {0 , 0,
0 , 24, 0, 0 , 24, 0,
0 }; 0 };
for (int i = 0; try[i]; i++) { for (int i = 0; try[i]; i++) {
@ -596,6 +612,8 @@ static HRESULT fix_format(struct ao *ao)
bufferPeriod = bufferDuration = devicePeriod; bufferPeriod = bufferDuration = devicePeriod;
} }
ao->format = af_fmt_from_planar(ao->format);
// handle unsupported buffer size hopefully this shouldn't happen because of // handle unsupported buffer size hopefully this shouldn't happen because of
// the above integer device period // the above integer device period
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd370875%28v=vs.85%29.aspx // http://msdn.microsoft.com/en-us/library/windows/desktop/dd370875%28v=vs.85%29.aspx