📄 winmm_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"#if defined (UMC_ENABLE_WINMM_AUDIO_RENDER)#include "winmm_render.h"void CALLBACK waveOutProc( HWAVEOUT /*m_hWO*/, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR /*dwParam1*/, DWORD /*dwParam2*/){ UMC::WinMMAudioRender* pRender = (UMC::WinMMAudioRender*) dwInstance; switch(uMsg) { case WOM_OPEN: break; case WOM_DONE: pRender->Release(); break; case WOM_CLOSE: break; default: break; }}UMC::WinMMAudioRender::BufArray::BufArray(): m_uiBufSize(0), m_uiHdrNum(BUF_NUM_MAX){ memset(m_pArray, 0, sizeof(WAVEHDR) * m_uiHdrNum); }UMC::WinMMAudioRender::BufArray::~BufArray(){ for (vm_var32 i = 0; i < m_uiHdrNum; i++) { if (m_pArray[i].lpData) { delete(m_pArray[i].lpData); } m_pArray[i].lpData = NULL; }}UMC::StatusUMC::WinMMAudioRender::BufArray::Init(vm_var32 uiBufSize){ Status umcRes = UMC_OK; m_uiBufSize = uiBufSize; for (vm_var32 i = 0; UMC_OK == umcRes && i < m_uiHdrNum; i++) { if (m_pArray[i].lpData) { delete(m_pArray[i].lpData); } memset(&m_pArray[i], 0, sizeof(WAVEHDR)); m_pArray[i].lpData = new char[BUF_SIZE]; if (NULL == m_pArray[i].lpData) { umcRes = UMC_ALLOC; } m_pArray[i].dwBufferLength = m_uiBufSize; memset(m_pArray[i].lpData, 0, m_uiBufSize); } return umcRes;}voidUMC::WinMMAudioRender::BufArray::ZeroBuffers(){ for (vm_var32 i = 0; i < m_uiHdrNum; i++) { if (m_pArray[i].lpData) { memset(m_pArray[i].lpData, 0, m_uiBufSize); } }}UMC::WinMMAudioRender::WinMMAudioRender(): m_hWO(NULL), m_sm_free_buffers(0), m_dfStartPTS(-1.0), m_dfSampleNorm(1.0){}UMC::StatusUMC::WinMMAudioRender::Reset(){ Status umcRes = UMC_OK; if (m_hWO) { Release(); waveOutClose(m_hWO); m_hWO = NULL; } if (m_sm_free_buffers) { m_sm_free_buffers = NULL; CloseHandle(m_sm_free_buffers); } // all buffers free if (UMC_OK == umcRes) { assert(NULL == m_sm_free_buffers); m_sm_free_buffers = CreateSemaphore( NULL, BUF_NUM_MAX, BUF_NUM_MAX, NULL ); if (NULL == m_sm_free_buffers) { umcRes = UMC_OPERATION_FAILED; } } m_Hdrs.ZeroBuffers(); if (UMC_OK == umcRes && MMSYSERR_NOERROR != waveOutOpen(&m_hWO, WAVE_MAPPER, &m_WaveFmtX, (DWORD_PTR) waveOutProc, (DWORD_PTR) this, CALLBACK_FUNCTION)) { umcRes = UMC_OPERATION_FAILED; } if (UMC_OK == umcRes) { DWORD wdVolume = m_dwVolume | (m_dwVolume << 16); if (MMSYSERR_NOERROR != waveOutSetVolume(m_hWO, wdVolume)) { umcRes = UMC_OPERATION_FAILED; } m_dfStartPTS = -1.0; m_iFreeBuf = BUF_NUM_MAX - 1; m_iDoneBuf = 0; m_iOffset = -1; } if (UMC_OK == umcRes) { umcRes = BasicAudioRender::Reset(); } return umcRes;}UMC::StatusUMC::WinMMAudioRender::Close(){ if (m_hWO) { Release(); waveOutClose(m_hWO); m_hWO = NULL; } if (m_sm_free_buffers) { CloseHandle(m_sm_free_buffers); } m_sm_free_buffers = NULL; return BasicAudioRender::Close();}UMC::WinMMAudioRender::~WinMMAudioRender(){ Close(); }UMC::StatusUMC::WinMMAudioRender::Init(MediaReceiverParams* pInit){ Status umcRes = UMC_OK; AudioRenderParams* pParams = DynamicCast<AudioRenderParams, MediaReceiverParams>(pInit); if (NULL == pParams) { umcRes = UMC_NULL_PTR; } sAudioStreamInfo *pASInfo = NULL; if (UMC_OK == umcRes) { pASInfo = &pParams->info; Close(); umcRes = m_Hdrs.Init(BUF_SIZE); } if (UMC_OK == umcRes) { umcRes = BasicAudioRender::Init(pInit); } if (UMC_OK == umcRes) { // prepare waveout m_WaveFmtX.wFormatTag = (WORD)WAVE_FORMAT_PCM; m_WaveFmtX.nChannels = (WORD)pASInfo->channels; m_WaveFmtX.nSamplesPerSec = pASInfo->sample_frequency; m_WaveFmtX.wBitsPerSample = (unsigned short)pASInfo->bitPerSample; m_WaveFmtX.nBlockAlign = (WORD)((m_WaveFmtX.wBitsPerSample * m_WaveFmtX.nChannels) >> 3); m_WaveFmtX.nAvgBytesPerSec = pASInfo->sample_frequency * m_WaveFmtX.nBlockAlign; m_WaveFmtX.cbSize = 0; m_dfStartPTS = -1.0; m_dwVolume = 0xffffffff; m_dfSampleNorm = 1.0 / pASInfo->sample_frequency; umcRes = Reset(); } return umcRes;}voidUMC::WinMMAudioRender::Release(){ if (m_hWO && m_sm_free_buffers) { waveOutUnprepareHeader(m_hWO, &m_Hdrs.m_pArray[m_iDoneBuf], sizeof(WAVEHDR)); ReleaseSemaphore(m_sm_free_buffers, 1, NULL); if (BUF_NUM_MAX == ++m_iDoneBuf) { m_iDoneBuf = 0; } }}UMC::StatusUMC::WinMMAudioRender::UnLockInputBuffer(MediaData *in, Status StreamStatus){ Status umcRes = BasicAudioRender::UnLockInputBuffer(in,StreamStatus); if (UMC_OK == umcRes && m_dfStartPTS == -1.0) m_dfStartPTS = in->GetTime(); return umcRes;}UMC::StatusUMC::WinMMAudioRender::SendFrame(MediaData* pInData){ Status umcRes = UMC_OK; vm_var32 uiBufSize = BUF_SIZE; MMRESULT res; vm_var32 uiBytes = 0; vm_byte* pbBuffer = NULL; if (NULL == pInData) { umcRes = UMC_NULL_PTR; } if (UMC_OK == umcRes) { uiBytes = pInData->GetDataSize(); pbBuffer = (vm_byte*)pInData->GetDataPointer(); // Init start PTS if it's first processed frame if (-1.0 == m_dfStartPTS) { double dfEndPts = 0.0; pInData->GetTime(m_dfStartPTS, dfEndPts); } } while (UMC_OK == umcRes && 0 < uiBytes) { if (-1 == m_iOffset) { WaitForSingleObject(m_sm_free_buffers, INFINITE); if (++m_iFreeBuf == BUF_NUM_MAX) { m_iFreeBuf = 0; } m_iOffset = 0; } WAVEHDR *pHdr = &m_Hdrs.m_pArray[m_iFreeBuf]; if (uiBufSize - m_iOffset > uiBytes) { memcpy(pHdr->lpData + m_iOffset, pbBuffer, uiBytes ); m_iOffset += uiBytes; uiBytes = 0; } else { memcpy(pHdr->lpData + m_iOffset, pbBuffer, uiBufSize - m_iOffset); uiBytes -= uiBufSize - m_iOffset; pbBuffer += (uiBufSize - m_iOffset); m_iOffset = -1; } if (-1 == m_iOffset) { res = waveOutPrepareHeader(m_hWO, pHdr, sizeof(WAVEHDR)); if (MMSYSERR_NOERROR == res) { res = waveOutWrite(m_hWO, pHdr, sizeof(WAVEHDR)); } if (MMSYSERR_NOERROR != res) { umcRes = UMC_OPERATION_FAILED; } } } return umcRes;}UMC::StatusUMC::WinMMAudioRender::Pause(bool bPause){ MMRESULT mmRes = MMSYSERR_NOERROR; if (m_hWO ) { if (bPause) { mmRes = waveOutPause(m_hWO); } else { mmRes = waveOutRestart(m_hWO); } } return (MMSYSERR_NOERROR == mmRes) ? UMC_OK : UMC_OPERATION_FAILED;}doubleUMC::WinMMAudioRender::GetTimeTick(){ if (m_hWO || -1.0 != m_dfStartPTS) { MMTIME wotime; wotime.wType = TIME_SAMPLES; wotime.u.sample = 0; if (MMSYSERR_NOERROR == waveOutGetPosition(m_hWO, &wotime, sizeof(wotime))) { return m_dfStartPTS + wotime.u.sample * m_dfSampleNorm; } } return 0;}#endif // UMC_ENABLE_WINMM_AUDIO_RENDER
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -