📄 directsound_render.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-2005 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 unsigned int UMC::DSoundAudioRender::m_cuiSizeOfFrame = 6144;const unsigned int UMC::DSoundAudioRender::m_cuiNumOfFrames = 10;UMC::DSoundAudioRender::DSoundAudioRender(): m_hTimer(NULL), m_dwSampleAlign(0){}UMC::DSoundAudioRender::~DSoundAudioRender(void){ Close(); }UMC::StatusUMC::DSoundAudioRender::Init(MediaReceiverParams* pInit){ Status umcRes = UMC_OK; AudioRenderParams* pParams = DynamicCast<AudioRenderParams, MediaReceiverParams>(pInit); if (NULL == pParams) { umcRes = UMC_NULL_PTR; } if (UMC_OK == umcRes) { umcRes = BasicAudioRender::Init(pInit); } HWNDModuleContext* pHWNDContext = NULL; if (UMC_OK == umcRes) { pHWNDContext = DynamicCast<HWNDModuleContext,ModuleContext>(pParams->pModuleContext); if (NULL == pHWNDContext) { umcRes = UMC_FAILED_TO_INITIALIZE; } } sAudioStreamInfo* info = NULL; int iLength = 0; DWORD dwBufferSize = 0; if (UMC_OK == umcRes) { info = &pParams->info; int 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, (WORD)info->channels, info->sample_frequency, (WORD)(info->bitPerSample >> 3)); } if (UMC_OK == umcRes && NULL == m_hTimer) { m_hTimer = CreateWaitableTimer(0,false,0); if (NULL == m_hTimer) { umcRes = UMC_OPERATION_FAILED; } } 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_OPERATION_FAILED; } } if (UMC_OK == umcRes) { umcRes = m_AudioPtsArray.Init(m_cuiNumOfFrames, m_dfNorm); } return umcRes;}UMC::StatusUMC::DSoundAudioRender::SendFrame(MediaData* in){ Status umcRes = UMC_OK; assert(NULL != in); if (!in) { umcRes = UMC_NULL_PTR; } if (UMC_OK == umcRes && NULL == in->GetDataPointer()) { umcRes = UMC_NULL_PTR; } vm_var32 uiLength = in->GetDataSize(); vm_var32 uiStartWritePos = m_DSBuffer.GetNextWriteOffset(); vm_var32 uiWrapSize = 0; double dfStartPTS = in->GetTime(); if (UMC_OK == umcRes) { umcRes = m_AudioPtsArray.SetFramePTS(m_DSBuffer.GetNextWriteOffset(), 0, in->GetTime()); } for (unsigned char *data_ptr = (unsigned char *) in->GetDataPointer(); UMC_OK == umcRes && 0 != uiLength && !m_bStop && !m_bPrepareForReposition; /*Sleep(0)*/) { DWORD dwPlayCursor = 0; DWORD dwWriteCursor = 0; DWORD dwBytesWrote = 0; if (WAIT_OBJECT_0 != WaitForSingleObject(m_hTimer,INFINITE)) { umcRes = UMC_OPERATION_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) { 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, min(uiLength,dwPlayCursor - m_DSBuffer.GetNextWriteOffset()), dwBytesWrote); if (UMC_OK == umcRes) { 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, min(uiLength, dwPlayCursor - m_DSBuffer.GetNextWriteOffset()), dwBytesWrote); if (UMC_OK == umcRes) { assert(uiStartWritePos == 0 || 0 == uiWrapSize);// assert(uiStartWritePos + in->GetDataSize() - uiLength - uiWrapSize <= m_dwDSBufferSize); 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; } } } }// vm_debug_trace(-1,"CopyData: frame start %f/entry start %f; pos %d:len %d: wrap %d\n",// in->GetTime(),// dfStartPTS,// uiStartWritePos,// in->GetDataSize() - uiLength - uiWrapSize,// uiWrapSize); } return umcRes;}UMC::StatusUMC::DSoundAudioRender::Close(){ m_DSBuffer.Close(); if (NULL != m_hTimer) { CloseHandle(m_hTimer); m_hTimer = NULL; } m_DSBuffer.Close(); m_AudioPtsArray.Reset(); m_dwSampleAlign = 0; return BasicAudioRender::Close();}doubleUMC::DSoundAudioRender::GetTimeTick(){ double pts = 0; DWORD 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::StatusUMC::DSoundAudioRender::Pause(bool new_value){ return m_DSBuffer.Pause(new_value); }floatUMC::DSoundAudioRender::SetVolume(float volume){ return m_DSBuffer.SetVolume(volume); }floatUMC::DSoundAudioRender::GetVolume(){ return m_DSBuffer.GetVolume(); }unsigned intBasicAudioRenderThreadProc(void* vpParam);UMC::StatusUMC::DSoundAudioRender::Reset(){ UMC::Status ret = BasicAudioRender::Reset(); m_AudioPtsArray.Reset(); m_DSBuffer.Reset(); m_Thread.Wait(); m_bPrepareForReposition = false; m_Thread.Create(BasicAudioRenderThreadProc, this); return ret;}UMC::StatusUMC::DSoundAudioRender::SetParams(MediaReceiverParams *pMedia){ UMC::Status umcRes = UMC::UMC_OK; AudioRenderParams* pParams = DynamicCast<AudioRenderParams, MediaReceiverParams>(pMedia); if (NULL == pParams) { umcRes = UMC_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((WORD)info->channels, info->sample_frequency, (WORD)(info->bitPerSample >> 3)); if(UMC_OK == umcRes) { umcRes = BasicAudioRender::SetParams(pMedia); m_AudioPtsArray.DynamicSetParams(m_dfNorm); } } else { umcRes = UMC_OPERATION_FAILED; } } return umcRes;}#endif // UMC_ENABLE_DSOUND_AUDIO_RENDER
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -