[vlc-devel] [PATCH V2 3/8] aout: add exclusive_mode support
Thomas Guillem
thomas at gllm.fr
Fri Nov 8 18:13:09 CET 2019
- VLC_AOUT_EXCLUSIVE_ON will disable any filters/resampler/converter and will
work only if the input and output formats are compatible.
- VLC_AOUT_EXCLUSIVE_FORCED will disable any filters/resampler but will try to
adapt the input format to the output format by adding a converter
- VLC_AOUT_EXCLUSIVE_OFF will act as normal.
---
include/vlc_aout.h | 8 +++
src/audio_output/aout_internal.h | 1 +
src/audio_output/dec.c | 2 +
src/audio_output/filters.c | 85 +++++++++++++++++++++-----------
src/audio_output/output.c | 15 +++++-
src/libvlc-module.c | 19 +++++++
6 files changed, 99 insertions(+), 31 deletions(-)
diff --git a/include/vlc_aout.h b/include/vlc_aout.h
index 46022e98625..677897a0bb8 100644
--- a/include/vlc_aout.h
+++ b/include/vlc_aout.h
@@ -112,6 +112,12 @@
/* FIXME to remove once aout.h is cleaned a bit more */
#include <vlc_block.h>
+enum vlc_aout_exclusive_mode {
+ VLC_AOUT_EXCLUSIVE_OFF,
+ VLC_AOUT_EXCLUSIVE_ON,
+ VLC_AOUT_EXCLUSIVE_FORCED,
+};
+
struct vlc_audio_output_events {
void (*timing_report)(audio_output_t *, vlc_tick_t system_now, vlc_tick_t pts);
void (*volume_report)(audio_output_t *, float);
@@ -510,11 +516,13 @@ typedef struct
* binauralizer audio filter).
*/
bool headphones;
+ enum vlc_aout_exclusive_mode exclusive_mode;
} aout_filters_cfg_t;
#define AOUT_FILTERS_CFG_INIT (aout_filters_cfg_t) \
{ .remap = AOUT_CHAN_REMAP_INIT, \
.headphones = false, \
+ .exclusive_mode = VLC_AOUT_EXCLUSIVE_OFF, \
};
typedef struct aout_filters aout_filters_t;
diff --git a/src/audio_output/aout_internal.h b/src/audio_output/aout_internal.h
index a94d0864105..2959290a813 100644
--- a/src/audio_output/aout_internal.h
+++ b/src/audio_output/aout_internal.h
@@ -46,6 +46,7 @@ typedef struct
module_t *module; /**< Output plugin (or NULL if inactive) */
aout_filters_t *filters;
aout_volume_t *volume;
+ enum vlc_aout_exclusive_mode exclusive_mode;
struct
{
diff --git a/src/audio_output/dec.c b/src/audio_output/dec.c
index d89fedbf62c..0f4878e3ed2 100644
--- a/src/audio_output/dec.c
+++ b/src/audio_output/dec.c
@@ -98,6 +98,7 @@ int aout_DecNew(audio_output_t *p_aout, const audio_sample_format_t *p_format,
owner->sync.clock = clock;
owner->filters_cfg = AOUT_FILTERS_CFG_INIT;
+ owner->filters_cfg.exclusive_mode = owner->exclusive_mode;
if (aout_OutputNew (p_aout))
goto error;
aout_volume_SetFormat (owner->volume, owner->mixer_format.i_format);
@@ -164,6 +165,7 @@ static int aout_CheckReady (audio_output_t *aout)
aout_OutputDelete (aout);
owner->filter_format = owner->mixer_format = owner->input_format;
owner->filters_cfg = AOUT_FILTERS_CFG_INIT;
+ owner->filters_cfg.exclusive_mode = owner->exclusive_mode;
if (aout_OutputNew (aout))
owner->mixer_format.i_format = 0;
aout_volume_SetFormat (owner->volume,
diff --git a/src/audio_output/filters.c b/src/audio_output/filters.c
index a297f4c6974..ef8a278f43f 100644
--- a/src/audio_output/filters.c
+++ b/src/audio_output/filters.c
@@ -582,35 +582,57 @@ aout_filters_t *aout_FiltersNewWithClock(vlc_object_t *obj, const vlc_clock_t *c
assert(input_format.channel_type == AUDIO_CHANNEL_TYPE_BITMAP);
- /* parse user filter lists */
- if (var_InheritBool (obj, "audio-time-stretch"))
+ bool exclusive_forced = false;
+ if (cfg)
{
- if (AppendFilter(obj, "audio filter", "scaletempo",
- filters, &input_format, &output_format, NULL) == 0)
- filters->rate_filter = filters->tab[filters->count - 1];
+ if (cfg->exclusive_mode == VLC_AOUT_EXCLUSIVE_ON)
+ {
+ /* Exclusive mode is not possible if input and output formats don't
+ * match */
+ if (!AOUT_FMTS_IDENTICAL(&input_format, &output_format))
+ goto error;
+ return filters;
+ }
+ else if (cfg->exclusive_mode == VLC_AOUT_EXCLUSIVE_FORCED)
+ {
+ /* Forced exclusive mode is mode permissive. Allow to add visual
+ * filters and a converter, but don't insert any resamplers */
+ exclusive_forced = true;
+ }
}
- if (cfg != NULL)
+ if (!exclusive_forced)
{
- AppendRemapFilter(obj, filters, &input_format, &output_format,
- cfg->remap);
+ /* parse user filter lists */
+ if (var_InheritBool (obj, "audio-time-stretch"))
+ {
+ if (AppendFilter(obj, "audio filter", "scaletempo",
+ filters, &input_format, &output_format, NULL) == 0)
+ filters->rate_filter = filters->tab[filters->count - 1];
+ }
- if (input_format.i_channels > 2 && cfg->headphones)
- AppendFilter(obj, "audio filter", "binauralizer", filters,
- &input_format, &output_format, NULL);
- }
+ if (cfg != NULL)
+ {
+ AppendRemapFilter(obj, filters, &input_format, &output_format,
+ cfg->remap);
- /* Now add user filters */
- char *str = var_InheritString (obj, "audio-filter");
- if (str != NULL)
- {
- char *p = str, *name;
- while ((name = strsep (&p, " :")) != NULL)
+ if (input_format.i_channels > 2 && cfg->headphones)
+ AppendFilter(obj, "audio filter", "binauralizer", filters,
+ &input_format, &output_format, NULL);
+ }
+
+ /* Now add user filters */
+ char *str = var_InheritString (obj, "audio-filter");
+ if (str != NULL)
{
- AppendFilter(obj, "audio filter", name, filters,
- &input_format, &output_format, NULL);
+ char *p = str, *name;
+ while ((name = strsep (&p, " :")) != NULL)
+ {
+ AppendFilter(obj, "audio filter", name, filters,
+ &input_format, &output_format, NULL);
+ }
+ free (str);
}
- free (str);
}
char *visual = var_InheritString(obj, "audio-visual");
@@ -630,17 +652,20 @@ aout_filters_t *aout_FiltersNewWithClock(vlc_object_t *obj, const vlc_clock_t *c
input_format = output_format;
/* insert the resampler */
- output_format.i_rate = outfmt->i_rate;
- assert (AOUT_FMTS_IDENTICAL(&output_format, outfmt));
- filters->resampler = FindResampler (obj, &input_format,
- &output_format);
- if (filters->resampler == NULL && input_format.i_rate != outfmt->i_rate)
+ if (!exclusive_forced)
{
- msg_Err (obj, "cannot setup a resampler");
- goto error;
+ output_format.i_rate = outfmt->i_rate;
+ assert (AOUT_FMTS_IDENTICAL(&output_format, outfmt));
+ filters->resampler = FindResampler (obj, &input_format,
+ &output_format);
+ if (filters->resampler == NULL && input_format.i_rate != outfmt->i_rate)
+ {
+ msg_Err (obj, "cannot setup a resampler");
+ goto error;
+ }
+ if (filters->rate_filter == NULL)
+ filters->rate_filter = filters->resampler;
}
- if (filters->rate_filter == NULL)
- filters->rate_filter = filters->resampler;
return filters;
diff --git a/src/audio_output/output.c b/src/audio_output/output.c
index 4177b3bfe03..55795e83b80 100644
--- a/src/audio_output/output.c
+++ b/src/audio_output/output.c
@@ -338,6 +338,18 @@ audio_output_t *aout_New (vlc_object_t *parent)
var_Create (aout, "equalizer-bands", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
var_Create (aout, "equalizer-preset", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
+ char *exclusive_str = var_InheritString (aout, "aout-exclusive");
+ if (!exclusive_str)
+ owner->exclusive_mode = VLC_AOUT_EXCLUSIVE_OFF;
+ else if (strcmp(exclusive_str, "on") == 0)
+ owner->exclusive_mode = VLC_AOUT_EXCLUSIVE_ON;
+ else if (strcmp(exclusive_str, "forced") == 0)
+ owner->exclusive_mode = VLC_AOUT_EXCLUSIVE_FORCED;
+ else
+ owner->exclusive_mode = VLC_AOUT_EXCLUSIVE_OFF;
+
+ free (exclusive_str);
+
return aout;
}
@@ -600,7 +612,8 @@ int aout_OutputNew (audio_output_t *aout)
for (size_t i = 0; formats[i] != 0 && ret != VLC_SUCCESS; ++i)
{
filter_fmt->i_format = fmt->i_format = formats[i];
- ret = aout->start(aout, fmt, owner->exclusive_mode);
+ ret = aout->start(aout, fmt,
+ owner->exclusive_mode != VLC_AOUT_EXCLUSIVE_OFF);
}
vlc_mutex_unlock(&owner->lock);
if (ret)
diff --git a/src/libvlc-module.c b/src/libvlc-module.c
index 9dc892e82bf..1fe7a40a0af 100644
--- a/src/libvlc-module.c
+++ b/src/libvlc-module.c
@@ -124,6 +124,14 @@ static const char *const ppsz_snap_formats[] =
#define ROLE_TEXT N_("Media role")
#define ROLE_LONGTEXT N_("Media (player) role for operating system policy.")
+#define AOUT_EXCLUSIVE_TEXT N_("Exclusive mode")
+#define AOUT_EXCLUSIVE_LONGTEXT N_( \
+ "VLC will have a direct connection of the audio endpoint device. " \
+ "This mode can be used to reduce the audio latency or " \
+ "to assure that the audio stream won't be modified by the OS. " \
+ "This mode is more likely to fail if the soundcard format is not handled " \
+ "by VLC or if the audio output isn't compatible." )
+
#define AUDIO_TEXT N_("Enable audio")
#define AUDIO_LONGTEXT N_( \
"You can completely disable the audio output. The audio " \
@@ -139,6 +147,14 @@ static const char *ppsz_roles_text[] = {
N_("Accessibility"), N_("Test"),
};
+static const char *ppsz_aout_exclusive[] = {
+ "off", "on", "forced"
+};
+static const char *ppsz_aout_exclusive_text[] = {
+ N_("Off"), N_("On"),
+ N_("Forced (with audio conversion)")
+};
+
#define GAIN_TEXT N_("Audio gain")
#define GAIN_LONGTEXT N_( \
"This linear gain will be applied to outputted audio.")
@@ -1617,6 +1633,9 @@ vlc_module_begin ()
change_short('A')
add_string( "role", "video", ROLE_TEXT, ROLE_LONGTEXT, true )
change_string_list( ppsz_roles, ppsz_roles_text )
+ add_string( "aout-exclusive", "off", AOUT_EXCLUSIVE_TEXT,
+ AOUT_EXCLUSIVE_LONGTEXT, false )
+ change_string_list( ppsz_aout_exclusive, ppsz_aout_exclusive_text )
set_subcategory( SUBCAT_AUDIO_AFILTER )
add_module_list("audio-filter", "audio filter", NULL,
--
2.20.1
More information about the vlc-devel
mailing list