[vlc-commits] [Git][videolan/vlc][master] 14 commits: aout: split aout_PrepareStereoMode

Jean-Baptiste Kempf gitlab at videolan.org
Wed May 19 10:33:00 UTC 2021



Jean-Baptiste Kempf pushed to branch master at VideoLAN / VLC


Commits:
dd037e4a by Thomas Guillem at 2021-05-19T10:16:54+00:00
aout: split aout_PrepareStereoMode

 - aout_PrepareStereoMode() prepares the "stereo-mode" var list and return the
default mode.
 - aout_HasStereoMode() returns true if a mode is available (in "stereo-mode" var list)
 - aout_UpdateStereo() does the actual changes.

No functional changes. This will be used by next commits.

- - - - -
9c67cd41 by Thomas Guillem at 2021-05-19T10:16:54+00:00
aout: add --mix-mode option

- - - - -
de2e530b by Thomas Guillem at 2021-05-19T10:16:54+00:00
aout: move headphones mode from stereo to mix mode

The aout->current_sink_info.headphones special case is handled after the
aout is started. At this point, only the filters need to be updated (via
filters_cfg).

- - - - -
d51f44af by Thomas Guillem at 2021-05-19T10:16:54+00:00
aout: print precise channels for the mix-mode menu

Example:
Original: Ambisonics
Original: 3F2M/LFE

5.1: 3F2R/LFE
7.1: 3F2M2R/LFE

- - - - -
483c3c7e by Thomas Guillem at 2021-05-19T10:16:54+00:00
aout: only propose original and binaural for ambisonics

- - - - -
72ee0103 by Thomas Guillem at 2021-05-19T10:16:54+00:00
aout: don't propose binaural mix mode if no module can handle it

- - - - -
de1e6c60 by Thomas Guillem at 2021-05-19T10:16:54+00:00
aout: use only stereo-mode for stereo

- - - - -
f54b115a by Thomas Guillem at 2021-05-19T10:16:54+00:00
aout: prepare the stereo-mode before starting the aout

This will allow to change aout->mixer_format before starting the aout,
cf. next commit.

- - - - -
3b32be66 by Thomas Guillem at 2021-05-19T10:16:54+00:00
aout: change LEFT/RIGHT fmt from aout_UpdateStereoMode

- - - - -
aa22f0f1 by Thomas Guillem at 2021-05-19T10:16:54+00:00
aout: assert than we can't apply both stereo and mix mode

- - - - -
1a4a91f9 by Thomas Guillem at 2021-05-19T10:16:54+00:00
aout: use a new chan_mode for binaural

Instead of using a custom cfg with an extra "audio filter".

i_chan_mode is already used by "audio converter" for dolbystereo.

The spatialaudio "audio filter" is converted to an "audio converter".
Such type of modules are loaded automatically when a conversion is needed
(the chan_mode conversion). Since this module is now an "audio
converter", don't override in/out fmt, but test for in/out fmt
compatibility.

- - - - -
ec53b544 by Thomas Guillem at 2021-05-19T10:16:54+00:00
spatialaudio: remove the "headphones" option

- - - - -
bdfc2a3b by Thomas Guillem at 2021-05-19T10:16:54+00:00
qt: add "mix-mode" menu

- - - - -
89cc76ca by Thomas Guillem at 2021-05-19T10:16:54+00:00
qt: display "mix-mode" or "stereo-mode" menu

But not both.
If one has entries, the other ones has 0 entries (and is disabled).

- - - - -


11 changed files:

- include/vlc_aout.h
- include/vlc_es.h
- modules/audio_filter/channel_mixer/spatialaudio.cpp
- modules/gui/qt/menus/menus.cpp
- modules/gui/qt/player/player_controller.cpp
- modules/gui/qt/player/player_controller.hpp
- modules/gui/qt/player/player_controller_p.hpp
- src/audio_output/aout_internal.h
- src/audio_output/filters.c
- src/audio_output/output.c
- src/libvlc-module.c


Changes:

=====================================
include/vlc_aout.h
=====================================
@@ -97,9 +97,16 @@
 #define AOUT_VAR_CHAN_LEFT          3
 #define AOUT_VAR_CHAN_RIGHT         4
 #define AOUT_VAR_CHAN_DOLBYS        5
-#define AOUT_VAR_CHAN_HEADPHONES    6
+/* deprecated: AOUT_VAR_CHAN_HEADPHONES 6, use AOUT_MIX_MODE_BINAURAL */
 #define AOUT_VAR_CHAN_MONO          7
 
+#define AOUT_MIX_MODE_UNSET         0
+#define AOUT_MIX_MODE_STEREO        1
+#define AOUT_MIX_MODE_BINAURAL      2
+#define AOUT_MIX_MODE_4_0           3
+#define AOUT_MIX_MODE_5_1           4
+#define AOUT_MIX_MODE_7_1           5
+
 /*****************************************************************************
  * Main audio output structures
  *****************************************************************************/


=====================================
include/vlc_es.h
=====================================
@@ -170,6 +170,7 @@ static const uint16_t vlc_chan_maps[] =
 /* Values available for i_chan_mode only */
 #define AOUT_CHANMODE_DUALMONO    0x1
 #define AOUT_CHANMODE_DOLBYSTEREO 0x2
+#define AOUT_CHANMODE_BINAURAL    0x4
 
 /**
  * Picture orientation.


=====================================
modules/audio_filter/channel_mixer/spatialaudio.cpp
=====================================
@@ -43,18 +43,12 @@
 #include <spatialaudio/Ambisonics.h>
 #include <spatialaudio/SpeakersBinauralizer.h>
 
-#define CFG_PREFIX "spatialaudio-"
-
 #define DEFAULT_HRTF_PATH "hrtfs" DIR_SEP "dodeca_and_7channel_3DSL_HRTF.sofa"
 
 #define HRTF_FILE_TEXT N_("HRTF file for the binauralization")
 #define HRTF_FILE_LONGTEXT N_("Custom HRTF (Head-related transfer function) file " \
                               "in the SOFA format.")
 
-#define HEADPHONES_TEXT N_("Headphones mode (binaural)")
-#define HEADPHONES_LONGTEXT N_("If the output is stereo, render ambisonics " \
-                               "with the binaural decoder.")
-
 static int OpenBinauralizer(vlc_object_t *p_this);
 static int Open( vlc_object_t * );
 static void Close( filter_t * );
@@ -67,14 +61,13 @@ vlc_module_begin()
     set_category(CAT_AUDIO)
     set_subcategory(SUBCAT_AUDIO_AFILTER)
     set_callback(Open)
-    add_bool(CFG_PREFIX "headphones", false,
-             HEADPHONES_TEXT, HEADPHONES_LONGTEXT, true)
+    add_obsolete_bool("spatialaudio-headphones")
     add_loadfile("hrtf-file", NULL, HRTF_FILE_TEXT, HRTF_FILE_LONGTEXT)
     add_shortcut("ambisonics")
 
     add_submodule()
     set_shortname(N_("Binauralizer"))
-    set_capability("audio filter", 0)
+    set_capability("audio converter", 30)
     set_callback(OpenBinauralizer)
     add_shortcut("binauralizer")
 vlc_module_end()
@@ -332,8 +325,18 @@ static const struct FilterOperationInitializer {
 static int OpenBinauralizer(vlc_object_t *p_this)
 {
     filter_t *p_filter = (filter_t *)p_this;
-    audio_format_t *infmt = &p_filter->fmt_in.audio;
-    audio_format_t *outfmt = &p_filter->fmt_out.audio;
+    const audio_format_t *infmt = &p_filter->fmt_in.audio;
+    const audio_format_t *outfmt = &p_filter->fmt_out.audio;
+
+    if (infmt->i_format != VLC_CODEC_FL32 || outfmt->i_format != VLC_CODEC_FL32)
+        return VLC_EGENERIC;
+
+    if (infmt->i_rate != outfmt->i_rate)
+        return VLC_EGENERIC;
+
+    if (infmt->i_channels <= 2 || outfmt->i_channels != 2
+     || outfmt->i_chan_mode != AOUT_CHANMODE_BINAURAL)
+        return VLC_EGENERIC;
 
     filter_spatialaudio *p_sys = new(std::nothrow)filter_spatialaudio();
     if (p_sys == NULL)
@@ -395,12 +398,6 @@ static int OpenBinauralizer(vlc_object_t *p_this)
     }
     p_sys->binauralizer.Reset();
 
-    outfmt->i_format = infmt->i_format = VLC_CODEC_FL32;
-    outfmt->i_rate = infmt->i_rate;
-    outfmt->i_physical_channels = AOUT_CHANS_STEREO;
-    aout_FormatPrepare(infmt);
-    aout_FormatPrepare(outfmt);
-
     p_filter->p_sys = p_sys;
     p_filter->ops = &filter_ops.ops;
 
@@ -463,12 +460,9 @@ static int Open(vlc_object_t *p_this)
 
     msg_Dbg(p_filter, "Order: %d %d %d", p_sys->i_order, p_sys->i_nondiegetic, infmt->i_channels);
 
-    static const char *const options[] = { "headphones", NULL };
-    config_ChainParse(p_filter, CFG_PREFIX, options, p_filter->p_cfg);
-
     unsigned i_tailLength = 0;
     if (p_filter->fmt_out.audio.i_channels == 2
-     && var_InheritBool(p_filter, CFG_PREFIX "headphones"))
+     && p_filter->fmt_out.audio.i_chan_mode == AOUT_CHANMODE_BINAURAL)
     {
         p_sys->mode = filter_spatialaudio::AMBISONICS_BINAURAL_DECODER;
 


=====================================
modules/gui/qt/menus/menus.cpp
=====================================
@@ -452,7 +452,11 @@ QMenu *VLCMenuBar::AudioMenu( intf_thread_t *p_intf, QMenu * current )
             updateAudioDevice( p_intf, audioDeviceSubmenu );
         });
 
-        current->addMenu( new CheckableListMenu(qtr( "&Stereo Mode" ), THEMIM->getAudioStereoMode(), CheckableListMenu::GROUPED, current) );
+        VLCVarChoiceModel *mix_mode = THEMIM->getAudioMixMode();
+        if (mix_mode->rowCount() == 0)
+            current->addMenu( new CheckableListMenu(qtr( "&Stereo Mode" ), THEMIM->getAudioStereoMode(), CheckableListMenu::GROUPED, current) );
+        else
+            current->addMenu( new CheckableListMenu(qtr( "&Mix Mode" ), mix_mode, CheckableListMenu::GROUPED, current) );
         current->addSeparator();
 
         current->addMenu( new CheckableListMenu(qtr( "&Visualizations" ), THEMIM->getAudioVisualizations(), CheckableListMenu::GROUPED, current) );


=====================================
modules/gui/qt/player/player_controller.cpp
=====================================
@@ -296,6 +296,7 @@ static void on_player_state_changed(vlc_player_t *, enum vlc_player_state state,
             msg_Dbg( that->p_intf, "on_player_state_changed VLC_PLAYER_STATE_PLAYING");
             PlayerController::AoutPtr aout = q->getAout();
             that->m_audioStereoMode.resetObject( aout.get() );
+            that->m_audioMixMode.resetObject( aout.get() );
             that->m_audioVisualization.resetObject( aout.get() );
             break;
         }
@@ -310,6 +311,7 @@ static void on_player_state_changed(vlc_player_t *, enum vlc_player_state state,
             msg_Dbg( that->p_intf, "on_player_state_changed VLC_PLAYER_STATE_STOPPED");
 
             that->m_audioStereoMode.resetObject((audio_output_t*)nullptr);
+            that->m_audioMixMode.resetObject((audio_output_t*)nullptr);
             that->m_audioVisualization.resetObject((audio_output_t*)nullptr);
 
             /* reset the state on stop */
@@ -1019,6 +1021,7 @@ PlayerControllerPrivate::PlayerControllerPrivate(PlayerController *playercontrol
     , m_deinterlaceMode((vout_thread_t*)nullptr, "deinterlace-mode")
     , m_autoscale((vout_thread_t*)nullptr, "autoscale")
     , m_audioStereoMode((audio_output_t*)nullptr, "stereo-mode")
+    , m_audioMixMode((audio_output_t*)nullptr, "mix-mode")
     , m_audioDeviceList(m_player)
     , m_audioVisualization((audio_output_t*)nullptr, "visual")
 {
@@ -1826,6 +1829,7 @@ QABSTRACTLIST_GETTER( VLCVarChoiceModel, getCrop, m_crop)
 QABSTRACTLIST_GETTER( VLCVarChoiceModel, getDeinterlace, m_deinterlace)
 QABSTRACTLIST_GETTER( VLCVarChoiceModel, getDeinterlaceMode, m_deinterlaceMode)
 QABSTRACTLIST_GETTER( VLCVarChoiceModel, getAudioStereoMode, m_audioStereoMode)
+QABSTRACTLIST_GETTER( VLCVarChoiceModel, getAudioMixMode, m_audioMixMode)
 QABSTRACTLIST_GETTER( VLCVarChoiceModel, getAudioVisualizations, m_audioVisualization)
 
 


=====================================
modules/gui/qt/player/player_controller.hpp
=====================================
@@ -176,6 +176,7 @@ public:
     Q_PROPERTY(bool muted READ isMuted WRITE setMuted NOTIFY soundMuteChanged)
     Q_PROPERTY(AudioDeviceModel* audioDevices READ getAudioDevices CONSTANT)
     Q_PROPERTY(VLCVarChoiceModel* audioStereoMode READ getAudioStereoMode CONSTANT)
+    Q_PROPERTY(VLCVarChoiceModel* audioMixMode READ getAudioMixMode CONSTANT)
     Q_PROPERTY(VLCVarChoiceModel* audioVisualization READ getAudioVisualizations CONSTANT)
     Q_PROPERTY(bool hasAudioVisualization READ hasAudioVisualization NOTIFY hasAudioVisualizationChanged)
 
@@ -347,6 +348,7 @@ public slots:
     void setMuted( bool muted );
     AudioDeviceModel* getAudioDevices();
     VLCVarChoiceModel* getAudioStereoMode();
+    VLCVarChoiceModel* getAudioMixMode();
     VLCVarChoiceModel* getAudioVisualizations();
     bool hasAudioVisualization() const;
 


=====================================
modules/gui/qt/player/player_controller_p.hpp
=====================================
@@ -142,6 +142,7 @@ public:
 
     //aout properties
     VLCVarChoiceModel m_audioStereoMode;
+    VLCVarChoiceModel m_audioMixMode;
     float           m_volume = 0.f;
     bool            m_muted = false;
     AudioDeviceModel m_audioDeviceList;


=====================================
src/audio_output/aout_internal.h
=====================================
@@ -78,6 +78,7 @@ typedef struct
     vlc_tick_t original_pts;
 
     int requested_stereo_mode; /**< Requested stereo mode set by the user */
+    int requested_mix_mode; /**< Requested mix mode set by the user */
 
     /* Original input format and profile, won't change for the lifetime of a
      * stream (between aout_DecNew() and aout_DecDelete()). */


=====================================
src/audio_output/filters.c
=====================================
@@ -152,8 +152,7 @@ static filter_t *TryFormat (vlc_object_t *obj, vlc_fourcc_t codec,
 static int aout_FiltersPipelineCreate(vlc_object_t *obj, filter_t **filters,
                                       unsigned *count, unsigned max,
                                  const audio_sample_format_t *restrict infmt,
-                                 const audio_sample_format_t *restrict outfmt,
-                                 bool headphones)
+                                 const audio_sample_format_t *restrict outfmt)
 {
     aout_FormatsPrint (obj, "conversion:", infmt, outfmt);
     max -= *count;
@@ -207,13 +206,8 @@ static int aout_FiltersPipelineCreate(vlc_object_t *obj, filter_t **filters,
             infmt->channel_type != outfmt->channel_type ?
             "audio renderer" : "audio converter";
 
-        config_chain_t *cfg = NULL;
-        if (headphones)
-            config_ChainParseOptions(&cfg, "{headphones=true}");
         filter_t *f = aout_filter_Create(obj, NULL, filter_type, NULL,
-                                         &input, &output, cfg, true);
-        if (cfg)
-            config_ChainDestroy(cfg);
+                                         &input, &output, NULL, true);
 
         if (f == NULL)
         {
@@ -430,7 +424,7 @@ static int AppendFilter(vlc_object_t *obj, const char *type, const char *name,
 
     /* convert to the filter input format if necessary */
     if (aout_FiltersPipelineCreate (obj, filters->tab, &filters->count,
-                                    max - 1, infmt, &filter->fmt_in.audio, false))
+                                    max - 1, infmt, &filter->fmt_in.audio))
     {
         msg_Err (filter, "cannot add user %s \"%s\" (skipped)", type, name);
         filter_Close( filter );
@@ -552,8 +546,7 @@ aout_filters_t *aout_FiltersNewWithClock(vlc_object_t *obj, const vlc_clock_t *c
         /* convert to the output format (minus resampling) if necessary */
         output_format.i_rate = input_format.i_rate;
         if (aout_FiltersPipelineCreate (obj, filters->tab, &filters->count,
-                                  AOUT_MAX_FILTERS, &input_format, &output_format,
-                                  cfg->headphones))
+                                  AOUT_MAX_FILTERS, &input_format, &output_format))
         {
             msg_Warn (obj, "cannot setup audio renderer pipeline");
             /* Fallback to bitmap without any conversions */
@@ -597,15 +590,9 @@ aout_filters_t *aout_FiltersNewWithClock(vlc_object_t *obj, const vlc_clock_t *c
     }
 
     if (cfg != NULL)
-    {
         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);
-    }
-
     /* Now add user filters */
     char *str = var_InheritString (obj, "audio-filter");
     if (str != NULL)
@@ -628,7 +615,7 @@ aout_filters_t *aout_FiltersNewWithClock(vlc_object_t *obj, const vlc_clock_t *c
     /* convert to the output format (minus resampling) if necessary */
     output_format.i_rate = input_format.i_rate;
     if (aout_FiltersPipelineCreate (obj, filters->tab, &filters->count,
-                              AOUT_MAX_FILTERS, &input_format, &output_format, false))
+                              AOUT_MAX_FILTERS, &input_format, &output_format))
     {
         msg_Err (obj, "cannot setup filtering pipeline");
         goto error;


=====================================
src/audio_output/output.c
=====================================
@@ -193,6 +193,21 @@ static int StereoModeCallback (vlc_object_t *obj, const char *varname,
     return 0;
 }
 
+static int MixModeCallback (vlc_object_t *obj, const char *varname,
+                               vlc_value_t oldval, vlc_value_t newval, void *data)
+{
+    audio_output_t *aout = (audio_output_t *)obj;
+    (void)varname; (void)oldval; (void)newval; (void)data;
+
+    aout_owner_t *owner = aout_owner (aout);
+    vlc_mutex_lock (&owner->lock);
+    owner->requested_mix_mode = newval.i_int;
+    vlc_mutex_unlock (&owner->lock);
+
+    aout_RestartRequest (aout, AOUT_RESTART_STEREOMODE);
+    return 0;
+}
+
 static void aout_ChangeViewpoint(audio_output_t *, const vlc_viewpoint_t *);
 
 static int ViewpointCallback (vlc_object_t *obj, const char *var,
@@ -335,6 +350,12 @@ audio_output_t *aout_New (vlc_object_t *parent)
     var_AddCallback (aout, "stereo-mode", StereoModeCallback, NULL);
     var_Change(aout, "stereo-mode", VLC_VAR_SETTEXT, _("Stereo audio mode"));
 
+    /* Mix mode */
+    var_Create (aout, "mix-mode", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
+    owner->requested_mix_mode = var_GetInteger (aout, "mix-mode");
+    var_AddCallback (aout, "mix-mode", MixModeCallback, NULL);
+    var_Change(aout, "mix-mode", VLC_VAR_SETTEXT, _("Audio mix mode"));
+
     /* Equalizer */
     var_Create (aout, "equalizer-preamp", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT);
     var_Create (aout, "equalizer-bands", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
@@ -376,6 +397,7 @@ void aout_Destroy (audio_output_t *aout)
     var_SetFloat (aout, "volume", -1.f);
     var_DelCallback(aout, "volume", var_Copy, vlc_object_parent(aout));
     var_DelCallback (aout, "stereo-mode", StereoModeCallback, NULL);
+    var_DelCallback (aout, "mix-mode", MixModeCallback, NULL);
     aout_Release(aout);
 }
 
@@ -397,34 +419,25 @@ void aout_Release(audio_output_t *aout)
     vlc_object_delete(VLC_OBJECT(aout));
 }
 
-static void aout_PrepareStereoMode (audio_output_t *aout,
-                                    audio_sample_format_t *restrict fmt,
-                                    aout_filters_cfg_t *filters_cfg,
-                                    audio_channel_type_t input_chan_type,
-                                    unsigned i_nb_input_channels)
+static int aout_PrepareStereoMode(audio_output_t *aout,
+                                  const audio_sample_format_t *restrict fmt,
+                                  unsigned i_nb_input_channels)
 {
     aout_owner_t *owner = aout_owner (aout);
 
     /* Fill Stereo mode choices */
-    var_Change(aout, "stereo-mode", VLC_VAR_CLEARCHOICES);
     vlc_value_t val;
     const char *txt;
     val.i_int = 0;
 
-    if (!AOUT_FMT_LINEAR(fmt) || i_nb_input_channels == 1)
-        return;
+    if (!AOUT_FMT_LINEAR(fmt) || i_nb_input_channels != 2)
+        return AOUT_VAR_CHAN_UNSET;
 
-    int i_output_mode = owner->requested_stereo_mode;
-    int i_default_mode = AOUT_VAR_CHAN_UNSET;
+    int i_default_mode = owner->requested_stereo_mode;
 
     val.i_int = AOUT_VAR_CHAN_MONO;
     var_Change(aout, "stereo-mode", VLC_VAR_ADDCHOICE, val, _("Mono"));
 
-    if (i_nb_input_channels != 2)
-    {
-        val.i_int = AOUT_VAR_CHAN_UNSET;
-        var_Change(aout, "stereo-mode", VLC_VAR_ADDCHOICE, val, _("Original"));
-    }
     if (fmt->i_chan_mode & AOUT_CHANMODE_DOLBYSTEREO)
     {
         val.i_int = AOUT_VAR_CHAN_DOLBYS;
@@ -437,83 +450,204 @@ static void aout_PrepareStereoMode (audio_output_t *aout,
     }
     var_Change(aout, "stereo-mode", VLC_VAR_ADDCHOICE, val, txt);
 
-    if (i_nb_input_channels == 2)
+    if (fmt->i_chan_mode & AOUT_CHANMODE_DUALMONO)
+        i_default_mode = AOUT_VAR_CHAN_LEFT;
+    else
+        i_default_mode = val.i_int; /* Stereo or Dolby Surround */
+
+    val.i_int = AOUT_VAR_CHAN_LEFT;
+    var_Change(aout, "stereo-mode", VLC_VAR_ADDCHOICE, val, _("Left"));
+    val.i_int = AOUT_VAR_CHAN_RIGHT;
+    var_Change(aout, "stereo-mode", VLC_VAR_ADDCHOICE, val, _("Right"));
+
+    val.i_int = AOUT_VAR_CHAN_RSTEREO;
+    var_Change(aout, "stereo-mode", VLC_VAR_ADDCHOICE, val,
+               _("Reverse stereo"));
+
+    return i_default_mode;
+}
+
+static void aout_UpdateStereoMode(audio_output_t *aout, int mode,
+                                  audio_sample_format_t *restrict fmt,
+                                  aout_filters_cfg_t *filters_cfg)
+{
+    /* The user may have selected a different channels configuration. */
+    switch (mode)
     {
-        if (fmt->i_chan_mode & AOUT_CHANMODE_DUALMONO)
-            i_default_mode = AOUT_VAR_CHAN_LEFT;
-        else
-            i_default_mode = val.i_int; /* Stereo or Dolby Surround */
+        case AOUT_VAR_CHAN_RSTEREO:
+            filters_cfg->remap[AOUT_CHANIDX_LEFT] = AOUT_CHANIDX_RIGHT;
+            filters_cfg->remap[AOUT_CHANIDX_RIGHT] = AOUT_CHANIDX_LEFT;
+            break;
+        case AOUT_VAR_CHAN_STEREO:
+            break;
+        case AOUT_VAR_CHAN_LEFT:
+            filters_cfg->remap[AOUT_CHANIDX_RIGHT] = AOUT_CHANIDX_DISABLE;
+            fmt->i_physical_channels = AOUT_CHAN_CENTER;
+            aout_FormatPrepare (fmt);
+            break;
+        case AOUT_VAR_CHAN_RIGHT:
+            filters_cfg->remap[AOUT_CHANIDX_LEFT] = AOUT_CHANIDX_DISABLE;
+            fmt->i_physical_channels = AOUT_CHAN_CENTER;
+            aout_FormatPrepare (fmt);
+            break;
+        case AOUT_VAR_CHAN_DOLBYS:
+            fmt->i_chan_mode = AOUT_CHANMODE_DOLBYSTEREO;
+            break;
+        case AOUT_VAR_CHAN_MONO:
+            /* Remix all channels into one */
+            for (size_t i = 0; i < AOUT_CHANIDX_MAX; ++ i)
+                filters_cfg->remap[i] = AOUT_CHANIDX_LEFT;
+            break;
+        default:
+            break;
+    }
 
-        val.i_int = AOUT_VAR_CHAN_LEFT;
-        var_Change(aout, "stereo-mode", VLC_VAR_ADDCHOICE, val, _("Left"));
-        val.i_int = AOUT_VAR_CHAN_RIGHT;
-        var_Change(aout, "stereo-mode", VLC_VAR_ADDCHOICE, val, _("Right"));
+    var_Change(aout, "stereo-mode", VLC_VAR_SETVALUE,
+               (vlc_value_t) { .i_int = mode});
+}
 
-        val.i_int = AOUT_VAR_CHAN_RSTEREO;
-        var_Change(aout, "stereo-mode", VLC_VAR_ADDCHOICE, val,
-                   _("Reverse stereo"));
+static bool aout_HasStereoMode(audio_output_t *aout, int mode)
+{
+    bool mode_available = false;
+    vlc_value_t *vals;
+    size_t count;
+
+    if (!var_Change(aout, "stereo-mode", VLC_VAR_GETCHOICES,
+                    &count, &vals, (char ***)NULL))
+    {
+        for (size_t i = 0; !mode_available && i < count; ++i)
+        {
+            if (vals[i].i_int == mode)
+                mode_available = true;
+        }
+        free(vals);
     }
+    return mode_available;
+}
+
+static void aout_AddMixModeChoice(audio_output_t *aout, int mode,
+                                  const char *suffix,
+                                  const audio_sample_format_t *restrict fmt)
+{
+    assert(suffix);
+    const char *text;
+    char *buffer = NULL;
 
-    if (input_chan_type == AUDIO_CHANNEL_TYPE_AMBISONICS
-     || i_nb_input_channels > 2)
+    if (fmt == NULL)
+        text = suffix;
+    else
     {
-        val.i_int = AOUT_VAR_CHAN_HEADPHONES;
-        var_Change(aout, "stereo-mode", VLC_VAR_ADDCHOICE, val,
-                   _("Headphones"));
+        const char *channels = aout_FormatPrintChannels(fmt);
+        if (asprintf(&buffer, "%s: %s", suffix, channels) < 0)
+            return;
+        text = buffer;
+    }
+
+    vlc_value_t val = { .i_int = mode };
+    var_Change(aout, "mix-mode", VLC_VAR_ADDCHOICE, val, text);
+
+    free(buffer);
+}
+
+static void aout_SetupMixModeChoices (audio_output_t *aout,
+                                      const audio_sample_format_t *restrict fmt)
+{
+    if (fmt->i_channels <= 2)
+        return;
 
-        if (aout->current_sink_info.headphones)
-            i_default_mode = AOUT_VAR_CHAN_HEADPHONES;
+    const bool has_spatialaudio = module_exists("spatialaudio");
+
+    aout_AddMixModeChoice(aout, AOUT_MIX_MODE_UNSET, _("Original"), fmt);
+
+    if (fmt->channel_type != AUDIO_CHANNEL_TYPE_AMBISONICS && has_spatialaudio)
+        aout_AddMixModeChoice(aout, AOUT_MIX_MODE_STEREO, _("Stereo"), NULL);
+
+    if (has_spatialaudio)
+        aout_AddMixModeChoice(aout, AOUT_MIX_MODE_BINAURAL, _("Binaural"), NULL);
+
+    /* Only propose Original and Binaural for Ambisonics content */
+    if (fmt->channel_type == AUDIO_CHANNEL_TYPE_AMBISONICS && has_spatialaudio)
+        return;
+
+    if (fmt->i_physical_channels != AOUT_CHANS_4_0)
+    {
+        static const audio_sample_format_t fmt_4_0 = {
+            .i_physical_channels = AOUT_CHANS_4_0,
+            .i_channels = 4,
+        };
+        aout_AddMixModeChoice(aout, AOUT_MIX_MODE_4_0, _("4.0"), &fmt_4_0);
     }
 
+    if (fmt->i_physical_channels != AOUT_CHANS_5_1)
+    {
+        static const audio_sample_format_t fmt_5_1 = {
+            .i_physical_channels = AOUT_CHANS_5_1,
+            .i_channels = 6,
+        };
+        aout_AddMixModeChoice(aout, AOUT_MIX_MODE_5_1, _("5.1"), &fmt_5_1);
+    }
+
+    if (fmt->i_physical_channels != AOUT_CHANS_7_1)
+    {
+        static const audio_sample_format_t fmt_7_1 = {
+            .i_physical_channels = AOUT_CHANS_7_1,
+            .i_channels = 8,
+        };
+        aout_AddMixModeChoice(aout, AOUT_MIX_MODE_7_1, _("7.1"), &fmt_7_1);
+    }
+}
+
+static bool aout_HasMixModeChoice(audio_output_t *aout, int mode)
+{
     bool mode_available = false;
     vlc_value_t *vals;
     size_t count;
 
-    if (!var_Change(aout, "stereo-mode", VLC_VAR_GETCHOICES,
+    if (!var_Change(aout, "mix-mode", VLC_VAR_GETCHOICES,
                     &count, &vals, (char ***)NULL))
     {
         for (size_t i = 0; !mode_available && i < count; ++i)
         {
-            if (vals[i].i_int == i_output_mode)
+            if (vals[i].i_int == mode)
                 mode_available = true;
         }
         free(vals);
     }
-    if (!mode_available)
-        i_output_mode = i_default_mode;
+    return mode_available;
+}
 
+
+static void aout_UpdateMixMode(audio_output_t *aout, int mode,
+                               audio_sample_format_t *restrict fmt)
+{
     /* The user may have selected a different channels configuration. */
-    switch (i_output_mode)
+    switch (mode)
     {
-        case AOUT_VAR_CHAN_RSTEREO:
-            filters_cfg->remap[AOUT_CHANIDX_LEFT] = AOUT_CHANIDX_RIGHT;
-            filters_cfg->remap[AOUT_CHANIDX_RIGHT] = AOUT_CHANIDX_LEFT;
+        case AOUT_MIX_MODE_UNSET:
             break;
-        case AOUT_VAR_CHAN_STEREO:
+        case AOUT_MIX_MODE_BINAURAL:
+            fmt->i_physical_channels = AOUT_CHANS_STEREO;
+            fmt->i_chan_mode = AOUT_CHANMODE_BINAURAL;
             break;
-        case AOUT_VAR_CHAN_LEFT:
-            filters_cfg->remap[AOUT_CHANIDX_RIGHT] = AOUT_CHANIDX_DISABLE;
+        case AOUT_MIX_MODE_STEREO:
+            fmt->i_physical_channels = AOUT_CHANS_STEREO;
             break;
-        case AOUT_VAR_CHAN_RIGHT:
-            filters_cfg->remap[AOUT_CHANIDX_LEFT] = AOUT_CHANIDX_DISABLE;
-            break;
-        case AOUT_VAR_CHAN_DOLBYS:
-            fmt->i_chan_mode = AOUT_CHANMODE_DOLBYSTEREO;
+        case AOUT_MIX_MODE_4_0:
+            fmt->i_physical_channels = AOUT_CHANS_4_0;
             break;
-        case AOUT_VAR_CHAN_HEADPHONES:
-            filters_cfg->headphones = true;
+        case AOUT_MIX_MODE_5_1:
+            fmt->i_physical_channels = AOUT_CHANS_5_1;
             break;
-        case AOUT_VAR_CHAN_MONO:
-            /* Remix all channels into one */
-            for (size_t i = 0; i < AOUT_CHANIDX_MAX; ++ i)
-                filters_cfg->remap[i] = AOUT_CHANIDX_LEFT;
+        case AOUT_MIX_MODE_7_1:
+            fmt->i_physical_channels = AOUT_CHANS_7_1;
             break;
         default:
             break;
     }
 
-    var_Change(aout, "stereo-mode", VLC_VAR_SETVALUE,
-               (vlc_value_t) { .i_int = i_output_mode });
+    assert(mode == AOUT_VAR_CHAN_UNSET || aout_HasMixModeChoice(aout, mode));
+
+    var_Change(aout, "mix-mode", VLC_VAR_SETVALUE, (vlc_value_t) { .i_int = mode});
 }
 
 /**
@@ -529,12 +663,14 @@ int aout_OutputNew (audio_output_t *aout)
     audio_sample_format_t *filter_fmt = &owner->filter_format;
     aout_filters_cfg_t *filters_cfg = &owner->filters_cfg;
 
-    audio_channel_type_t input_chan_type = fmt->channel_type;
     unsigned i_nb_input_channels = fmt->i_channels;
     vlc_fourcc_t formats[] = {
         fmt->i_format, 0, 0
     };
 
+    var_Change(aout, "stereo-mode", VLC_VAR_CLEARCHOICES);
+    var_Change(aout, "mix-mode", VLC_VAR_CLEARCHOICES);
+
     /* Ideally, the audio filters would be created before the audio output,
      * and the ideal audio format would be the output of the filters chain.
      * But that scheme would not really play well with digital pass-through. */
@@ -560,10 +696,12 @@ int aout_OutputNew (audio_output_t *aout)
         fmt->i_format = (fmt->i_bitspersample > 16) ? VLC_CODEC_FL32
                                                     : VLC_CODEC_S16N;
 
-        if (fmt->i_physical_channels == AOUT_CHANS_STEREO
-         && (owner->requested_stereo_mode == AOUT_VAR_CHAN_LEFT
-          || owner->requested_stereo_mode == AOUT_VAR_CHAN_RIGHT))
-            fmt->i_physical_channels = AOUT_CHAN_CENTER;
+        aout_SetupMixModeChoices(aout, fmt);
+
+        /* Prefer the user requested mode if available, otherwise, use the
+         * default one */
+        if (aout_HasMixModeChoice(aout, owner->requested_mix_mode))
+            aout_UpdateMixMode(aout, owner->requested_mix_mode, fmt);
 
         aout_FormatPrepare (fmt);
         assert (aout_FormatNbChannels(fmt) > 0);
@@ -594,6 +732,13 @@ int aout_OutputNew (audio_output_t *aout)
         }
     }
 
+    int stereo_mode =
+        aout_PrepareStereoMode(aout, fmt, i_nb_input_channels);
+
+    if (stereo_mode != AOUT_VAR_CHAN_UNSET
+     && aout_HasStereoMode(aout, stereo_mode))
+        aout_UpdateStereoMode(aout, stereo_mode, fmt, filters_cfg);
+
     aout->current_sink_info.headphones = false;
 
     vlc_mutex_lock(&owner->lock);
@@ -615,8 +760,16 @@ int aout_OutputNew (audio_output_t *aout)
     }
     assert(aout->flush && aout->play && aout->time_get && aout->pause);
 
-    aout_PrepareStereoMode (aout, fmt, filters_cfg, input_chan_type,
-                            i_nb_input_channels);
+    /* Autoselect the headphones mode if available and if the user didn't
+     * request any mode */
+    if (aout->current_sink_info.headphones
+     && owner->requested_mix_mode == AOUT_VAR_CHAN_UNSET
+     && aout_HasMixModeChoice(aout, AOUT_MIX_MODE_BINAURAL))
+    {
+        assert(fmt->i_physical_channels == AOUT_CHANS_STEREO);
+        assert(stereo_mode == AOUT_VAR_CHAN_UNSET);
+        aout_UpdateMixMode(aout, AOUT_MIX_MODE_BINAURAL, fmt);
+    }
 
     aout_FormatPrepare (fmt);
     assert (fmt->i_bytes_per_frame > 0 && fmt->i_frame_length > 0);


=====================================
src/libvlc-module.c
=====================================
@@ -190,12 +190,22 @@ static const char *const ppsz_force_dolby_descriptions[] = {
 static const int pi_stereo_mode_values[] = { AOUT_VAR_CHAN_UNSET,
     AOUT_VAR_CHAN_STEREO, AOUT_VAR_CHAN_RSTEREO,
     AOUT_VAR_CHAN_LEFT, AOUT_VAR_CHAN_RIGHT, AOUT_VAR_CHAN_DOLBYS,
-    AOUT_VAR_CHAN_HEADPHONES, AOUT_VAR_CHAN_MONO,
+    AOUT_VAR_CHAN_MONO,
 };
 static const char *const ppsz_stereo_mode_texts[] = { N_("Unset"),
     N_("Stereo"), N_("Reverse stereo"),
     N_("Left"), N_("Right"), N_("Dolby Surround"),
-    N_("Headphones"), N_("Mono"),
+    N_("Mono"),
+};
+
+#define MIX_MODE_TEXT N_("Audio mix mode")
+static const int pi_mix_mode_values[] = { 
+    AOUT_MIX_MODE_UNSET, AOUT_MIX_MODE_STEREO, AOUT_MIX_MODE_BINAURAL,
+    AOUT_MIX_MODE_4_0, AOUT_MIX_MODE_5_1, AOUT_MIX_MODE_7_1,
+};
+static const char *const ppsz_mix_mode_texts[] = {
+    N_("Unset"), N_("Stereo"), N_("Binaural"),
+    "4.0", "5.1", "7.1",
 };
 
 #define AUDIO_FILTER_TEXT N_("Audio filters")
@@ -1552,6 +1562,8 @@ vlc_module_begin ()
         change_integer_list( pi_force_dolby_values, ppsz_force_dolby_descriptions )
     add_integer( "stereo-mode", 0, STEREO_MODE_TEXT, NULL, true )
         change_integer_list( pi_stereo_mode_values, ppsz_stereo_mode_texts )
+    add_integer( "mix-mode", NULL, MIX_MODE_TEXT, MIX_MODE_TEXT, true )
+        change_integer_list( pi_mix_mode_values, ppsz_mix_mode_texts )
     add_integer( "audio-desync", 0, DESYNC_TEXT,
                  DESYNC_LONGTEXT, true )
         change_safe ()



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/e97d492a8c886ad8a91da419daef088a5ff274fd...89cc76caa790f6d834b8e3c5ff40a2994b9a4a48

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/e97d492a8c886ad8a91da419daef088a5ff274fd...89cc76caa790f6d834b8e3c5ff40a2994b9a4a48
You're receiving this email because of your account on code.videolan.org.




More information about the vlc-commits mailing list