mirror of https://github.com/mpv-player/mpv
ao_wasapi: deduplicate wasapi sample format selection
This commit is contained in:
parent
15eb1e1ad3
commit
434d3d4976
|
@ -94,6 +94,20 @@ static const struct wasapi_sample_fmt wasapi_formats[] = {
|
||||||
{0},
|
{0},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void wasapi_get_best_sample_formats(
|
||||||
|
int src_format, struct wasapi_sample_fmt *out_formats)
|
||||||
|
{
|
||||||
|
int mp_formats[AF_FORMAT_COUNT];
|
||||||
|
af_get_best_sample_formats(src_format, mp_formats);
|
||||||
|
for (int n = 0; mp_formats[n]; n++) {
|
||||||
|
for (int i = 0; wasapi_formats[i].mp_format; i++) {
|
||||||
|
if (wasapi_formats[i].mp_format == mp_formats[n])
|
||||||
|
*out_formats++ = wasapi_formats[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*out_formats = (struct wasapi_sample_fmt) {0};
|
||||||
|
}
|
||||||
|
|
||||||
static const GUID *format_to_subtype(int format)
|
static const GUID *format_to_subtype(int format)
|
||||||
{
|
{
|
||||||
for (int i = 0; wasapi_formats[i].mp_format; i++) {
|
for (int i = 0; wasapi_formats[i].mp_format; i++) {
|
||||||
|
@ -120,54 +134,21 @@ static void update_waveformat_datarate(WAVEFORMATEXTENSIBLE *wformat)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_waveformat(WAVEFORMATEXTENSIBLE *wformat,
|
static void set_waveformat(WAVEFORMATEXTENSIBLE *wformat,
|
||||||
struct wasapi_sample_fmt format,
|
struct wasapi_sample_fmt *format,
|
||||||
DWORD samplerate, struct mp_chmap *channels)
|
DWORD samplerate, struct mp_chmap *channels)
|
||||||
{
|
{
|
||||||
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 = format.bits;
|
wformat->Format.wBitsPerSample = format->bits;
|
||||||
wformat->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
|
wformat->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
|
||||||
|
|
||||||
wformat->SubFormat = *format_to_subtype(format.mp_format);
|
wformat->SubFormat = *format_to_subtype(format->mp_format);
|
||||||
wformat->Samples.wValidBitsPerSample = format.used_msb;
|
wformat->Samples.wValidBitsPerSample = format->used_msb;
|
||||||
wformat->dwChannelMask = mp_chmap_to_waveext(channels);
|
wformat->dwChannelMask = mp_chmap_to_waveext(channels);
|
||||||
update_waveformat_datarate(wformat);
|
update_waveformat_datarate(wformat);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This implicitly transforms all pcm formats to: interleaved / signed (except
|
|
||||||
// 8-bit is unsigned) / waveext channel order. "Special" formats should be
|
|
||||||
// exempt as they should already satisfy these properties.
|
|
||||||
static void set_waveformat_with_ao(WAVEFORMATEXTENSIBLE *wformat, struct ao *ao)
|
|
||||||
{
|
|
||||||
struct mp_chmap channels = ao->channels;
|
|
||||||
|
|
||||||
if (mp_chmap_is_unknown(&channels))
|
|
||||||
mp_chmap_from_channels(&channels, channels.num);
|
|
||||||
mp_chmap_reorder_to_waveext(&channels);
|
|
||||||
if (!mp_chmap_is_valid(&channels))
|
|
||||||
mp_chmap_from_channels(&channels, 2);
|
|
||||||
|
|
||||||
// First find a format that is actually representable.
|
|
||||||
// (Notably excludes AF_FORMAT_DOUBLE.)
|
|
||||||
struct wasapi_sample_fmt format =
|
|
||||||
{AF_FORMAT_S16, 16, 16, &KSDATAFORMAT_SUBTYPE_PCM};
|
|
||||||
|
|
||||||
int alt_formats[AF_FORMAT_COUNT];
|
|
||||||
af_get_best_sample_formats(ao->format, alt_formats);
|
|
||||||
for (int n = 0; alt_formats[n]; n++) {
|
|
||||||
for (int i = 0; wasapi_formats[i].mp_format; i++) {
|
|
||||||
if (wasapi_formats[i].mp_format == alt_formats[n]) {
|
|
||||||
format = wasapi_formats[i];
|
|
||||||
goto found_format;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
found_format:
|
|
||||||
|
|
||||||
set_waveformat(wformat, format, ao->samplerate, &channels);
|
|
||||||
}
|
|
||||||
|
|
||||||
// other wformat parameters must already be set with set_waveformat
|
// other wformat parameters must already be set with set_waveformat
|
||||||
static void change_waveformat_samplerate(WAVEFORMATEXTENSIBLE *wformat,
|
static void change_waveformat_samplerate(WAVEFORMATEXTENSIBLE *wformat,
|
||||||
DWORD samplerate)
|
DWORD samplerate)
|
||||||
|
@ -331,16 +312,12 @@ static bool try_format_exclusive(struct ao *ao, WAVEFORMATEXTENSIBLE *wformat)
|
||||||
static bool search_sample_formats(struct ao *ao, WAVEFORMATEXTENSIBLE *wformat,
|
static bool search_sample_formats(struct ao *ao, WAVEFORMATEXTENSIBLE *wformat,
|
||||||
int samplerate, struct mp_chmap *channels)
|
int samplerate, struct mp_chmap *channels)
|
||||||
{
|
{
|
||||||
int alt_formats[AF_FORMAT_COUNT];
|
struct wasapi_sample_fmt alt_formats[MP_ARRAY_SIZE(wasapi_formats)];
|
||||||
af_get_best_sample_formats(ao->format, alt_formats);
|
wasapi_get_best_sample_formats(ao->format, alt_formats);
|
||||||
for (int n = 0; alt_formats[n]; n++) {
|
for (int n = 0; alt_formats[n].mp_format; n++) {
|
||||||
for (int i = 0; wasapi_formats[i].mp_format; i++) {
|
set_waveformat(wformat, &alt_formats[n], samplerate, channels);
|
||||||
if (wasapi_formats[i].mp_format == alt_formats[n]) {
|
if (try_format_exclusive(ao, wformat))
|
||||||
set_waveformat(wformat, wasapi_formats[i], samplerate, channels);
|
return true;
|
||||||
if (try_format_exclusive(ao, wformat))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wformat->Format.wBitsPerSample = 0;
|
wformat->Format.wBitsPerSample = 0;
|
||||||
|
@ -483,10 +460,24 @@ exit_label:
|
||||||
static bool find_formats(struct ao *ao)
|
static bool find_formats(struct ao *ao)
|
||||||
{
|
{
|
||||||
struct wasapi_state *state = ao->priv;
|
struct wasapi_state *state = ao->priv;
|
||||||
|
struct mp_chmap channels = ao->channels;
|
||||||
|
|
||||||
|
if (mp_chmap_is_unknown(&channels))
|
||||||
|
mp_chmap_from_channels(&channels, channels.num);
|
||||||
|
mp_chmap_reorder_to_waveext(&channels);
|
||||||
|
if (!mp_chmap_is_valid(&channels))
|
||||||
|
mp_chmap_from_channels(&channels, 2);
|
||||||
|
|
||||||
|
struct wasapi_sample_fmt alt_formats[MP_ARRAY_SIZE(wasapi_formats)];
|
||||||
|
wasapi_get_best_sample_formats(ao->format, alt_formats);
|
||||||
|
struct wasapi_sample_fmt wasapi_format =
|
||||||
|
{AF_FORMAT_S16, 16, 16, &KSDATAFORMAT_SUBTYPE_PCM};;
|
||||||
|
if (alt_formats[0].mp_format)
|
||||||
|
wasapi_format = alt_formats[0];
|
||||||
|
|
||||||
AUDCLNT_SHAREMODE share_mode;
|
AUDCLNT_SHAREMODE share_mode;
|
||||||
WAVEFORMATEXTENSIBLE wformat;
|
WAVEFORMATEXTENSIBLE wformat;
|
||||||
|
set_waveformat(&wformat, &wasapi_format, ao->samplerate, &channels);
|
||||||
set_waveformat_with_ao(&wformat, ao);
|
|
||||||
|
|
||||||
if (state->opt_exclusive || af_fmt_is_spdif(ao->format)) {
|
if (state->opt_exclusive || af_fmt_is_spdif(ao->format)) {
|
||||||
share_mode = AUDCLNT_SHAREMODE_EXCLUSIVE;
|
share_mode = AUDCLNT_SHAREMODE_EXCLUSIVE;
|
||||||
|
|
Loading…
Reference in New Issue