[vlc-commits] [Git][videolan/vlc][master] 4 commits: aout: use container_of to get the owner

Jean-Baptiste Kempf (@jbk) gitlab at videolan.org
Sat Mar 26 11:08:24 UTC 2022



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


Commits:
a9ab2bdc by Thomas Guillem at 2022-03-26T10:41:13+00:00
aout: use container_of to get the owner

- - - - -
5e633503 by Thomas Guillem at 2022-03-26T10:41:13+00:00
aout: split aout and stream internally

This change is required for the gapless rework, to identify 2 different
streams, using the same aout APIS. The gapless stream, will be created,
if it has the same format as the previous one, and will wait in the
first Play to make a transition with the previous stream.

This is also a prerequisite for the aout/stream rework (in all aout
modules) planned for VLC 5.0.

Splitting the 2 API internally partition the decoder.c code: the decoder
should only handle the aout stream and not the aout devices (like sound,
mute, selection...).

For now, the aout reference and ownership is still kept in the decoder.c
because the aout and input_resource don't allow creating more than one
streams from one aout. This will be fixed in VLC 5.0.

- - - - -
07aa6e96 by Thomas Guillem at 2022-03-26T10:41:13+00:00
aout: remove unused variable

- - - - -
8ab9e9eb by Thomas Guillem at 2022-03-26T10:41:13+00:00
aout: move stream variables from owner to stream

And rename stream functions from aout_* to vlc_aout_stream_*.

- - - - -


4 changed files:

- src/audio_output/aout_internal.h
- src/audio_output/dec.c
- src/audio_output/output.c
- src/input/decoder.c


Changes:

=====================================
src/audio_output/aout_internal.h
=====================================
@@ -41,17 +41,15 @@ enum {
 };
 
 typedef struct aout_volume aout_volume_t;
+typedef struct vlc_aout_stream vlc_aout_stream;
 
 typedef struct
 {
     vlc_mutex_t lock;
     module_t *module; /**< Output plugin (or NULL if inactive) */
-    aout_filters_t *filters;
-    aout_volume_t *volume;
     bool bitexact;
 
-    atomic_bool drained;
-    _Atomic vlc_tick_t drain_deadline;
+    vlc_aout_stream *main_stream;
 
     struct
     {
@@ -67,44 +65,11 @@ typedef struct
         vlc_viewpoint_t value;
     } vp;
 
-    struct
-    {
-        struct vlc_clock_t *clock;
-        float rate; /**< Play-out speed rate */
-        vlc_tick_t resamp_start_drift; /**< Resampler drift absolute value */
-        int resamp_type; /**< Resampler mode (FIXME: redundant / resampling) */
-        bool discontinuity;
-        vlc_tick_t request_delay;
-        vlc_tick_t delay;
-        vlc_tick_t first_pts;
-    } sync;
-    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()). */
-    int                   input_profile;
-    audio_sample_format_t input_format;
-
-    /* Format used to configure the conversion filters. It is based on the
-     * input_format but its fourcc can be different when the module is handling
-     * codec passthrough. Indeed, in case of DTSHD->DTS or EAC3->AC3 fallback,
-     * the filter need to know which codec is handled by the output. */
-    audio_sample_format_t filter_format;
-
-    /* Output format used and modified by the module. */
-    audio_sample_format_t mixer_format;
-
-    aout_filters_cfg_t filters_cfg;
-
     struct vlc_audio_meter meter;
 
-    atomic_uint buffers_lost;
-    atomic_uint buffers_played;
-    atomic_uchar restart;
-
     vlc_atomic_rc_t rc;
 } aout_owner_t;
 
@@ -114,9 +79,15 @@ typedef struct
     aout_owner_t   owner;
 } aout_instance_t;
 
+static inline aout_instance_t *aout_instance (audio_output_t *aout)
+{
+    return container_of(aout, aout_instance_t, output);
+}
+
 static inline aout_owner_t *aout_owner (audio_output_t *aout)
 {
-    return &((aout_instance_t *)aout)->owner;
+    aout_instance_t *instance = aout_instance(aout);
+    return &instance->owner;
 }
 
 /****************************************************************************
@@ -137,7 +108,10 @@ audio_output_t *aout_New (vlc_object_t *);
 #define aout_New(a) aout_New(VLC_OBJECT(a))
 void aout_Destroy (audio_output_t *);
 
-int aout_OutputNew(audio_output_t *);
+int aout_OutputNew(audio_output_t *aout, vlc_aout_stream *stream,
+                   audio_sample_format_t *fmt, int input_profile,
+                   audio_sample_format_t *filter_fmt,
+                   aout_filters_cfg_t *filters_cfg);
 void aout_OutputDelete( audio_output_t * p_aout );
 
 vlc_audio_meter_plugin *
@@ -159,28 +133,30 @@ void aout_FormatsPrint(vlc_object_t *, const char *,
 #define AOUT_DEC_CHANGED 1
 #define AOUT_DEC_FAILED VLC_EGENERIC
 
-int aout_DecNew(audio_output_t *, const audio_sample_format_t *, int profile,
-                struct vlc_clock_t *clock, const audio_replay_gain_t *);
-void aout_DecDelete(audio_output_t *);
-int aout_DecPlay(audio_output_t *aout, block_t *block);
-void aout_DecGetResetStats(audio_output_t *, unsigned *, unsigned *);
-void aout_DecChangePause(audio_output_t *, bool b_paused, vlc_tick_t i_date);
-void aout_DecChangeRate(audio_output_t *aout, float rate);
-void aout_DecChangeDelay(audio_output_t *aout, vlc_tick_t delay);
-void aout_DecFlush(audio_output_t *);
-void aout_DecDrain(audio_output_t *);
-/* Contrary to other aout_Dec*() functions, this function can be called from
+vlc_aout_stream *vlc_aout_stream_New(audio_output_t *p_aout,
+                                     const audio_sample_format_t *p_format,
+                                     int profile, struct vlc_clock_t *clock,
+                                     const audio_replay_gain_t *p_replay_gain);
+void vlc_aout_stream_Delete(vlc_aout_stream *);
+int vlc_aout_stream_Play(vlc_aout_stream *stream, block_t *block);
+void vlc_aout_stream_GetResetStats(vlc_aout_stream *stream, unsigned *, unsigned *);
+void vlc_aout_stream_ChangePause(vlc_aout_stream *stream, bool b_paused, vlc_tick_t i_date);
+void vlc_aout_stream_ChangeRate(vlc_aout_stream *stream, float rate);
+void vlc_aout_stream_ChangeDelay(vlc_aout_stream *stream, vlc_tick_t delay);
+void vlc_aout_stream_Flush(vlc_aout_stream *stream);
+void vlc_aout_stream_Drain(vlc_aout_stream *stream);
+/* Contrary to other vlc_aout_stream_*() functions, this function can be called from
  * any threads */
-bool aout_DecIsDrained(audio_output_t *);
+bool vlc_aout_stream_IsDrained(vlc_aout_stream *stream);
+/* Called from output.c */
+void vlc_aout_stream_NotifyDrained(vlc_aout_stream *stream);
+void vlc_aout_stream_NotifyGain(vlc_aout_stream *stream, float gain);
 
-void aout_RequestRestart (audio_output_t *, unsigned);
-void aout_RequestRetiming(audio_output_t *aout, vlc_tick_t system_ts,
-                          vlc_tick_t audio_ts);
+void vlc_aout_stream_RequestRestart(vlc_aout_stream *stream, unsigned);
+void vlc_aout_stream_RequestRetiming(vlc_aout_stream *stream, vlc_tick_t system_ts,
+                                     vlc_tick_t audio_ts);
 
-static inline void aout_InputRequestRestart(audio_output_t *aout)
-{
-    aout_RequestRestart(aout, AOUT_RESTART_FILTERS);
-}
+void aout_InputRequestRestart(audio_output_t *aout);
 
 static inline void aout_SetWavePhysicalChannels(audio_sample_format_t *fmt)
 {


=====================================
src/audio_output/dec.c
=====================================
@@ -38,12 +38,64 @@
 #include "clock/clock.h"
 #include "libvlc.h"
 
+struct vlc_aout_stream
+{
+    aout_instance_t *instance;
+    aout_volume_t *volume;
+    aout_filters_t *filters;
+    aout_filters_cfg_t filters_cfg;
+
+    atomic_bool drained;
+    _Atomic vlc_tick_t drain_deadline;
+
+    struct
+    {
+        struct vlc_clock_t *clock;
+        float rate; /**< Play-out speed rate */
+        vlc_tick_t resamp_start_drift; /**< Resampler drift absolute value */
+        int resamp_type; /**< Resampler mode (FIXME: redundant / resampling) */
+        bool discontinuity;
+        vlc_tick_t request_delay;
+        vlc_tick_t delay;
+    } sync;
+    vlc_tick_t original_pts;
+
+    /* Original input format and profile, won't change for the lifetime of a
+     * stream (between vlc_aout_stream_New() and vlc_aout_stream_Delete()). */
+    int                   input_profile;
+    audio_sample_format_t input_format;
+
+    /* Format used to configure the conversion filters. It is based on the
+     * input_format but its fourcc can be different when the module is handling
+     * codec passthrough. Indeed, in case of DTSHD->DTS or EAC3->AC3 fallback,
+     * the filter need to know which codec is handled by the output. */
+    audio_sample_format_t filter_format;
+
+    /* Output format used and modified by the module. */
+    audio_sample_format_t mixer_format;
+
+    atomic_uchar restart;
+
+    atomic_uint buffers_lost;
+    atomic_uint buffers_played;
+};
+
+static inline aout_owner_t *aout_stream_owner(vlc_aout_stream *stream)
+{
+    return &stream->instance->owner;
+}
+
+static inline audio_output_t *aout_stream_aout(vlc_aout_stream *stream)
+{
+    return &stream->instance->output;
+}
 /**
  * Creates an audio output
  */
-int aout_DecNew(audio_output_t *p_aout, const audio_sample_format_t *p_format,
-                int profile, vlc_clock_t *clock,
-                const audio_replay_gain_t *p_replay_gain)
+vlc_aout_stream * vlc_aout_stream_New(audio_output_t *p_aout,
+                                      const audio_sample_format_t *p_format,
+                                      int profile, vlc_clock_t *clock,
+                                      const audio_replay_gain_t *p_replay_gain)
 {
     assert(p_aout);
     assert(p_format);
@@ -57,7 +109,7 @@ int aout_DecNew(audio_output_t *p_aout, const audio_sample_format_t *p_format,
            || i_map_channels > AOUT_CHAN_MAX || p_format->i_channels > INPUT_CHAN_MAX )
         {
             msg_Err( p_aout, "invalid audio channels count" );
-            return -1;
+            return NULL;
         }
     }
 
@@ -65,110 +117,123 @@ int aout_DecNew(audio_output_t *p_aout, const audio_sample_format_t *p_format,
     {
         msg_Err( p_aout, "excessive audio sample frequency (%u)",
                  p_format->i_rate );
-        return -1;
+        return NULL;
     }
     if( p_format->i_rate < 4000 )
     {
         msg_Err( p_aout, "too low audio sample frequency (%u)",
                  p_format->i_rate );
-        return -1;
+        return NULL;
     }
 
     aout_owner_t *owner = aout_owner(p_aout);
 
-    /* Create the audio output stream */
+    vlc_aout_stream *stream = malloc(sizeof(*stream));
+    if (stream == NULL)
+        return NULL;
+    stream->instance = aout_instance(p_aout);
+
+    stream->volume = NULL;
     if (!owner->bitexact)
-        owner->volume = aout_volume_New (p_aout, p_replay_gain);
+        stream->volume = aout_volume_New (p_aout, p_replay_gain);
 
-    atomic_store_explicit(&owner->restart, 0, memory_order_relaxed);
-    owner->input_profile = profile;
-    owner->filter_format = owner->mixer_format = owner->input_format = *p_format;
+    atomic_init(&stream->restart, 0);
+    stream->input_profile = profile;
+    stream->filter_format = stream->mixer_format = stream->input_format = *p_format;
 
-    owner->sync.clock = clock;
+    stream->sync.clock = clock;
 
-    owner->filters = NULL;
-    owner->filters_cfg = AOUT_FILTERS_CFG_INIT;
-    if (aout_OutputNew (p_aout))
+    stream->filters = NULL;
+    stream->filters_cfg = AOUT_FILTERS_CFG_INIT;
+    if (aout_OutputNew(p_aout, stream, &stream->mixer_format, stream->input_profile,
+                       &stream->filter_format, &stream->filters_cfg))
         goto error;
-    aout_volume_SetFormat (owner->volume, owner->mixer_format.i_format);
+    aout_volume_SetFormat (stream->volume, stream->mixer_format.i_format);
 
-    vlc_audio_meter_Reset(&owner->meter, &owner->mixer_format);
+    vlc_audio_meter_Reset(&owner->meter, &stream->mixer_format);
 
     if (!owner->bitexact)
     {
         /* Create the audio filtering "input" pipeline */
-        owner->filters = aout_FiltersNewWithClock(VLC_OBJECT(p_aout), clock,
-                                                  &owner->filter_format,
-                                                  &owner->mixer_format,
-                                                  &owner->filters_cfg);
-        if (owner->filters == NULL)
+        stream->filters = aout_FiltersNewWithClock(VLC_OBJECT(p_aout), clock,
+                                                   &stream->filter_format,
+                                                   &stream->mixer_format,
+                                                   &stream->filters_cfg);
+        if (stream->filters == NULL)
         {
             aout_OutputDelete (p_aout);
             vlc_audio_meter_Reset(&owner->meter, NULL);
 
 error:
-            aout_volume_Delete (owner->volume);
-            owner->volume = NULL;
-            return -1;
+            aout_volume_Delete (stream->volume);
+            stream->volume = NULL;
+            free(stream);
+            return NULL;
         }
     }
 
-    owner->sync.rate = 1.f;
-    owner->sync.resamp_type = AOUT_RESAMPLING_NONE;
-    owner->sync.discontinuity = true;
-    owner->original_pts = VLC_TICK_INVALID;
-    owner->sync.delay = owner->sync.request_delay = 0;
+    stream->sync.rate = 1.f;
+    stream->sync.resamp_type = AOUT_RESAMPLING_NONE;
+    stream->sync.discontinuity = true;
+    stream->sync.delay = stream->sync.request_delay = 0;
+    stream->original_pts = VLC_TICK_INVALID;
 
-    atomic_init (&owner->buffers_lost, 0);
-    atomic_init (&owner->buffers_played, 0);
+    atomic_init (&stream->buffers_lost, 0);
+    atomic_init (&stream->buffers_played, 0);
     atomic_store_explicit(&owner->vp.update, true, memory_order_relaxed);
-    return 0;
+
+    atomic_init(&stream->drained, false);
+    atomic_init(&stream->drain_deadline, VLC_TICK_INVALID);
+
+    return stream;
 }
 
 /**
  * Stops all plugins involved in the audio output.
  */
-void aout_DecDelete (audio_output_t *aout)
+void vlc_aout_stream_Delete (vlc_aout_stream *stream)
 {
-    aout_owner_t *owner = aout_owner (aout);
+    audio_output_t *aout = aout_stream_aout(stream);
 
-    if (owner->mixer_format.i_format)
+    if (stream->mixer_format.i_format)
     {
-        aout_DecFlush(aout);
-        if (owner->filters)
-            aout_FiltersDelete (aout, owner->filters);
+        vlc_aout_stream_Flush(stream);
+        if (stream->filters)
+            aout_FiltersDelete (aout, stream->filters);
         aout_OutputDelete (aout);
     }
-    aout_volume_Delete (owner->volume);
-    owner->volume = NULL;
+    aout_volume_Delete (stream->volume);
+    free(stream);
 }
 
-static int aout_CheckReady (audio_output_t *aout)
+static int stream_CheckReady (vlc_aout_stream *stream)
 {
-    aout_owner_t *owner = aout_owner (aout);
+    aout_owner_t *owner = aout_stream_owner(stream);
+    audio_output_t *aout = aout_stream_aout(stream);
     int status = AOUT_DEC_SUCCESS;
 
-    int restart = atomic_exchange_explicit(&owner->restart, 0,
+    int restart = atomic_exchange_explicit(&stream->restart, 0,
                                            memory_order_acquire);
     if (unlikely(restart))
     {
-        if (owner->filters)
+        if (stream->filters)
         {
-            aout_FiltersDelete (aout, owner->filters);
-            owner->filters = NULL;
+            aout_FiltersDelete (aout, stream->filters);
+            stream->filters = NULL;
         }
 
         if (restart & AOUT_RESTART_OUTPUT)
         {   /* Reinitializes the output */
             msg_Dbg (aout, "restarting output...");
-            if (owner->mixer_format.i_format)
+            if (stream->mixer_format.i_format)
                 aout_OutputDelete (aout);
-            owner->filter_format = owner->mixer_format = owner->input_format;
-            owner->filters_cfg = AOUT_FILTERS_CFG_INIT;
-            if (aout_OutputNew (aout))
-                owner->mixer_format.i_format = 0;
-            aout_volume_SetFormat (owner->volume,
-                                   owner->mixer_format.i_format);
+            stream->filter_format = stream->mixer_format = stream->input_format;
+            stream->filters_cfg = AOUT_FILTERS_CFG_INIT;
+            if (aout_OutputNew(aout, stream, &stream->mixer_format, stream->input_profile,
+                               &stream->filter_format, &stream->filters_cfg))
+                stream->mixer_format.i_format = 0;
+            aout_volume_SetFormat (stream->volume,
+                                   stream->mixer_format.i_format);
 
             /* Notify the decoder that the aout changed in order to try a new
              * suitable codec (like an HDMI audio format). However, keep the
@@ -179,41 +244,41 @@ static int aout_CheckReady (audio_output_t *aout)
         }
 
         msg_Dbg (aout, "restarting filters...");
-        owner->sync.resamp_type = AOUT_RESAMPLING_NONE;
+        stream->sync.resamp_type = AOUT_RESAMPLING_NONE;
 
-        if (owner->mixer_format.i_format && !owner->bitexact)
+        if (stream->mixer_format.i_format && !owner->bitexact)
         {
-            owner->filters = aout_FiltersNewWithClock(VLC_OBJECT(aout),
-                                                      owner->sync.clock,
-                                                      &owner->filter_format,
-                                                      &owner->mixer_format,
-                                                      &owner->filters_cfg);
-            if (owner->filters == NULL)
+            stream->filters = aout_FiltersNewWithClock(VLC_OBJECT(aout),
+                                                       stream->sync.clock,
+                                                       &stream->filter_format,
+                                                       &stream->mixer_format,
+                                                       &stream->filters_cfg);
+            if (stream->filters == NULL)
             {
                 aout_OutputDelete (aout);
-                owner->mixer_format.i_format = 0;
+                stream->mixer_format.i_format = 0;
             }
-            aout_FiltersSetClockDelay(owner->filters, owner->sync.delay);
+            aout_FiltersSetClockDelay(stream->filters, stream->sync.delay);
         }
 
         vlc_audio_meter_Reset(&owner->meter,
-                         owner->mixer_format.i_format ? &owner->mixer_format : NULL);
+                              stream->mixer_format.i_format ? &stream->mixer_format : NULL);
 
         /* TODO: This would be a good time to call clean up any video output
          * left over by an audio visualization:
         input_resource_TerminatVout(MAGIC HERE); */
     }
-    return (owner->mixer_format.i_format) ? status : AOUT_DEC_FAILED;
+    return (stream->mixer_format.i_format) ? status : AOUT_DEC_FAILED;
 }
 
 /**
  * Marks the audio output for restart, to update any parameter of the output
  * plug-in (e.g. output device or channel mapping).
  */
-void aout_RequestRestart (audio_output_t *aout, unsigned mode)
+void vlc_aout_stream_RequestRestart(vlc_aout_stream *stream, unsigned mode)
 {
-    aout_owner_t *owner = aout_owner (aout);
-    atomic_fetch_or_explicit(&owner->restart, mode, memory_order_release);
+    audio_output_t *aout = aout_stream_aout(stream);
+    atomic_fetch_or_explicit(&stream->restart, mode, memory_order_release);
     msg_Dbg (aout, "restart requested (%u)", mode);
 }
 
@@ -221,21 +286,20 @@ void aout_RequestRestart (audio_output_t *aout, unsigned mode)
  * Buffer management
  */
 
-static void aout_StopResampling (audio_output_t *aout)
+static void stream_StopResampling(vlc_aout_stream *stream)
 {
-    aout_owner_t *owner = aout_owner (aout);
-    assert(owner->filters);
+    assert(stream->filters);
 
-    owner->sync.resamp_type = AOUT_RESAMPLING_NONE;
-    aout_FiltersAdjustResampling (owner->filters, 0);
+    stream->sync.resamp_type = AOUT_RESAMPLING_NONE;
+    aout_FiltersAdjustResampling (stream->filters, 0);
 }
 
-static void aout_DecSynchronize(audio_output_t *aout, vlc_tick_t system_now,
-                                vlc_tick_t dec_pts);
-static void aout_DecSilence (audio_output_t *aout, vlc_tick_t length, vlc_tick_t pts)
+static void stream_Synchronize(vlc_aout_stream *stream, vlc_tick_t system_now,
+                               vlc_tick_t dec_pts);
+static void stream_Silence (vlc_aout_stream *stream, vlc_tick_t length, vlc_tick_t pts)
 {
-    aout_owner_t *owner = aout_owner (aout);
-    const audio_sample_format_t *fmt = &owner->mixer_format;
+    audio_output_t *aout = aout_stream_aout(stream);
+    const audio_sample_format_t *fmt = &stream->mixer_format;
     size_t frames = samples_from_vlc_tick(length, fmt->i_rate);
 
     block_t *block = block_Alloc (frames * fmt->i_bytes_per_frame
@@ -252,13 +316,13 @@ static void aout_DecSilence (audio_output_t *aout, vlc_tick_t length, vlc_tick_t
 
     const vlc_tick_t system_now = vlc_tick_now();
     const vlc_tick_t system_pts =
-       vlc_clock_ConvertToSystem(owner->sync.clock, system_now, pts,
-                                 owner->sync.rate);
+       vlc_clock_ConvertToSystem(stream->sync.clock, system_now, pts,
+                                 stream->sync.rate);
     aout->play(aout, block, system_pts);
 }
 
-static void aout_DecSynchronize(audio_output_t *aout, vlc_tick_t system_now,
-                                vlc_tick_t dec_pts)
+static void stream_Synchronize(vlc_aout_stream *stream, vlc_tick_t system_now,
+                               vlc_tick_t dec_pts)
 {
     /**
      * Depending on the drift between the actual and intended playback times,
@@ -276,48 +340,50 @@ static void aout_DecSynchronize(audio_output_t *aout, vlc_tick_t system_now,
      * all samples in the buffer will have been played. Then:
      *    pts = vlc_tick_now() + delay
      */
-    aout_owner_t *owner = aout_owner (aout);
     vlc_tick_t delay;
+    audio_output_t *aout = aout_stream_aout(stream);
 
     if (aout_TimeGet(aout, &delay) != 0)
         return; /* nothing can be done if timing is unknown */
 
-    if (owner->sync.discontinuity)
+    if (stream->sync.discontinuity)
     {
         /* Chicken-egg situation for most aout modules that can't be started
          * deferred (all except PulseAudio). These modules will start to play
          * data immediately and ignore the given play_date (that take the clock
-         * jitter into account). We don't want to let aout_RequestRetiming()
+         * jitter into account). We don't want to let vlc_aout_stream_RequestRetiming()
          * handle the first silence (from the "Early audio output" case) since
          * this function will first update the clock without taking the jitter
          * into account. Therefore, we manually insert silence that correspond
          * to the clock jitter value before updating the clock.
          */
         vlc_tick_t play_date =
-            vlc_clock_ConvertToSystem(owner->sync.clock, system_now + delay,
-                                      dec_pts, owner->sync.rate);
+            vlc_clock_ConvertToSystem(stream->sync.clock, system_now + delay,
+                                      dec_pts, stream->sync.rate);
         vlc_tick_t jitter = play_date - system_now;
         if (jitter > 0)
         {
-            aout_DecSilence (aout, jitter, dec_pts - delay);
+            stream_Silence(stream, jitter, dec_pts - delay);
             if (aout_TimeGet(aout, &delay) != 0)
                 return;
         }
     }
 
-    aout_RequestRetiming(aout, system_now + delay, dec_pts);
+    vlc_aout_stream_RequestRetiming(stream, system_now + delay, dec_pts);
 }
 
-void aout_RequestRetiming(audio_output_t *aout, vlc_tick_t system_ts,
-                          vlc_tick_t audio_ts)
+void vlc_aout_stream_RequestRetiming(vlc_aout_stream *stream, vlc_tick_t system_ts,
+                                     vlc_tick_t audio_ts)
 {
-    aout_owner_t *owner = aout_owner (aout);
-    float rate = owner->sync.rate;
+    aout_owner_t *owner = aout_stream_owner(stream);
+    audio_output_t *aout = aout_stream_aout(stream);
+
+    float rate = stream->sync.rate;
     vlc_tick_t drift =
-        vlc_clock_Update(owner->sync.clock, system_ts, audio_ts, rate);
+        vlc_clock_Update(stream->sync.clock, system_ts, audio_ts, rate);
 
     if (unlikely(drift == VLC_TICK_MAX) || owner->bitexact)
-        return; /* cf. VLC_TICK_MAX comment in aout_DecPlay() */
+        return; /* cf. VLC_TICK_MAX comment in vlc_aout_stream_Play() */
 
     /* Following calculations expect an opposite drift. Indeed,
      * vlc_clock_Update() returns a positive relative time, corresponding to
@@ -331,156 +397,157 @@ void aout_RequestRetiming(audio_output_t *aout, vlc_tick_t system_ts,
      * is not portable, not supported by some hardware and often unsafe/buggy
      * where supported. The other alternative is to flush the buffers
      * completely. */
-    if (drift > (owner->sync.discontinuity ? 0
+    if (drift > (stream->sync.discontinuity ? 0
                 : lroundf(+3 * AOUT_MAX_PTS_DELAY / rate)))
     {
-        if (!owner->sync.discontinuity)
+        if (!stream->sync.discontinuity)
             msg_Warn (aout, "playback way too late (%"PRId64"): "
                       "flushing buffers", drift);
         else
             msg_Dbg (aout, "playback too late (%"PRId64"): "
                      "flushing buffers", drift);
-        aout_DecFlush(aout);
-        aout_StopResampling (aout);
+        vlc_aout_stream_Flush(stream);
+        stream_StopResampling(stream);
 
         return; /* nothing can be done if timing is unknown */
     }
 
     /* Early audio output.
      * This is rare except at startup when the buffers are still empty. */
-    if (drift < (owner->sync.discontinuity ? 0
+    if (drift < (stream->sync.discontinuity ? 0
                 : lroundf(-3 * AOUT_MAX_PTS_ADVANCE / rate)))
     {
-        if (!owner->sync.discontinuity)
+        if (!stream->sync.discontinuity)
             msg_Warn (aout, "playback way too early (%"PRId64"): "
                       "playing silence", drift);
-        aout_DecSilence (aout, -drift, audio_ts);
+        stream_Silence(stream, -drift, audio_ts);
 
-        aout_StopResampling (aout);
-        owner->sync.discontinuity = true;
+        stream_StopResampling(stream);
+        stream->sync.discontinuity = true;
         drift = 0;
     }
 
-    if (!aout_FiltersCanResample(owner->filters))
+    if (!aout_FiltersCanResample(stream->filters))
         return;
 
     /* Resampling */
     if (drift > +AOUT_MAX_PTS_DELAY
-     && owner->sync.resamp_type != AOUT_RESAMPLING_UP)
+     && stream->sync.resamp_type != AOUT_RESAMPLING_UP)
     {
         msg_Warn (aout, "playback too late (%"PRId64"): up-sampling",
                   drift);
-        owner->sync.resamp_type = AOUT_RESAMPLING_UP;
-        owner->sync.resamp_start_drift = +drift;
+        stream->sync.resamp_type = AOUT_RESAMPLING_UP;
+        stream->sync.resamp_start_drift = +drift;
     }
     if (drift < -AOUT_MAX_PTS_ADVANCE
-     && owner->sync.resamp_type != AOUT_RESAMPLING_DOWN)
+     && stream->sync.resamp_type != AOUT_RESAMPLING_DOWN)
     {
         msg_Warn (aout, "playback too early (%"PRId64"): down-sampling",
                   drift);
-        owner->sync.resamp_type = AOUT_RESAMPLING_DOWN;
-        owner->sync.resamp_start_drift = -drift;
+        stream->sync.resamp_type = AOUT_RESAMPLING_DOWN;
+        stream->sync.resamp_start_drift = -drift;
     }
 
-    if (owner->sync.resamp_type == AOUT_RESAMPLING_NONE)
+    if (stream->sync.resamp_type == AOUT_RESAMPLING_NONE)
         return; /* Everything is fine. Nothing to do. */
 
-    if (llabs (drift) > 2 * owner->sync.resamp_start_drift)
+    if (llabs (drift) > 2 * stream->sync.resamp_start_drift)
     {   /* If the drift is ever increasing, then something is seriously wrong.
          * Cease resampling and hope for the best. */
         msg_Warn (aout, "timing screwed (drift: %"PRId64" us): "
                   "stopping resampling", drift);
-        aout_StopResampling (aout);
+        stream_StopResampling(stream);
         return;
     }
 
     /* Resampling has been triggered earlier. This checks if it needs to be
      * increased or decreased. Resampling rate changes must be kept slow for
      * the comfort of listeners. */
-    int adj = (owner->sync.resamp_type == AOUT_RESAMPLING_UP) ? +2 : -2;
+    int adj = (stream->sync.resamp_type == AOUT_RESAMPLING_UP) ? +2 : -2;
 
-    if (2 * llabs (drift) <= owner->sync.resamp_start_drift)
+    if (2 * llabs (drift) <= stream->sync.resamp_start_drift)
         /* If the drift has been reduced from more than half its initial
          * value, then it is time to switch back the resampling direction. */
         adj *= -1;
 
-    if (!aout_FiltersAdjustResampling (owner->filters, adj))
+    if (!aout_FiltersAdjustResampling (stream->filters, adj))
     {   /* Everything is back to normal: stop resampling. */
-        owner->sync.resamp_type = AOUT_RESAMPLING_NONE;
+        stream->sync.resamp_type = AOUT_RESAMPLING_NONE;
         msg_Dbg (aout, "resampling stopped (drift: %"PRId64" us)", drift);
     }
 }
 
 /*****************************************************************************
- * aout_DecPlay : filter & mix the decoded buffer
+ * vlc_aout_stream_Play : filter & mix the decoded buffer
  *****************************************************************************/
-int aout_DecPlay(audio_output_t *aout, block_t *block)
+int vlc_aout_stream_Play(vlc_aout_stream *stream, block_t *block)
 {
-    aout_owner_t *owner = aout_owner (aout);
+    aout_owner_t *owner = aout_stream_owner(stream);
+    audio_output_t *aout = aout_stream_aout(stream);
 
     assert (block->i_pts != VLC_TICK_INVALID);
 
     block->i_length = vlc_tick_from_samples( block->i_nb_samples,
-                                   owner->input_format.i_rate );
+                                   stream->input_format.i_rate );
 
-    int ret = aout_CheckReady (aout);
+    int ret = stream_CheckReady (stream);
     if (unlikely(ret == AOUT_DEC_FAILED))
         goto drop; /* Pipeline is unrecoverably broken :-( */
 
     if (block->i_flags & BLOCK_FLAG_DISCONTINUITY)
     {
-        owner->sync.discontinuity = true;
-        owner->original_pts = VLC_TICK_INVALID;
+        stream->sync.discontinuity = true;
+        stream->original_pts = VLC_TICK_INVALID;
     }
 
-    if (owner->original_pts == VLC_TICK_INVALID)
+    if (stream->original_pts == VLC_TICK_INVALID)
     {
         /* Use the original PTS for synchronization and as a play date of the
          * aout module. This PTS need to be saved here in order to use the PTS
          * of the first block that has been filtered. Indeed, aout filters may
          * need more than one block to output a new one. */
-        owner->original_pts = block->i_pts;
+        stream->original_pts = block->i_pts;
     }
 
-    if (owner->filters)
+    if (stream->filters)
     {
         if (atomic_load_explicit(&owner->vp.update, memory_order_relaxed))
         {
             vlc_mutex_lock (&owner->vp.lock);
-            aout_FiltersChangeViewpoint (owner->filters, &owner->vp.value);
+            aout_FiltersChangeViewpoint (stream->filters, &owner->vp.value);
             atomic_store_explicit(&owner->vp.update, false, memory_order_relaxed);
             vlc_mutex_unlock (&owner->vp.lock);
         }
 
-        block = aout_FiltersPlay(owner->filters, block, owner->sync.rate);
+        block = aout_FiltersPlay(stream->filters, block, stream->sync.rate);
         if (block == NULL)
             return ret;
     }
 
-    const vlc_tick_t original_pts = owner->original_pts;
-    owner->original_pts = VLC_TICK_INVALID;
+    const vlc_tick_t original_pts = stream->original_pts;
+    stream->original_pts = VLC_TICK_INVALID;
 
     /* Software volume */
-    aout_volume_Amplify (owner->volume, block);
+    aout_volume_Amplify(stream->volume, block);
 
     /* Update delay */
-    if (owner->sync.request_delay != owner->sync.delay)
+    if (stream->sync.request_delay != stream->sync.delay)
     {
-        owner->sync.delay = owner->sync.request_delay;
-        vlc_tick_t delta = vlc_clock_SetDelay(owner->sync.clock, owner->sync.delay);
-        if (owner->filters)
-            aout_FiltersSetClockDelay(owner->filters, owner->sync.delay);
+        stream->sync.delay = stream->sync.request_delay;
+        vlc_tick_t delta = vlc_clock_SetDelay(stream->sync.clock, stream->sync.delay);
+        if (stream->filters)
+            aout_FiltersSetClockDelay(stream->filters, stream->sync.delay);
         if (delta > 0)
-            aout_DecSilence (aout, delta, block->i_pts);
+            stream_Silence(stream, delta, block->i_pts);
     }
 
     /* Drift correction */
     vlc_tick_t system_now = vlc_tick_now();
-    aout_DecSynchronize(aout, system_now, original_pts);
+    stream_Synchronize(stream, system_now, original_pts);
 
     vlc_tick_t play_date =
-        vlc_clock_ConvertToSystem(owner->sync.clock, system_now, original_pts,
-                                  owner->sync.rate);
+        vlc_clock_ConvertToSystem(stream->sync.clock, system_now, original_pts,
+                                  stream->sync.rate);
     if (unlikely(play_date == VLC_TICK_MAX))
     {
         /* The clock is paused but not the output, play the audio anyway since
@@ -492,35 +559,33 @@ int aout_DecPlay(audio_output_t *aout, block_t *block)
     vlc_audio_meter_Process(&owner->meter, block, play_date);
 
     /* Output */
-    owner->sync.discontinuity = false;
+    stream->sync.discontinuity = false;
     aout->play(aout, block, play_date);
 
-    atomic_fetch_add_explicit(&owner->buffers_played, 1, memory_order_relaxed);
+    atomic_fetch_add_explicit(&stream->buffers_played, 1, memory_order_relaxed);
     return ret;
 drop:
-    owner->sync.discontinuity = true;
-    owner->original_pts = VLC_TICK_INVALID;
+    stream->sync.discontinuity = true;
+    stream->original_pts = VLC_TICK_INVALID;
     block_Release (block);
-    atomic_fetch_add_explicit(&owner->buffers_lost, 1, memory_order_relaxed);
+    atomic_fetch_add_explicit(&stream->buffers_lost, 1, memory_order_relaxed);
     return ret;
 }
 
-void aout_DecGetResetStats(audio_output_t *aout, unsigned *restrict lost,
+void vlc_aout_stream_GetResetStats(vlc_aout_stream *stream, unsigned *restrict lost,
                            unsigned *restrict played)
 {
-    aout_owner_t *owner = aout_owner (aout);
-
-    *lost = atomic_exchange_explicit(&owner->buffers_lost, 0,
+    *lost = atomic_exchange_explicit(&stream->buffers_lost, 0,
                                      memory_order_relaxed);
-    *played = atomic_exchange_explicit(&owner->buffers_played, 0,
+    *played = atomic_exchange_explicit(&stream->buffers_played, 0,
                                        memory_order_relaxed);
 }
 
-void aout_DecChangePause (audio_output_t *aout, bool paused, vlc_tick_t date)
+void vlc_aout_stream_ChangePause(vlc_aout_stream *stream, bool paused, vlc_tick_t date)
 {
-    aout_owner_t *owner = aout_owner (aout);
+    audio_output_t *aout = aout_stream_aout(stream);
 
-    if (owner->mixer_format.i_format)
+    if (stream->mixer_format.i_format)
     {
         if (aout->pause != NULL)
             aout->pause(aout, paused, date);
@@ -529,37 +594,34 @@ void aout_DecChangePause (audio_output_t *aout, bool paused, vlc_tick_t date)
     }
 }
 
-void aout_DecChangeRate(audio_output_t *aout, float rate)
+void vlc_aout_stream_ChangeRate(vlc_aout_stream *stream, float rate)
 {
-    aout_owner_t *owner = aout_owner(aout);
-
-    owner->sync.rate = rate;
+    stream->sync.rate = rate;
 }
 
-void aout_DecChangeDelay(audio_output_t *aout, vlc_tick_t delay)
+void vlc_aout_stream_ChangeDelay(vlc_aout_stream *stream, vlc_tick_t delay)
 {
-    aout_owner_t *owner = aout_owner(aout);
-
-    owner->sync.request_delay = delay;
+    stream->sync.request_delay = delay;
 }
 
-void aout_DecFlush(audio_output_t *aout)
+void vlc_aout_stream_Flush(vlc_aout_stream *stream)
 {
-    aout_owner_t *owner = aout_owner (aout);
+    audio_output_t *aout = aout_stream_aout(stream);
+    aout_owner_t *owner = aout_stream_owner(stream);
 
-    if (owner->mixer_format.i_format)
+    if (stream->mixer_format.i_format)
     {
         vlc_audio_meter_Flush(&owner->meter);
 
-        if (owner->filters)
-            aout_FiltersFlush (owner->filters);
+        if (stream->filters)
+            aout_FiltersFlush (stream->filters);
 
         aout->flush(aout);
-        vlc_clock_Reset(owner->sync.clock);
-        if (owner->filters)
-            aout_FiltersResetClock(owner->filters);
+        vlc_clock_Reset(stream->sync.clock);
+        if (stream->filters)
+            aout_FiltersResetClock(stream->filters);
 
-        if (owner->sync.delay > 0)
+        if (stream->sync.delay > 0)
         {
             /* Also reset the delay in case of a positive delay. This will
              * trigger a silence playback before the next play. Consequently,
@@ -567,60 +629,70 @@ void aout_DecFlush(audio_output_t *aout)
              * dejitter. This will allow the aout to update the master clock
              * sooner.
              */
-            vlc_clock_SetDelay(owner->sync.clock, 0);
-            if (owner->filters)
-                aout_FiltersSetClockDelay(owner->filters, 0);
-            owner->sync.request_delay = owner->sync.delay;
-            owner->sync.delay = 0;
+            vlc_clock_SetDelay(stream->sync.clock, 0);
+            if (stream->filters)
+                aout_FiltersSetClockDelay(stream->filters, 0);
+            stream->sync.request_delay = stream->sync.delay;
+            stream->sync.delay = 0;
         }
     }
 
-    atomic_store_explicit(&owner->drained, false, memory_order_relaxed);
-    atomic_store_explicit(&owner->drain_deadline, VLC_TICK_INVALID,
+    atomic_store_explicit(&stream->drained, false, memory_order_relaxed);
+    atomic_store_explicit(&stream->drain_deadline, VLC_TICK_INVALID,
                           memory_order_relaxed);
 
-    owner->sync.discontinuity = true;
-    owner->original_pts = VLC_TICK_INVALID;
+    stream->sync.discontinuity = true;
+    stream->original_pts = VLC_TICK_INVALID;
+}
+
+void vlc_aout_stream_NotifyGain(vlc_aout_stream *stream, float gain)
+{
+    aout_volume_SetVolume(stream->volume, gain);
+}
+
+void vlc_aout_stream_NotifyDrained(vlc_aout_stream *stream)
+{
+    atomic_store_explicit(&stream->drained, true, memory_order_relaxed);
 }
 
-bool aout_DecIsDrained(audio_output_t *aout)
+bool vlc_aout_stream_IsDrained(vlc_aout_stream *stream)
 {
-    aout_owner_t *owner = aout_owner (aout);
+    audio_output_t *aout = aout_stream_aout(stream);
 
     if (aout->drain == NULL)
     {
         vlc_tick_t drain_deadline =
-            atomic_load_explicit(&owner->drain_deadline, memory_order_relaxed);
+            atomic_load_explicit(&stream->drain_deadline, memory_order_relaxed);
         return drain_deadline != VLC_TICK_INVALID
             && vlc_tick_now() >= drain_deadline;
     }
     else
-        return atomic_load_explicit(&owner->drained, memory_order_relaxed);
+        return atomic_load_explicit(&stream->drained, memory_order_relaxed);
 }
 
-void aout_DecDrain(audio_output_t *aout)
+void vlc_aout_stream_Drain(vlc_aout_stream *stream)
 {
-    aout_owner_t *owner = aout_owner (aout);
+    audio_output_t *aout = aout_stream_aout(stream);
 
-    if (!owner->mixer_format.i_format)
+    if (!stream->mixer_format.i_format)
         return;
 
-    if (owner->filters)
+    if (stream->filters)
     {
-        block_t *block = aout_FiltersDrain (owner->filters);
+        block_t *block = aout_FiltersDrain (stream->filters);
         if (block)
             aout->play(aout, block, vlc_tick_now());
     }
 
     if (aout->drain)
     {
-        assert(!atomic_load_explicit(&owner->drained, memory_order_relaxed));
+        assert(!atomic_load_explicit(&stream->drained, memory_order_relaxed));
 
         aout->drain(aout);
     }
     else
     {
-        assert(atomic_load_explicit(&owner->drain_deadline,
+        assert(atomic_load_explicit(&stream->drain_deadline,
                                     memory_order_relaxed) == VLC_TICK_INVALID);
 
         vlc_tick_t drain_deadline = vlc_tick_now();
@@ -628,17 +700,17 @@ void aout_DecDrain(audio_output_t *aout)
         vlc_tick_t delay;
         if (aout_TimeGet(aout, &delay) == 0)
             drain_deadline += delay;
-        /* else the deadline is now, and aout_DecIsDrained() will return true
-         * on the first call. */
+        /* else the deadline is now, and vlc_aout_stream_IsDrained() will
+         * return true on the first call. */
 
-        atomic_store_explicit(&owner->drain_deadline, drain_deadline,
+        atomic_store_explicit(&stream->drain_deadline, drain_deadline,
                               memory_order_relaxed);
     }
 
-    vlc_clock_Reset(owner->sync.clock);
-    if (owner->filters)
-        aout_FiltersResetClock(owner->filters);
+    vlc_clock_Reset(stream->sync.clock);
+    if (stream->filters)
+        aout_FiltersResetClock(stream->filters);
 
-    owner->sync.discontinuity = true;
-    owner->original_pts = VLC_TICK_INVALID;
+    stream->sync.discontinuity = true;
+    stream->original_pts = VLC_TICK_INVALID;
 }


=====================================
src/audio_output/output.c
=====================================
@@ -66,13 +66,16 @@ static int var_CopyDevice (vlc_object_t *src, const char *name,
 static void aout_TimingNotify(audio_output_t *aout, vlc_tick_t system_ts,
                               vlc_tick_t audio_ts)
 {
-    aout_RequestRetiming(aout, system_ts, audio_ts);
+    aout_owner_t *owner = aout_owner (aout);
+    assert(owner->main_stream);
+    vlc_aout_stream_RequestRetiming(owner->main_stream, system_ts, audio_ts);
 }
 
 static void aout_DrainedNotify(audio_output_t *aout)
 {
     aout_owner_t *owner = aout_owner (aout);
-    atomic_store_explicit(&owner->drained, true, memory_order_relaxed);
+    assert(owner->main_stream);
+    vlc_aout_stream_NotifyDrained(owner->main_stream);
 }
 
 /**
@@ -151,7 +154,14 @@ out:
 
 static void aout_RestartNotify (audio_output_t *aout, unsigned mode)
 {
-    aout_RequestRestart (aout, mode);
+    aout_owner_t *owner = aout_owner (aout);
+    if (owner->main_stream)
+        vlc_aout_stream_RequestRestart(owner->main_stream, mode);
+}
+
+void aout_InputRequestRestart(audio_output_t *aout)
+{
+    aout_RestartNotify(aout, AOUT_RESTART_FILTERS);
 }
 
 static int aout_GainNotify (audio_output_t *aout, float gain)
@@ -159,8 +169,9 @@ static int aout_GainNotify (audio_output_t *aout, float gain)
     aout_owner_t *owner = aout_owner (aout);
 
     vlc_mutex_assert(&owner->lock);
-    aout_volume_SetVolume (owner->volume, gain);
     /* XXX: ideally, return -1 if format cannot be amplified */
+    if (owner->main_stream != NULL)
+        vlc_aout_stream_NotifyGain(owner->main_stream, gain);
     return 0;
 }
 
@@ -250,8 +261,7 @@ audio_output_t *aout_New (vlc_object_t *parent)
     vlc_atomic_rc_init(&owner->rc);
     vlc_audio_meter_Init(&owner->meter, aout);
 
-    atomic_init(&owner->drained, false);
-    atomic_init(&owner->drain_deadline, VLC_TICK_INVALID);
+    owner->main_stream = NULL;
 
     /* Audio output module callbacks */
     var_Create (aout, "volume", VLC_VAR_FLOAT);
@@ -665,12 +675,12 @@ static void aout_UpdateMixMode(audio_output_t *aout, int mode,
  * the codec from the mixer_format in case of DTSHD/DTS or EAC3/AC3 fallback
  * \warning The caller must NOT hold the audio output lock.
  */
-int aout_OutputNew (audio_output_t *aout)
+int aout_OutputNew(audio_output_t *aout, vlc_aout_stream *stream,
+                   audio_sample_format_t *fmt, int input_profile,
+                   audio_sample_format_t *filter_fmt,
+                   aout_filters_cfg_t *filters_cfg)
 {
     aout_owner_t *owner = aout_owner (aout);
-    audio_sample_format_t *fmt = &owner->mixer_format;
-    audio_sample_format_t *filter_fmt = &owner->filter_format;
-    aout_filters_cfg_t *filters_cfg = &owner->filters_cfg;
 
     vlc_fourcc_t formats[] = {
         fmt->i_format, 0, 0
@@ -719,7 +729,7 @@ int aout_OutputNew (audio_output_t *aout)
         switch (fmt->i_format)
         {
             case VLC_CODEC_DTS:
-                if (owner->input_profile > 0)
+                if (input_profile > 0)
                 {
                     assert(ARRAY_SIZE(formats) >= 3);
                     /* DTSHD can be played as DTSHD or as DTS */
@@ -728,7 +738,7 @@ int aout_OutputNew (audio_output_t *aout)
                 }
                 break;
             case VLC_CODEC_A52:
-                if (owner->input_profile > 0)
+                if (input_profile > 0)
                 {
                     assert(ARRAY_SIZE(formats) >= 3);
                     formats[0] = VLC_CODEC_EAC3;
@@ -749,11 +759,16 @@ int aout_OutputNew (audio_output_t *aout)
     aout->current_sink_info.headphones = false;
 
     vlc_mutex_lock(&owner->lock);
+    /* XXX: Remove when aout/stream support is complete (in all modules) */
+    assert(owner->main_stream == NULL);
+
     int ret = VLC_EGENERIC;
     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);
+        if (ret == 0)
+            owner->main_stream = stream;
     }
     vlc_mutex_unlock(&owner->lock);
     if (ret)
@@ -781,6 +796,7 @@ int aout_OutputNew (audio_output_t *aout)
     aout_FormatPrepare (fmt);
     assert (fmt->i_bytes_per_frame > 0 && fmt->i_frame_length > 0);
     aout_FormatPrint (aout, "output", fmt);
+
     return 0;
 }
 
@@ -794,6 +810,7 @@ void aout_OutputDelete (audio_output_t *aout)
     aout_owner_t *owner = aout_owner(aout);
     vlc_mutex_lock(&owner->lock);
     aout->stop (aout);
+    owner->main_stream = NULL;
     vlc_mutex_unlock(&owner->lock);
 }
 


=====================================
src/input/decoder.c
=====================================
@@ -128,7 +128,10 @@ struct vlc_input_decoder_t
      * The input thread can read these variables in order to stop outputs, when
      * both ModuleThread and DecoderThread are stopped (from DecoderDelete()).
      */
+
+    /* If p_aout is valid, then p_astream is valid too */
     audio_output_t *p_aout;
+    vlc_aout_stream *p_astream; 
 
     vout_thread_t   *p_vout;
     bool             vout_started;
@@ -250,11 +253,14 @@ static int DecoderThread_Reload( vlc_input_decoder_t *p_owner,
     {
         assert( p_owner->fmt.i_cat == AUDIO_ES );
         audio_output_t *p_aout = p_owner->p_aout;
+        vlc_aout_stream *p_astream = p_owner->p_astream;
         // no need to lock, the decoder and ModuleThread are dead
         p_owner->p_aout = NULL;
+        p_owner->p_astream = NULL;
         if( p_aout )
         {
-            aout_DecDelete( p_aout );
+            assert( p_astream );
+            vlc_aout_stream_Delete( p_astream );
             input_resource_PutAout( p_owner->p_resource, p_aout );
         }
     }
@@ -330,12 +336,14 @@ static int ModuleThread_UpdateAudioFormat( decoder_t *p_dec )
          p_dec->fmt_out.i_profile != p_owner->fmt.i_profile ) )
     {
         audio_output_t *p_aout = p_owner->p_aout;
+        vlc_aout_stream *p_astream = p_owner->p_astream;
 
         /* Parameters changed, restart the aout */
         vlc_mutex_lock( &p_owner->lock );
+        p_owner->p_astream = NULL;
         p_owner->p_aout = NULL; // the DecoderThread should not use the old aout anymore
         vlc_mutex_unlock( &p_owner->lock );
-        aout_DecDelete( p_aout );
+        vlc_aout_stream_Delete( p_astream );
 
         input_resource_PutAout( p_owner->p_resource, p_aout );
     }
@@ -370,13 +378,16 @@ static int ModuleThread_UpdateAudioFormat( decoder_t *p_dec )
         }
 
         audio_output_t *p_aout;
+        vlc_aout_stream *p_astream;
 
         p_aout = input_resource_GetAout( p_owner->p_resource );
         if( p_aout )
         {
-            if( aout_DecNew( p_aout, &format, p_dec->fmt_out.i_profile,
-                             p_owner->p_clock,
-                             &p_dec->fmt_out.audio_replay_gain ) )
+            p_astream = vlc_aout_stream_New( p_aout, &format,
+                                             p_dec->fmt_out.i_profile,
+                                             p_owner->p_clock,
+                                             &p_dec->fmt_out.audio_replay_gain );
+            if( p_astream == NULL )
             {
                 input_resource_PutAout( p_owner->p_resource, p_aout );
                 p_aout = NULL;
@@ -385,6 +396,7 @@ static int ModuleThread_UpdateAudioFormat( decoder_t *p_dec )
 
         vlc_mutex_lock( &p_owner->lock );
         p_owner->p_aout = p_aout;
+        p_owner->p_astream = p_astream;
 
         DecoderUpdateFormatLocked( p_owner );
         aout_FormatPrepare( &p_owner->fmt.audio );
@@ -1207,8 +1219,8 @@ static int ModuleThread_PlayAudio( vlc_input_decoder_t *p_owner, vlc_frame_t *p_
     {
         msg_Dbg( p_dec, "end of audio preroll" );
 
-        if( p_owner->p_aout )
-            aout_DecFlush( p_owner->p_aout );
+        if( p_owner->p_astream )
+            vlc_aout_stream_Flush( p_owner->p_astream );
     }
 
     /* */
@@ -1219,16 +1231,16 @@ static int ModuleThread_PlayAudio( vlc_input_decoder_t *p_owner, vlc_frame_t *p_
     DecoderWaitUnblock( p_owner );
     vlc_mutex_unlock( &p_owner->lock );
 
-    audio_output_t *p_aout = p_owner->p_aout;
+    vlc_aout_stream *p_astream = p_owner->p_astream;
 
-    if( p_aout == NULL )
+    if( p_astream == NULL )
     {
         msg_Dbg( p_dec, "discarded audio buffer" );
         block_Release( p_audio );
         return VLC_EGENERIC;
     }
 
-    int status = aout_DecPlay( p_aout, p_audio );
+    int status = vlc_aout_stream_Play( p_astream, p_audio );
     if( status == AOUT_DEC_CHANGED )
     {
         /* Only reload the decoder */
@@ -1249,9 +1261,9 @@ static void ModuleThread_UpdateStatAudio( vlc_input_decoder_t *p_owner,
 {
     unsigned played = 0;
     unsigned aout_lost = 0;
-    if( p_owner->p_aout != NULL )
+    if( p_owner->p_astream != NULL )
     {
-        aout_DecGetResetStats( p_owner->p_aout, &aout_lost, &played );
+        vlc_aout_stream_GetResetStats( p_owner->p_astream, &aout_lost, &played );
     }
     if (lost) aout_lost++;
 
@@ -1508,8 +1520,8 @@ static void DecoderThread_Flush( vlc_input_decoder_t *p_owner )
 #endif
     if( p_dec->fmt_in.i_cat == AUDIO_ES )
     {
-        if( p_owner->p_aout )
-            aout_DecFlush( p_owner->p_aout );
+        if( p_owner->p_astream )
+            vlc_aout_stream_Flush( p_owner->p_astream );
     }
     else if( p_dec->fmt_in.i_cat == VIDEO_ES )
     {
@@ -1549,8 +1561,8 @@ static void DecoderThread_ChangePause( vlc_input_decoder_t *p_owner, bool paused
             break;
         case AUDIO_ES:
             vlc_mutex_lock( &p_owner->lock );
-            if( p_owner->p_aout != NULL )
-                aout_DecChangePause( p_owner->p_aout, paused, date );
+            if( p_owner->p_astream != NULL )
+                vlc_aout_stream_ChangePause( p_owner->p_astream, paused, date );
             vlc_mutex_unlock( &p_owner->lock );
             break;
         case SPU_ES:
@@ -1573,8 +1585,8 @@ static void DecoderThread_ChangeRate( vlc_input_decoder_t *p_owner, float rate )
                 vout_ChangeRate( p_owner->p_vout, rate );
             break;
         case AUDIO_ES:
-            if( p_owner->p_aout != NULL )
-                aout_DecChangeRate( p_owner->p_aout, rate );
+            if( p_owner->p_astream != NULL )
+                vlc_aout_stream_ChangeRate( p_owner->p_astream, rate );
             break;
         case SPU_ES:
             if( p_owner->p_vout != NULL )
@@ -1607,8 +1619,8 @@ static void DecoderThread_ChangeDelay( vlc_input_decoder_t *p_owner, vlc_tick_t
             break;
         case AUDIO_ES:
             vlc_mutex_lock( &p_owner->lock );
-            if( p_owner->p_aout != NULL )
-                aout_DecChangeDelay( p_owner->p_aout, delay );
+            if( p_owner->p_astream != NULL )
+                vlc_aout_stream_ChangeDelay( p_owner->p_astream, delay );
             vlc_mutex_unlock( &p_owner->lock );
             break;
         case SPU_ES:
@@ -1740,8 +1752,8 @@ static void *DecoderThread( void *p_data )
         if( frame == NULL && p_owner->dec.fmt_in.i_cat == AUDIO_ES )
         {   /* Draining: the decoder is drained and all decoded buffers are
              * queued to the output at this point. Now drain the output. */
-            if( p_owner->p_aout != NULL )
-                aout_DecDrain( p_owner->p_aout );
+            if( p_owner->p_astream != NULL )
+                vlc_aout_stream_Drain( p_owner->p_astream );
         }
 
         /* TODO? Wait for draining instead of polling. */
@@ -1830,6 +1842,7 @@ CreateDecoder( vlc_object_t *p_parent, const es_format_t *fmt,
     p_owner->cbs = cbs;
     p_owner->cbs_userdata = cbs_userdata;
     p_owner->p_aout = NULL;
+    p_owner->p_astream = NULL;
     p_owner->p_vout = NULL;
     p_owner->vout_started = false;
     p_owner->i_spu_channel = VOUT_SPU_CHANNEL_INVALID;
@@ -1994,7 +2007,8 @@ static void DeleteDecoder( vlc_input_decoder_t *p_owner, enum es_format_category
             if( p_owner->p_aout )
             {
                 /* TODO: REVISIT gap-less audio */
-                aout_DecDelete( p_owner->p_aout );
+                assert( p_owner->p_astream );
+                vlc_aout_stream_Delete( p_owner->p_astream );
                 input_resource_PutAout( p_owner->p_resource, p_owner->p_aout );
             }
             break;
@@ -2287,8 +2301,8 @@ bool vlc_input_decoder_IsEmpty( vlc_input_decoder_t * p_owner )
 #endif
     if( p_owner->fmt.i_cat == VIDEO_ES && p_owner->p_vout != NULL )
         b_empty = vout_IsEmpty( p_owner->p_vout );
-    else if( p_owner->fmt.i_cat == AUDIO_ES && p_owner->p_aout != NULL )
-        b_empty = aout_DecIsDrained( p_owner->p_aout );
+    else if( p_owner->fmt.i_cat == AUDIO_ES && p_owner->p_astream != NULL )
+        b_empty = vlc_aout_stream_IsDrained( p_owner->p_astream );
     else
         b_empty = true; /* TODO subtitles support */
     vlc_mutex_unlock( &p_owner->lock );



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/f485b52be2410d2f7890d180481230df3250383d...8ab9e9eb9e859c0bd9349a763e6025ec3dc4b1e9

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


VideoLAN code repository instance


More information about the vlc-commits mailing list