[vlc-devel] [PATCH 15/16] pulse: handle AUDIO_CHANNELS_TYPE_AMBISONICS

Rémi Denis-Courmont remi at remlab.net
Tue Jul 11 04:00:47 CEST 2017


Le 10 juillet 2017 21:00:20 GMT+08:00, Thomas Guillem <thomas at gllm.fr> a écrit :
>
>
>
>On Fri, Jul 7, 2017, at 17:16, Rémi Denis-Courmont wrote:
>> Le 7 juillet 2017 17:03:01 GMT+03:00, Thomas Guillem <thomas at gllm.fr>
>a écrit :>> ---
>>> 
>>>  modules/audio_output/pulse.c | 90
>+++++++++++++++++++++++++++++++++++++++++++-
>>> >>  1 file changed, 89 insertions(+), 1 deletion(-)
>>> 
>>> 
>>> 
>>> diff --git a/modules/audio_output/pulse.c
>b/modules/audio_output/pulse.c
>>> >> index ac1254c8b9..ccec8df8f4 100644
>>> 
>>> --- a/modules/audio_output/pulse.c
>>> 
>>> +++ b/modules/audio_output/pulse.c
>>> 
>>> @@ -74,6 +74,10 @@ struct aout_sys_t
>>> 
>>>      pa_stream_flags_t flags_force; /**< Forced flags (stream must
>be NULL) */
>>> >>      char *sink_force; /**< Forced sink name (stream must be
>NULL) */
>>> >>  
>>> 
>>> +    vlc_fourcc_t fourcc;
>>> 
>>> +    uint8_t chans_table[AOUT_CHAN_MAX];
>>> 
>>> +    uint8_t chans_to_reorder;
>>> 
>>> +
>>> 
>>>      struct sink *sinks; /**< Locally-cached list of sinks */
>>> 
>>>  };
>>> 
>>>  
>>> 
>>> @@ -490,6 +494,11 @@ static void Play(audio_output_t *aout, block_t
>*block)
>>> >>      aout_sys_t *sys = aout->sys;
>>> 
>>>      pa_stream *s = sys->stream;
>>> 
>>>  
>>> 
>>> +    if (sys->chans_to_reorder)
>>> 
>>> +        aout_ChannelReorder(block->p_buffer, block->i_buffer,
>>> 
>>> +                            sys->chans_to_reorder,
>sys->chans_table,
>>> >> +                            sys->fourcc);
>>> 
>>> +
>>> 
>>>      const void *ptr = data_convert(&block);
>>> 
>>>      if (unlikely(ptr == NULL))
>>> 
>>>          return;
>>> 
>>> @@ -687,6 +696,36 @@ static const char *str_map(const char *key,
>const char *const table[][2],
>>> >>       return (r != NULL) ? r[1] : NULL;
>>> 
>>>  }
>>> 
>>>  
>>> 
>>> +static int channel_map_pulse_to_vlc(pa_channel_position_t map)
>>> 
>>> +{
>>> 
>>> +    static_assert(AOUT_CHAN_MAX == 9, "Missing channels");
>>> 
>>> +
>>> 
>>> +    switch (map)
>>> 
>>> +    {
>>> 
>>> +        case PA_CHANNEL_POSITION_FRONT_LEFT:
>>> 
>>> +            return AOUT_CHAN_LEFT;
>>> 
>>> +        case PA_CHANNEL_POSITION_FRONT_RIGHT:
>>> 
>>> +            return AOUT_CHAN_RIGHT;
>>> 
>>> +        case PA_CHANNEL_POSITION_SIDE_LEFT:
>>> 
>>> +            return AOUT_CHAN_MIDDLELEFT;
>>> 
>>> +        case PA_CHANNEL_POSITION_SIDE_RIGHT:
>>> 
>>> +            return AOUT_CHAN_MIDDLERIGHT;
>>> 
>>> +        case PA_CHANNEL_POSITION_REAR_LEFT:
>>> 
>>> +            return AOUT_CHAN_REARLEFT;
>>> 
>>> +        case PA_CHANNEL_POSITION_REAR_RIGHT:
>>> 
>>> +            return AOUT_CHAN_REARRIGHT;
>>> 
>>> +        case PA_CHANNEL_POSITION_REAR_CENTER:
>>> 
>>> +            return AOUT_CHAN_REARCENTER;
>>> 
>>> +        case PA_CHANNEL_POSITION_LFE:
>>> 
>>> +            return AOUT_CHAN_LFE;
>>> 
>>> +        case PA_CHANNEL_POSITION_MONO:
>>> 
>>> +        case PA_CHANNEL_POSITION_FRONT_CENTER:
>>> 
>>> +            return AOUT_CHAN_CENTER;
>>> 
>>> +        default:
>>> 
>>> +            return 0;
>>> 
>>> +    }
>>> 
>>> +}
>>> 
>>> +
>>> 
>>>  /**
>>> 
>>>   * Create a PulseAudio playback stream, a.k.a. a sink input.
>>> 
>>>   */
>>> 
>>> @@ -804,6 +843,7 @@ static int Start(audio_output_t *aout,
>audio_sample_format_t *restrict fmt)
>>> >>  
>>> 
>>>      if (encoding != PA_ENCODING_PCM)
>>> 
>>>      {
>>> 
>>> +        assert(fmt->channels_type == AUDIO_CHANNELS_TYPE_PHYSICAL);
>>> >>          pa_format_info_set_channels(formatv, ss.channels);
>>> 
>>>  
>>> 
>>>          /* FIX flags are only permitted for PCM, and there is no
>way to pass
>>> >> @@ -812,7 +852,7 @@ static int Start(audio_output_t *aout,
>audio_sample_format_t *restrict fmt)
>>> >>                   | PA_STREAM_FIX_RATE
>>> 
>>>                   | PA_STREAM_FIX_CHANNELS);
>>> 
>>>      }
>>> 
>>> -    else
>>> 
>>> +    else if (fmt->channels_type == AUDIO_CHANNELS_TYPE_PHYSICAL)
>>> >>      {
>>> 
>>>          /* Channel mapping (order defined in vlc_aout.h) */
>>> 
>>>          struct pa_channel_map map;
>>> 
>>> @@ -861,6 +901,19 @@ static int Start(audio_output_t *aout,
>audio_sample_format_t *restrict fmt)
>>> >>          pa_format_info_set_channels(formatv, ss.channels);
>>> 
>>>          pa_format_info_set_channel_map(formatv, &map);
>>> 
>>>      }
>>> 
>>> +    else
>>> 
>>> +    {   /* AUDIO_CHANNELS_TYPE_AMBISONICS */
>>> 
>>> +        fmt->channels_type = AUDIO_CHANNELS_TYPE_PHYSICAL;
>>> 
>>> +
>>> 
>>> +        /* Use the channel layout of the sink and override the
>current one.
>>> >> +         * This new layout be will used to configure the
>ambisonics filter. */
>>> >> +        flags |= PA_STREAM_FIX_CHANNELS;
>>> 
>>> +
>>> 
>>> +        /* Setup low latency in order to quickly react to
>ambisonics filters
>>> >> +         * viewpoint changes. */
>>> 
>>> +        flags |= PA_STREAM_ADJUST_LATENCY;
>>> 
>>> +        attr.tlength = pa_usec_to_bytes(2 * AOUT_MIN_PREPARE_TIME,
>&ss);
>>> >> +    }
>>> 
>>>  
>>> 
>>>      /* Create a playback stream */
>>> 
>>>      pa_proplist *props = pa_proplist_new();
>>> 
>>> @@ -934,9 +987,44 @@ static int Start(audio_output_t *aout,
>audio_sample_format_t *restrict fmt)
>>> >>          fmt->i_rate = spec->rate;
>>> 
>>>      }
>>> 
>>>  
>>> 
>>> +    if (flags & PA_STREAM_FIX_CHANNELS)
>>> 
>>> +    {
>>> 
>>> +        const pa_channel_map *map = pa_stream_get_channel_map(s);
>>> >> +        assert(map != NULL);
>>> 
>>> +
>>> 
>>> +        const char *name = pa_channel_map_to_name(map);
>>> 
>>> +        msg_Info(aout, "using %s channel map", (name != NULL) ?
>name : "?");
>>> >> +
>>> 
>>> +        uint8_t chans_out_count = 0;
>>> 
>>> +        uint32_t chans_out[AOUT_CHAN_MAX];
>>> 
>>> +        fmt->i_physical_channels = 0;
>>> 
>>> +        for (uint8_t i = 0; i < map->channels; ++i)
>>> 
>>> +        {
>>> 
>>> +            int vlcchan = channel_map_pulse_to_vlc(map->map[i]);
>>> >> +            if (vlcchan != 0)
>>> 
>>> +            {
>>> 
>>> +                chans_out[chans_out_count++] = vlcchan;
>>> 
>>> +                assert(chans_out_count <= AOUT_CHAN_MAX);
>>> 
>>> +                fmt->i_physical_channels |= vlcchan;
>>> 
>>> +            }
>>> 
>>> +        }
>>> 
>>> +        if (chans_out_count != map->channels)
>>> 
>>> +            msg_Warn(aout, "%u channels won't be mapped",
>>> 
>>> +                     map->channels - chans_out_count);
>>> 
>>> +        fmt->i_original_channels = fmt->i_physical_channels;
>>> 
>>> +        aout_FormatPrepare(fmt);
>>> 
>>> +
>>> 
>>> +        sys->chans_to_reorder =
>>> 
>>> +            aout_CheckChannelReorder(NULL, chans_out,
>fmt->i_physical_channels,
>>> >> +                                     sys->chans_table);
>>> 
>>> +    }
>>> 
>>> +    else
>>> 
>>> +        sys->chans_to_reorder = 0;
>>> 
>>> +
>>> 
>>>      stream_buffer_attr_cb(s, aout);
>>> 
>>>      stream_moved_cb(s, aout);
>>> 
>>>      pa_threaded_mainloop_unlock(sys->mainloop);
>>> 
>>> +    sys->fourcc = fmt->i_format;
>>> 
>>>  
>>> 
>>>      return VLC_SUCCESS; 
>>> 
>> 
>> Why do you impose the channel order here?!
>
>I use the current channel layout of the pulse stream. The ambisonics
>renderer need the output channel layout untouched since the rendering
>algorithm depend of the channel layout.
>>  -- 
>>  Rémi Denis-Courmont
>>  Typed on an inconvenient virtual keyboard 
>> _________________________________________________
>> vlc-devel mailing list
>> To unsubscribe or modify your subscription options:
>> https://mailman.videolan.org/listinfo/vlc-devel

Also, not sure fix flags work well, if at all, with changing sinks (or with changing card profile) while playing. Not very good idea on output side, AFAICT.
-- 
Rémi Denis-Courmont
Typed on an inconvenient virtual keyboard
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/vlc-devel/attachments/20170711/1ce2f082/attachment.html>


More information about the vlc-devel mailing list