📄 pxgifrnd.cpp
字号:
HX_RELEASE(m_pContext); m_pContext = pContext; m_pContext->AddRef(); // Get a IHXCommonClassFactory interface HX_RELEASE(m_pCommonClassFactory); retVal = m_pContext->QueryInterface(IID_IHXCommonClassFactory, (void**) &m_pCommonClassFactory); if (SUCCEEDED(retVal)) {#if defined(HELIX_FEATURE_HYPER_NAVIGATE) // Get an IHXHyperNavigate interface HX_RELEASE(m_pHyperNavigate); m_pContext->QueryInterface(IID_IHXHyperNavigate, (void**) &m_pHyperNavigate);#endif /* #if defined(HELIX_FEATURE_HYPER_NAVIGATE) */ // Get the IHXStatusMessage interface - it's OK if TLC doesn't support // this, so we won't check error return. HX_RELEASE(m_pStatusMessage); m_pContext->QueryInterface(IID_IHXStatusMessage, (void**) &m_pStatusMessage); // Get an IHXScheduler interface HX_RELEASE(m_pScheduler); retVal = m_pContext->QueryInterface(IID_IHXScheduler, (void**) &m_pScheduler); if (SUCCEEDED(retVal)) { // Get the IHXErrorMessages interface - OK if // TLC doesn't support it HX_RELEASE(m_pErrorMessages); m_pContext->QueryInterface(IID_IHXErrorMessages, (void**) &m_pErrorMessages); // Create a PXCallback object HX_RELEASE(m_pCallback); m_pCallback = new PXCallback(); if (m_pCallback) { // AddRef the object m_pCallback->AddRef(); // Init the callback object retVal = m_pCallback->Init(m_pContext, this); if (SUCCEEDED(retVal)) { // Create the IHXValues object HX_RELEASE(m_pValues); m_pCommonClassFactory->CreateInstance(CLSID_IHXValues, (void**) &m_pValues); } } else { retVal = HXR_OUTOFMEMORY; } } } } return retVal;}STDMETHODIMP CGIFRenderer::GetRendererInfo(REF(const char **) rppszStreamMimeType, REF(UINT32) rulInitialGranularity){ rppszStreamMimeType = (const char**) m_ppszStreamMimeType; rulInitialGranularity = 1000; return HXR_OK;}STDMETHODIMP CGIFRenderer::StartStream(IHXStream* pStream, IHXPlayer* pPlayer){ HX_RESULT retVal = HXR_OK; if (pStream && pPlayer) { // Save a copy of the stream HX_RELEASE(m_pStream); m_pStream = pStream; m_pStream->AddRef(); // Create a PXClientAdviseSink object HX_RELEASE(m_pClientAdviseSink); m_pClientAdviseSink = new PXClientAdviseSink(); if (m_pClientAdviseSink) { // AddRef the object m_pClientAdviseSink->AddRef(); // Init the object - this registers this renderer // as a client advise sink retVal = m_pClientAdviseSink->Init(pPlayer, (PXClientAdviseSinkResponse*) this); } else { retVal = HXR_OUTOFMEMORY; }#if defined(HELIX_FEATURE_MISU) if (SUCCEEDED(retVal)) { // Create a IHXMultiInstanceSiteUserSupplier interface HX_RELEASE(m_pMISUS); retVal = m_pCommonClassFactory->CreateInstance(CLSID_IHXMultiInstanceSiteUserSupplier, (void**) &m_pMISUS); if (SUCCEEDED(retVal)) { // Register ourselves as a site user retVal = m_pMISUS->SetSingleSiteUser((IUnknown*) (IHXSiteUser*) this); } }#endif } else { retVal = HXR_FAIL; } return retVal;}STDMETHODIMP CGIFRenderer::OnHeader(IHXValues *pStreamHeaderObj){ // Check for input error if (pStreamHeaderObj == NULL) { return HXR_FAIL; } // Get content version from header UINT32 ulIncomingContentVersion; HX_RESULT retVal = pStreamHeaderObj->GetPropertyULONG32("ContentVersion", ulIncomingContentVersion); if (retVal != HXR_OK) { return HXR_FAIL; } // Get stream version from header UINT32 ulIncomingStreamVersion; retVal = pStreamHeaderObj->GetPropertyULONG32("StreamVersion", ulIncomingStreamVersion); if (retVal != HXR_OK) { return HXR_FAIL; } // Check the versions if (ulIncomingContentVersion > m_ulHighestSupportedContentVersion || ulIncomingStreamVersion > m_ulHighestSupportedStreamVersion) { // Add to AU collection AddToAutoUpgradeCollection(m_ppszStreamMimeType[2], m_pContext); // Now we return an error, any error actually return HXR_NO_RENDERER; } // Get the opaque data from the stream header IHXBuffer *pBuffer = NULL; retVal = pStreamHeaderObj->GetPropertyBuffer("OpaqueData", pBuffer); if (retVal != HXR_OK) { return retVal; } // Unpack some info BYTE *pData = pBuffer->GetBuffer(); UnPack8(pData, m_ucTarget); // These are no longer used by the renderer they are parsed in the new hypernavigate object in the core so all renderer // commands are consistent and parsed in one place. We do have to skip over them since the file format still puts them in.// UnPack8(pData, m_ucURLType);// UnPack32(pData, m_ulSeekTime); pData += 5; // Even though the 2 above members were removed we still need to increment the data pointer // Note that we don't get the alpha from the background color // in the opaque part of the stream header - we get that from // the "bgOpacity" CString property in the stream header BYTE ucBgRed = pData[0]; BYTE ucBgGreen = pData[1]; BYTE ucBgBlue = pData[2]; m_ulBackgroundColor = (ucBgRed << 16) | (ucBgGreen << 8) | ucBgBlue; pData += 4; UnPackString(pData, m_cURL); // Get the current URL IHXStreamSource* pStreamSource = NULL; retVal = m_pStream->GetSource(pStreamSource); if (retVal != HXR_OK || !pStreamSource) { HX_RELEASE(pBuffer); return HXR_FAIL; } const char* pszURL = pStreamSource->GetURL(); if (!pszURL) { HX_RELEASE(pBuffer); HX_RELEASE(pStreamSource); return HXR_FAIL; } CHXString cOriginalURL = pszURL; HX_RELEASE(pStreamSource); // Check the URL to see if it's relative if (m_cURL.length() > 0) { if (m_ucTarget == kTargetPlayer) { if (IsURLRelative(m_cURL.c_str()) && !strstr(m_cURL.c_str(), "command:")) { CHXString cRelURL(m_cURL.c_str()); CHXString cAbsURL; retVal = MakeAbsoluteURL(cOriginalURL, cRelURL, cAbsURL); if (retVal == HXR_OK) { m_cURL = (const char *) cAbsURL; } } } } // Get the renderer flags property m_ulRendererFlags = 0; pStreamHeaderObj->GetPropertyULONG32("RendererFlags", m_ulRendererFlags); // Check bit 0 to see if parsing failed m_ulWidth = 0; m_ulHeight = 0; UINT32 ulBytesUsed = 0; if (m_ulRendererFlags & GIF_RENDERER_FLAG_PARSEFAILED) { // Get the width and height from the stream header pStreamHeaderObj->GetPropertyULONG32("Width", m_ulWidth); pStreamHeaderObj->GetPropertyULONG32("Height", m_ulHeight); if (!m_ulWidth || !m_ulHeight) { m_ulWidth = 48; m_ulHeight = 48; m_bNoNativeSize = TRUE; } } else { // Create a CGIFCodec HX_DELETE(m_pGIFCodec); m_pGIFCodec = new CGIFCodec(); if (!m_pGIFCodec) { HX_RELEASE(pBuffer); return HXR_OUTOFMEMORY; } // Initialize the CGIFCodec for decompression ulBytesUsed = pData - pBuffer->GetBuffer(); retVal = m_pGIFCodec->InitDecompress(pData, pBuffer->GetSize() - ulBytesUsed); if (retVal != HXR_OK) { HX_RELEASE(pBuffer); HX_DELETE(m_pGIFCodec); return retVal; } // Set the width and height m_ulWidth = m_pGIFCodec->GetLogicalScreenWidth(); m_ulHeight = m_pGIFCodec->GetLogicalScreenHeight(); } // Get the mediaRepeat string IHXBuffer* pMediaRepeatStr = NULL; pStreamHeaderObj->GetPropertyCString("mediaRepeat", pMediaRepeatStr); if (pMediaRepeatStr) { if (!strcmp((const char*) pMediaRepeatStr->GetBuffer(), "strip")) { m_bPreserveMediaRepeat = FALSE; } } HX_RELEASE(pMediaRepeatStr); // Save the stream header's opaque buffer HX_RELEASE(m_pStreamHeaderBuffer); m_pStreamHeaderBuffer = pBuffer; m_pStreamHeaderBuffer->AddRef(); // Init the stream header buffer offset m_ulStreamHeaderOffset = ulBytesUsed; // Now we can release the IHXBuffer HX_RELEASE(pBuffer); // Create an output buffer HX_RELEASE(m_pOutputBuffer); retVal = m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer, (void **) &m_pOutputBuffer); if (retVal != HXR_OK) { HX_DELETE(m_pGIFCodec); return retVal; } // Compute the size of the output buffer m_ulDataWidth = m_ulWidth * m_ulBytesPerPixel; m_ulPadWidth = (m_ulDataWidth + 3) & ~3; // This rounds up to nearest multiple of 4 UINT32 ulNumBytes = m_ulPadWidth * m_ulHeight; // Set the size of the output buffer retVal = m_pOutputBuffer->SetSize(ulNumBytes); if (retVal != HXR_OK) { HX_DELETE(m_pGIFCodec); HX_RELEASE(m_pOutputBuffer); return retVal; } // Initially draw the background color into the display buffer DrawBackgroundColor(); // Initialize the rendering members m_ulCurImg = 0; m_ulCurImgRenderTime = 0; m_ulCurDelayTime = 0; m_lLastImg = -1; // Initialize the loop done count m_ulLoopsDone = 0; // Clear the ignore packets flag m_bIgnorePackets = FALSE; // Set the first time sync flag m_bFirstTimeSync = TRUE; // If the parsing failed, then fill in the image with a bomb image if (m_ulRendererFlags & GIF_RENDERER_FLAG_PARSEFAILED) { CopyBombImage(); } else { // Send some debug info MLOG_MISC(m_pErrorMessages, "0x%08x::OnHeader() w=%lu h=%lu loopcount=%lu\n", this, m_pGIFCodec->GetLogicalScreenWidth(), m_pGIFCodec->GetLogicalScreenHeight(), m_pGIFCodec->GetLoopCount()); } // Get the duration pStreamHeaderObj->GetPropertyULONG32("Duration", m_ulEndTime); return HXR_OK;}STDMETHODIMP CGIFRenderer::OnBegin(UINT32 ulTimeAfterBegin){ MLOG_MISC(m_pErrorMessages, "%lu OnBegin(%lu) this=0x%08x\n", HX_GET_BETTERTICKCOUNT(), ulTimeAfterBegin, this); return HXR_OK;}STDMETHODIMP CGIFRenderer::GetDisplayType(REF(HX_DISPLAY_TYPE) rDisplayType, REF(IHXBuffer *) rpDisplayInfo){ rDisplayType = HX_DISPLAY_WINDOW | HX_DISPLAY_SUPPORTS_RESIZE | HX_DISPLAY_SUPPORTS_FULLSCREEN; return HXR_OK;}STDMETHODIMP CGIFRenderer::OnPacket(IHXPacket *pPacket, INT32 lTimeOffset){ MLOG_MISC(m_pErrorMessages, "%lu OnPacket(,%ld) this=0x%08x\n", HX_GET_BETTERTICKCOUNT(), lTimeOffset, this); // Check for input error if (pPacket == NULL) { return HXR_INVALID_PARAMETER; } // Save the time offset m_lTimeOffset = lTimeOffset; // If we are in between OnPreSeek() and OnPostSeek(), we will ignore // packets if (m_bIgnorePackets || m_bImageBombed) { return HXR_OK; } // Check if the packet is lost if (pPacket->IsLost()) { m_pGIFCodec->PacketLost(); return HXR_OK; } // Get the IHXBuffer from the packet IHXBuffer *pBuffer = pPacket->GetBuffer(); if (pBuffer == NULL) { return HXR_INVALID_PARAMETER; } BYTE* pData = pBuffer->GetBuffer(); UINT32 ulDataSize = pBuffer->GetSize();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -