⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 alsa.c

📁 uclinux 下的vlc播放器源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
        snprintf( psz_default_iec_device, sizeof(psz_default_iec_device),                  "iec958:AES0=0x%x,AES1=0x%x,AES2=0x%x,AES3=0x%x",                  IEC958_AES0_CON_EMPHASIS_NONE | IEC958_AES0_NONAUDIO,                  IEC958_AES1_CON_ORIGINAL | IEC958_AES1_CON_PCM_CODER,                  0,                  ( p_aout->output.output.i_rate == 48000 ?                    IEC958_AES3_CON_FS_48000 :                    ( p_aout->output.output.i_rate == 44100 ?                      IEC958_AES3_CON_FS_44100 : IEC958_AES3_CON_FS_32000 ) ) );        psz_iec_device = psz_default_iec_device;    }    else if( AOUT_FMT_NON_LINEAR( &p_aout->output.output ) )    {        psz_iec_device = psz_device;    }    else    {        psz_iec_device = NULL;    }    /* Choose the linear PCM format (read the comment above about FPU       and float32) */    if( p_aout->p_libvlc->i_cpu & CPU_CAPABILITY_FPU )    {        i_vlc_pcm_format = VLC_FOURCC('f','l','3','2');        i_snd_pcm_format = SND_PCM_FORMAT_FLOAT;    }    else    {        i_vlc_pcm_format = AOUT_FMT_S16_NE;        i_snd_pcm_format = SND_PCM_FORMAT_S16;    }    /* If the variable doesn't exist then it's the first time we're called       and we have to probe the available audio formats and channels */    if ( var_Type( p_aout, "audio-device" ) == 0 )    {        Probe( p_aout, psz_device, psz_iec_device, &i_snd_pcm_format );    }    if ( var_Get( p_aout, "audio-device", &val ) < 0 )    {        free( p_sys );        free( psz_device );        return VLC_EGENERIC;    }    p_aout->output.output.i_format = i_vlc_pcm_format;    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;        free( psz_device );        psz_device = strdup( "surround51" );    }    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;        free( psz_device );        psz_device = strdup( "surround40" );    }    else if ( val.i_int == AOUT_VAR_STEREO )    {        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_physical_channels = AOUT_CHAN_CENTER;    }    else if( val.i_int != AOUT_VAR_SPDIF )    {        /* This should not happen ! */        msg_Err( p_aout, "internal: can't find audio-device (%i)", val.i_int );        free( p_sys );        free( psz_device );        return VLC_EGENERIC;    }#ifdef ALSA_DEBUG    snd_output_stdio_attach( &p_sys->p_snd_stderr, stderr, 0 );#endif    /* Open the device */    if ( val.i_int == AOUT_VAR_SPDIF )    {        if ( ( i_snd_rc = snd_pcm_open( &p_sys->p_snd_pcm, psz_iec_device,                            SND_PCM_STREAM_PLAYBACK, 0 ) ) < 0 )        {            msg_Err( p_aout, "cannot open ALSA device `%s' (%s)",                             psz_iec_device, snd_strerror( i_snd_rc ) );            free( p_sys );            free( psz_device );            return VLC_EGENERIC;        }        i_buffer_size = ALSA_SPDIF_BUFFER_SIZE;        i_snd_pcm_format = SND_PCM_FORMAT_S16;        i_channels = 2;        i_vlc_pcm_format = VLC_FOURCC('s','p','d','i');        p_aout->output.i_nb_samples = i_period_size = ALSA_SPDIF_PERIOD_SIZE;        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 );    }    else    {        int i;        msg_Dbg( p_aout, "opening ALSA device `%s'", psz_device );        /* Since it seems snd_pcm_close hasen't really released the device at          the time it returns, probe if the device is available in loop for 1s.          We cannot use blocking mode since the we would wait indefinitely when          switching from a dmx device to surround51. */        for( i = 10; i >= 0; i-- )        {            if ( ( i_snd_rc = snd_pcm_open( &p_sys->p_snd_pcm, psz_device,                   SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK ) ) == -EBUSY )            {                if( i ) msleep( 100000 /* 100ms */ );                else msg_Err( p_aout, "audio device: %s is already in use",                              psz_device );                continue;            }            break;        }        if( i_snd_rc < 0 )        {            msg_Err( p_aout, "cannot open ALSA device `%s' (%s)",                             psz_device, snd_strerror( i_snd_rc ) );            free( p_sys );            free( psz_device );            return VLC_EGENERIC;        }        /* We want blocking mode */        snd_pcm_nonblock( p_sys->p_snd_pcm, 0 );        i_buffer_size = ALSA_DEFAULT_BUFFER_SIZE;        i_channels = aout_FormatNbChannels( &p_aout->output.output );        p_aout->output.i_nb_samples = i_period_size = ALSA_DEFAULT_PERIOD_SIZE;        aout_VolumeSoftInit( p_aout );    }    /* Free psz_device so that all the remaining data is stack-allocated */    free( psz_device );    p_aout->output.pf_play = Play;    snd_pcm_hw_params_alloca(&p_hw);    snd_pcm_sw_params_alloca(&p_sw);    /* Due to some bugs in alsa with some drivers, we need to retry in s16l       if snd_pcm_hw_params fails in fl32 */    while ( b_retry )    {        b_retry = VLC_FALSE;        /* Get Initial hardware parameters */        if ( ( i_snd_rc = snd_pcm_hw_params_any( p_sys->p_snd_pcm, p_hw ) ) < 0 )        {            msg_Err( p_aout, "unable to retrieve initial hardware parameters (%s)",                         snd_strerror( i_snd_rc ) );            goto error;        }        /* Set format. */        if ( ( i_snd_rc = snd_pcm_hw_params_set_format( p_sys->p_snd_pcm, p_hw,                                                    i_snd_pcm_format ) ) < 0 )        {            if( i_snd_pcm_format != SND_PCM_FORMAT_S16 )            {                i_snd_pcm_format = SND_PCM_FORMAT_S16;                i_snd_rc = snd_pcm_hw_params_set_format( p_sys->p_snd_pcm,                                                     p_hw, i_snd_pcm_format );            }            if ( i_snd_rc < 0 )            {                msg_Err( p_aout, "unable to set stream sample size and "                     "word order (%s)", snd_strerror( i_snd_rc ) );                goto error;            }        }        if( i_vlc_pcm_format != VLC_FOURCC('s','p','d','i') )        switch( i_snd_pcm_format )        {        case SND_PCM_FORMAT_FLOAT:            i_vlc_pcm_format = VLC_FOURCC('f','l','3','2');            break;        case SND_PCM_FORMAT_S16:            i_vlc_pcm_format = AOUT_FMT_S16_NE;            break;        }        p_aout->output.output.i_format = i_vlc_pcm_format;        if ( ( i_snd_rc = snd_pcm_hw_params_set_access( p_sys->p_snd_pcm, p_hw,                                    SND_PCM_ACCESS_RW_INTERLEAVED ) ) < 0 )        {            msg_Err( p_aout, "unable to set interleaved stream format (%s)",                             snd_strerror( i_snd_rc ) );            goto error;        }        /* Set channels. */        if ( ( i_snd_rc = snd_pcm_hw_params_set_channels( p_sys->p_snd_pcm, p_hw,                                                      i_channels ) ) < 0 )        {            msg_Err( p_aout, "unable to set number of output channels (%s)",                             snd_strerror( i_snd_rc ) );            goto error;        }        /* Set rate. */        i_old_rate = p_aout->output.output.i_rate;#ifdef HAVE_ALSA_NEW_API        i_snd_rc = snd_pcm_hw_params_set_rate_near( p_sys->p_snd_pcm, p_hw,                                                &p_aout->output.output.i_rate,                                                NULL );#else        i_snd_rc = snd_pcm_hw_params_set_rate_near( p_sys->p_snd_pcm, p_hw,                                                p_aout->output.output.i_rate,                                                NULL );#endif        if( i_snd_rc < 0 || p_aout->output.output.i_rate != i_old_rate )        {            msg_Warn( p_aout, "The rate %d Hz is not supported by your " \                "hardware. Using %d Hz instead.\n", i_old_rate, \                p_aout->output.output.i_rate );        }        /* Set buffer size. */#ifdef HAVE_ALSA_NEW_API        if ( ( i_snd_rc = snd_pcm_hw_params_set_buffer_size_near( p_sys->p_snd_pcm,                                    p_hw, &i_buffer_size ) ) < 0 )#else        if ( ( i_snd_rc = snd_pcm_hw_params_set_buffer_size_near( p_sys->p_snd_pcm,                                    p_hw, i_buffer_size ) ) < 0 )#endif        {            msg_Err( p_aout, "unable to set buffer size (%s)",                         snd_strerror( i_snd_rc ) );            goto error;        }        /* Set period size. */#ifdef HAVE_ALSA_NEW_API        if ( ( i_snd_rc = snd_pcm_hw_params_set_period_size_near( p_sys->p_snd_pcm,                                    p_hw, &i_period_size, NULL ) ) < 0 )#else        if ( ( i_snd_rc = snd_pcm_hw_params_set_period_size_near( p_sys->p_snd_pcm,                                    p_hw, i_period_size, NULL ) ) < 0 )#endif        {            msg_Err( p_aout, "unable to set period size (%s)",                         snd_strerror( i_snd_rc ) );            goto error;        }        p_aout->output.i_nb_samples = i_period_size;        /* Commit hardware parameters. */        if ( ( i_snd_rc = snd_pcm_hw_params( p_sys->p_snd_pcm, p_hw ) ) < 0 )        {            if ( b_retry == VLC_FALSE &&                                i_snd_pcm_format == SND_PCM_FORMAT_FLOAT)            {                b_retry = VLC_TRUE;                i_snd_pcm_format = SND_PCM_FORMAT_S16;                p_aout->output.output.i_format = AOUT_FMT_S16_NE;                msg_Warn( p_aout, "unable to commit hardware configuration "                                  "with fl32 samples. Retrying with s16l (%s)",                                     snd_strerror( i_snd_rc ) );            }            else            {                msg_Err( p_aout, "unable to commit hardware configuration (%s)",                         snd_strerror( i_snd_rc ) );                goto error;            }        }    }#ifdef HAVE_ALSA_NEW_API    if( ( i_snd_rc = snd_pcm_hw_params_get_period_time( p_hw,                                    &p_sys->i_period_time, NULL ) ) < 0 )#else    if( ( p_sys->i_period_time =                  (int)snd_pcm_hw_params_get_period_time( p_hw, NULL ) ) < 0 )#endif    {        msg_Err( p_aout, "unable to get period time (%s)",                         snd_strerror( i_snd_rc ) );        goto error;    }    /* Get Initial software parameters */    snd_pcm_sw_params_current( p_sys->p_snd_pcm, p_sw );    i_snd_rc = snd_pcm_sw_params_set_sleep_min( p_sys->p_snd_pcm, p_sw, 0 );    i_snd_rc = snd_pcm_sw_params_set_avail_min( p_sys->p_snd_pcm, p_sw,                                                p_aout->output.i_nb_samples );    /* Commit software parameters. */    if ( snd_pcm_sw_params( p_sys->p_snd_pcm, p_sw ) < 0 )    {        msg_Err( p_aout, "unable to set software configuration" );        goto error;    }#ifdef ALSA_DEBUG    snd_output_printf( p_sys->p_snd_stderr, "\nALSA hardware setup:\n\n" );    snd_pcm_dump_hw_setup( p_sys->p_snd_pcm, p_sys->p_snd_stderr );    snd_output_printf( p_sys->p_snd_stderr, "\nALSA software setup:\n\n" );    snd_pcm_dump_sw_setup( p_sys->p_snd_pcm, p_sys->p_snd_stderr );    snd_output_printf( p_sys->p_snd_stderr, "\n" );#endif    /* Create ALSA thread and wait for its readiness. */    if( vlc_thread_create( p_aout, "aout", ALSAThread,                           VLC_THREAD_PRIORITY_OUTPUT, VLC_FALSE ) )    {        msg_Err( p_aout, "cannot create ALSA thread (%s)", strerror(errno) );        goto error;    }    return 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -