📄 rtrender.cpp
字号:
// the optimized scheduler has presidence so we check it first if (m_bPendingCallback && m_pOptimizedScheduler) { m_pOptimizedScheduler->Remove(m_PendingHandle); m_bPendingCallback = FALSE; m_PendingHandle = 0; } HX_RELEASE(m_pOptimizedScheduler); if (m_bPendingCallback && m_pScheduler) { m_pScheduler->Remove(m_PendingHandle); m_bPendingCallback = FALSE; m_PendingHandle = 0; } HX_RELEASE(m_pScheduler); HX_RELEASE(m_pHeader); HX_RELEASE(m_pLastPacket); HX_RELEASE(m_pContext); HX_RELEASE(m_pPlayer); HX_RELEASE(m_pCommonClassFactory); HX_RELEASE(m_pHyperNavigate); HX_RELEASE(m_pPreferences); HX_RELEASE(m_pStatusMessage); HX_RELEASE(m_pValues); HX_ASSERT(!m_pMISUSSite);#ifdef _DEBUG#if defined(RT_OUTPUT_LOGFILE) if(m_logfile) { fclose(m_logfile); }#endif#endif#if defined(_MACINTOSH) || defined(_MAC_UNIX) if (m_hHyperlinkCursor) { m_pResourceLoader->UnloadResource((Handle)m_hHyperlinkCursor); m_hHyperlinkCursor = NULL; HX_RELEASE(m_pResourceLoader); } #endif#if defined(_UNIX) && (!(defined(_BEOS))) && (!(defined(_MAC_UNIX))) if (m_pVisualInfo) { XFree(m_pVisualInfo); m_pVisualInfo = NULL; } if (m_hHyperlinkCursor && m_pPixmapDisplay) { XLockDisplay(m_pPixmapDisplay); XFreeCursor(m_pPixmapDisplay, m_hHyperlinkCursor); XUnlockDisplay(m_pPixmapDisplay); }#endif HX_DELETE(m_pMutex);}// *** IUnknown methods ***/////////////////////////////////////////////////////////////////////////// Method:// IUnknown::QueryInterface// Purpose:// Implement this to export the interfaces supported by your // object.//STDMETHODIMP CRealTextRenderer::QueryInterface(REFIID riid, void** ppvObj){ if (IsEqualIID(riid, IID_IUnknown)) { AddRef(); *ppvObj = this; return HXR_OK; } else if (IsEqualIID(riid, IID_IHXPlugin)) { AddRef(); *ppvObj = (IHXPlugin*)this; return HXR_OK; } else if (IsEqualIID(riid, IID_IHXRenderer)) { AddRef(); *ppvObj = (IHXRenderer*)this; return HXR_OK; } else if (IsEqualIID(riid, IID_IHXSiteUser)) { AddRef(); *ppvObj = (IHXSiteUser*)this; return HXR_OK; } else if (IsEqualIID(riid, IID_IHXSiteUserSupplier)) { if (m_pMISUS) { return m_pMISUS->QueryInterface(IID_IHXSiteUserSupplier,ppvObj); } else { *ppvObj = NULL; return HXR_UNEXPECTED; } } else if (IsEqualIID(riid, IID_IHXStatistics)) { AddRef(); *ppvObj = (IHXStatistics*)this; return HXR_OK; } else if (IsEqualIID(riid, IID_IHXCallback)) { AddRef(); *ppvObj = (IHXCallback*)this; return HXR_OK; } else if (IsEqualIID(riid, IID_IHXUpdateProperties)) { AddRef(); *ppvObj = (IHXUpdateProperties*)this; return HXR_OK; } else if (IsEqualIID(riid, IID_IHXValues)) { AddRef(); *ppvObj = (IHXValues*)this; return HXR_OK; } *ppvObj = NULL; return HXR_NOINTERFACE;}/////////////////////////////////////////////////////////////////////////// Method:// IUnknown::AddRef// Purpose:// Everyone usually implements this the same... feel free to use// this implementation.//STDMETHODIMP_(ULONG32) CRealTextRenderer::AddRef(){ return InterlockedIncrement(&m_lRefCount);}/////////////////////////////////////////////////////////////////////////// Method:// IUnknown::Release// Purpose:// Everyone usually implements this the same... feel free to use// this implementation.//STDMETHODIMP_(ULONG32) CRealTextRenderer::Release(){ if (InterlockedDecrement(&m_lRefCount) > 0) { return m_lRefCount; } delete this; return 0;}// *** IHXRenderer methods ***/////////////////////////////////////////////////////////////////////////// Method:// IHXRenderer::StartStream// Purpose:// Called by client engine to inform the renderer of the stream it// will be rendering. The stream interface can provide access to// its source or player. This method also provides access to the // primary client controller interface.//STDMETHODIMP CRealTextRenderer::StartStream( IHXStream* pStream, IHXPlayer* pPlayer){ // Save for later use! m_pStream = pStream; m_pPlayer = pPlayer; if (m_pStream ) m_pStream->AddRef(); if (m_pPlayer ) m_pPlayer->AddRef(); HX_RESULT hxr = m_pCommonClassFactory->CreateInstance(CLSID_IHXMultiInstanceSiteUserSupplier, (void**)&m_pMISUS); if (SUCCEEDED(hxr)) { m_pMISUS->SetSingleSiteUser((IUnknown*)(IHXSiteUser*)this); } generatePreFix(); return HXR_OK;}void CRealTextRenderer::RemoveCallback(CallbackHandle &hCallback){ if (hCallback != (CallbackHandle)NULL) { if (m_pOptimizedScheduler != NULL) { m_pOptimizedScheduler->Remove(hCallback); } else if (m_pScheduler) { m_pScheduler->Remove(hCallback); } hCallback = NULL; }}/////////////////////////////////////////////////////////////////////////// Method:// IHXRenderer::EndStream// Purpose:// Called by client engine to inform the renderer that the stream// is was rendering is closed.//STDMETHODIMP CRealTextRenderer::EndStream(){ m_pMutex->Lock(); // Removing callback within mutex after OEM Gold release of 2/2002 // is safe (no danger of deadlock) since since the scheduler mutex // is not held across Func call. // Removing callback outside the mutex could result in incorrectly // removing a different callback that reused this handle. RemoveCallback(m_PendingHandle); HX_RELEASE(m_pStream);#ifdef _DEBUG#if defined(RT_OUTPUT_LOGFILE) if(m_logfile) { if(m_txtWin.getDebugFlags()&RT_RENDER_DEBUG_FLAGS_MASK) { fprintf(m_logfile,"\nCRealTextRenderer::EndStream()\n"); } fflush(m_logfile); }#endif#endif //XXXEH1208- we only want to set this in the draw thread, namely // in SchedulerCallback(), in case we've still got a pending draw // in that thread when EndStream() gets called: (right???) m_bEndStreamJustOccurred = TRUE; if (m_bPendingCallback) { m_bPendingCallback = FALSE; SchedulerCallback(); } m_PlayState = Stopped; //Fixes seeking to very end of SMIL-frozen stream and m_PlayState never // getting reset from "Seeking" because draw thread (SchedulerCallback) // never gets called again to do so (in this case) so repaint never // gets done: if(m_txtWin.isLiveSource() || //(Always set to Stopped if is live) m_ulTimeOfCurrentDraw >= m_ulDuration + m_lTimeOffset) { m_PlayState = Stopped; LOG((m_logfile,"\n CRealTextRenderer::EndStream(): " "setting m_PlayState to Stopped\n")); } m_pMutex->Unlock(); return HXR_OK;}/////////////////////////////////////////////////////////////////////////// Method:// IHXRenderer::OnHeader// Purpose:// Called by client engine when a header for this renderer is // available. The header will arrive before any packets.//STDMETHODIMP CRealTextRenderer::OnHeader(IHXValues* pHeader){ HX_RESULT hxr = HXR_OK; ULONG32 ulLengthHeader, retVal; // Keep this for later use... m_pHeader = pHeader; m_pHeader->AddRef(); IHXBuffer* pOpaqueData = 0; ULONG32 ulStreamNumber = 0; ULONG32 ulMaxBitRate = 0; ULONG32 ulAvgBitRate = 0; ULONG32 ulMaxPacketSize = 0; ULONG32 ulAvgPacketSize = 0; ULONG32 ulStartTime = 0; ULONG32 ulPreroll = 0; ULONG32 ulPresentationDuration = 0; IHXBuffer* pStreamName = 0; IHXBuffer* pMimeType = 0; ULONG32 ulMinMajorVer = 0L; ULONG32 ulMinMinorVer = 0L; ULONG32 ulContentMajorVer = 0L; ULONG32 ulContentMinorVer = 0L; BOOL bAutoUpgradeNeeded=FALSE; pHeader->GetPropertyBuffer ("OpaqueData", pOpaqueData); pHeader->GetPropertyULONG32("StreamNumber", ulStreamNumber); pHeader->GetPropertyULONG32("MaxBitRate", ulMaxBitRate); pHeader->GetPropertyULONG32("AvgBitRate", ulAvgBitRate); pHeader->GetPropertyULONG32("MaxPacketSize", ulMaxPacketSize); pHeader->GetPropertyULONG32("AvgPacketSize", ulAvgPacketSize); pHeader->GetPropertyULONG32("StartTime", ulStartTime); pHeader->GetPropertyULONG32("Preroll", ulPreroll); pHeader->GetPropertyULONG32("Duration", ulPresentationDuration); //This is "timeZero" of the encoder; we can no longer assume 0 is when // the encoder started (in fact, it is guaranteed NOT to be 0 by rtlive). // If we get 0 here, then it's an older encoder so we'll have to force // an auto-upgrade because text simply will not show up if the timelines // of the renderer and the rtlive app are not in sync. Note: ulMinMajor // and ulMinMinor version stuff, below, will tell us to auto-upgrade in // this case, unless they don't exist, either, in which case we're OK // because that means an older encoder is sending 0-based timeline text: ULONG32 ulStartTimeHigh = 0L; pHeader->GetPropertyULONG32("RTLiveStartTimeHigh", ulStartTimeHigh); pHeader->GetPropertyULONG32("RTLiveStartTimeLow", m_ulStreamStartTime); m_ulStreamStartTime |= ulStartTimeHigh<<0x10; ULONG32 ulRTFileFormatVersion = 0; //The following is sent by the RT file format to the // RT renderer to notify it what "parsing" version to // use. This is done via the stream header properties // "RTMarkupParsing[Major|Minor]Version" (which are ULONG32s). // This must be done so that the ff and the renderer // are in sync as far as how they deal with new tags, // e.g., if the file format ignores a tag it doesn't // recognize but the renderer is newer and recognizes // the tag, the renderer should behave as does the ff // and ignore the tag otherwise the renderer might // display the text in a different place than the ff // thinks it is and the next packet sent by the ff // will tell the renderer to draw in a place that // might overlap the prior packet's text due to this // discrepancy. pHeader->GetPropertyULONG32("RTMarkupParsingMajorVersion", m_ulRTMarkupParsingMajorVersion); pHeader->GetPropertyULONG32("RTMarkupParsingMinorVersion", m_ulRTMarkupParsingMinorVersion); //These (put together) are the minimum version that the renderer // must know about. If the renderer is older, it must fire auto-upgrade: // Note: this is the file format/rtlive version, NOT the content or // parsing version: pHeader->GetPropertyULONG32("MinRTMajorVersion", ulMinMajorVer); pHeader->GetPropertyULONG32("MinRTMinorVersion", ulMinMinorVer); //These (put together) are the version that the rt file's author has // declared for the file contents. If omitted from the file, it is 0.0: // Note: this will allow us to properly deal with future changes to // the header and other tags in the rt file, namely: force auto-upgrade: pHeader->GetPropertyULONG32("RTMajorContentVersion", ulContentMajorVer); pHeader->GetPropertyULONG32("RTMinorContentVersion", ulContentMinorVer); //If renderer is older than ff, we should have been notified to // auto update!!! BOOL bRendererIsOlderThanFileFormat = FALSE; if(m_ulRTMarkupParsingMajorVersion > REAL_TEXT_MARKUP_PARSING_MAJOR_VERSION || (m_ulRTMarkupParsingMajorVersion == REAL_TEXT_MARKUP_PARSING_MAJOR_VERSION && m_ulRTMarkupParsingMinorVersion > REAL_TEXT_MARKUP_PARSING_MINOR_VERSION) ) { //The renderer is older than the file format so we // won't be able to play the stream until we get the // latest rtrender dll: bRendererIsOlderThanFileFormat = TRUE; } //And, if renderer is too old to handle content version, it should // force an auto-upgrade as well: BOOL bRendererIsTooOldToRenderContent = FALSE; if((ulContentMajorVer > REAL_TEXT_CONTENT_MAJOR_VERSION) || (ulContentMajorVer == REAL_TEXT_CONTENT_MAJOR_VERSION && ulContentMinorVer > REAL_TEXT_CONTENT_MINOR_VERSION) ) { //The renderer is older than the file format so we // won't be able to play the stream until we get the // latest rtrender dll: bRendererIsTooOldToRenderContent = TRUE; } //Now, if certain properties did not exist (returned 0) or // if we're older than the file format AND we're older than // the ulMinMajorVer.ulMinMinorVer, we should force an auto-upgrade: if(bRendererIsTooOldToRenderContent || (bRendererIsOlderThanFileFormat && (0!=ulMinMajorVer || 0!=ulMinMinorVer)) ) { if(bRendererIsTooOldToRenderContent || (ulMinMajorVer > REAL_TEXT_MARKUP_PARSING_MAJOR_VERSION || (ulMinMajorVer == REAL_TEXT_MARKUP_PARSING_MAJOR_VERSION && ulMinMinorVer > REAL_TEXT_MARKUP_PARSING_MINOR_VERSION)) ) { HX_ASSERT(m_pContext); AddToAutoUpgradeCollection(zm_pStreamMimeTypes[0], m_pContext); hxr = HXR_FAIL; bAutoUpgradeNeeded = TRUE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -