Ejemplo n.º 1
0
static void SetupOutputFormat( decoder_t *p_dec, bool b_trust )
{
    decoder_sys_t *p_sys = p_dec->p_sys;

    p_dec->fmt_out.i_codec = GetVlcAudioFormat( p_sys->p_context->sample_fmt );
    p_dec->fmt_out.audio.i_format = p_dec->fmt_out.i_codec;
    p_dec->fmt_out.audio.i_rate = p_sys->p_context->sample_rate;

    /* */
    if( p_sys->i_previous_channels == p_sys->p_context->channels &&
        p_sys->i_previous_layout == p_sys->p_context->channel_layout )
        return;
    if( b_trust )
    {
        p_sys->i_previous_channels = p_sys->p_context->channels;
        p_sys->i_previous_layout = p_sys->p_context->channel_layout;
    }

    /* Specified order
     * FIXME should we use fmt_in.audio.i_physical_channels or not ?
     */
    const unsigned i_order_max = 8 * sizeof(p_sys->p_context->channel_layout);
    uint32_t pi_order_src[i_order_max];
    int i_channels_src = 0;

    if( p_sys->p_context->channel_layout )
    {
        for( unsigned i = 0; i < sizeof(pi_channels_map)/sizeof(*pi_channels_map); i++ )
        {
            if( p_sys->p_context->channel_layout & pi_channels_map[i][0] )
                pi_order_src[i_channels_src++] = pi_channels_map[i][1];
        }
    }
    else
    {
        /* Create default order  */
        if( b_trust )
            msg_Warn( p_dec, "Physical channel configuration not set : guessing" );
        for( unsigned int i = 0; i < __MIN( i_order_max, (unsigned)p_sys->p_context->channels ); i++ )
        {
            if( i < sizeof(pi_channels_map)/sizeof(*pi_channels_map) )
                pi_order_src[i_channels_src++] = pi_channels_map[i][1];
        }
    }
    if( i_channels_src != p_sys->p_context->channels && b_trust )
        msg_Err( p_dec, "Channel layout not understood" );

    uint32_t i_layout_dst;
    int      i_channels_dst;
    p_sys->b_extract = aout_CheckChannelExtraction( p_sys->pi_extraction,
                                                    &i_layout_dst, &i_channels_dst,
                                                    NULL, pi_order_src, i_channels_src );
    if( i_channels_dst != i_channels_src && b_trust )
        msg_Warn( p_dec, "%d channels are dropped", i_channels_src - i_channels_dst );

    p_dec->fmt_out.audio.i_physical_channels =
    p_dec->fmt_out.audio.i_original_channels = i_layout_dst;
    aout_FormatPrepare( &p_dec->fmt_out.audio );
}
Ejemplo n.º 2
0
Archivo: audio.c Proyecto: MSalmo/vlc
static int transcode_audio_initialize_encoder( sout_stream_id_t *id, sout_stream_t *p_stream )
{
    sout_stream_sys_t *p_sys = p_stream->p_sys;
    /* Initialization of encoder format structures */
    es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
                    id->p_decoder->fmt_out.i_codec );
    id->p_encoder->fmt_in.audio.i_format = id->p_decoder->fmt_out.i_codec;
    id->p_encoder->fmt_in.audio.i_rate = id->p_encoder->fmt_out.audio.i_rate;
    id->p_encoder->fmt_in.audio.i_physical_channels =
        id->p_encoder->fmt_out.audio.i_physical_channels;
    aout_FormatPrepare( &id->p_encoder->fmt_in.audio );

    id->p_encoder->p_cfg = p_stream->p_sys->p_audio_cfg;
    id->p_encoder->p_module =
        module_need( id->p_encoder, "encoder", p_sys->psz_aenc, true );
    if( !id->p_encoder->p_module )
    {
        msg_Err( p_stream, "cannot find audio encoder (module:%s fourcc:%4.4s). Take a look few lines earlier to see possible reason.",
                 p_sys->psz_aenc ? p_sys->psz_aenc : "any",
                 (char *)&p_sys->i_acodec );
        module_unneed( id->p_decoder, id->p_decoder->p_module );
        id->p_decoder->p_module = NULL;
        return VLC_EGENERIC;
    }

    id->p_encoder->fmt_out.i_codec =
        vlc_fourcc_GetCodec( AUDIO_ES, id->p_encoder->fmt_out.i_codec );

    /* Fix input format */
    id->p_encoder->fmt_in.audio.i_format = id->p_encoder->fmt_in.i_codec;
    if( !id->p_encoder->fmt_in.audio.i_physical_channels
     || !id->p_encoder->fmt_in.audio.i_original_channels )
    {
        if( id->p_encoder->fmt_in.audio.i_channels < 6 )
            id->p_encoder->fmt_in.audio.i_physical_channels =
            id->p_encoder->fmt_in.audio.i_original_channels =
                      pi_channels_maps[id->p_encoder->fmt_in.audio.i_channels];
    }
    aout_FormatPrepare( &id->p_encoder->fmt_in.audio );

    return VLC_SUCCESS;
}
Ejemplo n.º 3
0
/*****************************************************************************
 * SplitConversion: split a conversion in two parts
 *****************************************************************************
 * Returns the number of conversions required by the first part - 0 if only
 * one conversion was asked.
 * Beware : p_output_format can be modified during this function if the
 * developer passed SplitConversion( toto, titi, titi, ... ). That is legal.
 * SplitConversion( toto, titi, toto, ... ) isn't.
 *****************************************************************************/
static int SplitConversion( const audio_sample_format_t * p_input_format,
                            const audio_sample_format_t * p_output_format,
                            audio_sample_format_t * p_middle_format )
{
    vlc_bool_t b_format =
             (p_input_format->i_format != p_output_format->i_format);
    vlc_bool_t b_rate = (p_input_format->i_rate != p_output_format->i_rate);
    vlc_bool_t b_channels =
        (p_input_format->i_physical_channels
          != p_output_format->i_physical_channels)
     || (p_input_format->i_original_channels
          != p_output_format->i_original_channels);
    int i_nb_conversions = b_format + b_rate + b_channels;

    if ( i_nb_conversions <= 1 ) return 0;

    memcpy( p_middle_format, p_output_format, sizeof(audio_sample_format_t) );

    if ( i_nb_conversions == 2 )
    {
        if ( !b_format || !b_channels )
        {
            p_middle_format->i_rate = p_input_format->i_rate;
            aout_FormatPrepare( p_middle_format );
            return 1;
        }

        /* !b_rate */
        p_middle_format->i_physical_channels
             = p_input_format->i_physical_channels;
        p_middle_format->i_original_channels
             = p_input_format->i_original_channels;
        aout_FormatPrepare( p_middle_format );
        return 1;
    }

    /* i_nb_conversion == 3 */
    p_middle_format->i_rate = p_input_format->i_rate;
    aout_FormatPrepare( p_middle_format );
    return 2;
}
Ejemplo n.º 4
0
/*****************************************************************************
 * Open: initialize as "audio filter"
 *****************************************************************************/
static int Open( vlc_object_t *p_this )
{
    filter_t     *p_filter = (filter_t *)p_this;

    /* Allocate structure */
    filter_sys_t *p_sys = p_filter->p_sys = malloc( sizeof(*p_sys) );
    if( ! p_sys )
        return VLC_ENOMEM;

    p_sys->scale             = 1.0;
    p_sys->sample_rate       = p_filter->fmt_in.audio.i_rate;
    p_sys->samples_per_frame = aout_FormatNbChannels( &p_filter->fmt_in.audio );
    p_sys->bytes_per_sample  = 4;
    p_sys->bytes_per_frame   = p_sys->samples_per_frame * p_sys->bytes_per_sample;

    msg_Dbg( p_this, "format: %5i rate, %i nch, %i bps, %s",
             p_sys->sample_rate,
             p_sys->samples_per_frame,
             p_sys->bytes_per_sample,
             "fl32" );

    p_sys->ms_stride       = var_InheritInteger( p_this, "scaletempo-stride" );
    p_sys->percent_overlap = var_InheritFloat( p_this, "scaletempo-overlap" );
    p_sys->ms_search       = var_InheritInteger( p_this, "scaletempo-search" );

    msg_Dbg( p_this, "params: %i stride, %.3f overlap, %i search",
             p_sys->ms_stride, p_sys->percent_overlap, p_sys->ms_search );

    p_sys->buf_queue      = NULL;
    p_sys->buf_overlap    = NULL;
    p_sys->table_blend    = NULL;
    p_sys->buf_pre_corr   = NULL;
    p_sys->table_window   = NULL;
    p_sys->bytes_overlap  = 0;
    p_sys->bytes_queued   = 0;
    p_sys->bytes_to_slide = 0;
    p_sys->frames_stride_error = 0;

    if( reinit_buffers( p_filter ) != VLC_SUCCESS )
    {
        Close( p_this );
        return VLC_EGENERIC;
    }

    p_filter->fmt_in.audio.i_format = VLC_CODEC_FL32;
    aout_FormatPrepare(&p_filter->fmt_in.audio);
    p_filter->fmt_out.audio = p_filter->fmt_in.audio;
    p_filter->pf_audio_filter = DoWork;

    return VLC_SUCCESS;
}
Ejemplo n.º 5
0
Archivo: audio.c Proyecto: MSalmo/vlc
int transcode_audio_new( sout_stream_t *p_stream,
                                sout_stream_id_t *id )
{
    sout_stream_sys_t *p_sys = p_stream->p_sys;
    audio_sample_format_t fmt_last;

    /*
     * Open decoder
     */

    /* Initialization of decoder structures */
    id->p_decoder->fmt_out = id->p_decoder->fmt_in;
    id->p_decoder->fmt_out.i_extra = 0;
    id->p_decoder->fmt_out.p_extra = 0;
    id->p_decoder->pf_decode_audio = NULL;
    id->p_decoder->pf_aout_format_update = audio_update_format;
    /* id->p_decoder->p_cfg = p_sys->p_audio_cfg; */

    id->p_decoder->p_module =
        module_need( id->p_decoder, "decoder", "$codec", false );
    if( !id->p_decoder->p_module )
    {
        msg_Err( p_stream, "cannot find audio decoder" );
        return VLC_EGENERIC;
    }
    /* decoders don't set audio.i_format, but audio filters use it */
    id->p_decoder->fmt_out.audio.i_format = id->p_decoder->fmt_out.i_codec;
    aout_FormatPrepare( &id->p_decoder->fmt_out.audio );
    fmt_last = id->p_decoder->fmt_out.audio;
    /* Fix AAC SBR changing number of channels and sampling rate */
    if( !(id->p_decoder->fmt_in.i_codec == VLC_CODEC_MP4A &&
        fmt_last.i_rate != id->p_encoder->fmt_in.audio.i_rate &&
        fmt_last.i_channels != id->p_encoder->fmt_in.audio.i_channels) )
        fmt_last.i_rate = id->p_decoder->fmt_in.audio.i_rate;

    /*
     * Open encoder
     */
    if( transcode_audio_initialize_encoder( id, p_stream ) == VLC_EGENERIC )
	return VLC_EGENERIC;

    if( unlikely( transcode_audio_initialize_filters( p_stream, id, p_sys, &fmt_last ) != VLC_SUCCESS ) )
        return VLC_EGENERIC;

    return VLC_SUCCESS;
}
Ejemplo n.º 6
0
static int UpdateAudioFormat( decoder_t *p_dec )
{
    int i_err;
    decoder_sys_t *p_sys = p_dec->p_sys;
    struct mpg123_frameinfo frame_info;

    /* Get details about the stream */
    i_err = mpg123_info( p_sys->p_handle, &frame_info );
    if( i_err != MPG123_OK )
    {
        msg_Err( p_dec, "mpg123_info failed: %s",
                 mpg123_plain_strerror( i_err ) );
        return VLC_EGENERIC;
    }

    p_dec->fmt_out.i_bitrate = frame_info.bitrate * 1000;

    switch( frame_info.mode )
    {
        case MPG123_M_DUAL:
            p_dec->fmt_out.audio.i_chan_mode = AOUT_CHANMODE_DUALMONO;
            /* fall through */
        case MPG123_M_STEREO:
        case MPG123_M_JOINT:
            p_dec->fmt_out.audio.i_physical_channels =
                AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
            break;
        case MPG123_M_MONO:
            p_dec->fmt_out.audio.i_physical_channels = AOUT_CHAN_CENTER;
            break;
        default:
            return VLC_EGENERIC;
    }

    aout_FormatPrepare( &p_dec->fmt_out.audio );

    /* Date management */
    if( p_dec->fmt_out.audio.i_rate != frame_info.rate )
    {
        p_dec->fmt_out.audio.i_rate = frame_info.rate;
        date_Init( &p_sys->end_date, p_dec->fmt_out.audio.i_rate, 1 );
        date_Set( &p_sys->end_date, 0 );
    }

    return decoder_UpdateAudioFormat( p_dec );
}
Ejemplo n.º 7
0
static filter_t *ResamplerCreate(filter_t *p_filter)
{
    filter_t *p_resampler = vlc_object_create( p_filter, sizeof (filter_t) );
    if( unlikely( p_resampler == NULL ) )
        return NULL;

    p_resampler->owner.sys = NULL;
    p_resampler->p_cfg = NULL;
    p_resampler->fmt_in = p_filter->fmt_in;
    p_resampler->fmt_out = p_filter->fmt_in;
    p_resampler->fmt_out.audio.i_rate =
        vlc_atomic_load_float( &p_filter->p_sys->rate_shift );
    aout_FormatPrepare( &p_resampler->fmt_out.audio );
    p_resampler->p_module = module_need( p_resampler, "audio resampler", NULL,
                                         false );

    if( p_resampler->p_module == NULL )
    {
        msg_Err( p_filter, "Could not load resampler" );
        vlc_object_release( p_resampler );
        return NULL;
    }
    return p_resampler;
}
Ejemplo n.º 8
0
/*****************************************************************************
 * aout_InputNew : allocate a new input and rework the filter pipeline
 *****************************************************************************/
int aout_InputNew( aout_instance_t * p_aout, aout_input_t * p_input, const aout_request_vout_t *p_request_vout )
{
    audio_sample_format_t chain_input_format;
    audio_sample_format_t chain_output_format;
    vlc_value_t val, text;
    char *psz_filters, *psz_visual, *psz_scaletempo;
    int i_visual;

    aout_FormatPrint( p_aout, "input", &p_input->input );

    p_input->i_nb_resamplers = p_input->i_nb_filters = 0;

    /* Prepare FIFO. */
    aout_FifoInit( p_aout, &p_input->mixer.fifo, p_aout->mixer_format.i_rate );
    p_input->mixer.begin = NULL;

    /* */
    if( p_request_vout )
    {
        p_input->request_vout = *p_request_vout;
    }
    else
    {
        p_input->request_vout.pf_request_vout = RequestVout;
        p_input->request_vout.p_private = p_aout;
    }

    /* Prepare format structure */
    chain_input_format  = p_input->input;
    chain_output_format = p_aout->mixer_format;
    chain_output_format.i_rate = p_input->input.i_rate;
    aout_FormatPrepare( &chain_output_format );

    /* Now add user filters */
    if( var_Type( p_aout, "visual" ) == 0 )
    {
        var_Create( p_aout, "visual", VLC_VAR_STRING | VLC_VAR_HASCHOICE );
        text.psz_string = _("Visualizations");
        var_Change( p_aout, "visual", VLC_VAR_SETTEXT, &text, NULL );
        val.psz_string = (char*)""; text.psz_string = _("Disable");
        var_Change( p_aout, "visual", VLC_VAR_ADDCHOICE, &val, &text );
        val.psz_string = (char*)"spectrometer"; text.psz_string = _("Spectrometer");
        var_Change( p_aout, "visual", VLC_VAR_ADDCHOICE, &val, &text );
        val.psz_string = (char*)"scope"; text.psz_string = _("Scope");
        var_Change( p_aout, "visual", VLC_VAR_ADDCHOICE, &val, &text );
        val.psz_string = (char*)"spectrum"; text.psz_string = _("Spectrum");
        var_Change( p_aout, "visual", VLC_VAR_ADDCHOICE, &val, &text );
        val.psz_string = (char*)"vuMeter"; text.psz_string = _("Vu meter");
        var_Change( p_aout, "visual", VLC_VAR_ADDCHOICE, &val, &text );

        /* Look for goom plugin */
        if( module_exists( "goom" ) )
        {
            val.psz_string = (char*)"goom"; text.psz_string = (char*)"Goom";
            var_Change( p_aout, "visual", VLC_VAR_ADDCHOICE, &val, &text );
        }

        /* Look for libprojectM plugin */
        if( module_exists( "projectm" ) )
        {
            val.psz_string = (char*)"projectm"; text.psz_string = (char*)"projectM";
            var_Change( p_aout, "visual", VLC_VAR_ADDCHOICE, &val, &text );
        }

        if( var_Get( p_aout, "effect-list", &val ) == VLC_SUCCESS )
        {
            var_SetString( p_aout, "visual", val.psz_string );
            free( val.psz_string );
        }
        var_AddCallback( p_aout, "visual", VisualizationCallback, NULL );
    }

    if( var_Type( p_aout, "equalizer" ) == 0 )
    {
        module_config_t *p_config;
        int i;

        p_config = config_FindConfig( VLC_OBJECT(p_aout), "equalizer-preset" );
        if( p_config && p_config->i_list )
        {
               var_Create( p_aout, "equalizer",
                           VLC_VAR_STRING | VLC_VAR_HASCHOICE );
            text.psz_string = _("Equalizer");
            var_Change( p_aout, "equalizer", VLC_VAR_SETTEXT, &text, NULL );

            val.psz_string = (char*)""; text.psz_string = _("Disable");
            var_Change( p_aout, "equalizer", VLC_VAR_ADDCHOICE, &val, &text );

            for( i = 0; i < p_config->i_list; i++ )
            {
                val.psz_string = (char *)p_config->ppsz_list[i];
                text.psz_string = (char *)p_config->ppsz_list_text[i];
                var_Change( p_aout, "equalizer", VLC_VAR_ADDCHOICE,
                            &val, &text );
            }

            var_AddCallback( p_aout, "equalizer", EqualizerCallback, NULL );
        }
    }

    if( var_Type( p_aout, "audio-filter" ) == 0 )
    {
        var_Create( p_aout, "audio-filter",
                    VLC_VAR_STRING | VLC_VAR_DOINHERIT );
        text.psz_string = _("Audio filters");
        var_Change( p_aout, "audio-filter", VLC_VAR_SETTEXT, &text, NULL );
    }
    if( var_Type( p_aout, "audio-visual" ) == 0 )
    {
        var_Create( p_aout, "audio-visual",
                    VLC_VAR_STRING | VLC_VAR_DOINHERIT );
        text.psz_string = _("Audio visualizations");
        var_Change( p_aout, "audio-visual", VLC_VAR_SETTEXT, &text, NULL );
    }

    if( var_Type( p_aout, "audio-replay-gain-mode" ) == 0 )
    {
        module_config_t *p_config;
        int i;

        p_config = config_FindConfig( VLC_OBJECT(p_aout), "audio-replay-gain-mode" );
        if( p_config && p_config->i_list )
        {
            var_Create( p_aout, "audio-replay-gain-mode",
                        VLC_VAR_STRING | VLC_VAR_DOINHERIT );

            text.psz_string = _("Replay gain");
            var_Change( p_aout, "audio-replay-gain-mode", VLC_VAR_SETTEXT, &text, NULL );

            for( i = 0; i < p_config->i_list; i++ )
            {
                val.psz_string = (char *)p_config->ppsz_list[i];
                text.psz_string = (char *)p_config->ppsz_list_text[i];
                var_Change( p_aout, "audio-replay-gain-mode", VLC_VAR_ADDCHOICE,
                            &val, &text );
            }

            var_AddCallback( p_aout, "audio-replay-gain-mode", ReplayGainCallback, NULL );
        }
    }
    if( var_Type( p_aout, "audio-replay-gain-preamp" ) == 0 )
    {
        var_Create( p_aout, "audio-replay-gain-preamp",
                    VLC_VAR_FLOAT | VLC_VAR_DOINHERIT );
    }
    if( var_Type( p_aout, "audio-replay-gain-default" ) == 0 )
    {
        var_Create( p_aout, "audio-replay-gain-default",
                    VLC_VAR_FLOAT | VLC_VAR_DOINHERIT );
    }
    if( var_Type( p_aout, "audio-replay-gain-peak-protection" ) == 0 )
    {
        var_Create( p_aout, "audio-replay-gain-peak-protection",
                    VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
    }
    if( var_Type( p_aout, "audio-time-stretch" ) == 0 )
    {
        var_Create( p_aout, "audio-time-stretch",
                    VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
    }

    psz_filters = var_GetString( p_aout, "audio-filter" );
    psz_visual = var_GetString( p_aout, "audio-visual");
    psz_scaletempo = var_GetBool( p_aout, "audio-time-stretch" ) ? strdup( "scaletempo" ) : NULL;

    p_input->b_recycle_vout = psz_visual && *psz_visual;

    /* parse user filter lists */
    char *const ppsz_array[] = { psz_scaletempo, psz_filters, psz_visual };
    p_input->p_playback_rate_filter = NULL;

    for( i_visual = 0; i_visual < 3 && !AOUT_FMT_NON_LINEAR(&chain_output_format); i_visual++ )
    {
        char *psz_next = NULL;
        char *psz_parser = ppsz_array[i_visual];

        if( psz_parser == NULL || !*psz_parser )
            continue;

        while( psz_parser && *psz_parser )
        {
            filter_t * p_filter = NULL;

            if( p_input->i_nb_filters >= AOUT_MAX_FILTERS )
            {
                msg_Dbg( p_aout, "max filters reached (%d)", AOUT_MAX_FILTERS );
                break;
            }

            while( *psz_parser == ' ' && *psz_parser == ':' )
            {
                psz_parser++;
            }
            if( ( psz_next = strchr( psz_parser , ':'  ) ) )
            {
                *psz_next++ = '\0';
            }
            if( *psz_parser =='\0' )
            {
                break;
            }

            /* Create a VLC object */
            static const char typename[] = "audio filter";
            p_filter = vlc_custom_create( p_aout, sizeof(*p_filter),
                                          VLC_OBJECT_GENERIC, typename );
            if( p_filter == NULL )
            {
                msg_Err( p_aout, "cannot add user filter %s (skipped)",
                         psz_parser );
                psz_parser = psz_next;
                continue;
            }

            vlc_object_attach( p_filter , p_aout );

            p_filter->p_owner = malloc( sizeof(*p_filter->p_owner) );
            p_filter->p_owner->p_aout  = p_aout;
            p_filter->p_owner->p_input = p_input;

            /* request format */
            memcpy( &p_filter->fmt_in.audio, &chain_output_format,
                    sizeof(audio_sample_format_t) );
            p_filter->fmt_in.i_codec = chain_output_format.i_format;
            memcpy( &p_filter->fmt_out.audio, &chain_output_format,
                    sizeof(audio_sample_format_t) );
            p_filter->fmt_out.i_codec = chain_output_format.i_format;
            p_filter->pf_audio_buffer_new = aout_FilterBufferNew;

            /* try to find the requested filter */
            if( i_visual == 2 ) /* this can only be a visualization module */
            {
                p_filter->p_module = module_need( p_filter, "visualization2",
                                                  psz_parser, true );
            }
            else /* this can be a audio filter module as well as a visualization module */
            {
                p_filter->p_module = module_need( p_filter, "audio filter",
                                              psz_parser, true );

                if ( p_filter->p_module == NULL )
                {
                    /* if the filter requested a special format, retry */
                    if ( !( AOUT_FMTS_IDENTICAL( &p_filter->fmt_in.audio,
                                                 &chain_input_format )
                            && AOUT_FMTS_IDENTICAL( &p_filter->fmt_out.audio,
                                                    &chain_output_format ) ) )
                    {
                        aout_FormatPrepare( &p_filter->fmt_in.audio );
                        aout_FormatPrepare( &p_filter->fmt_out.audio );
                        p_filter->p_module = module_need( p_filter,
                                                          "audio filter",
                                                          psz_parser, true );
                    }
                    /* try visual filters */
                    else
                    {
                        memcpy( &p_filter->fmt_in.audio, &chain_output_format,
                                sizeof(audio_sample_format_t) );
                        memcpy( &p_filter->fmt_out.audio, &chain_output_format,
                                sizeof(audio_sample_format_t) );
                        p_filter->p_module = module_need( p_filter,
                                                          "visualization2",
                                                          psz_parser, true );
                    }
                }
            }

            /* failure */
            if ( p_filter->p_module == NULL )
            {
                msg_Err( p_aout, "cannot add user filter %s (skipped)",
                         psz_parser );

                free( p_filter->p_owner );
                vlc_object_release( p_filter );

                psz_parser = psz_next;
                continue;
            }

            /* complete the filter chain if necessary */
            if ( !AOUT_FMTS_IDENTICAL( &chain_input_format,
                                       &p_filter->fmt_in.audio ) )
            {
                if ( aout_FiltersCreatePipeline( p_aout, p_input->pp_filters,
                                                 &p_input->i_nb_filters,
                                                 &chain_input_format,
                                                 &p_filter->fmt_in.audio ) < 0 )
                {
                    msg_Err( p_aout, "cannot add user filter %s (skipped)",
                             psz_parser );

                    module_unneed( p_filter, p_filter->p_module );
                    free( p_filter->p_owner );
                    vlc_object_release( p_filter );

                    psz_parser = psz_next;
                    continue;
                }
            }

            /* success */
            p_input->pp_filters[p_input->i_nb_filters++] = p_filter;
            memcpy( &chain_input_format, &p_filter->fmt_out.audio,
                    sizeof( audio_sample_format_t ) );

            if( i_visual == 0 ) /* scaletempo */
                p_input->p_playback_rate_filter = p_filter;

            /* next filter if any */
            psz_parser = psz_next;
        }
    }
    free( psz_visual );
    free( psz_filters );
    free( psz_scaletempo );

    /* complete the filter chain if necessary */
    if ( !AOUT_FMTS_IDENTICAL( &chain_input_format, &chain_output_format ) )
    {
        if ( aout_FiltersCreatePipeline( p_aout, p_input->pp_filters,
                                         &p_input->i_nb_filters,
                                         &chain_input_format,
                                         &chain_output_format ) < 0 )
        {
            inputFailure( p_aout, p_input, "couldn't set an input pipeline" );
            return -1;
        }
    }

    /* Prepare hints for the buffer allocator. */
    p_input->input_alloc.b_alloc = true;
    p_input->input_alloc.i_bytes_per_sec = -1;

    /* Create resamplers. */
    if ( !AOUT_FMT_NON_LINEAR( &p_aout->mixer_format ) )
    {
        chain_output_format.i_rate = (__MAX(p_input->input.i_rate,
                                            p_aout->mixer_format.i_rate)
                                 * (100 + AOUT_MAX_RESAMPLING)) / 100;
        if ( chain_output_format.i_rate == p_aout->mixer_format.i_rate )
        {
            /* Just in case... */
            chain_output_format.i_rate++;
        }
        if ( aout_FiltersCreatePipeline( p_aout, p_input->pp_resamplers,
                                         &p_input->i_nb_resamplers,
                                         &chain_output_format,
                                         &p_aout->mixer_format ) < 0 )
        {
            inputFailure( p_aout, p_input, "couldn't set a resampler pipeline");
            return -1;
        }

        aout_FiltersHintBuffers( p_aout, p_input->pp_resamplers,
                                 p_input->i_nb_resamplers,
                                 &p_input->input_alloc );
        p_input->input_alloc.b_alloc = true;

        /* Setup the initial rate of the resampler */
        p_input->pp_resamplers[0]->fmt_in.audio.i_rate = p_input->input.i_rate;
    }
    p_input->i_resampling_type = AOUT_RESAMPLING_NONE;

    if( ! p_input->p_playback_rate_filter && p_input->i_nb_resamplers > 0 )
    {
        p_input->p_playback_rate_filter = p_input->pp_resamplers[0];
    }

    aout_FiltersHintBuffers( p_aout, p_input->pp_filters,
                             p_input->i_nb_filters,
                             &p_input->input_alloc );
    p_input->input_alloc.b_alloc = true;

    /* i_bytes_per_sec is still == -1 if no filters */
    p_input->input_alloc.i_bytes_per_sec = __MAX(
                                    p_input->input_alloc.i_bytes_per_sec,
                                    (int)(p_input->input.i_bytes_per_frame
                                     * p_input->input.i_rate
                                     / p_input->input.i_frame_length) );

    ReplayGainSelect( p_aout, p_input );

    /* Success */
    p_input->b_error = false;
    p_input->i_last_input_rate = INPUT_RATE_DEFAULT;

    return 0;
}
Ejemplo n.º 9
0
static int transcode_audio_filter_chain_build( sout_stream_t *p_stream, filter_chain_t *p_chain,
                                               const es_format_t *p_dst, const es_format_t *p_src )
{
    if( !transcode_audio_filter_needed( p_dst, p_src ) )
        return VLC_SUCCESS;

    es_format_t current = *p_src;

    msg_Dbg( p_stream, "Looking for filter "
             "(%4.4s->%4.4s, channels %d->%d, rate %d->%d)",
         (const char *)&p_src->i_codec,
         (const char *)&p_dst->i_codec,
         p_src->audio.i_channels,
         p_dst->audio.i_channels,
         p_src->audio.i_rate,
         p_dst->audio.i_rate );

    /* If any filter is needed, convert to fl32 */
    if( current.i_codec != VLC_CODEC_FL32 )
    {
        /* First step, convert to fl32 */
        current.i_codec =
        current.audio.i_format = VLC_CODEC_FL32;
        aout_FormatPrepare( &current.audio );

        if( !filter_chain_AppendFilter( p_chain, NULL, NULL, NULL, &current ) )
        {
            msg_Err( p_stream, "Failed to find conversion filter to fl32" );
            return VLC_EGENERIC;
        }
        current = *filter_chain_GetFmtOut( p_chain );
    }

    /* Fix sample rate */
    if( current.audio.i_rate != p_dst->audio.i_rate )
    {
        current.audio.i_rate = p_dst->audio.i_rate;
        aout_FormatPrepare( &current.audio );
        if( !filter_chain_AppendFilter( p_chain, NULL, NULL, NULL, &current ) )
        {
            msg_Err( p_stream, "Failed to find conversion filter for resampling" );
            return VLC_EGENERIC;
        }
        current = *filter_chain_GetFmtOut( p_chain );
    }

    /* Fix channels */
    if( current.audio.i_channels != p_dst->audio.i_channels )
    {
        current.audio.i_channels = p_dst->audio.i_channels;
        current.audio.i_physical_channels = p_dst->audio.i_physical_channels;
        current.audio.i_original_channels = p_dst->audio.i_original_channels;

        if( ( !current.audio.i_physical_channels || !current.audio.i_original_channels ) &&
            current.audio.i_channels < 6 )
            current.audio.i_physical_channels =
            current.audio.i_original_channels = pi_channels_maps[current.audio.i_channels];

        aout_FormatPrepare( &current.audio );
        if( !filter_chain_AppendFilter( p_chain, NULL, NULL, NULL, &current ) )
        {
            msg_Err( p_stream, "Failed to find conversion filter for channel mixing" );
            return VLC_EGENERIC;
        }
        current = *filter_chain_GetFmtOut( p_chain );
    }
    /* And last step, convert to the requested codec */
    if( current.i_codec != p_dst->i_codec )
    {
        current.i_codec = p_dst->i_codec;
        aout_FormatPrepare( &current.audio );
        if( !filter_chain_AppendFilter( p_chain, NULL, NULL, NULL, &current ) )
        {
            msg_Err( p_stream, "Failed to find conversion filter to %4.4s",
                     (const char*)&p_dst->i_codec);
            return VLC_EGENERIC;
        }
        current = *filter_chain_GetFmtOut( p_chain );
    }

    if( transcode_audio_filter_needed( p_dst, &current ) )
    {
        /* Weird case, a filter has side effects, doomed */
        msg_Err( p_stream, "Failed to create a valid audio filter chain" );
        return VLC_EGENERIC;
    }

    msg_Dbg( p_stream, "Got complete audio filter chain" );
    return VLC_SUCCESS;
}
Ejemplo n.º 10
0
Archivo: oss.c Proyecto: forthyen/SDesk
/*****************************************************************************
 * Open: open the audio device (the digital sound processor)
 *****************************************************************************
 * This function opens the DSP as a usual non-blocking write-only file, and
 * modifies the p_aout->p_sys->i_fd with the file's descriptor.
 *****************************************************************************/
static int Open( vlc_object_t *p_this )
{
    aout_instance_t * p_aout = (aout_instance_t *)p_this;
    struct aout_sys_t * p_sys;
    char * psz_device;
    vlc_value_t val;

    /* Allocate structure */
    p_aout->output.p_sys = p_sys = malloc( sizeof( aout_sys_t ) );
    if( p_sys == NULL )
    {
        msg_Err( p_aout, "out of memory" );
        return VLC_ENOMEM;
    }

    /* Get device name */
    if( (psz_device = config_GetPsz( p_aout, "dspdev" )) == NULL )
    {
        msg_Err( p_aout, "no audio device specified (maybe /dev/dsp?)" );
        free( p_sys );
        return VLC_EGENERIC;
    }

    /* Open the sound device in non-blocking mode, because ALSA's OSS
     * emulation and some broken OSS drivers would make a blocking call
     * wait forever until the device is available. Since this breaks the
     * OSS spec, we immediately put it back to blocking mode if the
     * operation was successful. */
    p_sys->i_fd = open( psz_device, O_WRONLY | O_NDELAY );
    if( p_sys->i_fd < 0 )
    {
        msg_Err( p_aout, "cannot open audio device (%s)", psz_device );
        free( p_sys );
        return VLC_EGENERIC;
    }

    /* if the opening was ok, put the device back in blocking mode */
    fcntl( p_sys->i_fd, F_SETFL,
            fcntl( p_sys->i_fd, F_GETFL ) &~ FNDELAY );

    free( psz_device );

    p_aout->output.pf_play = Play;

    if ( var_Type( p_aout, "audio-device" ) == 0 )
    {
        Probe( p_aout );
    }

    if ( var_Get( p_aout, "audio-device", &val ) < 0 )
    {
        /* Probe() has failed. */
        free( p_sys );
        return VLC_EGENERIC;
    }

    if ( val.i_int == AOUT_VAR_SPDIF )
    {
        p_aout->output.output.i_format = VLC_FOURCC('s','p','d','i');
    }
    else if ( val.i_int == AOUT_VAR_5_1 )
    {
        p_aout->output.output.i_format = AOUT_FMT_S16_NE;
        p_aout->output.output.i_physical_channels
            = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
               | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
               | AOUT_CHAN_LFE;
    }
    else if ( val.i_int == AOUT_VAR_2F2R )
    {
        p_aout->output.output.i_format = AOUT_FMT_S16_NE;
        p_aout->output.output.i_physical_channels
            = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
               | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
    }
    else if ( val.i_int == AOUT_VAR_STEREO )
    {
        p_aout->output.output.i_format = AOUT_FMT_S16_NE;
        p_aout->output.output.i_physical_channels
            = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
    }
    else if ( val.i_int == AOUT_VAR_MONO )
    {
        p_aout->output.output.i_format = AOUT_FMT_S16_NE;
        p_aout->output.output.i_physical_channels = AOUT_CHAN_CENTER;
    }
    else
    {
        /* This should not happen ! */
        msg_Err( p_aout, "internal: can't find audio-device (%i)", val.i_int );
        free( p_sys );
        return VLC_EGENERIC;
    }

    val.b_bool = VLC_TRUE;
    var_Set( p_aout, "intf-change", val );

    /* Reset the DSP device */
    if( ioctl( p_sys->i_fd, SNDCTL_DSP_RESET, NULL ) < 0 )
    {
        msg_Err( p_aout, "cannot reset OSS audio device" );
        close( p_sys->i_fd );
        free( p_sys );
        return VLC_EGENERIC;
    }

    /* Set the output format */
    if ( AOUT_FMT_NON_LINEAR( &p_aout->output.output ) )
    {
        int i_format = AFMT_AC3;

        if( ioctl( p_sys->i_fd, SNDCTL_DSP_SETFMT, &i_format ) < 0
             || i_format != AFMT_AC3 )
        {
            msg_Err( p_aout, "cannot reset OSS audio device" );
            close( p_sys->i_fd );
            free( p_sys );
            return VLC_EGENERIC;
        }

        p_aout->output.output.i_format = VLC_FOURCC('s','p','d','i');
        p_aout->output.i_nb_samples = A52_FRAME_NB;
        p_aout->output.output.i_bytes_per_frame = AOUT_SPDIF_SIZE;
        p_aout->output.output.i_frame_length = A52_FRAME_NB;

        aout_VolumeNoneInit( p_aout );
    }

    if ( !AOUT_FMT_NON_LINEAR( &p_aout->output.output ) )
    {
        unsigned int i_format = AFMT_S16_NE;
        unsigned int i_frame_size, i_fragments;
        unsigned int i_rate;
        unsigned int i_nb_channels;
        audio_buf_info audio_buf;

        if( ioctl( p_sys->i_fd, SNDCTL_DSP_SETFMT, &i_format ) < 0 )
        {
            msg_Err( p_aout, "cannot set audio output format" );
            close( p_sys->i_fd );
            free( p_sys );
            return VLC_EGENERIC;
        }

        switch ( i_format )
        {
        case AFMT_U8:
            p_aout->output.output.i_format = VLC_FOURCC('u','8',' ',' ');
            break;
        case AFMT_S8:
            p_aout->output.output.i_format = VLC_FOURCC('s','8',' ',' ');
            break;
        case AFMT_U16_LE:
            p_aout->output.output.i_format = VLC_FOURCC('u','1','6','l');
            break;
        case AFMT_S16_LE:
            p_aout->output.output.i_format = VLC_FOURCC('s','1','6','l');
            break;
        case AFMT_U16_BE:
            p_aout->output.output.i_format = VLC_FOURCC('u','1','6','b');
            break;
        case AFMT_S16_BE:
            p_aout->output.output.i_format = VLC_FOURCC('s','1','6','b');
            break;
        default:
            msg_Err( p_aout, "OSS fell back to an unknown format (%d)",
                     i_format );
            close( p_sys->i_fd );
            free( p_sys );
            return VLC_EGENERIC;
        }

        i_nb_channels = aout_FormatNbChannels( &p_aout->output.output );

        /* Set the number of channels */
        if( ioctl( p_sys->i_fd, SNDCTL_DSP_CHANNELS, &i_nb_channels ) < 0 ||
            i_nb_channels != aout_FormatNbChannels( &p_aout->output.output ) )
        {
            msg_Err( p_aout, "cannot set number of audio channels (%s)",
                     aout_FormatPrintChannels( &p_aout->output.output) );
            close( p_sys->i_fd );
            free( p_sys );
            return VLC_EGENERIC;
        }

        /* Set the output rate */
        i_rate = p_aout->output.output.i_rate;
        if( ioctl( p_sys->i_fd, SNDCTL_DSP_SPEED, &i_rate ) < 0 )
        {
            msg_Err( p_aout, "cannot set audio output rate (%i)",
                             p_aout->output.output.i_rate );
            close( p_sys->i_fd );
            free( p_sys );
            return VLC_EGENERIC;
        }

        if( i_rate != p_aout->output.output.i_rate )
        {
            p_aout->output.output.i_rate = i_rate;
        }

        /* Set the fragment size */
        aout_FormatPrepare( &p_aout->output.output );

        /* i_fragment = xxxxyyyy where: xxxx        is fragtotal
         *                              1 << yyyy   is fragsize */
        i_fragments = 0;
        i_frame_size = FRAME_SIZE * p_aout->output.output.i_bytes_per_frame;
        while( i_frame_size >>= 1 )
        {
            ++i_fragments;
        }
        i_fragments |= FRAME_COUNT << 16;
        if( ioctl( p_sys->i_fd, SNDCTL_DSP_SETFRAGMENT, &i_fragments ) < 0 )
        {
            msg_Warn( p_aout, "cannot set fragment size (%.8x)", i_fragments );
        }

        if( ioctl( p_sys->i_fd, SNDCTL_DSP_GETOSPACE, &audio_buf ) < 0 )
        {
            msg_Err( p_aout, "cannot get fragment size" );
            close( p_sys->i_fd );
            free( p_sys );
            return VLC_EGENERIC;
        }
        else
        {
            /* Number of fragments actually allocated */
            p_aout->output.p_sys->i_fragstotal = audio_buf.fragstotal;

            /* Maximum duration the soundcard's buffer can hold */
            p_aout->output.p_sys->max_buffer_duration =
                (mtime_t)audio_buf.fragstotal * audio_buf.fragsize * 1000000
                / p_aout->output.output.i_bytes_per_frame
                / p_aout->output.output.i_rate
                * p_aout->output.output.i_frame_length;

            p_aout->output.i_nb_samples = audio_buf.fragsize /
                p_aout->output.output.i_bytes_per_frame;
        }

        aout_VolumeSoftInit( p_aout );
    }
Ejemplo n.º 11
0
/*****************************************************************************
 * aout_InputNew : allocate a new input and rework the filter pipeline
 *****************************************************************************/
int aout_InputNew( aout_instance_t * p_aout, aout_input_t * p_input )
{
    audio_sample_format_t chain_input_format;
    audio_sample_format_t chain_output_format;
    vlc_value_t val, text;
    char * psz_filters, *psz_visual;
    int i_visual;

    aout_FormatPrint( p_aout, "input", &p_input->input );

    p_input->i_nb_filters = 0;

    /* Prepare FIFO. */
    aout_FifoInit( p_aout, &p_input->fifo, p_aout->mixer.mixer.i_rate );
    p_input->p_first_byte_to_mix = NULL;

    /* Prepare format structure */
    memcpy( &chain_input_format, &p_input->input,
            sizeof(audio_sample_format_t) );
    memcpy( &chain_output_format, &p_aout->mixer.mixer,
            sizeof(audio_sample_format_t) );
    chain_output_format.i_rate = p_input->input.i_rate;
    aout_FormatPrepare( &chain_output_format );

    /* Now add user filters */
    if( var_Type( p_aout, "visual" ) == 0 )
    {
        module_t *p_module;
        var_Create( p_aout, "visual", VLC_VAR_STRING | VLC_VAR_HASCHOICE );
        text.psz_string = _("Visualizations");
        var_Change( p_aout, "visual", VLC_VAR_SETTEXT, &text, NULL );
        val.psz_string = ""; text.psz_string = _("Disable");
        var_Change( p_aout, "visual", VLC_VAR_ADDCHOICE, &val, &text );
        val.psz_string = "spectrometer"; text.psz_string = _("Spectrometer");
        var_Change( p_aout, "visual", VLC_VAR_ADDCHOICE, &val, &text );
        val.psz_string = "scope"; text.psz_string = _("Scope");
        var_Change( p_aout, "visual", VLC_VAR_ADDCHOICE, &val, &text );
        val.psz_string = "spectrum"; text.psz_string = _("Spectrum");
        var_Change( p_aout, "visual", VLC_VAR_ADDCHOICE, &val, &text );

        /* Look for goom plugin */
        p_module = config_FindModule( VLC_OBJECT(p_aout), "goom" );
        if( p_module )
        {
            val.psz_string = "goom"; text.psz_string = "Goom";
            var_Change( p_aout, "visual", VLC_VAR_ADDCHOICE, &val, &text );
        }

        /* Look for galaktos plugin */
        p_module = config_FindModule( VLC_OBJECT(p_aout), "galaktos" );
        if( p_module )
        {
            val.psz_string = "galaktos"; text.psz_string = "GaLaktos";
            var_Change( p_aout, "visual", VLC_VAR_ADDCHOICE, &val, &text );
        }

        if( var_Get( p_aout, "effect-list", &val ) == VLC_SUCCESS )
        {
            var_Set( p_aout, "visual", val );
            if( val.psz_string ) free( val.psz_string );
        }
        var_AddCallback( p_aout, "visual", VisualizationCallback, NULL );
    }

    if( var_Type( p_aout, "equalizer" ) == 0 )
    {
        module_config_t *p_config;
        int i;

        p_config = config_FindConfig( VLC_OBJECT(p_aout), "equalizer-preset" );
        if( p_config && p_config->i_list )
        {
               var_Create( p_aout, "equalizer",
                           VLC_VAR_STRING | VLC_VAR_HASCHOICE );
            text.psz_string = _("Equalizer");
            var_Change( p_aout, "equalizer", VLC_VAR_SETTEXT, &text, NULL );

            val.psz_string = ""; text.psz_string = _("Disable");
            var_Change( p_aout, "equalizer", VLC_VAR_ADDCHOICE, &val, &text );

            for( i = 0; i < p_config->i_list; i++ )
            {
                val.psz_string = p_config->ppsz_list[i];
                text.psz_string = p_config->ppsz_list_text[i];
                var_Change( p_aout, "equalizer", VLC_VAR_ADDCHOICE,
                            &val, &text );
            }

            var_AddCallback( p_aout, "equalizer", EqualizerCallback, NULL );
        }
    }

    if( var_Type( p_aout, "audio-filter" ) == 0 )
    {
        var_Create( p_aout, "audio-filter",
                    VLC_VAR_STRING | VLC_VAR_DOINHERIT );
        text.psz_string = _("Audio filters");
        var_Change( p_aout, "audio-filter", VLC_VAR_SETTEXT, &text, NULL );
    }
    if( var_Type( p_aout, "audio-visual" ) == 0 )
    {
        var_Create( p_aout, "audio-visual",
                    VLC_VAR_STRING | VLC_VAR_DOINHERIT );
        text.psz_string = _("Audio visualizations");
        var_Change( p_aout, "audio-visual", VLC_VAR_SETTEXT, &text, NULL );
    }

    var_Get( p_aout, "audio-filter", &val );
    psz_filters = val.psz_string;
    var_Get( p_aout, "audio-visual", &val );
    psz_visual = val.psz_string;

    /* parse user filter lists */
    for( i_visual = 0; i_visual < 2; i_visual++ )
    {
        char *psz_next = NULL;
        char *psz_parser = i_visual ? psz_visual : psz_filters;

        if( psz_parser == NULL || !*psz_parser )
            continue;

        while( psz_parser && *psz_parser )
        {
            aout_filter_t * p_filter = NULL;

            if( p_input->i_nb_filters >= AOUT_MAX_FILTERS )
            {
                msg_Dbg( p_aout, "max filters reached (%d)", AOUT_MAX_FILTERS );
                break;
            }

            while( *psz_parser == ' ' && *psz_parser == ':' )
            {
                psz_parser++;
            }
            if( ( psz_next = strchr( psz_parser , ':'  ) ) )
            {
                *psz_next++ = '\0';
            }
            if( *psz_parser =='\0' )
            {
                break;
            }

            /* Create a VLC object */
            p_filter = vlc_object_create( p_aout, sizeof(aout_filter_t) );
            if( p_filter == NULL )
            {
                msg_Err( p_aout, "cannot add user filter %s (skipped)",
                         psz_parser );
                psz_parser = psz_next;
                continue;
            }

            vlc_object_attach( p_filter , p_aout );

            /* try to find the requested filter */
            if( i_visual == 1 ) /* this can only be a visualization module */
            {
                /* request format */
                memcpy( &p_filter->input, &chain_output_format,
                        sizeof(audio_sample_format_t) );
                memcpy( &p_filter->output, &chain_output_format,
                        sizeof(audio_sample_format_t) );

                p_filter->p_module = module_Need( p_filter, "visualization",
                                                  psz_parser, VLC_TRUE );
            }
            else /* this can be a audio filter module as well as a visualization module */
            {
                /* request format */
                memcpy( &p_filter->input, &chain_input_format,
                        sizeof(audio_sample_format_t) );
                memcpy( &p_filter->output, &chain_output_format,
                        sizeof(audio_sample_format_t) );

                p_filter->p_module = module_Need( p_filter, "audio filter",
                                              psz_parser, VLC_TRUE );

                if ( p_filter->p_module == NULL )
                {
                    /* if the filter requested a special format, retry */
                    if ( !( AOUT_FMTS_IDENTICAL( &p_filter->input,
                                                 &chain_input_format )
                            && AOUT_FMTS_IDENTICAL( &p_filter->output,
                                                    &chain_output_format ) ) )
                    {
                        aout_FormatPrepare( &p_filter->input );
                        aout_FormatPrepare( &p_filter->output );
                        p_filter->p_module = module_Need( p_filter,
                                                          "audio filter",
                                                          psz_parser, VLC_TRUE );
                    }
                    /* try visual filters */
                    else
                    {
                        memcpy( &p_filter->input, &chain_output_format,
                                sizeof(audio_sample_format_t) );
                        memcpy( &p_filter->output, &chain_output_format,
                                sizeof(audio_sample_format_t) );
                        p_filter->p_module = module_Need( p_filter,
                                                          "visualization",
                                                          psz_parser, VLC_TRUE );
                    }
                }
            }

            /* failure */
            if ( p_filter->p_module == NULL )
            {
                msg_Err( p_aout, "cannot add user filter %s (skipped)",
                         psz_parser );

                vlc_object_detach( p_filter );
                vlc_object_destroy( p_filter );

                psz_parser = psz_next;
                continue;
            }

            /* complete the filter chain if necessary */
            if ( !AOUT_FMTS_IDENTICAL( &chain_input_format, &p_filter->input ) )
            {
                if ( aout_FiltersCreatePipeline( p_aout, p_input->pp_filters,
                                                 &p_input->i_nb_filters,
                                                 &chain_input_format,
                                                 &p_filter->input ) < 0 )
                {
                    msg_Err( p_aout, "cannot add user filter %s (skipped)",
                             psz_parser );

                    module_Unneed( p_filter, p_filter->p_module );
                    vlc_object_detach( p_filter );
                    vlc_object_destroy( p_filter );

                    psz_parser = psz_next;
                    continue;
                }
            }

            /* success */
            p_filter->b_continuity = VLC_FALSE;
            p_input->pp_filters[p_input->i_nb_filters++] = p_filter;
            memcpy( &chain_input_format, &p_filter->output,
                    sizeof( audio_sample_format_t ) );

            /* next filter if any */
            psz_parser = psz_next;
        }
    }
    if( psz_filters ) free( psz_filters );
    if( psz_visual ) free( psz_visual );

    /* complete the filter chain if necessary */
    if ( !AOUT_FMTS_IDENTICAL( &chain_input_format, &chain_output_format ) )
    {
        if ( aout_FiltersCreatePipeline( p_aout, p_input->pp_filters,
                                         &p_input->i_nb_filters,
                                         &chain_input_format,
                                         &chain_output_format ) < 0 )
        {
            inputFailure( p_aout, p_input, "couldn't set an input pipeline" );
            return -1;
        }
    }

    /* Prepare hints for the buffer allocator. */
    p_input->input_alloc.i_alloc_type = AOUT_ALLOC_HEAP;
    p_input->input_alloc.i_bytes_per_sec = -1;

    /* Create resamplers. */
    if ( AOUT_FMT_NON_LINEAR( &p_aout->mixer.mixer ) )
    {
        p_input->i_nb_resamplers = 0;
    }
    else
    {
        chain_output_format.i_rate = (__MAX(p_input->input.i_rate,
                                            p_aout->mixer.mixer.i_rate)
                                 * (100 + AOUT_MAX_RESAMPLING)) / 100;
        if ( chain_output_format.i_rate == p_aout->mixer.mixer.i_rate )
        {
            /* Just in case... */
            chain_output_format.i_rate++;
        }
        p_input->i_nb_resamplers = 0;
        if ( aout_FiltersCreatePipeline( p_aout, p_input->pp_resamplers,
                                         &p_input->i_nb_resamplers,
                                         &chain_output_format,
                                         &p_aout->mixer.mixer ) < 0 )
        {
            inputFailure( p_aout, p_input, "couldn't set a resampler pipeline");
            return -1;
        }

        aout_FiltersHintBuffers( p_aout, p_input->pp_resamplers,
                                 p_input->i_nb_resamplers,
                                 &p_input->input_alloc );
        p_input->input_alloc.i_alloc_type = AOUT_ALLOC_HEAP;

        /* Setup the initial rate of the resampler */
        p_input->pp_resamplers[0]->input.i_rate = p_input->input.i_rate;
    }
    p_input->i_resampling_type = AOUT_RESAMPLING_NONE;

    aout_FiltersHintBuffers( p_aout, p_input->pp_filters,
                             p_input->i_nb_filters,
                             &p_input->input_alloc );
    p_input->input_alloc.i_alloc_type = AOUT_ALLOC_HEAP;

    /* i_bytes_per_sec is still == -1 if no filters */
    p_input->input_alloc.i_bytes_per_sec = __MAX(
                                    p_input->input_alloc.i_bytes_per_sec,
                                    (int)(p_input->input.i_bytes_per_frame
                                     * p_input->input.i_rate
                                     / p_input->input.i_frame_length) );

    /* Success */
    p_input->b_error = VLC_FALSE;
    p_input->b_restart = VLC_FALSE;

    return 0;
}
Ejemplo n.º 12
0
static int Open(vlc_object_t *object)
{
    filter_t     *filter = (filter_t *)object;

    const es_format_t *src = &filter->fmt_in;
    es_format_t       *dst = &filter->fmt_out;

    if (!AOUT_FMTS_SIMILAR(&src->audio, &dst->audio))
        return VLC_EGENERIC;
    if (src->i_codec == dst->i_codec)
        return VLC_EGENERIC;

    cvt_direct_t direct = FindDirect(src->i_codec, dst->i_codec);
    if (direct) {
        filter->pf_audio_filter = direct;
        filter->p_sys = NULL;
        goto end;
    }

    /* */
    filter_sys_t *sys = malloc(sizeof(*sys));
    if (!sys)
        return VLC_ENOMEM;

    /* Find the cost minimal conversion */
    for (unsigned mask = 0; mask <= 0x07; mask++) {
        memset(sys, 0, sizeof(*sys));

        vlc_fourcc_t fsrc = src->i_codec;
        vlc_fourcc_t fdst = dst->i_codec;

        if (mask & 0x01) {
            sys->pre = FindSwap(&fsrc, fsrc);
            if (!sys->pre)
                continue;
        }
        if (mask & 0x02) {
            sys->post = FindSwap(&fdst, fdst);
            if (!sys->post)
                continue;
        }

        const bool has_middle = mask & 0x04;
        for (int i = 0; fsrc != fdst && i < 1 + has_middle; i++) {
            /* XXX Hardcoded middle format: native 16 bits */
            vlc_fourcc_t ftarget = has_middle && i == 0 ? VLC_CODEC_S16N : fdst;
            sys->directs[i] = FindDirect(fsrc, ftarget);
            if (!sys->directs[i]) {
                sys->indirects[i] = FindIndirect(fsrc, ftarget);
                if (!sys->indirects[i])
                    break;
                sys->indirects_ratio[i][0] = aout_BitsPerSample(fsrc) / 8;
                sys->indirects_ratio[i][1] = aout_BitsPerSample(ftarget) / 8;
            }
            fsrc = ftarget;
        }
        if (fsrc != fdst)
            continue;

        /* We have a full conversion */
        filter->pf_audio_filter = Filter;
        filter->p_sys = sys;
        goto end;
    }
    free(sys);
    return VLC_EGENERIC;

end:
    dst->audio = src->audio;
    dst->audio.i_format = dst->i_codec;
    aout_FormatPrepare(&dst->audio);

    msg_Dbg(filter, "%4.4s->%4.4s, bits per sample: %i->%i",
            (char *)&src->i_codec, (char *)&dst->i_codec,
            src->audio.i_bitspersample, dst->audio.i_bitspersample);
    return VLC_SUCCESS;
}
Ejemplo n.º 13
0
/*****************************************************************************
 * DecoderOpen: probe the decoder and return score
 *****************************************************************************/
static int DecoderOpen( vlc_object_t *p_this )
{
    decoder_t *p_dec = (decoder_t*)p_this;
    vlc_fourcc_t format = p_dec->fmt_in.i_codec;

    switch( p_dec->fmt_in.i_codec )
    {
    case VLC_FOURCC('a','r','a','w'):
    case VLC_FOURCC('a','f','l','t'):
    /* _signed_ big endian samples (mov) */
    case VLC_FOURCC('t','w','o','s'):
    /* _signed_ little endian samples (mov) */
    case VLC_FOURCC('s','o','w','t'):
        format =
            vlc_fourcc_GetCodecAudio( p_dec->fmt_in.i_codec,
                                      p_dec->fmt_in.audio.i_bitspersample );
        if( !format )
        {
            msg_Err( p_dec, "bad parameters(bits/sample)" );
            return VLC_EGENERIC;
        }
        break;
    }

    void (*decode) (void *, const uint8_t *, unsigned) = NULL;
    uint_fast8_t bits;

    switch( format )
    {
#ifdef WORDS_BIGENDIAN
    case VLC_CODEC_F64L:
#else
    case VLC_CODEC_F64B:
#endif
        format = VLC_CODEC_FL64;
        decode = F64IDecode;
        bits = 64;
        break;
    case VLC_CODEC_FL64:
        decode = F64NDecode;
        bits = 64;
        break;
#ifdef WORDS_BIGENDIAN
    case VLC_CODEC_F32L:
#else
    case VLC_CODEC_F32B:
#endif
        format = VLC_CODEC_FL32;
        decode = F32IDecode;
        bits = 32;
        break;
    case VLC_CODEC_FL32:
        decode = F32NDecode;
        bits = 32;
        break;
    case VLC_CODEC_U32B:
        format = VLC_CODEC_S32N;
        decode = U32BDecode;
        bits = 32;
        break;
    case VLC_CODEC_U32L:
        format = VLC_CODEC_S32N;
        decode = U32LDecode;
        bits = 32;
        break;
    case VLC_CODEC_S32I:
        format = VLC_CODEC_S32N;
        decode = S32IDecode;
        /* fall through */
    case VLC_CODEC_S32N:
        bits = 32;
        break;
    case VLC_CODEC_S24B32:
        format = VLC_CODEC_S32N;
        decode = S24B32Decode;
        bits = 32;
        break;
    case VLC_CODEC_S24L32:
        format = VLC_CODEC_S32N;
        decode = S24L32Decode;
        bits = 32;
        break;
    case VLC_CODEC_U24B:
        format = VLC_CODEC_S32N;
        decode = U24BDecode;
        bits = 24;
        break;
    case VLC_CODEC_U24L:
        format = VLC_CODEC_S32N;
        decode = U24LDecode;
        bits = 24;
        break;
    case VLC_CODEC_S24B:
        format = VLC_CODEC_S32N;
        decode = S24BDecode;
        bits = 24;
        break;
    case VLC_CODEC_S24L:
        format = VLC_CODEC_S32N;
        decode = S24LDecode;
        bits = 24;
        break;
    case VLC_CODEC_S20B:
        format = VLC_CODEC_S32N;
        decode = S20BDecode;
        bits = 20;
        break;
    case VLC_CODEC_U16B:
        format = VLC_CODEC_S16N;
        decode = U16BDecode;
        bits = 16;
        break;
    case VLC_CODEC_U16L:
        format = VLC_CODEC_S16N;
        decode = U16LDecode;
        bits = 16;
        break;
    case VLC_CODEC_S16I:
        format = VLC_CODEC_S16N;
        decode = S16IDecode;
        /* fall through */
    case VLC_CODEC_S16N:
        bits = 16;
        break;
    case VLC_CODEC_DAT12:
        format = VLC_CODEC_S16N;
        decode = DAT12Decode;
        bits = 12;
        break;
    case VLC_CODEC_S8:
        decode = S8Decode;
        format = VLC_CODEC_U8;
        /* fall through */
    case VLC_CODEC_U8:
        bits = 8;
        break;
    default:
        return VLC_EGENERIC;
    }

    if( p_dec->fmt_in.audio.i_channels == 0 ||
        p_dec->fmt_in.audio.i_channels > INPUT_CHAN_MAX )
    {
        msg_Err( p_dec, "bad channels count (1-%i): %i",
                 AOUT_CHAN_MAX, p_dec->fmt_in.audio.i_channels );
        return VLC_EGENERIC;
    }

    if( p_dec->fmt_in.audio.i_rate == 0 || p_dec->fmt_in.audio.i_rate > 384000 )
    {
        msg_Err( p_dec, "bad samplerate: %d Hz", p_dec->fmt_in.audio.i_rate );
        return VLC_EGENERIC;
    }

    msg_Dbg( p_dec, "samplerate:%dHz channels:%d bits/sample:%d",
             p_dec->fmt_in.audio.i_rate, p_dec->fmt_in.audio.i_channels,
             p_dec->fmt_in.audio.i_bitspersample );

    /* Allocate the memory needed to store the decoder's structure */
    decoder_sys_t *p_sys = malloc(sizeof(*p_sys));
    if( unlikely(p_sys == NULL) )
        return VLC_ENOMEM;

    /* Set output properties */
    p_dec->fmt_out.i_codec = format;
    p_dec->fmt_out.audio.channel_type = p_dec->fmt_in.audio.channel_type;
    p_dec->fmt_out.audio.i_format = format;
    p_dec->fmt_out.audio.i_rate = p_dec->fmt_in.audio.i_rate;
    if( p_dec->fmt_in.audio.i_channels <= ARRAY_SIZE( pi_channels_maps ) - 1 )
    {
        if( p_dec->fmt_in.audio.i_physical_channels )
            p_dec->fmt_out.audio.i_physical_channels =
                                           p_dec->fmt_in.audio.i_physical_channels;
        else
            p_dec->fmt_out.audio.i_physical_channels =
                                  pi_channels_maps[p_dec->fmt_in.audio.i_channels];
    }
    else
    {
        /* Unknown channel map, let the aout/filters decide what to do */
        p_dec->fmt_out.audio.i_channels = p_dec->fmt_in.audio.i_channels;
        p_dec->fmt_out.audio.i_physical_channels = 0;
    }
    aout_FormatPrepare( &p_dec->fmt_out.audio );

    p_sys->decode = decode;
    p_sys->framebits = bits * p_dec->fmt_out.audio.i_channels;
    assert( p_sys->framebits );

    date_Init( &p_sys->end_date, p_dec->fmt_out.audio.i_rate, 1 );
    date_Set( &p_sys->end_date, 0 );

    p_dec->pf_decode = DecodeBlock;
    p_dec->pf_flush  = Flush;
    p_dec->p_sys = p_sys;

    return VLC_SUCCESS;
}
Ejemplo n.º 14
0
Archivo: dec.c Proyecto: forthyen/SDesk
/*****************************************************************************
 * 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;
}
Ejemplo n.º 15
0
static int audio_update_format( decoder_t *p_dec )
{
    aout_FormatPrepare( &p_dec->fmt_out.audio );
    return 0;
}
Ejemplo n.º 16
0
Archivo: oss.c Proyecto: CSRedRat/vlc
/*****************************************************************************
 * Open: open the audio device (the digital sound processor)
 *****************************************************************************
 * This function opens the DSP as a usual non-blocking write-only file, and
 * modifies the p_aout->p_sys->i_fd with the file's descriptor.
 *****************************************************************************/
static int Open( vlc_object_t *p_this )
{
    audio_output_t * p_aout = (audio_output_t *)p_this;
    struct aout_sys_t * p_sys;
    char * psz_device;
    vlc_value_t val;

    /* Allocate structure */
    p_aout->sys = p_sys = malloc( sizeof( aout_sys_t ) );
    if( p_sys == NULL )
        return VLC_ENOMEM;

    /* Get device name */
    if( (psz_device = var_InheritString( p_aout, "oss-audio-device" )) == NULL )
    {
        msg_Err( p_aout, "no audio device specified (maybe /dev/dsp?)" );
        free( p_sys );
        return VLC_EGENERIC;
    }

    /* Open the sound device in non-blocking mode, because ALSA's OSS
     * emulation and some broken OSS drivers would make a blocking call
     * wait forever until the device is available. Since this breaks the
     * OSS spec, we immediately put it back to blocking mode if the
     * operation was successful. */
    p_sys->i_fd = vlc_open( psz_device, O_WRONLY | O_NDELAY );
    if( p_sys->i_fd < 0 )
    {
        msg_Err( p_aout, "cannot open audio device (%s)", psz_device );
        free( psz_device );
        free( p_sys );
        return VLC_EGENERIC;
    }

    /* if the opening was ok, put the device back in blocking mode */
    fcntl( p_sys->i_fd, F_SETFL,
            fcntl( p_sys->i_fd, F_GETFL ) &~ FNDELAY );

    free( psz_device );

    p_aout->pf_play = aout_PacketPlay;
    p_aout->pf_pause = aout_PacketPause;
    p_aout->pf_flush = aout_PacketFlush;

    if ( var_Type( p_aout, "audio-device" ) == 0 )
        Probe( p_aout );
    var_AddCallback( p_aout, "audio-device", aout_ChannelsRestart, NULL );

    if ( var_Get( p_aout, "audio-device", &val ) < 0 )
        /* Probe() has failed. */
        goto error;

    if ( val.i_int == AOUT_VAR_SPDIF )
    {
        p_aout->format.i_format = VLC_CODEC_SPDIFL;
    }
    else if ( val.i_int == AOUT_VAR_5_1 )
    {
        p_aout->format.i_format = VLC_CODEC_S16N;
        p_aout->format.i_physical_channels
            = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
               | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
               | AOUT_CHAN_LFE;
    }
    else if ( val.i_int == AOUT_VAR_2F2R )
    {
        p_aout->format.i_format = VLC_CODEC_S16N;
        p_aout->format.i_physical_channels
            = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
               | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
    }
    else if ( val.i_int == AOUT_VAR_STEREO )
    {
        p_aout->format.i_format = VLC_CODEC_S16N;
        p_aout->format.i_physical_channels
            = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
    }
    else if ( val.i_int == AOUT_VAR_MONO )
    {
        p_aout->format.i_format = VLC_CODEC_S16N;
        p_aout->format.i_physical_channels = AOUT_CHAN_CENTER;
    }
    else
    {
        /* This should not happen ! */
        msg_Err( p_aout, "internal: can't find audio-device (%"PRId64")",
                 val.i_int );
        goto error;
    }

    var_TriggerCallback( p_aout, "intf-change" );

    /* Reset the DSP device */
    if( ioctl( p_sys->i_fd, SNDCTL_DSP_RESET, NULL ) < 0 )
    {
        msg_Err( p_aout, "cannot reset OSS audio device" );
        goto error;
    }

    /* Set the output format */
    if ( AOUT_FMT_SPDIF( &p_aout->format ) )
    {
        int i_format = AFMT_AC3;

        if( ioctl( p_sys->i_fd, SNDCTL_DSP_SETFMT, &i_format ) < 0
             || i_format != AFMT_AC3 )
        {
            msg_Err( p_aout, "cannot reset OSS audio device" );
            goto error;
        }

        p_aout->format.i_format = VLC_CODEC_SPDIFL;
        p_aout->format.i_bytes_per_frame = AOUT_SPDIF_SIZE;
        p_aout->format.i_frame_length = A52_FRAME_NB;

        aout_PacketInit( p_aout, &p_sys->packet, A52_FRAME_NB );
        aout_VolumeNoneInit( p_aout );
    }
    else
    {
        unsigned int i_format = AFMT_S16_NE;
        unsigned int i_frame_size, i_fragments;
        unsigned int i_rate;
        unsigned int i_nb_channels;
        audio_buf_info audio_buf;

        if( ioctl( p_sys->i_fd, SNDCTL_DSP_SETFMT, &i_format ) < 0 )
        {
            msg_Err( p_aout, "cannot set audio output format" );
            goto error;
        }

        switch ( i_format )
        {
        case AFMT_U8:
            p_aout->format.i_format = VLC_CODEC_U8;
            break;
        case AFMT_S8:
            p_aout->format.i_format = VLC_CODEC_S8;
            break;
        case AFMT_U16_LE:
            p_aout->format.i_format = VLC_CODEC_U16L;
            break;
        case AFMT_S16_LE:
            p_aout->format.i_format = VLC_CODEC_S16L;
            break;
        case AFMT_U16_BE:
            p_aout->format.i_format = VLC_CODEC_U16B;
            break;
        case AFMT_S16_BE:
            p_aout->format.i_format = VLC_CODEC_S16B;
            break;
        default:
            msg_Err( p_aout, "OSS fell back to an unknown format (%d)",
                     i_format );
            goto error;
        }

        i_nb_channels = aout_FormatNbChannels( &p_aout->format );

        /* Set the number of channels */
        if( ioctl( p_sys->i_fd, SNDCTL_DSP_CHANNELS, &i_nb_channels ) < 0 ||
            i_nb_channels != aout_FormatNbChannels( &p_aout->format ) )
        {
            msg_Err( p_aout, "cannot set number of audio channels (%s)",
                     aout_FormatPrintChannels( &p_aout->format) );
            goto error;
        }

        /* Set the output rate */
        i_rate = p_aout->format.i_rate;
        if( ioctl( p_sys->i_fd, SNDCTL_DSP_SPEED, &i_rate ) < 0 )
        {
            msg_Err( p_aout, "cannot set audio output rate (%i)",
                             p_aout->format.i_rate );
            goto error;
        }

        if( i_rate != p_aout->format.i_rate )
        {
            p_aout->format.i_rate = i_rate;
        }

        /* Set the fragment size */
        aout_FormatPrepare( &p_aout->format );

        /* i_fragment = xxxxyyyy where: xxxx        is fragtotal
         *                              1 << yyyy   is fragsize */
        i_frame_size = ((uint64_t)p_aout->format.i_bytes_per_frame * p_aout->format.i_rate * 65536) / (48000 * 2 * 2) / FRAME_COUNT;
        i_fragments = 4;
        while( i_fragments < 12 && (1U << i_fragments) < i_frame_size )
        {
            ++i_fragments;
        }
        i_fragments |= FRAME_COUNT << 16;
        if( ioctl( p_sys->i_fd, SNDCTL_DSP_SETFRAGMENT, &i_fragments ) < 0 )
        {
            msg_Warn( p_aout, "cannot set fragment size (%.8x)", i_fragments );
        }

        if( ioctl( p_sys->i_fd, SNDCTL_DSP_GETOSPACE, &audio_buf ) < 0 )
        {
            msg_Err( p_aout, "cannot get fragment size" );
            goto error;
        }

        /* Number of fragments actually allocated */
        p_aout->sys->i_fragstotal = audio_buf.fragstotal;

        /* Maximum duration the soundcard's buffer can hold */
        p_aout->sys->max_buffer_duration =
                (mtime_t)audio_buf.fragstotal * audio_buf.fragsize * 1000000
                / p_aout->format.i_bytes_per_frame
                / p_aout->format.i_rate
                * p_aout->format.i_frame_length;

        aout_PacketInit( p_aout, &p_sys->packet,
                         audio_buf.fragsize/p_aout->format.i_bytes_per_frame );
        aout_VolumeSoftInit( p_aout );
    }

    /* Create OSS thread and wait for its readiness. */
    if( vlc_clone( &p_sys->thread, OSSThread, p_aout,
                   VLC_THREAD_PRIORITY_OUTPUT ) )
    {
        msg_Err( p_aout, "cannot create OSS thread (%m)" );
        aout_PacketDestroy( p_aout );
        goto error;
    }

    return VLC_SUCCESS;

error:
    var_DelCallback( p_aout, "audio-device", aout_ChannelsRestart, NULL );
    close( p_sys->i_fd );
    free( p_sys );
    return VLC_EGENERIC;
}
Ejemplo n.º 17
0
/*****************************************************************************
 * Open: open the audio device
 *****************************************************************************
 * This function opens and setups Win32 waveOut
 *****************************************************************************/
static int Open( vlc_object_t *p_this )
{
    aout_instance_t *p_aout = (aout_instance_t *)p_this;
    vlc_value_t val;
    int i;

    /* Allocate structure */
    p_aout->output.p_sys = malloc( sizeof( aout_sys_t ) );

    if( p_aout->output.p_sys == NULL )
    {
        msg_Err( p_aout, "out of memory" );
        return VLC_EGENERIC;
    }

    p_aout->output.pf_play = Play;
    p_aout->b_die = VLC_FALSE;

    if( var_Type( p_aout, "audio-device" ) == 0 )
    {
        Probe( p_aout );
    }

    if( var_Get( p_aout, "audio-device", &val ) < 0 )
    {
        /* Probe() has failed. */
        free( p_aout->output.p_sys );
        return VLC_EGENERIC;
    }

    var_Create( p_aout, "waveout-float32", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );

    /* Open the device */
    if( val.i_int == AOUT_VAR_SPDIF )
    {
        p_aout->output.output.i_format = VLC_FOURCC('s','p','d','i');

        if( OpenWaveOut( p_aout, VLC_FOURCC('s','p','d','i'),
                         p_aout->output.output.i_physical_channels,
                         aout_FormatNbChannels( &p_aout->output.output ),
                         p_aout->output.output.i_rate, VLC_FALSE )
            != VLC_SUCCESS )
        {
            msg_Err( p_aout, "cannot open waveout audio device" );
            free( p_aout->output.p_sys );
            return VLC_EGENERIC;
        }

        /* Calculate the frame size in bytes */
        p_aout->output.i_nb_samples = A52_FRAME_NB;
        p_aout->output.output.i_bytes_per_frame = AOUT_SPDIF_SIZE;
        p_aout->output.output.i_frame_length = A52_FRAME_NB;
        p_aout->output.p_sys->i_buffer_size =
            p_aout->output.output.i_bytes_per_frame;

        aout_VolumeNoneInit( p_aout );
    }
    else
    {
        if( val.i_int == AOUT_VAR_5_1 )
        {
            p_aout->output.output.i_physical_channels
                = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
                   | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
                   | AOUT_CHAN_LFE;
        }
        else if( val.i_int == AOUT_VAR_2F2R )
        {
            p_aout->output.output.i_physical_channels
                = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
                   | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
        }
        else if( val.i_int == AOUT_VAR_MONO )
        {
            p_aout->output.output.i_physical_channels = AOUT_CHAN_CENTER;
        }
        else
        {
            p_aout->output.output.i_physical_channels
                = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
        }

        if( OpenWaveOutPCM( p_aout, &p_aout->output.output.i_format,
                            p_aout->output.output.i_physical_channels,
                            aout_FormatNbChannels( &p_aout->output.output ),
                            p_aout->output.output.i_rate, VLC_FALSE )
            != VLC_SUCCESS )
        {
            msg_Err( p_aout, "cannot open waveout audio device" );
            free( p_aout->output.p_sys );
            return VLC_EGENERIC;
        }

        /* Calculate the frame size in bytes */
        p_aout->output.i_nb_samples = FRAME_SIZE;
        aout_FormatPrepare( &p_aout->output.output );
        p_aout->output.p_sys->i_buffer_size = FRAME_SIZE *
            p_aout->output.output.i_bytes_per_frame;

        aout_VolumeSoftInit( p_aout );
    }


    waveOutReset( p_aout->output.p_sys->h_waveout );

    /* Allocate silence buffer */
    p_aout->output.p_sys->p_silence_buffer =
        malloc( p_aout->output.p_sys->i_buffer_size );
    if( p_aout->output.p_sys->p_silence_buffer == NULL )
    {
        free( p_aout->output.p_sys );
        msg_Err( p_aout, "out of memory" );
        return 1;
    }

    /* Zero the buffer. WinCE doesn't have calloc(). */
    memset( p_aout->output.p_sys->p_silence_buffer, 0,
            p_aout->output.p_sys->i_buffer_size );

    /* Now we need to setup our waveOut play notification structure */
    p_aout->output.p_sys->p_notif =
        vlc_object_create( p_aout, sizeof(notification_thread_t) );
    p_aout->output.p_sys->p_notif->p_aout = p_aout;
    p_aout->output.p_sys->event = CreateEvent( NULL, FALSE, FALSE, NULL );

    /* Then launch the notification thread */
    if( vlc_thread_create( p_aout->output.p_sys->p_notif,
                           "waveOut Notification Thread", WaveOutThread,
                           VLC_THREAD_PRIORITY_HIGHEST, VLC_FALSE ) )
    {
        msg_Err( p_aout, "cannot create WaveOutThread" );
    }

    /* We need to kick off the playback in order to have the callback properly
     * working */
    for( i = 0; i < FRAMES_NUM; i++ )
    {
        p_aout->output.p_sys->waveheader[i].dwFlags = WHDR_DONE;
        p_aout->output.p_sys->waveheader[i].dwUser = 0;
    }
    PlayWaveOut( p_aout, p_aout->output.p_sys->h_waveout,
                 &p_aout->output.p_sys->waveheader[0], NULL );

    return 0;
}
Ejemplo n.º 18
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.º 19
0
static int OpenBinauralizer(vlc_object_t *p_this)
{
    filter_t *p_filter = (filter_t *)p_this;
    audio_format_t *infmt = &p_filter->fmt_in.audio;
    audio_format_t *outfmt = &p_filter->fmt_out.audio;

    filter_sys_t *p_sys;
    p_sys = p_filter->p_sys = (filter_sys_t*)new(std::nothrow)filter_sys_t();
    if (p_sys == NULL)
        return VLC_ENOMEM;

    p_sys->mode = filter_sys_t::BINAURALIZER;
    p_sys->i_rate = p_filter->fmt_in.audio.i_rate;
    p_sys->i_inputNb = p_filter->fmt_in.audio.i_channels;
    p_sys->i_outputNb = 2;

    if (allocateBuffers(p_sys) != VLC_SUCCESS)
    {
        delete p_sys;
        return VLC_ENOMEM;
    }

    unsigned s = 0;
    p_sys->speakers = new CAmbisonicSpeaker[infmt->i_channels]();

    p_sys->speakers[s++].SetPosition({DegreesToRadians(30), 0.f, 1.f});
    p_sys->speakers[s++].SetPosition({DegreesToRadians(-30), 0.f, 1.f});

    if ((infmt->i_physical_channels & AOUT_CHANS_MIDDLE) == AOUT_CHANS_MIDDLE)
    {
        /* Middle */
        p_sys->speakers[s++].SetPosition({DegreesToRadians(110), 0.f, 1.f});
        p_sys->speakers[s++].SetPosition({DegreesToRadians(-110), 0.f, 1.f});
    }

    if ((infmt->i_physical_channels & AOUT_CHANS_REAR) == AOUT_CHANS_REAR)
    {
        /* Rear */
        p_sys->speakers[s++].SetPosition({DegreesToRadians(145), 0.f, 1.f});
        p_sys->speakers[s++].SetPosition({DegreesToRadians(-145), 0.f, 1.f});
    }

    if ((infmt->i_physical_channels & AOUT_CHAN_CENTER) == AOUT_CHAN_CENTER)
        p_sys->speakers[s++].SetPosition({DegreesToRadians(0), 0.f, 1.f});

    if ((infmt->i_physical_channels & AOUT_CHAN_LFE) == AOUT_CHAN_LFE)
        p_sys->speakers[s++].SetPosition({DegreesToRadians(0), 0.f, 0.5f});

    std::string HRTFPath = getHRTFPath(p_filter);
    msg_Dbg(p_filter, "Using the HRTF file: %s", HRTFPath.c_str());

    unsigned i_tailLength = 0;
    if (!p_sys->binauralizer.Configure(p_sys->i_rate, AMB_BLOCK_TIME_LEN,
                                       p_sys->speakers, infmt->i_channels, i_tailLength,
                                       HRTFPath))
    {
        msg_Err(p_filter, "Error creating the binauralizer.");
        delete p_sys;
        return VLC_EGENERIC;
    }
    p_sys->binauralizer.Reset();

    outfmt->i_format = infmt->i_format = VLC_CODEC_FL32;
    outfmt->i_physical_channels = AOUT_CHANS_STEREO;
    aout_FormatPrepare(infmt);
    aout_FormatPrepare(outfmt);

    p_filter->pf_audio_filter = Mix;
    p_filter->pf_flush = Flush;
    p_filter->pf_change_viewpoint = ChangeViewpoint;

    return VLC_SUCCESS;
}
Ejemplo n.º 20
0
Archivo: kai.c Proyecto: cspowart/vlc
/*****************************************************************************
 * Open: open the audio device
 *****************************************************************************/
static int Start ( audio_output_t *p_aout, audio_sample_format_t *fmt )
{
    aout_sys_t *p_sys = p_aout->sys;
    char *psz_mode;
    ULONG i_kai_mode;
    KAISPEC ks_wanted, ks_obtained;
    int i_nb_channels;
    int i_bytes_per_frame;
    vlc_value_t val, text;
    audio_sample_format_t format = *fmt;

    if( var_Get( p_aout, "audio-device", &val ) != VLC_ENOVAR )
    {
        /* The user has selected an audio device. */
        if ( val.i_int == AOUT_VAR_STEREO )
        {
            format.i_physical_channels
                = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
        }
        else if ( val.i_int == AOUT_VAR_MONO )
        {
            format.i_physical_channels = AOUT_CHAN_CENTER;
        }
    }

    psz_mode = var_InheritString( p_aout, "kai-audio-device" );
    if( !psz_mode )
        psz_mode = ( char * )ppsz_kai_audio_device[ 0 ];  // "auto"

    i_kai_mode = KAIM_AUTO;
    if( strcmp( psz_mode, "dart" ) == 0 )
        i_kai_mode = KAIM_DART;
    else if( strcmp( psz_mode, "uniaud" ) == 0 )
        i_kai_mode = KAIM_UNIAUD;
    msg_Dbg( p_aout, "selected mode = %s", psz_mode );

    if( psz_mode != ppsz_kai_audio_device[ 0 ])
        free( psz_mode );

    i_nb_channels = aout_FormatNbChannels( &format );
    if ( i_nb_channels > 2 )
    {
        /* KAI doesn't support more than two channels. */
        i_nb_channels = 2;
        format.i_physical_channels
            = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
    }

    /* Support s16l only */
    format.i_format = VLC_CODEC_S16L;

    aout_FormatPrepare( &format );

    i_bytes_per_frame = format.i_bytes_per_frame;

    /* Initialize library */
    if( kaiInit( i_kai_mode ))
    {
        msg_Err( p_aout, "cannot initialize KAI");

        return VLC_EGENERIC;
    }

    ks_wanted.usDeviceIndex   = 0;
    ks_wanted.ulType          = KAIT_PLAY;
    ks_wanted.ulBitsPerSample = BPS_16;
    ks_wanted.ulSamplingRate  = format.i_rate;
    ks_wanted.ulDataFormat    = MCI_WAVE_FORMAT_PCM;
    ks_wanted.ulChannels      = i_nb_channels;
    ks_wanted.ulNumBuffers    = 2;
    ks_wanted.ulBufferSize    = FRAME_SIZE * i_bytes_per_frame;
    ks_wanted.fShareable      = !var_InheritBool( p_aout,
                                                  "kai-audio-exclusive-mode");
    ks_wanted.pfnCallBack     = KaiCallback;
    ks_wanted.pCallBackData   = p_aout;
    msg_Dbg( p_aout, "requested ulBufferSize = %ld", ks_wanted.ulBufferSize );

    /* Open the sound device. */
    if( kaiOpen( &ks_wanted, &ks_obtained, &p_sys->hkai ))
    {
        msg_Err( p_aout, "cannot open KAI device");

        goto exit_kai_done;
    }

    msg_Dbg( p_aout, "open in %s mode",
             ks_obtained.fShareable ? "shareable" : "exclusive" );
    msg_Dbg( p_aout, "obtained i_nb_samples = %lu",
             ks_obtained.ulBufferSize / i_bytes_per_frame );
    msg_Dbg( p_aout, "obtained i_bytes_per_frame = %d",
             format.i_bytes_per_frame );

    p_sys->format = *fmt = format;

    p_aout->time_get = aout_PacketTimeGet;
    p_aout->play  = Play;
    p_aout->pause = NULL;
    p_aout->flush = aout_PacketFlush;

    aout_SoftVolumeStart( p_aout );

    aout_PacketInit( p_aout, &p_sys->packet,
                     ks_obtained.ulBufferSize / i_bytes_per_frame, &format );

    if ( var_Type( p_aout, "audio-device" ) == 0 )
    {
        /* First launch. */
        var_Create( p_aout, "audio-device",
                    VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
        text.psz_string = _("Audio Device");
        var_Change( p_aout, "audio-device", VLC_VAR_SETTEXT, &text, NULL );

        val.i_int = AOUT_VAR_STEREO;
        text.psz_string = _("Stereo");
        var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text );
        val.i_int = AOUT_VAR_MONO;
        text.psz_string = _("Mono");
        var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text );
        if ( i_nb_channels == 2 )
        {
            val.i_int = AOUT_VAR_STEREO;
        }
        else
        {
            val.i_int = AOUT_VAR_MONO;
        }
        var_Change( p_aout, "audio-device", VLC_VAR_SETDEFAULT, &val, NULL );
        var_AddCallback( p_aout, "audio-device", aout_ChannelsRestart, NULL );
    }

    /* Prevent SIG_FPE */
    _control87(MCW_EM, MCW_EM);

    return VLC_SUCCESS;

exit_kai_done :
    kaiDone();

    return VLC_EGENERIC;
}
Ejemplo n.º 21
0
Archivo: rtp.c Proyecto: Geal/vlc
void *codec_init (demux_t *demux, es_format_t *fmt)
{
    if (fmt->i_cat == AUDIO_ES)
        aout_FormatPrepare (&fmt->audio);
    return es_out_Add (demux->out, fmt);
}
Ejemplo n.º 22
0
/*****************************************************************************
 * Open: open the audio device
 *****************************************************************************/
static int Start ( audio_output_t *p_aout, audio_sample_format_t *fmt )
{
    aout_sys_t *p_sys = p_aout->sys;
    char *psz_mode;
    ULONG i_kai_mode;
    KAISPEC ks_wanted, ks_obtained;
    int i_nb_channels;
    int i_bytes_per_frame;
    vlc_value_t val, text;
    audio_sample_format_t format = *fmt;

    psz_mode = var_InheritString( p_aout, "kai-audio-device" );
    if( !psz_mode )
        psz_mode = ( char * )ppsz_kai_audio_device[ 0 ];  // "auto"

    i_kai_mode = KAIM_AUTO;
    if( strcmp( psz_mode, "dart" ) == 0 )
        i_kai_mode = KAIM_DART;
    else if( strcmp( psz_mode, "uniaud" ) == 0 )
        i_kai_mode = KAIM_UNIAUD;
    msg_Dbg( p_aout, "selected mode = %s", psz_mode );

    if( psz_mode != ppsz_kai_audio_device[ 0 ])
        free( psz_mode );

    i_nb_channels = aout_FormatNbChannels( &format );
    if ( i_nb_channels >= 2 )
    {
        /* KAI doesn't support more than two channels. */
        i_nb_channels = 2;
        format.i_physical_channels = AOUT_CHANS_STEREO;
    }
    else
        format.i_physical_channels = AOUT_CHAN_CENTER;

    /* Support S16 only */
    format.i_format = VLC_CODEC_S16N;

    aout_FormatPrepare( &format );

    i_bytes_per_frame = format.i_bytes_per_frame;

    /* Initialize library */
    if( kaiInit( i_kai_mode ))
    {
        msg_Err( p_aout, "cannot initialize KAI");

        return VLC_EGENERIC;
    }

    ks_wanted.usDeviceIndex   = 0;
    ks_wanted.ulType          = KAIT_PLAY;
    ks_wanted.ulBitsPerSample = BPS_16;
    ks_wanted.ulSamplingRate  = format.i_rate;
    ks_wanted.ulDataFormat    = MCI_WAVE_FORMAT_PCM;
    ks_wanted.ulChannels      = i_nb_channels;
    ks_wanted.ulNumBuffers    = 2;
    ks_wanted.ulBufferSize    = FRAME_SIZE * i_bytes_per_frame;
    ks_wanted.fShareable      = !var_InheritBool( p_aout,
                                                  "kai-audio-exclusive-mode");
    ks_wanted.pfnCallBack     = KaiCallback;
    ks_wanted.pCallBackData   = p_aout;
    msg_Dbg( p_aout, "requested ulBufferSize = %ld", ks_wanted.ulBufferSize );

    /* Open the sound device. */
    if( kaiOpen( &ks_wanted, &ks_obtained, &p_sys->hkai ))
    {
        msg_Err( p_aout, "cannot open KAI device");

        goto exit_kai_done;
    }

    msg_Dbg( p_aout, "open in %s mode",
             ks_obtained.fShareable ? "shareable" : "exclusive" );
    msg_Dbg( p_aout, "obtained i_nb_samples = %lu",
             ks_obtained.ulBufferSize / i_bytes_per_frame );
    msg_Dbg( p_aout, "obtained i_bytes_per_frame = %d",
             format.i_bytes_per_frame );

    p_sys->format = *fmt = format;

    p_aout->time_get = TimeGet;
    p_aout->play     = Play;
    p_aout->pause    = Pause;
    p_aout->flush    = Flush;

    aout_SoftVolumeStart( p_aout );

    CreateBuffer( p_aout, AUDIO_BUFFER_SIZE_IN_SECONDS *
                          format.i_rate * format.i_bytes_per_frame );

    /* Prevent SIG_FPE */
    _control87(MCW_EM, MCW_EM);

    return VLC_SUCCESS;

exit_kai_done :
    kaiDone();

    return VLC_EGENERIC;
}
Ejemplo n.º 23
0
int transcode_audio_process( sout_stream_t *p_stream,
                                    sout_stream_id_t *id,
                                    block_t *in, block_t **out )
{
    sout_stream_sys_t *p_sys = p_stream->p_sys;
    block_t *p_block, *p_audio_buf;
    *out = NULL;

    if( unlikely( in == NULL ) )
    {
        block_t *p_block;
        do {
           p_block = id->p_encoder->pf_encode_audio(id->p_encoder, NULL );
           block_ChainAppend( out, p_block );
        } while( p_block );
        return VLC_SUCCESS;
    }

    while( (p_audio_buf = id->p_decoder->pf_decode_audio( id->p_decoder,
                                                          &in )) )
    {
        if( p_sys->b_master_sync )
        {
            mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
            mtime_t i_drift = 0;

            if( likely( p_audio_buf->i_pts != VLC_TS_INVALID ) )
                i_drift = p_audio_buf->i_pts - i_pts;

            if ( unlikely(i_drift > MASTER_SYNC_MAX_DRIFT
                 || i_drift < -MASTER_SYNC_MAX_DRIFT) )
            {
                msg_Dbg( p_stream,
                    "audio drift is too high (%"PRId64"), resetting master sync",
                    i_drift );
                date_Set( &id->interpolated_pts, p_audio_buf->i_pts );
                i_pts = p_audio_buf->i_pts + 1;
            }
            if( likely(p_audio_buf->i_pts != VLC_TS_INVALID ) )
                p_sys->i_master_drift = p_audio_buf->i_pts - i_pts;
            date_Increment( &id->interpolated_pts, p_audio_buf->i_nb_samples );
            p_audio_buf->i_pts = i_pts;
        }

        p_audio_buf->i_dts = p_audio_buf->i_pts;

        /* Check if audio format has changed, and filters need reinit */
        if( unlikely( ( id->p_decoder->fmt_out.audio.i_rate != p_sys->fmt_audio.i_rate ) ||
                      ( id->p_decoder->fmt_out.audio.i_physical_channels != p_sys->fmt_audio.i_physical_channels ) ) )
        {
            msg_Info( p_stream, "Audio changed, trying to reinitialize filters" );
            if( id->p_af_chain != NULL )
                aout_FiltersDelete( (vlc_object_t *)NULL, id->p_af_chain );

            /* decoders don't set audio.i_format, but audio filters use it */
            id->p_decoder->fmt_out.audio.i_format = id->p_decoder->fmt_out.i_codec;
            aout_FormatPrepare( &id->p_decoder->fmt_out.audio );

            if( transcode_audio_initialize_filters( p_stream, id, p_sys, &id->p_decoder->fmt_out.audio ) != VLC_SUCCESS )
                return VLC_EGENERIC;

        }

        /* Run filter chain */
        p_audio_buf = aout_FiltersPlay( id->p_af_chain, p_audio_buf,
                                        INPUT_RATE_DEFAULT );
        if( !p_audio_buf )
            abort();

        p_audio_buf->i_dts = p_audio_buf->i_pts;

        p_block = id->p_encoder->pf_encode_audio( id->p_encoder, p_audio_buf );

        block_ChainAppend( out, p_block );
        block_Release( p_audio_buf );
    }

    return VLC_SUCCESS;
}
Ejemplo n.º 24
0
/*****************************************************************************
 * OpenFilter:
 *****************************************************************************/
static int OpenFilter( vlc_object_t *p_this )
{
    filter_t *p_filter = (filter_t *)p_this;
    filter_sys_t *p_sys;

    audio_format_t *audio_in  = &p_filter->fmt_in.audio;
    audio_format_t *audio_out = &p_filter->fmt_out.audio;

    if( ( audio_in->i_format != audio_out->i_format ) ||
        ( audio_in->i_rate != audio_out->i_rate ) )
        return VLC_EGENERIC;

    /* Allocate the memory needed to store the module's structure */
    p_sys = p_filter->p_sys = malloc( sizeof(filter_sys_t) );
    if( unlikely( p_sys == NULL ) )
        return VLC_ENOMEM;

    /* get number of and layout of input channels */
    uint32_t i_output_physical = 0;
    uint8_t pi_map_ch[ AOUT_CHAN_MAX ] = { 0 }; /* which out channel each in channel is mapped to */
    p_sys->b_normalize = var_InheritBool( p_this, REMAP_CFG "normalize" );

    for( uint8_t in_ch = 0, wg4_i = 0; in_ch < audio_in->i_channels; in_ch++, wg4_i++ )
    {
        /* explode in_channels in the right order */
        while( ( audio_in->i_physical_channels & pi_vlc_chan_order_wg4[ wg4_i ] ) == 0 )
        {
            wg4_i++;
            assert( wg4_i < sizeof( pi_vlc_chan_order_wg4 )/sizeof( pi_vlc_chan_order_wg4[0] ) );
        }
        unsigned channel_wg4idx_len = sizeof( channel_wg4idx )/sizeof( channel_wg4idx[0] );
        uint8_t *pi_chnidx = memchr( channel_wg4idx, wg4_i, channel_wg4idx_len );
        assert( pi_chnidx != NULL );
        uint8_t chnidx = pi_chnidx - channel_wg4idx;
        uint8_t out_idx = var_InheritInteger( p_this, channel_name[chnidx] );
        pi_map_ch[in_ch] = channel_wg4idx[ out_idx ];

        i_output_physical |= channel_flag[ out_idx ];
    }
    i_output_physical = CanonicaliseChannels( i_output_physical );

    audio_out->i_physical_channels = i_output_physical;
    aout_FormatPrepare( audio_out );

    /* condense out_channels */
    uint8_t out_ch_sorted[ AOUT_CHAN_MAX ];
    for( uint8_t i = 0, wg4_i = 0; i < audio_out->i_channels; i++, wg4_i++ )
    {
        while( ( audio_out->i_physical_channels & pi_vlc_chan_order_wg4[ wg4_i ] ) == 0 )
        {
            wg4_i++;
            assert( wg4_i < sizeof( pi_vlc_chan_order_wg4 )/sizeof( pi_vlc_chan_order_wg4[0] ) );
        }
        out_ch_sorted[ i ] = wg4_i;
    }
    bool b_multiple = false; /* whether we need to add channels (multiple in mapped to an out) */
    memset( p_sys->nb_in_ch, 0, sizeof( p_sys->nb_in_ch ) );
    for( uint8_t i = 0; i < audio_in->i_channels; i++ )
    {
        uint8_t wg4_out_ch = pi_map_ch[i];
        uint8_t *pi_out_ch = memchr( out_ch_sorted, wg4_out_ch, audio_out->i_channels );
        assert( pi_out_ch != NULL );
        p_sys->map_ch[i] = pi_out_ch - out_ch_sorted;
        if( ++p_sys->nb_in_ch[ p_sys->map_ch[i] ] > 1 )
            b_multiple = true;
    }

    msg_Dbg( p_filter, "%s '%4.4s'->'%4.4s' %d Hz->%d Hz %s->%s",
             "Remap filter",
             (char *)&audio_in->i_format, (char *)&audio_out->i_format,
             audio_in->i_rate, audio_out->i_rate,
             aout_FormatPrintChannels( audio_in ),
             aout_FormatPrintChannels( audio_out ) );

    p_sys->pf_remap = GetRemapFun( audio_in, b_multiple );
    if( !p_sys->pf_remap )
    {
        msg_Err( p_filter, "Could not decide on %s remap function", b_multiple ? "an add" : "a copy" );
        free( p_sys );
        return VLC_EGENERIC;
    }

    p_filter->pf_audio_filter = Remap;
    return VLC_SUCCESS;
}
Ejemplo n.º 25
0
int transcode_audio_new( sout_stream_t *p_stream,
                                sout_stream_id_t *id )
{
    sout_stream_sys_t *p_sys = p_stream->p_sys;
    audio_sample_format_t fmt_last;

    /*
     * Open decoder
     */

    /* Initialization of decoder structures */
    id->p_decoder->fmt_out = id->p_decoder->fmt_in;
    id->p_decoder->fmt_out.i_extra = 0;
    id->p_decoder->fmt_out.p_extra = 0;
    id->p_decoder->pf_decode_audio = NULL;
    id->p_decoder->pf_aout_format_update = audio_update_format;
    /* id->p_decoder->p_cfg = p_sys->p_audio_cfg; */

    id->p_decoder->p_module =
        module_need( id->p_decoder, "decoder", "$codec", false );
    if( !id->p_decoder->p_module )
    {
        msg_Err( p_stream, "cannot find audio decoder" );
        return VLC_EGENERIC;
    }
    /* decoders don't set audio.i_format, but audio filters use it */
    id->p_decoder->fmt_out.audio.i_format = id->p_decoder->fmt_out.i_codec;
    aout_FormatPrepare( &id->p_decoder->fmt_out.audio );
    fmt_last = id->p_decoder->fmt_out.audio;
    /* Fix AAC SBR changing number of channels and sampling rate */
    if( !(id->p_decoder->fmt_in.i_codec == VLC_CODEC_MP4A &&
        fmt_last.i_rate != id->p_encoder->fmt_in.audio.i_rate &&
        fmt_last.i_channels != id->p_encoder->fmt_in.audio.i_channels) )
        fmt_last.i_rate = id->p_decoder->fmt_in.audio.i_rate;

    /*
     * Open encoder
     */

    /* Initialization of encoder format structures */
    es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
                    id->p_decoder->fmt_out.i_codec );
    id->p_encoder->fmt_in.audio.i_format = id->p_decoder->fmt_out.i_codec;
    id->p_encoder->fmt_in.audio.i_rate = id->p_encoder->fmt_out.audio.i_rate;
    id->p_encoder->fmt_in.audio.i_physical_channels =
        id->p_encoder->fmt_out.audio.i_physical_channels;
    aout_FormatPrepare( &id->p_encoder->fmt_in.audio );

    id->p_encoder->p_cfg = p_stream->p_sys->p_audio_cfg;
    id->p_encoder->p_module =
        module_need( id->p_encoder, "encoder", p_sys->psz_aenc, true );
    if( !id->p_encoder->p_module )
    {
        msg_Err( p_stream, "cannot find audio encoder (module:%s fourcc:%4.4s). Take a look few lines earlier to see possible reason.",
                 p_sys->psz_aenc ? p_sys->psz_aenc : "any",
                 (char *)&p_sys->i_acodec );
        module_unneed( id->p_decoder, id->p_decoder->p_module );
        id->p_decoder->p_module = NULL;
        return VLC_EGENERIC;
    }

    id->p_encoder->fmt_out.i_codec =
        vlc_fourcc_GetCodec( AUDIO_ES, id->p_encoder->fmt_out.i_codec );

    /* Fix input format */
    id->p_encoder->fmt_in.audio.i_format = id->p_encoder->fmt_in.i_codec;
    if( !id->p_encoder->fmt_in.audio.i_physical_channels
     || !id->p_encoder->fmt_in.audio.i_original_channels )
    {
        if( id->p_encoder->fmt_in.audio.i_channels < 6 )
            id->p_encoder->fmt_in.audio.i_physical_channels =
            id->p_encoder->fmt_in.audio.i_original_channels =
                      pi_channels_maps[id->p_encoder->fmt_in.audio.i_channels];
    }
    aout_FormatPrepare( &id->p_encoder->fmt_in.audio );

    if( unlikely( transcode_audio_initialize_filters( p_stream, id, p_sys, &fmt_last ) != VLC_SUCCESS ) )
        return VLC_EGENERIC;

    return VLC_SUCCESS;
}
Ejemplo n.º 26
0
Archivo: dca.c Proyecto: etix/vlc
static int Open( vlc_object_t *p_this )
{
    decoder_t *p_dec = (decoder_t *)p_this;
    decoder_sys_t *p_sys;

    if( p_dec->fmt_in.i_codec != VLC_CODEC_DTS
     || p_dec->fmt_in.audio.i_rate == 0
     || p_dec->fmt_in.audio.i_physical_channels == 0
     || p_dec->fmt_in.audio.i_original_channels == 0
     || p_dec->fmt_in.audio.i_bytes_per_frame == 0
     || p_dec->fmt_in.audio.i_frame_length == 0 )
        return VLC_EGENERIC;

    /* Allocate the memory needed to store the module's structure */
    p_sys = p_dec->p_sys = malloc( sizeof(decoder_sys_t) );
    if( p_sys == NULL )
        return VLC_ENOMEM;

    p_sys->b_dynrng = var_InheritBool( p_this, "dts-dynrng" );
    p_sys->b_dontwarn = 0;

    /* We'll do our own downmixing, thanks. */
    p_sys->i_nb_channels = aout_FormatNbChannels( &p_dec->fmt_in.audio );
    if( channels_vlc2dca( &p_dec->fmt_in.audio, &p_sys->i_flags )
        != VLC_SUCCESS )
    {
        msg_Warn( p_this, "unknown sample format!" );
        free( p_sys );
        return VLC_EGENERIC;
    }
    //p_sys->i_flags |= DCA_ADJUST_LEVEL;

    /* Initialize libdca */
    p_sys->p_libdca = dca_init( 0 );
    if( p_sys->p_libdca == NULL )
    {
        msg_Err( p_this, "unable to initialize libdca" );
        free( p_sys );
        return VLC_EGENERIC;
    }

    /* libdca channel order
     * libdca currently only decodes 5.1, even if you have a DTS-ES source. */
    static const uint32_t pi_channels_in[] = {
        AOUT_CHAN_CENTER, AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT,
        AOUT_CHAN_REARCENTER, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT,
        AOUT_CHAN_LFE, 0
    };

    aout_CheckChannelReorder( pi_channels_in, NULL,
                              p_dec->fmt_in.audio.i_physical_channels,
                              p_sys->pi_chan_table );

    p_dec->fmt_out.i_cat = AUDIO_ES;
    p_dec->fmt_out.audio = p_dec->fmt_in.audio;
    p_dec->fmt_out.audio.i_format = VLC_CODEC_FL32;
    p_dec->fmt_out.i_codec = p_dec->fmt_out.audio.i_format;

    aout_FormatPrepare( &p_dec->fmt_out.audio );

    if( decoder_UpdateAudioFormat( p_dec ) )
    {
        es_format_Init( &p_dec->fmt_out, UNKNOWN_ES, 0 );
        Close( p_this );
        return VLC_EGENERIC;
    }

    p_dec->pf_decode = Decode;
    p_dec->pf_flush  = NULL;
    return VLC_SUCCESS;
}
Ejemplo n.º 27
0
static int Audio_GetOutput(decoder_t *p_dec, picture_t **pp_out_pic,
                           block_t **pp_out_block, bool *p_abort,
                           mtime_t i_timeout)
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    mc_api_out out;
    int i_ret;
    (void) p_abort;

    assert(!pp_out_pic && pp_out_block);

    i_ret = p_sys->api->get_out(p_sys->api, &out, i_timeout);
    if (i_ret != 1)
        return i_ret;

    if (out.type == MC_OUT_TYPE_BUF)
    {
        block_t *p_block = NULL;
        if (!p_sys->b_has_format) {
            msg_Warn(p_dec, "Buffers returned before output format is set, dropping frame");
            return p_sys->api->release_out(p_sys->api, out.u.buf.i_index, false);
        }

        p_block = block_Alloc(out.u.buf.i_size);
        if (!p_block)
            return -1;
        p_block->i_nb_samples = out.u.buf.i_size
                              / p_dec->fmt_out.audio.i_bytes_per_frame;

        if (p_sys->u.audio.b_extract)
        {
            aout_ChannelExtract(p_block->p_buffer,
                                p_dec->fmt_out.audio.i_channels,
                                out.u.buf.p_ptr, p_sys->u.audio.i_channels,
                                p_block->i_nb_samples, p_sys->u.audio.pi_extraction,
                                p_dec->fmt_out.audio.i_bitspersample);
        }
        else
            memcpy(p_block->p_buffer, out.u.buf.p_ptr, out.u.buf.i_size);

        if (out.u.buf.i_ts != 0 && out.u.buf.i_ts != date_Get(&p_sys->u.audio.i_end_date))
            date_Set(&p_sys->u.audio.i_end_date, out.u.buf.i_ts);

        p_block->i_pts = date_Get(&p_sys->u.audio.i_end_date);
        p_block->i_length = date_Increment(&p_sys->u.audio.i_end_date,
                                           p_block->i_nb_samples)
                          - p_block->i_pts;

        if (p_sys->api->release_out(p_sys->api, out.u.buf.i_index, false))
        {
            block_Release(p_block);
            return -1;
        }
        *pp_out_block = p_block;
        return 1;
    } else {
        uint32_t i_layout_dst;
        int      i_channels_dst;

        assert(out.type == MC_OUT_TYPE_CONF);

        if (out.u.conf.audio.channel_count <= 0
         || out.u.conf.audio.channel_count > 8
         || out.u.conf.audio.sample_rate <= 0)
        {
            msg_Warn( p_dec, "invalid audio properties channels count %d, sample rate %d",
                      out.u.conf.audio.channel_count,
                      out.u.conf.audio.sample_rate);
            return -1;
        }

        msg_Err(p_dec, "output: channel_count: %d, channel_mask: 0x%X, rate: %d",
                out.u.conf.audio.channel_count, out.u.conf.audio.channel_mask,
                out.u.conf.audio.sample_rate);

        p_dec->fmt_out.i_codec = VLC_CODEC_S16N;
        p_dec->fmt_out.audio.i_format = p_dec->fmt_out.i_codec;

        p_dec->fmt_out.audio.i_rate = out.u.conf.audio.sample_rate;
        date_Init(&p_sys->u.audio.i_end_date, out.u.conf.audio.sample_rate, 1 );

        p_sys->u.audio.i_channels = out.u.conf.audio.channel_count;
        p_sys->u.audio.b_extract =
            aout_CheckChannelExtraction(p_sys->u.audio.pi_extraction,
                                        &i_layout_dst, &i_channels_dst,
                                        NULL, pi_audio_order_src,
                                        p_sys->u.audio.i_channels);

        if (p_sys->u.audio.b_extract)
            msg_Warn(p_dec, "need channel extraction: %d -> %d",
                     p_sys->u.audio.i_channels, i_channels_dst);

        p_dec->fmt_out.audio.i_original_channels =
        p_dec->fmt_out.audio.i_physical_channels = i_layout_dst;
        aout_FormatPrepare(&p_dec->fmt_out.audio);

        if (decoder_UpdateAudioFormat(p_dec))
            return -1;

        p_sys->b_has_format = true;
        return 0;
    }
}
Ejemplo n.º 28
0
static int PAOpenStream( audio_output_t *p_aout )
{
    aout_sys_t *p_sys = p_aout->sys;
    const PaHostErrorInfo* paLastHostErrorInfo = Pa_GetLastHostErrorInfo();
    PaStreamParameters paStreamParameters;
    vlc_value_t val;
    int i_channels, i_err;
    uint32_t i_channel_mask;

    if( var_Get( p_aout, "audio-device", &val ) < 0 )
    {
        return VLC_EGENERIC;
    }

    if( val.i_int == AOUT_VAR_5_1 )
    {
        p_aout->format.i_physical_channels
            = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
              | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
              | AOUT_CHAN_LFE;
    }
    else if( val.i_int == AOUT_VAR_3F2R )
    {
        p_aout->format.i_physical_channels
            = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
            | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
    }
    else if( val.i_int == AOUT_VAR_2F2R )
    {
        p_aout->format.i_physical_channels
            = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
            | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
    }
    else if( val.i_int == AOUT_VAR_MONO )
    {
        p_aout->format.i_physical_channels = AOUT_CHAN_CENTER;
    }
    else
    {
        p_aout->format.i_physical_channels
            = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
    }

    i_channels = aout_FormatNbChannels( &p_aout->format );
    msg_Dbg( p_aout, "nb_channels requested = %d", i_channels );
    i_channel_mask = p_aout->format.i_physical_channels;

    /* Calculate the frame size in bytes */
    p_sys->i_sample_size = 4 * i_channels;
    aout_FormatPrepare( &p_aout->format );
    aout_PacketInit( p_aout, &p_sys->packet, FRAME_SIZE );
    aout_VolumeSoftInit( p_aout );

    /* Check for channel reordering */
    p_aout->sys->i_channel_mask = i_channel_mask;
    p_aout->sys->i_bits_per_sample = 32; /* forced to paFloat32 */
    p_aout->sys->i_channels = i_channels;

    p_aout->sys->b_chan_reorder =
        aout_CheckChannelReorder( NULL, pi_channels_out,
                                  i_channel_mask, i_channels,
                                  p_aout->sys->pi_chan_table );

    if( p_aout->sys->b_chan_reorder )
    {
        msg_Dbg( p_aout, "channel reordering needed" );
    }

    paStreamParameters.device = p_sys->i_device_id;
    paStreamParameters.channelCount = i_channels;
    paStreamParameters.sampleFormat = paFloat32;
    paStreamParameters.suggestedLatency =
        p_sys->deviceInfo->defaultLowOutputLatency;
    paStreamParameters.hostApiSpecificStreamInfo = NULL;

    i_err = Pa_OpenStream( &p_sys->p_stream, NULL /* no input */,
                &paStreamParameters, (double)p_aout->format.i_rate,
                FRAME_SIZE, paClipOff, paCallback, p_sys );
    if( i_err != paNoError )
    {
        msg_Err( p_aout, "Pa_OpenStream returns %d : %s", i_err,
                 Pa_GetErrorText( i_err ) );
        if( i_err == paUnanticipatedHostError )
        {
            msg_Err( p_aout, "type %d code %ld : %s",
                     paLastHostErrorInfo->hostApiType,
                     paLastHostErrorInfo->errorCode,
                     paLastHostErrorInfo->errorText );
        }
        p_sys->p_stream = 0;
        aout_PacketDestroy( p_aout );
        return VLC_EGENERIC;
    }

    i_err = Pa_StartStream( p_sys->p_stream );
    if( i_err != paNoError )
    {
        msg_Err( p_aout, "Pa_StartStream() failed" );
        Pa_CloseStream( p_sys->p_stream );
        aout_PacketDestroy( p_aout );
        return VLC_EGENERIC;
    }

    return VLC_SUCCESS;
}
Ejemplo n.º 29
0
static int Open (vlc_object_t *obj)
{
    demux_t *demux = (demux_t *)obj;
    demux_sys_t *sys = vlc_obj_malloc(obj, sizeof (*sys));
    if (unlikely(sys == NULL))
        return VLC_ENOMEM;

    /* Open the device */
    const char *device = demux->psz_location;
    if (device == NULL || !device[0])
        device = "default";

    const int mode = SND_PCM_NONBLOCK
                 /*| SND_PCM_NO_AUTO_RESAMPLE*/
                   | SND_PCM_NO_AUTO_CHANNELS
                 /*| SND_PCM_NO_AUTO_FORMAT*/;
    snd_pcm_t *pcm;
    int val = snd_pcm_open (&pcm, device, SND_PCM_STREAM_CAPTURE, mode);
    if (val != 0)
    {
        msg_Err (demux, "cannot open ALSA device \"%s\": %s", device,
                 snd_strerror (val));
        return VLC_EGENERIC;
    }
    sys->pcm = pcm;
    msg_Dbg (demux, "using ALSA device: %s", device);
    DumpDevice (VLC_OBJECT(demux), pcm);

    /* Negotiate capture parameters */
    snd_pcm_hw_params_t *hw;
    es_format_t fmt;
    unsigned param;
    int dir;

    snd_pcm_hw_params_alloca (&hw);
    snd_pcm_hw_params_any (pcm, hw);
    Dump (demux, "initial hardware setup:\n", snd_pcm_hw_params_dump, hw);

    val = snd_pcm_hw_params_set_rate_resample (pcm, hw, 0);
    if (val)
    {
        msg_Err (demux, "cannot disable resampling: %s", snd_strerror (val));
        goto error;
    }

    val = snd_pcm_hw_params_set_access (pcm, hw,
                                        SND_PCM_ACCESS_RW_INTERLEAVED);
    if (val)
    {
        msg_Err (demux, "cannot set access mode: %s", snd_strerror (val));
        goto error;
    }

    snd_pcm_format_t format = SND_PCM_FORMAT_UNKNOWN;
    for (size_t i = 0; i < sizeof (choices) / sizeof (choices[0]); i++)
        if (snd_pcm_hw_params_test_format (pcm, hw, choices[i]) == 0)
        {
            val = snd_pcm_hw_params_set_format (pcm, hw, choices[i]);
            if (val)
            {
                msg_Err (demux, "cannot set sample format: %s",
                         snd_strerror (val));
                goto error;
            }
            format = choices[i];
            break;
        }

    if (format == SND_PCM_FORMAT_UNKNOWN)
    {
        msg_Err (demux, "no supported sample format");
        goto error;
    }

    assert ((size_t)format < (sizeof (formats) / sizeof (formats[0])));
    es_format_Init (&fmt, AUDIO_ES, formats[format]);
    fmt.audio.i_format = fmt.i_codec;

    param = 1 + var_InheritBool (demux, "alsa-stereo");
    val = snd_pcm_hw_params_set_channels_max (pcm, hw, &param);
    if (val)
    {
        msg_Err (demux, "cannot restrict channels count: %s",
                 snd_strerror (val));
        goto error;
    }
    val = snd_pcm_hw_params_set_channels_last (pcm, hw, &param);
    if (val)
    {
        msg_Err (demux, "cannot set channels count: %s", snd_strerror (val));
        goto error;
    }
    assert (param > 0);
    assert (param < (sizeof (channel_maps) / sizeof (channel_maps[0])));
    fmt.audio.i_channels = param;
    fmt.audio.i_physical_channels = channel_maps[param - 1];

    param = var_InheritInteger (demux, "alsa-samplerate");
    val = snd_pcm_hw_params_set_rate_max (pcm, hw, &param, NULL);
    if (val)
    {
        msg_Err (demux, "cannot restrict rate to %u Hz or less: %s", 192000,
                 snd_strerror (val));
        goto error;
    }
    val = snd_pcm_hw_params_set_rate_last (pcm, hw, &param, &dir);
    if (val)
    {
        msg_Err (demux, "cannot set sample rate: %s", snd_strerror (val));
        goto error;
    }
    if (dir)
        msg_Warn (demux, "sample rate is not integral");
    fmt.audio.i_rate = param;
    sys->rate = param;

    sys->start = mdate ();
    sys->caching = INT64_C(1000) * var_InheritInteger (demux, "live-caching");
    param = sys->caching;
    val = snd_pcm_hw_params_set_buffer_time_near (pcm, hw, &param, NULL);
    if (val)
    {
        msg_Err (demux, "cannot set buffer duration: %s", snd_strerror (val));
        goto error;
    }

    param /= 4;
    val = snd_pcm_hw_params_set_period_time_near (pcm, hw, &param, NULL);
    if (val)
    {
        msg_Err (demux, "cannot set period: %s", snd_strerror (val));
        goto error;
    }

    val = snd_pcm_hw_params_get_period_size (hw, &sys->period_size, &dir);
    if (val)
    {
        msg_Err (demux, "cannot get period size: %s", snd_strerror (val));
        goto error;
    }
    if (dir > 0)
        sys->period_size++;

    /* Commit hardware parameters */
    val = snd_pcm_hw_params (pcm, hw);
    if (val)
    {
        msg_Err (demux, "cannot commit hardware parameters: %s",
                 snd_strerror (val));
        goto error;
    }
    Dump (demux, "final HW setup:\n", snd_pcm_hw_params_dump, hw);

    /* Kick recording */
    aout_FormatPrepare (&fmt.audio);
    sys->es = es_out_Add (demux->out, &fmt);
    demux->p_sys = sys;

    if (vlc_clone (&sys->thread, Thread, demux, VLC_THREAD_PRIORITY_INPUT))
    {
        es_out_Del (demux->out, sys->es);
        goto error;
    }

    demux->pf_demux = NULL;
    demux->pf_control = Control;
    return VLC_SUCCESS;
error:
    snd_pcm_close (pcm);
    return VLC_EGENERIC;
}
Ejemplo n.º 30
0
/*****************************************************************************
 * aout_OutputNew : allocate a new output and rework the filter pipeline
 *****************************************************************************
 * This function is entered with the mixer lock.
 *****************************************************************************/
int aout_OutputNew( aout_instance_t * p_aout,
                    audio_sample_format_t * p_format )
{
    /* Retrieve user defaults. */
    int i_rate = var_InheritInteger( p_aout, "aout-rate" );
    vlc_value_t val, text;
    /* kludge to avoid a fpu error when rate is 0... */
    if( i_rate == 0 ) i_rate = -1;

    memcpy( &p_aout->output.output, p_format, sizeof(audio_sample_format_t) );
    if ( i_rate != -1 )
        p_aout->output.output.i_rate = i_rate;
    aout_FormatPrepare( &p_aout->output.output );

    /* Find the best output plug-in. */
    p_aout->output.p_module = module_need( p_aout, "audio output", "$aout", false );
    if ( p_aout->output.p_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. */
        var_Get( p_aout, "audio-channels", &val );

        if ( val.i_int == AOUT_VAR_CHAN_RSTEREO )
        {
            p_aout->output.output.i_original_channels |=
                                        AOUT_CHAN_REVERSESTEREO;
        }
        else if ( val.i_int == AOUT_VAR_CHAN_STEREO )
        {
            p_aout->output.output.i_original_channels =
                AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
        }
        else if ( val.i_int == AOUT_VAR_CHAN_LEFT )
        {
            p_aout->output.output.i_original_channels = AOUT_CHAN_LEFT;
        }
        else if ( val.i_int == AOUT_VAR_CHAN_RIGHT )
        {
            p_aout->output.output.i_original_channels = AOUT_CHAN_RIGHT;
        }
        else if ( val.i_int == AOUT_VAR_CHAN_DOLBYS )
        {
            p_aout->output.output.i_original_channels
                = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_DOLBYSTEREO;
        }
    }
    else if ( p_aout->output.output.i_physical_channels == AOUT_CHAN_CENTER
              && (p_aout->output.output.i_original_channels
                   & AOUT_CHAN_PHYSMASK) == (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT) )
    {
        /* 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->output.output.i_original_channels & AOUT_CHAN_DUALMONO )
        {
            /* Go directly to the left channel. */
            p_aout->output.output.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->output.output.i_physical_channels ==
               (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT)
                && (p_aout->output.output.i_original_channels &
                     (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT)) )
    {
        /* 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->output.output.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->output.output.i_original_channels & AOUT_CHAN_DUALMONO )
        {
            /* Go directly to the left channel. */
            p_aout->output.output.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_SetBool( p_aout, "intf-change", true );

    aout_FormatPrepare( &p_aout->output.output );

    aout_lock_output_fifo( p_aout );

    /* Prepare FIFO. */
    aout_FifoInit( p_aout, &p_aout->output.fifo,
                   p_aout->output.output.i_rate );

    aout_unlock_output_fifo( p_aout );

    aout_FormatPrint( p_aout, "output", &p_aout->output.output );

    /* Calculate the resulting mixer output format. */
    p_aout->mixer_format = p_aout->output.output;
    if ( !AOUT_FMT_NON_LINEAR(&p_aout->output.output) )
    {
        /* Non-S/PDIF mixer only deals with float32 or fixed32. */
        p_aout->mixer_format.i_format
                     = HAVE_FPU ? VLC_CODEC_FL32 : VLC_CODEC_FI32;
        aout_FormatPrepare( &p_aout->mixer_format );
    }
    else
    {
        p_aout->mixer_format.i_format = p_format->i_format;
    }

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

    /* Create filters. */
    p_aout->output.i_nb_filters = 0;
    if ( aout_FiltersCreatePipeline( p_aout, p_aout->output.pp_filters,
                                     &p_aout->output.i_nb_filters,
                                     &p_aout->mixer_format,
                                     &p_aout->output.output ) < 0 )
    {
        msg_Err( p_aout, "couldn't create audio output pipeline" );
        module_unneed( p_aout, p_aout->output.p_module );
        return -1;
    }

    /* Prepare hints for the buffer allocator. */
    p_aout->mixer_allocation.b_alloc = true;
    p_aout->mixer_allocation.i_bytes_per_sec
                        = p_aout->mixer_format.i_bytes_per_frame
                           * p_aout->mixer_format.i_rate
                           / p_aout->mixer_format.i_frame_length;

    aout_FiltersHintBuffers( p_aout, p_aout->output.pp_filters,
                             p_aout->output.i_nb_filters,
                             &p_aout->mixer_allocation );

    p_aout->output.b_error = 0;
    return 0;
}