📄 hxaudses.cpp
字号:
HXAudioData audioData; CHXAudioPlayer* pPlayer = 0; CHXAudioStream* pStream = 0; CHXSimpleList* pStreamList = 0;#if defined(HELIX_FEATURE_VOLUME) || defined(HELIX_FEATURE_MIXER) UINT16 uPlayerVolume = HX_INIT_VOLUME;#endif UCHAR* pMixBuffer = 0; UCHAR* pPlayerBuf = NULL; UCHAR* pSessionBuf = NULL; IHXBuffer* pMixIHXBuffer = NULL; BufType bufType = BUFFER_NONE; for (UINT16 i = 0; !theErr && i < uPush; i++ ) { m_uNumToBePushed = uPush - i; m_bSessionBufferDirty = FALSE; // only used for multi-player case UINT32 ulNumBytesWritten = m_ulBytesPerGran; BOOL bAtLeastOnePlayerActive = FALSE; theErr = m_pSessionBuf->SetSize(m_ulBytesPerGran); if( theErr == HXR_OUTOFMEMORY ) { theErr = HXR_OUTOFMEMORY; goto exit; } pSessionBuf = m_pSessionBuf->GetBuffer(); // Zero session buffer. //memset(pSessionBuf, 0, HX_SAFESIZE_T(m_ulBytesPerGran)); // Get each player pPlayer = 0; CHXSimpleList::Iterator lIter = m_pPlayerList->Begin(); for (; lIter != m_pPlayerList->End(); ++lIter) { BOOL bStalled = FALSE; pPlayer = (CHXAudioPlayer*) (*lIter); if (pPlayer->GetStreamCount() == 0 || pPlayer->IsDonePlayback() || pPlayer->GetState() != E_PLAYING) { continue; } bAtLeastOnePlayerActive = TRUE; if (m_pPlayerList->GetCount() == 1) { pMixIHXBuffer = m_pSessionBuf; bufType = BUFFER_SESSION; } else { if (!m_pPlayerBuf) { m_pPlayerBuf = new CHXBuffer; m_pPlayerBuf->AddRef(); } m_pPlayerBuf->SetSize(m_ulBytesPerGran); pPlayerBuf = m_pPlayerBuf->GetBuffer(); // Zero play buffer.// memset(pPlayerBuf, 0, HX_SAFESIZE_T(m_ulBytesPerGran)); pMixIHXBuffer = m_pPlayerBuf; bufType = BUFFER_PLAYER; } pMixBuffer = pMixIHXBuffer->GetBuffer(); BOOL bIsMixBufferDirty = FALSE; BOOL bMayNeedToRollbackTimestamp = FALSE; if (pPlayer->GetState() == E_PLAYING) { UINT32 ulBufTime = 0; // Get each stream associated with this player pStreamList = pPlayer->GetStreamList(); if (pStreamList) { CHXSimpleList::Iterator lIter = pStreamList->Begin(); for (; lIter != pStreamList->End(); ++lIter) { pStream = (CHXAudioStream*) (*lIter); pStream->m_bMayNeedToRollbackTimestamp = FALSE; // don't mix paused audio streams if (pStream->GetState() != E_PAUSED) { theErr = pStream->MixIntoBuffer( pMixBuffer, m_ulBytesPerGran, ulBufTime, bIsMixBufferDirty); // so as not to trigger ReallyNeedData // since one of the streams internal m_llLastwritetime // has been updated even though this flag is set to FALSE.#if 0 if (!bIsMixBufferDirty && (theErr == HXR_OK || theErr == HXR_NO_DATA)) { bIsMixBufferDirty = TRUE; ::memset(pMixBuffer, 0, HX_SAFESIZE_T(m_ulBytesPerGran)); }#endif if (theErr == HXR_NO_DATA) { pStream->m_bMayNeedToRollbackTimestamp = TRUE; bMayNeedToRollbackTimestamp = TRUE; theErr = HXR_OK; continue; } if (theErr == HXR_FAIL) { theErr = HXR_OK; goto exit; } if (theErr == HXR_OUTOFMEMORY) { goto exit; } if (theErr == HXR_WOULD_BLOCK) {#ifdef _RAHULDEBUG { char str[255]; /* Flawfinder: ignore */ ::sprintf(str, "Num to be pushed remaining: %lu\n", m_uNumToBePushed); /* Flawfinder: ignore */ OutputDebugString(str); }#endif if (bMayNeedToRollbackTimestamp) { bMayNeedToRollbackTimestamp = FALSE; lIter = pStreamList->Begin(); for (; lIter != pStreamList->End(); ++lIter) { pStream = (CHXAudioStream*) (*lIter); if (pStream->m_bMayNeedToRollbackTimestamp) { pStream->m_bMayNeedToRollbackTimestamp = FALSE; pStream->RollBackTimestamp(); } } } goto handlewouldblock; } } if (pPlayer->GetState() != E_PLAYING) { /* We should keep the last buffer around and the last stream * to be mixed again...TBD XXX Rahul */ //pPlayer->SetLastMixedBuffer(pMixBuffer, pStream); bStalled = TRUE; break; } } } //if (pStreamList) /* This pause may have happended due to ondrynotification */ if (m_bPaused || m_bStoppedDuringPause) { /* This would happen ONLY IF THERE IS ONE AUDIO PLAYER * and that has been paused. So simply break */ goto exit; //break; } /* hmmm... looks like there are more than one audio player. * continue with the next one */ if (bStalled) { continue; } /* If the mixer buffer was not used, make sure it is initialized * to silence since we pass it to post process hooks */ if (!bIsMixBufferDirty) {//{FILE* f1 = ::fopen("e:\\audioses.txt", "a+"); ::fprintf(f1, "%lu\t%p\tsilence in mix buffer\n", HX_GET_BETTERTICKCOUNT(), this);::fclose(f1);} ::memset(pMixBuffer, 0, HX_SAFESIZE_T(m_ulBytesPerGran)); }#if defined(HELIX_FEATURE_VOLUME) && defined(HELIX_FEATURE_MIXER) // Apply Player volume to buffer; do this before we call // the post mix hooks. uPlayerVolume = pPlayer->GetVolume(); if (uPlayerVolume != 100 && bIsMixBufferDirty) { CHXMixer::ApplyVolume(pMixBuffer, m_ulBytesPerGran, uPlayerVolume, m_DeviceFmt.uBitsPerSample); }#endif /* HELIX_FEATURE_VOLUME && HELIX_FEATURE_MIXER */ // Give data to this AudioPlayer's post mix hooks // (do they want 8 or 16 bit?) BOOL bChanged = FALSE; ProcessPostMixHooks(pPlayer, pMixIHXBuffer, &bDisableWrite, ulBufTime, bChanged); /* * If the mixer buffer changed (because of a post mix hook) * make sure to point the player/session buffer to this * modified buffer */ if (bChanged) { pMixBuffer = pMixIHXBuffer->GetBuffer(); if (bufType == BUFFER_PLAYER) { m_pPlayerBuf = pMixIHXBuffer; pPlayerBuf = pMixIHXBuffer->GetBuffer(); } else { m_pSessionBuf = pMixIHXBuffer; pSessionBuf = pMixIHXBuffer->GetBuffer(); } } }#if defined(HELIX_FEATURE_MIXER) // Don't mix if volume is 0. // Don't mix if this player has disabled device write. // Don't mix if there is only one player since we would have // written data into session buf instead of player buffer if (m_pPlayerList->GetCount() > 1 && uPlayerVolume > 0 && !bDisableWrite) { /* We always set a volume of 100 since we have already applied volume * to player buffer */ CHXMixer::MixBuffer( pPlayerBuf, pSessionBuf, m_ulBytesPerGran, FALSE, 100, m_DeviceFmt.uBitsPerSample, m_bSessionBufferDirty); }#endif /* HELIX_FEATURE_MIXER */ pPlayer->UpdateLastWriteTime(m_ulGranularity); } if (!bAtLeastOnePlayerActive) { goto exit; } /* did we ever write to the session buffer ? */ if (m_pPlayerList->GetCount() > 1 && !m_bSessionBufferDirty) {//{FILE* f1 = ::fopen("e:\\audioses.txt", "a+"); ::fprintf(f1, "%lu\t%p\tsilence in session buffer\n", HX_GET_BETTERTICKCOUNT(), this);::fclose(f1);} ::memset(pSessionBuf, 0, HX_SAFESIZE_T(m_ulBytesPerGran)); } // This increments with each buffered played. m_dBufEndTime += m_dGranularity; // Set the session buffer to the IRMA buffer. audioData.pData = m_pSessionBuf; audioData.ulAudioTime = (ULONG32)m_dBufEndTime; if (m_pAudioDev && !m_bDisableWrite) { /* are we dealing with a f*%$'ed up sound card */ if ((m_BeforeHookDeviceFmt.uChannels == 1 && m_DeviceFmt.uChannels == 2)|| m_BeforeHookDeviceFmt.uBitsPerSample == 8) { ConvertTo8BitAndOrMono(&audioData); } if (m_pFinalHook && m_bUseFinalHook) { if (HXR_OK == ProcessAudioHook(ACTION_CHECK, m_pFinalHook)) { m_pOutDataPtr->pData = NULL; m_pOutDataPtr->ulAudioTime = audioData.ulAudioTime; m_pOutDataPtr->uAudioStreamType = audioData.uAudioStreamType; m_pFinalHook->OnBuffer(&audioData, m_pOutDataPtr); HX_ASSERT(m_pOutDataPtr->pData); if (m_pOutDataPtr->pData) { HX_RELEASE(audioData.pData); m_pSessionBuf = audioData.pData = m_pOutDataPtr->pData; } else { /* This is a screwed up Hook. Disable it */ m_bUseFinalHook = FALSE; } } } if (m_pHookList) { ProcessHooks(&audioData); } ulNumBytesWritten = audioData.pData->GetSize(); if (HXR_OK == ProcessAudioDevice(ACTION_CHECK, m_pAudioDev)) { // Write session audio data to device. theErr = m_pAudioDev->Write(&audioData); if( theErr == HXR_OUTOFMEMORY ) { goto exit; } } if (theErr == HXR_WOULD_BLOCK) { HXAudioData* pAudioData = new HXAudioData; pAudioData->pData = audioData.pData; pAudioData->pData->AddRef(); pAudioData->ulAudioTime = audioData.ulAudioTime; pAudioData->uAudioStreamType= audioData.uAudioStreamType; // Create auxiliary buffer list, if one is not already created if (!m_pAuxiliaryAudioBuffers) { m_pAuxiliaryAudioBuffers = new CHXSimpleList; } if( NULL == m_pAuxiliaryAudioBuffers->AddTail(pAudioData) ) { theErr = HXR_OUTOFMEMORY; goto exit; } HX_RELEASE(m_pSessionBuf); } /* Any error from audio device other than memory error is * returned as HXR_AUDIO_DRIVER */ if (theErr != HXR_OK && theErr != HXR_WOULD_BLOCK && theErr != HXR_OUTOFMEMORY) { theErr = HXR_AUDIO_DRIVER; } } if (!theErr) { m_ulBlocksWritten++; m_dNumBytesWritten += ulNumBytesWritten; } // So this function is good in theory, but in practice we find in // heap-optimized mode it is not necessary, and it leads to // unnecessary heap fragmentation.#if !defined(HELIX_CONFIG_MIN_HEAP_FRAG) theErr = CheckForBufferReuse();#endif } // for loop } // end if we have audio streamshandlewouldblock: // mask this error if (theErr == HXR_WOULD_BLOCK) { theErr = HXR_OK; } // If we do not have audio.. OR if we do have audio but // we have disabled writing to the device, then we need to // fake the timeline. if (!theErr && !m_ulCallbackID && (!m_bHasStreams || m_bDisableWrite)) { if (m_bFirstPlayAudio) { // First time thru, we initialize callback time. HXTimeval lTime = m_pScheduler->GetCurrentSchedulerTime(); m_pFakeAudioCBTime->tv_sec = lTime.tv_sec; m_pFakeAudioCBTime->tv_usec = lTime.tv_usec; m_ulIncreasingTimer = 0; m_ulLastFakeCallbackTime = HX_GET_TICKCOUNT(); *m_pFakeAudioCBTime += (int) (m_ulGranularity*1000); } m_bFakeAudioTimeline = TRUE; m_ulCallbackID = m_pScheduler->RelativeEnter( this, m_ulGranularity); if (m_bFirstPlayAudio) { OnTimeSync(m_ulIncreasingTimer); } } else if (!theErr && !m_ulCallbackID && m_bHasStreams && !m_bDisableWrite) { m_bFakeAudioTimeline = FALSE; m_ulCallbackID = m_pScheduler->RelativeEnter(this, m_ulGranularity*9/10);#if 0 // XXX HP don't send OnTimeSync() untill we resume the audio device // the following logic caused OnTimeSync() sent to video renderer before the audio // timeline is started after seeking, as a consequence, the A/V could be out of // sync, video could be frozen for short period time in order to wait the audio // timeline to catch up if (m_bFirstPlayAudio) { OnTimeSync(m_ulIncreasingTimer); }#endif }exit: m_bInPlayAudio = FALSE; // can only happen in multi-player pause/resume/stop case if (m_bDeferActualResume && theErr != HXR_OUTOFMEMORY)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -