vidrendf.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:18k
源码类别:

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: vidrendf.cpp,v 1.9.2.1 2004/07/09 01:55:01 hubbe Exp $
  3.  * 
  4.  * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
  5.  * 
  6.  * The contents of this file, and the files included with this file,
  7.  * are subject to the current version of the RealNetworks Public
  8.  * Source License (the "RPSL") available at
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed
  10.  * the file under the current version of the RealNetworks Community
  11.  * Source License (the "RCSL") available at
  12.  * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
  13.  * will apply. You may also obtain the license terms directly from
  14.  * RealNetworks.  You may not use this file except in compliance with
  15.  * the RPSL or, if you have a valid RCSL with RealNetworks applicable
  16.  * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
  17.  * the rights, obligations and limitations governing use of the
  18.  * contents of the file.
  19.  * 
  20.  * Alternatively, the contents of this file may be used under the
  21.  * terms of the GNU General Public License Version 2 or later (the
  22.  * "GPL") in which case the provisions of the GPL are applicable
  23.  * instead of those above. If you wish to allow use of your version of
  24.  * this file only under the terms of the GPL, and not to allow others
  25.  * to use your version of this file under the terms of either the RPSL
  26.  * or RCSL, indicate your decision by deleting the provisions above
  27.  * and replace them with the notice and other provisions required by
  28.  * the GPL. If you do not delete the provisions above, a recipient may
  29.  * use your version of this file under the terms of any one of the
  30.  * RPSL, the RCSL or the GPL.
  31.  * 
  32.  * This file is part of the Helix DNA Technology. RealNetworks is the
  33.  * developer of the Original Code and owns the copyrights in the
  34.  * portions it created.
  35.  * 
  36.  * This file, and the files included with this file, is distributed
  37.  * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
  38.  * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
  39.  * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
  40.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
  41.  * ENJOYMENT OR NON-INFRINGEMENT.
  42.  * 
  43.  * Technology Compatibility Kit Test Suite(s) Location:
  44.  *    http://www.helixcommunity.org/content/tck
  45.  * 
  46.  * Contributor(s):
  47.  * 
  48.  * ***** END LICENSE BLOCK ***** */
  49. #ifdef ENABLE_TRACE
  50. #define HX_TRACE_THINGY(x, m, l)
  51.     {
  52. FILE* f1;
  53. f1 = ::fopen(x, "a+");
  54. (f1)?(::fprintf(f1, "%ld - %s = %ld n", HX_GET_BETTERTICKCOUNT(), m, l), ::fclose(f1)):(0);
  55.     }
  56. #define STAMPBUF(x, m)
  57.     {
  58. FILE* f1;
  59. f1 = ::fopen(x, "a+");
  60. (f1)?(::fprintf(f1, "%ld - %sn", HX_GET_BETTERTICKCOUNT(), m), ::fclose(f1)):(0);
  61.     }
  62. #else // ENABLE_TRACE
  63. #define HX_TRACE_THINGY(x, m, l)
  64. #ifdef MEASURE_PERF
  65. #define LOGBUFFSIZE 100000
  66. char textmem[LOGBUFFSIZE];
  67. char *textptr = textmem;
  68. #define STAMPBUF(x, txt) { if (textptr - textmem < LOGBUFFSIZE) textptr += SafeSprintf(textptr, LOGBUFFSIZE - (textptr - textmem), "%s: %ld*n", txt, HX_GET_BETTERTICKCOUNT()); }
  69. #else // MEASURE_PERF
  70. #define STAMPBUF(x, txt)
  71. #endif // MEASURE_PERF
  72. #endif // ENABLE_TRACE
  73. /****************************************************************************
  74.  *  Defines
  75.  */
  76. #if !defined(HELIX_FEATURE_MIN_HEAP)
  77. #define MAX_BUFFERED_DECODED_FRAMES 12
  78. #else // HELIX_FEATURE_MIN_HEAP
  79. #define MAX_BUFFERED_DECODED_FRAMES 2
  80. #endif // HELIX_FEATURE_MIN_HEAP
  81. #if defined(HELIX_FEATURE_MIN_HEAP)
  82. #define FORMAT_MINIMUM_PREROLL 1000
  83. #define FORMAT_DEFAULT_PREROLL 2000
  84. #define FORMAT_MAXIMUM_PREROLL 3000
  85. #else
  86. #define FORMAT_MINIMUM_PREROLL 3000
  87. #define FORMAT_DEFAULT_PREROLL 5000
  88. #define FORMAT_MAXIMUM_PREROLL 15000
  89. #endif
  90. #define MAX_DECODE_SPIN 100
  91. /****************************************************************************
  92.  *  Includes
  93.  */
  94. #include "vidrendf.h"
  95. #include "vidrend.h"
  96. #include "hxtick.h"
  97. #include "hxassert.h"
  98. #include "hxstrutl.h"
  99. /****************************************************************************
  100.  *  Debug
  101.  */
  102. #ifdef ENABLE_FRAME_TRACE
  103. #define MAX_FRAME_TRACE_ENTRIES 100000
  104. ULONG32 ulFrameTraceIdx = 0;
  105. LONG32 frameTraceArray[MAX_FRAME_TRACE_ENTRIES][3];
  106. void DumpFrameEntries(void)
  107. {
  108.     FILE* pFile = NULL;
  109.     ULONG32 ulIdx;
  110.     if (ulFrameTraceIdx > 0)
  111.     {
  112. pFile = fopen("c:\buf.txt", "wb");
  113.     }
  114.     if (pFile)
  115.     {
  116. for (ulIdx = 0; ulIdx < ulFrameTraceIdx; ulIdx++)
  117. {
  118.     fprintf(pFile, "%c(%d) = %xn", (char) frameTraceArray[ulIdx][1], 
  119.    frameTraceArray[ulIdx][2], 
  120.    frameTraceArray[ulIdx][0]);
  121. }
  122. fclose(pFile);
  123.     }
  124.     ulFrameTraceIdx = 0;
  125. }
  126. #endif // ENABLE_FRAME_TRACE
  127. /****************************************************************************
  128.  *  Method:
  129.  *    CVideoFormat::CVideoFormat
  130.  *
  131.  */
  132. CVideoFormat::CVideoFormat(IHXCommonClassFactory* pCommonClassFactory,
  133.    CVideoRenderer* pVideoRenderer)
  134. : m_pCommonClassFactory(pCommonClassFactory)
  135. , m_pVideoRenderer(pVideoRenderer)
  136. , m_pMutex(NULL)
  137. , m_pAssemblerMutex(NULL)
  138. , m_pOutputQueue(NULL)
  139. , m_pFramePool(NULL)
  140. , m_lMaxBufferedDecodedFrames(MAX_BUFFERED_DECODED_FRAMES)
  141. , m_pHeader(NULL)
  142. , m_ulStartTime(0)
  143. , m_bDecodeSuspended(FALSE)
  144. , m_bRawPacketsDone(FALSE)
  145. , m_lRefCount(0)
  146. , m_LastError(HXR_OK)
  147. {
  148.     HX_ASSERT(m_pCommonClassFactory);
  149.     m_pCommonClassFactory->AddRef();
  150.     m_pVideoRenderer->AddRef();
  151. #ifdef THREADS_SUPPORTED
  152.     HXMutex::MakeMutex(m_pMutex);
  153.     HXMutex::MakeMutex(m_pAssemblerMutex);
  154.     HXMutex::MakeMutex(m_pDecoderMutex);
  155. #else
  156.     HXMutex::MakeStubMutex(m_pMutex);
  157.     HXMutex::MakeStubMutex(m_pAssemblerMutex);
  158.     HXMutex::MakeStubMutex(m_pDecoderMutex);
  159. #endif
  160. }
  161. /****************************************************************************
  162.  *  Method:
  163.  *    CVideoFormat::~CVideoFormat
  164.  *
  165.  */
  166. CVideoFormat::~CVideoFormat()
  167. {
  168.     _Reset();
  169.     HX_DELETE(m_pFramePool);
  170.     HX_DELETE(m_pOutputQueue);
  171.     HX_DELETE(m_pMutex);
  172.     HX_DELETE(m_pAssemblerMutex);
  173.     HX_DELETE(m_pDecoderMutex);
  174.     HX_RELEASE(m_pHeader);
  175.     HX_RELEASE(m_pVideoRenderer);
  176.     HX_RELEASE(m_pCommonClassFactory);
  177. #ifdef ENABLE_FRAME_TRACE
  178.     DumpFrameEntries();
  179. #endif // ENABLE_FRAME_TRACE
  180. }
  181. /****************************************************************************
  182.  *  Method:
  183.  *    CVideoFormat::Init
  184.  *
  185.  */
  186. HX_RESULT CVideoFormat::Init(IHXValues* pHeader)
  187. {
  188.     HX_RESULT retVal = HXR_OK;
  189.     HX_RELEASE(m_pHeader);
  190.     m_pHeader = pHeader;
  191.     if (m_pHeader)
  192.     {
  193. m_pHeader->AddRef();
  194.     }
  195.     if (SUCCEEDED(retVal))
  196.     {
  197. m_pFramePool = CreateBufferPool();
  198.     }
  199.     if (SUCCEEDED(retVal))
  200.     {
  201. m_lMaxBufferedDecodedFrames = GetMaxDecodedFrames();
  202. FlushOutputQueue();
  203. HX_DELETE(m_pOutputQueue);
  204. m_pOutputQueue = new CRingBuffer(m_lMaxBufferedDecodedFrames);
  205. retVal = HXR_OUTOFMEMORY;
  206. if (m_pOutputQueue)
  207. {
  208.     retVal = HXR_OK;
  209. }
  210.     }
  211.     return retVal;
  212. }
  213. /****************************************************************************
  214.  *  Method:
  215.  *    CVideoFormat::CreateBufferPool
  216.  *
  217.  */
  218. CHXBufferPool* CVideoFormat::CreateBufferPool(void)
  219. {
  220.     return new CHXBufferPool(
  221.     (BufferSizeFunc) CMediaPacket::GetBufferSize,
  222.     (BufferKillerFunc) CMediaPacket::DeletePacket);
  223. }
  224. /****************************************************************************
  225.  *  Method:
  226.  *    CVideoFormat::CreateAssembledPacket
  227.  *
  228.  */
  229. CMediaPacket* CVideoFormat::CreateAssembledPacket(IHXPacket* pPayloadData)
  230. {
  231.     CMediaPacket* pFramePacket = NULL;
  232.     BOOL bIsKeyframe = FALSE;
  233.     if (pPayloadData->IsLost())
  234.     {
  235. pFramePacket = NULL;
  236.     }
  237.     else
  238.     {
  239. IHXBuffer* pBuffer = pPayloadData->GetBuffer();
  240. if (pBuffer)
  241. {
  242.     pFramePacket = new CMediaPacket(pBuffer->GetBuffer(),
  243.     pBuffer->GetBuffer(), 
  244.     pBuffer->GetSize(),
  245.     pBuffer->GetSize(),
  246.     pPayloadData->GetTime(),
  247.     MDPCKT_USES_IHXBUFFER_FLAG,
  248.     NULL);
  249.     pBuffer->Release();
  250. }
  251.     }
  252.     return pFramePacket;
  253. }
  254. /****************************************************************************
  255.  *  Method:
  256.  *    CVideoFormat::ReturnAssembledPacket
  257.  *
  258.  */
  259. void CVideoFormat::ReturnAssembledPacket(CMediaPacket* pFramePacket)
  260. {
  261.     if (pFramePacket)
  262.     {
  263. m_pMutex->Lock();
  264. m_InputQueue.AddTail(pFramePacket);
  265. m_pMutex->Unlock();
  266.     }
  267. }
  268. /****************************************************************************
  269.  *  Method:
  270.  *    CVideoFormat::Enqueue
  271.  *
  272.  */
  273. BOOL CVideoFormat::Enqueue(IHXPacket* pPayloadData)
  274. {
  275.     BOOL bEnqueued = FALSE;
  276.     CMediaPacket* pFramePacket = NULL;
  277.     
  278.     m_pAssemblerMutex->Lock();
  279.     pFramePacket = CreateAssembledPacket(pPayloadData);
  280.   
  281.     if (pFramePacket != NULL)
  282.     {
  283. m_pMutex->Lock();
  284. m_InputQueue.AddTail(pFramePacket);
  285. m_pMutex->Unlock();
  286. bEnqueued = TRUE;
  287.     } 
  288.     m_pAssemblerMutex->Unlock();
  289.      
  290.     return bEnqueued;
  291. }
  292. /****************************************************************************
  293.  *  Method:
  294.  *    CVideoFormat::Requeue
  295.  *
  296.  */
  297. HX_RESULT CVideoFormat::Requeue(CMediaPacket* pFramePacket)
  298. {
  299.     if (pFramePacket != NULL)
  300.     {
  301. m_pMutex->Lock();
  302. m_InputQueue.AddHead(pFramePacket);
  303. m_pMutex->Unlock();
  304.     }
  305.     return HXR_OK;
  306. }
  307. /****************************************************************************
  308.  *  Method:
  309.  *    CVideoFormat::Dequeue
  310.  *
  311.  */
  312. CMediaPacket* CVideoFormat::Dequeue(void)
  313. {
  314.     CMediaPacket* pPacket = (CMediaPacket*) m_pOutputQueue->Get();
  315. #ifdef ENABLE_FRAME_TRACE
  316.     if (pPacket && (ulFrameTraceIdx < MAX_FRAME_TRACE_ENTRIES))
  317.     {
  318. frameTraceArray[ulFrameTraceIdx][2] = pPacket->m_ulTime;
  319. frameTraceArray[ulFrameTraceIdx][0] = 
  320.     (LONG32) pPacket->m_pData;
  321. frameTraceArray[ulFrameTraceIdx++][1] = 'G';
  322.     }
  323. #endif // ENABLE_FRAME_TRACE
  324.     return pPacket;
  325. }
  326. /****************************************************************************
  327.  *  Method:
  328.  *    CVideoFormat::Reset
  329.  *
  330.  */
  331. void CVideoFormat::Reset(void)
  332. {
  333.     _Reset();
  334. }
  335. void CVideoFormat::_Reset()
  336. {
  337.     m_pMutex->Lock();
  338.     CMediaPacket* pFrame;
  339.     
  340.     while (!m_InputQueue.IsEmpty())
  341.     {
  342. pFrame = (CMediaPacket*) m_InputQueue.RemoveHead();
  343. pFrame->Clear();
  344. delete pFrame;
  345.     }
  346.     
  347.     FlushOutputQueue();
  348.     m_pMutex->Unlock();
  349. }
  350. /****************************************************************************
  351.  *  Method:
  352.  *    CVideoFormat::DecodeFrame
  353.  *
  354.  */
  355. void CVideoFormat::FlushOutputQueue(void)
  356. {
  357.     CMediaPacket* pFrame;
  358.     if (m_pOutputQueue)
  359.     {
  360. while ((pFrame = (CMediaPacket*) m_pOutputQueue->Get()) != NULL)
  361. {
  362. #ifdef ENABLE_FRAME_TRACE
  363.     if (ulFrameTraceIdx < MAX_FRAME_TRACE_ENTRIES)
  364.     {
  365. frameTraceArray[ulFrameTraceIdx][2] = pFrame->m_ulTime;
  366. frameTraceArray[ulFrameTraceIdx][0] = 
  367.     (LONG32) pFrame->m_pData;
  368. frameTraceArray[ulFrameTraceIdx++][1] = 'F';
  369.     }
  370. #endif // ENABLE_FRAME_TRACE
  371.     pFrame->Clear();
  372.     delete pFrame;
  373. }
  374.     }
  375. }
  376. /****************************************************************************
  377.  *  Method:
  378.  *    CVideoFormat::DecodeFrame
  379.  *
  380.  */
  381. BOOL CVideoFormat::DecodeFrame(void)
  382. {
  383.     CMediaPacket* pEncodedPacket;
  384.     CMediaPacket* pDecodedPacket = NULL;
  385.     ULONG32 ulLoopCounter = 0;
  386.     m_pVideoRenderer->BltIfNeeded();
  387.     m_pDecoderMutex->Lock();
  388.     m_pMutex->Lock();
  389.     
  390.     if ((!m_InputQueue.IsEmpty()) &&
  391. (!m_pOutputQueue->IsFull()) &&
  392. (!m_bDecodeSuspended))
  393.     {
  394. do
  395. {
  396.     pEncodedPacket = (CMediaPacket*) m_InputQueue.RemoveHead();
  397.     m_pMutex->Unlock();
  398.     pDecodedPacket = CreateDecodedPacket(pEncodedPacket);
  399.     if (pDecodedPacket)
  400.     {
  401. #ifdef ENABLE_FRAME_TRACE
  402. if (ulFrameTraceIdx < MAX_FRAME_TRACE_ENTRIES)
  403. {
  404.     frameTraceArray[ulFrameTraceIdx][2] = pDecodedPacket->m_ulTime;
  405.     frameTraceArray[ulFrameTraceIdx][0] = 
  406. (LONG32) pDecodedPacket->m_pData;
  407.     frameTraceArray[ulFrameTraceIdx++][1] = 'D';
  408. }
  409. #endif // ENABLE_FRAME_TRACE
  410. m_pOutputQueue->Put(pDecodedPacket);
  411. if (pDecodedPacket->m_pData)
  412. {
  413.     m_pDecoderMutex->Unlock();
  414.     m_pVideoRenderer->BltIfNeeded();
  415.     return TRUE;
  416. }
  417.     }
  418.     m_pDecoderMutex->Unlock();
  419.             if( m_LastError == HXR_OUTOFMEMORY )
  420.             {
  421.                 m_bDecodeSuspended = TRUE;
  422.             }
  423.             else
  424.             {
  425.                 m_pVideoRenderer->BltIfNeeded();
  426.             }
  427.     ulLoopCounter++;
  428.     m_pDecoderMutex->Lock();
  429.     m_pMutex->Lock();
  430. } while ((!m_InputQueue.IsEmpty()) &&
  431.  (!m_pOutputQueue->IsFull()) &&
  432.  ((ulLoopCounter++) < MAX_DECODE_SPIN) &&
  433.  (!m_bDecodeSuspended));
  434.     }
  435.     m_pMutex->Unlock();
  436.     m_pDecoderMutex->Unlock();
  437.     
  438.     return pDecodedPacket ? TRUE : FALSE;
  439. }
  440. /****************************************************************************
  441.  *  Method:
  442.  *    CVideoFormat::ReturnDecodedPacket
  443.  *
  444.  */
  445. BOOL CVideoFormat::ReturnDecodedPacket(CMediaPacket* pDecodedPacket)
  446. {
  447.     BOOL bPacketAccepted = FALSE;
  448.     if (pDecodedPacket)
  449.     {
  450. #ifdef ENABLE_FRAME_TRACE
  451. if (ulFrameTraceIdx < MAX_FRAME_TRACE_ENTRIES)
  452. {
  453.     frameTraceArray[ulFrameTraceIdx][2] = pDecodedPacket->m_ulTime;
  454.     frameTraceArray[ulFrameTraceIdx][0] = 
  455. (LONG32) pDecodedPacket->m_pData;
  456.     frameTraceArray[ulFrameTraceIdx++][1] = 'D';
  457. }
  458. #endif // ENABLE_FRAME_TRACE
  459.     
  460. bPacketAccepted = m_pOutputQueue->Put(pDecodedPacket);
  461.     }
  462.     return bPacketAccepted;
  463. }
  464. /****************************************************************************
  465.  *  Method:
  466.  *    CVideoFormat::GetMaxDecodedFrames
  467.  *
  468.  */
  469. ULONG32 CVideoFormat::GetMaxDecodedFrames(void)
  470. {
  471.     return MAX_BUFFERED_DECODED_FRAMES;
  472. }
  473. /****************************************************************************
  474.  *  Method:
  475.  *    CVideoFormat::CreateDecodedPacket
  476.  *
  477.  */
  478. CMediaPacket* CVideoFormat::CreateDecodedPacket(CMediaPacket* pCodedPacket)
  479. {
  480.     CMediaPacket* pDecodedPacket = NULL;
  481.     if (pCodedPacket != NULL)
  482.     {
  483. pCodedPacket->Clear();
  484. delete pCodedPacket;
  485. pCodedPacket = NULL;
  486.     }
  487.     return pDecodedPacket;
  488. }
  489. /****************************************************************************
  490.  *  Method:
  491.  *    CVideoFormat::OnDecodedPacketRelease
  492.  *
  493.  */
  494. void CVideoFormat::OnDecodedPacketRelease(CMediaPacket* &pPacket)
  495. {
  496. #ifdef ENABLE_FRAME_TRACE
  497.     if (ulFrameTraceIdx < MAX_FRAME_TRACE_ENTRIES)
  498.     {
  499. frameTraceArray[ulFrameTraceIdx][2] = pPacket->m_ulTime;
  500. frameTraceArray[ulFrameTraceIdx][0] = 
  501.     (LONG32) pPacket->m_pData;
  502. frameTraceArray[ulFrameTraceIdx++][1] = 'R';
  503.     }
  504. #endif // ENABLE_FRAME_TRACE
  505.     ;
  506. }
  507. /****************************************************************************
  508.  *  Method:
  509.  *    CVideoFormat::InitBitmapInfoHeader
  510.  *
  511.  */
  512. HX_RESULT CVideoFormat::InitBitmapInfoHeader(
  513.     HXBitmapInfoHeader &BitmapInfoHeader,
  514.     CMediaPacket* pVideoPacket)
  515. {
  516.     HX_RESULT retVal = HXR_OK;
  517.     return retVal;
  518. }
  519. /****************************************************************************
  520.  *  Method:
  521.  *    CVideoFormat::GetDefaultPreroll
  522.  *
  523.  */
  524. ULONG32 CVideoFormat::GetDefaultPreroll(IHXValues* pValues)
  525. {
  526.     return FORMAT_DEFAULT_PREROLL;
  527. }
  528. /****************************************************************************
  529.  *  Method:
  530.  *    CVideoFormat::GetMinimumPreroll
  531.  *
  532.  */
  533. ULONG32 CVideoFormat::GetMinimumPreroll(IHXValues* pValues)
  534. {
  535.     return FORMAT_MINIMUM_PREROLL;
  536. }
  537. /****************************************************************************
  538.  *  Method:
  539.  *    CVideoFormat::GetMaximumPreroll
  540.  *
  541.  */
  542. ULONG32 CVideoFormat::GetMaximumPreroll(IHXValues* pValues)
  543. {
  544.     return FORMAT_MAXIMUM_PREROLL;
  545. }
  546. /****************************************************************************
  547.  *  Method:
  548.  *    CVideoFormat::GetMimeTypes
  549.  *
  550.  */
  551. const char** CVideoFormat::GetMimeTypes(void)
  552. {
  553.     return NULL;
  554. }
  555. // *** IUnknown methods ***
  556. /****************************************************************************
  557. *  IUnknown::AddRef                                            ref:  hxcom.h
  558. *
  559. *  This routine increases the object reference count in a thread safe
  560. *  manner. The reference count is used to manage the lifetime of an object.
  561. *  This method must be explicitly called by the user whenever a new
  562. *  reference to an object is used.
  563. */
  564. STDMETHODIMP_(ULONG32) CVideoFormat::AddRef()
  565. {
  566.     return InterlockedIncrement(&m_lRefCount);
  567. }
  568. /****************************************************************************
  569. *  IUnknown::Release                                           ref:  hxcom.h
  570. *
  571. *  This routine decreases the object reference count in a thread safe
  572. *  manner, and deletes the object if no more references to it exist. It must
  573. *  be called explicitly by the user whenever an object is no longer needed.
  574. */
  575. STDMETHODIMP_(ULONG32) CVideoFormat::Release()
  576. {
  577.     if (InterlockedDecrement(&m_lRefCount) > 0)
  578.     {
  579.         return m_lRefCount;
  580.     }
  581.     
  582.     delete this;
  583.     return 0;
  584. }
  585. /****************************************************************************
  586. *  IUnknown::QueryInterface                                    ref:  hxcom.h
  587. *
  588. *  This routine indicates which interfaces this object supports. If a given
  589. *  interface is supported, the object's reference count is incremented, and
  590. *  a reference to that interface is returned. Otherwise a NULL object and
  591. *  error code are returned. This method is called by other objects to
  592. *  discover the functionality of this object.
  593. */
  594. STDMETHODIMP CVideoFormat::QueryInterface(REFIID riid, void** ppvObj)
  595. {
  596.     if (IsEqualIID(riid, IID_IUnknown))
  597.     {
  598. AddRef();
  599. *ppvObj = (IUnknown*)(IHXPlugin*) this;
  600. return HXR_OK;
  601.     }
  602.     
  603.     *ppvObj = NULL;
  604.     return HXR_NOINTERFACE;
  605. }
  606. HX_RESULT
  607. CVideoFormat::GetLastError()
  608. {
  609.     return m_LastError;
  610. }