pxgifff.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:52k
- /* ***** BEGIN LICENSE BLOCK *****
- * Source last modified: $Id: pxgifff.cpp,v 1.3.16.1 2004/07/09 01:54:22 hubbe Exp $
- *
- * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
- *
- * The contents of this file, and the files included with this file,
- * are subject to the current version of the RealNetworks Public
- * Source License (the "RPSL") available at
- * http://www.helixcommunity.org/content/rpsl unless you have licensed
- * the file under the current version of the RealNetworks Community
- * Source License (the "RCSL") available at
- * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
- * will apply. You may also obtain the license terms directly from
- * RealNetworks. You may not use this file except in compliance with
- * the RPSL or, if you have a valid RCSL with RealNetworks applicable
- * to this file, the RCSL. Please see the applicable RPSL or RCSL for
- * the rights, obligations and limitations governing use of the
- * contents of the file.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License Version 2 or later (the
- * "GPL") in which case the provisions of the GPL are applicable
- * instead of those above. If you wish to allow use of your version of
- * this file only under the terms of the GPL, and not to allow others
- * to use your version of this file under the terms of either the RPSL
- * or RCSL, indicate your decision by deleting the provisions above
- * and replace them with the notice and other provisions required by
- * the GPL. If you do not delete the provisions above, a recipient may
- * use your version of this file under the terms of any one of the
- * RPSL, the RCSL or the GPL.
- *
- * This file is part of the Helix DNA Technology. RealNetworks is the
- * developer of the Original Code and owns the copyrights in the
- * portions it created.
- *
- * This file, and the files included with this file, is distributed
- * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
- * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
- * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
- * ENJOYMENT OR NON-INFRINGEMENT.
- *
- * Technology Compatibility Kit Test Suite(s) Location:
- * http://www.helixcommunity.org/content/tck
- *
- * Contributor(s):
- *
- * ***** END LICENSE BLOCK ***** */
- // system
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- // include
- #include "hxtypes.h"
- #include "hxcom.h"
- #include "hxcomm.h"
- #include "ihxpckts.h"
- #include "hxfiles.h"
- #include "hxformt.h"
- #include "hxplugn.h"
- #include "hxver.h"
- #include "hxerror.h"
- #include "hxxres.h"
- #include "hxxrsmg.h"
- #include "ihxfgbuf.h"
- #include "hxvsrc.h"
- #include "hxengin.h"
- #ifdef _MACINTOSH
- #include <ctype.h>
- #endif
- // pncont
- #include "hxstring.h"
- #include "hxslist.h"
- #include "chxpckts.h"
- #include "chxfgbuf.h"
- // pnmisc
- #include "hxurl.h"
- #include "unkimp.h"
- #include "baseobj.h"
- #ifdef _AIX
- #include "dllpath.h"
- ENABLE_MULTILOAD_DLLACCESS_PATHS(Pxgifff);
- #endif
- // pxcomlib
- #include "gstring.h"
- #include "pxutil.h"
- #include "pxcolor.h"
- #include "parseurl.h"
- #include "buffutil.h"
- // pxgiflib
- #include "lzw.h"
- #include "gifimage.h"
- #include "gifcodec.h"
- // coreres
- #include "pixres.h"
- // pxgifff
- #if defined(HELIX_FEATURE_VIEWSOURCE)
- #include "gifvsrc.h"
- #endif /* #if defined(HELIX_FEATURE_VIEWSOURCE) */
- #include "pxgifff.h"
- #include "giffdll.ver"
- // pndebug
- #include "errdbg.h"
- #include "hxheap.h"
- #ifdef _DEBUG
- #undef HX_THIS_FILE
- static const char HX_THIS_FILE[] = __FILE__;
- #endif
- #define BASE_GIFSTREAM_VERSION HX_ENCODE_PROD_VERSION(0, 0, 0, 0)
- #define MEDREP_GIFSTREAM_VERSION HX_ENCODE_PROD_VERSION(0, 1, 0, 0)
- const char * const CGIFFileFormat::m_pszDescription = "Helix GIF File Format Plugin";
- const char * const CGIFFileFormat::m_pszCopyright = HXVER_COPYRIGHT;
- const char * const CGIFFileFormat::m_pszMoreInfoURL = HXVER_MOREINFO;
- const char * const CGIFFileFormat::m_ppszFileMimeTypes[] = {"image/gif", NULL};
- const char * const CGIFFileFormat::m_ppszFileExtensions[] = {"gif", NULL};
- const char * const CGIFFileFormat::m_ppszFileOpenNames[] = {"GIF File Format (*.gif)", NULL};
- const char * const CGIFFileFormat::m_pszStreamMimeType = "application/vnd.rn-gifstream2";
- const char * const CGIFFileFormat::m_pszBadStreamMimeType = "application/vnd.rn-gifstream3";
- const UINT32 CGIFFileFormat::m_ulContentVersion = HX_ENCODE_PROD_VERSION(0, 0, 0, 0);
- const UINT32 CGIFFileFormat::m_ulStreamVersion = BASE_GIFSTREAM_VERSION;
- #ifdef _WINDOWS
- extern HINSTANCE g_hInstance;
- #endif
- CGIFFileFormat::CGIFFileFormat()
- {
- m_lRefCount = 0;
- m_pContext = NULL;
- m_pFileObject = NULL;
- m_pFileStat = NULL;
- m_pFormatResponse = NULL;
- m_pCommonClassFactory = NULL;
- m_pError = NULL;
- m_ulBitRate = 0;
- m_ulPreroll = 0;
- m_ulDuration = 0;
- m_pURL = NULL;
- m_pRequestURL = NULL;
- m_ulSeekTime = 0;
- m_ucTarget = kTargetBrowser;
- m_ucURLType = kURLTypeNormal;
- m_lCurrentTime = 0;
- m_plImageStartTime = NULL;
- m_lCurImgIndex = 0;
- m_ulState = kStateConstructed;
- m_ulFileSize = 0;
- m_pGIFCodec = NULL;
- m_bReliable = FALSE;
- m_ulNumBytesRead = 0;
- m_pFileBuffer = NULL;
- m_pFragFileBuffer = NULL;
- m_ppPacket = NULL;
- m_ulNumPackets = 0;
- m_ulCurrentPacketIndex = 0;
- m_bParseFailed = FALSE;
- m_pMediaRepeatStr = NULL;
- }
- CGIFFileFormat::~CGIFFileFormat()
- {
- Close();
- }
- STDMETHODIMP CGIFFileFormat::QueryInterface(REFIID riid, void **ppvObj)
- {
- if (IsEqualIID(riid, IID_IUnknown))
- {
- AddRef();
- *ppvObj = (IUnknown *) (IHXPlugin *) this;
- return HXR_OK;
- }
- else if (IsEqualIID(riid, IID_IHXPlugin))
- {
- AddRef();
- *ppvObj = (IHXPlugin *) this;
- return HXR_OK;
- }
- else if (IsEqualIID(riid, IID_IHXFileFormatObject))
- {
- AddRef();
- *ppvObj = (IHXFileFormatObject *) this;
- return HXR_OK;
- }
- else if (IsEqualIID(riid, IID_IHXFileResponse))
- {
- AddRef();
- *ppvObj = (IHXFileResponse *) this;
- return HXR_OK;
- }
- else if (IsEqualIID(riid, IID_IHXFileStatResponse))
- {
- AddRef();
- *ppvObj = (IHXFileStatResponse *) this;
- return HXR_OK;
- }
- #if defined(HELIX_FEATURE_VIEWSOURCE)
- else if (IsEqualIID(riid, IID_IHXFileViewSource))
- {
- CGIFViewSource* pVsrc = new CGIFViewSource(m_pContext,
- (IUnknown*)(IHXPlugin*)this);
- if ( pVsrc == NULL )
- {
- return HXR_FAIL;
- }
- return pVsrc->QueryInterface(riid, ppvObj);
- }
- #endif /* #if defined(HELIX_FEATURE_VIEWSOURCE) */
- else if (IsEqualIID(riid, IID_IHXThreadSafeMethods))
- {
- AddRef();
- *ppvObj = (IHXThreadSafeMethods*)this;
- return HXR_OK;
- }
- *ppvObj = NULL;
- return HXR_NOINTERFACE;
- }
- STDMETHODIMP_(UINT32) CGIFFileFormat::AddRef()
- {
- return InterlockedIncrement(&m_lRefCount);
- }
- STDMETHODIMP_(UINT32) CGIFFileFormat::Release()
- {
- if (InterlockedDecrement(&m_lRefCount) > 0)
- {
- return m_lRefCount;
- }
- delete this;
- return 0;
- }
- STDMETHODIMP CGIFFileFormat::GetPluginInfo(REF(BOOL) bMultipleLoad,
- REF(const char*) pDescription,
- REF(const char*) pCopyright,
- REF(const char*) pMoreInfoURL,
- REF(ULONG32) ulVersionNumber)
- {
- bMultipleLoad = TRUE; // Must be true for file formats.
- pDescription = m_pszDescription;
- pCopyright = m_pszCopyright;
- pMoreInfoURL = m_pszMoreInfoURL;
- ulVersionNumber = TARVER_ULONG32_VERSION;
- return HXR_OK;
- }
- STDMETHODIMP CGIFFileFormat::GetFileFormatInfo(REF(const char **) rppszFileMimeTypes,
- REF(const char **) rppszFileExtensions,
- REF(const char **) rppszFileOpenNames)
- {
- rppszFileMimeTypes = (const char**) m_ppszFileMimeTypes;
- rppszFileExtensions = (const char**) m_ppszFileExtensions;
- rppszFileOpenNames = (const char**) m_ppszFileOpenNames;
- return HXR_OK;
- }
- STDMETHODIMP CGIFFileFormat::InitPlugin(IUnknown *pContext)
- {
- // Check for input error
- if (pContext == NULL)
- {
- return HXR_INVALID_PARAMETER;
- }
- // Save a copy of the context
- m_pContext = pContext;
- m_pContext->AddRef();
- // Get an IHXCommonClassFactory interface from the context
- HX_RELEASE(m_pCommonClassFactory);
- HX_RESULT retVal = m_pContext->QueryInterface(IID_IHXCommonClassFactory, (void **) &m_pCommonClassFactory);
- if (retVal != HXR_OK)
- {
- HX_RELEASE(m_pContext);
- return HXR_NOINTERFACE;
- }
- // Get the IHXErrorMessages interface
- // It's OK if TLC doesn't support it.
- HX_RELEASE(m_pError);
- m_pContext->QueryInterface(IID_IHXErrorMessages, (void **) &m_pError);
- return HXR_OK;
- }
- STDMETHODIMP CGIFFileFormat::InitFileFormat(IHXRequest *pRequest,
- IHXFormatResponse *pFormatResponse,
- IHXFileObject *pFileObject)
- {
- #ifdef XXXMEH_DEBUG_LOG
- const char* pszURLDbg = NULL;
- pRequest->GetURL(pszURLDbg);
- DEBUG_OUTF("pxgifff.log", (s, "0x%08x::InitFileFormat(): %sn", this, pszURLDbg));
- #endif
- // Check for input error
- if (pRequest == NULL || pFormatResponse == NULL || pFileObject == NULL)
- {
- return HXR_INVALID_PARAMETER;
- }
- // Check state
- if (m_ulState != kStateConstructed)
- {
- return HXR_UNEXPECTED;
- }
- // Save a copy of the IHXFormatResponse
- m_pFormatResponse = pFormatResponse;
- m_pFormatResponse->AddRef();
- // Get the URL string from the IHXRequest object
- const char *pszURL = NULL;
- HX_RESULT retVal = pRequest->GetURL(pszURL);
- if (retVal != HXR_OK)
- {
- return m_pFormatResponse->InitDone(retVal);
- }
- if (pszURL)
- {
- HX_DELETE(m_pRequestURL);
- m_pRequestURL = new CHXString(pszURL);
- }
- // Create an IHXValues object to hold the param name/value pairs
- IHXValues *pValues = NULL;
- retVal = m_pCommonClassFactory->CreateInstance(CLSID_IHXValues, (void**) &pValues);
- if (FAILED(retVal))
- {
- return m_pFormatResponse->InitDone(retVal);
- }
- // Now add the following parameters to the IHXValues. These
- // parameters could have come as URL-encoded parameters or as
- // parameters in the request headers. These parameters will be
- // added as CString properties to the IHXValues.
- AddURLOrRequestParam(pRequest, "bitrate", m_pContext, pValues);
- AddURLOrRequestParam(pRequest, "duration", m_pContext, pValues);
- AddURLOrRequestParam(pRequest, "preroll", m_pContext, pValues);
- AddURLOrRequestParam(pRequest, "url", m_pContext, pValues);
- AddURLOrRequestParam(pRequest, "target", m_pContext, pValues);
- AddURLOrRequestParam(pRequest, "bgcolor", m_pContext, pValues);
- AddURLOrRequestParam(pRequest, "reliable", m_pContext, pValues);
- AddURLOrRequestParam(pRequest, "mediaRepeat", m_pContext, pValues);
- // Set the bitrate
- retVal = ExtractValueUINT32(pValues, "bitrate", kDefaultBitRate, m_ulBitRate);
- if (retVal != HXR_OK)
- {
- HX_RELEASE(pValues);
- ReportError(IDS_ERR_GIF_BADBITRATE);
- return m_pFormatResponse->InitDone(retVal);
- }
- // Set the duration
- retVal = ExtractValueTime(pValues, "duration", kDefaultDuration, m_ulDuration);
- if (retVal != HXR_OK)
- {
- HX_RELEASE(pValues);
- ReportError(IDS_ERR_GIF_BADDURATION);
- return m_pFormatResponse->InitDone(retVal);
- }
- // Set the preroll
- retVal = ExtractValueTime(pValues, "preroll", 0, m_ulPreroll);
- if (retVal != HXR_OK)
- {
- HX_RELEASE(pValues);
- ReportError(IDS_ERR_GIF_BADPREROLL);
- return m_pFormatResponse->InitDone(retVal);
- }
- // Set the URL
- CHXString cTmp;
- retVal = ExtractValueString(pValues, "url", NULL, cTmp);
- if (retVal != HXR_OK)
- {
- HX_RELEASE(pValues);
- ReportError(IDS_ERR_GIF_BADURL);
- return m_pFormatResponse->InitDone(retVal);
- }
- if (cTmp.GetLength() > 0)
- {
- HX_DELETE(m_pURL);
- m_pURL = new CHXString((const char*) cTmp);
- }
- CHXString cTarget;
- retVal = ExtractValueString(pValues, "target", "_browser", cTarget);
- if (retVal != HXR_OK)
- {
- HX_RELEASE(pValues);
- ReportError(IDS_ERR_GIF_BADTARGET);
- return m_pFormatResponse->InitDone(retVal);
- }
- retVal = ExtractValueColor(pValues, "bgcolor", 0x00FFFFFF, m_ulBackgroundColor);
- if (retVal != HXR_OK)
- {
- HX_RELEASE(pValues);
- ReportError(IDS_ERR_GIF_BADBGCOLOR);
- return m_pFormatResponse->InitDone(retVal);
- }
- retVal = ExtractValueBOOL(pValues, "reliable", FALSE, m_bReliable);
- if (retVal != HXR_OK)
- {
- HX_RELEASE(pValues);
- ReportError(IDS_ERR_GIF_BADRELFLAG);
- return m_pFormatResponse->InitDone(retVal);
- }
- // Get the media repeat string
- pValues->GetPropertyCString("mediaRepeat", m_pMediaRepeatStr);
- // Release the IHXValues object
- HX_RELEASE(pValues);
- // Check url encoded bitrate
- if (!m_ulBitRate)
- {
- ReportError(IDS_ERR_GIF_BITRATEZERO);
- return m_pFormatResponse->InitDone(retVal);
- }
- // Check target string
- if (cTarget == "_player")
- {
- m_ucTarget = kTargetPlayer;
- }
- else if (cTarget == "_browser")
- {
- m_ucTarget = kTargetBrowser;
- }
- else
- {
- ReportError(IDS_ERR_GIF_ILLEGALTARGET);
- return m_pFormatResponse->InitDone(retVal);
- }
- // Set some defaults
- m_ucURLType = kURLTypeNormal;
- m_ulSeekTime = 0;
- // Check the URL if present
- if (m_pURL && m_pURL->GetLength() > 0)
- {
- // Check to see if it's a command
- if (m_pURL->Left(8) == "command:")
- {
- // Yes it is a command. Make sure it's either seek, pause, or play
- if (*m_pURL == "command:pause()")
- {
- m_ucURLType = kURLTypeCommandPause;
- }
- else if (*m_pURL == "command:play()")
- {
- m_ucURLType = kURLTypeCommandPlay;
- }
- else if (*m_pURL == "command:stop()")
- {
- m_ucURLType = kURLTypeCommandStop;
- }
- else if (m_pURL->Mid(8,5) == "seek(" &&
- m_pURL->Right(1) == ")")
- {
- m_ucURLType = kURLTypeCommandSeek;
- // Make sure there's a valid seek time
- CHXString cSeekStr = m_pURL->Mid(13, m_pURL->GetLength() - 14);
- BOOL bRet = ConvertTimeStringToULONG32((char*) (const char*) cSeekStr,
- cSeekStr.GetLength(),
- m_ulSeekTime);
- if (bRet == FALSE)
- {
- ReportError(IDS_ERR_GIF_BADTIMEFORMAT);
- return m_pFormatResponse->InitDone(retVal);
- }
- }
- else
- {
- ReportError(IDS_ERR_GIF_UNKPLAYERCOMMAND);
- return m_pFormatResponse->InitDone(retVal);
- }
- }
- }
- // Reconcile the URL and the target
- if (m_ucTarget == kTargetBrowser && m_ucURLType != kURLTypeNormal)
- {
- ReportError(IDS_ERR_GIF_NOTARGETBROWSER);
- return m_pFormatResponse->InitDone(retVal);
- }
- // Save a copy of the file object
- m_pFileObject = pFileObject;
- m_pFileObject->AddRef();
- // Set the new state
- m_ulState = kStateFileInit;
- // Init the file object - see InitDone for response
- return m_pFileObject->Init(HX_FILE_READ | HX_FILE_BINARY, this);
- }
- STDMETHODIMP CGIFFileFormat::InitDone(HX_RESULT status)
- {
- #ifdef XXXMEH_DEBUG_LOG
- DEBUG_OUTF("pxgifff.log", (s, "0x%08x::InitDone(0x%08x)n", this, status));
- #endif
- // Check state
- if (m_ulState != kStateFileInit)
- {
- return HXR_UNEXPECTED;
- }
- // Check for input error
- if (status != HXR_OK)
- {
- return m_pFormatResponse->InitDone(status);
- }
- // Now we must get the IHXFileStat interface from the IHXFileObject
- HX_RELEASE(m_pFileStat);
- HX_RESULT retVal = m_pFileObject->QueryInterface(IID_IHXFileStat, (void **) &m_pFileStat);
- if (retVal != HXR_OK)
- {
- return m_pFormatResponse->InitDone(retVal);
- }
- // Set the new state
- m_ulState = kStateFileStat;
- // Now we find out how big is the file
- return m_pFileStat->Stat(this);
- }
- STDMETHODIMP CGIFFileFormat::StatDone(HX_RESULT status, UINT32 ulSize, UINT32 ulCreationTime,
- UINT32 ulAccessTime, UINT32 ulModificationTime, UINT32 ulMode)
- {
- #ifdef XXXMEH_DEBUG_LOG
- DEBUG_OUTF("pxgifff.log", (s, "0x%08x::StatDone(0x%08x,%lu,,,,)n", this, status, ulSize));
- #endif
- HX_RESULT retVal = HXR_OK;
- if (m_ulState == kStateFileStat)
- {
- if (SUCCEEDED(status))
- {
- // Set the file size
- m_ulFileSize = ulSize;
- // Now we no longer need the IHXFileStat interface
- HX_RELEASE(m_pFileStat);
- // Create an IHXFragmentedBuffer to hold the file
- CHXFragmentedBuffer* pTmp = NULL;
- retVal = CHXFragmentedBuffer::CreateObject(&pTmp);
- if (SUCCEEDED(retVal))
- {
- HX_RELEASE(m_pFragFileBuffer);
- retVal = pTmp->QueryInterface(IID_IHXFragmentedBuffer, (void**) &m_pFragFileBuffer);
- if (SUCCEEDED(retVal))
- {
- // Set the new state
- m_ulState = kStateFileRead;
- // Clear the bytes read counter
- m_ulNumBytesRead = 0;
- // Now we read, 2k at a time
- retVal = m_pFileObject->Read(2048);
- }
- else
- {
- retVal = m_pFormatResponse->InitDone(retVal);
- }
- }
- else
- {
- retVal = m_pFormatResponse->InitDone(retVal);
- }
- }
- else
- {
- retVal = m_pFormatResponse->InitDone(status);
- }
- }
- else
- {
- retVal = HXR_UNEXPECTED;
- }
- return retVal;
- }
- STDMETHODIMP CGIFFileFormat::ReadDone(HX_RESULT status, IHXBuffer *pBuffer)
- {
- #ifdef XXXMEH_DEBUG_LOG
- UINT32 ulSize = (SUCCEEDED(status) && pBuffer ? pBuffer->GetSize() : 0);
- DEBUG_OUTF("pxgifff.log", (s, "0x%08x::ReadDone(0x%08x,0x%08x): pBuffer->GetSize() = %lun",
- this, status, pBuffer, ulSize));
- #endif
- HX_RESULT retVal = HXR_OK;
- if (m_ulState == kStateFileRead)
- {
- if (SUCCEEDED(status))
- {
- // Append the buffer to the fragmented buffer
- retVal = m_pFragFileBuffer->Append(pBuffer, 0, pBuffer->GetSize());
- if (SUCCEEDED(retVal))
- {
- // Update the number of bytes read
- m_ulNumBytesRead += pBuffer->GetSize();
- // Have we read all we were supposed to?
- if (m_ulFileSize > 0 && m_ulNumBytesRead >= m_ulFileSize)
- {
- retVal = ParseFile();
- if (SUCCEEDED(retVal))
- {
- // Set the new state
- m_ulState = kStateInitialized;
- }
- else
- {
- m_bParseFailed = TRUE;
- const char* pszStr = (m_pRequestURL ? (const char*) *m_pRequestURL : NULL);
- ReportError(IDS_ERR_GIF_CORRUPTFILE, pszStr);
- retVal = HXR_OK;
- // Set the new state
- m_ulState = kStateInitialized;
- }
- // Tell the response interface we're ready
- retVal = m_pFormatResponse->InitDone(retVal);
- }
- else
- {
- // No, either we haven't read enough or we don't
- // know how big the file really is. Either way,
- // we need to do another read.
- retVal = m_pFileObject->Read(2048);
- }
- }
- }
- else
- {
- // We might have gotten here if we didn't know the file size
- // and we're reading until we got an error. Therefore, if
- // we're here AND we've read some bytes OK, then we'll try
- // parsing the file. If we have NOT read any bytes successfully,
- // then we'll fail
- //
- if (m_ulNumBytesRead > 0)
- {
- retVal = ParseFile();
- if (SUCCEEDED(retVal))
- {
- // Set the new state
- m_ulState = kStateInitialized;
- }
- else
- {
- m_bParseFailed = TRUE;
- const char* pszStr = (m_pRequestURL ? (const char*) *m_pRequestURL : NULL);
- ReportError(IDS_ERR_GIF_CORRUPTFILE, pszStr);
- retVal = HXR_OK;
- // Set the new state
- m_ulState = kStateInitialized;
- }
- }
- else
- {
- retVal = status;
- }
- retVal = m_pFormatResponse->InitDone(retVal);
- }
- }
- else
- {
- retVal = HXR_UNEXPECTED;
- }
- return retVal;
- }
- STDMETHODIMP CGIFFileFormat::GetFileHeader()
- {
- #ifdef XXXMEH_DEBUG_LOG
- DEBUG_OUTF("pxgifff.log", (s, "0x%08x::GetFileHeader()n", this));
- #endif
- // Check the state
- if (m_ulState != kStateInitialized)
- {
- return HXR_UNEXPECTED;
- }
- // Create an IHXValues object
- IHXValues *pHeader = NULL;
- HX_RESULT retVal = m_pCommonClassFactory->CreateInstance(CLSID_IHXValues, (void **) &pHeader);
- if (retVal != HXR_OK)
- {
- m_pFormatResponse->FileHeaderReady(retVal, NULL);
- }
- // Set the StreamCount propery - we always only have 1 stream
- pHeader->SetPropertyULONG32("StreamCount", 1);
- pHeader->SetPropertyULONG32("IsRealDataType", 1);
- // Set the width and height
- if (m_pGIFCodec)
- {
- pHeader->SetPropertyULONG32("Width", m_pGIFCodec->GetLogicalScreenWidth());
- pHeader->SetPropertyULONG32("Height", m_pGIFCodec->GetLogicalScreenHeight());
- }
- // Set the new state
- m_ulState = kStateFileHeaderSent;
- // Inform the response interface that we have the file header
- retVal = m_pFormatResponse->FileHeaderReady(HXR_OK, pHeader);
- // Release our reference on the IHXValues object
- HX_RELEASE(pHeader);
- return retVal;
- }
- STDMETHODIMP CGIFFileFormat::GetStreamHeader(UINT16 usStreamNum)
- {
- #ifdef XXXMEH_DEBUG_LOG
- DEBUG_OUTF("pxgifff.log", (s, "0x%08x::GetStreamHeader(%u)n", this, usStreamNum));
- #endif
- // Check the state
- if (m_ulState != kStateFileHeaderSent)
- {
- return HXR_UNEXPECTED;
- }
- // Check for input error
- if (usStreamNum != 0)
- {
- return m_pFormatResponse->StreamHeaderReady(HXR_FAIL, NULL);
- }
- UINT32 ulPreDataBytes = 0;
- if (m_pGIFCodec && !m_bParseFailed)
- {
- // Resolve the minimum duration with the requested duration.
- //
- // Here's the rule: if the duration was not specified (i.e. - the
- // duration is equal to the default, then take the duration that's
- // in the GIF file, as long as it HAS some duration
- if (m_ulDuration == kDefaultDuration &&
- m_pGIFCodec->IsGIF89a() &&
- m_pGIFCodec->GetDelayTimeSum() > 0)
- {
- m_ulDuration = m_pGIFCodec->GetDelayTimeSum();
- }
- // Allocate space for the array of scheduling times
- INT32 lNumImages = (INT32) m_pGIFCodec->GetNumImages();
- 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;
- }
- 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;
- }