Beispiel #1
0
static void aout_CheckRestart (audio_output_t *aout)
{
    aout_owner_t *owner = aout_owner (aout);

    aout_assert_locked (aout);

    int restart = vlc_atomic_swap (&owner->restart, 0);
    if (likely(restart == 0))
        return;

    assert (restart & AOUT_RESTART_INPUT);

    const aout_request_vout_t request_vout = owner->input->request_vout;

    if (likely(owner->input != NULL))
        aout_InputDelete (aout, owner->input);
    owner->input = NULL;

    /* Reinitializes the output */
    if (restart & AOUT_RESTART_OUTPUT)
    {
        aout_MixerDelete (owner->volume.mixer);
        owner->volume.mixer = NULL;
        aout_OutputDelete (aout);

        if (aout_OutputNew (aout, &owner->input_format))
            return; /* we are officially screwed */
        owner->volume.mixer = aout_MixerNew (aout,
                                             owner->mixer_format.i_format);
    }

    owner->input = aout_InputNew (aout, &owner->input_format,
                                  &owner->mixer_format, &request_vout);
}
Beispiel #2
0
/**
 * Stops all plugins involved in the audio output.
 */
void aout_Shutdown (audio_output_t *p_aout)
{
    aout_owner_t *owner = aout_owner (p_aout);
    aout_input_t *input;
    struct audio_mixer *mixer;

    aout_lock( p_aout );
    /* Remove the input. */
    input = owner->input;
    if (likely(input != NULL))
        aout_InputDelete (p_aout, input);
    owner->input = NULL;

    mixer = owner->volume.mixer;
    owner->volume.mixer = NULL;

    var_DelCallback (p_aout, "audio-replay-gain-mode",
                     ReplayGainCallback, owner);

    aout_OutputDelete( p_aout );
    var_Destroy( p_aout, "audio-device" );
    var_Destroy( p_aout, "audio-channels" );

    aout_unlock( p_aout );

    aout_MixerDelete (mixer);
    free (input);
}
Beispiel #3
0
Datei: dec.c Projekt: etix/vlc
static int aout_CheckReady (audio_output_t *aout)
{
    aout_owner_t *owner = aout_owner (aout);

    int status = AOUT_DEC_SUCCESS;
    int restart = atomic_exchange (&owner->restart, 0);
    if (unlikely(restart))
    {
        if (owner->mixer_format.i_format)
            aout_FiltersDelete (aout, owner->filters);

        if (restart & AOUT_RESTART_OUTPUT)
        {   /* Reinitializes the output */
            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;
            aout_volume_SetFormat (owner->volume,
                                   owner->mixer_format.i_format);
            status = AOUT_DEC_CHANGED;
        }

        msg_Dbg (aout, "restarting filters...");
        owner->sync.end = VLC_TS_INVALID;
        owner->sync.resamp_type = AOUT_RESAMPLING_NONE;

        if (owner->mixer_format.i_format)
        {
            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) ? status : AOUT_DEC_FAILED;
}
Beispiel #4
0
Datei: dec.c Projekt: ares89/vlc
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);

        if (restart & AOUT_RESTART_OUTPUT)
        {   /* Reinitializes the output */
            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;
            aout_volume_SetFormat (owner->volume,
                                   owner->mixer_format.i_format);
        }

        msg_Dbg (aout, "restarting filters...");
        owner->sync.end = VLC_TS_INVALID;
        owner->sync.resamp_type = AOUT_RESAMPLING_NONE;

        if (owner->mixer_format.i_format
         && aout_FiltersNew (aout, &owner->input_format, &owner->mixer_format,
                             &request_vout))
        {
            aout_OutputDelete (aout);
            owner->mixer_format.i_format = 0;
        }
    }
    return (owner->mixer_format.i_format) ? 0 : -1;
}
/**
 * Stops all plugins involved in the audio output.
 */
void aout_DecDelete (audio_output_t *aout)
{
    aout_owner_t *owner = aout_owner (aout);

    aout_OutputLock (aout);
    if (owner->mixer_format.i_format)
    {
        aout_FiltersDelete (aout, owner->filters);
        aout_OutputDelete (aout);
    }
    aout_volume_Delete (owner->volume);
    aout_OutputUnlock (aout);
    var_Destroy (aout, "stereo-mode");
}
Beispiel #6
0
/*****************************************************************************
 * aout_DecDelete : delete a decoder
 *****************************************************************************/
int aout_DecDelete( aout_instance_t * p_aout, aout_input_t * p_input )
{
    int i_input;

    /* This function can only be called by the decoder itself, so no need
     * to lock p_input->lock. */
    vlc_mutex_lock( &p_aout->mixer_lock );

    for ( i_input = 0; i_input < p_aout->i_nb_inputs; i_input++ )
    {
        if ( p_aout->pp_inputs[i_input] == p_input )
        {
            break;
        }
    }

    if ( i_input == p_aout->i_nb_inputs )
    {
        msg_Err( p_aout, "cannot find an input to delete" );
        return -1;
    }

    /* Remove the input from the list. */
    memmove( &p_aout->pp_inputs[i_input], &p_aout->pp_inputs[i_input + 1],
             (AOUT_MAX_INPUTS - i_input - 1) * sizeof(aout_input_t *) );
    p_aout->i_nb_inputs--;

    aout_InputDelete( p_aout, p_input );

    vlc_mutex_destroy( &p_input->lock );
    free( p_input );

    if ( !p_aout->i_nb_inputs )
    {
        aout_OutputDelete( p_aout );
        aout_MixerDelete( p_aout );
        if ( var_Type( p_aout, "audio-device" ) != 0 )
        {
            var_Destroy( p_aout, "audio-device" );
        }
        if ( var_Type( p_aout, "audio-channels" ) != 0 )
        {
            var_Destroy( p_aout, "audio-channels" );
        }
    }

    vlc_mutex_unlock( &p_aout->mixer_lock );

    return 0;
}
Beispiel #7
0
Datei: dec.c Projekt: etix/vlc
/**
 * Creates an audio output
 */
int aout_DecNew( audio_output_t *p_aout,
                 const audio_sample_format_t *p_format,
                 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 ) )
    {
        msg_Err( p_aout, "incompatible audio channels count with layout mask" );
        return -1;
    }

    if( p_format->i_rate > 352800 )
    {
        msg_Err( p_aout, "excessive audio sample frequency (%u)",
                 p_format->i_rate );
        return -1;
    }
    if( p_format->i_rate < 4000 )
    {
        msg_Err( p_aout, "too low audio sample frequency (%u)",
                 p_format->i_rate );
        return -1;
    }

    var_Create (p_aout, "stereo-mode", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
    vlc_value_t txt;
    txt.psz_string = _("Stereo audio mode");
    var_Change (p_aout, "stereo-mode", VLC_VAR_SETTEXT, &txt, NULL);

    aout_owner_t *owner = aout_owner(p_aout);

    /* TODO: reduce lock scope depending on decoder's real need */
    aout_OutputLock (p_aout);

    /* Create the audio output stream */
    owner->volume = aout_volume_New (p_aout, p_replay_gain);

    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 */
    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);
        owner->volume = NULL;
        aout_OutputUnlock (p_aout);
        var_Destroy (p_aout, "stereo-mode");
        return -1;
    }

    owner->sync.end = VLC_TS_INVALID;
    owner->sync.resamp_type = AOUT_RESAMPLING_NONE;
    owner->sync.discontinuity = true;
    aout_OutputUnlock (p_aout);

    atomic_init (&owner->buffers_lost, 0);
    atomic_init (&owner->buffers_played, 0);
    return 0;
}
/**
 * Creates an audio output
 */
int aout_DecNew( audio_output_t *p_aout,
                 const audio_sample_format_t *p_format,
                 const audio_replay_gain_t *p_replay_gain,
                 const aout_request_vout_t *p_request_vout )
{
    /* Sanitize audio format */
    if( p_format->i_channels != aout_FormatNbChannels( p_format ) )
    {
        msg_Err( p_aout, "incompatible audio channels count with layout mask" );
        return -1;
    }

    if( p_format->i_rate > 352800 )
    {
        msg_Err( p_aout, "excessive audio sample frequency (%u)",
                 p_format->i_rate );
        return -1;
    }
    if( p_format->i_rate < 4000 )
    {
        msg_Err( p_aout, "too low audio sample frequency (%u)",
                 p_format->i_rate );
        return -1;
    }

    aout_owner_t *owner = aout_owner(p_aout);

    /* TODO: reduce lock scope depending on decoder's real need */
    aout_OutputLock (p_aout);

    var_Destroy( p_aout, "stereo-mode" );

    /* Create the audio output stream */
    owner->volume = aout_volume_New (p_aout, p_replay_gain);

    atomic_store (&owner->restart, (atomic_uchar)0);			// sunqueen modify
    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 */
    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_OutputUnlock (p_aout);
        return -1;
    }

    owner->sync.end = VLC_TS_INVALID;
    owner->sync.resamp_type = AOUT_RESAMPLING_NONE;
    owner->sync.discontinuity = true;
    aout_OutputUnlock (p_aout);

    atomic_init (&owner->buffers_lost, 0);
    return 0;
}
Beispiel #9
0
/*****************************************************************************
 * aout_DecNew : create a decoder
 *****************************************************************************/
static aout_input_t * DecNew( vlc_object_t * p_this, aout_instance_t * p_aout,
                              audio_sample_format_t * p_format )
{
    aout_input_t * p_input;
    input_thread_t * p_input_thread;
    vlc_value_t val;

    /* We can only be called by the decoder, so no need to lock
     * p_input->lock. */
    vlc_mutex_lock( &p_aout->mixer_lock );

    if ( p_aout->i_nb_inputs >= AOUT_MAX_INPUTS )
    {
        msg_Err( p_aout, "too many inputs already (%d)", p_aout->i_nb_inputs );
        return NULL;
    }

    p_input = malloc(sizeof(aout_input_t));
    if ( p_input == NULL )
    {
        msg_Err( p_aout, "out of memory" );
        return NULL;
    }

    vlc_mutex_init( p_aout, &p_input->lock );

    p_input->b_changed = 0;
    p_input->b_error = 1;
    aout_FormatPrepare( p_format );
    memcpy( &p_input->input, p_format,
            sizeof(audio_sample_format_t) );

    p_aout->pp_inputs[p_aout->i_nb_inputs] = p_input;
    p_aout->i_nb_inputs++;

    if ( p_aout->mixer.b_error )
    {
        int i;

        var_Destroy( p_aout, "audio-device" );
        var_Destroy( p_aout, "audio-channels" );

        /* Recreate the output using the new format. */
        if ( aout_OutputNew( p_aout, p_format ) < 0 )
        {
            for ( i = 0; i < p_aout->i_nb_inputs - 1; i++ )
            {
                vlc_mutex_lock( &p_aout->pp_inputs[i]->lock );
                aout_InputDelete( p_aout, p_aout->pp_inputs[i] );
                vlc_mutex_unlock( &p_aout->pp_inputs[i]->lock );
            }
            vlc_mutex_unlock( &p_aout->mixer_lock );
            return p_input;
        }

        /* Create other input streams. */
        for ( i = 0; i < p_aout->i_nb_inputs - 1; i++ )
        {
            vlc_mutex_lock( &p_aout->pp_inputs[i]->lock );
            aout_InputDelete( p_aout, p_aout->pp_inputs[i] );
            aout_InputNew( p_aout, p_aout->pp_inputs[i] );
            vlc_mutex_unlock( &p_aout->pp_inputs[i]->lock );
        }
    }
    else
    {
        aout_MixerDelete( p_aout );
    }

    if ( aout_MixerNew( p_aout ) == -1 )
    {
        aout_OutputDelete( p_aout );
        vlc_mutex_unlock( &p_aout->mixer_lock );
        return NULL;
    }

    aout_InputNew( p_aout, p_input );

    vlc_mutex_unlock( &p_aout->mixer_lock );

    var_Create( p_this, "audio-desync", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
    var_Get( p_this, "audio-desync", &val );
    p_input->i_desync = val.i_int * 1000;

    p_input_thread = (input_thread_t *)vlc_object_find( p_this,
                                           VLC_OBJECT_INPUT, FIND_PARENT );
    if( p_input_thread )
    {
        p_input->i_pts_delay = p_input_thread->i_pts_delay;
        p_input->i_pts_delay += p_input->i_desync;
        vlc_object_release( p_input_thread );
    }
    else
    {
        p_input->i_pts_delay = DEFAULT_PTS_DELAY;
        p_input->i_pts_delay += p_input->i_desync;
    }

    return p_input;
}
Beispiel #10
0
/*****************************************************************************
 * aout_Restart : re-open the output device and rebuild the input and output
 *                pipelines
 *****************************************************************************
 * This function is used whenever the parameters of the output plug-in are
 * changed (eg. selecting S/PDIF or PCM).
 *****************************************************************************/
static int aout_Restart( aout_instance_t * p_aout )
{
    int i;
    bool b_error = 0;

    aout_lock_mixer( p_aout );

    if ( p_aout->i_nb_inputs == 0 )
    {
        aout_unlock_mixer( p_aout );
        msg_Err( p_aout, "no decoder thread" );
        return -1;
    }

    /* Lock all inputs. */
    aout_lock_input_fifos( p_aout );

    for ( i = 0; i < p_aout->i_nb_inputs; i++ )
    {
        aout_lock_input( p_aout, p_aout->pp_inputs[i] );
        aout_InputDelete( p_aout, p_aout->pp_inputs[i] );
    }

    aout_MixerDelete( p_aout );

    /* Re-open the output plug-in. */
    aout_OutputDelete( p_aout );

    if ( aout_OutputNew( p_aout, &p_aout->pp_inputs[0]->input ) == -1 )
    {
        /* Release all locks and report the error. */
        for ( i = 0; i < p_aout->i_nb_inputs; i++ )
        {
            vlc_mutex_unlock( &p_aout->pp_inputs[i]->lock );
        }
        aout_unlock_input_fifos( p_aout );
        aout_unlock_mixer( p_aout );
        return -1;
    }

    if ( aout_MixerNew( p_aout ) == -1 )
    {
        aout_OutputDelete( p_aout );
        for ( i = 0; i < p_aout->i_nb_inputs; i++ )
        {
            vlc_mutex_unlock( &p_aout->pp_inputs[i]->lock );
        }
        aout_unlock_input_fifos( p_aout );
        aout_unlock_mixer( p_aout );
        return -1;
    }

    /* Re-open all inputs. */
    for ( i = 0; i < p_aout->i_nb_inputs; i++ )
    {
        aout_input_t * p_input = p_aout->pp_inputs[i];
        b_error |= aout_InputNew( p_aout, p_input );
        p_input->b_changed = 1;
        aout_unlock_input( p_aout, p_input );
    }

    aout_unlock_input_fifos( p_aout );
    aout_unlock_mixer( p_aout );

    return b_error;
}
Beispiel #11
0
/**
 * Creates an audio output
 */
int aout_DecNew( audio_output_t *p_aout,
                 const audio_sample_format_t *p_format,
                 const audio_replay_gain_t *p_replay_gain,
                 const aout_request_vout_t *p_request_vout )
{
    /* Sanitize audio format */
    if( p_format->i_channels > 32 )
    {
        msg_Err( p_aout, "too many audio channels (%u)",
                 p_format->i_channels );
        return -1;
    }
    if( p_format->i_channels <= 0 )
    {
        msg_Err( p_aout, "no audio channels" );
        return -1;
    }
    if( p_format->i_channels != aout_FormatNbChannels( p_format ) )
    {
        msg_Err( p_aout, "incompatible audio channels count with layout mask" );
        return -1;
    }

    if( p_format->i_rate > 192000 )
    {
        msg_Err( p_aout, "excessive audio sample frequency (%u)",
                 p_format->i_rate );
        return -1;
    }
    if( p_format->i_rate < 4000 )
    {
        msg_Err( p_aout, "too low audio sample frequency (%u)",
                 p_format->i_rate );
        return -1;
    }

    aout_owner_t *owner = aout_owner(p_aout);
#ifdef RECYCLE
    /* Calling decoder is responsible for serializing aout_DecNew() and
     * aout_DecDelete(). So no need to lock to _read_ those properties. */
    if (owner->module != NULL) /* <- output exists */
    {   /* Check if we can recycle the existing output and pipelines */
        if (AOUT_FMTS_IDENTICAL(&owner->input_format, p_format))
            return 0;

        /* TODO? If the new input format is closer to the output format than
         * the old input format was, then the output could be recycled. The
         * input pipeline however would need to be restarted. */

        /* No recycling: delete everything and restart from scratch */
        aout_Shutdown (p_aout);
    }
#endif
    int ret = 0;

    /* TODO: reduce lock scope depending on decoder's real need */
    aout_lock( p_aout );
    assert (owner->module == NULL);

    /* Create the audio output stream */
    var_Destroy( p_aout, "audio-device" );
    var_Destroy( p_aout, "audio-channels" );

    owner->input_format = *p_format;
    vlc_atomic_set (&owner->restart, 0);
    if( aout_OutputNew( p_aout, p_format ) < 0 )
    {
        ret = -1;
        goto error;
    }

    /* Allocate a software mixer */
    assert (owner->volume.mixer == NULL);
    owner->volume.mixer = aout_MixerNew (p_aout, owner->mixer_format.i_format);

    aout_ReplayGainInit (&owner->gain.data, p_replay_gain);
    var_AddCallback (p_aout, "audio-replay-gain-mode",
                     ReplayGainCallback, owner);
    var_TriggerCallback (p_aout, "audio-replay-gain-mode");

    /* Create the audio filtering "input" pipeline */
    date_Init (&owner->sync.date, owner->mixer_format.i_rate, 1);
    date_Set (&owner->sync.date, VLC_TS_INVALID);

    assert (owner->input == NULL);
    owner->input = aout_InputNew (p_aout, p_format, &owner->mixer_format,
                                  p_request_vout);
    if (owner->input == NULL)
    {
        struct audio_mixer *mixer = owner->volume.mixer;

        owner->volume.mixer = NULL;
        aout_OutputDelete (p_aout);
        aout_unlock (p_aout);
        aout_MixerDelete (mixer);
        return -1;
    }
error:
    aout_unlock( p_aout );
    return ret;
}