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

📄 waveout.c

📁 video linux conference
💻 C
📖 第 1 页 / 共 2 页
字号:
                        p_aout->output.output.i_rate, VLC_TRUE )        == VLC_SUCCESS )    {        val.i_int = AOUT_VAR_MONO;        text.psz_string = N_("Mono");        var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text );        msg_Dbg( p_aout, "device supports 1 channel" );    }    /* Test for SPDIF support */    if ( AOUT_FMT_NON_LINEAR( &p_aout->output.output ) )    {        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_TRUE )            == VLC_SUCCESS )        {            msg_Dbg( p_aout, "device supports A/52 over S/PDIF" );            val.i_int = AOUT_VAR_SPDIF;            text.psz_string = N_("A/52 over S/PDIF");            var_Change( p_aout, "audio-device",                        VLC_VAR_ADDCHOICE, &val, &text );            if( config_GetInt( p_aout, "spdif" ) )                var_Set( p_aout, "audio-device", val );        }    }    var_Change( p_aout, "audio-device", VLC_VAR_CHOICESCOUNT, &val, NULL );    if( val.i_int <= 0 )    {        /* Probe() has failed. */        var_Destroy( p_aout, "audio-device" );        return;    }    var_AddCallback( p_aout, "audio-device", aout_ChannelsRestart, NULL );    val.b_bool = VLC_TRUE;    var_Set( p_aout, "intf-change", val );}/***************************************************************************** * Play: play a sound buffer ***************************************************************************** * This doesn't actually play the buffer. This just stores the buffer so it * can be played by the callback thread. *****************************************************************************/static void Play( aout_instance_t *_p_aout ){}/***************************************************************************** * Close: close the audio device *****************************************************************************/static void Close( vlc_object_t *p_this ){    aout_instance_t *p_aout = (aout_instance_t *)p_this;    aout_sys_t *p_sys = p_aout->output.p_sys;    /* Before calling waveOutClose we must reset the device */    p_aout->b_die = VLC_TRUE;    waveOutReset( p_sys->h_waveout );    /* wake up the audio thread */    SetEvent( p_sys->event );    vlc_thread_join( p_sys->p_notif );    vlc_object_destroy( p_sys->p_notif );    CloseHandle( p_sys->event );    /* Close the device */    if( waveOutClose( p_sys->h_waveout ) != MMSYSERR_NOERROR )    {        msg_Err( p_aout, "waveOutClose failed" );    }    free( p_sys->p_silence_buffer );    free( p_sys );}/***************************************************************************** * OpenWaveOut: open the waveout sound device ****************************************************************************/static int OpenWaveOut( aout_instance_t *p_aout, int i_format,                        int i_channels, int i_nb_channels, int i_rate,                        vlc_bool_t b_probe ){    MMRESULT result;    unsigned int i;    /* Set sound format */#define waveformat p_aout->output.p_sys->waveformat    waveformat.dwChannelMask = 0;    for( i = 0; i < sizeof(pi_channels_src)/sizeof(uint32_t); i++ )    {        if( i_channels & pi_channels_src[i] )            waveformat.dwChannelMask |= pi_channels_in[i];    }    switch( i_format )    {    case VLC_FOURCC('s','p','d','i'):        i_nb_channels = 2;        /* To prevent channel re-ordering */        waveformat.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;        waveformat.Format.wBitsPerSample = 16;        waveformat.Samples.wValidBitsPerSample =            waveformat.Format.wBitsPerSample;        waveformat.Format.wFormatTag = WAVE_FORMAT_DOLBY_AC3_SPDIF;        waveformat.SubFormat = __KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF;        break;    case VLC_FOURCC('f','l','3','2'):        waveformat.Format.wBitsPerSample = sizeof(float) * 8;        waveformat.Samples.wValidBitsPerSample =            waveformat.Format.wBitsPerSample;        waveformat.Format.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;        waveformat.SubFormat = __KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;        break;    case VLC_FOURCC('s','1','6','l'):        waveformat.Format.wBitsPerSample = 16;        waveformat.Samples.wValidBitsPerSample =            waveformat.Format.wBitsPerSample;        waveformat.Format.wFormatTag = WAVE_FORMAT_PCM;        waveformat.SubFormat = __KSDATAFORMAT_SUBTYPE_PCM;        break;    }    waveformat.Format.nChannels = i_nb_channels;    waveformat.Format.nSamplesPerSec = i_rate;    waveformat.Format.nBlockAlign =        waveformat.Format.wBitsPerSample / 8 * i_nb_channels;    waveformat.Format.nAvgBytesPerSec =        waveformat.Format.nSamplesPerSec * waveformat.Format.nBlockAlign;    /* Only use the new WAVE_FORMAT_EXTENSIBLE format for multichannel audio */    if( i_nb_channels <= 2 )    {        waveformat.Format.cbSize = 0;    }    else    {        waveformat.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;        waveformat.Format.cbSize =            sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);    }    /* Open the device */    result = waveOutOpen( &p_aout->output.p_sys->h_waveout, WAVE_MAPPER,                          (WAVEFORMATEX *)&waveformat,                          (DWORD_PTR)WaveOutCallback, (DWORD_PTR)p_aout,                          CALLBACK_FUNCTION | (b_probe?WAVE_FORMAT_QUERY:0) );    if( result == WAVERR_BADFORMAT )    {        msg_Warn( p_aout, "waveOutOpen failed WAVERR_BADFORMAT" );        return VLC_EGENERIC;    }    if( result == MMSYSERR_ALLOCATED )    {        msg_Warn( p_aout, "waveOutOpen failed WAVERR_ALLOCATED" );        return VLC_EGENERIC;    }    if( result != MMSYSERR_NOERROR )    {        msg_Warn( p_aout, "waveOutOpen failed" );        return VLC_EGENERIC;    }    p_aout->output.p_sys->b_chan_reorder =        aout_CheckChannelReorder( pi_channels_in, pi_channels_out,                                  waveformat.dwChannelMask, i_nb_channels,                                  p_aout->output.p_sys->pi_chan_table );    if( p_aout->output.p_sys->b_chan_reorder )    {        msg_Dbg( p_aout, "channel reordering needed" );    }    return VLC_SUCCESS;#undef waveformat}/***************************************************************************** * OpenWaveOutPCM: open a PCM waveout sound device ****************************************************************************/static int OpenWaveOutPCM( aout_instance_t *p_aout, int *i_format,                           int i_channels, int i_nb_channels, int i_rate,                           vlc_bool_t b_probe ){    vlc_value_t val;    var_Get( p_aout, "waveout-float32", &val );    if( !val.b_bool || OpenWaveOut( p_aout, VLC_FOURCC('f','l','3','2'),                                   i_channels, i_nb_channels, i_rate, b_probe )        != VLC_SUCCESS )    {        if ( OpenWaveOut( p_aout, VLC_FOURCC('s','1','6','l'),                          i_channels, i_nb_channels, i_rate, b_probe )             != VLC_SUCCESS )        {            return VLC_EGENERIC;        }        else        {            *i_format = VLC_FOURCC('s','1','6','l');            return VLC_SUCCESS;        }    }    else    {        *i_format = VLC_FOURCC('f','l','3','2');        return VLC_SUCCESS;    }}/***************************************************************************** * PlayWaveOut: play a buffer through the WaveOut device *****************************************************************************/static int PlayWaveOut( aout_instance_t *p_aout, HWAVEOUT h_waveout,                        WAVEHDR *p_waveheader, aout_buffer_t *p_buffer ){    MMRESULT result;    /* Prepare the buffer */    if( p_buffer != NULL )        p_waveheader->lpData = p_buffer->p_buffer;    else        /* Use silence buffer instead */        p_waveheader->lpData = p_aout->output.p_sys->p_silence_buffer;    p_waveheader->dwUser = p_buffer ? (DWORD_PTR)p_buffer : (DWORD_PTR)1;    p_waveheader->dwBufferLength = p_aout->output.p_sys->i_buffer_size;    p_waveheader->dwFlags = 0;    result = waveOutPrepareHeader( h_waveout, p_waveheader, sizeof(WAVEHDR) );    if( result != MMSYSERR_NOERROR )    {        msg_Err( p_aout, "waveOutPrepareHeader failed" );        return VLC_EGENERIC;    }    /* Send the buffer to the waveOut queue */    result = waveOutWrite( h_waveout, p_waveheader, sizeof(WAVEHDR) );    if( result != MMSYSERR_NOERROR )    {        msg_Err( p_aout, "waveOutWrite failed" );        return VLC_EGENERIC;    }    return VLC_SUCCESS;}/***************************************************************************** * WaveOutCallback: what to do once WaveOut has played its sound samples *****************************************************************************/static void CALLBACK WaveOutCallback( HWAVEOUT h_waveout, UINT uMsg,                                      DWORD _p_aout,                                      DWORD dwParam1, DWORD dwParam2 ){    aout_instance_t *p_aout = (aout_instance_t *)_p_aout;    int i, i_queued_frames = 0;    if( uMsg != WOM_DONE ) return;    if( p_aout->b_die ) return;    /* Find out the current latency */    for( i = 0; i < FRAMES_NUM; i++ )    {        /* Check if frame buf is available */        if( !(p_aout->output.p_sys->waveheader[i].dwFlags & WHDR_DONE) )        {            i_queued_frames++;        }    }    /* Don't wake up the thread too much */    if( i_queued_frames < FRAMES_NUM / 2 )        SetEvent( p_aout->output.p_sys->event );}/***************************************************************************** * WaveOutThread: this thread will capture play notification events.  ***************************************************************************** * We use this thread to feed new audio samples to the sound card because * we are not authorized to use waveOutWrite() directly in the waveout * callback. *****************************************************************************/static void WaveOutThread( notification_thread_t *p_notif ){    aout_instance_t *p_aout = p_notif->p_aout;    aout_sys_t *p_sys = p_aout->output.p_sys;    aout_buffer_t *p_buffer = NULL;    WAVEHDR *p_waveheader = p_sys->waveheader;    int i, i_queued_frames;    vlc_bool_t b_sleek;    /* We don't want any resampling when using S/PDIF */    b_sleek = p_aout->output.output.i_format == VLC_FOURCC('s','p','d','i');    while( 1 )    {        WaitForSingleObject( p_sys->event, INFINITE );        /* Cleanup and find out the current latency */        i_queued_frames = 0;        for( i = 0; i < FRAMES_NUM; i++ )        {            if( (p_waveheader[i].dwFlags & WHDR_DONE) &&                p_waveheader[i].dwUser )            {                /* Unprepare and free the buffers which has just been played */                waveOutUnprepareHeader( p_sys->h_waveout, &p_waveheader[i],                                        sizeof(WAVEHDR) );                if( p_waveheader[i].dwUser != 1 )                    aout_BufferFree( (aout_buffer_t *)p_waveheader[i].dwUser );                p_waveheader[i].dwUser = 0;            }            /* Check if frame buf is available */            if( !(p_waveheader[i].dwFlags & WHDR_DONE) )            {                i_queued_frames++;            }        }        if( p_aout->b_die ) return;        /* Try to fill in as many frame buffers as possible */        for( i = 0; i < FRAMES_NUM; i++ )        {            /* Check if frame buf is available */            if( p_waveheader[i].dwFlags & WHDR_DONE )            {                /* Take into account the latency */                p_buffer = aout_OutputNextBuffer( p_aout,                    mdate() + 1000000 * i_queued_frames /                    p_aout->output.output.i_rate * p_aout->output.i_nb_samples,                    b_sleek );                if( !p_buffer && i_queued_frames )                {                    /* We aren't late so no need to play a blank sample */                    break;                }                /* Do the channel reordering */                if( p_buffer && p_sys->b_chan_reorder )                {                    aout_ChannelReorder( p_buffer->p_buffer,                        p_buffer->i_nb_bytes,                        p_sys->waveformat.Format.nChannels,                        p_sys->pi_chan_table,                        p_sys->waveformat.Format.wBitsPerSample );                }                PlayWaveOut( p_aout, p_sys->h_waveout,                             &p_waveheader[i], p_buffer );                i_queued_frames++;            }        }    }}static int VolumeInfos( aout_instance_t * p_aout, audio_volume_t * pi_soft ){    *pi_soft = AOUT_VOLUME_MAX / 2;    return 0;}static int VolumeGet( aout_instance_t * p_aout, audio_volume_t * pi_volume ){    DWORD i_waveout_vol;#ifdef UNDER_CE    waveOutGetVolume( 0, &i_waveout_vol );#else    waveOutGetVolume( p_aout->output.p_sys->h_waveout, &i_waveout_vol );#endif    i_waveout_vol &= 0xFFFF;    *pi_volume = p_aout->output.i_volume =        i_waveout_vol * AOUT_VOLUME_MAX / 2 / 0xFFFF;    return 0;}static int VolumeSet( aout_instance_t * p_aout, audio_volume_t i_volume ){    unsigned long i_waveout_vol = i_volume * 0xFFFF * 2 / AOUT_VOLUME_MAX;    i_waveout_vol |= (i_waveout_vol << 16);#ifdef UNDER_CE    waveOutSetVolume( 0, i_waveout_vol );#else    waveOutSetVolume( p_aout->output.p_sys->h_waveout, i_waveout_vol );#endif    p_aout->output.i_volume = i_volume;    return 0;}

⌨️ 快捷键说明

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