diff options
Diffstat (limited to 'audio/out')
-rw-r--r-- | audio/out/ao.c | 34 | ||||
-rw-r--r-- | audio/out/ao.h | 10 | ||||
-rw-r--r-- | audio/out/ao_alsa.c | 2 | ||||
-rw-r--r-- | audio/out/ao_lavc.c | 2 | ||||
-rw-r--r-- | audio/out/internal.h | 3 |
5 files changed, 43 insertions, 8 deletions
diff --git a/audio/out/ao.c b/audio/out/ao.c index c9d8f42b4a..0647067e50 100644 --- a/audio/out/ao.c +++ b/audio/out/ao.c @@ -158,7 +158,7 @@ error: static struct ao *ao_init(bool probing, struct mpv_global *global, struct input_ctx *input_ctx, - struct encode_lavc_context *encode_lavc_ctx, + struct encode_lavc_context *encode_lavc_ctx, int flags, int samplerate, int format, struct mp_chmap channels, char *dev, char *name, char **args) { @@ -169,6 +169,7 @@ static struct ao *ao_init(bool probing, struct mpv_global *global, ao->channels = channels; ao->format = format; ao->encode_lavc_ctx = encode_lavc_ctx; + ao->init_flags = flags; if (ao->driver->encode != !!ao->encode_lavc_ctx) goto fail; @@ -190,7 +191,7 @@ static struct ao *ao_init(bool probing, struct mpv_global *global, snprintf(redirect, sizeof(redirect), "%s", ao->redirect); snprintf(rdevice, sizeof(rdevice), "%s", ao->device ? ao->device : ""); talloc_free(ao); - return ao_init(probing, global, input_ctx, encode_lavc_ctx, + return ao_init(probing, global, input_ctx, encode_lavc_ctx, flags, samplerate, format, channels, rdevice, redirect, NULL); } goto fail; @@ -240,7 +241,7 @@ static void split_ao_device(void *tmp, char *opt, char **out_ao, char **out_dev) } struct ao *ao_init_best(struct mpv_global *global, - bool ao_null_fallback, + int init_flags, struct input_ctx *input_ctx, struct encode_lavc_context *encode_lavc_ctx, int samplerate, int format, struct mp_chmap channels) @@ -283,7 +284,7 @@ struct ao *ao_init_best(struct mpv_global *global, } } - if (ao_null_fallback) { + if (init_flags & AO_INIT_NULL_FALLBACK) { MP_TARRAY_APPEND(tmp, ao_list, ao_num, (struct m_obj_settings){.name = "null"}); } @@ -297,7 +298,7 @@ struct ao *ao_init_best(struct mpv_global *global, dev = pref_dev; mp_verbose(log, "Using preferred device '%s'\n", dev); } - ao = ao_init(probing, global, input_ctx, encode_lavc_ctx, + ao = ao_init(probing, global, input_ctx, encode_lavc_ctx, init_flags, samplerate, format, channels, dev, entry->name, entry->attribs); if (ao) @@ -429,6 +430,29 @@ bool ao_chmap_sel_adjust(struct ao *ao, const struct mp_chmap_sel *s, return r; } +// safe_multichannel=true behaves like ao_chmap_sel_adjust. +// safe_multichannel=false is a helper for callers which do not support safe +// handling of arbitrary channel layouts. If the multichannel layouts are not +// considered "always safe" (e.g. HDMI), then allow only stereo or mono, if +// they are part of the list in *s. +bool ao_chmap_sel_adjust2(struct ao *ao, const struct mp_chmap_sel *s, + struct mp_chmap *map, bool safe_multichannel) +{ + if (!safe_multichannel && (ao->init_flags & AO_INIT_SAFE_MULTICHANNEL_ONLY)) { + struct mp_chmap res = *map; + if (mp_chmap_sel_adjust(s, &res)) { + if (!mp_chmap_equals(&res, &(struct mp_chmap)MP_CHMAP_INIT_MONO) && + !mp_chmap_equals(&res, &(struct mp_chmap)MP_CHMAP_INIT_STEREO)) + { + MP_WARN(ao, "Disabling multichannel output.\n"); + *map = (struct mp_chmap)MP_CHMAP_INIT_STEREO; + } + } + } + + return ao_chmap_sel_adjust(ao, s, map); +} + bool ao_chmap_sel_get_def(struct ao *ao, const struct mp_chmap_sel *s, struct mp_chmap *map, int num) { diff --git a/audio/out/ao.h b/audio/out/ao.h index e8e64e33eb..3c16cef0e5 100644 --- a/audio/out/ao.h +++ b/audio/out/ao.h @@ -50,6 +50,14 @@ enum { AO_EVENT_HOTPLUG = 2, }; +enum { + // Allow falling back to ao_null if nothing else works. + AO_INIT_NULL_FALLBACK = 1 << 0, + // Only accept multichannel configurations that are guaranteed to work + // (i.e. not sending arbitrary layouts over HDMI). + AO_INIT_SAFE_MULTICHANNEL_ONLY = 1 << 1, +}; + typedef struct ao_control_vol { float left; float right; @@ -72,7 +80,7 @@ struct encode_lavc_context; struct mp_audio; struct ao *ao_init_best(struct mpv_global *global, - bool ao_null_fallback, + int init_flags, struct input_ctx *input_ctx, struct encode_lavc_context *encode_lavc_ctx, int samplerate, int format, struct mp_chmap channels); diff --git a/audio/out/ao_alsa.c b/audio/out/ao_alsa.c index d09f5fc499..4a55d19656 100644 --- a/audio/out/ao_alsa.c +++ b/audio/out/ao_alsa.c @@ -360,7 +360,7 @@ static bool query_chmaps(struct ao *ao, struct mp_chmap *chmap) snd_pcm_free_chmaps(maps); - return ao_chmap_sel_adjust(ao, &chmap_sel, chmap); + return ao_chmap_sel_adjust2(ao, &chmap_sel, chmap, false); } // Map back our selected channel layout to an ALSA one. This is done this way so diff --git a/audio/out/ao_lavc.c b/audio/out/ao_lavc.c index 6b4279ca87..8ae1317407 100644 --- a/audio/out/ao_lavc.c +++ b/audio/out/ao_lavc.c @@ -123,7 +123,7 @@ static int init(struct ao *ao) struct mp_chmap_sel sel = {0}; mp_chmap_sel_add_any(&sel); - if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels)) + if (!ao_chmap_sel_adjust2(ao, &sel, &ao->channels, false)) goto fail; mp_chmap_reorder_to_lavc(&ao->channels); ac->codec->channels = ao->channels.num; diff --git a/audio/out/internal.h b/audio/out/internal.h index 49131ba293..88160bbeb6 100644 --- a/audio/out/internal.h +++ b/audio/out/internal.h @@ -43,6 +43,7 @@ struct ao { struct encode_lavc_context *encode_lavc_ctx; struct input_ctx *input_ctx; struct mp_log *log; // Using e.g. "[ao/coreaudio]" as prefix + int init_flags; // AO_INIT_* flags // The device as selected by the user, usually using ao_device_desc.name // from an entry from the list returned by driver->list_devices. If the @@ -191,6 +192,8 @@ void ao_wakeup_poll(struct ao *ao); bool ao_chmap_sel_adjust(struct ao *ao, const struct mp_chmap_sel *s, struct mp_chmap *map); +bool ao_chmap_sel_adjust2(struct ao *ao, const struct mp_chmap_sel *s, + struct mp_chmap *map, bool safe_multichannel); bool ao_chmap_sel_get_def(struct ao *ao, const struct mp_chmap_sel *s, struct mp_chmap *map, int num); |