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

📄 directsound_render.cpp

📁 audio-video-codecs.rar语音编解码器
💻 CPP
字号:
/*
//
//                  INTEL CORPORATION PROPRIETARY INFORMATION
//     This software is supplied under the terms of a license agreement or
//     nondisclosure agreement with Intel Corporation and may not be copied
//     or disclosed except in accordance with the terms of that agreement.
//       Copyright(c) 2003-2007 Intel Corporation. All Rights Reserved.
//
*/

#include "umc_defs.h"

#ifdef UMC_ENABLE_DSOUND_AUDIO_RENDER

#include <windows.h>
#include "ipps.h"
#include <vm_debug.h>
#include "directsound_render.h"

//const Ipp32u UMC::DSoundAudioRender::m_cuiSizeOfFrame = 6144;
const Ipp32u UMC::DSoundAudioRender::m_cuiNumOfFrames = 10;

UMC::DSoundAudioRender::DSoundAudioRender():
    m_hTimer(NULL),
    m_dwSampleAlign(0)
{}

UMC::DSoundAudioRender::~DSoundAudioRender(void)
{   Close();    }

UMC::Status UMC::DSoundAudioRender::Init(MediaReceiverParams* pInit)
{
    Status umcRes = UMC_OK;

    AudioRenderParams* pParams =
        DynamicCast<AudioRenderParams, MediaReceiverParams>(pInit);
    if (NULL == pParams)
    {   umcRes = UMC_ERR_NULL_PTR;  }

    HWNDModuleContext* pHWNDContext = NULL;
    if (UMC_OK == umcRes)
    {
        pHWNDContext =
            DynamicCast<HWNDModuleContext,ModuleContext>(pParams->pModuleContext);
        if (NULL == pHWNDContext)
        {    umcRes = UMC_ERR_INIT; }
    }

    sAudioStreamInfo* info = NULL;
    Ipp32s iLength = 0;
    Ipp32u dwBufferSize = 0;
    if (UMC_OK == umcRes)
    {
        info = &pParams->info;

        Ipp32s iSamples;
        switch (info->stream_type)
        {
            case AC3_AUDIO:
                iSamples = 256*6;
                break;
            case MP1L2_AUDIO:
            case MP1L3_AUDIO:
                iSamples = 1152;
                break;
            case MP2L3_AUDIO:
                iSamples = 576;
                break;
            default: iSamples = 1024;
        }

        m_dwSampleAlign = info->channels * (info->bitPerSample >> 3);
        iLength = m_dwSampleAlign * iSamples;
        dwBufferSize = iLength * m_cuiNumOfFrames;
    }

    if (UMC_OK == umcRes)
    {
        umcRes = m_DSBuffer.Init(pHWNDContext->m_hWnd,
                                 dwBufferSize,
                                 (Ipp16u)info->channels,
                                 info->sample_frequency,
                                 (Ipp16u)(info->bitPerSample >> 3));
    }

    if (UMC_OK == umcRes && NULL == m_hTimer)
    {
        m_hTimer = CreateWaitableTimer(0,false,0);
        if (NULL == m_hTimer)
        { umcRes = UMC_ERR_FAILED;  }
    }

    if (UMC_OK == umcRes)
    {   umcRes = BasicAudioRender::Init(pInit); }

    if (UMC_OK == umcRes)
    {   umcRes = m_AudioPtsArray.Init(m_cuiNumOfFrames, m_dfNorm);    }

    if (UMC_OK == umcRes)
    {
        LONG period = (LONG) (iLength / 2 * m_dfNorm * 1000);   // 32/2 ms
        LARGE_INTEGER interval;
        interval.QuadPart = - period/4*10000;  // in terms of 100ns

        if (!SetWaitableTimer(m_hTimer,&interval,period,0,0,true))
        {   umcRes = UMC_ERR_FAILED;  }
    }

    return umcRes;
}

UMC::Status UMC::DSoundAudioRender::SendFrame(MediaData* in)
{
    Status umcRes = UMC_OK;

    VM_ASSERT(NULL != in);
    if (!in)
    {  umcRes = UMC_ERR_NULL_PTR;  }

    if (UMC_OK == umcRes && NULL == in->GetDataPointer())
    {   umcRes = UMC_ERR_NULL_PTR;  }

    Ipp32u uiLength = in->GetDataSize();
    Ipp32u uiStartWritePos = m_DSBuffer.GetNextWriteOffset();
    Ipp32u uiWrapSize = 0;
    Ipp64f dfStartPTS = in->GetTime();

    if (UMC_OK == umcRes) {
        umcRes = m_AudioPtsArray.SetFramePTS(m_DSBuffer.GetNextWriteOffset(),
                                             0, in->GetTime());
    }

    for (Ipp8u *data_ptr = (Ipp8u *) in->GetDataPointer();
         UMC_OK == umcRes && 0 != uiLength && !m_bStop;)  {
        Ipp32u dwPlayCursor = 0;
        Ipp32u dwWriteCursor = 0;
        Ipp32u dwBytesWrote = 0;

        if (WAIT_OBJECT_0 != WaitForSingleObject(m_hTimer,INFINITE))
        {   umcRes = UMC_ERR_FAILED;  }

        if (UMC_OK == umcRes)
        { umcRes = m_DSBuffer.GetPlayPos(dwPlayCursor);   }

        if (UMC_OK == umcRes)
        { umcRes = m_DSBuffer.GetWritePos(dwWriteCursor); }

        if (UMC_OK == umcRes) {

            if (dwPlayCursor <= dwWriteCursor) {
                //  Do not put data up to the Play position itself - leave some space behind it
                if (m_dwSampleAlign <= dwPlayCursor)
                    {  dwPlayCursor -= m_dwSampleAlign;    }

                if (m_DSBuffer.GetNextWriteOffset() >= dwWriteCursor) {
                    umcRes = m_DSBuffer.CopyDataToBuffer(data_ptr, uiLength, dwBytesWrote);
                    if (UMC_OK == umcRes) {
                        VM_ASSERT(uiStartWritePos == 0 || 0 == uiWrapSize);
                        data_ptr += dwBytesWrote;
                        uiLength -= dwBytesWrote;
                        umcRes = m_AudioPtsArray.SetFramePTS(uiStartWritePos,
                                                             in->GetDataSize() - uiLength - uiWrapSize,
                                                             dfStartPTS);
                        if (0 == m_DSBuffer.GetNextWriteOffset()) {
                            uiWrapSize = in->GetDataSize() - uiLength;
                            dfStartPTS = in->GetTime() + uiWrapSize * m_dfNorm;
                            uiStartWritePos = 0;
                        }
                    }
                }

                if ((UMC_OK == umcRes) && (m_DSBuffer.GetNextWriteOffset() < dwPlayCursor) && uiLength) {
                    dwBytesWrote = 0;
                    umcRes = m_DSBuffer.CopyDataToBuffer(data_ptr,
                                                         IPP_MIN(uiLength, dwPlayCursor - m_DSBuffer.GetNextWriteOffset()),
                                                         dwBytesWrote);
                    if (UMC_OK == umcRes) {
                        VM_ASSERT(uiStartWritePos == 0 || 0 == uiWrapSize);
                        data_ptr += dwBytesWrote;
                        uiLength -= dwBytesWrote;
                        umcRes = m_AudioPtsArray.SetFramePTS(uiStartWritePos,
                                                             in->GetDataSize() - uiLength - uiWrapSize, dfStartPTS);
                    }
                }
            } else {
                if ((m_DSBuffer.GetNextWriteOffset() > dwWriteCursor) &&
                    (m_DSBuffer.GetNextWriteOffset() < dwPlayCursor)) {
                    //  Do not put data up to the Play position itself - leave some space behind it
                    if (m_DSBuffer.GetNextWriteOffset() + m_dwSampleAlign <= dwPlayCursor)
                    {   dwPlayCursor -= m_dwSampleAlign;    }

                    umcRes = m_DSBuffer.CopyDataToBuffer(data_ptr,
                                                         IPP_MIN(uiLength, dwPlayCursor - m_DSBuffer.GetNextWriteOffset()),
                                                         dwBytesWrote);
                    if (UMC_OK == umcRes) {
                        VM_ASSERT(uiStartWritePos == 0 || 0 == uiWrapSize);
                        data_ptr += dwBytesWrote;
                        uiLength -= dwBytesWrote;
                        umcRes = m_AudioPtsArray.SetFramePTS(uiStartWritePos,
                                                             in->GetDataSize() - uiLength - uiWrapSize,
                                                             dfStartPTS);
                        if (0 == m_DSBuffer.GetNextWriteOffset()) {
                            uiWrapSize = in->GetDataSize() - uiLength;
                            dfStartPTS = in->GetTime() + uiWrapSize * m_dfNorm;
                            uiStartWritePos = 0;
                        }
                    }
                }
            }
        }
    }
    return umcRes;
}

UMC::Status UMC::DSoundAudioRender::DrainBuffer()
{
    Status umcRes = UMC_OK;
    Ipp32u dwPlayCursor = 0;
    Ipp32u dwPlayCursorLast = 0;
    Ipp32u dwWriteCursor = 0;
    Ipp32u dwStopCursor = m_DSBuffer.GetNextWriteOffset();
    Ipp32s m_Cycle;

    if (UMC_OK == umcRes) {
        umcRes = m_DSBuffer.GetPlayPos(dwPlayCursor);
    }

    if (UMC_OK == umcRes) {
        umcRes = m_DSBuffer.GetWritePos(dwWriteCursor);
    }

    m_Cycle = (dwPlayCursor > dwStopCursor) ? 1 : 0;

    while ((UMC_OK == umcRes) && !((m_Cycle == 0) && (dwPlayCursor > dwStopCursor)) ) {

        if (WAIT_OBJECT_0 != WaitForSingleObject(m_hTimer,INFINITE)) {
            umcRes = UMC_ERR_FAILED;
        }

        if (UMC_OK == umcRes) {
            if (dwPlayCursor <= dwWriteCursor) {

                if (m_dwSampleAlign <= dwPlayCursor) {
                    dwPlayCursor -= m_dwSampleAlign;
                }

                if (m_DSBuffer.GetNextWriteOffset() >= dwWriteCursor) {
                    umcRes = m_DSBuffer.CopyZerosToBuffer(0);
                }

                if ((UMC_OK == umcRes) && (m_DSBuffer.GetNextWriteOffset() < dwPlayCursor)) {
                    umcRes = m_DSBuffer.CopyZerosToBuffer(dwPlayCursor - m_DSBuffer.GetNextWriteOffset());
                }

            } else {
                if ((m_DSBuffer.GetNextWriteOffset() > dwWriteCursor) &&
                    (m_DSBuffer.GetNextWriteOffset() < dwPlayCursor)) {

                    if (dwWriteCursor + m_dwSampleAlign <= dwPlayCursor) {
                        dwPlayCursor -= m_dwSampleAlign;
                    }
                    umcRes = m_DSBuffer.CopyZerosToBuffer(dwPlayCursor - m_DSBuffer.GetNextWriteOffset());
                }
            }
        }

        if (UMC_OK == umcRes) {
            dwPlayCursorLast = dwPlayCursor;
            umcRes = m_DSBuffer.GetPlayPos(dwPlayCursor);
        }

        if (UMC_OK == umcRes) {
            if (dwPlayCursor < dwPlayCursorLast)
                m_Cycle--;
            umcRes = m_DSBuffer.GetWritePos(dwWriteCursor);
        }
    }
    return umcRes;
}

UMC::Status UMC::DSoundAudioRender::Close()
{
    BasicAudioRender::Close();
    m_DSBuffer.Close();
    if (NULL != m_hTimer) {
        CloseHandle(m_hTimer);
        m_hTimer = NULL;
    }
    m_AudioPtsArray.Reset();
    m_dwSampleAlign = 0;
    return UMC_OK;
}

Ipp64f UMC::DSoundAudioRender::GetTimeTick()
{
    Ipp64f pts = 0;
    Ipp32u dwPlayCursor;
    Status umcRes = m_DSBuffer.GetPlayPos(dwPlayCursor);

    if (UMC_OK == umcRes)
    {
        pts = m_AudioPtsArray.GetTime(dwPlayCursor);
        umcRes = BasicAudioRender::GetTimeTick(pts);
        if(UMC_OK == umcRes)
        {
            m_DSBuffer.GetPlayPos(dwPlayCursor);
            pts = m_AudioPtsArray.GetTime(dwPlayCursor);
        }

        if (m_DSBuffer.GetCompensation() <= pts)
        {   pts -= m_DSBuffer.GetCompensation();    }
        else
        {   pts = 0;    }
    }
    else
    {   pts = -1.;  }
    return pts;
}

UMC::Status UMC::DSoundAudioRender::Pause(bool new_value)
{   return m_DSBuffer.Pause(new_value); }

Ipp32f UMC::DSoundAudioRender::SetVolume(Ipp32f volume)
{   return m_DSBuffer.SetVolume(volume);    }

Ipp32f UMC::DSoundAudioRender::GetVolume()
{   return m_DSBuffer.GetVolume();  }

Ipp32u VM_THREAD_CALLCONVENTION BasicAudioRenderThreadProc(void* vpParam);

UMC::Status UMC::DSoundAudioRender::Reset()
{
    UMC::Status ret = BasicAudioRender::Reset();
    m_AudioPtsArray.Reset();
    m_DSBuffer.Reset();
    m_Thread.Wait();

    m_Thread.Create(BasicAudioRenderThreadProc, this);
    return ret;
}

UMC::Status UMC::DSoundAudioRender::SetParams(MediaReceiverParams *pMedia,
                                              Ipp32u  trickModes)
{

    UMC::Status umcRes = UMC::UMC_OK;
    AudioRenderParams* pParams =
        DynamicCast<AudioRenderParams, MediaReceiverParams>(pMedia);
    if (NULL == pParams)
    {   umcRes = UMC_ERR_NULL_PTR;  }

    if (UMC_OK == umcRes)
    {
        sAudioStreamInfo* info = NULL;
        info = &pParams->info;

        if((info->channels         != m_wInitedChannels) ||
           (info->sample_frequency != m_dwInitedFrequency))
        {
            umcRes = m_DSBuffer.DynamicSetParams((Ipp16u)info->channels,
                                                 info->sample_frequency,
                                                 (Ipp16u)(info->bitPerSample >> 3));
            if(UMC_OK == umcRes)
            {
                 umcRes = BasicAudioRender::SetParams(pMedia, trickModes);
                 m_AudioPtsArray.DynamicSetParams(m_dfNorm);
            }
        }
        else
        {
             umcRes = UMC_ERR_FAILED;
        }
    }
    return umcRes;
}

#endif  // UMC_ENABLE_DSOUND_AUDIO_RENDER

⌨️ 快捷键说明

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