?? hxaudply.cpp
字號:
/************************************************************************ * Method: * CHXAudioPlayer::GetStreamCount * Purpose: * Get the number of streams associated with this player. */UINT16 CHXAudioPlayer::GetStreamCount(){ return m_pStreamList->GetCount();}/************************************************************************ * Method: * CHXAudioPlayer::SetStreamInfoResponse * Purpose: * Add the stream info response interface to our list. */STDMETHODIMP CHXAudioPlayer::SetStreamInfoResponse( IHXAudioStreamInfoResponse* pResponse){ if (!pResponse || !m_pStreamRespList) { return HXR_FAILED; } /* Add to the stream response list */ LISTPOSITION lPos = m_pStreamRespList->Find(pResponse); if (lPos) { return HXR_FAILED; } m_pStreamRespList->AddTail((void*) pResponse); pResponse->AddRef(); // Released in destructor return HXR_OK;}/************************************************************************ * Method: * CHXAudioPlayer::RemoveStreamInfoResponse * Purpose: * Remove stream info response that was added earlier */STDMETHODIMP CHXAudioPlayer::RemoveStreamInfoResponse( IHXAudioStreamInfoResponse* pResponse){ /* Add to the stream response list */ if (pResponse && m_pStreamRespList) { LISTPOSITION lPos = m_pStreamRespList->Find(pResponse); if (lPos) { m_pStreamRespList->RemoveAt(lPos); pResponse->Release(); // Released in destructor return HXR_OK; } } return HXR_FAILED;}UINT16CHXAudioPlayer::NumberOfResumedStreams(void){ UINT16 uNumActive = 0; if (m_pStreamList && m_pStreamList->GetCount() > 0) { CHXAudioStream* pStream = 0; CHXSimpleList::Iterator lIter = m_pStreamList->Begin(); for (; lIter != m_pStreamList->End(); ++lIter) { pStream = (CHXAudioStream*) (*lIter); if (pStream->GetState() == E_PLAYING) { uNumActive++; } } } return uNumActive;}void CHXAudioPlayer::StreamInitialized(CHXAudioStream* pAudioStream){ /* If we are already initialized, it means this stream was added mid- * presentation and gogt initialized later. In this case, report arrival * of this stream to all StreamInfoResponse objects registered with the * player */ if (m_pStreamRespList && m_bInited) { IHXAudioStreamInfoResponse* pAudioStreamInfoResponse = 0; CHXSimpleList::Iterator lIter = m_pStreamRespList->Begin(); for (; lIter != m_pStreamRespList->End(); ++lIter) { pAudioStreamInfoResponse = (IHXAudioStreamInfoResponse*) (*lIter); pAudioStreamInfoResponse->OnStream(pAudioStream); } } m_bHasStreams = TRUE;}ULONG32 CHXAudioPlayer::GetInitialPushdown(BOOL bAtStart /* = FALSE*/){ /* If there are any audio streams, initial pushdown is session's * initial pushdown */ if (m_pStreamList->GetCount() > 0) { ULONG32 ulRet = m_Owner->GetInitialPushdown(bAtStart) + m_ulGranularity;#ifdef HELIX_FEATURE_MIN_HEAP // The MIN_HEAP code seems to need 1 extra block's worth // of data to avoid rebuffers during playback. This // is a low impact temporary solution that fixes the problem. ulRet += m_ulGranularity;#endif /* HELIX_FEATURE_MIN_HEAP */ return ulRet; } else { return 0; }}/************************************************************************ * Method: * CHXAudioPlayer::OnTimerCallback * Purpose: * Timer callback when implementing fake timeline. */void CHXAudioPlayer::OnTimerCallback(){ ULONG32 ulCurrentTime = HX_GET_TICKCOUNT(); m_ulIncreasingTimer += CALCULATE_ELAPSED_TICKS(m_ulLastFakeCallbackTime, ulCurrentTime); m_ulLastFakeCallbackTime = ulCurrentTime; OnTimeSync(m_ulIncreasingTimer); /* A call to timesync may result in stopping * playback and we do not want to have any more * time syncs. */ /* Put this back in the scheduler. */ if (m_bInited && m_eState == E_PLAYING && !m_ulCallbackID) { *m_pFakeAudioCBTime += (int) (m_ulGranularity*1000); m_ulCallbackID = m_pScheduler->AbsoluteEnter( this, *((HXTimeval*)m_pFakeAudioCBTime)); }}voidCHXAudioPlayer::SetLive(BOOL bIsLive){ m_bIsLive = bIsLive; CHXAudioStream* s = 0; CHXSimpleList::Iterator lIter = m_pStreamList->Begin(); for (; lIter != m_pStreamList->End(); ++lIter) { s = (CHXAudioStream*) (*lIter); s->SetLive(m_bIsLive); }}voidCHXAudioPlayer::AudioFormatNowKnown(void){ HX_ASSERT(m_bInited); /* When : More than one audio stream created after initialization * and one of them already called this function earlier */ if (m_bHasStreams) { return; } m_bHasStreams = TRUE; m_bInited = FALSE; /* internal setup */ HX_RESULT theErr = Setup(m_ulGranularity); if (theErr != HXR_OK) { IHXErrorMessages* pErrorMessage = NULL; m_pContext->QueryInterface(IID_IHXErrorMessages, (void**) &pErrorMessage); if (pErrorMessage) { pErrorMessage->Report(HXLOG_ERR, theErr, 0, NULL, NULL); pErrorMessage->Release(); } return; } HX_ASSERT(m_bInited); /* If we have not yet resumed, it is simply setting the audio * player from fake timeline mode to audio timeline mode. * Instead if we have already been resumed and are acting as a * fake timeline, we need to kinda pause from being a fake timeline to * an audio timeline, In this process, we may have to seek the audio * device to generate right timesyncs. */ /* If we are already resumed, we need to call resume again internally */ if (m_bIsResumed) { StopFakeTimeline(); Seek(m_ulCurrentTime); // only resume the owner if we are in a play state... // otherwise owner will be resumed when the player gets resumed. if (m_eState == E_PLAYING) { m_Owner->Resume(); } } else { /* Cool! HXPlayer will call resume later */ }}voidCHXAudioPlayer::RegisterRealAudioStream(CHXAudioStream* pAudioStream){ if (!m_pRealAudioStreamList) { m_pRealAudioStreamList = new CHXSimpleList; } m_pRealAudioStreamList->AddTail((void*) pAudioStream); m_bAdjustForRealAudio = TRUE;}voidCHXAudioPlayer::UnRegisterRealAudioStream(CHXAudioStream* pAudioStream){ if (!m_pRealAudioStreamList) { return; } LISTPOSITION posStream = m_pRealAudioStreamList->Find((void*) pAudioStream); if (posStream) { m_pRealAudioStreamList->RemoveAt(posStream); } /* Check if there are any more RealAudio Streams registered */ if (m_pRealAudioStreamList->GetCount() == 0) { m_bAdjustForRealAudio = FALSE; }}BOOLCHXAudioPlayer::IsAudioOnlyTrue(void){ BOOL bRetValue = TRUE; IHXPlayer* pPlayer = NULL; m_pContext->QueryInterface(IID_IHXPlayer, (void**)&pPlayer); HX_ASSERT(pPlayer); UINT16 uNumSources = pPlayer->GetSourceCount(); IUnknown* pUnknown = NULL; IHXStreamSource* pStreamSource = NULL; IHXStream* pStream = NULL; for (UINT16 i=0; bRetValue && i < uNumSources; i++) { pPlayer->GetSource(i, pUnknown); pUnknown->QueryInterface(IID_IHXStreamSource, (void**) &pStreamSource); HX_RELEASE(pUnknown); HX_ASSERT(pStreamSource); UINT16 uNumStreams = pStreamSource->GetStreamCount(); for (UINT16 j=0; bRetValue && j < uNumStreams; j++) { pStreamSource->GetStream(j, pUnknown); pUnknown->QueryInterface(IID_IHXStream, (void**) &pStream); HX_RELEASE(pUnknown); HX_ASSERT(pStream); IHXValues* pHeader = pStream->GetHeader(); if (pHeader) { if (!IsThisAudioStream(pHeader)) { bRetValue = FALSE; } pHeader->Release(); } pStream->Release(); } HX_RELEASE(pStreamSource); } HX_RELEASE(pPlayer); return bRetValue;}BOOLCHXAudioPlayer::IsThisAudioStream(IHXValues* pHeader){ CHXSimpleList::Iterator ndxStream = m_pStreamList->Begin(); for(; ndxStream != m_pStreamList->End(); ++ndxStream) { CHXAudioStream* pAudioStream = (CHXAudioStream*) (*ndxStream); IHXValues* pAudioHeader = pAudioStream->GetStreamInfo(); if (pAudioHeader == pHeader) { HX_RELEASE(pAudioHeader); return TRUE; } HX_RELEASE(pAudioHeader); } return FALSE;}voidCHXAudioPlayer::AdjustForRealAudio(){ UINT32 ulCurrentDeviceTime = m_ulCurrentTime;#if defined(HELIX_FEATURE_AUDIO_INACCURATESAMPLING) if (m_bAdjustForRealAudio) { CHXAudioStream* pAudioStream = NULL; // Only use a playing audio stream for time adjustment: for (CHXSimpleList::Iterator streamIterator = m_pRealAudioStreamList->Begin(); streamIterator != m_pRealAudioStreamList->End(); ++streamIterator) { if ( ((CHXAudioStream*) (*streamIterator))->GetState() == E_PLAYING) { pAudioStream = (CHXAudioStream*) *streamIterator; break; } } if (pAudioStream) { UINT32 ulAdjustedTime = 0L; double dBytesPlayed = m_Owner->GetNumBytesPlayed(); if (HXR_OK == pAudioStream->ConvertCurrentTime( dBytesPlayed, m_ulCurrentTime, ulAdjustedTime)) { UINT32 ulTickCount = HX_GET_TICKCOUNT(); /* This is to avoid stall at end of the presentation */ /* The RA stream may have a duration of say 30 seconds * but the actual data may be only for 29.9 * seconds. In this case, audio stream will never * return time more than 29.9 seconds and we will get * stalled. To avoid this, we wait for atmost * MAX_WAIT_AT_SAME_TIME (== max granularity+50 ms) at * the same timestamp. If we find that we are pushing * more data in the audio device but the audio stream * is reporting the same time for the past * MAX_WAIT_AT_SAME_TIME, we increment our timestamp * by the real time elapsed since the last update. * This code will only trigger when we are near the * end of presentation. */ if (m_bTimeReturned && ulAdjustedTime <= m_ulLastCurrentTimeReturned && ulCurrentDeviceTime > m_ulLastDeviceTimeAdjusted && ulCurrentDeviceTime - m_ulLastDeviceTimeAdjusted > MAX_WAIT_AT_SAME_TIME) { UINT32 ulElapsedTime = CALCULATE_ELAPSED_TICKS(m_ulTimeAdjustDoneAt, ulTickCount); if (ulElapsedTime >= MAX_WAIT_AT_SAME_TIME) { m_ulCurrentTime = m_ulLastCurrentTimeReturned + ulElapsedTime; m_ulTimeAdjustDoneAt = ulTickCount; m_ulLastDeviceTimeAdjusted = ulCurrentDeviceTime; } else { m_ulCurrentTime = ulAdjustedTime; } } else { m_ulTimeAdjustDoneAt = ulTickCount; m_ulCurrentTime = ulAdjustedTime; } } } }#endif /* HELIX_FEATURE_AUDIO_INACCURATESAMPLING */ /* Never go back in time */ if (!m_bTimeReturned) { m_bTimeReturned = TRUE; m_ulLastCurrentTimeReturned = m_ulCurrentTime; m_ulTimeAdjustDoneAt = HX_GET_TICKCOUNT(); m_ulLastDeviceTimeAdjusted = ulCurrentDeviceTime; } else if (m_ulCurrentTime <= m_ulLastCurrentTimeReturned) { m_ulCurrentTime = m_ulLastCurrentTimeReturned; } else { m_ulLastDeviceTimeAdjusted = ulCurrentDeviceTime; m_ulLastCurrentTimeReturned = m_ulCurrentTime; }}HX_RESULTCHXAudioPlayer::ResumeFakeTimeline(void){ HX_RESULT rc = HXR_OK; HX_ASSERT(!m_bHasStreams); HXTimeval lTime = m_pScheduler->GetCurrentSchedulerTime(); m_pFakeAudioCBTime->tv_sec = lTime.tv_sec; m_pFakeAudioCBTime->tv_usec = lTime.tv_usec; m_ulIncreasingTimer = m_ulCurrentTime; m_ulLastFakeCallbackTime = HX_GET_TICKCOUNT(); *m_pFakeAudioCBTime += (int) (m_ulGranularity*1000); m_ulCallbackID = m_pScheduler->AbsoluteEnter(this, *((HXTimeval*) m_pFakeAudioCBTime)); return rc;}HX_RESULT CHXAudioPlayer::Func(){ m_ulCallbackID = 0; OnTimerCallback(); return HXR_OK;}HX_RESULT CHXAudioPlayer::StopFakeTimeline(void){ HX_RESULT rc = HXR_OK; if(m_ulCallbackID && m_pScheduler) { m_pScheduler->Remove(m_ulCallbackID); } return rc;}doubleCHXAudioPlayer::NumberOfBytesWritten(){ return m_Owner->NumberOfBytesWritten();}doubleCHXAudioPlayer::ConvertMsToBytes(UINT32 ulTime){ return m_Owner->ConvertMsToBytes(ulTime);}voidCHXAudioPlayer::UpdateStreamLastWriteTime(){ // Make each stream seek, too, since they own the resampling buffers. CHXAudioStream* s = 0; CHXSimpleList::Iterator lIter = m_pStreamList->Begin(); for (; lIter != m_pStreamList->End(); ++lIter) { s = (CHXAudioStream*) (*lIter); s->UpdateStreamLastWriteTime(); }}voidCHXAudioPlayer::SaveLastNMilliSeconds(BOOL bSave, UINT32 ulNMilliSeconds){ // Make each stream seek, too, since they own the resampling buffers. CHXAudioStream* s = 0; CHXSimpleList::Iterator lIter = m_pStreamList->Begin(); for (; lIter != m_pStreamList->End(); ++lIter) { s = (CHXAudioStream*) (*lIter); s->SaveLastNMilliSeconds(bSave, ulNMilliSeconds); }}voidCHXAudioPlayer::RewindPlayer(UINT32 ulTimeToRewind){ if (m_pStreamList->GetCount() == 0 || !m_bCanBeRewound) { return; } // Make each stream seek, too, since they own the resampling buffers. CHXAudioStream* s = 0; CHXSimpleList::Iterator lIter = m_pStreamList->Begin(); for (; lIter != m_pStreamList->End(); ++lIter) { s = (CHXAudioStream*) (*lIter); s->RewindStream(ulTimeToRewind); } HX_ASSERT(m_llLastWriteTime >= ulTimeToRewind); if (m_llLastWriteTime >= ulTimeToRewind) { m_llLastWriteTime -= ulTimeToRewind; }}HX_RESULTCHXAudioPlayer::ProcessAudioHook(PROCESS_ACTION action, IHXAudioHook* pAudioHook){ return HXR_OK;}STDMETHODIMP CHXAudioPlayer::SetError( HX_RESULT theErr ){ if (theErr != HXR_OK) { IHXErrorMessages* pErrorMessage = NULL; m_pContext->QueryInterface(IID_IHXErrorMessages, (void**) &pErrorMessage); if (pErrorMessage) { pErrorMessage->Report(HXLOG_ERR, theErr, 0, NULL, NULL); pErrorMessage->Release(); } } return HXR_OK;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -