[vlc-commits] aout: add support for unknown channel layout

Thomas Guillem git at videolan.org
Mon Jul 10 17:14:10 CEST 2017


vlc | branch: master | Thomas Guillem <thomas at gllm.fr> | Fri Jul  7 11:30:43 2017 +0200| [d07a089dad5d7691c1f9cefff96b53e3de4d24b3] | committer: Thomas Guillem

aout: add support for unknown channel layout

If the input doesn't have a valid channel layout, use the wave one and drop
extra channels via the trivial mixer.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=d07a089dad5d7691c1f9cefff96b53e3de4d24b3
---

 src/audio_output/aout_internal.h | 14 ++++++++++++++
 src/audio_output/dec.c           | 18 ++++++++++++++----
 src/audio_output/filters.c       | 36 ++++++++++++++++++++++++++++++++++--
 3 files changed, 62 insertions(+), 6 deletions(-)

diff --git a/src/audio_output/aout_internal.h b/src/audio_output/aout_internal.h
index 8516d4cd40..4088d1a956 100644
--- a/src/audio_output/aout_internal.h
+++ b/src/audio_output/aout_internal.h
@@ -152,6 +152,20 @@ static inline void aout_InputRequestRestart(audio_output_t *aout)
     aout_RequestRestart(aout, AOUT_RESTART_FILTERS);
 }
 
+static inline void aout_SetWavePhysicalChannels(audio_sample_format_t *fmt)
+{
+    static const uint32_t wave_channels[] = {
+        AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER,
+        AOUT_CHAN_LFE, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT,
+        AOUT_CHAN_MIDDLELEFT, AOUT_CHAN_MIDDLERIGHT, AOUT_CHAN_REARCENTER };
+
+    fmt->i_physical_channels = 0;
+    for (int i = 0; i < fmt->i_channels && i < AOUT_CHAN_MAX; ++i)
+        fmt->i_physical_channels |= wave_channels[i];
+    fmt->i_original_channels = fmt->i_physical_channels;
+    aout_FormatPrepare(fmt);
+}
+
 /* From filters.c */
 bool aout_FiltersCanResample (aout_filters_t *filters);
 
diff --git a/src/audio_output/dec.c b/src/audio_output/dec.c
index 157443635e..bceb817faf 100644
--- a/src/audio_output/dec.c
+++ b/src/audio_output/dec.c
@@ -45,11 +45,14 @@ int aout_DecNew( audio_output_t *p_aout,
                  const audio_replay_gain_t *p_replay_gain,
                  const aout_request_vout_t *p_request_vout )
 {
-    /* Sanitize audio format */
-    unsigned i_channels = aout_FormatNbChannels( p_format );
-    if( i_channels != p_format->i_channels && AOUT_FMT_LINEAR( p_format ) )
+
+    /* Sanitize audio format, input need to have a valid physical channels
+     * layout or a valid number of channels. */
+    int i_map_channels = aout_FormatNbChannels( p_format );
+    if( ( i_map_channels == 0 && p_format->i_channels == 0 )
+       || i_map_channels > AOUT_CHAN_MAX || p_format->i_channels > INPUT_CHAN_MAX )
     {
-        msg_Err( p_aout, "incompatible audio channels count with layout mask" );
+        msg_Err( p_aout, "invalid audio channels count" );
         return -1;
     }
 
@@ -82,6 +85,13 @@ int aout_DecNew( audio_output_t *p_aout,
     atomic_store (&owner->restart, 0);
     owner->input_format = *p_format;
     owner->mixer_format = owner->input_format;
+
+    if (i_map_channels == 0)
+    {
+        /* The output channel map is unknown, use the WAVE one. */
+        assert(owner->mixer_format.i_channels > 0);
+        aout_SetWavePhysicalChannels(&owner->mixer_format);
+    }
     owner->request_vout = *p_request_vout;
 
     if (aout_OutputNew (p_aout, &owner->mixer_format))
diff --git a/src/audio_output/filters.c b/src/audio_output/filters.c
index 400d6e72f7..9944d0f2e0 100644
--- a/src/audio_output/filters.c
+++ b/src/audio_output/filters.c
@@ -56,6 +56,16 @@ static filter_t *CreateFilter (vlc_object_t *obj, const char *type,
     filter->fmt_in.i_codec = infmt->i_format;
     filter->fmt_out.audio = *outfmt;
     filter->fmt_out.i_codec = outfmt->i_format;
+
+#ifndef NDEBUG
+    /* Assure that infmt/oufmt are well prepared and that channels
+     * configurations are valid*/
+    if( infmt->i_physical_channels != 0 )
+        assert( aout_FormatNbChannels( infmt ) == infmt->i_channels );
+    if( outfmt->i_physical_channels != 0 )
+        assert( aout_FormatNbChannels( outfmt ) == outfmt->i_channels );
+#endif
+
     filter->p_module = module_need (filter, type, name, false);
     if (filter->p_module == NULL)
     {
@@ -442,12 +452,34 @@ aout_filters_t *aout_FiltersNew (vlc_object_t *obj,
         }
         return filters;
     }
-    if (aout_FormatNbChannels(infmt) == 0 || aout_FormatNbChannels(outfmt) == 0)
+    if (aout_FormatNbChannels(outfmt) == 0)
     {
-        msg_Warn (obj, "No channel mask, cannot setup filters");
+        msg_Warn (obj, "No ouput channel mask, cannot setup filters");
         goto error;
     }
 
+    if (aout_FormatNbChannels(&input_format) == 0)
+    {
+        /* The input channel map is unknown, use the WAVE one and add a
+         * converter that will drop extra channels that are not handled by VLC
+         * */
+        msg_Info(obj, "unknown channel map, using the WAVE channel layout.");
+
+        assert(input_format.i_channels > 0);
+        audio_sample_format_t input_phys_format = input_format;
+        aout_SetWavePhysicalChannels(&input_phys_format);
+
+        filter_t *f = FindConverter (obj, &input_format, &input_phys_format);
+        if (f == NULL)
+        {
+            msg_Err (obj, "cannot find channel converter");
+            goto error;
+        }
+
+        input_format = input_phys_format;
+        filters->tab[filters->count++] = f;
+    }
+
     /* parse user filter lists */
     if (var_InheritBool (obj, "audio-time-stretch"))
     {



More information about the vlc-commits mailing list