📄 rvorbis.cpp
字号:
ogg_int64_t den = m_audioFmt.ulSamplesPerSec; ogg_int64_t q = m_totalSamples / den; ogg_int64_t r = m_totalSamples - q * den; return (UINT32)(q * 1000 + (r * 1000) / den);}UINT32 CVorbisRenderer::BytesToMs(UINT32 ulNumBytes){ UINT32 q = ulNumBytes / m_ulBytesPerSec; UINT32 r = ulNumBytes - q * m_ulBytesPerSec; return q * 1000 + (r * 1000) / m_ulBytesPerSec;}UINT32 CVorbisRenderer::MsToBytes(UINT32 ulMs){ UINT32 q = ulMs / 1000; UINT32 r = ulMs - q * 1000; return q * m_ulBytesPerSec + (r * m_ulBytesPerSec) / 1000;}STDMETHODIMP CVorbisRenderer::OnDryNotification(UINT32 ulCurrentStreamTime, UINT32 ulMinimumDurationRequired){ HX_RESULT res = HXR_UNEXPECTED; DPRINTF(D_VORBIS,("OnDryNotification(%u %u)\n", ulCurrentStreamTime, ulMinimumDurationRequired)); if (VorbisPlay != m_VorbisState) { res = HXR_OK; } else if (m_pDepack) { BOOL bDone = FALSE; UINT32 ulEndTime = ulCurrentStreamTime + ulMinimumDurationRequired; BOOL bWroteData = FALSE; UINT32 ulLastWriteTime = 0; BOOL bAudioParamsChanged = FALSE; BOOL bEOS = FALSE; while (!bDone) { ogg_packet* pPkt = NULL; HX_RESULT err = m_pDepack->GetVorbisPacket(pPkt); if (HXR_OK == err) { if (pPkt->b_o_s) { gotoInitialHeaderState(); } else if (pPkt->e_o_s) { bEOS = TRUE; } else { HX_ASSERT(!bEOS); } switch (m_VorbisState) { case VorbisInitialHeader: res = handleInitialHeader(pPkt); bEOS = FALSE; break; case VorbisCommentHeader: if (vorbis_synthesis_headerin(&m_vi, &m_vc, pPkt) >= 0) { DPRINTF(D_VORBIS,("Got Comment Header\n")); updateTACInfo(&m_vc); m_VorbisState = VorbisCodebookHeader; } break; case VorbisCodebookHeader: vorbis_synthesis_headerin(&m_vi, &m_vc, pPkt); vorbis_synthesis_init(&m_vd, &m_vi); vorbis_block_init(&m_vd, &m_vb); m_VorbisState = VorbisPlay; DPRINTF(D_VORBIS,("Got Codebooks\n")); break; case VorbisPlay: DPRINTF(D_VORBIS,("calling DecodeAndRender\n")); ulLastWriteTime = DecodeAndRender(pPkt); bWroteData = TRUE; bDone = IsTimeGreaterOrEqual(ulLastWriteTime,ulEndTime); break; default: HX_ASSERT(!"Unexpected state!"); bDone = TRUE; break; }; _ogg_free(pPkt); } else { bDone = TRUE; } } if (!bWroteData || IsTimeLess(ulLastWriteTime, ulEndTime) && !IsRebuffering() && !bEOS) { /* We ran out of data and we didn't satisfy what * is needed. Initiate a rebuffer so we get more * packets */ StartRebuffer(); } else if (bWroteData && IsTimeGreaterOrEqual(ulLastWriteTime,ulEndTime) && IsRebuffering()) { /* We wrote data, satisfied what was needed and * were rebuffering. Time to end the rebuffer. */ EndRebuffer(); } if (bEOS) { /* We don't have any more data and we've seen an * end of stream packet. This could be the start * of a video only stream group. Disable ODN * calls for now so we don't rebuffer and * transition to the VorbisInitialHeader state so * that we are ready for the next stream and so * OnPacket will process the packets. */ m_pCurrentStream->SetDryNotification(NULL); gotoInitialHeaderState(); } DPRINTF(D_VORBIS,("needed %ldms sent %ldms...\n", ulMinimumDurationRequired, (bWroteData) ? (ulLastWriteTime - ulCurrentStreamTime) : 0)); res = HXR_OK; } DPRINTF(D_VORBIS,("OnDryNotification() : res %08x\n", res)); return res;}STDMETHODIMP CVorbisRenderer::OnTimeSync(UINT32 currentPlayBackTime){ DPRINTF(D_VORBIS,("OnTimeSync(%u)\n", currentPlayBackTime)); return HXR_OK;}STDMETHODIMP CVorbisRenderer::OnPreSeek(UINT32 timeBeforeSeek, UINT32 timeAfterSeek){ DPRINTF(D_VORBIS,("OnPreSeek(%u, %u)\n", timeBeforeSeek, timeAfterSeek)); m_bInSeekMode = TRUE; return HXR_OK;}STDMETHODIMP CVorbisRenderer::OnPostSeek(UINT32 timeBeforeSeek, UINT32 timeAfterSeek){ DPRINTF(D_VORBIS,("OnPostSeek(%u, %u)\n", timeBeforeSeek, timeAfterSeek)); m_bInSeekMode = FALSE; m_bIsFirstPacket = TRUE; if (m_pDepack) { m_pDepack->Reset(); } return HXR_OK;}STDMETHODIMP CVorbisRenderer::OnPause(UINT32 timeBeforePause){ DPRINTF(D_VORBIS,("CVorbisRenderer::OnPause(%u)\n", timeBeforePause)); return HXR_OK;}STDMETHODIMP CVorbisRenderer::OnBuffering(UINT32 reason, UINT16 percentComplete){ return HXR_OK;}STDMETHODIMP CVorbisRenderer::OnEndofPackets(void){ DPRINTF(D_VORBIS,("CVorbisRenderer::OnEndofPackets()\n")); if (m_pDepack) { m_pDepack->EndOfStream(); } m_bEndOfPackets = TRUE; if (IsRebuffering()) { EndRebuffer(); } return HXR_OK;}STDMETHODIMP CVorbisRenderer::EndStream(void){ DPRINTF(D_VORBIS,("CVorbisRenderer::EndStream()\n")); Shutdown(); return HXR_OK;}CVorbisRenderer::~CVorbisRenderer(void){ Shutdown();}STDMETHODIMP_(UINT32) CVorbisRenderer::AddRef(void){ return InterlockedIncrement(&m_RefCount);}STDMETHODIMP_(UINT32) CVorbisRenderer::Release(void){ if (InterlockedDecrement(&m_RefCount) > 0) return m_RefCount; delete this; return 0;}STDMETHODIMP CVorbisRenderer::QueryInterface(REFIID interfaceID, void **ppInterfaceObj){ if (IsEqualIID(interfaceID, IID_IUnknown)) { AddRef(); *ppInterfaceObj = (IUnknown *)(IHXPlugin *)this; return HXR_OK; } else if (IsEqualIID(interfaceID, IID_IHXPlugin)) { AddRef(); *ppInterfaceObj = (IHXPlugin *)this; return HXR_OK; } else if (IsEqualIID(interfaceID, IID_IHXRenderer)) { AddRef(); *ppInterfaceObj = (IHXRenderer *)this; return HXR_OK; } *ppInterfaceObj = NULL; return HXR_NOINTERFACE;}HX_RESULT CVorbisRenderer::InitAudioStream(UINT32 ulSampleRate, UINT16 usChannels){ HX_RESULT res = HXR_OK; DPRINTF(D_VORBIS,("InitAudioStream(%u, %u)\n", ulSampleRate, usChannels)); UINT32 uCurrentSampleRate = 0; UINT32 uCurrentChannels = 0; if (m_pCurrentStream) { res = m_pCurrentStream->GetStreamInfo(uCurrentSampleRate, uCurrentChannels); m_pCurrentStream->SetDryNotification(NULL); m_pCurrentStream = NULL; } if ((uCurrentSampleRate != ulSampleRate) && m_totalSamples && uCurrentSampleRate) { ogg_int64_t q = m_totalSamples / uCurrentSampleRate; ogg_int64_t r = m_totalSamples - q * uCurrentSampleRate; m_totalSamples = q * ulSampleRate + (r * ulSampleRate) / uCurrentSampleRate; } m_audioFmt.ulSamplesPerSec = ulSampleRate; m_audioFmt.uChannels = usChannels; m_audioFmt.uBitsPerSample = 16; m_audioFmt.ulSamplesPerSec = ulSampleRate; m_audioFmt.uMaxBlockSize = 4096; m_ulBytesPerSec = (m_audioFmt.uChannels * (m_audioFmt.uBitsPerSample / 8) * m_audioFmt.ulSamplesPerSec); m_pCurrentStream = findAudioStream(m_audioFmt.ulSamplesPerSec, m_audioFmt.uChannels); if (m_pCurrentStream) { m_pCurrentStream->SetDryNotification(this); } else { res = HXR_UNEXPECTED; } return res;}COggAudioStreamHelper* CVorbisRenderer::findAudioStream(UINT32 ulSampleRate, UINT16 usChannels){ COggAudioStreamHelper* pRet = NULL; CHXSimpleList::Iterator itr = m_audioStreams.Begin(); for (;!pRet && (itr != m_audioStreams.End()); ++itr) { COggAudioStreamHelper* pHlpr = (COggAudioStreamHelper*)*itr; UINT32 uSampRate; UINT32 uChannels; if ((HXR_OK == pHlpr->GetStreamInfo(uSampRate, uChannels)) && (uSampRate == ulSampleRate) && (usChannels == uChannels)) { pRet = pHlpr; pRet->AddRef(); } } if (!pRet) { IHXAudioStream* pAudioStream = NULL; HX_RESULT res = m_pAudioPlayer->CreateAudioStream(&pAudioStream); if (HXR_OK == res) { pRet = new COggAudioStreamHelper; if (pRet) { pRet->AddRef(); // For return value res = pRet->Init(pAudioStream); if (HXR_OK == res) { if (m_audioStreams.AddTail(pRet)) { pRet->AddRef(); // For list res = pAudioStream->Init(&m_audioFmt, m_pStreamHeaderObj); if (HXR_OK != res) { pRet->Release(); // For list m_audioStreams.RemoveTail(); } } else { res = HXR_OUTOFMEMORY; } } if (HXR_OK != res) { HX_RELEASE(pRet); // For return value } } } HX_RELEASE(pAudioStream); } return pRet;}UINT32 CVorbisRenderer::DecodeAndRender(ogg_packet* pOp){ UINT32 ulLastWriteTime = 0; // we have a packet to decode float **pcm; int samples; int convsize = m_audioFmt.uMaxBlockSize / m_vi.channels; if (vorbis_synthesis(&m_vb, pOp) == 0) vorbis_synthesis_blockin(&m_vd, &m_vb); else { DPRINTF(D_VORBIS,("ERROR ? HMMMMMMM\n")); } UINT32 ulAudioTime = CurrentTime(); while ((samples = vorbis_synthesis_pcmout(&m_vd, &pcm)) > 0) { int i, j; int clipflag = 0; int bout = (samples < convsize ? samples : convsize); int audioByteCt = bout * m_vi.channels * 2; HXAudioData audioData; audioData.pData = NULL; audioData.ulAudioTime = ulAudioTime; if ((HXR_OK == m_pClassFactory->CreateInstance(CLSID_IHXBuffer, (void **)&audioData.pData)) && (HXR_OK == audioData.pData->SetSize(audioByteCt))) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -