📄 pxgifff.cpp
字号:
STDMETHODIMP CGIFFileFormat::CloseDone(HX_RESULT status){ return HXR_OK;}STDMETHODIMP CGIFFileFormat::WriteDone(HX_RESULT status){ return HXR_UNEXPECTED;}void CGIFFileFormat::ReportError(UINT32 ulErrorID, const char* pszArg){ // Try to get the string from the resource manager BYTE ucSeverity = HXLOG_CRIT; HX_RESULT lRMACode = HXR_FAIL; CHXString cErrStr; HX_RESULT retVal = GetResourceErrorString(ulErrorID, cErrStr); if (retVal != HXR_OK) { switch (ulErrorID) { case IDS_ERR_GIF_BADBITRATE: cErrStr = ERRSTR_GIF_BADBITRATE; break; case IDS_ERR_GIF_BADDURATION: cErrStr = ERRSTR_GIF_BADDURATION; break; case IDS_ERR_GIF_BADPREROLL: cErrStr = ERRSTR_GIF_BADPREROLL; break; case IDS_ERR_GIF_BADURL: cErrStr = ERRSTR_GIF_BADURL; break; case IDS_ERR_GIF_BADTARGET: cErrStr = ERRSTR_GIF_BADTARGET; break; case IDS_ERR_GIF_BADBGCOLOR: cErrStr = ERRSTR_GIF_BADBGCOLOR; break; case IDS_ERR_GIF_BADRELFLAG: cErrStr = ERRSTR_GIF_BADRELFLAG; break; case IDS_ERR_GIF_BITRATEZERO: cErrStr = ERRSTR_GIF_BITRATEZERO; break; case IDS_ERR_GIF_ILLEGALTARGET: cErrStr = ERRSTR_GIF_ILLEGALTARGET; break; case IDS_ERR_GIF_BADTIMEFORMAT: cErrStr = ERRSTR_GIF_BADTIMEFORMAT; break; case IDS_ERR_GIF_UNKPLAYERCOMMAND: cErrStr = ERRSTR_GIF_UNKPLAYERCOMMAND; break; case IDS_ERR_GIF_NOTARGETBROWSER: cErrStr = ERRSTR_GIF_NOTARGETBROWSER; break; case IDS_ERR_GIF_CORRUPTFILE: cErrStr = ERRSTR_GIF_CORRUPTFILE; break; default: cErrStr = ERRSTR_GIF_GENERALERROR; break; } } if (ulErrorID == IDS_ERR_GIF_CORRUPTFILE) { if (pszArg) { char* pszStr = new char [strlen((const char*) cErrStr) + strlen(pszArg) + 1]; if (pszStr) { sprintf(pszStr, (const char*) cErrStr, pszArg); /* Flawfinder: ignore */ cErrStr = pszStr; } HX_VECTOR_DELETE(pszStr); ucSeverity = HXLOG_DEBUG; lRMACode = HXR_OK; } } if (m_pError) { m_pError->Report(ucSeverity, lRMACode, 0, (const char*) cErrStr, NULL); }}HX_RESULT CGIFFileFormat::GetResourceErrorString(UINT32 ulErrorID, CHXString& rErrorStr){ IHXExternalResourceManager* pResMgr = NULL; HX_RESULT retVal = m_pContext->QueryInterface(IID_IHXExternalResourceManager, (void**) &pResMgr); if (retVal != HXR_OK) { return retVal; } IHXExternalResourceReader* pResRdr = NULL; retVal = pResMgr->CreateExternalResourceReader(CORE_RESOURCE_SHORT_NAME, pResRdr); if (retVal != HXR_OK) { HX_RELEASE(pResMgr); return retVal; }#ifdef _WINDOWS char szDLLPath[1024]; /* Flawfinder: ignore */ GetModuleFileName((HMODULE)g_hInstance, szDLLPath, sizeof(szDLLPath)); pResRdr->SetDefaultResourceFile(szDLLPath);#endif IHXXResource* pRes = pResRdr->GetResource(HX_RT_STRING, ulErrorID); if(!pRes) { HX_RELEASE(pResRdr); HX_RELEASE(pResMgr); return HXR_FAIL; } // Assign the error string to the out parameter rErrorStr = (const char*) pRes->ResourceData(); // Release all references HX_RELEASE(pRes); HX_RELEASE(pResRdr); HX_RELEASE(pResMgr); return HXR_OK;}HX_RESULT CGIFFileFormat::ParseFile(){ HX_RESULT retVal = HXR_OK; if (m_pFileObject && m_pFragFileBuffer) { // We don't need the file object anymore HX_RELEASE(m_pFileObject); // We need to get an IHXBuffer interface from the IHXFragmentedBuffer HX_RELEASE(m_pFileBuffer); retVal = m_pFragFileBuffer->QueryInterface(IID_IHXBuffer, (void**) &m_pFileBuffer); if (SUCCEEDED(retVal)) { // Get the buffer (this causes the initial gather) BYTE* pBuf = m_pFileBuffer->GetBuffer(); if (pBuf) { // Get the size UINT32 ulBufSize = m_pFileBuffer->GetSize(); // Now we allocate a CGIFCodec HX_DELETE(m_pGIFCodec); m_pGIFCodec = new CGIFCodec(); if (m_pGIFCodec) { // Initialize the wire format - this verifies this is a GIF // and sets up for parsing retVal = m_pGIFCodec->InitParseWireFormat(pBuf, ulBufSize); } else { retVal = HXR_OUTOFMEMORY; } } else { retVal = HXR_FAIL; } } HX_RELEASE(m_pFragFileBuffer); } else { retVal = HXR_UNEXPECTED; } return retVal;}HX_RESULT CGIFFileFormat::MakeAllPackets(){ HX_RESULT retVal = HXR_OK; // We don't know how many packets we'll have up front, so we'll put // them on a list and move them to an array when we're done. CHXSimpleList* pList = new CHXSimpleList(); if (pList) { // Loop through the packets while (SUCCEEDED(retVal) && !m_pGIFCodec->ParseFinished()) { // Ask the CGIF Codec for the next size UINT32 ulLength = 0; retVal = m_pGIFCodec->GetPacketBufferLength(ulLength); if (SUCCEEDED(retVal)) { // Create buffer to hold the packet IHXBuffer* pBuffer = NULL; retVal = m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer, (void**) &pBuffer); if (SUCCEEDED(retVal)) { // Set the size of the IHXBuffer retVal = pBuffer->SetSize(ulLength + 4); // Extra 4 is for flags if (SUCCEEDED(retVal)) { // Get the packet from the CGIFCodec BOOL bFirstInImage = FALSE; retVal = m_pGIFCodec->GetPacketBuffer(pBuffer->GetBuffer() + 4, pBuffer->GetSize() - 4, bFirstInImage); if (SUCCEEDED(retVal)) { // If this is a new image (and not the very first image), then update // the current image index and the start time if (bFirstInImage) { m_lCurImgIndex++; if (m_lCurImgIndex >= 0 && m_lCurImgIndex < (INT32) m_pGIFCodec->GetNumImages()) { m_lCurrentTime = m_plImageStartTime[m_lCurImgIndex]; } else { retVal = HXR_UNEXPECTED; } } if (SUCCEEDED(retVal)) { // Set the flags UINT32 ulFlags = 0; if (bFirstInImage) { ulFlags |= 0x01; } // Put the flags into the packet BYTE *pBuf = pBuffer->GetBuffer(); Pack32(pBuf, ulFlags); // Create an IHXPacket IHXPacket* pPacket = NULL; retVal = m_pCommonClassFactory->CreateInstance(CLSID_IHXPacket, (void**) &pPacket); if (SUCCEEDED(retVal)) { INT32 lTimeStamp = m_lCurrentTime; if (lTimeStamp < 0) { lTimeStamp = 0; } // Fill in the Packet with the relevant data // XXX-MEH // This is a result of a client core bug which causes // the core not to deliver timestamps which are past the duration // of the stream. Specifically, it's causing animated GIFs whose // duration is set artificially low not to receive all their // packets. As a workaround, we set all GIF packet timestamps to 0. retVal = pPacket->Set(pBuffer, // the actual data from the file 0, // timestamp 0, // our stream number (always 0) HX_ASM_SWITCH_ON, // yes, we are using ASM (sort of) 0); // always rule 0 if (SUCCEEDED(retVal)) { // Update the current timestamp m_lCurrentTime += ((pBuffer->GetSize() + 24) * 8000 / m_ulBitRate) + 1; // AddRef the packet before putting it on the list pPacket->AddRef(); // Put this packet onto the tail of the list pList->AddTail((void*) pPacket); } } HX_RELEASE(pPacket); } } } } HX_RELEASE(pBuffer); } } } else { retVal = HXR_OUTOFMEMORY; } // Terminate the parsing m_pGIFCodec->TermParse(); // Now we can release the GIF codec HX_DELETE(m_pGIFCodec); // Release the file buffer HX_RELEASE(m_pFileBuffer); if (SUCCEEDED(retVal)) { // Clear out any existing packets 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); } // Allocate the array m_ulNumPackets = pList->GetCount(); m_ppPacket = new IHXPacket* [m_ulNumPackets]; if (m_ppPacket) { // Run through the list, transferring packet pointers to the array UINT32 i = 0; LISTPOSITION pos = pList->GetHeadPosition(); while (pos) { // No need to AddRef()/Release() since we know there's only one ref IHXPacket* pPacket = (IHXPacket*) pList->GetNext(pos); m_ppPacket[i++] = pPacket; } // Now we can clear out the list pList->RemoveAll(); // Reset the current packet index m_ulCurrentPacketIndex = 0; } else { retVal = HXR_OUTOFMEMORY; } } // Now we can delete the list HX_DELETE(pList); return retVal;}/************************************************************************ * Method: * IHXThreadSafeMethods::IsThreadSafe */STDMETHODIMP_(UINT32)CGIFFileFormat::IsThreadSafe(){ return HX_THREADSAFE_METHOD_FF_GETPACKET | HX_THREADSAFE_METHOD_FSR_READDONE;}HX_RESULT STDAPICALLTYPE CGIFFileFormat::HXCreateInstance(IUnknown** ppIUnknown){ HX_RESULT retVal = HXR_OK; if (ppIUnknown) { // Set default *ppIUnknown = NULL; // Create the object CGIFFileFormat* pObj = new CGIFFileFormat(); if (pObj) { // QI for IUnknown retVal = pObj->QueryInterface(IID_IUnknown, (void**) ppIUnknown); } else { retVal = HXR_OUTOFMEMORY; } if (FAILED(retVal)) { HX_DELETE(pObj); } } else { retVal = HXR_FAIL; } return HXR_OK;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -