comimgrend.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:22k
源码类别:

Symbian

开发平台:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 1.0/RPSL 1.0 
  3.  *  
  4.  * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
  5.  *      
  6.  * The contents of this file, and the files included with this file, are 
  7.  * subject to the current version of the RealNetworks Public Source License 
  8.  * Version 1.0 (the "RPSL") available at 
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed 
  10.  * the file under the RealNetworks Community Source License Version 1.0 
  11.  * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
  12.  * in which case the RCSL will apply. You may also obtain the license terms 
  13.  * directly from RealNetworks.  You may not use this file except in 
  14.  * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
  15.  * applicable to this file, the RCSL.  Please see the applicable RPSL or 
  16.  * RCSL for the rights, obligations and limitations governing use of the 
  17.  * contents of the file.  
  18.  *  
  19.  * This file is part of the Helix DNA Technology. RealNetworks is the 
  20.  * developer of the Original Code and owns the copyrights in the portions 
  21.  * it created. 
  22.  *  
  23.  * This file, and the files included with this file, is distributed and made 
  24.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  25.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  26.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
  27.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  28.  * 
  29.  * Technology Compatibility Kit Test Suite(s) Location: 
  30.  *    http://www.helixcommunity.org/content/tck 
  31.  * 
  32.  * Contributor(s): 
  33.  *  
  34.  * ***** END LICENSE BLOCK ***** */ 
  35. #include "hxtypes.h"
  36. #include "hxwintyp.h"
  37. #include "hxcom.h"
  38. #include "hxcomm.h"
  39. #include "ihxpckts.h"
  40. #include "hxfiles.h"
  41. #include "hxcore.h"
  42. #include "hxrendr.h"
  43. #include "hxplugn.h"
  44. #include "hxwin.h"
  45. #include "hxevent.h"
  46. #include "hxvsurf.h"
  47. #include "hxslist.h"
  48. #include "hxver.h"
  49. #include "baseobj.h"
  50. #include "wbmphdr.h"
  51. #include "hxtick.h"
  52. #include "unifimg.h"
  53. #include "nativeimgdec.h"
  54. #include "comimgrend.h"
  55. #include "comimgrend.ver"
  56. #include "hxheap.h"
  57. #ifdef _DEBUG
  58. #undef HX_THIS_FILE
  59. static const char HX_THIS_FILE[] = __FILE__;
  60. #endif
  61. const char* const CCommonImageRenderer::m_pszName              = "CommonImageRenderer";
  62. const char* const CCommonImageRenderer::m_pszDescription       = "Helix Common Image Renderer Plugin";
  63. const char* const CCommonImageRenderer::m_pszCopyright         = HXVER_COPYRIGHT;
  64. const char* const CCommonImageRenderer::m_pszMoreInfoURL       = HXVER_MOREINFO;
  65. const char* const CCommonImageRenderer::m_ppszStreamMimeType[] = {IMAGE_MIMETYPE_JPEG,
  66.                                                                   IMAGE_MIMETYPE_PNG,
  67.                                                                   IMAGE_MIMETYPE_WBMP,
  68.                                                                   IMAGE_MIMETYPE_JPEG_STREAMED,
  69.                                                                   IMAGE_MIMETYPE_PNG_STREAMED,
  70.                                                                   IMAGE_MIMETYPE_WBMP_STREAMED,
  71.                                                                   NULL};
  72. CCommonImageRenderer::CCommonImageRenderer()
  73. {
  74.     m_lRefCount           = 0;
  75.     m_pContext            = NULL;
  76.     m_pSite               = NULL;
  77.     m_pCommonClassFactory = NULL;
  78.     m_pStreamHeader       = NULL;
  79.     m_pMimeTypeStr        = NULL;
  80.     m_ulImageWidth        = 0;
  81.     m_ulImageHeight       = 0;
  82.     m_pPacketList         = NULL;
  83.     m_bHasForceRedraw     = FALSE;
  84.     m_bDecodeComplete     = FALSE;
  85.     m_pBitmapInfoHeader   = NULL;
  86.     m_pOutputBuffer       = NULL;
  87.     m_pNativeImageDecoder = NULL;
  88. }
  89. CCommonImageRenderer::~CCommonImageRenderer()
  90. {
  91.     ClearPacketList();
  92.     HX_RELEASE(m_pContext);
  93.     HX_RELEASE(m_pSite);
  94.     HX_RELEASE(m_pCommonClassFactory);
  95.     HX_RELEASE(m_pStreamHeader);
  96.     HX_DELETE(m_pPacketList);
  97.     HX_DELETE(m_pBitmapInfoHeader);
  98.     HX_RELEASE(m_pOutputBuffer);
  99.     HX_DELETE(m_pNativeImageDecoder);
  100. }
  101. STDMETHODIMP CCommonImageRenderer::QueryInterface(REFIID riid, void** ppvObj)
  102. {
  103.     HX_RESULT retVal = HXR_OK;
  104.     if (ppvObj)
  105.     {
  106.         // Set default
  107.         *ppvObj = NULL;
  108.         // Check for IID type
  109.         if (IsEqualIID(riid, IID_IUnknown))
  110.         {
  111.             AddRef();
  112.             *ppvObj = (IUnknown*) (CHXBaseCountingObject*) (IHXPlugin*) this;
  113.         }
  114.         else if (IsEqualIID(riid, IID_IHXPlugin))
  115.         {
  116.             AddRef();
  117.             *ppvObj = (IHXPlugin*) this;
  118.         }
  119.         else if (IsEqualIID(riid, IID_IHXRenderer))
  120.         {
  121.             AddRef();
  122.             *ppvObj = (IHXRenderer*) this;
  123.         }
  124.         else if (IsEqualIID(riid, IID_IHXSiteUser))
  125.         {
  126.             AddRef();
  127.             *ppvObj = (IHXSiteUser*) this;
  128.         }
  129.         else
  130.         {
  131.             retVal = HXR_NOINTERFACE;
  132.         }
  133.     }
  134.     else
  135.     {
  136.         retVal = HXR_FAIL;
  137.     }
  138.     return retVal;
  139. }
  140. STDMETHODIMP_(UINT32) CCommonImageRenderer::AddRef()
  141. {
  142.     return InterlockedIncrement(&m_lRefCount);
  143. }
  144. STDMETHODIMP_(UINT32) CCommonImageRenderer::Release()
  145. {
  146.     if (InterlockedDecrement(&m_lRefCount) > 0)
  147.     {
  148.         return m_lRefCount;
  149.     }
  150.     delete this;
  151.     return 0;
  152. }
  153. STDMETHODIMP CCommonImageRenderer::GetPluginInfo(REF(BOOL)        rbLoadMultiple,
  154.                                                  REF(const char*) rpszDescription,
  155.                                                  REF(const char*) rpszCopyright,
  156.                                                  REF(const char*) rpszMoreInfoURL,
  157.                                                  REF(UINT32)      rulVersionNumber)
  158. {
  159.     rbLoadMultiple   = TRUE;
  160.     rpszDescription  = (const char*) m_pszDescription;
  161.     rpszCopyright    = (const char*) m_pszCopyright;
  162.     rpszMoreInfoURL  = (const char*) m_pszMoreInfoURL;
  163.     rulVersionNumber = TARVER_ULONG32_VERSION;
  164.     return HXR_OK;
  165. }
  166. STDMETHODIMP CCommonImageRenderer::InitPlugin(IUnknown* pContext)
  167. {
  168.     HX_RESULT retVal = HXR_FAIL;
  169.     if (pContext)
  170.     {
  171.         // Save a copy of the calling context
  172.         HX_RELEASE(m_pContext);
  173.         m_pContext = pContext;
  174.         m_pContext->AddRef();
  175.         // Get a IHXCommonClassFactory interface
  176.         HX_RELEASE(m_pCommonClassFactory);
  177.         retVal = m_pContext->QueryInterface(IID_IHXCommonClassFactory,
  178.                                             (void**) &m_pCommonClassFactory);
  179.     }
  180.     return retVal;
  181. }
  182. STDMETHODIMP CCommonImageRenderer::GetRendererInfo(REF(const char**) rppszStreamMimeType,
  183.                                                    REF(UINT32)       rulInitialGranularity)
  184. {
  185.     rppszStreamMimeType   = (const char**) m_ppszStreamMimeType;
  186.     rulInitialGranularity = 100;
  187.     return HXR_OK;
  188. }
  189. STDMETHODIMP CCommonImageRenderer::StartStream(IHXStream* pStream, IHXPlayer* pPlayer)
  190. {
  191.     HX_RESULT retVal = HXR_OK;
  192.     return retVal;
  193. }
  194. STDMETHODIMP CCommonImageRenderer::OnHeader(IHXValues* pHeader)
  195. {
  196.     HX_RESULT retVal = HXR_FAIL;
  197.     if (pHeader)
  198.     {
  199.         // Parse the stream header
  200.         retVal = ParseStreamHeader(pHeader, m_ulImageWidth,
  201.                                    m_ulImageHeight, m_pMimeTypeStr);
  202.         if (SUCCEEDED(retVal))
  203.         {
  204.             // Save the stream header
  205.             HX_RELEASE(m_pStreamHeader);
  206.             m_pStreamHeader = pHeader;
  207.             m_pStreamHeader->AddRef();
  208.         }
  209.     }
  210.     return retVal;
  211. }
  212. STDMETHODIMP CCommonImageRenderer::OnBegin(UINT32 ulTimeAfterBegin)
  213. {
  214.     HX_RESULT retVal = HXR_OK;
  215.     return retVal;
  216. }
  217. STDMETHODIMP CCommonImageRenderer::GetDisplayType(REF(HX_DISPLAY_TYPE) rDisplayType,
  218.                                                   REF(IHXBuffer*)      rpDisplayInfo)
  219. {
  220.     HX_RESULT retVal = HXR_OK;
  221.     rDisplayType = HX_DISPLAY_WINDOW          |
  222.                    HX_DISPLAY_SUPPORTS_RESIZE |
  223.                    HX_DISPLAY_SUPPORTS_FULLSCREEN;
  224.     return retVal;
  225. }
  226. STDMETHODIMP CCommonImageRenderer::OnPacket(IHXPacket* pPacket, INT32 lTimeOffset)
  227. {
  228.     HX_RESULT retVal = HXR_FAIL;
  229.     if (pPacket)
  230.     {
  231.         if (!m_pPacketList)
  232.         {
  233.             m_pPacketList = new CHXSimpleList();
  234.         }
  235.         if (m_pPacketList)
  236.         {
  237.             // AddRef the packet before going on the list
  238.             pPacket->AddRef();
  239.             // Add the packet to the list
  240.             m_pPacketList->AddTail((void*) pPacket);
  241.         }
  242.         // Clear the return value
  243.         retVal = HXR_OK;
  244.     }
  245.     return retVal;
  246. }
  247. STDMETHODIMP CCommonImageRenderer::OnTimeSync(UINT32 ulTime)
  248. {
  249.     HX_RESULT retVal = HXR_OK;
  250.     if (m_bDecodeComplete && !m_bHasForceRedraw )
  251.         _ForceRedraw();
  252.     
  253.     return retVal;
  254. }
  255. STDMETHODIMP CCommonImageRenderer::OnPreSeek(UINT32 ulTimeBefore, UINT32 ulTimeAfter)
  256. {
  257.     HX_RESULT retVal = HXR_OK;
  258.     return retVal;
  259. }
  260. STDMETHODIMP CCommonImageRenderer::OnPostSeek(UINT32 ulTimeBefore, UINT32 ulTimeAfter)
  261. {
  262.     HX_RESULT retVal = HXR_OK;
  263.     return retVal;
  264. }
  265. STDMETHODIMP CCommonImageRenderer::OnPause(UINT32 ulTimeBeforePause)
  266. {
  267.     HX_RESULT retVal = HXR_OK;
  268.     return retVal;
  269. }
  270. STDMETHODIMP CCommonImageRenderer::OnBuffering(UINT32 ulReason, UINT16 usPercentComplete)
  271. {
  272.     HX_RESULT retVal = HXR_OK;
  273.     return retVal;
  274. }
  275. STDMETHODIMP CCommonImageRenderer::OnEndofPackets()
  276. {
  277.     HX_RESULT retVal = HXR_OK;
  278.     // Generate single image buffer from list of packets
  279.     IHXBuffer* pBuffer = NULL;
  280.     retVal = GenerateImageBuffer(m_pPacketList, m_pStreamHeader, pBuffer);
  281.     if (SUCCEEDED(retVal))
  282.     {
  283.         // Now we can clear the packet list
  284.         ClearPacketList();
  285.         // Delete the list object
  286.         HX_DELETE(m_pPacketList);
  287.         // Create the native image decoder object
  288.         HX_DELETE(m_pNativeImageDecoder);
  289.         m_pNativeImageDecoder = CNativeImageDecoder::CreateNativeImageDecoder();
  290.         if (m_pNativeImageDecoder)
  291.         {
  292.             // Decode the image asynchronously
  293.             retVal = m_pNativeImageDecoder->Decode(m_pContext,
  294.                                                    this,
  295.                                                    pBuffer,
  296.                                                    m_pMimeTypeStr);
  297.         }
  298.     }
  299.     HX_RELEASE(pBuffer);
  300.     return retVal;
  301. }
  302. STDMETHODIMP CCommonImageRenderer::EndStream()
  303. {
  304.     HX_RESULT retVal = HXR_OK;
  305.     ClearPacketList();
  306.     HX_RELEASE(m_pContext);
  307.     HX_RELEASE(m_pSite);
  308.     HX_RELEASE(m_pCommonClassFactory);
  309.     HX_DELETE(m_pPacketList);
  310.     HX_DELETE(m_pBitmapInfoHeader);
  311.     HX_RELEASE(m_pOutputBuffer);
  312.     HX_DELETE(m_pNativeImageDecoder);
  313.     return retVal;
  314. }
  315. STDMETHODIMP CCommonImageRenderer::AttachSite(IHXSite* pSite)
  316. {
  317.     HX_RESULT retVal = HXR_FAIL;
  318.     if (pSite && !m_pSite)
  319.     {
  320.         // Save the site
  321.         m_pSite = pSite;
  322.         m_pSite->AddRef();
  323.         // Set the size of the site
  324.         HXxSize cSize = {m_ulImageWidth, m_ulImageHeight};
  325.         m_pSite->SetSize(cSize);
  326.         // Clear the return value
  327.         retVal = HXR_OK;
  328.     }
  329.     return retVal;
  330. }
  331. STDMETHODIMP CCommonImageRenderer::DetachSite()
  332. {
  333.     HX_RESULT retVal = HXR_OK;
  334.     // Release our ref on the site
  335.     HX_RELEASE(m_pSite);
  336.     return retVal;
  337. }
  338. STDMETHODIMP CCommonImageRenderer::HandleEvent(HXxEvent* pEvent)
  339. {
  340.     HX_RESULT retVal = HXR_FAIL;
  341.     if (pEvent)
  342.     {
  343.         // Set defaults
  344.         pEvent->handled = FALSE;
  345.         pEvent->result  = 0;
  346.         // Switch based on event type
  347.         switch (pEvent->event)
  348.         {
  349.             case HX_SURFACE_UPDATE:
  350.                 {
  351.                     if (m_pSite)
  352.                     {
  353.                         // Get the site size
  354.                         HXxSize cSize = {0,0};
  355.                         m_pSite->GetSize(cSize);
  356.                         // Create src and dst rects
  357.                         HXxRect cSrcRect = {0, 0, m_ulImageWidth, m_ulImageHeight};
  358.                         HXxRect cDstRect = {0, 0, cSize.cx,       cSize.cy};
  359.                         // Get the video surface
  360.                         IHXVideoSurface* pSurf = (IHXVideoSurface*) pEvent->param1;
  361.                         if( pSurf && m_pOutputBuffer )
  362.                         {
  363.                             pSurf->AddRef();
  364.                             // Blt to the surface
  365.                             pSurf->Blt(m_pOutputBuffer->GetBuffer(),
  366.                                        m_pBitmapInfoHeader,
  367.                                        cDstRect,
  368.                                        cSrcRect);
  369.                             pSurf->Release();
  370.                             pEvent->handled = TRUE;
  371.                         }
  372.                     }
  373.                 }
  374.                 break;
  375.             default:
  376.                 break;
  377.         }
  378.         // Clear the return value
  379.         retVal = HXR_OK;
  380.     }
  381.     return retVal;
  382. }
  383. STDMETHODIMP_(BOOL) CCommonImageRenderer::NeedsWindowedSites()
  384. {
  385.     return FALSE;
  386. }
  387. STDMETHODIMP CCommonImageRenderer::DecodeDone(HX_RESULT           status,
  388.                                               HXBitmapInfoHeader* pHeader,
  389.                                               IHXBuffer*          pBuffer)
  390. {
  391.     HX_RESULT retVal = HXR_FAIL;
  392.     if (SUCCEEDED(status) && pHeader && pBuffer)
  393.     {
  394.         // Allocate an HXBitmapInfoHeader
  395.         HX_DELETE(m_pBitmapInfoHeader);
  396.         m_pBitmapInfoHeader = new HXBitmapInfoHeader;
  397.         if (m_pBitmapInfoHeader)
  398.         {
  399.             // Copy the bitmap header
  400.             memcpy(m_pBitmapInfoHeader, pHeader, sizeof(HXBitmapInfoHeader));
  401.             // Save the buffer
  402.             HX_RELEASE(m_pOutputBuffer);
  403.             m_pOutputBuffer = pBuffer;
  404.             m_pOutputBuffer->AddRef();
  405.             // Clear the return value
  406.             retVal = HXR_OK;
  407.         }
  408.         m_bDecodeComplete = TRUE;
  409.         //If the HX_SURFACE_UPDATE event came in while we were still
  410.         //waiting on the async decode then we need to blt now to
  411.         //catch up.
  412.         if( !m_bHasForceRedraw )
  413.             _ForceRedraw();
  414.     }
  415.     return retVal;
  416. }
  417. void CCommonImageRenderer::_ForceRedraw()
  418. {
  419.     if( m_pSite )
  420.     {
  421.         HXxSize cSize = {0, 0};
  422.         m_pSite->GetSize(cSize);
  423.         HXxRect cRect = {0, 0, cSize.cx, cSize.cy};
  424.         m_pSite->DamageRect(cRect);
  425.         m_pSite->ForceRedraw();
  426.         m_bHasForceRedraw = TRUE;
  427.     }
  428. }
  429. HX_RESULT STDAPICALLTYPE CCommonImageRenderer::HXCreateInstance(IUnknown** ppIUnknown)
  430. {
  431.     HX_RESULT retVal = HXR_FAIL;
  432.     if (ppIUnknown)
  433.     {
  434.         // Set default
  435.         *ppIUnknown = NULL;
  436.         // Create the object
  437.         CCommonImageRenderer *pObj = new CCommonImageRenderer();
  438.         if (pObj)
  439.         {
  440.             // QI for IUnknown
  441.             retVal = pObj->QueryInterface(IID_IUnknown, (void**) ppIUnknown);
  442.         }
  443.         if (FAILED(retVal))
  444.         {
  445.             HX_DELETE(pObj);
  446.         }
  447.     }
  448.     return retVal;
  449. }
  450. HX_RESULT CCommonImageRenderer::GenerateImageBuffer(CHXSimpleList*  pPacketList,
  451.                                                     IHXValues*      pStreamHeader,
  452.                                                     REF(IHXBuffer*) rpBuffer)
  453. {
  454.     HX_RESULT retVal = HXR_FAIL;
  455.     // First run through and see how big a single buffer we need
  456.     UINT32 ulTotal = SumCopyPacketList(pPacketList, pStreamHeader, NULL);
  457.     if (ulTotal && m_pCommonClassFactory)
  458.     {
  459.         // Create the buffer
  460.         IHXBuffer* pWholeBuffer = NULL;
  461.         retVal = m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer,
  462.                                                        (void**) &pWholeBuffer);
  463.         if (SUCCEEDED(retVal))
  464.         {
  465.             // Set the size
  466.             retVal = pWholeBuffer->SetSize(ulTotal);
  467.             if (SUCCEEDED(retVal))
  468.             {
  469.                 SumCopyPacketList(pPacketList, pStreamHeader, pWholeBuffer);
  470.                 // Set the out parameter
  471.                 HX_RELEASE(rpBuffer);
  472.                 rpBuffer = pWholeBuffer;
  473.                 rpBuffer->AddRef();
  474.             }
  475.         }
  476.         HX_RELEASE(pWholeBuffer);
  477.     }
  478.     return retVal;
  479. }
  480. UINT32 CCommonImageRenderer::SumCopyPacketList(CHXSimpleList* pPacketList,
  481.                                                IHXValues*     pStreamHeader,
  482.                                                IHXBuffer*     pWholeBuffer)
  483. {
  484.     UINT32 ulRet = 0;
  485.     if (pPacketList && pPacketList->GetCount() > 0 && pStreamHeader)
  486.     {
  487.         // Get the mime type
  488.         IHXBuffer* pMimeTypeStr = NULL;
  489.         pStreamHeader->GetPropertyCString("MimeType", pMimeTypeStr);
  490.         if (pMimeTypeStr)
  491.         {
  492.             const char* pszMimeType = (const char*) pMimeTypeStr->GetBuffer();
  493.             if (pszMimeType)
  494.             {
  495.                 // Get the number of overhead bytes
  496.                 UINT32 ulOverheadBytes = 0;
  497.                 if (!strcmp(pszMimeType, IMAGE_MIMETYPE_JPEG_STREAMED))
  498.                 {
  499.                     // 20 bytes of overhead in JPEG packetization
  500.                     ulOverheadBytes = 20;
  501.                 }
  502.                 else if (!strcmp(pszMimeType, IMAGE_MIMETYPE_WBMP_STREAMED))
  503.                 {
  504.                     // 4 bytes of overhead in WBMP packetization
  505.                     ulOverheadBytes = 4;
  506.                     // If we are the WBMP wire format (coming from
  507.                     // the WBMP file format and not the unified
  508.                     // file format), then we need to add the value
  509.                     // of the opaque data.
  510.                     IHXBuffer* pOpaque = NULL;
  511.                     pStreamHeader->GetPropertyBuffer("OpaqueData", pOpaque);
  512.                     if (pOpaque)
  513.                     {
  514.                         if (pWholeBuffer)
  515.                         {
  516.                             memcpy(pWholeBuffer->GetBuffer() + ulRet,
  517.                                    pOpaque->GetBuffer(),
  518.                                    pOpaque->GetSize());
  519.                         }
  520.                         ulRet += pOpaque->GetSize();
  521.                     }
  522.                     HX_RELEASE(pOpaque);
  523.                 }
  524.                 // Loop through the packets, either adding up
  525.                 // or copying or both
  526.                 LISTPOSITION pos = pPacketList->GetHeadPosition();
  527.                 while (pos)
  528.                 {
  529.                     IHXPacket* pPacket = (IHXPacket*) pPacketList->GetNext(pos);
  530.                     if (pPacket)
  531.                     {
  532.                         IHXBuffer* pBuffer = pPacket->GetBuffer();
  533.                         if (pBuffer)
  534.                         {
  535.                             // Add up (and maybe copy) the actual
  536.                             // bytes minus the overhead
  537.                             if (pWholeBuffer)
  538.                             {
  539.                                 memcpy(pWholeBuffer->GetBuffer() + ulRet,
  540.                                        pBuffer->GetBuffer() + ulOverheadBytes,
  541.                                        pBuffer->GetSize()   - ulOverheadBytes);
  542.                             }
  543.                             ulRet += pBuffer->GetSize() - ulOverheadBytes;
  544.                         }
  545.                         HX_RELEASE(pBuffer);
  546.                     }
  547.                 }
  548.             }
  549.         }
  550.         HX_RELEASE(pMimeTypeStr);
  551.     }
  552.     return ulRet;
  553. }
  554. void CCommonImageRenderer::ClearPacketList()
  555. {
  556.     if (m_pPacketList)
  557.     {
  558.         LISTPOSITION pos = m_pPacketList->GetHeadPosition();
  559.         while (pos)
  560.         {
  561.             IHXPacket* pPacket = (IHXPacket*) m_pPacketList->GetNext(pos);
  562.             HX_RELEASE(pPacket);
  563.         }
  564.         m_pPacketList->RemoveAll();
  565.     }
  566. }
  567. HX_RESULT CCommonImageRenderer::ParseStreamHeader(IHXValues*      pHeader,
  568.                                                   REF(UINT32)     rulImageWidth,
  569.                                                   REF(UINT32)     rulImageHeight,
  570.                                                   REF(IHXBuffer*) rpMimeTypeStr)
  571. {
  572.     HX_RESULT retVal = HXR_FAIL;
  573.     if (pHeader)
  574.     {
  575.         // Get the mime type string buffer
  576.         HX_RELEASE(rpMimeTypeStr);
  577.         retVal = pHeader->GetPropertyCString("MimeType", rpMimeTypeStr);
  578.         if (SUCCEEDED(retVal))
  579.         {
  580.             // Get the mime type string
  581.             const char* pszMimeType = (const char*) rpMimeTypeStr->GetBuffer();
  582.             // Get the opaque data
  583.             IHXBuffer* pOpaque = NULL;
  584.             pHeader->GetPropertyBuffer("OpaqueData", pOpaque);
  585.             // Default the width and height
  586.             rulImageWidth  = 0;
  587.             rulImageHeight = 0;
  588.             // Parse based on mime type
  589.             if (!strcmp(pszMimeType, IMAGE_MIMETYPE_JPEG) ||
  590.                 !strcmp(pszMimeType, IMAGE_MIMETYPE_PNG)  ||
  591.                 !strcmp(pszMimeType, IMAGE_MIMETYPE_WBMP))
  592.             {
  593.                 // This header came from unified fileformat
  594.                 pHeader->GetPropertyULONG32("ImageWidth",  rulImageWidth);
  595.                 pHeader->GetPropertyULONG32("ImageHeight", rulImageHeight);
  596.             }
  597.             else if (!strcmp(pszMimeType, IMAGE_MIMETYPE_PNG_STREAMED) ||
  598.                      !strcmp(pszMimeType, IMAGE_MIMETYPE_JPEG_STREAMED))
  599.             {
  600.                 if (pOpaque && pOpaque->GetSize() >= 8)
  601.                 {
  602.                     BYTE* pBuf = (BYTE*) pOpaque->GetBuffer();
  603.                     rulImageWidth  = (pBuf[0] << 24) | (pBuf[1] << 16) | (pBuf[2] << 8) | pBuf[3];
  604.                     rulImageHeight = (pBuf[4] << 24) | (pBuf[5] << 16) | (pBuf[6] << 8) | pBuf[7];
  605.                 }
  606.             }
  607.             else if (!strcmp(pszMimeType, IMAGE_MIMETYPE_WBMP_STREAMED))
  608.             {
  609.                 if (pOpaque)
  610.                 {
  611.                     // Unpack the stream header
  612.                     UINT32 ulHdrSize = 0;
  613.                     ParseWBMPHeader((BYTE*) pOpaque->GetBuffer(),
  614.                                     pOpaque->GetSize(),
  615.                                     rulImageWidth,
  616.                                     rulImageHeight,
  617.                                     ulHdrSize);
  618.                 }
  619.             }
  620.             HX_RELEASE(pOpaque);
  621.             if (!rulImageWidth || !rulImageHeight)
  622.             {
  623.                 retVal = HXR_FAIL;
  624.             }
  625.         }
  626.     }
  627.     return retVal;
  628. }