Commit 2b2af1eb authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

Spawn one audio output instance per audio input

When asked for more than one reference to an audio output instance, the
input resource will now return distinct instances, instead of multiple
references to a unique instance. This means each audio decoder will use
an audio output of its own. Earlier, audio decoders from the same input
would share their output through a mixer.

In practice, this change does not make much difference. Indeed, there
is normally only one active AUDIO_ES decoder_t/aout_input_t per input
in any case. There is one quirk to render multiple audio tracks:
 # vlc --sout-all --sout '#display'

There are a few advantages to this approach:

- The output of each audio track can be controlled independently. For
instance, different tracks can be routed to different devices,
different ports, or in theory at least, to different output plugins.

- This enables simplification of the audio output subsystem as it can
now be assumed that there is only one (or zero) input per output.
Track mixing is not required anymore. This is not to be confused with
channel mixing!

- We can get rid of the audio mixer plugins completely.

There are also disadvantages. But there was no way to run into this
situation with VLC, except for the --sout-all quirk as far as I know:

- If the output does not support mixing internally, only one track can
be rendered at a time. But any sane operating system supports mixing in
hardware or software, so that more than one process can output audio.

- The audio tracks might not be in perfect synchronization anymore.

Note that the user interface does not support more than one output any
better than the input (ES output) core. The input resource currently
only keeps track of one audio output, but this could be fixed if
needed. If you use PulseAudio, you can control the extrar outputs using
an external PulseAudio mixer UI; I don't know about other systems.
parent 4626438f
......@@ -67,9 +67,11 @@ struct input_resource_t
/* You need lock+lock_hold to write to the following variables and
* only lock or lock_hold to read them */
int i_vout;
vout_thread_t **pp_vout;
int i_vout;
/* TODO? track more than one audio output (like video outputs) */
bool b_aout_busy;
aout_instance_t *p_aout;
};
......@@ -329,39 +331,58 @@ static void DestroyAout( input_resource_t *p_resource )
vlc_object_release( p_resource->p_aout );
p_resource->p_aout = NULL;
}
static aout_instance_t *RequestAout( input_resource_t *p_resource, aout_instance_t *p_aout )
static void ReleaseAout( input_resource_t *p_resource,
aout_instance_t *p_aout )
{
vlc_assert_locked( &p_resource->lock );
msg_Dbg( p_resource->p_parent, "releasing audio output" );
if( likely(p_aout == p_resource->p_aout) )
p_resource->b_aout_busy = false;
vlc_object_release( p_aout );
}
if( p_aout )
static aout_instance_t *AllocateAout( input_resource_t *p_resource )
{
aout_instance_t *p_aout;
if( unlikely(p_resource->b_aout_busy) )
{
msg_Dbg( p_resource->p_parent, "releasing aout" );
vlc_object_release( p_aout );
return NULL;
msg_Dbg( p_resource->p_parent, "creating audio output" );
return aout_New( p_resource->p_parent );
}
else
{
p_aout = p_resource->p_aout;
if( !p_aout )
if( p_aout == NULL )
{
msg_Dbg( p_resource->p_parent, "creating aout" );
msg_Dbg( p_resource->p_parent, "creating audio output" );
p_aout = aout_New( p_resource->p_parent );
if( unlikely(p_aout == NULL) )
return NULL;
vlc_mutex_lock( &p_resource->lock_hold );
p_resource->p_aout = p_aout;
vlc_mutex_unlock( &p_resource->lock_hold );
}
else
{
msg_Dbg( p_resource->p_parent, "reusing aout" );
}
msg_Dbg( p_resource->p_parent, "recycling audio output" );
if( !p_aout )
return NULL;
p_resource->b_aout_busy = true;
vlc_object_hold( p_aout );
return p_aout;
}
static aout_instance_t *RequestAout( input_resource_t *p_resource, aout_instance_t *p_aout )
{
vlc_assert_locked( &p_resource->lock );
if( p_aout )
{
ReleaseAout( p_resource, p_aout );
return NULL;
}
return AllocateAout( p_resource );
}
static aout_instance_t *HoldAout( input_resource_t *p_resource )
{
vlc_mutex_lock( &p_resource->lock_hold );
......@@ -374,6 +395,7 @@ static aout_instance_t *HoldAout( input_resource_t *p_resource )
return p_aout;
}
static void TerminateAout( input_resource_t *p_resource )
{
vlc_mutex_lock( &p_resource->lock_hold );
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment