return -1;
}
- if( p_format->i_rate > 192000 )
+ if( p_format->i_rate > 352800 )
{
msg_Err( p_aout, "excessive audio sample frequency (%u)",
p_format->i_rate );
aout_owner_t *owner = aout_owner(p_aout);
/* TODO: reduce lock scope depending on decoder's real need */
- aout_lock( p_aout );
+ aout_OutputLock (p_aout);
var_Destroy( p_aout, "stereo-mode" );
atomic_store (&owner->restart, 0);
owner->input_format = *p_format;
owner->mixer_format = owner->input_format;
+ owner->request_vout = *p_request_vout;
if (aout_OutputNew (p_aout, &owner->mixer_format))
goto error;
aout_volume_SetFormat (owner->volume, owner->mixer_format.i_format);
/* Create the audio filtering "input" pipeline */
- if (aout_FiltersNew (p_aout, p_format, &owner->mixer_format,
- p_request_vout))
+ owner->filters = aout_FiltersNew (p_aout, p_format, &owner->mixer_format,
+ &owner->request_vout);
+ if (owner->filters == NULL)
{
aout_OutputDelete (p_aout);
error:
aout_volume_Delete (owner->volume);
- aout_unlock (p_aout);
+ aout_OutputUnlock (p_aout);
return -1;
}
owner->sync.end = VLC_TS_INVALID;
owner->sync.resamp_type = AOUT_RESAMPLING_NONE;
owner->sync.discontinuity = true;
- aout_unlock( p_aout );
+ aout_OutputUnlock (p_aout);
atomic_init (&owner->buffers_lost, 0);
return 0;
/**
* Stops all plugins involved in the audio output.
*/
-void aout_DecDelete (audio_output_t *p_aout)
+void aout_DecDelete (audio_output_t *aout)
{
- aout_owner_t *owner = aout_owner (p_aout);
+ aout_owner_t *owner = aout_owner (aout);
- aout_lock( p_aout );
- aout_FiltersDelete (p_aout);
- aout_OutputDelete( p_aout );
+ aout_OutputLock (aout);
+ if (owner->mixer_format.i_format)
+ {
+ aout_FiltersDelete (aout, owner->filters);
+ aout_OutputDelete (aout);
+ }
aout_volume_Delete (owner->volume);
-
- var_Destroy( p_aout, "stereo-mode" );
-
- aout_unlock( p_aout );
+ aout_OutputUnlock (aout);
+ var_Destroy (aout, "stereo-mode");
}
-#define AOUT_RESTART_OUTPUT 1
-#define AOUT_RESTART_INPUT 2
static int aout_CheckReady (audio_output_t *aout)
{
aout_owner_t *owner = aout_owner (aout);
- aout_assert_locked (aout);
-
int restart = atomic_exchange (&owner->restart, 0);
if (unlikely(restart))
{
- const aout_request_vout_t request_vout = owner->request_vout;
+ if (owner->mixer_format.i_format)
+ aout_FiltersDelete (aout, owner->filters);
- aout_FiltersDelete (aout);
if (restart & AOUT_RESTART_OUTPUT)
{ /* Reinitializes the output */
- aout_OutputDelete (aout);
+ msg_Dbg (aout, "restarting output...");
+ if (owner->mixer_format.i_format)
+ aout_OutputDelete (aout);
owner->mixer_format = owner->input_format;
if (aout_OutputNew (aout, &owner->mixer_format))
owner->mixer_format.i_format = 0;
owner->mixer_format.i_format);
}
+ msg_Dbg (aout, "restarting filters...");
owner->sync.end = VLC_TS_INVALID;
owner->sync.resamp_type = AOUT_RESAMPLING_NONE;
- if (aout_FiltersNew (aout, &owner->input_format, &owner->mixer_format,
- &request_vout))
+ if (owner->mixer_format.i_format)
{
- aout_OutputDelete (aout);
- owner->mixer_format.i_format = 0;
+ owner->filters = aout_FiltersNew (aout, &owner->input_format,
+ &owner->mixer_format,
+ &owner->request_vout);
+ if (owner->filters == NULL)
+ {
+ aout_OutputDelete (aout);
+ owner->mixer_format.i_format = 0;
+ }
}
+ /* 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) ? 0 : -1;
}
* Marks the audio output for restart, to update any parameter of the output
* plug-in (e.g. output device or channel mapping).
*/
-static void aout_RequestRestart (audio_output_t *aout)
+void aout_RequestRestart (audio_output_t *aout, unsigned mode)
{
aout_owner_t *owner = aout_owner (aout);
-
- /* NOTE: restarting output requires restarting input. */
- atomic_fetch_or (&owner->restart, AOUT_RESTART_OUTPUT);
-}
-
-int aout_ChannelsRestart (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)oldval; (void)newval; (void)data;
-
- if (!strcmp (varname, "audio-device"))
- {
- /* This is supposed to be a significant change and supposes
- * rebuilding the channel choices. */
- var_Destroy (aout, "stereo-mode");
- }
- aout_RequestRestart (aout);
- return 0;
+ atomic_fetch_or (&owner->restart, mode);
+ msg_Dbg (aout, "restart requested (%u)", mode);
}
-/**
- * This function will safely mark aout input to be restarted as soon as
- * possible to take configuration changes into account
- */
-void aout_InputRequestRestart (audio_output_t *aout)
-{
- aout_owner_t *owner = aout_owner (aout);
-
- atomic_fetch_or (&owner->restart, AOUT_RESTART_INPUT);
-}
-
-
/*
* Buffer management
*/
-/*****************************************************************************
- * aout_DecNewBuffer : ask for a new empty buffer
- *****************************************************************************/
-block_t *aout_DecNewBuffer (audio_output_t *aout, size_t samples)
-{
- /* NOTE: the caller is responsible for serializing input change */
- aout_owner_t *owner = aout_owner (aout);
-
- size_t length = samples * owner->input_format.i_bytes_per_frame
- / owner->input_format.i_frame_length;
- block_t *block = block_Alloc( length );
- if( likely(block != NULL) )
- {
- block->i_nb_samples = samples;
- block->i_pts = block->i_length = 0;
- }
- return block;
-}
-
-/*****************************************************************************
- * aout_DecDeleteBuffer : destroy an undecoded buffer
- *****************************************************************************/
-void aout_DecDeleteBuffer (audio_output_t *aout, block_t *block)
-{
- (void) aout;
- block_Release (block);
-}
-
static void aout_StopResampling (audio_output_t *aout)
{
aout_owner_t *owner = aout_owner (aout);
owner->sync.resamp_type = AOUT_RESAMPLING_NONE;
- aout_FiltersAdjustResampling (aout, 0);
+ aout_FiltersAdjustResampling (owner->filters, 0);
}
static void aout_DecSilence (audio_output_t *aout, mtime_t length, mtime_t pts)
* value, then it is time to switch back the resampling direction. */
adj *= -1;
- if (!aout_FiltersAdjustResampling (aout, adj))
+ if (!aout_FiltersAdjustResampling (owner->filters, adj))
{ /* Everything is back to normal: stop resampling. */
owner->sync.resamp_type = AOUT_RESAMPLING_NONE;
msg_Dbg (aout, "resampling stopped (drift: %"PRId64" us)", drift);
block->i_length = CLOCK_FREQ * block->i_nb_samples
/ owner->input_format.i_rate;
- aout_lock (aout);
+ aout_OutputLock (aout);
if (unlikely(aout_CheckReady (aout)))
goto drop; /* Pipeline is unrecoverably broken :-( */
if (block->i_flags & BLOCK_FLAG_DISCONTINUITY)
owner->sync.discontinuity = true;
- block = aout_FiltersPlay (aout, block, input_rate);
+ block = aout_FiltersPlay (owner->filters, block, input_rate);
if (block == NULL)
goto lost;
owner->sync.discontinuity = false;
aout_OutputPlay (aout, block);
out:
- aout_unlock (aout);
+ aout_OutputUnlock (aout);
return 0;
drop:
owner->sync.discontinuity = true;
{
aout_owner_t *owner = aout_owner (aout);
- aout_lock (aout);
+ aout_OutputLock (aout);
if (owner->sync.end != VLC_TS_INVALID)
{
if (paused)
else
owner->sync.end += date;
}
- aout_OutputPause (aout, paused, date);
- aout_unlock (aout);
+ if (owner->mixer_format.i_format)
+ aout_OutputPause (aout, paused, date);
+ aout_OutputUnlock (aout);
}
-void aout_DecFlush (audio_output_t *aout)
+void aout_DecFlush (audio_output_t *aout, bool wait)
{
aout_owner_t *owner = aout_owner (aout);
- aout_lock (aout);
+ aout_OutputLock (aout);
owner->sync.end = VLC_TS_INVALID;
- aout_OutputFlush (aout, false);
- aout_unlock (aout);
+ if (owner->mixer_format.i_format)
+ aout_OutputFlush (aout, wait);
+ aout_OutputUnlock (aout);
}
bool aout_DecIsEmpty (audio_output_t *aout)
mtime_t now = mdate ();
bool empty = true;
- aout_lock (aout);
+ aout_OutputLock (aout);
if (owner->sync.end != VLC_TS_INVALID)
empty = owner->sync.end <= now;
- if (empty)
+ if (empty && owner->mixer_format.i_format)
/* The last PTS has elapsed already. So the underlying audio output
* buffer should be empty or almost. Thus draining should be fast
* and will not block the caller too long. */
aout_OutputFlush (aout, true);
- aout_unlock (aout);
+ aout_OutputUnlock (aout);
return empty;
}