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

📄 directx.c

📁 video linux conference
💻 C
📖 第 1 页 / 共 3 页
字号:
    }    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;    p_aout->output.p_sys->i_bits_per_sample = waveformat.Format.wBitsPerSample;    p_aout->output.p_sys->i_channels = i_nb_channels;    /* Then fill in the direct sound descriptor */    memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));    dsbdesc.dwSize = sizeof(DSBUFFERDESC);    dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2/* Better position accuracy */                    | DSBCAPS_CTRLPOSITIONNOTIFY     /* We need notification */                    | DSBCAPS_GLOBALFOCUS;      /* Allows background playing */    /* 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);        /* Needed for 5.1 on emu101k */        dsbdesc.dwFlags |= DSBCAPS_LOCHARDWARE;    }    dsbdesc.dwBufferBytes = FRAMES_NUM * i_bytes_per_frame;   /* buffer size */    dsbdesc.lpwfxFormat = (WAVEFORMATEX *)&waveformat;    if FAILED( IDirectSound_CreateSoundBuffer(                   p_aout->output.p_sys->p_dsobject, &dsbdesc,                   &p_aout->output.p_sys->p_dsbuffer, NULL) )    {        if( dsbdesc.dwFlags & DSBCAPS_LOCHARDWARE )        {            /* Try without DSBCAPS_LOCHARDWARE */            dsbdesc.dwFlags &= ~DSBCAPS_LOCHARDWARE;            if FAILED( IDirectSound_CreateSoundBuffer(                   p_aout->output.p_sys->p_dsobject, &dsbdesc,                   &p_aout->output.p_sys->p_dsbuffer, NULL) )            {                return VLC_EGENERIC;            }            if( !b_probe )                msg_Dbg( p_aout, "couldn't use hardware sound buffer" );        }        else        {            return VLC_EGENERIC;        }    }    /* Stop here if we were just probing */    if( b_probe )    {        IDirectSoundBuffer_Release( p_aout->output.p_sys->p_dsbuffer );        p_aout->output.p_sys->p_dsbuffer = NULL;        return VLC_SUCCESS;    }    /* Backup the size of a frame */    p_aout->output.p_sys->p_notif->i_frame_size = i_bytes_per_frame;    /* Now the secondary buffer is created, we need to setup its position     * notification */    for( i = 0; i < FRAMES_NUM; i++ )    {        p_aout->output.p_sys->p_notif->p_events[i].dwOffset = i *            p_aout->output.p_sys->p_notif->i_frame_size;        p_aout->output.p_sys->p_notif->i_frame_status[i] = FRAME_EMPTY;    }    /* Get the IDirectSoundNotify interface */    if FAILED( IDirectSoundBuffer_QueryInterface(                                p_aout->output.p_sys->p_dsbuffer,                                &IID_IDirectSoundNotify,                                (LPVOID *)&p_aout->output.p_sys->p_dsnotify ) )    {        msg_Err( p_aout, "cannot get IDirectSoundNotify interface" );        goto error;    }    if FAILED( IDirectSoundNotify_SetNotificationPositions(                                    p_aout->output.p_sys->p_dsnotify,                                    FRAMES_NUM,                                    p_aout->output.p_sys->p_notif->p_events ) )    {        msg_Err( p_aout, "cannot set position notification" );        goto error;    }    p_aout->output.p_sys->i_channel_mask = waveformat.dwChannelMask;    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; error:    DestroyDSBuffer( p_aout );    return VLC_EGENERIC;}/***************************************************************************** * CreateDSBufferPCM: creates a PCM direct sound buffer. ***************************************************************************** * We first try to create a WAVE_FORMAT_IEEE_FLOAT buffer if supported by * the hardware, otherwise we create a WAVE_FORMAT_PCM buffer. ****************************************************************************/static int CreateDSBufferPCM( 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, "directx-audio-float32", &val );    /* Float32 audio samples are not supported for 5.1 output on the emu101k */    if( !val.b_bool || i_nb_channels > 2 ||        CreateDSBuffer( p_aout, VLC_FOURCC('f','l','3','2'),                        i_channels, i_nb_channels, i_rate,                        FRAME_SIZE * 4 * i_nb_channels, b_probe )        != VLC_SUCCESS )    {        if ( CreateDSBuffer( p_aout, VLC_FOURCC('s','1','6','l'),                             i_channels, i_nb_channels, i_rate,                             FRAME_SIZE * 2 * i_nb_channels, 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;    }}/***************************************************************************** * DestroyDSBuffer ***************************************************************************** * This function destroys the secondary buffer. *****************************************************************************/static void DestroyDSBuffer( aout_instance_t *p_aout ){    if( p_aout->output.p_sys->p_dsnotify )    {        IDirectSoundNotify_Release( p_aout->output.p_sys->p_dsnotify );        p_aout->output.p_sys->p_dsnotify = NULL;    }    if( p_aout->output.p_sys->p_dsbuffer )    {        IDirectSoundBuffer_Release( p_aout->output.p_sys->p_dsbuffer );        p_aout->output.p_sys->p_dsbuffer = NULL;    }}/***************************************************************************** * FillBuffer: Fill in one of the direct sound frame buffers. ***************************************************************************** * Returns VLC_SUCCESS on success. *****************************************************************************/static int FillBuffer( aout_instance_t *p_aout, int i_frame,                       aout_buffer_t *p_buffer ){    notification_thread_t *p_notif = p_aout->output.p_sys->p_notif;    aout_sys_t *p_sys = p_aout->output.p_sys;    void *p_write_position, *p_wrap_around;    long l_bytes1, l_bytes2;    HRESULT dsresult;    /* Before copying anything, we have to lock the buffer */    dsresult = IDirectSoundBuffer_Lock(                p_sys->p_dsbuffer,                              /* DS buffer */                i_frame * p_notif->i_frame_size,             /* Start offset */                p_notif->i_frame_size,                    /* Number of bytes */                &p_write_position,                  /* Address of lock start */                &l_bytes1,       /* Count of bytes locked before wrap around */                &p_wrap_around,            /* Buffer adress (if wrap around) */                &l_bytes2,               /* Count of bytes after wrap around */                0 );                                                /* Flags */    if( dsresult == DSERR_BUFFERLOST )    {        IDirectSoundBuffer_Restore( p_sys->p_dsbuffer );        dsresult = IDirectSoundBuffer_Lock(                               p_sys->p_dsbuffer,                               i_frame * p_notif->i_frame_size,                               p_notif->i_frame_size,                               &p_write_position,                               &l_bytes1,                               &p_wrap_around,                               &l_bytes2,                               0 );    }    if( dsresult != DS_OK )    {        msg_Warn( p_notif, "cannot lock buffer" );        if( p_buffer ) aout_BufferFree( p_buffer );        return VLC_EGENERIC;    }    if( p_buffer == NULL )    {        memset( p_write_position, 0, l_bytes1 );    }    else    {        if( p_sys->b_chan_reorder )        {            /* Do the channel reordering here */            aout_ChannelReorder( p_buffer->p_buffer, p_buffer->i_nb_bytes,                                 p_sys->i_channels, p_sys->pi_chan_table,                                 p_sys->i_bits_per_sample );        }        p_aout->p_vlc->pf_memcpy( p_write_position, p_buffer->p_buffer,                                  l_bytes1 );        aout_BufferFree( p_buffer );    }    /* Now the data has been copied, unlock the buffer */    IDirectSoundBuffer_Unlock( p_sys->p_dsbuffer, p_write_position, l_bytes1,                               p_wrap_around, l_bytes2 );    return VLC_SUCCESS;}/***************************************************************************** * DirectSoundThread: this thread will capture play notification events.  ***************************************************************************** * We use this thread to emulate a callback mechanism. The thread probes for * event notification and fills up the DS secondary buffer when needed. *****************************************************************************/static void DirectSoundThread( notification_thread_t *p_notif ){    HANDLE  notification_events[FRAMES_NUM];    HRESULT dsresult;    aout_instance_t *p_aout = p_notif->p_aout;    int i, i_which_frame, i_last_frame, i_next_frame;    mtime_t mtime;    vlc_bool_t b_sleek;    for( i = 0; i < FRAMES_NUM; i++ )        notification_events[i] = p_notif->p_events[i].hEventNotify;    /* We don't want any resampling when using S/PDIF output */    b_sleek = p_aout->output.output.i_format == VLC_FOURCC('s','p','d','i');    /* Tell the main thread that we are ready */    vlc_thread_ready( p_notif );    msg_Dbg( p_notif, "DirectSoundThread ready" );    /* Wait here until Play() is called */    WaitForSingleObject( notification_events[0], INFINITE );    if( !p_notif->b_die )    {        mwait( p_notif->start_date - AOUT_PTS_TOLERANCE / 2 );        /* start playing the buffer */        dsresult = IDirectSoundBuffer_Play( p_aout->output.p_sys->p_dsbuffer,                                        0,                         /* Unused */                                        0,                         /* Unused */                                        DSBPLAY_LOOPING );          /* Flags */        if( dsresult == DSERR_BUFFERLOST )        {            IDirectSoundBuffer_Restore( p_aout->output.p_sys->p_dsbuffer );            dsresult = IDirectSoundBuffer_Play(                                            p_aout->output.p_sys->p_dsbuffer,                                            0,                     /* Unused */                                            0,                     /* Unused */                                            DSBPLAY_LOOPING );      /* Flags */        }        if( dsresult != DS_OK )        {            msg_Err( p_aout, "cannot start playing buffer" );        }    }    while( !p_notif->b_die )    {        aout_buffer_t *p_buffer;        long l_latency;        /* wait for the position notification */        i_which_frame = WaitForMultipleObjects( FRAMES_NUM,                                                notification_events, 0,                                                INFINITE ) - WAIT_OBJECT_0;        if( p_notif->b_die )            break;        mtime = mdate();        /* We take into account the current latency */        if SUCCEEDED( IDirectSoundBuffer_GetCurrentPosition(                        p_aout->output.p_sys->p_dsbuffer,                        &l_latency, NULL ) )        {            if( l_latency > (i_which_frame * FRAME_SIZE)                  && l_latency < ((i_which_frame+1) * FRAME_SIZE) )            {                l_latency = - ( l_latency /                                p_aout->output.output.i_bytes_per_frame %                                FRAME_SIZE );            }            else            {                l_latency = FRAME_SIZE - ( l_latency /                                      p_aout->output.output.i_bytes_per_frame %                                      FRAME_SIZE );            }        }        else        {            l_latency = 0;        }        /* Mark last frame as empty */        i_last_frame = (i_which_frame + FRAMES_NUM -1) % FRAMES_NUM;        i_next_frame = (i_which_frame + 1) % FRAMES_NUM;        p_notif->i_frame_status[i_last_frame] = FRAME_EMPTY;        /* Try to fill in as many frame buffers as possible */        for( i = i_next_frame; (i % FRAMES_NUM) != i_which_frame; i++ )        {            /* Check if frame buf is already filled */            if( p_notif->i_frame_status[i % FRAMES_NUM] == FRAME_QUEUED )                continue;            p_buffer = aout_OutputNextBuffer( p_aout,                mtime + 1000000 / p_aout->output.output.i_rate *                ((i - i_next_frame + 1) * FRAME_SIZE + l_latency), b_sleek );            /* If there is no audio data available and we have some buffered             * already, then just wait for the next time */            if( !p_buffer && (i != i_next_frame) )            {                //msg_Err( p_aout, "only %i frame buffers filled!",                //         i - i_next_frame );                break;            }            if( FillBuffer( p_aout, (i%FRAMES_NUM), p_buffer )                != VLC_SUCCESS )                break;            /* Mark the frame buffer as QUEUED */            p_notif->i_frame_status[i%FRAMES_NUM] = FRAME_QUEUED;        }    }    /* make sure the buffer isn't playing */    IDirectSoundBuffer_Stop( p_aout->output.p_sys->p_dsbuffer );    /* free the events */    for( i = 0; i < FRAMES_NUM; i++ )        CloseHandle( notification_events[i] );    msg_Dbg( p_notif, "DirectSoundThread exiting" );}

⌨️ 快捷键说明

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