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

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