📄 pxgifff.cpp
字号:
HX_VECTOR_DELETE(m_plImageStartTime); m_plImageStartTime = new INT32 [lNumImages]; if (!m_plImageStartTime) { return m_pFormatResponse->StreamHeaderReady(HXR_FAIL, NULL); } // Initially we fill these times with the time the image has to be displayed INT32 i; INT32 lRunningSum = 0; for (i = 0; i < lNumImages; i++) { m_plImageStartTime[i] = lRunningSum; lRunningSum += (INT32) m_pGIFCodec->GetDelayTime(i) * 10; } // Now we go from last image to first, adjusting times UINT32 ulTotalBytesToSend = 0; INT32 lLastStartTime = m_plImageStartTime[lNumImages - 1]; for (i = m_pGIFCodec->GetNumImages() - 1; i >= 0; i--) { INT32 lTransmitSize = m_pGIFCodec->GetImageDataSize(i); // Actual bytes to transmit INT32 lOverheadSize = ((lTransmitSize / 500) + 1) * 24; // This is an estimate of packet overhead INT32 lTransmitTime = ((lTransmitSize + lOverheadSize) * 8000 / m_ulBitRate) + 1; // transmit time in milliseconds if (lLastStartTime < m_plImageStartTime[i]) { m_plImageStartTime[i] = lLastStartTime - lTransmitTime; } else { m_plImageStartTime[i] -= lTransmitTime; } lLastStartTime = m_plImageStartTime[i]; ulTotalBytesToSend += (UINT32) lTransmitSize; } // Now the min preroll should be the negative of the first start time if (m_plImageStartTime[0] >= 0) { return m_pFormatResponse->StreamHeaderReady(HXR_FAIL, NULL); } UINT32 ulMinPreroll = (UINT32) -m_plImageStartTime[0]; // Resolve this with the requested preroll if (m_ulPreroll < ulMinPreroll) { m_ulPreroll = ulMinPreroll; } // Compute predata bytes ulPreDataBytes = m_ulBitRate * m_ulPreroll / 8000; if (ulPreDataBytes > ulTotalBytesToSend) { ulPreDataBytes = ulTotalBytesToSend; } } // Create an IHXValues object IHXValues *pStreamHeader = NULL; HX_RESULT retVal = m_pCommonClassFactory->CreateInstance(CLSID_IHXValues, (void **) &pStreamHeader); if (retVal != HXR_OK) { return m_pFormatResponse->StreamHeaderReady(retVal, NULL); } // Set the mime type char* pszStreamMimeType = (char*) m_pszStreamMimeType; if (m_bParseFailed) { pszStreamMimeType = (char*) m_pszBadStreamMimeType; } // Create buffer to hold MIME type IHXBuffer *pMimeType = NULL; retVal = PXUtilities::CreateStringBuffer(pszStreamMimeType, m_pContext, pMimeType); if (retVal != HXR_OK) { HX_RELEASE(pStreamHeader); return m_pFormatResponse->StreamHeaderReady(retVal, NULL); } // Generate an ASM rule book char szASMRuleBook[256]; /* Flawfinder: ignore */ if (m_bReliable) { sprintf(szASMRuleBook, "AverageBandwidth=%ld,Priority=10;", m_ulBitRate); /* Flawfinder: ignore */ } else { sprintf(szASMRuleBook, /* Flawfinder: ignore */ "AverageBandwidth=%ld,Priority=5;AverageBandwidth=%ld,Priority=9;", m_ulBitRate, 0); } // Create buffer to hold ASM rules IHXBuffer *pASMRuleBook = NULL; retVal = PXUtilities::CreateStringBuffer((const char*) szASMRuleBook, m_pContext, pASMRuleBook); if (retVal != HXR_OK) { HX_RELEASE(pStreamHeader); HX_RELEASE(pMimeType); return m_pFormatResponse->StreamHeaderReady(retVal, NULL); } // Create buffer to hold intrinsic duration type string const char* pszIntrinsicDur = NULL; if (m_pGIFCodec->GetNumImages() == 1 && m_pGIFCodec->GetDelayTimeSum() == 0) { pszIntrinsicDur = "intrinsicDurationDiscrete"; } else { pszIntrinsicDur = "intrinsicDurationContinuous"; } IHXBuffer* pIntrinsicDur = NULL; retVal = PXUtilities::CreateStringBuffer(pszIntrinsicDur, m_pContext, pIntrinsicDur); if (retVal != HXR_OK) { HX_RELEASE(pStreamHeader); HX_RELEASE(pMimeType); HX_RELEASE(pASMRuleBook); return m_pFormatResponse->StreamHeaderReady(retVal, NULL); } // Create buffer to hold opaque data IHXBuffer *pOpaqueData = NULL; retVal = m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer, (void **) &pOpaqueData); if (retVal != HXR_OK) { HX_RELEASE(pStreamHeader); HX_RELEASE(pMimeType); HX_RELEASE(pASMRuleBook); HX_RELEASE(pIntrinsicDur); return m_pFormatResponse->StreamHeaderReady(retVal, NULL); } // Fill in the Header with the parameters pStreamHeader->SetPropertyULONG32("StreamNumber", 0); pStreamHeader->SetPropertyULONG32("MaxBitRate", m_ulBitRate); pStreamHeader->SetPropertyULONG32("AvgBitRate", m_ulBitRate); pStreamHeader->SetPropertyULONG32("MaxPacketSize", 600); pStreamHeader->SetPropertyULONG32("AvgPacketSize", 500); pStreamHeader->SetPropertyULONG32("StartTime", 0); pStreamHeader->SetPropertyULONG32("Preroll", m_ulPreroll); pStreamHeader->SetPropertyULONG32("PreData", ulPreDataBytes); pStreamHeader->SetPropertyULONG32("PreDataAtStart", 1); pStreamHeader->SetPropertyULONG32("PreRollAtStart", 0); pStreamHeader->SetPropertyULONG32("PreDataAfterSeek", 0); pStreamHeader->SetPropertyULONG32("PreRollAfterSeek", 1); pStreamHeader->SetPropertyULONG32("Duration", m_ulDuration); pStreamHeader->SetPropertyULONG32("ContentVersion", m_ulContentVersion); pStreamHeader->SetPropertyCString("MimeType", pMimeType); pStreamHeader->SetPropertyCString("ASMRuleBook", pASMRuleBook); pStreamHeader->SetPropertyCString("intrinsicDurationType", pIntrinsicDur); // The mediaRepeat attribute says whether or not to strip the native // repeat value from the media. We need support for mediaRepeat in // the GIF renderer for this to work. Therefore, if mediaRepeat specified, // then we also need to bump the stream version. UINT32 ulStreamVersion = m_ulStreamVersion; if (m_pMediaRepeatStr) { pStreamHeader->SetPropertyCString("mediaRepeat", m_pMediaRepeatStr); ulStreamVersion = MEDREP_GIFSTREAM_VERSION; } // Now set the stream version pStreamHeader->SetPropertyULONG32("StreamVersion", ulStreamVersion); // Make a renderer flags property UINT32 ulRendererFlags = 0; if (m_bParseFailed) { ulRendererFlags |= GIF_RENDERER_FLAG_PARSEFAILED; if (m_pGIFCodec) { pStreamHeader->SetPropertyULONG32("Width", m_pGIFCodec->GetLogicalScreenWidth()); pStreamHeader->SetPropertyULONG32("Height", m_pGIFCodec->GetLogicalScreenHeight()); } } pStreamHeader->SetPropertyULONG32("RendererFlags", ulRendererFlags); // Ask the GIF Codec how big the header is UINT32 ulLength = 0; if (m_pGIFCodec && !m_bParseFailed) { retVal = m_pGIFCodec->GetPacketBufferLength(ulLength); if (retVal != HXR_OK) { HX_RELEASE(pMimeType); HX_RELEASE(pASMRuleBook); HX_RELEASE(pOpaqueData); HX_RELEASE(pStreamHeader); HX_RELEASE(pIntrinsicDur); return m_pFormatResponse->StreamHeaderReady(retVal, NULL); } } // Set the opaque data buffer to this length plus a bit more UINT32 ulExtraDataSize = 12 + (m_pURL ? m_pURL->GetLength() : 0) + 1; retVal = pOpaqueData->SetSize(ulLength + ulExtraDataSize); if (retVal != HXR_OK) { HX_RELEASE(pMimeType); HX_RELEASE(pASMRuleBook); HX_RELEASE(pOpaqueData); HX_RELEASE(pStreamHeader); HX_RELEASE(pIntrinsicDur); return m_pFormatResponse->StreamHeaderReady(retVal, NULL); } // Fill in the non-image-data information BYTE *pData = pOpaqueData->GetBuffer(); Pack8(pData, m_ucTarget); Pack8(pData, m_ucURLType); Pack32(pData, m_ulSeekTime); Pack8(pData, (BYTE) ((m_ulBackgroundColor & 0x00FF0000) >> 16)); // R Pack8(pData, (BYTE) ((m_ulBackgroundColor & 0x0000FF00) >> 8)); // G Pack8(pData, (BYTE) (m_ulBackgroundColor & 0x000000FF) ); // B Pack8(pData, (BYTE) ((m_ulBackgroundColor & 0xFF000000) >> 24)); // A CHXString cTmp; if (m_pURL) { cTmp = *m_pURL; } PackString(pData, cTmp); if (m_pGIFCodec && !m_bParseFailed) { // Get the opaque data BOOL bFirstInImage = FALSE; retVal = m_pGIFCodec->GetPacketBuffer(pData, pOpaqueData->GetSize() - ulExtraDataSize, bFirstInImage); if (retVal != HXR_OK) { HX_RELEASE(pMimeType); HX_RELEASE(pASMRuleBook); HX_RELEASE(pOpaqueData); HX_RELEASE(pStreamHeader); HX_RELEASE(pIntrinsicDur); return m_pFormatResponse->StreamHeaderReady(retVal, NULL); } } // Set the opaque data buffer property pStreamHeader->SetPropertyBuffer("OpaqueData", pOpaqueData); // Set the new state m_ulState = kStateStreamHeaderSent; // Initialize the current image index m_lCurImgIndex = -1; if (m_pGIFCodec && !m_bParseFailed) { // Go ahead and collect all the packets and hold them. We do // this since if we get a Seek(), we'll need to completely // resend all the packets. Ugh. retVal = MakeAllPackets(); if (retVal != HXR_OK) { HX_RELEASE(pMimeType); HX_RELEASE(pASMRuleBook); HX_RELEASE(pOpaqueData); HX_RELEASE(pStreamHeader); HX_RELEASE(pIntrinsicDur); return m_pFormatResponse->StreamHeaderReady(retVal, NULL); } } // Now we can tell the response interface that we're done m_pFormatResponse->StreamHeaderReady(HXR_OK, pStreamHeader); // Release our references HX_RELEASE(pStreamHeader); HX_RELEASE(pMimeType); HX_RELEASE(pASMRuleBook); HX_RELEASE(pOpaqueData); HX_RELEASE(pIntrinsicDur); return HXR_OK;}STDMETHODIMP CGIFFileFormat::GetPacket(UINT16 usStreamNum){#ifdef XXXMEH_DEBUG_LOG DEBUG_OUTF("pxgifff.log", (s, "0x%08x::GetPacket(%u)\n", this, usStreamNum));#endif HX_RESULT retVal = HXR_OK; if (m_ulState == kStateStreamHeaderSent) { if (usStreamNum == 0) { // Have we sent all the packets? if (m_ulCurrentPacketIndex < m_ulNumPackets && !m_bParseFailed) { // Get the packet pointer IHXPacket* pPacket = m_ppPacket[m_ulCurrentPacketIndex]; // Increment the packet index m_ulCurrentPacketIndex++; // Give the response interface the packet m_pFormatResponse->PacketReady(HXR_OK, pPacket); } else { // Set the state m_ulState = kStateFinished; // Tell the response interface we're done m_pFormatResponse->StreamDone(0); } } else { retVal = HXR_INVALID_PARAMETER; } } else { retVal = HXR_UNEXPECTED; } return retVal;}STDMETHODIMP CGIFFileFormat::SeekDone(HX_RESULT status){ return HXR_UNEXPECTED;}STDMETHODIMP CGIFFileFormat::Seek(UINT32 ulRequestedTime){ HX_RESULT retVal = HXR_OK; // XXXMEH - no matter WHEN we get a Seek(), we have to resend all the // packets again, since they are all timestamp 0. // // So all we need to do is reset the current packet index to 0. m_ulCurrentPacketIndex = 0; // Set the state m_ulState = kStateStreamHeaderSent; // Inform the response interface we're done m_pFormatResponse->SeekDone(HXR_OK); return retVal;}STDMETHODIMP CGIFFileFormat::Close(){ if (m_ppPacket && m_ulNumPackets) { for (UINT32 i = 0; i < m_ulNumPackets; i++) { HX_RELEASE(m_ppPacket[i]); } m_ulNumPackets = 0; HX_VECTOR_DELETE(m_ppPacket); } HX_RELEASE(m_pContext); HX_RELEASE(m_pFileObject); HX_RELEASE(m_pFileStat); HX_RELEASE(m_pFormatResponse); HX_RELEASE(m_pCommonClassFactory); HX_RELEASE(m_pError); HX_DELETE(m_pURL); HX_DELETE(m_pRequestURL); HX_RELEASE(m_pFileBuffer); HX_RELEASE(m_pFragFileBuffer); HX_DELETE(m_pGIFCodec); HX_VECTOR_DELETE(m_plImageStartTime); HX_RELEASE(m_pMediaRepeatStr); m_ulBitRate = 0; m_ulPreroll = 0; m_ulDuration = 0; m_lCurrentTime = 0; m_ulState = kStateConstructed; m_ulFileSize = 0; return HXR_OK;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -