Ejemplo n.º 1
0
/**
 * Flushes or drains the audio output buffers.
 * This enables the output to expedite seek and stop.
 * @param wait if true, wait for buffer playback (i.e. drain),
 *             if false, discard the buffers immediately (i.e. flush)
 */
void aout_OutputFlush( audio_output_t *aout, bool wait )
{
    aout_assert_locked( aout );

    if( aout->pf_flush != NULL )
        aout->pf_flush( aout, wait );
}
Ejemplo n.º 2
0
/**
 * Configures a custom volume setter. This is used by audio outputs that can
 * control the hardware volume directly and/or emulate it internally.
 * @param setter volume setter callback
 */
void aout_VolumeHardInit (audio_output_t *aout, aout_volume_cb setter)
{
    aout_assert_locked (aout);
    aout->pf_volume_set = setter;
    var_Create (aout, "volume", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT);
    var_Create (aout, "mute", VLC_VAR_BOOL|VLC_VAR_DOINHERIT);
}
Ejemplo n.º 3
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);
}
Ejemplo n.º 4
0
Archivo: output.c Proyecto: ares89/vlc
static int aout_GainNotify (audio_output_t *aout, float gain)
{
    aout_owner_t *owner = aout_owner (aout);

    aout_assert_locked (aout);
    aout_volume_SetVolume (owner->volume, gain);
    /* XXX: ideally, return -1 if format cannot be amplified */
    return 0;
}
Ejemplo n.º 5
0
/**
 * Configures the volume setter for software mixing
 * and apply the default volume.
 * @note Audio output plugins that cannot apply the volume
 * should call this function during activation.
 */
void aout_VolumeSoftInit (audio_output_t *aout)
{
    audio_volume_t volume = var_InheritInteger (aout, "volume");
    bool mute = var_InheritBool (aout, "mute");

    aout_assert_locked (aout);
    aout->pf_volume_set = aout_VolumeSoftSet;
    aout_VolumeSoftSet (aout, volume / (float)AOUT_VOLUME_DEFAULT, mute);
}
Ejemplo n.º 6
0
/**
 * Notifies the audio input of the drift from the requested audio
 * playback timestamp (@ref block_t.i_pts) to the anticipated playback time
 * as reported by the audio output hardware.
 * Depending on the drift amplitude, the input core may ignore the drift
 * trigger upsampling or downsampling, or even discard samples.
 * Future VLC versions may instead adjust the input decoding speed.
 *
 * The audio output plugin is responsible for estimating the ideal current
 * playback time defined as follows:
 *  ideal time = buffer timestamp - (output latency + pending buffer duration)
 *
 * Practically, this is the PTS (block_t.i_pts) of the current buffer minus
 * the latency reported by the output programming interface.
 * Computing the estimated drift directly would probably be more intuitive.
 * However the use of an absolute time value does not introduce extra
 * measurement errors due to the CPU scheduling jitter and clock resolution.
 * Furthermore, the ideal while it is an abstract value, is easy for most
 * audio output plugins to compute.
 * The following definition is equivalent but depends on the clock time:
 *  ideal time = real time + drift

 * @note If aout_LatencyReport() is never called, the core will assume that
 * there is no drift.
 *
 * @param ideal estimated ideal time as defined above.
 */
void aout_TimeReport (audio_output_t *aout, mtime_t ideal)
{
    mtime_t delta = mdate() - ideal /* = -drift */;

    aout_assert_locked (aout);
    if (delta < -AOUT_MAX_PTS_ADVANCE || +AOUT_MAX_PTS_DELAY < delta)
    {
        aout_owner_t *owner = aout_owner (aout);

        msg_Warn (aout, "not synchronized (%"PRId64" us), resampling",
                  delta);
        if (date_Get (&owner->sync.date) != VLC_TS_INVALID)
            date_Move (&owner->sync.date, delta);
    }
}
Ejemplo n.º 7
0
/**
 * Plays a decoded audio buffer.
 */
void aout_OutputPlay (audio_output_t *aout, block_t *block)
{
    aout_owner_t *owner = aout_owner (aout);

    aout_assert_locked (aout);

    aout_FiltersPlay (owner->filters, owner->nb_filters, &block);
    if (block == NULL)
        return;
    if (block->i_buffer == 0)
    {
        block_Release (block);
        return;
    }

    aout->pf_play (aout, block);
}
Ejemplo n.º 8
0
/**
 * Destroys the audio output plug-in instance.
 */
void aout_OutputDelete (audio_output_t *aout)
{
    aout_owner_t *owner = aout_owner (aout);

    aout_assert_locked (aout);

    if (owner->module == NULL)
        return;

    module_unneed (aout, owner->module);
    /* Clear callbacks */
    aout->pf_play = aout_DecDeleteBuffer; /* gruik */
    aout->pf_pause = NULL;
    aout->pf_flush = NULL;
    aout_VolumeNoneInit (aout);
    owner->module = NULL;
    aout_FiltersDestroyPipeline (owner->filters, owner->nb_filters);
}
Ejemplo n.º 9
0
/**
 * Volume setter for software volume.
 */
static int aout_VolumeSoftSet (audio_output_t *aout, float volume, bool mute)
{
    aout_owner_t *owner = aout_owner (aout);

    aout_assert_locked (aout);

    /* Cubic mapping from software volume to amplification factor.
     * This provides a good tradeoff between low and high volume ranges.
     *
     * This code is only used for the VLC software mixer. If you change this
     * formula, be sure to update the aout_VolumeHardInit()-based plugins also.
     */
    if (!mute)
        volume = volume * volume * volume;
    else
        volume = 0.;

    owner->volume.multiplier = volume;
    return 0;
}
Ejemplo n.º 10
0
Archivo: dec.c Proyecto: 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;
}
Ejemplo n.º 11
0
/*****************************************************************************
 * aout_OutputNew : allocate a new output and rework the filter pipeline
 *****************************************************************************
 * This function is entered with the mixer lock.
 *****************************************************************************/
int aout_OutputNew( audio_output_t *p_aout,
                    const audio_sample_format_t * p_format )
{
    aout_owner_t *owner = aout_owner (p_aout);

    aout_assert_locked( p_aout );
    p_aout->format = *p_format;

    aout_FormatPrepare( &p_aout->format );

    /* Find the best output plug-in. */
    owner->module = module_need (p_aout, "audio output", "$aout", false);
    if (owner->module == NULL)
    {
        msg_Err( p_aout, "no suitable audio output module" );
        return -1;
    }

    if ( var_Type( p_aout, "audio-channels" ) ==
             (VLC_VAR_INTEGER | VLC_VAR_HASCHOICE) )
    {
        /* The user may have selected a different channels configuration. */
        switch( var_InheritInteger( p_aout, "audio-channels" ) )
        {
            case AOUT_VAR_CHAN_RSTEREO:
                p_aout->format.i_original_channels |= AOUT_CHAN_REVERSESTEREO;
                break;
            case AOUT_VAR_CHAN_STEREO:
                p_aout->format.i_original_channels =
                                              AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
                break;
            case AOUT_VAR_CHAN_LEFT:
                p_aout->format.i_original_channels = AOUT_CHAN_LEFT;
                break;
            case AOUT_VAR_CHAN_RIGHT:
                p_aout->format.i_original_channels = AOUT_CHAN_RIGHT;
                break;
            case AOUT_VAR_CHAN_DOLBYS:
                p_aout->format.i_original_channels =
                      AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_DOLBYSTEREO;
                break;
        }
    }
    else if ( p_aout->format.i_physical_channels == AOUT_CHAN_CENTER
              && (p_aout->format.i_original_channels
                   & AOUT_CHAN_PHYSMASK) == (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT) )
    {
        vlc_value_t val, text;

        /* Mono - create the audio-channels variable. */
        var_Create( p_aout, "audio-channels",
                    VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
        text.psz_string = _("Audio Channels");
        var_Change( p_aout, "audio-channels", VLC_VAR_SETTEXT, &text, NULL );

        val.i_int = AOUT_VAR_CHAN_STEREO; text.psz_string = _("Stereo");
        var_Change( p_aout, "audio-channels", VLC_VAR_ADDCHOICE, &val, &text );
        val.i_int = AOUT_VAR_CHAN_LEFT; text.psz_string = _("Left");
        var_Change( p_aout, "audio-channels", VLC_VAR_ADDCHOICE, &val, &text );
        val.i_int = AOUT_VAR_CHAN_RIGHT; text.psz_string = _("Right");
        var_Change( p_aout, "audio-channels", VLC_VAR_ADDCHOICE, &val, &text );
        if ( p_aout->format.i_original_channels & AOUT_CHAN_DUALMONO )
        {
            /* Go directly to the left channel. */
            p_aout->format.i_original_channels = AOUT_CHAN_LEFT;
            var_SetInteger( p_aout, "audio-channels", AOUT_VAR_CHAN_LEFT );
        }
        var_AddCallback( p_aout, "audio-channels", aout_ChannelsRestart,
                         NULL );
    }
    else if ( p_aout->format.i_physical_channels ==
               (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT)
                && (p_aout->format.i_original_channels &
                     (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT)) )
    {
        vlc_value_t val, text;

        /* Stereo - create the audio-channels variable. */
        var_Create( p_aout, "audio-channels",
                    VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
        text.psz_string = _("Audio Channels");
        var_Change( p_aout, "audio-channels", VLC_VAR_SETTEXT, &text, NULL );

        if ( p_aout->format.i_original_channels & AOUT_CHAN_DOLBYSTEREO )
        {
            val.i_int = AOUT_VAR_CHAN_DOLBYS;
            text.psz_string = _("Dolby Surround");
        }
        else
        {
            val.i_int = AOUT_VAR_CHAN_STEREO;
            text.psz_string = _("Stereo");
        }
        var_Change( p_aout, "audio-channels", VLC_VAR_ADDCHOICE, &val, &text );
        val.i_int = AOUT_VAR_CHAN_LEFT; text.psz_string = _("Left");
        var_Change( p_aout, "audio-channels", VLC_VAR_ADDCHOICE, &val, &text );
        val.i_int = AOUT_VAR_CHAN_RIGHT; text.psz_string = _("Right");
        var_Change( p_aout, "audio-channels", VLC_VAR_ADDCHOICE, &val, &text );
        val.i_int = AOUT_VAR_CHAN_RSTEREO; text.psz_string=_("Reverse stereo");
        var_Change( p_aout, "audio-channels", VLC_VAR_ADDCHOICE, &val, &text );
        if ( p_aout->format.i_original_channels & AOUT_CHAN_DUALMONO )
        {
            /* Go directly to the left channel. */
            p_aout->format.i_original_channels = AOUT_CHAN_LEFT;
            var_SetInteger( p_aout, "audio-channels", AOUT_VAR_CHAN_LEFT );
        }
        var_AddCallback( p_aout, "audio-channels", aout_ChannelsRestart,
                         NULL );
    }
    var_TriggerCallback( p_aout, "intf-change" );

    aout_FormatPrepare( &p_aout->format );
    aout_FormatPrint( p_aout, "output", &p_aout->format );

    /* Choose the mixer format. */
    owner->mixer_format = p_aout->format;
    if (!AOUT_FMT_LINEAR(&p_aout->format))
        owner->mixer_format.i_format = p_format->i_format;
    else
    /* Most audio filters can only deal with single-precision,
     * so lets always use that when hardware supports floating point. */
    if( HAVE_FPU )
        owner->mixer_format.i_format = VLC_CODEC_FL32;
    else
    /* Otherwise, audio filters will not work. Use fixed-point if the input has
     * more than 16-bits depth. */
    if( p_format->i_bitspersample > 16 || !AOUT_FMT_LINEAR(p_format))
        owner->mixer_format.i_format = VLC_CODEC_FI32;
    else
    /* Fallback to 16-bits. This avoids pointless conversion to and from
     * 32-bits samples for the sole purpose of software mixing. */
        owner->mixer_format.i_format = VLC_CODEC_S16N;

    aout_FormatPrepare (&owner->mixer_format);
    aout_FormatPrint (p_aout, "mixer", &owner->mixer_format);

    /* Create filters. */
    owner->nb_filters = 0;
    if (aout_FiltersCreatePipeline (p_aout, owner->filters,
                                    &owner->nb_filters, &owner->mixer_format,
                                    &p_aout->format) < 0)
    {
        msg_Err( p_aout, "couldn't create audio output pipeline" );
        module_unneed (p_aout, owner->module);
        owner->module = NULL;
        return -1;
    }
    return 0;
}
Ejemplo n.º 12
0
/**
 * Notifies the audio output (if any) of pause/resume events.
 * This enables the output to expedite pause, instead of waiting for its
 * buffers to drain.
 */
void aout_OutputPause( audio_output_t *aout, bool pause, mtime_t date )
{
    aout_assert_locked( aout );
    if( aout->pf_pause != NULL )
        aout->pf_pause( aout, pause, date );
}