mirror of
https://github.com/mpv-player/mpv
synced 2024-12-27 01:22:30 +00:00
audio: add global options for resampler defaults
This is part of trying to get rid of --af-defaults, and the af resample filter. It requires a complicated mechanism to set the defaults on the resample filter for backwards compatibility.
This commit is contained in:
parent
23edaf4412
commit
6d4b4c0de3
@ -25,6 +25,8 @@ Interface changes
|
||||
- fix --external-files: strictly never select any tracks from them, unless
|
||||
explicitly selected (this may or may not be expected)
|
||||
- --ytdl is now always enabled, even for libmpv
|
||||
- add a number of --audio-resample-* options, which should from now on be
|
||||
used instead of --af-defaults=lavrresample:...
|
||||
--- mpv 0.28.0 ---
|
||||
- rename --hwdec=mediacodec option to mediacodec-copy, to reflect
|
||||
conventions followed by other hardware video decoding APIs
|
||||
|
@ -1441,16 +1441,6 @@ Audio
|
||||
want. For example, most A/V receivers connected via HDMI and that can
|
||||
do 7.1 would be served by: ``--audio-channels=7.1,5.1,stereo``
|
||||
|
||||
``--audio-normalize-downmix=<yes|no>``
|
||||
Enable/disable normalization if surround audio is downmixed to stereo
|
||||
(default: no). If this is disabled, downmix can cause clipping. If it's
|
||||
enabled, the output might be too silent. It depends on the source audio.
|
||||
|
||||
Technically, this changes the ``normalize`` suboption of the
|
||||
``lavrresample`` audio filter, which performs the downmixing.
|
||||
|
||||
If downmix happens outside of mpv for some reason, this has no effect.
|
||||
|
||||
``--audio-display=<no|attachment>``
|
||||
Setting this option to ``attachment`` (default) will display image
|
||||
attachments (e.g. album cover art) when playing audio files. It will
|
||||
@ -3453,6 +3443,44 @@ Software Scaler
|
||||
``--sws-cvs=<v>``
|
||||
Software scaler chroma vertical shifting. See ``--sws-scaler``.
|
||||
|
||||
Audio Resampler
|
||||
---------------
|
||||
|
||||
This controls the default options of any resampling done by mpv (but not within
|
||||
libavfilter, within the system audio API resampler, or any other places).
|
||||
|
||||
It also sets the defaults for the ``lavrresample`` audio filter.
|
||||
|
||||
``--audio-resample-filter-size=<length>``
|
||||
Length of the filter with respect to the lower sampling rate. (default:
|
||||
16)
|
||||
|
||||
``--audio-resample-phase-shift=<count>``
|
||||
Log2 of the number of polyphase entries. (..., 10->1024, 11->2048,
|
||||
12->4096, ...) (default: 10->1024)
|
||||
|
||||
``--audio-resample-cutoff=<cutoff>``
|
||||
Cutoff frequency (0.0-1.0), default set depending upon filter length.
|
||||
|
||||
``--audio-resample-linear=<yes|no>``
|
||||
If set then filters will be linearly interpolated between polyphase
|
||||
entries. (default: no)
|
||||
|
||||
``--audio-normalize-downmix=<yes|no>``
|
||||
Enable/disable normalization if surround audio is downmixed to stereo
|
||||
(default: no). If this is disabled, downmix can cause clipping. If it's
|
||||
enabled, the output might be too quiet. It depends on the source audio.
|
||||
|
||||
Technically, this changes the ``normalize`` suboption of the
|
||||
``lavrresample`` audio filter, which performs the downmixing.
|
||||
|
||||
If downmix happens outside of mpv for some reason, or in the decoder
|
||||
(decoder downmixing), or in the audio output (system mixer), this has no
|
||||
effect.
|
||||
|
||||
``--audio-swresample-o=<string>``
|
||||
Set AVOptions on the SwrContext or AVAudioResampleContext. These should
|
||||
be documented by FFmpeg or Libav.
|
||||
|
||||
Terminal
|
||||
--------
|
||||
|
@ -86,6 +86,23 @@ struct mp_aconverter {
|
||||
bool output_eof; // queued output EOF
|
||||
};
|
||||
|
||||
#define OPT_BASE_STRUCT struct mp_resample_opts
|
||||
const struct m_sub_options resample_config = {
|
||||
.opts = (const m_option_t[]) {
|
||||
OPT_INTRANGE("audio-resample-filter-size", filter_size, 0, 0, 32),
|
||||
OPT_INTRANGE("audio-resample-phase-shift", phase_shift, 0, 0, 30),
|
||||
OPT_FLAG("audio-resample-linear", linear, 0),
|
||||
OPT_DOUBLE("audio-resample-cutoff", cutoff, M_OPT_RANGE,
|
||||
.min = 0, .max = 1),
|
||||
OPT_FLAG("audio-normalize-downmix", normalize, 0),
|
||||
OPT_KEYVALUELIST("audio-swresample-o", avopts, 0),
|
||||
{0}
|
||||
},
|
||||
.size = sizeof(struct mp_resample_opts),
|
||||
.defaults = &(const struct mp_resample_opts)MP_RESAMPLE_OPTS_DEF,
|
||||
.change_flags = UPDATE_AUDIO,
|
||||
};
|
||||
|
||||
#if HAVE_LIBAVRESAMPLE
|
||||
static double get_delay(struct mp_aconverter *p)
|
||||
{
|
||||
@ -211,12 +228,7 @@ static bool configure_lavrr(struct mp_aconverter *p, bool verbose)
|
||||
cutoff = MPMAX(1.0 - 6.5 / (p->opts->filter_size + 8), 0.80);
|
||||
av_opt_set_double(p->avrctx, "cutoff", cutoff, 0);
|
||||
|
||||
int global_normalize;
|
||||
mp_read_option_raw(p->global, "audio-normalize-downmix", &m_option_type_flag,
|
||||
&global_normalize);
|
||||
int normalize = p->opts->normalize;
|
||||
if (normalize < 0)
|
||||
normalize = global_normalize;
|
||||
#if HAVE_LIBSWRESAMPLE
|
||||
av_opt_set_double(p->avrctx, "rematrix_maxval", normalize ? 1 : 1000, 0);
|
||||
#else
|
||||
@ -628,9 +640,9 @@ struct mp_aconverter *mp_aconverter_create(struct mpv_global *global,
|
||||
p->log = log;
|
||||
p->global = global;
|
||||
|
||||
static const struct mp_resample_opts defs = MP_RESAMPLE_OPTS_DEF;
|
||||
|
||||
p->opts = opts ? opts : &defs;
|
||||
p->opts = opts;
|
||||
if (!p->opts)
|
||||
p->opts = mp_get_config_group(p, global, &resample_config);
|
||||
|
||||
p->reorder_buffer = mp_aframe_pool_create(p);
|
||||
p->out_pool = mp_aframe_pool_create(p);
|
||||
|
@ -23,9 +23,11 @@ struct mp_resample_opts {
|
||||
.filter_size = 16, \
|
||||
.cutoff = 0.0, \
|
||||
.phase_shift = 10, \
|
||||
.normalize = -1, \
|
||||
.normalize = 0, \
|
||||
}
|
||||
|
||||
extern const struct m_sub_options resample_config;
|
||||
|
||||
struct mp_aconverter *mp_aconverter_create(struct mpv_global *global,
|
||||
struct mp_log *log,
|
||||
const struct mp_resample_opts *opts);
|
||||
|
@ -63,6 +63,7 @@ static bool get_desc(struct m_obj_desc *dst, int index)
|
||||
.priv_size = af->priv_size,
|
||||
.priv_defaults = af->priv_defaults,
|
||||
.options = af->options,
|
||||
.set_defaults = af->set_defaults,
|
||||
.p = af,
|
||||
};
|
||||
return true;
|
||||
@ -170,7 +171,7 @@ static struct af_instance *af_create(struct af_stream *s, char *name,
|
||||
.out_pool = mp_audio_pool_create(af),
|
||||
};
|
||||
struct m_config *config =
|
||||
m_config_from_obj_desc_and_args(af, s->log, NULL, &desc,
|
||||
m_config_from_obj_desc_and_args(af, s->log, s->global, &desc,
|
||||
name, s->opts->af_defs, args);
|
||||
if (!config)
|
||||
goto error;
|
||||
|
@ -52,6 +52,8 @@ struct af_info {
|
||||
int priv_size;
|
||||
const void *priv_defaults;
|
||||
const struct m_option *options;
|
||||
// For m_obj_desc.set_defaults
|
||||
void (*set_defaults)(struct mpv_global *global, void *p);
|
||||
};
|
||||
|
||||
// Linked list of audio filters
|
||||
|
@ -32,6 +32,7 @@
|
||||
|
||||
#include "common/av_common.h"
|
||||
#include "common/msg.h"
|
||||
#include "options/m_config.h"
|
||||
#include "options/m_option.h"
|
||||
#include "audio/filter/af.h"
|
||||
#include "audio/fmt-conversion.h"
|
||||
@ -42,6 +43,7 @@ struct af_resample {
|
||||
int allow_detach;
|
||||
double playback_speed;
|
||||
struct mp_resample_opts opts;
|
||||
int global_normalize;
|
||||
struct mp_aconverter *converter;
|
||||
};
|
||||
|
||||
@ -142,11 +144,34 @@ static int af_open(struct af_instance *af)
|
||||
af->filter_frame = filter;
|
||||
af->filter_out = filter_out;
|
||||
|
||||
if (s->opts.normalize < 0)
|
||||
s->opts.normalize = s->global_normalize;
|
||||
|
||||
s->converter = mp_aconverter_create(af->global, af->log, &s->opts);
|
||||
|
||||
return AF_OK;
|
||||
}
|
||||
|
||||
static void set_defaults(struct mpv_global *global, void *p)
|
||||
{
|
||||
struct af_resample *s = p;
|
||||
|
||||
struct mp_resample_opts *opts = &s->opts;
|
||||
|
||||
struct mp_resample_opts *src_opts =
|
||||
mp_get_config_group(s, global, &resample_config);
|
||||
|
||||
s->global_normalize = src_opts->normalize;
|
||||
|
||||
assert(!opts->avopts); // we don't set a default value, so it must be NULL
|
||||
|
||||
*opts = *src_opts;
|
||||
|
||||
opts->avopts = NULL;
|
||||
struct m_option dummy = {.type = &m_option_type_keyvalue_list};
|
||||
m_option_copy(&dummy, &opts->avopts, &src_opts->avopts);
|
||||
}
|
||||
|
||||
#define OPT_BASE_STRUCT struct af_resample
|
||||
|
||||
const struct af_info af_info_lavrresample = {
|
||||
@ -170,4 +195,5 @@ const struct af_info af_info_lavrresample = {
|
||||
OPT_KEYVALUELIST("o", opts.avopts, 0),
|
||||
{0}
|
||||
},
|
||||
.set_defaults = set_defaults,
|
||||
};
|
||||
|
@ -194,11 +194,18 @@ struct m_config *m_config_new(void *talloc_ctx, struct mp_log *log,
|
||||
return config;
|
||||
}
|
||||
|
||||
struct m_config *m_config_from_obj_desc(void *talloc_ctx, struct mp_log *log,
|
||||
struct m_obj_desc *desc)
|
||||
static struct m_config *m_config_from_obj_desc(void *talloc_ctx,
|
||||
struct mp_log *log,
|
||||
struct mpv_global *global,
|
||||
struct m_obj_desc *desc)
|
||||
{
|
||||
return m_config_new(talloc_ctx, log, desc->priv_size, desc->priv_defaults,
|
||||
desc->options);
|
||||
struct m_config *c =
|
||||
m_config_new(talloc_ctx, log, desc->priv_size, desc->priv_defaults,
|
||||
desc->options);
|
||||
c->global = global;
|
||||
if (desc->set_defaults && c->global)
|
||||
desc->set_defaults(c->global, c->optstruct);
|
||||
return c;
|
||||
}
|
||||
|
||||
// Like m_config_from_obj_desc(), but don't allocate option struct.
|
||||
@ -260,7 +267,7 @@ struct m_config *m_config_from_obj_desc_and_args(void *ta_parent,
|
||||
struct mp_log *log, struct mpv_global *global, struct m_obj_desc *desc,
|
||||
const char *name, struct m_obj_settings *defaults, char **args)
|
||||
{
|
||||
struct m_config *config = m_config_from_obj_desc(ta_parent, log, desc);
|
||||
struct m_config *config = m_config_from_obj_desc(ta_parent, log, global, desc);
|
||||
|
||||
for (int n = 0; defaults && defaults[n].name; n++) {
|
||||
struct m_obj_settings *entry = &defaults[n];
|
||||
|
@ -123,9 +123,6 @@ struct m_config *m_config_new(void *talloc_ctx, struct mp_log *log,
|
||||
// mpv_global. Expected to be called at early init on the main m_config.
|
||||
void m_config_create_shadow(struct m_config *config);
|
||||
|
||||
struct m_config *m_config_from_obj_desc(void *talloc_ctx, struct mp_log *log,
|
||||
struct m_obj_desc *desc);
|
||||
|
||||
struct m_config *m_config_from_obj_desc_noalloc(void *talloc_ctx,
|
||||
struct mp_log *log,
|
||||
struct m_obj_desc *desc);
|
||||
|
@ -32,6 +32,7 @@ typedef struct m_option m_option_t;
|
||||
struct m_config;
|
||||
struct mp_log;
|
||||
struct mpv_node;
|
||||
struct mpv_global;
|
||||
|
||||
///////////////////////////// Options types declarations ////////////////////
|
||||
|
||||
@ -129,6 +130,10 @@ struct m_obj_desc {
|
||||
bool hidden;
|
||||
// Callback to print custom help if "help" is passed
|
||||
void (*print_help)(struct mp_log *log);
|
||||
// Callback that allows you to override the static default values. The
|
||||
// pointer p points to the struct described by options/priv_size, with
|
||||
// priv_defaults already applied. You can write to it to set any defaults.
|
||||
void (*set_defaults)(struct mpv_global *global, void *p);
|
||||
// Set by m_obj_list_find(). If the requested name is an old alias, this
|
||||
// is set to the old name (while the name field uses the new name).
|
||||
const char *replaced_name;
|
||||
|
@ -94,6 +94,8 @@ extern const struct m_sub_options angle_conf;
|
||||
extern const struct m_sub_options cocoa_conf;
|
||||
extern const struct m_sub_options android_conf;
|
||||
|
||||
extern const struct m_sub_options resample_config;
|
||||
|
||||
static const struct m_sub_options screenshot_conf = {
|
||||
.opts = image_writer_opts,
|
||||
.size = sizeof(struct image_writer_opts),
|
||||
@ -474,7 +476,6 @@ const m_option_t mp_opts[] = {
|
||||
OPT_INTRANGE("audio-samplerate", force_srate, UPDATE_AUDIO, 1000, 16*48000),
|
||||
OPT_CHANNELS("audio-channels", audio_output_channels, UPDATE_AUDIO),
|
||||
OPT_AUDIOFORMAT("audio-format", audio_output_format, UPDATE_AUDIO),
|
||||
OPT_FLAG("audio-normalize-downmix", audio_normalize, UPDATE_AUDIO),
|
||||
OPT_DOUBLE("speed", playback_speed, M_OPT_RANGE, .min = 0.01, .max = 100.0),
|
||||
|
||||
OPT_FLAG("audio-pitch-correction", pitch_correction, 0),
|
||||
@ -691,6 +692,8 @@ const m_option_t mp_opts[] = {
|
||||
|
||||
OPT_STRING("record-file", record_file, M_OPT_FILE),
|
||||
|
||||
OPT_SUBSTRUCT("", resample_opts, resample_config, 0),
|
||||
|
||||
OPT_SUBSTRUCT("", input_opts, input_config, 0),
|
||||
|
||||
OPT_SUBSTRUCT("", vo, vo_sub_opts, 0),
|
||||
|
@ -275,7 +275,6 @@ typedef struct MPOpts {
|
||||
|
||||
struct m_channels audio_output_channels;
|
||||
int audio_output_format;
|
||||
int audio_normalize;
|
||||
int force_srate;
|
||||
double playback_speed;
|
||||
int pitch_correction;
|
||||
@ -331,6 +330,8 @@ typedef struct MPOpts {
|
||||
|
||||
int wingl_dwm_flush;
|
||||
|
||||
struct mp_resample_opts *resample_opts;
|
||||
|
||||
struct gl_video_opts *gl_video_opts;
|
||||
struct angle_opts *angle_opts;
|
||||
struct opengl_opts *opengl_opts;
|
||||
|
Loading…
Reference in New Issue
Block a user