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

📄 waveout.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 3 页
字号:
    }}/***************************************************************************** * 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,                        bool b_spdif){    MMRESULT result;    /* Prepare the buffer */    if( p_buffer != NULL )    {        p_waveheader->lpData = p_buffer->p_buffer;        /*          copy the buffer to the silence buffer :) so in case we don't          get the next buffer fast enough (I will repeat this one a time          for AC3 / DTS and SPDIF this will sound better instead of          a hickup)        */        if(b_spdif)        {           vlc_memcpy( p_aout->output.p_sys->p_silence_buffer,                       p_buffer->p_buffer,                       p_aout->output.p_sys->i_buffer_size );           p_aout->output.p_sys->i_repeat_counter = 2;        }    } else {        /* Use silence buffer instead */        if(p_aout->output.p_sys->i_repeat_counter)        {           p_aout->output.p_sys->i_repeat_counter--;           if(!p_aout->output.p_sys->i_repeat_counter)           {               vlc_memset( p_aout->output.p_sys->p_silence_buffer,                           0x00, p_aout->output.p_sys->i_buffer_size );           }        }        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 ){    (void)h_waveout;    (void)dwParam1;    (void)dwParam2;    aout_instance_t *p_aout = (aout_instance_t *)_p_aout;    int i, i_queued_frames = 0;    if( uMsg != WOM_DONE ) return;    if( !vlc_object_alive (p_aout) ) 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 );}/**************************************************************************** * WaveOutClearDoneBuffers: Clear all done marked buffers, and free aout_bufer **************************************************************************** * return value is the number of still playing buffers in the queue ****************************************************************************/static int WaveOutClearDoneBuffers(aout_sys_t *p_sys){    WAVEHDR *p_waveheader = p_sys->waveheader;    int i_queued_frames = 0;    for( int i = 0; i < FRAMES_NUM; i++ )    {        if( (p_waveheader[i].dwFlags & WHDR_DONE) &&            p_waveheader[i].dwUser )        {            aout_buffer_t *p_buffer =                    (aout_buffer_t *)(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( p_buffer );            p_waveheader[i].dwUser = 0;        }        /* Check if frame buf is available */        if( !(p_waveheader[i].dwFlags & WHDR_DONE) )        {            i_queued_frames++;        }    }    return i_queued_frames;}/***************************************************************************** * 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( vlc_object_t *p_this ){    notification_thread_t *p_notif = (notification_thread_t*)p_this;    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;    bool b_sleek;    mtime_t next_date;    uint32_t i_buffer_length = 64;    /* We don't want any resampling when using S/PDIF */    b_sleek = p_aout->output.output.i_format == VLC_FOURCC('s','p','d','i');    // wait for first call to "play()"    while( !p_sys->start_date && vlc_object_alive (p_aout) )           WaitForSingleObject( p_sys->event, INFINITE );    if( !vlc_object_alive (p_aout) )        return NULL;    msg_Dbg( p_aout, "will start to play in %"PRId64" us",             (p_sys->start_date - AOUT_PTS_TOLERANCE/4)-mdate());    // than wait a short time... before grabbing first frames    mwait( p_sys->start_date - AOUT_PTS_TOLERANCE/4 );#define waveout_warn(msg) msg_Warn( p_aout, "aout_OutputNextBuffer no buffer "\                           "got next_date=%d ms, "\                           "%d frames to play, "\                           "starving? %d, %s",(int)(next_date/(mtime_t)1000), \                           i_queued_frames, \                           p_aout->output.b_starving, msg);    next_date = mdate();    while( vlc_object_alive (p_aout) )    {        /* Cleanup and find out the current latency */        i_queued_frames = WaveOutClearDoneBuffers( p_sys );        if( !vlc_object_alive (p_aout) ) return NULL;        /* 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 )            {                // next_date = mdate() + 1000000 * i_queued_frames /                //  p_aout->output.output.i_rate * p_aout->output.i_nb_samples;                // the realtime has got our back-site:) to come in sync                if(next_date < mdate())                   next_date = mdate();                /* Take into account the latency */                p_buffer = aout_OutputNextBuffer( p_aout,                    next_date,                    b_sleek );                if(!p_buffer)                {#if 0                    msg_Dbg( p_aout, "aout_OutputNextBuffer no buffer "\                                      "got next_date=%d ms, "\                                      "%d frames to play, "\                                      "starving? %d",(int)(next_date/(mtime_t)1000),                                                     i_queued_frames,                                                     p_aout->output.b_starving);#endif                    if(p_aout->output.b_starving)                    {                        // means we are too early to request a new buffer?                        waveout_warn("waiting...")                        next_date = aout_FifoFirstDate( p_aout, &p_aout->output.fifo );                        mwait( next_date - AOUT_PTS_TOLERANCE/4 );                        next_date = mdate();                        p_buffer = aout_OutputNextBuffer( p_aout,                                     next_date,                                     b_sleek                                   );                    }                }                if( !p_buffer && i_queued_frames )                {                    /* We aren't late so no need to play a blank sample */                    break;                }                if( p_buffer )                {                    mtime_t buffer_length = (p_buffer->end_date                                             - p_buffer->start_date);                    next_date = next_date + buffer_length;                    i_buffer_length = buffer_length/1000;                }                /* 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, b_sleek );                i_queued_frames++;            }        }        if( !vlc_object_alive (p_aout) ) return NULL;        /*          deal with the case that the loop didn't fillup the buffer to the          max - instead of waiting that half the buffer is played before          fillup the waveout buffers, wait only for the next sample buffer          to arrive at the play method...          this will also avoid, that the last buffer is play until the          end, and then trying to get more data, so it will also          work - if the next buffer will arrive some ms before the          last buffer is finished.        */        if(i_queued_frames < FRAMES_NUM)           WaitForSingleObject( p_sys->new_buffer_event, INFINITE );        else           WaitForSingleObject( p_sys->event, INFINITE );    }#undef waveout_warn    return NULL;}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 + 0xFFFF /*rounding*/) / 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;}/*  reload the configuration drop down list, of the Audio Devices*/static int ReloadWaveoutDevices( vlc_object_t *p_this, char const *psz_name,                                 vlc_value_t newval, vlc_value_t oldval, void *data ){    int i;    module_config_t *p_item = config_FindConfig( p_this, psz_name );    if( !p_item ) return VLC_SUCCESS;    /* Clear-up the current list */    if( p_item->i_list )    {        /* Keep the first entry */        for( i = 1; i < p_item->i_list; i++ )        {            free((char *)(p_item->ppsz_list[i]) );            free((char *)(p_item->ppsz_list_text[i]) );        }        /* TODO: Remove when no more needed */        p_item->ppsz_list[i] = NULL;        p_item->ppsz_list_text[i] = NULL;    }    p_item->i_list = 1;    int wave_devices = waveOutGetNumDevs();    p_item->ppsz_list =        (char **)realloc( p_item->ppsz_list,                          (wave_devices+2) * sizeof(char *) );    p_item->ppsz_list_text =        (char **)realloc( p_item->ppsz_list_text,                          (wave_devices+2) * sizeof(char *) );    WAVEOUTCAPS caps;    char sz_dev_name[MAXPNAMELEN+32];    int j=1;    for(int i=0; i<wave_devices; i++)    {        if(waveOutGetDevCaps(i, &caps, sizeof(WAVEOUTCAPS))           == MMSYSERR_NOERROR)        {          sprintf( sz_dev_name, psz_device_name_fmt, caps.szPname,                                               caps.wMid,                                               caps.wPid                                              );          p_item->ppsz_list[j] = FromLocaleDup( sz_dev_name );          p_item->ppsz_list_text[j] = FromLocaleDup( sz_dev_name );          p_item->i_list++;          j++;        }    }    p_item->ppsz_list[j] = NULL;    p_item->ppsz_list_text[j] = NULL;    /* Signal change to the interface */    p_item->b_dirty = true;    return VLC_SUCCESS;}/*  convert devicename to device ID for output  if device not found return WAVE_MAPPER, so let  windows decide which preferred audio device  should be used.*/static uint32_t findDeviceID(char *psz_device_name){    if(!psz_device_name)       return WAVE_MAPPER;    uint32_t wave_devices = waveOutGetNumDevs();    WAVEOUTCAPS caps;    char sz_dev_name[MAXPNAMELEN+32];    for(uint32_t i=0; i<wave_devices; i++)    {        if(waveOutGetDevCaps(i, &caps, sizeof(WAVEOUTCAPS))           == MMSYSERR_NOERROR)        {            sprintf(sz_dev_name, psz_device_name_fmt, caps.szPname,                                               caps.wMid,                                               caps.wPid                                              );            char *psz_temp = FromLocaleDup(sz_dev_name);            if( !stricmp(psz_temp, psz_device_name) )            {                LocaleFree( psz_temp );                return i;            }            LocaleFree( psz_temp );        }    }    return WAVE_MAPPER;}

⌨️ 快捷键说明

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