summaryrefslogtreecommitdiffstats
path: root/options
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2016-08-04 20:49:20 +0200
committerwm4 <wm4@nowhere>2016-08-04 20:49:20 +0200
commit0b144eac39bbae51c3f2b7683f6982eb91b66393 (patch)
tree63f0585f4dece4195da5745a4969159d9b5d8122 /options
parentc30aa2340132e50994cdf168aaba011ecb4f6b0c (diff)
downloadmpv-0b144eac39bbae51c3f2b7683f6982eb91b66393.tar.bz2
mpv-0b144eac39bbae51c3f2b7683f6982eb91b66393.tar.xz
audio: use --audio-channels=auto behavior, except on ALSA
This commit adds an --audio-channel=auto-safe mode, and makes it the default. This mode behaves like "auto" with most AOs, except with ao_alsa. The intention is to allow multichannel output by default on sane APIs. ALSA is not sane as in it's so low level that it will e.g. configure any layout over HDMI, even if the connected A/V receiver does not support it. The HDMI fuckup is of course not ALSA's fault, but other audio APIs normally isolate applications from dealing with this and require the user to globally configure the correct output layout. This will help with other AOs too. ao_lavc (encoding) is changed to the new semantics as well, because it used to force stereo (perhaps because encoding mode is supposed to produce safe files for crap devices?). Exclusive mode output on Windows might need to be adjusted accordingly, as it grants the same kind of low level access as ALSA (requires more research). In addition to the things mentioned above, the --audio-channels option is extended to accept a set of channel layouts. This is supposed to be the correct way to configure mpv ALSA multichannel output. You need to put a list of channel layouts that your A/V receiver supports.
Diffstat (limited to 'options')
-rw-r--r--options/m_option.c104
-rw-r--r--options/m_option.h18
-rw-r--r--options/options.c3
-rw-r--r--options/options.h2
4 files changed, 94 insertions, 33 deletions
diff --git a/options/m_option.c b/options/m_option.c
index b7b76634f8..231b9aa5d2 100644
--- a/options/m_option.c
+++ b/options/m_option.c
@@ -2287,51 +2287,105 @@ const m_option_type_t m_option_type_afmt = {
#include "audio/chmap.h"
-static int parse_chmap(struct mp_log *log, const m_option_t *opt,
- struct bstr name, struct bstr param, void *dst)
+static int parse_channels(struct mp_log *log, const m_option_t *opt,
+ struct bstr name, struct bstr param, void *dst)
{
- // min>0: at least min channels, min=0: empty ok
- int min_ch = (opt->flags & M_OPT_MIN) ? opt->min : 1;
- assert(min_ch >= 0);
+ // see OPT_CHANNELS for semantics.
+ bool limited = opt->min;
+
+ struct m_channels res = {0};
if (bstr_equals0(param, "help")) {
mp_chmap_print_help(log);
+ if (!limited) {
+ mp_info(log, "\nOther values:\n"
+ " auto-safe\n");
+ }
return M_OPT_EXIT - 1;
}
- if (param.len == 0 && min_ch >= 1)
- return M_OPT_MISSING_PARAM;
-
- struct mp_chmap res = {0};
- if (!mp_chmap_from_str(&res, param)) {
- mp_err(log, "Error parsing channel layout: %.*s\n", BSTR_P(param));
- return M_OPT_INVALID;
+ bool auto_safe = bstr_equals0(param, "auto-safe");
+ if (bstr_equals0(param, "auto") || bstr_equals0(param, "empty") || auto_safe) {
+ if (limited) {
+ mp_err(log, "Disallowed parameter.\n");
+ return M_OPT_INVALID;
+ }
+ param.len = 0;
+ res.set = true;
+ res.auto_safe = auto_safe;
}
- if (!mp_chmap_is_valid(&res) && !(min_ch == 0 && mp_chmap_is_empty(&res))) {
- mp_err(log, "Invalid channel layout: %.*s\n", BSTR_P(param));
- return M_OPT_INVALID;
+ while (param.len) {
+ bstr item;
+ if (limited) {
+ item = param;
+ param.len = 0;
+ } else {
+ bstr_split_tok(param, ",", &item, &param);
+ }
+
+ struct mp_chmap map = {0};
+ if (!mp_chmap_from_str(&map, item) || !mp_chmap_is_valid(&map)) {
+ mp_err(log, "Invalid channel layout: %.*s\n", BSTR_P(item));
+ talloc_free(res.chmaps);
+ return M_OPT_INVALID;
+ }
+
+ MP_TARRAY_APPEND(NULL, res.chmaps, res.num_chmaps, map);
+ res.set = true;
}
- if (dst)
- *(struct mp_chmap *)dst = res;
+ if (dst) {
+ *(struct m_channels *)dst = res;
+ } else {
+ talloc_free(res.chmaps);
+ }
return 1;
}
-static char *print_chmap(const m_option_t *opt, const void *val)
+static char *print_channels(const m_option_t *opt, const void *val)
{
- const struct mp_chmap *chmap = val;
- return talloc_strdup(NULL, mp_chmap_to_str(chmap));
+ const struct m_channels *ch = val;
+ if (!ch->set)
+ return talloc_strdup(NULL, "");
+ if (ch->auto_safe)
+ return talloc_strdup(NULL, "auto-safe");
+ if (ch->num_chmaps > 0) {
+ char *res = talloc_strdup(NULL, "");
+ for (int n = 0; n < ch->num_chmaps; n++) {
+ if (n > 0)
+ res = talloc_strdup_append(res, ",");
+ res = talloc_strdup_append(res, mp_chmap_to_str(&ch->chmaps[n]));
+ }
+ return res;
+ }
+ return talloc_strdup(NULL, "auto");
}
+static void free_channels(void *src)
+{
+ struct m_channels *ch = src;
+ talloc_free(ch->chmaps);
+ *ch = (struct m_channels){0};
+}
-const m_option_type_t m_option_type_chmap = {
+static void copy_channels(const m_option_t *opt, void *dst, const void *src)
+{
+ struct m_channels *ch = dst;
+ free_channels(dst);
+ *ch = *(struct m_channels *)src;
+ ch->chmaps =
+ talloc_memdup(NULL, ch->chmaps, sizeof(ch->chmaps[0]) * ch->num_chmaps);
+}
+
+const m_option_type_t m_option_type_channels = {
.name = "Audio channels or channel map",
- .size = sizeof(struct mp_chmap),
- .parse = parse_chmap,
- .print = print_chmap,
- .copy = copy_opt,
+ .size = sizeof(struct m_channels),
+ .parse = parse_channels,
+ .print = print_channels,
+ .copy = copy_channels,
+ .free = free_channels,
};
static int parse_timestring(struct bstr str, double *time, char endchar)
diff --git a/options/m_option.h b/options/m_option.h
index e77452af69..80be447c42 100644
--- a/options/m_option.h
+++ b/options/m_option.h
@@ -61,7 +61,7 @@ extern const m_option_type_t m_option_type_afmt;
extern const m_option_type_t m_option_type_color;
extern const m_option_type_t m_option_type_geometry;
extern const m_option_type_t m_option_type_size_box;
-extern const m_option_type_t m_option_type_chmap;
+extern const m_option_type_t m_option_type_channels;
extern const m_option_type_t m_option_type_node;
// Used internally by m_config.c
@@ -98,6 +98,13 @@ struct m_geometry {
void m_geometry_apply(int *xpos, int *ypos, int *widw, int *widh,
int scrw, int scrh, struct m_geometry *gm);
+struct m_channels {
+ bool set : 1;
+ bool auto_safe : 1;
+ struct mp_chmap *chmaps;
+ int num_chmaps;
+};
+
struct m_obj_desc {
// Name which will be used in the option string
const char *name;
@@ -218,7 +225,7 @@ union m_option_value {
struct m_color color;
struct m_geometry geometry;
struct m_geometry size_box;
- struct mp_chmap chmap;
+ struct m_channels channels;
};
////////////////////////////////////////////////////////////////////////////
@@ -626,9 +633,10 @@ extern const char m_option_path_separator;
#define OPT_AUDIOFORMAT(...) \
OPT_GENERAL(int, __VA_ARGS__, .type = &m_option_type_afmt)
-#define OPT_CHMAP(...) \
- OPT_GENERAL(struct mp_chmap, __VA_ARGS__, .type = &m_option_type_chmap)
-
+// If .min==1, then passing auto is disallowed, but "" is still accepted, and
+// limit channel list to 1 item.
+#define OPT_CHANNELS(...) \
+ OPT_GENERAL(struct m_channels, __VA_ARGS__, .type = &m_option_type_channels)
#define M_CHOICES(choices) \
.priv = (void *)&(const struct m_opt_choice_alternatives[]){ \
diff --git a/options/options.c b/options/options.c
index 0ad9d71b40..9fd853ffda 100644
--- a/options/options.c
+++ b/options/options.c
@@ -279,7 +279,7 @@ const m_option_t mp_opts[] = {
// force video/audio rate:
OPT_DOUBLE("fps", force_fps, CONF_MIN, .min = 0),
OPT_INTRANGE("audio-samplerate", force_srate, 0, 1000, 16*48000),
- OPT_CHMAP("audio-channels", audio_output_channels, CONF_MIN, .min = 0),
+ OPT_CHANNELS("audio-channels", audio_output_channels, 0),
OPT_AUDIOFORMAT("audio-format", audio_output_format, 0),
OPT_FLAG("audio-normalize-downmix", audio_normalize, 0),
OPT_DOUBLE("speed", playback_speed, M_OPT_RANGE | M_OPT_FIXED,
@@ -805,7 +805,6 @@ const struct MPOpts mp_default_opts = {
.sub_visibility = 1,
.sub_pos = 100,
.sub_speed = 1.0,
- .audio_output_channels = MP_CHMAP_INIT_STEREO,
.audio_output_format = 0, // AF_FORMAT_UNKNOWN
.playback_speed = 1.,
.pitch_correction = 1,
diff --git a/options/options.h b/options/options.h
index 7690823aab..ef72865f56 100644
--- a/options/options.h
+++ b/options/options.h
@@ -226,7 +226,7 @@ typedef struct MPOpts {
double force_fps;
int index_mode;
- struct mp_chmap audio_output_channels;
+ struct m_channels audio_output_channels;
int audio_output_format;
int audio_normalize;
int force_srate;