📄 srcinfo.cpp
字号:
pRendInfo->m_bInitialBeginToBeSent = TRUE; m_pPlayer->EnterToBeginList(pRendInfo); } if (m_pSource->IsLive()) { pRendInfo->m_BufferingReason = BUFFERING_LIVE_PAUSE; } else { pRendInfo->m_BufferingReason = BUFFERING_SEEK; } } m_bSeekToLastFrame = bSeekToLastFrame; m_llLatestPacketTime = 0; return HXR_OK;}HX_RESULTSourceInfo::BeginTrack(void){#if defined(HELIX_FEATURE_ADVANCEDGROUPMGR) HX_RESULT rc = HXR_OK; UINT32 ulDelay = 0; UINT32 ulPausedTime = 0; RendererInfo* pRendInfo = NULL; STREAM_INFO* pStreamInfo = NULL; CHXAudioPlayer* pAudioPlayer = NULL; CHXMapLongToObj::Iterator ndxRend; if (!m_pSource) { rc = HXR_UNEXPECTED; goto cleanup; } if (m_pSource->IsPaused()) { ulPausedTime = m_pPlayer->m_ulCurrentPlayTime - m_ulPausedStartTime; ulDelay = m_pSource->GetDelay() + ulPausedTime; // update source's delay time which will call sourceinfo's // UpdateDelay() m_pSource->UpdateDelay(ulDelay); // resume m_pSource->ResumeAudioStreams(); rc = Begin(); } // track is stopped ahead of its duration else if (m_bStopped) { m_bStopped = FALSE; m_bSeekPending = TRUE; m_ulSeekTime = m_pPlayer->m_ulCurrentPlayTime; m_pSource->ReSetup(); } // either track has not been played yet // or track is still playing else { rc = HXR_FAILED; goto cleanup; } cleanup: return rc;#else return HXR_NOTIMPL;#endif /* HELIX_FEATURE_ADVANCEDGROUPMGR */}HX_RESULTSourceInfo::PauseTrack(void){#if defined(HELIX_FEATURE_ADVANCEDGROUPMGR) HX_RESULT rc = HXR_OK; // stop the source if (m_pSource) { m_pSource->PauseAudioStreams(); } m_ulPausedStartTime = m_pPlayer->m_ulCurrentPlayTime; rc = Pause(); return rc;#else return HXR_NOTIMPL;#endif /* HELIX_FEATURE_ADVANCEDGROUPMGR */}HX_RESULTSourceInfo::SeekTrack(UINT32 ulSeekTime){ // low priority since it is rarely used by the SMIL return HXR_NOTIMPL;}HX_RESULTSourceInfo::StopTrack(void){#if defined(HELIX_FEATURE_ADVANCEDGROUPMGR) HX_RESULT rc = HXR_OK; m_bStopped = TRUE; // stop the source if (m_pSource) { m_pSource->RemoveAudioStreams(); } Reset(); m_bDone = TRUE; m_pPlayer->m_uNumSourcesActive--; return rc;#else return HXR_NOTIMPL;#endif /* HELIX_FEATURE_ADVANCEDGROUPMGR */}HX_RESULTSourceInfo::SetSoundLevel(UINT16 uSoundLevel, BOOL bReflushAudioDevice){ m_uSoundLevel = uSoundLevel; m_pSource->SetSoundLevel(uSoundLevel, bReflushAudioDevice); return HXR_OK;}voidSourceInfo::Reset(){ /* m_pSource should never be NULL */ HX_ASSERT(m_pSource); if (!m_pSource) { return; }#if defined(HELIX_FEATURE_ADVANCEDGROUPMGR) if(m_bIsPersistentSource) { m_bDone = FALSE; m_bAllPacketsReceived = FALSE; CHXMapLongToObj::Iterator ndxRend = m_pRendererMap->Begin(); for (; ndxRend != m_pRendererMap->End(); ++ndxRend) { RendererInfo* pRendInfo = (RendererInfo*)(*ndxRend); IHXRenderer* pRend = (IHXRenderer*)pRendInfo->m_pRenderer; STREAM_INFO* pStreamInfo = pRendInfo->m_pStreamInfo; pStreamInfo->m_bSrcInfoStreamDone = FALSE; /* Reset the latest packet time */ pRendInfo->m_ulLatestEventTime = 0; m_pPlayer->m_pScheduler->Remove( pRendInfo->m_pTimeSyncCallback->GetPendingCallback()); pRendInfo->m_pTimeSyncCallback->CallbackCanceled(); pRendInfo->m_bIsFirstCallback = TRUE; pRendInfo->m_ulLastSyncTime = 0; pRendInfo->m_ulNumberOfPacketsQueued= 0; pRendInfo->m_ulNextDueSyncTime = 0; if (!pRendInfo->m_bInitialBeginToBeSent && pRendInfo->m_pRenderer) { pRendInfo->m_bInitialBeginToBeSent = TRUE; m_pPlayer->EnterToBeginList(pRendInfo); } } } else#endif /* HELIX_FEATURE_ADVANCEDGROUPMGR */ { DoCleanup(); RenderersCleanup(); } return;}voidSourceInfo::DoCleanup(EndCode endCode){ if (m_pProcessCallback && m_pPlayer->m_pScheduler) { m_pPlayer->m_pScheduler->Remove(m_pProcessCallback->GetPendingCallback()); m_pProcessCallback->CallbackCanceled(); } if (m_bIsPersistentSource) { return; } m_bLocked = TRUE; m_pMutex->Lock(); CHXMapLongToObj::Iterator ndxRend = m_pRendererMap->Begin(); for (; ndxRend != m_pRendererMap->End(); ++ndxRend) { RendererInfo* pRendInfo = (RendererInfo*)(*ndxRend); /* Tell each renderer that we are done with the stream */ if(pRendInfo) { if (pRendInfo->m_pStream && pRendInfo->m_pStreamInfo && pRendInfo->m_pStreamInfo->m_pHeader) { IHXBuffer* pMimeTypeBuffer = NULL; pRendInfo->m_pStreamInfo->m_pHeader->GetPropertyCString("MimeType", pMimeTypeBuffer); if (pMimeTypeBuffer && pMimeTypeBuffer->GetBuffer() && ::strcasecmp((const char*) pMimeTypeBuffer->GetBuffer(), "application/vnd.rn-objectsstream") == 0 || ::strcasecmp((const char*) pMimeTypeBuffer->GetBuffer(), "application/x-rn-objects") == 0 || ::strcasecmp((const char*) pMimeTypeBuffer->GetBuffer(), "application/vnd.rn-objects") == 0) { m_pPlayer->m_pEngine->m_lROBActive--; HX_ASSERT(m_pPlayer->m_pEngine->m_lROBActive >=0 ); } HX_RELEASE(pMimeTypeBuffer); } if(pRendInfo->m_pRenderer) pRendInfo->m_pRenderer->EndStream(); if (pRendInfo->m_bInitialBeginToBeSent) { m_pPlayer->RemoveFromPendingList(pRendInfo); } if (pRendInfo->m_pTimeSyncCallback) {//{FILE* f1 = ::fopen("c:\\temp\\ts.txt", "a+"); ::fprintf(f1, "%p RELEASING TimeSyncCallback: Pending: %d Handle: %lu\n", pRendInfo->m_pTimeSyncCallback, (int)pRendInfo->m_bIsCallbackPending, (UINT32) pRendInfo->m_PendingHandle);::fclose(f1);} m_pPlayer->m_pScheduler->Remove( pRendInfo->m_pTimeSyncCallback->GetPendingCallback()); pRendInfo->m_pTimeSyncCallback->CallbackCanceled(); HX_RELEASE(pRendInfo->m_pTimeSyncCallback); } HX_RELEASE(pRendInfo->m_pStream); } } // cleanup (i.e. registry) m_pSource->DoCleanup(endCode); UnRegister(); m_lastError = HXR_OK; m_bAreStreamsSetup = FALSE; m_bDone = FALSE; m_bInitialized = FALSE; m_bSeekPending = FALSE; m_bSeekToLastFrame = FALSE; m_pMutex->Unlock(); m_bLocked = FALSE;}voidSourceInfo::Stop(EndCode endCode){ /* We have already been here once */ if (m_pSource == NULL) { return; } DoCleanup(endCode); if (m_bIsPersistentSource) { return; } m_bLocked = TRUE; m_pMutex->Lock(); m_pSource->Stop();#if defined(HELIX_FEATURE_BASICGROUPMGR) if (m_bTrackStoppedToBeSent) { m_pPlayer->m_pGroupManager->TrackStopped(m_uGroupID, m_uTrackID); m_bTrackStoppedToBeSent = FALSE; if (m_pPeerSourceInfo) { m_pPeerSourceInfo->m_bTrackStoppedToBeSent = FALSE; } }#endif /* HELIX_FEATURE_BASICGROUPMGR */ m_pMutex->Unlock(); m_bLocked = FALSE;}voidSourceInfo::Remove(){ // stop the source if (m_pSource) { m_pSource->RemoveAudioStreams(); } m_bDone = TRUE; Stop(); CloseRenderers();}/* * -- LIVE SYNC SUPPORT -- * * SharedWallClock class is used for live sync support. * There is one of these objects per shared wall clock. * * This object will also be associated with an HXPlayer * since we won't ever share wall clocks between two players. * This is an intentional design choice, since it doesn't * reall make sense to do any sync-ing across multiple players. * * This object will keep a list of source's that are sharing * it. This is mainly needed so that the wall clock can * reset the start time for all the sources in the event that * it gets a new start time that is earlier than it had * previously thought. Basically, the start time of the wall * clock is what does the syncing. */SharedWallClock::SharedWallClock( const char* pName, UINT32 ulStartTime, HXPlayer* pPlayer) : m_ulStartTime(ulStartTime) , m_strName(pName) , m_pPlayer(pPlayer){ HX_ASSERT(m_pPlayer); (*m_pPlayer->m_pSharedWallClocks)[pName] = this;};/* * -- LIVE SYNC SUPPORT -- * * Obviously this is the method that handles resyncing the * start times for all the sources that share the wall clock. * * This method also returns the start time. The intended useage * is for the caller to pass the start time that it expects, and * then respect the start time that is returned. In the event that * the input start time is less than the previously known start * time, then all sources are reset. */UINT32SharedWallClock::ResetStartTime(UINT32 ulStartTime){ if (ulStartTime < m_ulStartTime) { m_ulStartTime = ulStartTime; CHXSimpleList::Iterator indx = m_UserList.Begin(); for (; indx != m_UserList.End(); ++indx) { SourceInfo* pSourceInfo = (SourceInfo*)(*indx); pSourceInfo->ResetStartTime(ulStartTime); } } return m_ulStartTime;};/* * -- LIVE SYNC SUPPORT -- * * Nothing tricky here, we just track the incoming user on our * list of known users. */voidSharedWallClock::AddUser(SourceInfo* pSourceInfo){ m_UserList.AddTail(pSourceInfo);};/* * -- LIVE SYNC SUPPORT -- * * This method removes users from the shared clock's user list * and also cleans up the shared clock when the last user is * removed. So, any caller of this method should take note to * NOT use the shared clock after calling this method. */voidSharedWallClock::RemoveUser(SourceInfo* pSourceInfo){ LISTPOSITION pos = m_UserList.Find(pSourceInfo); HX_ASSERT(pos); m_UserList.RemoveAt(pos); if (m_UserList.IsEmpty()) { m_pPlayer->m_pSharedWallClocks->RemoveKey(m_strName); delete this; }};/* * -- LIVE SYNC SUPPORT -- * * If the start time is changed for a source then all the * renderer's need to have their start time's reset. This * method just loops through the renderer info to do the work. */voidSourceInfo::ResetStartTime(UINT32 ulStartTime){ if (ulStartTime < m_ulStreamStartTime) { m_ulStreamStartTime = ulStartTime; CHXMapLongToObj::Iterator indx = m_pRendererMap->Begin(); for (; indx != m_pRendererMap->End(); ++indx) { RendererInfo* pRendererInfo = (RendererInfo*)(*indx); pRendererInfo->m_ulStreamStartTime = ulStartTime; } }};/* * -- LIVE SYNC SUPPORT -- * * This is the real work horse for live sync support. This * method actually determines if the URL for the source is * targeted at a shared wall clock by looking for the wallclock * option in the URL. * * If the wallclock name is found then we try to find the wall * clock object for this name and player. If we don't find it * then we create a new clock. If we do find it then we want * to determine if the start time should be reset to the lower * value. We also return the start time to be stored in the * renderers. */UINT32SourceInfo::CalculateLiveStartTime(IHXPacket* pFirstPacket){ UINT32 ulStreamStartTime = pFirstPacket->GetTime();; /* * Find out if this live feed has a "wallclock" property. */ CHXURL* pURL = m_pSource->GetCHXURL(); IHXValues* pValues = pURL->GetOptions(); IHXBuffer* pWallClockName = NULL; pValues->GetPropertyBuffer("wallclock", pWallClockName); if (pWallClockName) { m_strWallClockName = (const char*)pWallClockName->GetBuffer(); /* We shouldn't already have a wall clock! */ HX_ASSERT(m_pWallClock == NULL); /* * Lookup a wall clock with this name, if it's not found then * we are the first one, and we should create a shared wallclock * object, add it to the list, and do the standard setup. */ void* pLookupResult = NULL; if (!m_pPlayer->FindSharedWallClocks(m_strWallClockName,pLookupResult)) { m_pWallClock = new SharedWallClock(m_strWallClockName,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -