[vlc-devel] [PATCH V3 2/4] aout: add "audio-bitexact" option

Thomas Guillem thomas at gllm.fr
Tue Nov 26 16:31:24 CET 2019


---
 include/vlc_aout.h               |  8 +++
 src/audio_output/aout_internal.h |  1 +
 src/audio_output/dec.c           |  5 +-
 src/audio_output/filters.c       | 87 +++++++++++++++++++-------------
 src/audio_output/output.c        | 11 ++++
 src/libvlc-module.c              | 18 +++++++
 6 files changed, 94 insertions(+), 36 deletions(-)

diff --git a/include/vlc_aout.h b/include/vlc_aout.h
index 49527f30fb5..0e76923d1bd 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_bitexact_mode {
+    VLC_AOUT_BITEXACT_OFF,
+    VLC_AOUT_BITEXACT_ON,
+    VLC_AOUT_BITEXACT_CONVERT,
+};
+
 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);
@@ -504,11 +510,13 @@ typedef struct
      * binauralizer audio filter).
      */
     bool headphones;
+    enum vlc_aout_bitexact_mode bitexact_mode;
 } aout_filters_cfg_t;
 
 #define AOUT_FILTERS_CFG_INIT (aout_filters_cfg_t) \
     { .remap = AOUT_CHAN_REMAP_INIT, \
       .headphones = false, \
+      .bitexact_mode = VLC_AOUT_BITEXACT_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..29744884ca5 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_bitexact_mode bitexact_mode;
 
     struct
     {
diff --git a/src/audio_output/dec.c b/src/audio_output/dec.c
index d89fedbf62c..5d3da1211b3 100644
--- a/src/audio_output/dec.c
+++ b/src/audio_output/dec.c
@@ -89,7 +89,8 @@ int aout_DecNew(audio_output_t *p_aout, const audio_sample_format_t *p_format,
     aout_owner_t *owner = aout_owner(p_aout);
 
     /* Create the audio output stream */
-    owner->volume = aout_volume_New (p_aout, p_replay_gain);
+    if (owner->bitexact_mode == VLC_AOUT_BITEXACT_OFF)
+        owner->volume = aout_volume_New (p_aout, p_replay_gain);
 
     atomic_store_explicit(&owner->restart, 0, memory_order_relaxed);
     owner->input_profile = profile;
@@ -98,6 +99,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.bitexact_mode = owner->bitexact_mode;
     if (aout_OutputNew (p_aout))
         goto error;
     aout_volume_SetFormat (owner->volume, owner->mixer_format.i_format);
@@ -164,6 +166,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.bitexact_mode = owner->bitexact_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 168c97f707f..f162b185cdf 100644
--- a/src/audio_output/filters.c
+++ b/src/audio_output/filters.c
@@ -586,41 +586,55 @@ 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"))
+    if (cfg->bitexact_mode == VLC_AOUT_BITEXACT_ON)
     {
-        if (AppendFilter(obj, "audio filter", "scaletempo",
-                         filters, &input_format, &output_format, NULL) == 0)
-            filters->rate_filter = filters->tab[filters->count - 1];
+        /* Bit-exact mode is only possible if input and output formats are
+         * matching */
+        if (!AOUT_FMTS_IDENTICAL(&input_format, &output_format))
+            goto error;
+        /* Bypass all filters */
+        return filters;
     }
+    else if (cfg->bitexact_mode == VLC_AOUT_BITEXACT_OFF)
+    {
+        /* 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];
+        }
 
-    AppendRemapFilter(obj, filters, &input_format, &output_format,
-                      cfg->remap);
+        AppendRemapFilter(obj, filters, &input_format, &output_format,
+                          cfg->remap);
 
-    if (input_format.i_channels > 2 && cfg->headphones)
-        AppendFilter(obj, "audio filter", "binauralizer", filters,
-                     &input_format, &output_format, 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)
-    {
-        char *p = str, *name;
-        while ((name = strsep (&p, " :")) != 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");
-    if (visual != NULL && strcasecmp(visual, "none"))
-        AppendFilter(obj, "visualization", visual, filters,
-                     &input_format, &output_format, NULL);
-    free(visual);
+        char *visual = var_InheritString(obj, "audio-visual");
+        if (visual != NULL && strcasecmp(visual, "none"))
+            AppendFilter(obj, "visualization", visual, filters,
+                         &input_format, &output_format, NULL);
+        free(visual);
+    }
 
-    /* convert to the output format (minus resampling) if necessary */
+    /* Convert to the output format (minus resampling) if necessary.  */
+    assert(cfg->bitexact_mode == VLC_AOUT_BITEXACT_OFF
+        || cfg->bitexact_mode == VLC_AOUT_BITEXACT_CONVERT);
     output_format.i_rate = input_format.i_rate;
     if (aout_FiltersPipelineCreate (obj, filters->tab, &filters->count,
                               AOUT_MAX_FILTERS, &input_format, &output_format, false))
@@ -631,17 +645,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 (cfg->bitexact_mode == VLC_AOUT_BITEXACT_OFF)
     {
-        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 fe782d6e1d7..a7f0a4a7c2b 100644
--- a/src/audio_output/output.c
+++ b/src/audio_output/output.c
@@ -338,6 +338,17 @@ 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 *bitexact_str = var_InheritString (aout, "audio-bitexact");
+    if (!bitexact_str)
+        owner->bitexact_mode = VLC_AOUT_BITEXACT_OFF;
+    else if (strcmp(bitexact_str, "on") == 0)
+        owner->bitexact_mode = VLC_AOUT_BITEXACT_ON;
+    else if (strcmp(bitexact_str, "convert") == 0)
+        owner->bitexact_mode = VLC_AOUT_BITEXACT_CONVERT;
+    else
+        owner->bitexact_mode = VLC_AOUT_BITEXACT_OFF;
+    free (bitexact_str);
+
     return aout;
 }
 
diff --git a/src/libvlc-module.c b/src/libvlc-module.c
index 9dc892e82bf..36a3a704212 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 AUDIO_BITEXACT_TEXT N_("Bit-exact mode (pure mode)")
+#define AUDIO_BITEXACT_LONGTEXT N_( \
+    "'on' will disable all audio filters, even audio converters. " \
+    "This may result on audio not working if the output can't adapt to the " \
+    "input format. 'off' is the default, any filters and converters " \
+    "can be used'. 'convert' will only enable audio converters in order " \
+    "to adapt the input format to the output.")
+
 #define AUDIO_TEXT N_("Enable audio")
 #define AUDIO_LONGTEXT N_( \
     "You can completely disable the audio output. The audio " \
@@ -139,6 +147,13 @@ static const char *ppsz_roles_text[] = {
     N_("Accessibility"), N_("Test"),
 };
 
+static const char *ppsz_audio_bitexact[] = {
+    "on", "convert", "off"
+};
+static const char *ppsz_audio_bitexact_text[] = {
+    N_("On"), N_("With conversion (adapt to the output)"), N_("Off"),
+};
+
 #define GAIN_TEXT N_("Audio gain")
 #define GAIN_LONGTEXT N_( \
     "This linear gain will be applied to outputted audio.")
@@ -1619,6 +1634,9 @@ vlc_module_begin ()
         change_string_list( ppsz_roles, ppsz_roles_text )
 
     set_subcategory( SUBCAT_AUDIO_AFILTER )
+        add_string( "audio-bitexact", "off", AUDIO_BITEXACT_TEXT,
+                    AUDIO_BITEXACT_LONGTEXT, false )
+        change_string_list( ppsz_audio_bitexact, ppsz_audio_bitexact_text )
     add_module_list("audio-filter", "audio filter", NULL,
                     AUDIO_FILTER_TEXT, AUDIO_FILTER_LONGTEXT)
     set_subcategory( SUBCAT_AUDIO_VISUAL )
-- 
2.20.1



More information about the vlc-devel mailing list