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

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. /****************************************************************************
  36.  *  Debug Settings
  37.  */
  38. // #define ENABLE_TRACE
  39. // #define ENABLE_SYNC_TRACE
  40. // #define ENABLE_SCHED_TRACE
  41. // #define ENABLE_FETCH_TRACE
  42. // #define ENABLE_INPUT_TRACE
  43. /****************************************************************************
  44.  *  Operational Compile-time Settings
  45.  */
  46. // #define SYNC_RESIZE_OK
  47. // #define SYNC_VS_SWITCHING
  48. // #define REBUFFER_ON_VIDEO
  49. #define SET_NONZERO_VIEWFRAME_ONLY
  50. #define RESIZE_AFTER_SITE_ATTACHED
  51. #define DO_ABSOLUTE_TIMING
  52. #ifdef HELIX_FEATURE_VIDREND_SYNCSMOOTHING
  53. #define SYNC_SMOOTHING
  54. #define SYNC_PRE_SMOOTHING
  55. #endif // HELIX_FEATURE_VIDREND_SYNCSMOOTHING
  56. #define DEFAULT_VS2_TARGETRECT
  57. #define MAX_ULONG32_AS_DOUBLE ((double) ((ULONG32) 0xFFFFFFFF))
  58. #define MAX_LONG32_AS_DOUBLE ((double) ((LONG32) 0x7FFFFFFF))
  59. #define MIN_LONG32_AS_DOUBLE ((double) ((LONG32) 0x80000000))
  60. #if defined(_MACINTOSH) || defined(_MAC_UNIX)
  61. #define OSGRANULE_BOOSTING_ENABLED  FALSE
  62. #else // _MACINTOSH
  63. #define OSGRANULE_BOOSTING_ENABLED  TRUE
  64. #endif // _MACINTOSH
  65. /****************************************************************************
  66.  *  Debug Macros
  67.  */
  68. #ifdef ENABLE_TRACE
  69. #define HX_TRACE_THINGY(x, m, l)
  70.     {
  71. FILE* f1;
  72. f1 = ::fopen(x, "a+");
  73. (f1)?(::fprintf(f1, "%ld - %s = %ld n", HX_GET_BETTERTICKCOUNT(), m, l), ::fclose(f1)):(0);
  74.     }
  75. #else // ENABLE_TRACE
  76. #define HX_TRACE_THINGY(x, m, l)
  77. #endif // ENABLE_TRACE
  78. /****************************************************************************
  79.  *  Defines
  80.  */
  81. #define BASE_VIDEO_RENDERER_NAME    "Basic Video"
  82. #define NAME_STATS_EXT     ".name"
  83. #define C4CC_STATS_EXT     ".CodecFourCC"
  84. #if defined(HELIX_FEATURE_VIDREND_NO_DEFAULT_WINDOW_SIZE)
  85. #define DEFAULT_WIN_SIZE_X     0
  86. #define DEFAULT_WIN_SIZE_Y     0
  87. #else
  88. #define DEFAULT_WIN_SIZE_X     160
  89. #define DEFAULT_WIN_SIZE_Y     120
  90. #endif
  91. #define SYNC_INTERVAL     20     // in milliseconds
  92. #define EARLY_FRAME_TOL     3     // in milliseconds
  93. #define LATE_FRAME_TOL     30     // in milliseconds
  94. #define NO_FRAMES_POLLING_INTERVAL  20     // in milliseconds
  95. #define MAX_SLEEP_TIME     132     // in milliseconds
  96. #define BLT_PACKET_QUEUE_SIZE     3     // in packets
  97. #define SYNC_GOAL_SMOOTHING_DEPTH   30     // number of samples
  98. #define SPEEDUP_GOAL_SMOOTHING_DEPTH 8     // number of samples
  99. #define MAX_BAD_SAMPLE_INTERVAL     1000    // in milliseconds
  100. #define VIDEO_STAT_INTERVAL     1000    // in milliseconds
  101. #define VIDEO_STAT_INTERVAL_COUNT   2     // number of intervals to average over
  102. #define MAX_OPTIMIZED_VIDEO_LEAD 200 // in milliseconds
  103. #define DEFAULT_HARDWARE_BUFFER_COUNT 4
  104. #define AUDIO_SKEW_POWER     4     // Maximum Audio Speedup Slope as
  105.     // 1/(2^AUDIO_SKEW_POWER)
  106. #define MIN_BAD_PERSISTENCE_COUNT   0     // Minimum number of consecutive
  107.     // bad sync samples for the
  108.     // resync probation period to start
  109. #define MIN_GOOD_PERSISTENCE_COUNT  0     // Minimum number of consecutive
  110.     // good sync samples for the
  111.     // resync probation period to be
  112.     // cancelled
  113. #define MAX_BLT_LOOPS     3
  114. #define BLT_RELIEF_DELAY     1     // in milliseconds
  115. // Absolute timing settings
  116. #define N_STABILIZATION_ITERATIONS  5
  117. #define MAX_ALLOWED_TIMING_ERROR    2
  118. #define SMALLEST_TIMABLE_PERIOD     2
  119. // Default Decoding Priority
  120. #ifdef _WIN32
  121.     #ifdef HELIX_FEATURE_VIDREND_BOOSTDECODE_ON_STARTUP
  122.     // on ce we need to get this started quickly, otherwise the initial packets expire
  123.     // we set the priority so we can check in onpace to reset only once
  124.     #define DFLT_DECODE_PRIORITY     THREAD_PRIORITY_HIGHEST
  125.     #define DFLT_PRESENT_PRIORITY     THREAD_PRIORITY_ABOVE_NORMAL
  126.     #else
  127.     #define DFLT_DECODE_PRIORITY     THREAD_PRIORITY_BELOW_NORMAL
  128.     #define DFLT_PRESENT_PRIORITY     THREAD_PRIORITY_ABOVE_NORMAL
  129.     #endif // HELIX_FEATURE_VIDREND_BOOSTDECODE_ON_STARTUP
  130. #else // _WIN32
  131. #define DFLT_DECODE_PRIORITY     0
  132. #define DFLT_PRESENT_PRIORITY     0
  133. #endif // _WIN32
  134. // Lowest acceptable version numbers
  135. #define STREAM_MAJOR_VERSION  0
  136. #define STREAM_MINOR_VERSION  0
  137. #define CONTENT_MAJOR_VERSION 0
  138. #define CONTENT_MINOR_VERSION 0
  139. #define DECODER_INTERVAL 5
  140. #define BLTR_INTERVAL 5
  141. #ifdef _WIN32
  142. #define GETBITMAPCOLOR(x) GetBitmapColor( (LPBITMAPINFO)(x) )
  143. #else // _WIN32
  144. #define GETBITMAPCOLOR(x) GetBitmapColor( (HXBitmapInfo*)(x))
  145. #endif // _WIN32
  146. /****************************************************************************
  147.  *  Includes
  148.  */
  149. #include "hlxclib/stdio.h"
  150. #include "vidrend.ver"
  151. #include "hxtypes.h"
  152. #ifdef _WINDOWS
  153. #include <windows.h>
  154. #endif
  155. #if defined(_UNIX) && !defined(_MAC_UNIX)
  156. #include <stdio.h>
  157. #include <stdlib.h>
  158. #include <unistd.h>
  159. #ifndef QWS
  160. #include <X11/Intrinsic.h>
  161. #include <X11/StringDefs.h>
  162. #include <X11/Shell.h>
  163. #endif /* QWS */
  164. #endif
  165. #include "hxwintyp.h"
  166. #include "hxcom.h"
  167. #include "hxcomm.h"
  168. #include "hxthread.h"
  169. // for sync
  170. #include "hxengin.h"
  171. #include "hxprefs.h"
  172. #include "hxtick.h"
  173. #include "timeval.h"
  174. #include "hxevent.h"
  175. #include "hxvsurf.h"
  176. #include "ihxpckts.h"
  177. #include "hxfiles.h"
  178. #include "hxcore.h"
  179. #include "hxerror.h"
  180. #include "hxrendr.h"
  181. #include "addupcol.h"
  182. // #include "hxhyper.h"
  183. #include "hxplugn.h"
  184. #include "hxwin.h"
  185. // #include "hxasm.h"
  186. #include "hxmon.h"
  187. #include "hxbuffer.h" // for CHXBuffer
  188. #include "hxassert.h" // for HX_ASSERT()
  189. #include "hxheap.h" // for heap checking
  190. #include "hxslist.h" // CHXSimpleList
  191. #include "chxbufpl.h"
  192. #include "sdpchunk.h"
  193. #include "vidrend.h"
  194. #include "cpacemkr.h"
  195. #include "hxver.h"
  196. #if defined(_WINDOWS) && !defined(WIN32_PLATFORM_PSPC)
  197. #include "ddraw.h"
  198. #endif /* defined(_WINDOWS) && !defined(WIN32_PLATFORM_PSPC) */
  199. // #include "coloracc.h"
  200. #include "colormap.h"
  201. #include "chxxtype.h"   // For CHXxSize
  202. #if defined(HELIX_FEATURE_PREFERENCES)
  203. #include "hxprefs.h"
  204. #include "hxprefutil.h"
  205. #endif /* HELIX_FEATURE_PREFERENCES */
  206. /****************************************************************************
  207.  *  Debug
  208.  */
  209. #ifdef ENABLE_SYNC_TRACE
  210. #define MAX_SYNC_TRACE_ENTRIES 10000
  211. ULONG32 ulSyncTraceIdx = 0;
  212. ULONG32 syncTraceArray[MAX_SYNC_TRACE_ENTRIES][3];
  213. void DumpSyncEntries(void)
  214. {
  215.     FILE* pFile = NULL;
  216.     ULONG32 ulIdx;
  217.     if (ulSyncTraceIdx > 0)
  218.     {
  219. pFile = fopen("\helix\sync.txt", "wb");
  220.     }
  221.     if (pFile)
  222.     {
  223. for (ulIdx = 0; ulIdx < ulSyncTraceIdx; ulIdx++)
  224. {
  225.     fprintf(pFile, "%ut%ut%un", syncTraceArray[ulIdx][0],
  226.    syncTraceArray[ulIdx][1],
  227.    syncTraceArray[ulIdx][2]);
  228. }
  229. fclose(pFile);
  230.     }
  231.     ulSyncTraceIdx = 0;
  232. }
  233. #endif // ENABLE_SYNC_TRACE
  234. #ifdef ENABLE_SCHED_TRACE
  235. #define MAX_SCHED_TRACE_ENTRIES 10000
  236. ULONG32 ulSchedTraceIdx = 0;
  237. LONG32 schedTraceArray[MAX_SCHED_TRACE_ENTRIES];
  238. void DumpSchedEntries(void)
  239. {
  240.     FILE* pFile = NULL;
  241.     ULONG32 ulIdx;
  242.     if (ulSchedTraceIdx > 0)
  243.     {
  244. pFile = fopen("\helix\sched.txt", "wb");
  245.     }
  246.     if (pFile)
  247.     {
  248. for (ulIdx = 0; ulIdx < ulSchedTraceIdx; ulIdx++)
  249. {
  250.     fprintf(pFile, "%dn", schedTraceArray[ulIdx]);
  251. }
  252. fclose(pFile);
  253.     }
  254.     ulSchedTraceIdx = 0;
  255. }
  256. #endif // ENABLE_SCHED_TRACE
  257. #ifdef ENABLE_FETCH_TRACE
  258. #define MAX_FETCH_TRACE_ENTRIES 10000
  259. ULONG32 ulFetchTraceIdx = 0;
  260. LONG32 fetchTraceArray[MAX_FETCH_TRACE_ENTRIES];
  261. void DumpFetchEntries(void)
  262. {
  263.     FILE* pFile = NULL;
  264.     ULONG32 ulIdx;
  265.     if (ulFetchTraceIdx > 0)
  266.     {
  267. pFile = fopen("\helix\fetch.txt", "wb");
  268.     }
  269.     if (pFile)
  270.     {
  271. for (ulIdx = 0; ulIdx < ulFetchTraceIdx; ulIdx++)
  272. {
  273.     fprintf(pFile, "%dn", fetchTraceArray[ulIdx]);
  274. }
  275. fclose(pFile);
  276.     }
  277.     ulFetchTraceIdx = 0;
  278. }
  279. #endif // ENABLE_FETCH_TRACE
  280. #ifdef ENABLE_INPUT_TRACE
  281. #define MAX_INPUT_TRACE_ENTRIES 10000
  282. ULONG32 ulInputTraceIdx = 0;
  283. LONG32 inputTraceArray[MAX_INPUT_TRACE_ENTRIES];
  284. void DumpInputEntries(void)
  285. {
  286.     FILE* pFile = NULL;
  287.     ULONG32 ulIdx;
  288.     if (ulInputTraceIdx > 0)
  289.     {
  290. pFile = fopen("\helix\input.txt", "wb");
  291.     }
  292.     if (pFile)
  293.     {
  294. for (ulIdx = 0; ulIdx < ulInputTraceIdx; ulIdx++)
  295. {
  296.     fprintf(pFile, "%dn", inputTraceArray[ulIdx]);
  297. }
  298. fclose(pFile);
  299.     }
  300.     ulInputTraceIdx = 0;
  301. }
  302. #endif // ENABLE_INPUT_TRACE
  303. /****************************************************************************
  304.  *  Constants
  305.  */
  306. const char* const CVideoRenderer::zm_pDescription    = "RealNetworks Video Renderer Plugin";
  307. const char* const CVideoRenderer::zm_pCopyright      = HXVER_COPYRIGHT;
  308. const char* const CVideoRenderer::zm_pMoreInfoURL    = HXVER_MOREINFO;
  309. const char* const CVideoRenderer::zm_pStreamMimeTypes[] =
  310. {
  311.     NULL
  312. };
  313. /************************************************************************
  314.  *  CVideoRenderer
  315.  */
  316. /************************************************************************
  317.  *  Constructor/Destructor
  318.  */
  319. CVideoRenderer::CVideoRenderer(void)
  320. : m_lRefCount(0)
  321. , m_pContext(NULL)
  322. , m_pStream(NULL)
  323. , m_pHeader(NULL)
  324. , m_pMutex(NULL)
  325. , m_pBltMutex(NULL)
  326. , m_pVSMutex(NULL)
  327. , m_pDecoderPump(NULL)
  328. , m_pBltrPump(NULL)
  329. , m_ulDecoderPacemakerId(0)
  330. , m_ulBltrPacemakerId(0)
  331. , m_pDecoderVideoFormat(NULL)
  332. , m_pBltrVideoFormat(NULL)
  333. , m_pBackChannel(0)
  334. , m_pCommonClassFactory(0)
  335. , m_ulRegistryID(0)
  336. , m_pVideoStats(NULL)
  337. , m_pMISUS(NULL)
  338. , m_pMISUSSite(NULL)
  339. , m_ulEarlyFrameTol(EARLY_FRAME_TOL)
  340. , m_ulLateFrameTol(LATE_FRAME_TOL)
  341. , m_ulNoFramesPollingInterval(NO_FRAMES_POLLING_INTERVAL)
  342. , m_ulMaxSleepTime(MAX_SLEEP_TIME)
  343. , m_ulBltPacketQueueSize(BLT_PACKET_QUEUE_SIZE)
  344. , m_ulSyncGoalSmoothingDepth(SYNC_GOAL_SMOOTHING_DEPTH)
  345. , m_ulSpeedupGoalSmoothingDepth(SPEEDUP_GOAL_SMOOTHING_DEPTH)
  346. , m_ulMaxBadSeqSamples(0)
  347. , m_lTimeLineOffset(0)
  348. , m_lDecodePriority(DFLT_DECODE_PRIORITY)
  349. , m_ulStreamBaseTime(0)
  350. , m_ulBaseTime(0)
  351. , m_ulTimeNormalizationOffset(0)
  352. , m_bBitmapSet(FALSE)
  353. , m_bFrameSizeInitialized(FALSE)
  354. , m_bWinSizeFixed(FALSE)
  355. , m_bOSGranuleBoost(OSGRANULE_BOOSTING_ENABLED)
  356. , m_bOSGranuleBoostVS2(OSGRANULE_BOOSTING_ENABLED)
  357. , m_bOptimizedBlt(FALSE)
  358. , m_bUseVideoSurface2(FALSE)
  359. #if defined(_WINDOWS) && defined(HELIX_FEATURE_VIDREND_OPTIMIZEDVIDEO)
  360. , m_bTryVideoSurface2(TRUE)
  361. #else // _WINDOWS
  362. , m_bTryVideoSurface2(FALSE)
  363. #endif // _WINDOWS
  364. , m_bVideoSurface2Transition(FALSE)
  365. , m_bVideoSurface1Requested(FALSE)
  366. , m_bVideoSurfaceInitialized(FALSE)
  367. , m_bVideoSurfaceReinitRequested(FALSE)
  368. , m_bPresentInProgress(FALSE)
  369. , m_bVS2BufferUnavailableOnLastBlt(FALSE)
  370. , m_ulHWBufCount(DEFAULT_HARDWARE_BUFFER_COUNT)
  371. , m_ulConfigHWBufCount(DEFAULT_HARDWARE_BUFFER_COUNT)
  372. , m_pClipRect(NULL)
  373. , m_pPreferences(NULL)
  374. , m_pRegistry(NULL)
  375. , m_pScheduler(NULL)
  376. , m_pOptimizedScheduler(NULL)
  377. , m_bPendingCallback(FALSE)
  378. , m_bSchedulerStartRequested(FALSE)
  379. , m_hPendingHandle(0)
  380. , m_ulCallbackCounter(0)
  381. , m_bDecoderRunning(FALSE)
  382. , m_bSiteAttached(FALSE)
  383. , m_PlayState(Stopped)
  384. , m_ulBytesToBuffer(0)
  385. , m_ulAvgBitRate(0)
  386. , m_ulPreroll(0)
  387. , m_ulBufferingStartTime(0)
  388. , m_ulBufferingStopTime(0)
  389. , m_ulBufferingTimeOut(0)
  390. , m_bBufferingOccured(FALSE)
  391. , m_bBufferingNeeded(FALSE)
  392. , m_pVideoFormat(NULL)
  393. , m_pBltPacketQueue(NULL)
  394. , m_pActiveVideoPacket(NULL)
  395. , m_ulActiveVideoTime(0)
  396. , m_bFirstFrame(TRUE)
  397. , m_bBaseTimeSet(FALSE)
  398. , m_bFirstSurfaceUpdate(TRUE)
  399. , m_bPendingRedraw(FALSE)
  400. , m_bVS1UpdateInProgress(FALSE)
  401. , m_ulSyncSmoothingDepth(0)
  402. , m_ulSyncInterval(SYNC_INTERVAL)
  403. , m_ulBadSeqSampleCount(0)
  404. , m_ulGoodSeqSampleCount(0)
  405. , m_fTrendSyncDelta(0.0)
  406. , m_pResizeCB(NULL)
  407. , m_pVSurf2InputBIH(NULL)
  408. , m_bIsScheduledCB(0)
  409. #ifdef HELIX_FEATURE_VIDREND_UNTIMED_DECODE
  410. , m_bUntimedRendering(FALSE)
  411. #endif /* HELIX_FEATURE_VIDREND_UNTIMED_DECODE */
  412. , m_bActiveVideoPacketLocalized(FALSE)
  413. {
  414.     m_SetWinSize.cx = 0;
  415.     m_SetWinSize.cy = 0;
  416.     m_LastSetSize.cx = 0;
  417.     m_LastSetSize.cy = 0;
  418.     m_rViewRect.left   = 0;
  419.     m_rViewRect.top    = 0;
  420.     m_rViewRect.right  = 0;
  421.     m_rViewRect.bottom = 0; 
  422.     memset(&m_BitmapInfoHeader, 0, sizeof(HXBitmapInfoHeader));
  423. }
  424. CVideoRenderer::~CVideoRenderer()
  425. {
  426.     // NOTE: You should do your renderer cleanup here, instead of
  427.     // in EndStream(), because your renderer is still left around
  428.     // after the stream is ended in case it is a display renderer
  429.     // and it needs to "paint" it's display area.
  430.     EndOptimizedBlt();
  431.     if (m_pActiveVideoPacket)
  432.     {
  433. m_pActiveVideoPacket->Clear();
  434. delete m_pActiveVideoPacket;
  435. m_pActiveVideoPacket = NULL;
  436. m_ulActiveVideoTime = 0;
  437.     }
  438.     HX_RELEASE(m_pHeader);
  439.     HX_RELEASE(m_pContext);
  440.     HX_RELEASE(m_pCommonClassFactory);
  441.     if (m_pVideoFormat)
  442.     {
  443.         m_pVideoFormat->Release();
  444.         m_pVideoFormat = NULL;
  445.     }
  446.     HX_DELETE(m_pVSurf2InputBIH);
  447.     HX_DELETE(m_pClipRect);
  448.     HX_DELETE(m_pMutex);
  449.     HX_DELETE(m_pBltMutex);
  450.     HX_DELETE(m_pVSMutex);
  451.     RemoveCallback(m_hPendingHandle);
  452.     m_bPendingCallback = FALSE;
  453.     HX_RELEASE(m_pOptimizedScheduler);
  454.     HX_RELEASE(m_pScheduler);
  455.     HX_RELEASE(m_pPreferences);
  456.     HX_RELEASE(m_pRegistry);
  457.     ClearBltPacketQueue();
  458.     HX_DELETE(m_pBltPacketQueue);
  459.     HX_RELEASE(m_pResizeCB);
  460. #if defined(HELIX_FEATURE_STATS)
  461.     HX_DELETE(m_pVideoStats);
  462. #endif /* HELIX_FEATURE_STATS */
  463. }
  464. /************************************************************************
  465.  *  IHXPlugin Methods
  466.  */
  467. /************************************************************************
  468.  *  Method:
  469.  *    IHXPlugin::InitPlugin
  470.  *  Purpose:
  471.  *    Initializes the plugin for use. This interface must always be
  472.  *    called before any other method is called. This is primarily needed
  473.  *    so that the plugin can have access to the context for creation of
  474.  *    IHXBuffers and IMalloc.
  475.  */
  476. STDMETHODIMP CVideoRenderer::InitPlugin(IUnknown* /*IN*/ pContext)
  477. {
  478.     HX_RESULT retVal = HXR_OK;
  479.     HX_ASSERT(pContext);
  480.     m_pContext = pContext;
  481.     m_pContext->AddRef();
  482.     retVal = m_pContext->QueryInterface(IID_IHXCommonClassFactory,
  483. (void**) &m_pCommonClassFactory);
  484.     if (SUCCEEDED(retVal))
  485.     {
  486. m_pContext->QueryInterface(IID_IHXPreferences,
  487.                                    (void**) &m_pPreferences);
  488.     }
  489.     m_pContext->QueryInterface(IID_IHXRegistry, (void**) &m_pRegistry);
  490.     if (SUCCEEDED(retVal))
  491.     {
  492. retVal = m_pContext->QueryInterface(IID_IHXScheduler,
  493.     (void **) &m_pScheduler);
  494.     }
  495.     if (SUCCEEDED(retVal) && !m_pMutex)
  496.     {
  497. #ifdef THREADS_SUPPORTED
  498. retVal = HXMutex::MakeMutex(m_pMutex);
  499. #else  // THREADS_SUPPORTED
  500. retVal = HXMutex::MakeStubMutex(m_pMutex);
  501. #endif  // THREADS_SUPPORTED
  502.     }
  503.     if (SUCCEEDED(retVal) && !m_pBltMutex)
  504.     {
  505. #ifdef THREADS_SUPPORTED
  506. retVal = HXMutex::MakeMutex(m_pBltMutex);
  507. #else  // THREADS_SUPPORTED
  508. retVal = HXMutex::MakeStubMutex(m_pBltMutex);
  509. #endif  // THREADS_SUPPORTED
  510.     }
  511.     if (SUCCEEDED(retVal) && !m_pVSMutex)
  512.     {
  513. #ifdef THREADS_SUPPORTED
  514. retVal = HXMutex::MakeMutex(m_pVSMutex);
  515. #else  // THREADS_SUPPORTED
  516. retVal = HXMutex::MakeStubMutex(m_pVSMutex);
  517. #endif  // THREADS_SUPPORTED
  518.     }
  519. #if defined(HELIX_FEATURE_STATS)
  520.     if (SUCCEEDED(retVal))
  521.     {
  522. m_pVideoStats = new CVideoStatistics(m_pContext,
  523.      VIDEO_STAT_INTERVAL_COUNT);
  524. retVal = HXR_OUTOFMEMORY;
  525. if (m_pVideoStats)
  526. {
  527.     retVal = HXR_OK;
  528. }
  529.     }
  530. #endif /* HELIX_FEATURE_STATS */
  531.     if (FAILED(retVal))
  532.     {
  533. HX_RELEASE(m_pCommonClassFactory);
  534. HX_RELEASE(m_pPreferences);
  535. HX_RELEASE(m_pRegistry);
  536. HX_RELEASE(m_pScheduler);
  537.     }
  538.     return retVal;
  539. }
  540. /************************************************************************
  541.  *  Method:
  542.  *    IHXPlugin::GetPluginInfo
  543.  *  Purpose:
  544.  *    Returns the basic information about this plugin. Including:
  545.  *
  546.  *    bLoadMultiple whether or not this plugin DLL can be loaded
  547.  * multiple times. All File Formats must set
  548.  * this value to TRUE.
  549.  *    pDescription which is used in about UIs (can be NULL)
  550.  *    pCopyright which is used in about UIs (can be NULL)
  551.  *    pMoreInfoURL which is used in about UIs (can be NULL)
  552.  */
  553. STDMETHODIMP CVideoRenderer::GetPluginInfo
  554. (
  555.    REF(BOOL)        /*OUT*/ bLoadMultiple,
  556.    REF(const char*) /*OUT*/ pDescription,
  557.    REF(const char*) /*OUT*/ pCopyright,
  558.    REF(const char*) /*OUT*/ pMoreInfoURL,
  559.    REF(ULONG32)     /*OUT*/ ulVersionNumber
  560. )
  561. {
  562.     bLoadMultiple = TRUE;   // Must be true for file formats.
  563.     pDescription    = zm_pDescription;
  564.     pCopyright     = zm_pCopyright;
  565.     pMoreInfoURL    = zm_pMoreInfoURL;
  566.     ulVersionNumber = TARVER_ULONG32_VERSION;
  567.     return HXR_OK;
  568. }
  569. /************************************************************************
  570.  *  Method:
  571.  *    IHXPlugin::GetRendererInfo
  572.  *  Purpose:
  573.  *    If this object is a file format object this method returns
  574.  *    information vital to the instantiation of file format plugins.
  575.  *    If this object is not a file format object, it should return
  576.  *    HXR_UNEXPECTED.
  577.  */
  578. STDMETHODIMP CVideoRenderer::GetRendererInfo
  579. (
  580.  REF(const char**) /*OUT*/ pStreamMimeTypes,
  581.  REF(UINT32)      /*OUT*/ unInitialGranularity
  582. )
  583. {
  584.     pStreamMimeTypes = (const char**) zm_pStreamMimeTypes;
  585.     unInitialGranularity = SYNC_INTERVAL;
  586.     return HXR_OK;
  587. }
  588. /************************************************************************
  589.  *  IHXRenderer Methods
  590.  */
  591. /////////////////////////////////////////////////////////////////////////
  592. //  Method:
  593. // IHXRenderer::StartStream
  594. //  Purpose:
  595. // Called by client engine to inform the renderer of the stream it
  596. // will be rendering. The stream interface can provide access to
  597. // its source or player. This method also provides access to the
  598. // primary client controller interface.
  599. //
  600. STDMETHODIMP CVideoRenderer::StartStream(IHXStream* pStream,
  601.    IHXPlayer* pPlayer)
  602. {
  603.     m_pStream  = pStream;
  604.     if (m_pStream)
  605.     {
  606. m_pStream->AddRef();
  607.     }
  608. #if defined (HELIX_FEATURE_MISU)
  609.     m_pCommonClassFactory->CreateInstance(
  610. CLSID_IHXMultiInstanceSiteUserSupplier,
  611. (void**) &m_pMISUS);
  612.     if (m_pMISUS)
  613.     {
  614. m_pMISUS->SetSingleSiteUser((IUnknown*)(IHXSiteUser*) this);
  615.     }
  616. #endif //HELIX_FEATURE_MISU
  617.     if (m_pStream)
  618.     {
  619. IHXStreamSource* pSource = 0;
  620. if (m_pStream->GetSource(pSource) == HXR_OK)
  621. {
  622.     /* It is OK if the source does not support backchannel. Reasons:
  623.      *
  624.      * 1. This stream may not be coming from h261 fileformat.
  625.      *   It may instead be merged into a container fileformat which
  626.      *   may be does not support BackChannel.
  627.      *
  628.      * 2. The protocol used to serve this stream may not support
  629.      *   BackChannel.
  630.      */
  631.     pSource->QueryInterface(IID_IHXBackChannel, (void**) &m_pBackChannel);
  632.     pSource->Release();
  633. }
  634.     }
  635.     return HXR_OK;
  636. }
  637. /////////////////////////////////////////////////////////////////////////
  638. //  Method:
  639. // IHXRenderer::EndStream
  640. //  Purpose:
  641. // Called by client engine to inform the renderer that the stream
  642. // is was rendering is closed.
  643. //
  644. STDMETHODIMP CVideoRenderer::EndStream()
  645. {
  646.     // Stop Blts by changing state
  647.     m_pMutex->Lock();
  648.     m_PlayState = Stopped;
  649.     m_pMutex->Unlock();
  650.     // Stop Decoder
  651.     if (m_pDecoderPump)
  652.     {
  653. m_pDecoderPump->Stop();
  654. m_pDecoderPump->Signal();
  655. m_pDecoderPump->WaitForStop();
  656. m_pDecoderPump->Release();
  657. m_pDecoderPump = NULL;
  658.     }
  659.     // Wait for Blt if in progress and then flush packet queues
  660.     DisplayMutex_Lock();
  661.     if (m_pVideoFormat)
  662.     {
  663. m_pVideoFormat->Reset();
  664.     }
  665.     DisplayMutex_Unlock();
  666.     // IHXStream, IHXSourceStream or IHXBackChannel
  667.     // cannot be used after EndStream has been called.
  668.     HX_RELEASE(m_pStream);
  669.     HX_RELEASE(m_pBackChannel);
  670.     // Stop Bltr pump
  671.     if (m_pBltrPump)
  672.     {
  673. m_pBltrPump->Stop();
  674. m_pBltrPump->Signal();
  675.     }
  676.     // Flush Optimized Video Surface if used
  677.     if (m_bUseVideoSurface2 && m_pMISUSSite)
  678.     {
  679. FlushVideoSurface2(m_pMISUSSite);
  680.     }
  681.     if (m_pBltrPump)
  682.     {
  683. m_pBltrPump->WaitForStop();
  684. m_pBltrPump->Release();
  685. m_pBltrPump = NULL;
  686.     }
  687.     DisplayMutex_Lock();
  688.     if (m_pVideoFormat)
  689.     {
  690.         m_pVideoFormat->Release();
  691.         m_pVideoFormat = NULL;
  692.     }
  693.     DisplayMutex_Unlock();
  694. #ifdef ENABLE_SYNC_TRACE
  695.     DumpSyncEntries();
  696. #endif // ENABLE_SYNC_TRACE
  697. #ifdef ENABLE_SCHED_TRACE
  698.     DumpSchedEntries();
  699. #endif // ENABLE_SCHED_TRACE
  700. #ifdef ENABLE_FETCH_TRACE
  701.     DumpFetchEntries();
  702. #endif // ENABLE_FETCH_TRACE
  703. #ifdef ENABLE_INPUT_TRACE
  704.     DumpInputEntries();
  705. #endif // ENABLE_INPUT_TRACE
  706.     return HXR_OK;
  707. }
  708. /////////////////////////////////////////////////////////////////////////
  709. //  Method:
  710. // IHXRenderer::OnHeader
  711. //  Purpose:
  712. // Called by client engine when a header for this renderer is
  713. // available. The header will arrive before any packets.
  714. //
  715. STDMETHODIMP CVideoRenderer::OnHeader(IHXValues* pHeader)
  716. {
  717.     HX_RESULT retVal = HXR_OK;
  718.     HX_DELETE(m_pClipRect);
  719.     // Keep this for later use...
  720.     HX_RELEASE(m_pHeader);
  721.     m_pHeader = pHeader;
  722.     m_pHeader->AddRef();
  723.     m_ulStreamBaseTime = 0;
  724.     m_ulBaseTime = 0;
  725.     m_ulTimeNormalizationOffset = 0;
  726.     // check the stream versions
  727.     m_pHeader->AddRef();
  728.     retVal = CheckStreamVersions(m_pHeader);
  729.     m_pHeader->Release();
  730. #ifdef HELIX_FEATURE_QUICKTIME
  731.     IHXBuffer* pSDPData = NULL;
  732.     if (SUCCEEDED(retVal) &&
  733. SUCCEEDED(pHeader->GetPropertyCString("SDPData", pSDPData)))
  734.     {
  735. char *pData = (char*) pSDPData->GetBuffer();
  736. IHXValues *pValues = NULL;
  737. if (pData &&
  738.     SUCCEEDED(SDPParseChunk(pData,
  739.     strlen(pData),
  740.     pValues,
  741.     m_pCommonClassFactory,
  742.     SDPCTX_Renderer)))
  743. {
  744.     ULONG32 ulLeft;
  745.     ULONG32 ulRight;
  746.     ULONG32 ulTop;
  747.     ULONG32 ulBottom;
  748.     if (SUCCEEDED(pValues->GetPropertyULONG32(
  749.     "ClipFrameLeft", ulLeft)) &&
  750. SUCCEEDED(pValues->GetPropertyULONG32(
  751.     "ClipFrameRight", ulRight)) &&
  752. SUCCEEDED(pValues->GetPropertyULONG32(
  753.     "ClipFrameTop", ulTop)) &&
  754. SUCCEEDED(pValues->GetPropertyULONG32(
  755.     "ClipFrameBottom", ulBottom)))
  756.     {
  757. retVal = HXR_OUTOFMEMORY;
  758. m_pClipRect = (HXxRect*) new HXxRect;
  759. if (m_pClipRect)
  760. {
  761.     m_pClipRect->left = (INT32) ulLeft;
  762.     m_pClipRect->right = (INT32) ulRight;
  763.     m_pClipRect->top = (INT32) ulTop;
  764.     m_pClipRect->bottom = (INT32) ulBottom;
  765.     retVal = HXR_OK;
  766. }
  767.     }
  768. }
  769. HX_RELEASE(pValues);
  770.     }
  771.     HX_RELEASE(pSDPData);
  772. #endif // HELIX_FEATURE_QUICKTIME
  773.     if (SUCCEEDED(retVal))
  774.     {
  775. m_pVideoFormat = CreateFormatObject(m_pHeader);
  776. retVal = HXR_OUTOFMEMORY;
  777. if (m_pVideoFormat)
  778. {
  779.     m_pVideoFormat->AddRef();
  780.     retVal = HXR_OK;
  781. }
  782.     }
  783.     if (SUCCEEDED(retVal))
  784.     {
  785. retVal = m_pVideoFormat->Init(pHeader);
  786.     }
  787.     if (SUCCEEDED(retVal))
  788.     {
  789. m_ulEarlyFrameTol = GetEarlyFrameTolerance();
  790. m_ulLateFrameTol = GetLateFrameTolerance();
  791. m_ulMaxOptimizedVideoLead = GetMaxOptimizedVideoLead();
  792. m_ulMaxSleepTime = GetMaxSleepTime();
  793. m_ulNoFramesPollingInterval = GetNoFramesPollingInterval();
  794. m_ulBltPacketQueueSize = GetBltPacketQueueSize();
  795. m_ulSyncGoalSmoothingDepth = GetSyncGoalSmoothingDepth();
  796. m_ulSpeedupGoalSmoothingDepth = GetSpeedupGoalSmoothingDepth();
  797. m_ulMaxBadSeqSamples = GetMaxBadSeqSamples();
  798.     }
  799.     // Setup preroll
  800.     if (SUCCEEDED(retVal))
  801.     {
  802. BOOL bSetNewPreroll = FALSE;
  803.         m_ulPreroll = 0;
  804. ULONG32 ulMinPreroll = m_pVideoFormat->GetMinimumPreroll(pHeader);
  805. ULONG32 ulMaxPreroll = m_pVideoFormat->GetMaximumPreroll(pHeader);
  806.         // Check that the stream header has a preroll value. If not...
  807. pHeader->GetPropertyULONG32("Preroll", m_ulPreroll);
  808. if (m_ulPreroll == 0)
  809. {
  810.             // ... let's use default value.
  811.     m_ulPreroll = m_pVideoFormat->GetDefaultPreroll(pHeader);
  812.     bSetNewPreroll = TRUE;
  813. }
  814.         else if( m_ulPreroll > ulMaxPreroll )
  815.         {
  816.             m_ulPreroll = ulMaxPreroll;
  817.     bSetNewPreroll = TRUE;
  818.         }
  819. else if (m_ulPreroll < ulMinPreroll)
  820. {
  821.     m_ulPreroll = ulMinPreroll;
  822.     bSetNewPreroll = TRUE;
  823. }
  824. if (bSetNewPreroll)
  825. {
  826.     pHeader->SetPropertyULONG32("Preroll", m_ulPreroll);
  827. }
  828.     }
  829.     // Determine Average Bitrate
  830.     if (SUCCEEDED(retVal))
  831.     {
  832. if (FAILED(pHeader->GetPropertyULONG32("AvgBitRate", m_ulAvgBitRate)))
  833. {
  834.     m_ulAvgBitRate = 0;
  835. }
  836.     }
  837.     // Create Blt Queue
  838.     if (SUCCEEDED(retVal))
  839.     {
  840. m_pBltPacketQueue = new CRingBuffer(m_ulBltPacketQueueSize);
  841. retVal = HXR_OUTOFMEMORY;
  842. if (m_pBltPacketQueue)
  843. {
  844.     retVal = HXR_OK;
  845. }
  846.     }
  847.     return retVal;
  848. }
  849. /////////////////////////////////////////////////////////////////////////////
  850. //  Method:
  851. // CVideoRenderer::CheckStreamVersions
  852. //  copied from CRealAudioRenderer
  853. HX_RESULT CVideoRenderer::CheckStreamVersions(IHXValues* pHeader)
  854. {
  855.     // check stream and content versions so an upgrade can
  856.     // be called if necessary...
  857.     HX_RESULT pnr = HXR_OK;
  858.     BOOL bVersionOK = TRUE;
  859.     UINT32 ulStreamVersion = 0;
  860.     UINT32 ulContentVersion = 0;
  861.     if(HXR_OK == pHeader->GetPropertyULONG32("StreamVersion",
  862. ulStreamVersion))
  863.     {
  864. UINT32 ulMajorVersion = HX_GET_MAJOR_VERSION(ulStreamVersion);
  865. UINT32 ulMinorVersion = HX_GET_MINOR_VERSION(ulStreamVersion);
  866. ULONG32 ulThisMajorVersion = 0;
  867. ULONG32 ulThisMinorVersion = 0;
  868. GetStreamVersion(ulThisMajorVersion, ulThisMinorVersion);
  869. if((ulMajorVersion > ulThisMajorVersion) ||
  870.    ((ulMinorVersion > ulThisMinorVersion) &&
  871.     (ulMajorVersion == ulThisMajorVersion)))
  872. {
  873.     bVersionOK = FALSE;
  874. }
  875.     }
  876.     if(bVersionOK &&
  877.        (HXR_OK == pHeader->GetPropertyULONG32("ContentVersion",
  878.       ulContentVersion)))
  879.     {
  880. UINT32 ulMajorVersion = HX_GET_MAJOR_VERSION(ulContentVersion);
  881. UINT32 ulMinorVersion = HX_GET_MINOR_VERSION(ulContentVersion);
  882. ULONG32 ulThisMajorVersion = 0;
  883. ULONG32 ulThisMinorVersion = 0;
  884. GetContentVersion(ulThisMajorVersion, ulThisMinorVersion);
  885. if((ulMajorVersion > ulThisMajorVersion) ||
  886.    ((ulMinorVersion > ulThisMinorVersion) &&
  887.     (ulMajorVersion == ulMajorVersion)))
  888. {
  889.     bVersionOK = FALSE;
  890. }
  891.     }
  892.     if(!bVersionOK)
  893.     {
  894.         AddToAutoUpgradeCollection(GetUpgradeMimeType(), m_pContext);
  895. pnr = HXR_FAIL;
  896.     }
  897.     return pnr;
  898. }
  899. /////////////////////////////////////////////////////////////////////////
  900. //  Method:
  901. // IHXRenderer::OnPacket
  902. //  Purpose:
  903. // Called by client engine when a packet for this renderer is
  904. // due.
  905. //
  906. STDMETHODIMP CVideoRenderer::OnPacket(IHXPacket* pPacket, LONG32 lTimeOffset)
  907. {
  908.     m_lTimeLineOffset = lTimeOffset;
  909. #ifdef ENABLE_INPUT_TRACE
  910.     if (ulInputTraceIdx < MAX_INPUT_TRACE_ENTRIES)
  911.     {
  912. inputTraceArray[ulInputTraceIdx++] =
  913.     ComputeTimeAhead(pPacket->GetTime(), 0);
  914.     }
  915. #endif // ENABLE_INPUT_TRACE
  916.     if (m_bSchedulerStartRequested)
  917.     {
  918. StartSchedulers();
  919.     }
  920.     BOOL bQueueRet = m_pVideoFormat->Enqueue(pPacket);
  921.     if(bQueueRet == FALSE && m_pVideoFormat->GetLastError() == HXR_OUTOFMEMORY)
  922.     {
  923.         return HXR_OUTOFMEMORY;
  924.     }
  925.     // try to decode a frame
  926.     if (m_PlayState == Playing)
  927.     {
  928. if (!IsDecoderRunning() || NULL == m_pDecoderPump)
  929. {
  930.     BOOL bDecRet = m_pVideoFormat->DecodeFrame();
  931.             if( bDecRet == FALSE && m_pVideoFormat->GetLastError() == HXR_OUTOFMEMORY )
  932.             {
  933.                 return HXR_OUTOFMEMORY;
  934.             }
  935. }
  936. else
  937. {
  938.     m_pDecoderPump->Signal();
  939. }
  940.     }
  941.     else
  942.     {
  943. if (!m_bBaseTimeSet)
  944. {
  945.     m_pMutex->Lock();
  946.     if (m_PlayState != Playing)
  947.     {
  948. m_ulBaseTime = pPacket->GetTime();
  949.     }
  950.     m_pMutex->Unlock();
  951.     m_bBaseTimeSet = TRUE;
  952. }
  953. // If we are seeking, this is a pre-seek packet and there is
  954. // no need to decode it
  955. if (m_PlayState != Seeking)
  956. {
  957.     if (!IsDecoderRunning() || NULL == m_pDecoderPump)
  958.     {
  959. m_pVideoFormat->DecodeFrame();
  960.     }
  961.     else
  962.     {
  963. m_pDecoderPump->Signal();
  964.     }
  965.     if (m_PlayState == Buffering)
  966.     {
  967. if (IsBufferingComplete(pPacket))
  968. {
  969.     RequestBufferingEnd();
  970. }
  971.     }
  972. }
  973.     }
  974.     return HXR_OK;
  975. }
  976. /////////////////////////////////////////////////////////////////////////
  977. //  Method:
  978. // IHXRenderer::OnTimeSync
  979. //  Purpose:
  980. // Called by client engine to inform the renderer of the current
  981. // time relative to the streams synchronized time-line. The
  982. // renderer should use this time value to update its display or
  983. // render it's stream data accordingly.
  984. //
  985. STDMETHODIMP CVideoRenderer::OnTimeSync(ULONG32 ulTime)
  986. {
  987.     ULONG32 ulStreamBaseTime = HX_GET_BETTERTICKCOUNT();
  988.     ULONG32 ulBaseTime = ulTime;
  989.     BOOL bGoodSample = TRUE;
  990.     if (m_bSchedulerStartRequested)
  991.     {
  992. StartSchedulers();
  993.     }
  994. #ifdef HELIX_FEATURE_STATS
  995.     if (((ULONG32) (ulStreamBaseTime - m_pVideoStats->GetLastSyncTime())) >=
  996. VIDEO_STAT_INTERVAL)
  997.     {
  998. m_pVideoStats->SyncStats(ulStreamBaseTime);
  999.     }
  1000. #endif /* HELIX_FEATURE_STATS */
  1001. #ifdef ENABLE_SYNC_TRACE
  1002.     ULONG32 ulOrigStreamBaseTime = ulStreamBaseTime;
  1003. #endif // ENABLE_SYNC_TRACE
  1004. #ifdef SYNC_SMOOTHING_OLD_SCHEME
  1005.     LONG32 lNewSyncDelta = (LONG32) (ulStreamBaseTime - m_lTrendSyncDelta - ulTime);
  1006.     m_lTrendSyncDelta += lNewSyncDelta / ((LONG32) (m_ulSyncSmoothingDepth + 1));
  1007.     ulStreamBaseTime = ulTime + m_lTrendSyncDelta;
  1008.     if (m_ulSyncSmoothingDepth < m_ulSyncGoalSmoothingDepth)
  1009.     {
  1010. m_ulSyncSmoothingDepth++;
  1011.     }
  1012. #endif // SYNC_SMOOTHING_OLD_SCHEME
  1013. #ifdef SYNC_PRE_SMOOTHING
  1014.     if (m_ulSyncSmoothingDepth > 0)
  1015.     {
  1016. LONG32 lStreamBaseDelta = ((LONG32) (ulStreamBaseTime - m_ulStreamBaseTime));
  1017. ULONG32 ulBaseDelta = ulBaseTime - m_ulBaseTime;
  1018. BOOL bSkipSmoothing = FALSE;
  1019. bGoodSample = ((lStreamBaseDelta <= 0) ||
  1020.        (((ULONG32) lStreamBaseDelta) <=
  1021.         (ulBaseDelta + (ulBaseDelta >> AUDIO_SKEW_POWER))) ||
  1022.        (bSkipSmoothing = ((m_ulBadSeqSampleCount++) > m_ulMaxBadSeqSamples)));
  1023. if (bSkipSmoothing)
  1024. {
  1025.     m_ulSyncSmoothingDepth = 0;
  1026.     m_fTrendSyncDelta = 0.0;
  1027. }
  1028.     }
  1029. #endif // SYNC_PRE_SMOOTHING
  1030.     if (bGoodSample)
  1031.     {
  1032. #ifdef SYNC_SMOOTHING
  1033. double fNewSyncDelta = (((double) ((ULONG32) (ulStreamBaseTime - ulTime))) -
  1034.        m_fTrendSyncDelta);
  1035. // If we have a m_fTrendSyncDelta, make sure we consider
  1036. // m_fTrendSyncDelta wrap-around in relation to fNewSyncDelta
  1037. if (m_ulSyncSmoothingDepth > 0)
  1038. {
  1039.     if (fNewSyncDelta > MAX_LONG32_AS_DOUBLE)
  1040.     {
  1041. fNewSyncDelta = MAX_ULONG32_AS_DOUBLE - fNewSyncDelta;
  1042.     }
  1043.     else if (fNewSyncDelta < MIN_LONG32_AS_DOUBLE)
  1044.     {
  1045. fNewSyncDelta += MAX_ULONG32_AS_DOUBLE;
  1046.     }
  1047. }
  1048. if (fNewSyncDelta < 0.0)
  1049. {
  1050.     // We are trying to speed up: use speed up smoothing criteria
  1051.     m_fTrendSyncDelta += (fNewSyncDelta /
  1052.   ((m_ulSyncSmoothingDepth >= m_ulSpeedupGoalSmoothingDepth) ?
  1053.    m_ulSpeedupGoalSmoothingDepth + 1 : m_ulSyncSmoothingDepth + 1));
  1054. }
  1055. else
  1056. {
  1057.     m_fTrendSyncDelta += fNewSyncDelta / (m_ulSyncSmoothingDepth + 1);
  1058. }
  1059. if (m_fTrendSyncDelta > MAX_ULONG32_AS_DOUBLE)
  1060. {
  1061.     m_fTrendSyncDelta -= MAX_ULONG32_AS_DOUBLE;
  1062. }
  1063. else if (m_fTrendSyncDelta < 0)
  1064. {
  1065.      m_fTrendSyncDelta += MAX_ULONG32_AS_DOUBLE;
  1066. }
  1067. ulStreamBaseTime = ulTime + ((ULONG32) (m_fTrendSyncDelta));
  1068. if (m_ulSyncSmoothingDepth < m_ulSyncGoalSmoothingDepth)
  1069. {
  1070.     m_ulSyncSmoothingDepth++;
  1071. }
  1072. #endif // SYNC_SMOOTHING
  1073. m_ulGoodSeqSampleCount++;
  1074. m_ulStreamBaseTime = ulStreamBaseTime;
  1075. m_ulBaseTime = ulBaseTime;
  1076. m_ulTimeNormalizationOffset = m_ulStreamBaseTime -
  1077.       m_ulBaseTime -
  1078.       m_lTimeLineOffset;
  1079. if (m_ulGoodSeqSampleCount >= MIN_GOOD_PERSISTENCE_COUNT)
  1080. {
  1081.     m_ulBadSeqSampleCount = 0;
  1082. }
  1083.     }
  1084.     else
  1085.     {
  1086. // This is a bad sample
  1087. if (m_ulBadSeqSampleCount >= MIN_BAD_PERSISTENCE_COUNT)
  1088. {
  1089.     m_ulGoodSeqSampleCount = 0;
  1090. }
  1091.     }
  1092. #ifdef ENABLE_SYNC_TRACE
  1093.     if (ulSyncTraceIdx < MAX_SYNC_TRACE_ENTRIES)
  1094.     {
  1095. syncTraceArray[ulSyncTraceIdx][0] = m_ulBaseTime;
  1096. syncTraceArray[ulSyncTraceIdx][1] = m_ulStreamBaseTime;
  1097. syncTraceArray[ulSyncTraceIdx++][2] = ulOrigStreamBaseTime;
  1098.     }
  1099. #endif // ENABLE_SYNC_TRACE
  1100.     if (m_PlayState == Playing)
  1101.     {
  1102. if (!IsDecoderRunning())
  1103. {
  1104.     m_pVideoFormat->DecodeFrame();
  1105. }
  1106. if (m_bBufferingNeeded)
  1107. {
  1108.     m_pMutex->Lock();
  1109.     if (m_PlayState == Playing)
  1110.     {
  1111. BeginBuffering();
  1112.     }
  1113.     m_pMutex->Unlock();
  1114. }
  1115.     }
  1116.     else if ((m_PlayState == PlayStarting) ||
  1117.      (m_PlayState == Buffering))
  1118.     {
  1119. m_pMutex->Lock();
  1120. m_bBaseTimeSet = TRUE;
  1121. // Reset the offset to avoid race condition
  1122. // with m_ulTimeNormalizationOffset setting in OnPacket()
  1123. if (bGoodSample)
  1124. {
  1125.     m_ulTimeNormalizationOffset = m_ulStreamBaseTime -
  1126.   m_ulBaseTime -
  1127.   m_lTimeLineOffset;
  1128. }
  1129. if (m_PlayState == Buffering)
  1130. {
  1131.     EndBuffering();
  1132.     m_PlayState = PlayStarting;
  1133. }
  1134. if (m_PlayState == PlayStarting)
  1135. {
  1136.     m_PlayState = Playing;
  1137.     BltIfNeeded();
  1138.     StartSchedulers();
  1139.     if (m_pBltrPump)
  1140.     {
  1141. m_pBltrPump->Signal();
  1142.     }
  1143. }
  1144. m_pMutex->Unlock();
  1145.     }
  1146.     return HXR_OK;
  1147. }
  1148. HX_RESULT CVideoRenderer::StartSchedulers(void)
  1149. {
  1150.     HX_RESULT retVal = HXR_OK;
  1151. #ifdef HELIX_FEATURE_VIDREND_UNTIMED_DECODE
  1152.     // When running the decoder as fast as possible, we dont want to start the scheduler, so short
  1153.     // circuit this code. Additionally, calls such as BltIfNeeded() and ScheduleCallback() (which
  1154.     // may still be called) make assumptions based on the state of our interactions with the
  1155.     // scheduler, so we satisfy them by setting a pending handle representing a nonexistant callback.
  1156.     if( m_bUntimedRendering )
  1157.     {
  1158. m_hPendingHandle = 1;
  1159. return HXR_OK;
  1160.     }
  1161. #endif /* HELIX_FEATURE_VIDREND_UNTIMED_DECODE */
  1162.     m_bSchedulerStartRequested = FALSE;
  1163.     DisplayMutex_Lock();
  1164.     if (ShouldKickStartScheduler())
  1165.     {
  1166. m_bBufferingNeeded = FALSE;
  1167. ScheduleCallback(0);
  1168.     }
  1169.     if (SUCCEEDED(retVal) && (m_pDecoderPump == NULL))
  1170.     {
  1171. CVideoPaceMaker* pVideoPaceMaker;
  1172. retVal = HXR_OUTOFMEMORY;
  1173. pVideoPaceMaker = new CVideoPaceMaker;
  1174. if (pVideoPaceMaker)
  1175. {
  1176.     retVal = pVideoPaceMaker->QueryInterface(
  1177. IID_IHXPaceMaker,
  1178. (void**) &m_pDecoderPump);
  1179.     if (SUCCEEDED(retVal))
  1180.     {
  1181. pVideoPaceMaker = NULL;
  1182. m_pDecoderPump->Start(this,
  1183.     GetDecodePriority(),
  1184.     DECODER_INTERVAL,
  1185.     m_ulDecoderPacemakerId);
  1186.     }
  1187. }
  1188. HX_DELETE(pVideoPaceMaker);
  1189.     }
  1190.     if (SUCCEEDED(retVal) && (m_pBltrPump == NULL) && m_bTryVideoSurface2)
  1191.     {
  1192. CVideoPaceMaker* pVideoPaceMaker;
  1193. retVal = HXR_OUTOFMEMORY;
  1194. pVideoPaceMaker = new CVideoPaceMaker;
  1195. if (pVideoPaceMaker)
  1196. {
  1197.     retVal = pVideoPaceMaker->QueryInterface(
  1198. IID_IHXPaceMaker,
  1199. (void**) &m_pBltrPump);
  1200.     if (SUCCEEDED(retVal))
  1201.     {
  1202. pVideoPaceMaker = NULL;
  1203. m_pBltrPump->Start(this,
  1204.     DFLT_PRESENT_PRIORITY,
  1205.     BLTR_INTERVAL,
  1206.     m_ulBltrPacemakerId);
  1207.     }
  1208. }
  1209. HX_DELETE(pVideoPaceMaker);
  1210.     }
  1211.     DisplayMutex_Unlock();
  1212.     return retVal;
  1213. }
  1214. /////////////////////////////////////////////////////////////////////////
  1215. //  Method:
  1216. // IHXRenderer::OnPreSeek
  1217. //  Purpose:
  1218. // Called by client engine to inform the renderer that a seek is
  1219. // about to occur. The render is informed the last time for the
  1220. // stream's time line before the seek, as well as the first new
  1221. // time for the stream's time line after the seek will be completed.
  1222. //
  1223. STDMETHODIMP CVideoRenderer::OnPreSeek(ULONG32 ulOldTime, ULONG32 ulNewTime)
  1224. {
  1225.     // Change state to stop Blts
  1226.     m_pMutex->Lock();
  1227.     m_PlayState = Seeking;
  1228.     m_pMutex->Unlock();
  1229.     // Suspend the Decoder pump
  1230.     if (m_pDecoderPump)
  1231.     {
  1232. m_pDecoderPump->Suspend(TRUE);
  1233. m_pDecoderPump->Signal();
  1234. m_pDecoderPump->WaitForSuspend();
  1235.     }
  1236.     // Wait for Blt in progress to complete and reset
  1237.     // packet queues
  1238.     DisplayMutex_Lock();
  1239.     m_pVideoFormat->SetStartTime(ulNewTime);
  1240.     m_pVideoFormat->Reset();
  1241. #if defined(HELIX_FEATURE_STATS)
  1242.     m_pVideoStats->ResetSequence();
  1243. #endif /* HELIX_FEATURE_STATS */
  1244.     m_bFirstSurfaceUpdate = TRUE;
  1245.     m_bFirstFrame = TRUE;
  1246.     m_bBaseTimeSet = FALSE;
  1247.     DisplayMutex_Unlock();
  1248.     return HXR_OK;
  1249. }
  1250. /////////////////////////////////////////////////////////////////////////
  1251. //  Method:
  1252. // IHXRenderer::OnPostSeek
  1253. //  Purpose:
  1254. // Called by client engine to inform the renderer that a seek has
  1255. // just occured. The render is informed the last time for the
  1256. // stream's time line before the seek, as well as the first new
  1257. // time for the stream's time line after the seek.
  1258. //
  1259. STDMETHODIMP CVideoRenderer::OnPostSeek(ULONG32 ulOldTime, ULONG32 ulNewTime)
  1260. {
  1261.     DisplayMutex_Lock();
  1262.     // clean up the packet lists
  1263.     m_pVideoFormat->SetStartTime(ulNewTime);
  1264.     m_pVideoFormat->Reset();
  1265. #if defined(HELIX_FEATURE_STATS)
  1266.     m_pVideoStats->ResetSequence();
  1267. #endif /* HELIX_FEATURE_STATS */
  1268.     m_bFirstSurfaceUpdate = TRUE;
  1269.     m_bFirstFrame = TRUE;
  1270.     m_ulBaseTime = ulNewTime;
  1271.     m_bBaseTimeSet = TRUE;
  1272.     m_bVS2BufferUnavailableOnLastBlt = FALSE;
  1273.     if (m_pDecoderPump)
  1274.     {
  1275. m_pDecoderPump->Suspend(FALSE);
  1276. m_pDecoderPump->Signal();
  1277.     }
  1278.     if (m_bUseVideoSurface2 && m_pMISUSSite)
  1279.     {
  1280. FlushVideoSurface2(m_pMISUSSite);
  1281.     }
  1282.     DisplayMutex_Unlock();
  1283.     // PostSeek signals the proper packets are to start arriving
  1284.     m_pMutex->Lock();
  1285.     m_PlayState = PlayStarting;
  1286.     m_pMutex->Unlock();
  1287.     return HXR_OK;
  1288. }
  1289. /////////////////////////////////////////////////////////////////////////
  1290. //  Method:
  1291. // IHXRenderer::OnPause
  1292. //  Purpose:
  1293. // Called by client engine to inform the renderer that a pause has
  1294. // just occured. The render is informed the last time for the
  1295. // stream's time line before the pause.
  1296. //
  1297. STDMETHODIMP CVideoRenderer::OnPause(ULONG32 ulTime)
  1298. {
  1299.     m_pMutex->Lock();
  1300.     m_PlayState = Paused;
  1301.     m_pMutex->Unlock();
  1302.     return HXR_OK;
  1303. }
  1304. /////////////////////////////////////////////////////////////////////////
  1305. //  Method:
  1306. // IHXRenderer::OnBegin
  1307. //  Purpose:
  1308. // Called by client engine to inform the renderer that a begin or
  1309. // resume has just occured. The render is informed the first time
  1310. // for the stream's time line after the resume.
  1311. //
  1312. STDMETHODIMP CVideoRenderer::OnBegin(ULONG32 ulTime)
  1313. {
  1314.     HX_RESULT retVal = HXR_OK;
  1315.     m_pMutex->Lock();
  1316.     m_bBufferingOccured = FALSE;
  1317.     // If we are seeking, PostSeek will notify us when the play
  1318.     // will be starting
  1319.     if (m_PlayState != Seeking)
  1320.     {
  1321. m_PlayState = PlayStarting;
  1322.     }
  1323.     // No need to clear the Blt Packet queue here since
  1324.     // The Refresh event will always clear it and clearing
  1325.     // it here would create a race condition on Blt Packet
  1326.     // Queue (ring buffer) read.
  1327.     // ClearBltPacketQueue();
  1328.     m_ulSyncSmoothingDepth = 0;
  1329.     m_ulBadSeqSampleCount = 0;
  1330.     m_ulGoodSeqSampleCount = 0;
  1331.     m_bIsScheduledCB = 0;
  1332.     m_bVS2BufferUnavailableOnLastBlt = FALSE;
  1333.     retVal = StartSchedulers();
  1334.     m_pMutex->Unlock();
  1335. #ifdef HELIX_FEATURE_VIDREND_BOOSTDECODE_ON_STARTUP
  1336.     if (m_pDecoderPump)
  1337.     {
  1338.        //m_pDecoderPump->Suspend(TRUE);
  1339.        //m_pDecoderPump->WaitForSuspend();  // Wait for decoder thread to start and suspends itself
  1340.        //m_pDecoderPump->Suspend(FALSE);
  1341.        m_pDecoderPump->Signal();   // Kick-out decoder pump from suspension
  1342.     }
  1343. #endif  // HELIX_FEATURE_VIDREND_BOOSTDECODE_ON_STARTUP
  1344.     return retVal;
  1345. }
  1346. /////////////////////////////////////////////////////////////////////////
  1347. //  Method:
  1348. // IHXRenderer::OnBuffering
  1349. //  Purpose:
  1350. // Called by client engine to inform the renderer that buffering
  1351. // of data is occuring. The render is informed of the reason for
  1352. // the buffering (start-up of stream, seek has occured, network
  1353. // congestion, etc.), as well as percentage complete of the
  1354. // buffering process.
  1355. //
  1356. STDMETHODIMP CVideoRenderer::OnBuffering(ULONG32 ulFlags, UINT16 unPercentComplete)
  1357. {
  1358.     HX_RESULT retVal = HXR_OK;
  1359.     m_pMutex->Lock();
  1360.     if (m_PlayState == Buffering)
  1361.     {
  1362. if (IsBufferingComplete())
  1363. {
  1364.     EndBuffering();
  1365. }
  1366.     }
  1367.     else if (m_PlayState == Playing)
  1368.     {
  1369. m_PlayState = PlayStarting;
  1370.     }
  1371.     m_pMutex->Unlock();
  1372.     return retVal;
  1373. }
  1374. /////////////////////////////////////////////////////////////////////////
  1375. //  Method:
  1376. // IHXRenderer::GetDisplayType
  1377. //  Purpose:
  1378. // Called by client engine to ask the renderer for it's preferred
  1379. // display type. When layout information is not present, the
  1380. // renderer will be asked for it's prefered display type. Depending
  1381. // on the display type a buffer of additional information may be
  1382. // needed. This buffer could contain information about preferred
  1383. // window size.
  1384. //
  1385. STDMETHODIMP CVideoRenderer::GetDisplayType(REF(HX_DISPLAY_TYPE) ulFlags,
  1386.    REF(IHXBuffer*) pBuffer)
  1387. {
  1388.     ulFlags = HX_DISPLAY_WINDOW |
  1389.       HX_DISPLAY_SUPPORTS_RESIZE |
  1390.       HX_DISPLAY_SUPPORTS_FULLSCREEN |
  1391.       HX_DISPLAY_SUPPORTS_VIDCONTROLS;
  1392.     return HXR_OK;
  1393. }
  1394. /************************************************************************
  1395. * Method:
  1396. *     IHXRenderer::OnEndofPackets
  1397. * Purpose:
  1398. *     Called by client engine to inform the renderer that all the
  1399. *     packets have been delivered. However, if the user seeks before
  1400. *     EndStream() is called, renderer may start getting packets again
  1401. *     and the client engine will eventually call this function again.
  1402. */
  1403. STDMETHODIMP CVideoRenderer::OnEndofPackets(void)
  1404. {
  1405.     if (m_pVideoFormat)
  1406.     {
  1407. m_pVideoFormat->OnRawPacketsEnded();
  1408.     }
  1409.     return HXR_OK;
  1410. }
  1411. /************************************************************************
  1412.  *  IHXStatistics Methods
  1413.  */
  1414. /************************************************************************
  1415.  *  InitializeStatistics
  1416.  */
  1417. #define MAX_STAT_ENTRY_PAIRS 32
  1418. STDMETHODIMP CVideoRenderer::InitializeStatistics(UINT32 ulRegistryID)
  1419. {
  1420.     BOOL bCodecNameKnown = FALSE;
  1421.     char* pValue = NULL;
  1422.     HX_RESULT retVal = HXR_UNEXPECTED;
  1423.     m_ulRegistryID = ulRegistryID;
  1424. #if defined(HELIX_FEATURE_STATS)
  1425.     if (m_pVideoStats)
  1426.     {
  1427. retVal = HXR_OK;
  1428.     }
  1429.     if (SUCCEEDED(retVal))
  1430.     {
  1431. pValue = (char*) GetCodecName();
  1432. if (pValue != NULL)
  1433. {
  1434.     ReportStat(VS_CODEC_NAME, pValue);
  1435.     bCodecNameKnown = TRUE;
  1436. }
  1437.     }
  1438.     if (SUCCEEDED(retVal))
  1439.     {
  1440. pValue = (char*) GetRendererName();
  1441. if (pValue != NULL)
  1442. {
  1443.     ReportStat(VS_REND_NAME, pValue);
  1444.     // If Codec name is unknown, use a more generic renderer name
  1445.     if (!bCodecNameKnown)
  1446.     {
  1447. ReportStat(VS_CODEC_NAME, pValue);
  1448.     }
  1449. }
  1450.     }
  1451.     if (SUCCEEDED(retVal))
  1452.     {
  1453. pValue = (char*) GetCodecFourCC();
  1454. if (pValue != NULL)
  1455. {
  1456.     ReportStat(VS_CODEC_4CC, pValue);
  1457. }
  1458.     }
  1459.     if (SUCCEEDED(retVal))
  1460.     {
  1461. ReportStat(VS_CURRENT_FRAMERATE, "0.0");
  1462. ReportStat(VS_FRAMES_DISPLAYED, "100.0");
  1463. ReportStat(VS_FRAMES_DROPPED, (INT32) 0);
  1464. ReportStat(VS_FRAMES_LOST, (INT32) 0);
  1465. ReportStat(VS_SURESTREAM, "FALSE");
  1466. ReportStat(VS_IMAGE_WIDTH, (INT32) 0);
  1467. ReportStat(VS_IMAGE_HEIGHT, (INT32) 0);
  1468.     }
  1469.     if (SUCCEEDED(retVal))
  1470.     {
  1471. InitExtraStats();
  1472.     }
  1473.     if (SUCCEEDED(retVal))
  1474.     {
  1475. retVal = m_pVideoStats->DisplayStats(m_ulRegistryID);
  1476.     }
  1477.     return retVal;
  1478. #else
  1479.     return HXR_NOTIMPL;
  1480. #endif /* HELIX_FEATURE_STATS */
  1481. }
  1482. /************************************************************************
  1483.  *  UpdateStatistics
  1484.  */
  1485. STDMETHODIMP CVideoRenderer::UpdateStatistics()
  1486. {
  1487. #if defined(HELIX_FEATURE_STATS)
  1488.     HX_RESULT retVal = HXR_UNEXPECTED;
  1489.     if (m_pVideoStats)
  1490.     {
  1491. retVal = HXR_OK;
  1492.     }
  1493.     if (SUCCEEDED(retVal))
  1494.     {
  1495. retVal = m_pVideoStats->DisplayStats(m_ulRegistryID);
  1496.     }
  1497.     return retVal;
  1498. #else
  1499.     return HXR_NOTIMPL;
  1500. #endif /* HELIX_FEATURE_STATS */
  1501. }
  1502. /************************************************************************
  1503.  *  IHXUntimedDecoder Methods
  1504.  */
  1505. #ifdef HELIX_FEATURE_VIDREND_UNTIMED_DECODE
  1506. STDMETHODIMP_(BOOL) CVideoRenderer::IsUntimedRendering()
  1507. {
  1508.     return m_bUntimedRendering;
  1509. }
  1510. STDMETHODIMP_(HX_RESULT) CVideoRenderer::SetUntimedRendering(BOOL bUntimedRendering)
  1511. {
  1512.     if( m_PlayState != Stopped && m_PlayState != PlayStarting )
  1513.     {
  1514. return HXR_UNEXPECTED;
  1515.     }
  1516.     m_bUntimedRendering = bUntimedRendering;
  1517.     return HXR_OK;
  1518. }
  1519. #endif /* HELIX_FEATURE_VIDREND_UNTIMED_DECODE */
  1520. /************************************************************************
  1521.  *  IHXUpdateProperties Methods
  1522.  */
  1523. /************************************************************************
  1524.  *  UpdatePacketTimeOffset
  1525.  * Call this method to update the timestamp offset of cached packets
  1526.  */
  1527. STDMETHODIMP CVideoRenderer::UpdatePacketTimeOffset(INT32 lTimeOffset)
  1528. {
  1529.     m_lTimeLineOffset -= lTimeOffset;
  1530.     return HXR_OK;
  1531. }
  1532. /************************************************************************
  1533.  * Method:
  1534.  *     IHXUpdateProperties::UpdatePlayTimes
  1535.  * Purpose:
  1536.  *     Call this method to update the playtime attributes
  1537.  */
  1538. STDMETHODIMP
  1539. CVideoRenderer::UpdatePlayTimes(IHXValues* pProps)
  1540. {
  1541.     return HXR_OK;
  1542. }
  1543. /************************************************************************
  1544.  *  IHXRenderTimeLine Methods
  1545.  */
  1546. /************************************************************************
  1547.  *  GetTimeLineValue
  1548.  */
  1549. STDMETHODIMP CVideoRenderer::GetTimeLineValue(REF(UINT32) ulTime)
  1550. {
  1551.     ulTime = ((ULONG32) -ComputeTimeAhead(0, 0));
  1552.     if (m_PlayState != Playing)
  1553.     {
  1554.         return HXR_TIMELINE_SUSPENDED;
  1555.     }
  1556.     return HXR_OK;
  1557. }
  1558. /************************************************************************
  1559.  *  IHXSiteUser Methods
  1560.  */
  1561. /************************************************************************
  1562.  *  AttachSite
  1563.  */
  1564. STDMETHODIMP CVideoRenderer::AttachSite(IHXSite* /*IN*/ pSite)
  1565. {
  1566.     if (m_pMISUSSite)
  1567.     {
  1568. return HXR_UNEXPECTED;
  1569.     }
  1570.     m_bSiteAttached = TRUE;
  1571.     m_pMISUSSite = pSite;
  1572.     m_pMISUSSite->AddRef();
  1573.     // for sync
  1574.     IHXInterruptSafe* pIHXInterruptSafe = NULL;
  1575.     if (HXR_OK == m_pMISUSSite->QueryInterface(IID_IHXInterruptSafe,
  1576.        (void**)&pIHXInterruptSafe))
  1577.     {
  1578. // Get the pref to use the optimized scheduler or not
  1579. BOOL bUseOptimized = TRUE;
  1580. IHXBuffer* pPrefBuffer;
  1581. if( m_pPreferences &&
  1582.             m_pPreferences->ReadPref("UseOptimizedScheduler",
  1583. pPrefBuffer) == HXR_OK)
  1584. {
  1585.     bUseOptimized = *(pPrefBuffer->GetBuffer()) == '1';
  1586.     HX_RELEASE(pPrefBuffer);
  1587. }
  1588. if (pIHXInterruptSafe->IsInterruptSafe() && bUseOptimized)
  1589. {
  1590.     HX_RELEASE(m_pOptimizedScheduler);
  1591.     if (HXR_OK !=
  1592.     m_pContext->QueryInterface(IID_IHXOptimizedScheduler,
  1593.     (void **) &m_pOptimizedScheduler))
  1594.     {
  1595. // just for good luck
  1596. m_pOptimizedScheduler = NULL;
  1597.     }
  1598. }
  1599.     }
  1600.     HX_RELEASE(pIHXInterruptSafe);
  1601. #ifdef HELIX_FEATURE_VIDREND_OPTIMIZEDVIDEO
  1602.     // Get Run Configuration
  1603.     // Use of VideoSurface2
  1604.     if (m_pPreferences)
  1605.     {
  1606. ReadPrefBOOL(m_pPreferences, "VideoBoost\NoFlip", m_bTryVideoSurface2);
  1607.     }
  1608.     // Use of OS Granule Boosting
  1609.     if (m_pPreferences)
  1610.     {
  1611. ReadPrefBOOL(m_pPreferences, "VideoBoost\NoOSGranuleBoost", m_bOSGranuleBoost);
  1612. m_bOSGranuleBoostVS2 = m_bOSGranuleBoost;
  1613.     }
  1614.     // Hardware buffer count to request from VideoSurface2
  1615.     if (m_bTryVideoSurface2 && m_pPreferences)
  1616.     {
  1617. ReadPrefINT32(m_pPreferences, "VideoBoost\InitialHSCount", m_ulConfigHWBufCount);
  1618.     }
  1619. #endif // HELIX_FEATURE_VIDREND_OPTIMIZEDVIDEO
  1620.     /*
  1621.      * This is the best time to set the size of the site, we
  1622.      * know for example the the header has already been received
  1623.      * at this point.
  1624.      *
  1625.      * In most display renderers, you will store size information
  1626.      * in your stream header. In this example, we assume a specific
  1627.      * size, but we will initialize that size here as if it had
  1628.      * come from our header.
  1629.      *
  1630.      */
  1631.     SetupBitmapDefaults(m_pHeader, m_BitmapInfoHeader);
  1632.     FormatAndSetViewFrame(m_pClipRect,
  1633.   m_BitmapInfoHeader,
  1634.   m_rViewRect);
  1635.     m_bBitmapSet = ((m_BitmapInfoHeader.biWidth > 0) &&
  1636.     (m_BitmapInfoHeader.biHeight > 0));
  1637.     return HXR_OK;
  1638. }
  1639. STDMETHODIMP
  1640. CVideoRenderer::DetachSite()
  1641. {
  1642.     m_bSiteAttached = FALSE;
  1643.     HX_RELEASE(m_pMISUSSite);
  1644.     // We're done with these...
  1645.     if (m_pMISUS)
  1646.     {
  1647. m_pMISUS->ReleaseSingleSiteUser();
  1648.     }
  1649.     HX_RELEASE(m_pMISUS);
  1650.     return HXR_OK;
  1651. }
  1652. STDMETHODIMP_(BOOL)
  1653. CVideoRenderer::NeedsWindowedSites()
  1654. {
  1655.     return FALSE;
  1656. };
  1657. STDMETHODIMP
  1658. CVideoRenderer::HandleEvent(HXxEvent* /*IN*/ pEvent)
  1659. {
  1660.     HX_RESULT retVal = HXR_OK;
  1661.     pEvent->handled = FALSE;
  1662.     pEvent->result  = 0;
  1663.     switch (pEvent->event)
  1664.     {
  1665.     case HX_SURFACE_UPDATE:
  1666. m_pVSMutex->Lock();
  1667. retVal = UpdateDisplay(pEvent, TRUE);
  1668. m_pVSMutex->Unlock();
  1669. break;
  1670. #if defined(HELIX_FEATURE_VIDREND_OPTIMIZEDVIDEO)
  1671.     case HX_SURFACE_MODE_CHANGE:
  1672. switch ((int) pEvent->param2)
  1673. {
  1674. case HX_VIDEOSURFACE1_RECOMMENDED:
  1675.     pEvent->result = SwitchToVideoSurface1();
  1676.     if (SUCCEEDED(pEvent->result))
  1677.     {
  1678. pEvent->handled = TRUE;
  1679.     }
  1680.     break;
  1681. case HX_VIDEOSURFACE1_NOT_RECOMMENDED:
  1682.     pEvent->result = SwitchToVideoSurface2();
  1683.     if (SUCCEEDED(pEvent->result))
  1684.     {
  1685. pEvent->handled = TRUE;
  1686.     }
  1687.     break;
  1688. default:
  1689.     HX_ASSERT(FALSE);
  1690.     break;
  1691. }
  1692. break;
  1693. #endif // HELIX_FEATURE_VIDREND_OPTIMIZEDVIDEO
  1694.     default:
  1695. // nothing to do
  1696. break;
  1697.     }
  1698.     return retVal;
  1699. }
  1700. // *** IUnknown methods ***
  1701. /****************************************************************************
  1702. *  IUnknown::AddRef                                            ref:  hxcom.h
  1703. *
  1704. *  This routine increases the object reference count in a thread safe
  1705. *  manner. The reference count is used to manage the lifetime of an object.
  1706. *  This method must be explicitly called by the user whenever a new
  1707. *  reference to an object is used.
  1708. */
  1709. STDMETHODIMP_(ULONG32) CVideoRenderer::AddRef()
  1710. {
  1711.     return InterlockedIncrement(&m_lRefCount);
  1712. }
  1713. /****************************************************************************
  1714. *  IUnknown::Release                                           ref:  hxcom.h
  1715. *
  1716. *  This routine decreases the object reference count in a thread safe
  1717. *  manner, and deletes the object if no more references to it exist. It must
  1718. *  be called explicitly by the user whenever an object is no longer needed.
  1719. */
  1720. STDMETHODIMP_(ULONG32) CVideoRenderer::Release()
  1721. {
  1722.     if (InterlockedDecrement(&m_lRefCount) > 0)
  1723.     {
  1724.         return m_lRefCount;
  1725.     }
  1726.     delete this;
  1727.     return 0;
  1728. }
  1729. /****************************************************************************
  1730. *  IUnknown::QueryInterface                                    ref:  hxcom.h
  1731. *
  1732. *  This routine indicates which interfaces this object supports. If a given
  1733. *  interface is supported, the object's reference count is incremented, and
  1734. *  a reference to that interface is returned. Otherwise a NULL object and
  1735. *  error code are returned. This method is called by other objects to
  1736. *  discover the functionality of this object.
  1737. */
  1738. STDMETHODIMP CVideoRenderer::QueryInterface(REFIID riid, void** ppvObj)
  1739. {
  1740.     QInterfaceList  qiList[] =
  1741.     {
  1742. { GET_IIDHANDLE(IID_IHXCallback), (IHXCallback*)this},
  1743. { GET_IIDHANDLE(IID_IHXInterruptSafe), (IHXInterruptSafe*)this},
  1744. { GET_IIDHANDLE(IID_IHXUpdateProperties), (IHXUpdateProperties*)this},
  1745. { GET_IIDHANDLE(IID_IHXRenderTimeLine), (IHXRenderTimeLine*)this},
  1746. #ifdef HELIX_FEATURE_VIDREND_UNTIMED_DECODE
  1747. { GET_IIDHANDLE(IID_IHXUntimedRenderer), (IHXUntimedRenderer*)this},
  1748. #endif
  1749. { GET_IIDHANDLE(IID_IHXPaceMakerResponse), (IHXPaceMakerResponse*)this},
  1750. { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXPlugin*) this},
  1751. { GET_IIDHANDLE(IID_IHXPlugin), (IHXPlugin*)this},
  1752. { GET_IIDHANDLE(IID_IHXRenderer), (IHXRenderer*)this},
  1753. { GET_IIDHANDLE(IID_IHXSiteUser), (IHXSiteUser*)this},
  1754. { GET_IIDHANDLE(IID_IHXStatistics), (IHXStatistics*)this},
  1755.     };
  1756.     if (QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj) == HXR_OK)
  1757.     {
  1758. return HXR_OK ;
  1759.     }
  1760.     else if (m_pMISUS && IsEqualIID(riid, IID_IHXSiteUserSupplier))
  1761.     {
  1762. return m_pMISUS->QueryInterface(IID_IHXSiteUserSupplier,ppvObj);
  1763.     }
  1764.     else
  1765.     {
  1766. *ppvObj = NULL;
  1767. return HXR_NOINTERFACE;
  1768.     }
  1769. }
  1770. /****************************************************************************
  1771.  *  Renderer's customizable fuctions - can be called any time
  1772.  */
  1773. /****************************************************************************
  1774.  *  GetStreamVersion
  1775.  */
  1776. void CVideoRenderer::GetStreamVersion(ULONG32 &ulThisMajorVersion,
  1777.       ULONG32 &ulThisMinorVersion)
  1778. {
  1779.     ulThisMajorVersion = STREAM_MAJOR_VERSION;
  1780.     ulThisMinorVersion = STREAM_MINOR_VERSION;
  1781. }
  1782. /****************************************************************************
  1783.  *  GetContentVersion
  1784.  */
  1785. void CVideoRenderer::GetContentVersion(ULONG32 &ulThisMajorVersion,
  1786.        ULONG32 &ulThisMinorVersion)
  1787. {
  1788.     ulThisMajorVersion = CONTENT_MAJOR_VERSION;
  1789.     ulThisMinorVersion = CONTENT_MINOR_VERSION;
  1790. }
  1791. /****************************************************************************
  1792.  *  GetUpgradeMimeType
  1793.  */
  1794. const char* CVideoRenderer::GetUpgradeMimeType(void)
  1795. {
  1796.     const char** pStreamMimeTypes = NULL;
  1797.     UINT32 ulInitialGranularity;
  1798.     GetRendererInfo(pStreamMimeTypes, ulInitialGranularity);
  1799.     if (pStreamMimeTypes)
  1800.     {
  1801. return pStreamMimeTypes[0];
  1802.     }
  1803.     return NULL;
  1804. }
  1805. /****************************************************************************
  1806.  *  GetRendererName
  1807.  */
  1808. const char* CVideoRenderer::GetRendererName(void)
  1809. {
  1810.     return BASE_VIDEO_RENDERER_NAME;
  1811. }
  1812. /****************************************************************************
  1813.  *  GetCodecName
  1814.  */
  1815. const char* CVideoRenderer::GetCodecName(void)
  1816. {
  1817.     return NULL;
  1818. }
  1819. /****************************************************************************
  1820.  *  GetCodecFourCC
  1821.  */
  1822. const char* CVideoRenderer::GetCodecFourCC(void)
  1823. {
  1824.     return NULL;
  1825. }
  1826. /****************************************************************************
  1827.  *  GetLateFrameTolerance
  1828.  */
  1829. ULONG32 CVideoRenderer::GetLateFrameTolerance(void)
  1830. {
  1831.     return LATE_FRAME_TOL;
  1832. }
  1833. /****************************************************************************
  1834.  *  GetEarlyFrameTolerance
  1835.  */
  1836. ULONG32 CVideoRenderer::GetEarlyFrameTolerance(void)
  1837. {
  1838.     return EARLY_FRAME_TOL;
  1839. }
  1840. /****************************************************************************
  1841.  *  GetMaxOptimizedVideoLead
  1842.  */
  1843. ULONG32 CVideoRenderer::GetMaxOptimizedVideoLead(void)
  1844. {
  1845.     return MAX_OPTIMIZED_VIDEO_LEAD;
  1846. }
  1847. /****************************************************************************
  1848.  *  GetBltPacketQueueSize
  1849.  */
  1850. ULONG32 CVideoRenderer::GetBltPacketQueueSize(void)
  1851. {
  1852.     ULONG32 ulSize = BLT_PACKET_QUEUE_SIZE;
  1853.     if (m_pVideoFormat)
  1854.     {
  1855. m_pVideoFormat->GetMaxDecodedFrames();
  1856.     }
  1857.     return ulSize;
  1858. }
  1859. /****************************************************************************
  1860.  *  GetSyncGoalSmoothingDepth
  1861.  */
  1862. ULONG32 CVideoRenderer::GetSyncGoalSmoothingDepth(void)
  1863. {
  1864.     return SYNC_GOAL_SMOOTHING_DEPTH;
  1865. }
  1866. /****************************************************************************
  1867.  *  GetSpeedupGoalSmoothingDepth
  1868.  */
  1869. ULONG32 CVideoRenderer::GetSpeedupGoalSmoothingDepth(void)
  1870. {
  1871.     return SPEEDUP_GOAL_SMOOTHING_DEPTH;
  1872. }
  1873. /****************************************************************************
  1874.  *  GetNoFramesPollingInterval
  1875.  */
  1876. ULONG32 CVideoRenderer::GetNoFramesPollingInterval(void)
  1877. {
  1878.     return NO_FRAMES_POLLING_INTERVAL;
  1879. }
  1880. /****************************************************************************
  1881.  *  GetMaxSleepTime
  1882.  */
  1883. ULONG32 CVideoRenderer::GetMaxSleepTime(void)
  1884. {
  1885.     return m_ulMaxSleepTime;
  1886. }
  1887. /****************************************************************************
  1888.  *  GetMaxSleepTime
  1889.  */
  1890. ULONG32 CVideoRenderer::GetMaxBadSeqSamples(void)
  1891. {
  1892.     return MAX_BAD_SAMPLE_INTERVAL / m_ulSyncInterval;
  1893. }
  1894. /****************************************************************************
  1895.  *  GetDecodePriority
  1896.  */
  1897. LONG32 CVideoRenderer::GetDecodePriority(void)
  1898. {
  1899.     return m_lDecodePriority;
  1900. }
  1901. HX_RESULT CVideoRenderer::SetDecodePriority(LONG32 lPriority)
  1902. {
  1903.     HX_RESULT retVal = HXR_OK;
  1904.     if (m_pDecoderPump)
  1905.     {
  1906. retVal = m_pDecoderPump->SetPriority(lPriority);
  1907.     }
  1908.     if (SUCCEEDED(retVal))
  1909.     {
  1910. m_lDecodePriority = lPriority;
  1911.     }
  1912.     return retVal;
  1913. }
  1914. /****************************************************************************
  1915.  *  CreateFormatObject
  1916.  */
  1917. CVideoFormat* CVideoRenderer::CreateFormatObject(IHXValues* pHeader)
  1918. {
  1919.     return new CVideoFormat(m_pCommonClassFactory,
  1920.     this);
  1921. }
  1922. /****************************************************************************
  1923.  *  SetupBitmapDefaults
  1924.  */
  1925. void CVideoRenderer::SetupBitmapDefaults(IHXValues* pHeader,
  1926.    HXBitmapInfoHeader &bitmapInfoHeader)
  1927. {
  1928.     // size calculation is taken from crvvideo
  1929.     bitmapInfoHeader.biSize = sizeof (HXBitmapInfoHeader);
  1930.     bitmapInfoHeader.biWidth = 0; // 352; // unknown
  1931.     bitmapInfoHeader.biHeight = 0; // 288; // unknown
  1932.     bitmapInfoHeader.biPlanes = 1;
  1933.     bitmapInfoHeader.biBitCount = 24;
  1934.     bitmapInfoHeader.biCompression = HX_I420;
  1935.     bitmapInfoHeader.biSizeImage = bitmapInfoHeader.biWidth *
  1936.      bitmapInfoHeader.biHeight *
  1937.      bitmapInfoHeader.biBitCount /
  1938.      8;
  1939.     bitmapInfoHeader.biXPelsPerMeter = 0;
  1940.     bitmapInfoHeader.biYPelsPerMeter = 0;
  1941.     bitmapInfoHeader.biClrUsed = 0;
  1942.     bitmapInfoHeader.biClrImportant = 0;
  1943.     bitmapInfoHeader.rcolor = 0;
  1944.     bitmapInfoHeader.gcolor = 0;
  1945.     bitmapInfoHeader.bcolor = 0;
  1946. }
  1947. /****************************************************************************
  1948.  *  FormatAndSetViewFrame
  1949.  */
  1950. void CVideoRenderer::FormatAndSetViewFrame(HXxRect* pClipRect,
  1951.    HXBitmapInfoHeader &bitmapInfoHeader,
  1952.    HXxRect &rViewRect,
  1953.    BOOL bMutex)
  1954. {
  1955.     BOOL bAsDefault = TRUE;
  1956.     HXxSize szViewFrame;
  1957.     if (bMutex)
  1958.     {
  1959. DisplayMutex_Lock();
  1960.     }
  1961.     if (pClipRect)
  1962.     {
  1963. rViewRect = *pClipRect;
  1964. // Insure the ViewRect is inside the bitmap Rect
  1965. // Clip x
  1966. rViewRect.left = (rViewRect.left > 0) ?
  1967.     rViewRect.left : 0;
  1968. rViewRect.right = (rViewRect.right > 0) ?
  1969.     rViewRect.right : 0;
  1970. rViewRect.left = (rViewRect.left < bitmapInfoHeader.biWidth) ?
  1971.     rViewRect.left : bitmapInfoHeader.biWidth;
  1972. rViewRect.right = (rViewRect.right < bitmapInfoHeader.biWidth) ?
  1973.     rViewRect.right : bitmapInfoHeader.biWidth;
  1974. // Clip y
  1975. rViewRect.top = (rViewRect.top > 0) ?
  1976.     rViewRect.top : 0;
  1977. rViewRect.bottom = (rViewRect.bottom > 0) ?
  1978.     rViewRect.bottom : 0;
  1979. rViewRect.top = (rViewRect.top < bitmapInfoHeader.biHeight) ?
  1980.     rViewRect.top : bitmapInfoHeader.biHeight;
  1981. rViewRect.bottom = (rViewRect.bottom < bitmapInfoHeader.biHeight) ?
  1982.     rViewRect.bottom : bitmapInfoHeader.biHeight;
  1983.     }
  1984.     else
  1985.     {
  1986. rViewRect.left = 0;
  1987. rViewRect.top = 0;
  1988. rViewRect.right = bitmapInfoHeader.biWidth;
  1989. rViewRect.bottom = bitmapInfoHeader.biHeight;
  1990.     }
  1991.     // Compute Size
  1992.     szViewFrame.cx = rViewRect.right - rViewRect.left;
  1993.     szViewFrame.cy = rViewRect.bottom - rViewRect.top;
  1994.     if ((szViewFrame.cx <= 0) || (szViewFrame.cy <= 0))
  1995.     {
  1996. if (m_pClipRect)
  1997. {
  1998.     szViewFrame.cx = m_pClipRect->right - m_pClipRect->left;
  1999.     szViewFrame.cy = m_pClipRect->bottom - m_pClipRect->top;
  2000. }
  2001. if ((szViewFrame.cx <= 0) || (szViewFrame.cy <= 0))
  2002. {
  2003.     szViewFrame.cx = DEFAULT_WIN_SIZE_X;
  2004.     szViewFrame.cy = DEFAULT_WIN_SIZE_Y;
  2005. }
  2006.     }
  2007.     if (m_pClipRect)
  2008.     {
  2009. bAsDefault = FALSE;
  2010.     }
  2011.     _ResizeViewFrame(szViewFrame, FALSE, TRUE, bAsDefault);
  2012.     if (bMutex)
  2013.     {
  2014. DisplayMutex_Unlock();
  2015.     }
  2016. }
  2017. /****************************************************************************
  2018.  *  ResizeViewFrame
  2019.  */
  2020. BOOL CVideoRenderer::ResizeViewFrame(HXxSize szViewFrame,
  2021.      BOOL bMutex)
  2022. {
  2023.     HX_RESULT retVal;
  2024.     retVal = _ResizeViewFrame(szViewFrame,
  2025.       bMutex,
  2026.       FALSE,
  2027.       FALSE);
  2028.     return retVal;
  2029. }
  2030. BOOL CVideoRenderer::_ResizeViewFrame(HXxSize szViewFrame,
  2031.       BOOL bMutex,
  2032.       BOOL bForceSyncResize,
  2033.       BOOL bAsDefault)
  2034. {
  2035.     BOOL bRetVal = FALSE;
  2036.     if (m_bFrameSizeInitialized)
  2037.     {
  2038. return bRetVal;
  2039.     }
  2040.     if (bMutex)
  2041.     {
  2042. DisplayMutex_Lock();
  2043.     }
  2044.     if (!m_bFrameSizeInitialized)
  2045.     {
  2046. // If window size is already set, ignore further attempts to
  2047. // resize
  2048. if (m_bWinSizeFixed)
  2049. {
  2050.     szViewFrame.cx = m_SetWinSize.cx;
  2051.     szViewFrame.cy = m_SetWinSize.cy;
  2052. }
  2053. // If resulting size invalid, default to cliprect or bitmap size
  2054. if ((szViewFrame.cx <= 0) || (szViewFrame.cy <= 0))
  2055. {
  2056.     if (((szViewFrame.cx <= 0) || (szViewFrame.cy <= 0)) &&
  2057. m_pClipRect)
  2058.     {
  2059. szViewFrame.cx = m_pClipRect->right - m_pClipRect->left;
  2060. szViewFrame.cy = m_pClipRect->bottom - m_pClipRect->top;
  2061.     }
  2062.     if ((szViewFrame.cx <= 0) || (szViewFrame.cy <= 0))
  2063.     {
  2064. szViewFrame.cx = m_BitmapInfoHeader.biWidth;
  2065. szViewFrame.cy = m_BitmapInfoHeader.biHeight;
  2066.     }
  2067. }
  2068. m_SetWinSize.cx = szViewFrame.cx;
  2069. m_SetWinSize.cy = szViewFrame.cy;
  2070. #if !defined(HELIX_FEATURE_VIDREND_DYNAMIC_RESIZE)
  2071. m_bWinSizeFixed = (m_bWinSizeFixed || (!bAsDefault));
  2072. #else
  2073.         HX_ASSERT(!m_bWinSizeFixed);
  2074. #endif
  2075. #ifdef RESIZE_AFTER_SITE_ATTACHED
  2076. if (m_bSiteAttached)
  2077. #endif // RESIZE_AFTER_SITE_ATTACHED
  2078. {
  2079. #ifdef SET_NONZERO_VIEWFRAME_ONLY
  2080.     if ((szViewFrame.cx > 0) && (szViewFrame.cy > 0))
  2081. #endif // SET_NONZERO_VIEWFRAME_ONLY
  2082.     {
  2083. #ifdef SYNC_RESIZE_OK
  2084. bForceSyncResize = TRUE;
  2085. #endif // SYNC_RESIZE_OK
  2086. if ((m_LastSetSize.cx != szViewFrame.cx) ||
  2087.     (m_LastSetSize.cy != szViewFrame.cy))
  2088. {
  2089.     m_LastSetSize = szViewFrame;
  2090.     if (bForceSyncResize)
  2091.     {
  2092. m_pMISUSSite->SetSize(szViewFrame);
  2093.     }
  2094.     else
  2095.     {
  2096. if (m_pResizeCB == NULL)
  2097. {
  2098.     m_pResizeCB = new CSetSizeCB(m_pMISUSSite);
  2099.     HX_ASSERT(m_pResizeCB);
  2100.     if (m_pResizeCB)
  2101.     {
  2102. m_pResizeCB->AddRef();
  2103.     }
  2104. }
  2105. if (m_pResizeCB)
  2106. {
  2107.     m_pResizeCB->SetSize(szViewFrame);
  2108.     HX_ASSERT(m_pScheduler);
  2109.     if (m_pScheduler)
  2110.     {
  2111. m_pScheduler->RelativeEnter(m_pResizeCB, 0);
  2112.     }
  2113. }
  2114.     }
  2115. }
  2116.     }
  2117.     // Once the the frame size is initialized, it is no longer
  2118.     // changable by the renderer.
  2119.     // The frame size can become initialzied only of the window
  2120.     // size is fixed. It can become fixed only if explicitly set
  2121.     // by non-default mode call to ResizeViewFrame.  ResizeViewFrame
  2122.     // can be called in non-default mode by either the video format
  2123.     // or the call can be made internally based on meta-header
  2124.     // specified information (e.g. clip rect.)
  2125.     if (m_bWinSizeFixed)
  2126.     {
  2127. m_bFrameSizeInitialized = TRUE;
  2128. bRetVal = TRUE;
  2129.     }
  2130. }
  2131.     }
  2132.     if (bMutex)
  2133.     {
  2134. DisplayMutex_Unlock();
  2135.     }
  2136.     return bRetVal;
  2137. }
  2138. /****************************************************************************
  2139.  *  SetSyncInterval
  2140.  */
  2141. void CVideoRenderer::SetSyncInterval(ULONG32 ulSyncInterval)
  2142. {
  2143.     if (ulSyncInterval != 0)
  2144.     {
  2145. m_ulSyncInterval = ulSyncInterval;
  2146.     }
  2147. }
  2148. /****************************************************************************
  2149.  *  InitExtraStats
  2150.  */
  2151. HX_RESULT CVideoRenderer::InitExtraStats(void)
  2152. {
  2153.     return HXR_OK;
  2154. }
  2155. /****************************************************************************
  2156.  *  Method:
  2157.  *    CVideoFormat::AdjustVideoMapping
  2158.  *
  2159.  */
  2160. void CVideoRenderer::AdjustVideoMapping(HXxRect &destRect,
  2161. HXxRect &sorcRect,
  2162. CMediaPacket*pActiveVideoPacket)
  2163. {
  2164.     return;
  2165. }
  2166. /****************************************************************************
  2167.  *  Renderer's private fuctions
  2168.  */
  2169. BOOL CVideoRenderer::ForceRefresh(void)
  2170. {
  2171.     BOOL bIsVisible;
  2172.     // Ask what the size was really set to!
  2173.     HXxSize finalSize;
  2174.     m_pMISUSSite->GetSize(finalSize);
  2175.     /* We now damage the entire rect all the time             */
  2176.     HXxRect damageRect = {0, 0, finalSize.cx, finalSize.cy};
  2177.     // Mark associated screen area as damaged as well...
  2178.     m_pMISUSSite->DamageRect(damageRect);
  2179.     HX_ASSERT(!m_bPendingRedraw);
  2180.     HX_ASSERT(!m_bVS1UpdateInProgress);
  2181.     m_bPendingRedraw = TRUE;
  2182.     m_bVS1UpdateInProgress = TRUE;
  2183.     m_pVSMutex->Unlock();
  2184.     m_pMISUSSite->ForceRedraw();
  2185.     m_pVSMutex->Lock();
  2186.     m_bVS1UpdateInProgress = FALSE;
  2187.     // If the redraw is still pending, it did not occur so assume the
  2188.     // surface is invisible
  2189.     bIsVisible = !m_bPendingRedraw;
  2190.     m_bPendingRedraw = FALSE;
  2191.     return bIsVisible;
  2192. }
  2193. HX_RESULT CVideoRenderer::UpdateDisplay(HXxEvent* pEvent,
  2194. BOOL bSystemEvent,
  2195. BOOL bIsVisible)
  2196. {
  2197.     IHXVideoSurface* pVideoSurface;
  2198.     CMediaPacket* pTmpPacket;
  2199.     CMediaPacket* pVideoPacket = NULL;
  2200.     BOOL bBitmapFormatChanged = FALSE;
  2201.     BOOL bNewFrameBlt = FALSE;
  2202.     HXxSize windowSize = {0, 0};
  2203.     LONG32 lFramesInBuffer;
  2204.     HX_RESULT retVal = HXR_OK;
  2205.     if (m_bVS1UpdateInProgress && m_bUseVideoSurface2)
  2206.     {
  2207. // Ignore update for incorrect surface
  2208. return HXR_OK;
  2209.     }
  2210.     lFramesInBuffer = m_pBltPacketQueue->Count();
  2211.     m_bPendingRedraw = FALSE;
  2212.     HX_TRACE_THINGY("C:/trace.txt", "Handle", m_hPendingHandle);
  2213.     if (!m_bUseVideoSurface2 || !bSystemEvent)
  2214.     {
  2215. do
  2216. {
  2217.     pVideoPacket = (CMediaPacket*) m_pBltPacketQueue->Get();
  2218.     lFramesInBuffer--;
  2219.     if ((lFramesInBuffer <= 0) ||
  2220. (!m_pVideoFormat->IsFrameSkippable(pVideoPacket)))
  2221.     {
  2222. bNewFrameBlt = TRUE;
  2223. break;
  2224.     }
  2225. #if defined(HELIX_FEATURE_STATS)
  2226.     m_pVideoStats->ReportDroppedFrame();
  2227. #endif /* HELIX_FEATURE_STATS */
  2228.     ReleasePacket(pVideoPacket);
  2229. } while (TRUE);
  2230.     }
  2231.     pVideoSurface = (IHXVideoSurface*) (pEvent->param1);
  2232.     if (pVideoPacket)
  2233.     {
  2234. if (m_bVS2BufferUnavailableOnLastBlt &&
  2235.     m_pActiveVideoPacket)
  2236. {
  2237.     m_bVS2BufferUnavailableOnLastBlt = FALSE;
  2238. #if defined(HELIX_FEATURE_STATS)
  2239.     m_pVideoStats->ReportDroppedFrame();
  2240. #endif /* HELIX_FEATURE_STATS */
  2241. }
  2242. pTmpPacket = pVideoPacket;
  2243. pVideoPacket = m_pActiveVideoPacket;
  2244. m_pActiveVideoPacket = pTmpPacket;
  2245. m_ulActiveVideoTime = pTmpPacket->m_ulTime;
  2246. bBitmapFormatChanged = (m_pActiveVideoPacket->m_pSampleDesc &&
  2247. m_pVideoFormat->IsBitmapFormatChanged(
  2248. m_BitmapInfoHeader,
  2249. m_pActiveVideoPacket));
  2250.     }
  2251.     if (((!m_bVideoSurfaceInitialized) && m_pActiveVideoPacket) ||
  2252. m_bVideoSurfaceReinitRequested ||
  2253. bBitmapFormatChanged)
  2254.     {
  2255. BOOL bUsedVideoSurface2 = m_bUseVideoSurface2;
  2256. if (bBitmapFormatChanged)
  2257. {
  2258.     m_pVideoFormat->InitBitmapInfoHeader(m_BitmapInfoHeader,
  2259.  m_pActiveVideoPacket);
  2260.     m_bBitmapSet = TRUE;
  2261.     m_bVideoSurfaceInitialized = FALSE; // Force full reinit
  2262. }
  2263. FormatAndSetViewFrame(m_pClipRect,
  2264.       m_BitmapInfoHeader,
  2265.       m_rViewRect,
  2266.       FALSE);
  2267. HX_ASSERT(m_bBitmapSet);
  2268. // If we do not have information on the bitmap configuration or if
  2269. // we do not have surface to cofigure - do not intialize
  2270. if (m_bBitmapSet && pVideoSurface)
  2271. {
  2272.     // Try VideoSurface2 first unless not desired
  2273.     if (m_bTryVideoSurface2 && (!m_bVideoSurface1Requested))
  2274.     {
  2275. InitVideoSurface2(m_SetWinSize.cx, m_SetWinSize.cy);
  2276.     }
  2277.     // Try VideoSurface1 if prefered or if VideoSurface2 would
  2278.     // not initialize
  2279.     if ((!m_bUseVideoSurface2) || m_bVideoSurface1Requested)
  2280.     {
  2281. // Video Surface1 must be used
  2282. InitVideoSurface1(bUsedVideoSurface2, pVideoSurface);
  2283.     }
  2284.     m_bVideoSurfaceInitialized = TRUE;
  2285.     m_bVideoSurfaceReinitRequested = FALSE;
  2286.     m_bSchedulerStartRequested = TRUE;
  2287.     // Force the cycle in the decoder pump to expedite the completion
  2288.     // of the scheduler start request.
  2289.     if (IsDecoderRunning())
  2290.     {
  2291. if (m_pDecoderPump)
  2292. {
  2293.     m_pDecoderPump->Signal();
  2294. }
  2295.     }
  2296. #if defined(HELIX_FEATURE_STATS)
  2297.     ReportStat(VS_IMAGE_WIDTH, (INT32) (m_rViewRect.right - m_rViewRect.left));
  2298.     ReportStat(VS_IMAGE_HEIGHT, (INT32) (m_rViewRect.bottom - m_rViewRect.top));
  2299. #endif /* #if defined(HELIX_FEATURE_STATS) */
  2300. }
  2301.         // Now that we have the video dimensions, check to see that this clip
  2302.         // is not going to be too taxing on the poor CPU.
  2303.         UINT32 ulMaxVidWidth = 0;
  2304.         UINT32 ulMaxVidHeight = 0;
  2305.         if( m_pPreferences && 
  2306.             ( HXR_OK == ReadPrefINT32( m_pPreferences, "MaxVideoWidth", ulMaxVidWidth ) ) &&
  2307.             ( HXR_OK == ReadPrefINT32( m_pPreferences, "MaxVideoHeight", ulMaxVidHeight ) ) )
  2308.         {
  2309.             ULONG32 ulMaxVidArea = ulMaxVidWidth * ulMaxVidHeight;
  2310.             INT32 nWidth = (INT32) (m_rViewRect.right - m_rViewRect.left);
  2311.             INT32 nHeight = (INT32) (m_rViewRect.bottom - m_rViewRect.top);
  2312.             if( (ULONG32)(nWidth*nHeight) > ulMaxVidArea )
  2313.             {
  2314.                 IHXErrorMessages * pErrMsg = NULL;
  2315.                 m_pContext->QueryInterface(IID_IHXErrorMessages, (void**)&pErrMsg);
  2316.                 if( pErrMsg )
  2317.                 {
  2318.                     pErrMsg->Report(HXLOG_ERR, HXR_SLOW_MACHINE, 0, NULL, NULL);
  2319.                     HX_RELEASE(pErrMsg);
  2320.                 }
  2321.             }
  2322.         }
  2323.     }
  2324.     
  2325.     if (m_pActiveVideoPacket && bIsVisible && pVideoSurface)
  2326.     {
  2327. HX_ASSERT(m_bVideoSurfaceInitialized);
  2328. if (m_bVideoSurfaceInitialized && m_pActiveVideoPacket->m_pData)
  2329. {
  2330. #ifdef DEFAULT_VS2_TARGETRECT
  2331.     if (!m_bUseVideoSurface2)
  2332. #endif // DEFAULT_VS2_TARGETRECT
  2333.     {
  2334. m_pMISUSSite->GetSize(windowSize);
  2335.     }
  2336.     HXxRect rDestRect = { 0, 0, windowSize.cx, windowSize.cy };
  2337.     HXxRect rSrcRect = m_rViewRect;
  2338.     AdjustVideoMapping(rDestRect, rSrcRect, m_pActiveVideoPacket);
  2339.     if (m_bUseVideoSurface2)
  2340.     {
  2341. pEvent->result = UpdateVideoSurface2(pVideoSurface,
  2342.      rDestRect,
  2343.      rSrcRect,
  2344.      !bNewFrameBlt,
  2345.      bSystemEvent);
  2346. if (pEvent->result == HXR_ABORT)
  2347. {
  2348.     pEvent->result = HXR_OK;
  2349.     retVal = HXR_ABORT;
  2350. }
  2351.     }
  2352.     else if (bSystemEvent)
  2353.     {
  2354. pEvent->result = UpdateVideoSurface(pVideoSurface,
  2355.     m_pActiveVideoPacket,
  2356.     rDestRect,
  2357.     rSrcRect,
  2358.     m_bOptimizedBlt);
  2359. if (FAILED(pEvent->result))
  2360. {
  2361.     if (m_bVideoSurfaceReinitRequested)
  2362.     {
  2363. HX_ASSERT(!m_bVideoSurface1Requested);
  2364. InitVideoSurface2(m_SetWinSize.cx, m_SetWinSize.cy);
  2365. if (m_bUseVideoSurface2)
  2366. {
  2367.     m_bVideoSurfaceInitialized = TRUE;
  2368.     m_bVideoSurfaceReinitRequested = FALSE;
  2369.     pEvent->result = UpdateVideoSurface2(pVideoSurface,
  2370.  rDestRect,
  2371.  rSrcRect,
  2372.  FALSE,
  2373.  bSystemEvent);
  2374.     if (pEvent->result == HXR_ABORT)
  2375.     {
  2376. pEvent->result = HXR_OK;
  2377.     }
  2378. }
  2379.     }
  2380.     else
  2381.     {
  2382. InitVideoSurface1(FALSE, pVideoSurface);
  2383. pEvent->result = UpdateVideoSurface(pVideoSurface,
  2384.     m_pActiveVideoPacket,
  2385.     rDestRect,
  2386.     rSrcRect,
  2387.     m_bOptimizedBlt);
  2388.     }
  2389. }
  2390.     }
  2391.     else
  2392.     {
  2393. // This is not a system event and this call is not under
  2394. // the protection of the top level site (TLS) mutex and
  2395. // it needs to be.
  2396. // Bring it under the TLS mutex protection by envoking
  2397. // forced refresh
  2398. bIsVisible = ForceRefresh();
  2399. pEvent->result = HXR_OK;
  2400. retVal = HXR_ABORT;
  2401.     }
  2402.     if (bNewFrameBlt && bIsVisible)
  2403.     {
  2404. #if defined(HELIX_FEATURE_STATS)
  2405. if (pEvent->result == HXR_OK)
  2406. {
  2407.     m_pVideoStats->ReportBlt(m_pActiveVideoPacket->m_ulTime);
  2408. }
  2409. else if (!m_bVS2BufferUnavailableOnLastBlt)
  2410. {
  2411.     // If buffer wasn't available, we'll try again
  2412.     m_pVideoStats->ReportDroppedFrame();
  2413. }
  2414. #endif /* HELIX_FEATURE_STATS */
  2415.     }
  2416. }
  2417.     }
  2418.     if (pVideoPacket)
  2419.     {
  2420. ReleasePacket(pVideoPacket, m_bActiveVideoPacketLocalized);
  2421. m_bActiveVideoPacketLocalized = FALSE;
  2422.     }
  2423.     pEvent->handled = TRUE;
  2424.     return retVal;
  2425. }
  2426. HX_RESULT CVideoRenderer::UpdateVideoSurface(IHXVideoSurface* pVideoSurface,
  2427.      CMediaPacket* pVideoPacket,
  2428.      HXxRect &destRect,
  2429.      HXxRect &sorcRect,
  2430.      BOOL bOptimizedBlt)
  2431. {
  2432.     HX_RESULT retVal;
  2433.     if (bOptimizedBlt)
  2434.     {
  2435. retVal = pVideoSurface->OptimizedBlt(
  2436.     pVideoPacket->m_pData,
  2437.     destRect,
  2438.     sorcRect);
  2439.     }
  2440.     else
  2441.     {
  2442. retVal = pVideoSurface->Blt(
  2443.     pVideoPacket->m_pData,
  2444.     &m_BitmapInfoHeader,
  2445.     destRect,
  2446.     sorcRect);
  2447.     }
  2448.     return retVal;
  2449. }
  2450. HX_RESULT CVideoRenderer::InitVideoSurface1(BOOL bUsedVideoSurface2,
  2451.     IHXVideoSurface* pVideoSurface)
  2452. {
  2453.     HX_RESULT retVal = HXR_OK;
  2454.     if (bUsedVideoSurface2)
  2455.     {
  2456. OffOptimizedVideo();
  2457.     }
  2458.     /***
  2459.     if (pVideoSurface)
  2460.     {
  2461. retVal = pVideoSurface->EndOptimizedBlt();
  2462.     }
  2463.     else
  2464.     {
  2465. EndOptimizedBlt();
  2466.     }
  2467.     ***/
  2468.     // Video Surface1 is needed - try optimized Blt setup
  2469.     if (!m_bVideoSurfaceInitialized)
  2470.     {
  2471. if (pVideoSurface)
  2472. {
  2473.     retVal = pVideoSurface->BeginOptimizedBlt(&m_BitmapInfoHeader);
  2474. }
  2475. else
  2476. {
  2477.     retVal = BeginOptimizedBlt(&m_BitmapInfoHeader);
  2478. }
  2479. if (SUCCEEDED(retVal))
  2480. {
  2481.     m_bOptimizedBlt = TRUE;
  2482. }
  2483. else
  2484. {
  2485.     m_bOptimizedBlt = FALSE;
  2486. }
  2487. retVal = HXR_OK;
  2488.     }
  2489.     if (SUCCEEDED(retVal))
  2490.     {
  2491. m_ulEarlyFrameTol = GetEarlyFrameTolerance();
  2492. HX_DELETE(m_pVSurf2InputBIH);
  2493. m_bUseVideoSurface2 = FALSE;
  2494. if (m_bVS2BufferUnavailableOnLastBlt)
  2495. {
  2496. #if defined(HELIX_FEATURE_STATS)
  2497.     m_pVideoStats->ReportDroppedFrame();
  2498. #endif /* HELIX_FEATURE_STATS */
  2499.     m_bVS2BufferUnavailableOnLastBlt = FALSE;
  2500. }
  2501.     }
  2502.     return retVal;
  2503. }
  2504. inline BOOL CVideoRenderer::ShouldKickStartScheduler()
  2505. {
  2506.     BOOL bShouldStart;
  2507.     bShouldStart = (!m_bPendingCallback && !m_bUseVideoSurface2);
  2508.     return bShouldStart;
  2509. }
  2510. HX_RESULT CVideoRenderer::ScheduleCallback(UINT32 ulRelativeTime,
  2511.    BOOL bIsScheduled,
  2512.    UINT32 ulBaseTime)
  2513. {
  2514.     IHXCallback* pCallback = (IHXCallback*) this;
  2515.     CallbackHandle hPendingHandle;
  2516.     ULONG32 ulThisCallbackCount;
  2517.     if (m_hPendingHandle == (CallbackHandle)NULL)
  2518.     {
  2519. m_bPendingCallback = TRUE;
  2520. m_ulCallbackCounter++;
  2521. if (m_ulCallbackCounter == 0)
  2522. {
  2523.     m_ulCallbackCounter++;
  2524. }
  2525. ulThisCallbackCount = m_ulCallbackCounter;
  2526. m_hPendingHandle = ulThisCallbackCount;
  2527. m_bIsScheduledCB = bIsScheduled;
  2528. if (ulRelativeTime > m_ulMaxSleepTime)
  2529. {
  2530.     ulRelativeTime = m_ulMaxSleepTime;
  2531.     m_bIsScheduledCB = FALSE;
  2532. }
  2533. HX_TRACE_THINGY("C:/trace.txt", "SchedCBTime", ulRelativeTime);
  2534. #ifdef DO_ABSOLUTE_TIMING
  2535. LONG32 lTimeOffset;
  2536. HXTimeval hxTime;
  2537. ULONG32 ulNTries = N_STABILIZATION_ITERATIONS;
  2538. ULONG32 ulCurrentTime1;
  2539. ULONG32 ulCurrentTime2;
  2540. if (bIsScheduled)
  2541. {
  2542.     // Obtain atomic time reading (avoid context switch)
  2543.     do
  2544.     {
  2545. ulCurrentTime1 = HX_GET_BETTERTICKCOUNT();
  2546. // Always use the optimized scheduler if we have one
  2547. if (m_pOptimizedScheduler != NULL)
  2548. {
  2549.     hxTime = m_pOptimizedScheduler->GetCurrentSchedulerTime();
  2550. }
  2551. else
  2552. {
  2553.     hxTime = m_pScheduler->GetCurrentSchedulerTime();
  2554. }
  2555. ulCurrentTime2 = HX_GET_BETTERTICKCOUNT();
  2556. lTimeOffset = (LONG32) (ulCurrentTime2 - ulBaseTime + ulRelativeTime);
  2557. ulNTries--;
  2558.     } while (((ulCurrentTime2 - ulCurrentTime1) > MAX_ALLOWED_TIMING_ERROR) &&
  2559. (ulNTries != 0) &&
  2560. (lTimeOffset > 0));
  2561.     if (lTimeOffset >= SMALLEST_TIMABLE_PERIOD)
  2562.     {
  2563. hxTime.tv_usec += (lTimeOffset * MILLISECOND);
  2564. if (hxTime.tv_usec >= SECOND)
  2565. {
  2566.     hxTime.tv_sec += (hxTime.tv_usec / SECOND);
  2567.     hxTime.tv_usec %= SECOND;
  2568. }
  2569.     }
  2570.     hPendingHandle = ScheduleAbsoluteCallback(hxTime, pCallback);
  2571. }
  2572. else
  2573. #endif  // DO_ABSOLUTE_TIMING
  2574. {
  2575.     hPendingHandle = ScheduleRelativeCallback(ulRelativeTime, pCallback);
  2576. }
  2577. HX_ASSERT(hPendingHandle);
  2578. // Remember the handle if callback did not already fire synchronously
  2579. if (m_hPendingHandle == ulThisCallbackCount)
  2580. {
  2581.     HX_TRACE_THINGY("C:/trace.txt", "SchedCBHandle", hPendingHandle);
  2582.     m_hPendingHandle = hPendingHandle;
  2583.     m_bPendingCallback = (m_hPendingHandle != ((CallbackHandle) NULL));
  2584. }
  2585.     }
  2586.     return HXR_OK;
  2587. }
  2588. inline CallbackHandle CVideoRenderer::ScheduleRelativeCallback
  2589. (
  2590.     UINT32 ulRelativeTime,
  2591.     IHXCallback* pCallback
  2592. )
  2593. {
  2594.     CallbackHandle hCallback;
  2595.     // Always use the optimized scheduler if we have one
  2596.     if (m_pOptimizedScheduler != NULL)
  2597.     {
  2598. hCallback = m_pOptimizedScheduler->RelativeEnter(
  2599.     pCallback, ulRelativeTime);
  2600.     }
  2601.     else
  2602.     {
  2603. hCallback = m_pScheduler->RelativeEnter(
  2604.     pCallback, ulRelativeTime);
  2605.     }
  2606.     return hCallback;
  2607. }
  2608. inline CallbackHandle CVideoRenderer::ScheduleAbsoluteCallback
  2609. (
  2610.     HXTimeval &hxTime,
  2611.     IHXCallback* pCallback
  2612. )
  2613. {
  2614.     CallbackHandle hCallback;
  2615.     // Always use the optimized scheduler if we have one
  2616.     if (m_pOptimizedScheduler != NULL)
  2617.     {
  2618. hCallback = m_pOptimizedScheduler->AbsoluteEnter(
  2619.     pCallback, hxTime);
  2620.     }
  2621.     else
  2622.     {
  2623. hCallback = m_pScheduler->AbsoluteEnter(
  2624.     pCallback, hxTime);
  2625.     }
  2626.     return hCallback;
  2627. }
  2628. void CVideoRenderer::RemoveCallback(CallbackHandle &hCallback)
  2629. {
  2630.     if (hCallback != (CallbackHandle)NULL)
  2631.     {
  2632. if (m_pOptimizedScheduler != NULL)
  2633. {
  2634.     m_pOptimizedScheduler->Remove(hCallback);
  2635. }
  2636. else if (m_pScheduler)
  2637. {
  2638.     m_pScheduler->Remove(hCallback);
  2639. }
  2640. hCallback = NULL;
  2641.     }
  2642. }
  2643. /*
  2644.  *   Draw any frame that's due, and schedule a new callback for the next
  2645.  *   frame
  2646.  */
  2647. void CVideoRenderer::SchedulerCallback(BOOL bIsScheduled,
  2648.        BOOL bResched,
  2649.        BOOL bIsVS2Call,
  2650.        BOOL bProcessUndisplayableFramesOnly)
  2651. {
  2652.     CMediaPacket* pPkt;
  2653.     LONG32 lTimeDelta;
  2654.     ULONG32 ulNextFrameTime;
  2655.     BOOL bFrameIsSkippable;
  2656.     ULONG32 ulBaseTime;
  2657.     BOOL bHaveNextFrame;
  2658.     BOOL bDisplayFrame;
  2659.     ULONG32 ulLoopCounter = 0;
  2660.     DisplayMutex_Lock();
  2661.     while ((m_PlayState == Playing) ||
  2662.    ((m_PlayState == PlayStarting) && m_bFirstFrame))
  2663.     {
  2664. if (m_bUseVideoSurface2)
  2665. {
  2666.     if (bIsVS2Call)
  2667.     {
  2668. m_bVideoSurface2Transition = FALSE;
  2669.     }
  2670.     else
  2671.     {
  2672. m_bPendingCallback = FALSE;
  2673. DisplayMutex_Unlock();
  2674. return;
  2675.     }
  2676. }
  2677. else
  2678. {
  2679.     if (bIsVS2Call)
  2680.     {
  2681. DisplayMutex_Unlock();
  2682. return;
  2683.     }
  2684.     m_bVS2BufferUnavailableOnLastBlt = FALSE;
  2685. }
  2686. #ifdef ENABLE_FETCH_TRACE
  2687. ULONG32 ulFetchTraceStart = HX_GET_BETTERTICKCOUNT();
  2688. #endif // ENABLE_FETCH_TRACE
  2689. bDisplayFrame = TRUE;
  2690. #ifdef HELIX_FEATURE_VIDREND_UNTIMED_DECODE
  2691. if( !m_bUntimedRendering )
  2692. {
  2693. #endif /* HELIX_FEATURE_VIDREND_UNTIMED_DECODE */
  2694. while ((bHaveNextFrame = m_pVideoFormat->GetNextFrameTime(ulNextFrameTime)) != 0)
  2695. {
  2696. #ifdef ENABLE_FETCH_TRACE
  2697.     if (ulFetchTraceIdx < MAX_FETCH_TRACE_ENTRIES)
  2698.     {
  2699. fetchTraceArray[ulFetchTraceIdx++] =
  2700.     HX_GET_BETTERTICKCOUNT() - ulFetchTraceStart;
  2701.     }
  2702. #endif // ENABLE_FETCH_TRACE
  2703.     lTimeDelta = ComputeTimeAhead(ulNextFrameTime,
  2704.   0,
  2705.   &ulBaseTime);
  2706.     if (((lTimeDelta + ((LONG32) m_ulLateFrameTol)) >= 0) ||
  2707. bIsScheduled ||
  2708. m_bVS2BufferUnavailableOnLastBlt)
  2709.     {
  2710. break;
  2711.     }
  2712.     else
  2713.     {
  2714. #ifdef ENABLE_SCHED_TRACE
  2715. if (ulSchedTraceIdx < MAX_SCHED_TRACE_ENTRIES)
  2716. {
  2717.     schedTraceArray[ulSchedTraceIdx++] = lTimeDelta;
  2718. }
  2719. #endif // ENABLE_SCHED_TRACE
  2720. bFrameIsSkippable = TRUE;
  2721. m_pVideoFormat->IsNextFrameSkippable(bFrameIsSkippable);
  2722. if (!bFrameIsSkippable)
  2723. {
  2724.     if (m_bFirstFrame)
  2725.     {
  2726. bDisplayFrame = FALSE;
  2727.     }
  2728.     break;
  2729. }
  2730.     }
  2731. #ifdef ENABLE_FETCH_TRACE
  2732.     ulFetchTraceStart = HX_GET_BETTERTICKCOUNT();
  2733. #endif // ENABLE_FETCH_TRACE
  2734.     pPkt = m_pVideoFormat->Dequeue();
  2735. #ifdef ENABLE_FETCH_TRACE
  2736.     if (ulFetchTraceIdx < MAX_FETCH_TRACE_ENTRIES)
  2737.     {
  2738. fetchTraceArray[ulFetchTraceIdx++] =
  2739.     HX_GET_BETTERTICKCOUNT() - ulFetchTraceStart;
  2740.     }
  2741. #endif // ENABLE_FETCH_TRACE
  2742.     if (!m_bFirstFrame)
  2743.     {
  2744. #if defined(HELIX_FEATURE_STATS)
  2745. m_pVideoStats->ReportDroppedFrame();
  2746. #endif /* HELIX_FEATURE_STATS */
  2747.     }
  2748.     ReleasePacket(pPkt);
  2749. }
  2750. #ifdef HELIX_FEATURE_VIDREND_UNTIMED_DECODE
  2751. } else {
  2752.          bHaveNextFrame = m_pVideoFormat->GetNextFrameTime(ulNextFrameTime);
  2753.     lTimeDelta = 0;
  2754.     ComputeTimeAhead( 0, 0, &ulBaseTime );
  2755. }
  2756. #endif /* HELIX_FEATURE_VIDREND_UNTIMED_DECODE */
  2757. if (bProcessUndisplayableFramesOnly && bDisplayFrame)
  2758. {
  2759.     DisplayMutex_Unlock();
  2760.     return;
  2761. }
  2762. if (!m_bVS2BufferUnavailableOnLastBlt)
  2763. {
  2764.     if (bHaveNextFrame)
  2765.     {
  2766. if ((lTimeDelta > ((LONG32) m_ulEarlyFrameTol)) &&
  2767.     (!m_bFirstFrame))
  2768. {
  2769.     if (bResched)
  2770.     {
  2771. ScheduleCallback(lTimeDelta, TRUE, ulBaseTime);
  2772.     }
  2773.     DisplayMutex_Unlock();
  2774.     return;
  2775. }
  2776.     }
  2777.     else
  2778.     {
  2779. if (bResched)
  2780. {
  2781.     // m_pVideoFormat->DecodeFrame();  MBO: Give user Input priority
  2782.     ScheduleCallback(m_ulNoFramesPollingInterval);
  2783. }
  2784. DisplayMutex_Unlock();
  2785. return;
  2786.     }
  2787.     // Render
  2788.     pPkt = m_pVideoFormat->Dequeue();
  2789. }
  2790. else
  2791. {
  2792.     // We need to reblt - but if there is a frame that's up to date
  2793.     // use it instead of old failed frame.
  2794.     pPkt = NULL;
  2795.     if (bHaveNextFrame && (lTimeDelta <= 0))
  2796.     {
  2797. pPkt = m_pVideoFormat->Dequeue();
  2798.     }
  2799. }
  2800. if (pPkt != NULL)
  2801. {
  2802. #ifdef ENABLE_SCHED_TRACE
  2803.     if (ulSchedTraceIdx < MAX_SCHED_TRACE_ENTRIES)
  2804.     {
  2805. schedTraceArray[ulSchedTraceIdx++] = lTimeDelta;
  2806.     }
  2807. #endif // ENABLE_SCHED_TRACE
  2808.     if (m_pMISUSSite &&
  2809. m_pBltPacketQueue->Put(pPkt))
  2810.     {
  2811. if (pPkt->m_pData && bDisplayFrame)
  2812. {
  2813.     m_bFirstFrame = FALSE;
  2814. }
  2815. if (m_bUseVideoSurface2)
  2816. {
  2817.     ForceDisplayUpdate(FALSE, bDisplayFrame);
  2818.     if (m_bVS2BufferUnavailableOnLastBlt)
  2819.     {
  2820. // We couldn't blt frame because video buffer
  2821. // wasn't available, try again a bit later
  2822. DisplayMutex_Unlock();
  2823. return;
  2824.     }
  2825. }
  2826. else
  2827. {
  2828.     if ((!bDisplayFrame) || (!ForceRefresh()))
  2829.     {
  2830. // Site redraw did not occur - treat this as if the surface
  2831. // is invisible
  2832. ForceDisplayUpdate(FALSE, FALSE);
  2833. HX_ASSERT(!m_bPendingRedraw);
  2834.     }
  2835. }
  2836.     }
  2837.     else
  2838.     {
  2839. #if defined(HELIX_FEATURE_STATS)
  2840. m_pVideoStats->ReportDroppedFrame();
  2841. #endif /* HELIX_FEATURE_STATS */
  2842. ReleasePacket(pPkt);
  2843.     }
  2844. }
  2845. else
  2846. {
  2847.     // This is a reblt servicing
  2848.     if (m_bUseVideoSurface2)
  2849.     {
  2850. HX_ASSERT(bDisplayFrame);
  2851. ForceDisplayUpdate(FALSE, bDisplayFrame);
  2852. if (m_bVS2BufferUnavailableOnLastBlt)
  2853. {
  2854.     // We couldn't blt frame because video buffer
  2855.     // wasn't available, try again a bit later
  2856.     DisplayMutex_Unlock();
  2857.     return;
  2858. }
  2859.     }
  2860. }
  2861. if (bResched)
  2862. {
  2863.     ulLoopCounter++;
  2864.     if (ulLoopCounter > MAX_BLT_LOOPS)
  2865.     {
  2866. ScheduleCallback(BLT_RELIEF_DELAY);
  2867. DisplayMutex_Unlock();
  2868. return;
  2869.     }
  2870. }
  2871. else
  2872. {
  2873.     if (!bIsVS2Call)
  2874.     {
  2875. DisplayMutex_Unlock();
  2876. return;
  2877.     }
  2878. }
  2879. bIsScheduled = FALSE;
  2880.     }
  2881.     if ((m_PlayState != Stopped) &&
  2882. bResched)
  2883.     {
  2884. ScheduleCallback(NO_FRAMES_POLLING_INTERVAL);
  2885. DisplayMutex_Unlock();
  2886. return;
  2887.     }
  2888.     m_bPendingCallback = FALSE;
  2889.     DisplayMutex_Unlock();
  2890. }
  2891. void CVideoRenderer::ForceDisplayUpdate(BOOL bInternalSurfaceUpdateOnly,
  2892. BOOL bHasVisibleSurface)
  2893. {
  2894.     // Create fake events for HandleSurfaceUpdate:
  2895.     HX_ASSERT(m_pMISUSSite);
  2896. #if defined (HELIX_FEATURE_MISU)
  2897.     IHXSiteEnumerator* pSiteEnumerator;
  2898.     if (SUCCEEDED(m_pMISUSSite->QueryInterface(IID_IHXSiteEnumerator,
  2899.        (void**) &pSiteEnumerator)))
  2900.     {
  2901. IHXSite* pSite;
  2902. IHXSiteEnumerator::SitePosition nextPosition;
  2903. if (FAILED(pSiteEnumerator->GetFirstSite(pSite, nextPosition)))
  2904. {
  2905.     HX_ASSERT(FALSE);
  2906. }
  2907. else
  2908. {
  2909.     BOOL bKeepUpdating = TRUE;
  2910.     do
  2911.     {
  2912. bKeepUpdating = (ForceDisplayUpdateOnSite(pSite, 
  2913.   bInternalSurfaceUpdateOnly, 
  2914.   bHasVisibleSurface) != HXR_ABORT);
  2915. pSite->Release();
  2916.     }
  2917.     while (bKeepUpdating &&
  2918.    SUCCEEDED(pSiteEnumerator->GetNextSite(pSite, nextPosition)));
  2919. }
  2920. pSiteEnumerator->Release();
  2921.     }
  2922.     else
  2923.     {
  2924. ForceDisplayUpdateOnSite(m_pMISUSSite,
  2925.  bInternalSurfaceUpdateOnly,
  2926.  bHasVisibleSurface);
  2927.     }
  2928. #else //HELIX_FEATURE_MISU
  2929.     ForceDisplayUpdateOnSite(m_pMISUSSite,
  2930.      bInternalSurfaceUpdateOnly,
  2931.      bHasVisibleSurface);
  2932. #endif //HELIX_FEATURE_MISU
  2933. }
  2934. HX_RESULT CVideoRenderer::ForceDisplayUpdateOnSite(IHXSite* pSite, 
  2935.    BOOL bInternalSurfaceUpdateOnly,
  2936.    BOOL bHasVisibleSurface)
  2937. {
  2938.     HX_RESULT retVal = HXR_OK;
  2939.     IHXVideoSurface2* pVideoSurface2;
  2940.     IHXSite2* pSite2 = NULL;
  2941.     IHXVideoSurface* pVideoSurface = NULL;
  2942.     
  2943.     if (SUCCEEDED(pSite->QueryInterface(IID_IHXSite2, (void**) &pSite2)))
  2944.     {
  2945. pSite2->GetVideoSurface(pVideoSurface);
  2946.     }
  2947.     if (bInternalSurfaceUpdateOnly)
  2948.     {
  2949. if (pVideoSurface)
  2950. {
  2951.     if (SUCCEEDED(pVideoSurface->QueryInterface(IID_IHXVideoSurface2, 
  2952. (void**) &pVideoSurface2)))
  2953.     {
  2954. pVideoSurface2->PresentIfReady();
  2955. pVideoSurface2->Release();
  2956.     }
  2957. }
  2958.     }
  2959.     else
  2960.     {
  2961. HXxEvent fakeEvent;
  2962. fakeEvent.param1 = (void*) pVideoSurface;
  2963. retVal = UpdateDisplay(&fakeEvent, FALSE, bHasVisibleSurface);
  2964.     }
  2965.     
  2966.     HX_RELEASE(pVideoSurface);
  2967.     HX_RELEASE(pSite2);
  2968.     return retVal;
  2969. }
  2970. STDMETHODIMP CVideoRenderer::Func(void)
  2971. {
  2972.     HX_TRACE_THINGY("C:/trace.txt", "Func", 0);
  2973.     m_hPendingHandle = NULL;
  2974.     SchedulerCallback(m_bIsScheduledCB);
  2975.     return HXR_OK;
  2976. }
  2977. HX_RESULT CVideoRenderer::BeginOptimizedBlt(HXBitmapInfoHeader* pBitmapInfo)
  2978. {
  2979.     HX_RESULT retVal = HXR_UNEXPECTED;
  2980.     IHXSite2* pMISUSSite2   = NULL;
  2981.     IHXVideoSurface* pVideoSurface = NULL;
  2982.     if (m_pMISUSSite)
  2983.     {
  2984.         m_pMISUSSite->QueryInterface(IID_IHXSite2, (void**)&pMISUSSite2);
  2985.         if (pBitmapInfo && pMISUSSite2)
  2986.         {
  2987.             if (SUCCEEDED(pMISUSSite2->GetVideoSurface(pVideoSurface)))
  2988.             {
  2989.                 retVal = pVideoSurface->BeginOptimizedBlt(pBitmapInfo);
  2990.                 if (retVal == HXR_OK)
  2991.                 {
  2992.                     m_bOptimizedBlt = TRUE;
  2993.                 }
  2994.                 HX_RELEASE(pVideoSurface);
  2995.             }
  2996.         }
  2997. HX_RELEASE(pMISUSSite2);
  2998.     }
  2999.     return retVal;
  3000. }
  3001. void CVideoRenderer::EndOptimizedBlt(void)
  3002. {
  3003.     IHXSite2* pMISUSSite2 = NULL;
  3004.     IHXVideoSurface* pVideoSurface = NULL;
  3005.     if (m_bOptimizedBlt && m_pMISUSSite)
  3006.     {
  3007. m_pMISUSSite->QueryInterface(IID_IHXSite2, (void**)&pMISUSSite2);
  3008. if (pMISUSSite2)
  3009. {
  3010.     pMISUSSite2->GetVideoSurface(pVideoSurface);
  3011.     if (pVideoSurface)
  3012.     {
  3013. pVideoSurface->EndOptimizedBlt();
  3014. m_bOptimizedBlt = FALSE;
  3015. HX_RELEASE(pVideoSurface);
  3016.     }
  3017. }
  3018.     }
  3019.     HX_RELEASE(pMISUSSite2);
  3020. }
  3021. inline void CVideoRenderer::RequestBuffering(void)
  3022. {
  3023.     m_bBufferingNeeded = TRUE;
  3024. }
  3025. inline void CVideoRenderer::RequestBufferingEnd(void)
  3026. {
  3027.     m_bBufferingNeeded = FALSE;
  3028. }
  3029. HX_RESULT CVideoRenderer::BeginBuffering(void)
  3030. {
  3031.     HX_RESULT retVal = HXR_FAIL;
  3032. #ifdef REBUFFER_ON_VIDEO
  3033.     m_ulBufferingStartTime = HX_GET_BETTERTICKCOUNT();
  3034.     // If this is a reccuring rebuffer, start buffering only if
  3035.     // the preroll period passed since the last buffering completion.
  3036.     // This is done to prevent buffering all the time.
  3037.     if (!m_bBufferingOccured ||
  3038. ((m_ulBufferingStartTime - m_ulBufferingStopTime) > m_ulPreroll))
  3039.     {
  3040. // Bytes to Buffer could be used for Predata
  3041. // - Predata was not found beneficial yet
  3042. m_ulBytesToBuffer = (ULONG32) (((double) m_ulPreroll) *
  3043.        ((double) m_ulAvgBitRate) /
  3044.        8000.0);
  3045. m_ulBufferingTimeOut = m_ulPreroll * 2;
  3046. if (m_ulBufferingTimeOut > 0)
  3047. {
  3048.     m_PlayState = Buffering;
  3049.     retVal = m_pStream->ReportRebufferStatus(1, 0);
  3050. }
  3051.     }
  3052. #endif // REBUFFER_ON_VIDEO
  3053.     return retVal;
  3054. }
  3055. HX_RESULT CVideoRenderer::EndBuffering(void)
  3056. {
  3057.     HX_RESULT retVal = HXR_UNEXPECTED;
  3058. #ifdef REBUFFER_ON_VIDEO
  3059.     if (m_PlayState == Buffering)
  3060.     {
  3061. m_PlayState = PlayStarting;
  3062. m_bBufferingOccured = TRUE;
  3063. m_ulBufferingStopTime = HX_GET_BETTERTICKCOUNT();
  3064. HX_ASSERT(m_pStream);
  3065. retVal = m_pStream->ReportRebufferStatus(1,1);
  3066.     }
  3067. #endif // REBUFFER_ON_VIDEO
  3068.     return retVal;
  3069. }
  3070. inline BOOL CVideoRenderer::IsBufferingComplete(IHXPacket *pPacket)
  3071. {
  3072. #ifdef REBUFFER_ON_VIDEO
  3073.     ULONG32 ulTimeNow = HX_GET_BETTERTICKCOUNT();
  3074.     if ((m_PlayState == Buffering) && (m_bBufferingNeeded))
  3075.     {
  3076. if (pPacket &&
  3077.     ((pPacket->GetTime() - m_ulBaseTime) > m_ulPreroll))
  3078. {
  3079.     return TRUE;
  3080. }
  3081. return ((ulTimeNow - m_ulBufferingStartTime) > m_ulBufferingTimeOut);
  3082.     }
  3083. #endif // REBUFFER_ON_VIDEO
  3084.     return TRUE;
  3085. }
  3086. HX_RESULT CVideoRenderer::LocalizeActiveVideoPacket(void)
  3087. {
  3088.     HX_RESULT retVal = HXR_IGNORE;
  3089.     DisplayMutex_Lock();
  3090.     if (m_pActiveVideoPacket && (!m_bActiveVideoPacketLocalized))
  3091.     {
  3092. CMediaPacket* pLocalPacket = NULL;
  3093. ULONG32 ulDataSize = m_pActiveVideoPacket->m_ulDataSize;
  3094. UINT8* pData = new UINT8 [ulDataSize];
  3095. retVal = HXR_OUTOFMEMORY;
  3096. if (pData)
  3097. {
  3098.     retVal = HXR_OK;
  3099. }
  3100. if (retVal == HXR_OK)
  3101. {
  3102.     pLocalPacket = new CMediaPacket(pData,
  3103.     pData,
  3104.     ulDataSize,
  3105.     ulDataSize,
  3106.     m_pActiveVideoPacket->m_ulTime,
  3107.     m_pActiveVideoPacket->m_ulFlags,
  3108.     NULL);
  3109.     retVal = HXR_OUTOFMEMORY;
  3110.     if (pLocalPacket)
  3111.     {
  3112. retVal = HXR_OK;
  3113.     }
  3114. }
  3115. if (retVal == HXR_OK)
  3116. {
  3117.     memcpy(pData, m_pActiveVideoPacket->m_pData, ulDataSize); /* Flawfinder: ignore */
  3118.     ReleasePacket(m_pActiveVideoPacket);
  3119.     m_pActiveVideoPacket = pLocalPacket;
  3120.     m_bActiveVideoPacketLocalized = TRUE;
  3121. }
  3122. else
  3123. {
  3124.     HX_VECTOR_DELETE(pData);
  3125.     HX_DELETE(pLocalPacket);
  3126. }
  3127.     }
  3128.     DisplayMutex_Unlock();
  3129.     return retVal;
  3130. }
  3131. void CVideoRenderer::ReleaseFramePacket(CMediaPacket* pPacket)
  3132. {
  3133.     ReleasePacket(pPacket);
  3134. }
  3135. void CVideoRenderer::ReleasePacket(CMediaPacket* pPacket,
  3136.   BOOL bForceKill)
  3137. {
  3138.     CHXBufferPool* pFramePool = NULL;
  3139.     if (m_pVideoFormat)
  3140.     {
  3141. m_pVideoFormat->OnDecodedPacketRelease(pPacket);
  3142. pFramePool = m_pVideoFormat->GetFramePool();
  3143.     }
  3144.     if (pPacket)
  3145.     {
  3146. if (pFramePool && (!bForceKill))
  3147. {
  3148.     pFramePool->Put(pPacket);
  3149. }
  3150. else
  3151. {
  3152.     pPacket->Clear();
  3153.     delete pPacket;
  3154. }
  3155.     }
  3156.     if (IsDecoderRunning())
  3157.     {
  3158. if (m_pDecoderPump)
  3159. {
  3160.     m_pDecoderPump->Signal();
  3161. }
  3162.     }
  3163.     else
  3164.     {
  3165. if (m_pVideoFormat)
  3166. {
  3167.     m_pVideoFormat->DecodeFrame();
  3168. }
  3169.     }
  3170. }
  3171. void CVideoRenderer::ClearBltPacketQueue(void)
  3172. {
  3173.     CMediaPacket* pVideoPacket;
  3174.     if (m_pBltPacketQueue)
  3175.     {
  3176. while ((pVideoPacket = (CMediaPacket*) m_pBltPacketQueue->Get()) != 0)
  3177. {
  3178.     ReleasePacket(pVideoPacket);
  3179. }
  3180.     }
  3181. }
  3182. /****************************************************************************
  3183.  *  CVideoRenderer::CSetSizeCB
  3184.  *  This routine increases the object reference count in a thread safe
  3185.  *  manner. The reference count is used to manage the lifetime of an object.
  3186.  *  This method must be explicitly called by the user whenever a new
  3187.  *  reference to an object is used.
  3188.  */
  3189. /****************************************************************************
  3190.  *  CVideoRenderer::CSetSizeCB::QueryInterface
  3191.  */
  3192. STDMETHODIMP CVideoRenderer::CSetSizeCB::QueryInterface(REFIID riid,
  3193.   void** ppvObj)
  3194. {
  3195.     QInterfaceList  qiList[] =
  3196.     {
  3197. { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXPlugin*) this},
  3198. { GET_IIDHANDLE(IID_IHXCallback), (IHXCallback*)this},
  3199.     };
  3200.     return ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
  3201. }
  3202. /****************************************************************************
  3203.  *  CVideoRenderer::CSetSizeCB::AddRef                             
  3204.  */
  3205. STDMETHODIMP_(ULONG32) CVideoRenderer::CSetSizeCB::AddRef()
  3206. {
  3207.     return InterlockedIncrement(&m_lRefCount);
  3208. }
  3209. /****************************************************************************
  3210.  *  CVideoRenderer::CSetSizeCB::Release
  3211.  */
  3212. STDMETHODIMP_(ULONG32) CVideoRenderer::CSetSizeCB::Release()
  3213. {
  3214.     if (InterlockedDecrement(&m_lRefCount) > 0)
  3215.     {
  3216.         return m_lRefCount;
  3217.     }
  3218.     delete this;
  3219.     return 0;
  3220. }
  3221. /****************************************************************************
  3222.  *  CVideoRenderer::CSetSizeCB::Func
  3223.  */
  3224. STDMETHODIMP CVideoRenderer::CSetSizeCB::Func()
  3225. {
  3226.     return m_pSite->SetSize(m_szViewFrame);
  3227. }
  3228. /****************************************************************************
  3229.  *  CVideoRenderer::Pacemaker Responses
  3230.  */
  3231. STDMETHODIMP CVideoRenderer::OnPaceStart(ULONG32 ulId)
  3232. {
  3233.     if (ulId == m_ulDecoderPacemakerId)
  3234.     {
  3235. if (m_pVideoFormat)
  3236. {
  3237.     m_pDecoderVideoFormat = m_pVideoFormat;
  3238.     m_pDecoderVideoFormat->AddRef();
  3239. }
  3240. m_bDecoderRunning = TRUE;
  3241.     }
  3242.     else if (ulId == m_ulBltrPacemakerId)
  3243.     {
  3244. if (m_pVideoFormat)
  3245. {
  3246.     m_pBltrVideoFormat = m_pVideoFormat;
  3247.     m_pBltrVideoFormat->AddRef();
  3248. }
  3249.     }
  3250.     return HXR_OK;
  3251. }
  3252. STDMETHODIMP CVideoRenderer::OnPaceEnd(ULONG32 ulId)
  3253. {
  3254.     if (ulId == m_ulDecoderPacemakerId)
  3255.     {
  3256. m_bDecoderRunning = FALSE;
  3257.         if (m_pDecoderVideoFormat)
  3258.         {
  3259.             m_pDecoderVideoFormat->Release();
  3260.             m_pDecoderVideoFormat = NULL;
  3261.         }
  3262.     }
  3263.     else if (ulId == m_ulBltrPacemakerId)
  3264.     {
  3265.         if (m_pBltrVideoFormat)
  3266.         {
  3267.             m_pBltrVideoFormat->Release();
  3268.             m_pBltrVideoFormat = NULL;
  3269.         }
  3270.     }
  3271.     return HXR_OK;
  3272. }
  3273. STDMETHODIMP CVideoRenderer::OnPace(ULONG32 ulId)
  3274. {
  3275.     if (ulId == m_ulBltrPacemakerId)
  3276.     {
  3277. PresentFrame();
  3278.     }
  3279.     else if (ulId == m_ulDecoderPacemakerId)
  3280.     {
  3281. if (m_bSchedulerStartRequested)
  3282. {
  3283.     StartSchedulers();
  3284. }
  3285. while ((m_pDecoderVideoFormat->DecodeFrame()) != 0) ;
  3286. #ifdef HELIX_FEATURE_VIDREND_BOOSTDECODE_ON_STARTUP
  3287. // on ce we need to get this started quickly, otherwise the initial packets expire
  3288. if (THREAD_PRIORITY_BELOW_NORMAL != GetDecodePriority())
  3289. {
  3290.     SetDecodePriority(THREAD_PRIORITY_BELOW_NORMAL);
  3291.     return HXR_OK;
  3292. }
  3293. #endif
  3294.     }
  3295.     return HXR_OK;
  3296. }
  3297. /****************************************************************************
  3298.  *  Video Surface 2 Support
  3299.  */
  3300. HX_RESULT CVideoRenderer::InitVideoSurface2(ULONG32 ulWidth, ULONG32 ulHeight)
  3301. {
  3302. #ifdef HELIX_FEATURE_VIDREND_OPTIMIZEDVIDEO
  3303.     HX_RESULT retVal = HXR_FAIL;
  3304.     BOOL bTryVideoSurface2 = m_bTryVideoSurface2;
  3305.     if (bTryVideoSurface2)
  3306.     {
  3307.         HX_ASSERT(m_pMISUSSite);
  3308.         IHXVideoSurface* pVideoSurface = NULL;
  3309. IHXVideoSurface2* pVideoSurface2 = NULL;
  3310.         IHXSite2* pSite2 = NULL;
  3311. if (m_bUseVideoSurface2 &&
  3312.     m_pVSurf2InputBIH &&
  3313.     (m_pVSurf2InputBIH->biWidth == ((LONG32) ulWidth)) &&
  3314.     (m_pVSurf2InputBIH->biHeight == ((LONG32) ulHeight)))
  3315. {
  3316.     return HXR_OK;
  3317. }
  3318. // EndOptimizedBlt();
  3319. bTryVideoSurface2 = FALSE;
  3320.         m_pMISUSSite->QueryInterface(IID_IHXSite2, (void**) &pSite2);
  3321.         if (pSite2)
  3322.         {
  3323.             pSite2->GetVideoSurface(pVideoSurface);
  3324.         }
  3325. HX_RELEASE(pSite2);
  3326.         HX_ASSERT(pVideoSurface);
  3327.         if (pVideoSurface)
  3328.         {
  3329.             pVideoSurface->QueryInterface(IID_IHXVideoSurface2,
  3330.                                           (void**) &pVideoSurface2);
  3331.         }
  3332.         HX_RELEASE(pVideoSurface);
  3333.         if (pVideoSurface2)
  3334.         {
  3335.     HXBitmapInfoHeader userBIH;
  3336.     ULONG32 ulUserBufCount;
  3337.             IHXBuffer* pInitialCountBuffer = NULL;
  3338.     HX_RESULT status;
  3339.     m_ulHWBufCount = m_ulConfigHWBufCount;
  3340.     HX_RELEASE(pInitialCountBuffer);
  3341.     if (m_pVSurf2InputBIH == NULL)
  3342.     {
  3343. m_pVSurf2InputBIH = new HXBitmapInfoHeader;
  3344.     }
  3345.     retVal = HXR_OUTOFMEMORY;
  3346.     if (m_pVSurf2InputBIH)
  3347.     {
  3348. *m_pVSurf2InputBIH = m_BitmapInfoHeader;
  3349. m_pVSurf2InputBIH->biWidth = ulWidth;
  3350. m_pVSurf2InputBIH->biHeight = ulHeight;
  3351. retVal = HXR_OK;
  3352.     }
  3353.             if (SUCCEEDED(retVal))
  3354.     {
  3355. do
  3356. {
  3357.     // SetProperties should modify m_pVSurf2InputBIH
  3358.     status = pVideoSurface2->SetProperties(m_pVSurf2InputBIH,
  3359.    m_ulHWBufCount,
  3360.    (IHXRenderTimeLine*) this);
  3361.     /*** This code creates a leak - the renderer is not released
  3362.      *** Needs investigation.
  3363.     if (SUCCEEDED(status) && (m_ulHWBufCount > 0))
  3364.     {
  3365. UINT8* pVideoMem;
  3366. INT32 iPitch;
  3367. status = pVideoSurface2->GetVideoMem(pVideoMem,
  3368.      iPitch,
  3369.      HX_WAIT_FOREVER,
  3370.      m_pVSurf2InputBIH);
  3371. if (SUCCEEDED(status))
  3372. {
  3373.     pVideoSurface2->ReleaseVideoMem(pVideoMem);
  3374. }
  3375.     }
  3376.      ***/
  3377.     userBIH = *m_pVSurf2InputBIH;
  3378.     ulUserBufCount = m_ulHWBufCount;
  3379.     retVal = OnOptimizedVideo(status,
  3380.       m_BitmapInfoHeader,
  3381.       userBIH,
  3382.       ulUserBufCount);
  3383.     if (retVal == HXR_RETRY)
  3384.     {
  3385. *m_pVSurf2InputBIH = userBIH;
  3386. m_ulHWBufCount = ulUserBufCount;
  3387.     }
  3388. } while (retVal == HXR_RETRY);
  3389.     }
  3390.     if (SUCCEEDED(retVal) &&
  3391. SUCCEEDED(status) &&
  3392. (m_ulHWBufCount != 0))
  3393.     {
  3394. bTryVideoSurface2 = TRUE;
  3395.     }
  3396. }
  3397. if (bTryVideoSurface2)
  3398. {
  3399.     // Turning on video surface 2
  3400.     m_ulEarlyFrameTol = m_ulMaxOptimizedVideoLead;
  3401.     if (!m_bUseVideoSurface2)
  3402.     {
  3403. m_bVideoSurface2Transition = TRUE;
  3404. m_bUseVideoSurface2 = TRUE;
  3405. if (m_pBltrPump)
  3406. {
  3407.     // Wake up Bltr thread
  3408.     m_pBltrPump->Suspend(FALSE);
  3409.     m_pBltrPump->Signal();
  3410. }
  3411.     }
  3412. }
  3413. HX_RELEASE(pVideoSurface2);
  3414.     }
  3415.     if (FAILED(retVal))
  3416.     {
  3417. HX_DELETE(m_pVSurf2InputBIH);
  3418.     }
  3419.     m_bUseVideoSurface2 = bTryVideoSurface2;
  3420.     return retVal;
  3421. #else // HELIX_FEATURE_VIDREND_OPTIMIZEDVIDEO
  3422.     return HXR_NOTIMPL;
  3423. #endif // HELIX_FEATURE_VIDREND_OPTIMIZEDVIDEO
  3424. }
  3425. HX_RESULT CVideoRenderer::UpdateVideoSurface2(IHXVideoSurface* pVideoSurface,
  3426.       HXxRect &destRect,
  3427.       HXxRect &sorcRect,
  3428.       BOOL bRefresh,
  3429.       BOOL bSystemEvent)
  3430. {
  3431. #ifdef HELIX_FEATURE_VIDREND_OPTIMIZEDVIDEO
  3432.     VideoMemStruct videoMemoryInfo;
  3433.     IHXVideoSurface2* pVideoSurface2 = NULL;
  3434.     HX_RESULT retVal;
  3435.     HX_ASSERT(pVideoSurface);
  3436.     videoMemoryInfo.pVidMem = NULL;
  3437.     retVal = pVideoSurface->QueryInterface(IID_IHXVideoSurface2,
  3438.    (void**) &pVideoSurface2);
  3439.     if (!bRefresh)
  3440.     {
  3441. m_bPresentInProgress = TRUE;
  3442. // If we are in transition to video surface 2, we are not in
  3443. // natural Bltr thread, thus do not unlock the mutex to prevent
  3444. // other Blt entry points for interfering until the transition
  3445. // to natural queue thread is complete.
  3446. if (!m_bVideoSurface2Transition)
  3447. {
  3448.     DisplayMutex_Unlock();
  3449. }
  3450. if (SUCCEEDED(retVal))
  3451. {
  3452.     HX_ASSERT(m_bVideoSurface2Transition ? bSystemEvent : TRUE);
  3453.     retVal = pVideoSurface2->GetVideoMem(&videoMemoryInfo,
  3454.                                                  m_bVideoSurface2Transition ?
  3455.     HX_WAIT_NEVER : HX_WAIT_FOREVER);
  3456.     m_bVS2BufferUnavailableOnLastBlt = FAILED(retVal);
  3457. }
  3458. if (!m_bVideoSurface2Transition)
  3459. {
  3460.     DisplayMutex_Lock();
  3461.     // If the switch to VS1 occured after we successfully obtained video
  3462.     // memory, fail this VS2 Blt
  3463.     if ((!m_bUseVideoSurface2) && SUCCEEDED(retVal))
  3464.     {
  3465. retVal = HXR_FAIL;
  3466.     }
  3467. }
  3468. if (SUCCEEDED(retVal))
  3469. {
  3470.     retVal = TransferOptimizedVideo(pVideoSurface2,
  3471.                                             &videoMemoryInfo,
  3472.     m_pActiveVideoPacket,
  3473.     m_BitmapInfoHeader,
  3474.     sorcRect,
  3475.     sorcRect);
  3476. }
  3477. if (SUCCEEDED(retVal))
  3478. {
  3479.     if (m_bFirstSurfaceUpdate)
  3480.     {
  3481. m_bFirstSurfaceUpdate = FALSE;
  3482. if (bSystemEvent)
  3483. {
  3484.     retVal = pVideoSurface2->Present(&videoMemoryInfo,
  3485.      m_pActiveVideoPacket->m_ulTime,
  3486.      HX_MODE_IMMEDIATE,
  3487.      &destRect,
  3488.      &sorcRect);
  3489.     // We'll fail if the site is hidden by SMIL:
  3490.     if (FAILED(retVal))
  3491.     {
  3492. retVal = pVideoSurface2->Present(&videoMemoryInfo,
  3493.  m_pActiveVideoPacket->m_ulTime,
  3494.  HX_MODE_TIMED,
  3495.  &destRect,
  3496.  &sorcRect);
  3497.     }
  3498. }
  3499. else
  3500. {
  3501.     // Unless this is a system event we are not under the protection of the
  3502.     // top level site mutex and present immediate will acquire TLS mutex.
  3503.     // We must avoid deadlock with HandleEvent by relinquishing
  3504.     // VS mutex and forcing refresh.
  3505.     m_bPresentInProgress = FALSE;
  3506.     BOOL bIsVisible = ForceRefresh();
  3507.     // We'll fail if the site is not visible
  3508.     if (bIsVisible)
  3509.     {
  3510. // Abort any further updates for multiple site users since
  3511. // ForceRefresh will take care of all of them
  3512. retVal = HXR_ABORT;
  3513.     }
  3514.     else
  3515.     {
  3516. retVal = pVideoSurface2->Present(&videoMemoryInfo,
  3517.  m_pActiveVideoPacket->m_ulTime,
  3518.  HX_MODE_TIMED,
  3519.  &destRect,
  3520.  &sorcRect);
  3521.     }
  3522. }
  3523.     }
  3524.     else
  3525.     {
  3526. retVal = pVideoSurface2->Present(&videoMemoryInfo,
  3527.  m_pActiveVideoPacket->m_ulTime,
  3528.  HX_MODE_TIMED,
  3529.  &destRect,
  3530.  &sorcRect);
  3531.     }
  3532.     if (SUCCEEDED(retVal))
  3533.     {
  3534. videoMemoryInfo.pVidMem = NULL;
  3535.     }
  3536. }
  3537. m_bPresentInProgress = FALSE;
  3538.     }
  3539.     else if (!m_bPresentInProgress)
  3540.     {
  3541. HX_ASSERT(bSystemEvent);
  3542. retVal = pVideoSurface2->Present(NULL,
  3543.  0,
  3544.  HX_MODE_REFRESH,
  3545.  &destRect,
  3546.  &sorcRect);
  3547. // If no frames in video surface - make one and present it
  3548. if (FAILED(retVal) && bSystemEvent)
  3549. {
  3550.     retVal = pVideoSurface2->GetVideoMem(&videoMemoryInfo,
  3551.                                                  HX_WAIT_NEVER);
  3552.     if (SUCCEEDED(retVal))
  3553.     {
  3554. retVal = TransferOptimizedVideo(pVideoSurface2,
  3555.         &videoMemoryInfo,
  3556. m_pActiveVideoPacket,
  3557. m_BitmapInfoHeader,
  3558. sorcRect,
  3559. sorcRect);
  3560. if (SUCCEEDED(retVal))
  3561. {
  3562.     retVal = pVideoSurface2->Present(&videoMemoryInfo,
  3563.      m_pActiveVideoPacket->m_ulTime,
  3564.      HX_MODE_IMMEDIATE,
  3565.      &destRect,
  3566.      &sorcRect);
  3567.     if (FAILED(retVal))
  3568.     {
  3569. pVideoSurface2->ReleaseVideoMem(&videoMemoryInfo);
  3570. retVal = pVideoSurface2->Present(NULL,
  3571.  0,
  3572.  HX_MODE_REFRESH,
  3573.  &destRect,
  3574.  &sorcRect);
  3575.     }
  3576.     videoMemoryInfo.pVidMem = NULL;
  3577. }
  3578.     }
  3579.     else
  3580.     {
  3581. retVal = pVideoSurface2->Present(NULL,
  3582.  0,
  3583.  HX_MODE_REFRESH,
  3584.  &destRect,
  3585.  &sorcRect);
  3586.     }
  3587. }
  3588.     }
  3589.     if (videoMemoryInfo.pVidMem != NULL)
  3590.     {
  3591. pVideoSurface2->ReleaseVideoMem(&videoMemoryInfo);
  3592.     }
  3593.     HX_RELEASE(pVideoSurface2);
  3594.     return retVal;
  3595. #else // HELIX_FEATURE_VIDREND_OPTIMIZEDVIDEO
  3596.     return HXR_NOTIMPL;
  3597. #endif // HELIX_FEATURE_VIDREND_OPTIMIZEDVIDEO
  3598. }
  3599. HX_RESULT CVideoRenderer::FlushVideoSurface2(IHXSite* pSite)
  3600. {
  3601. #ifdef HELIX_FEATURE_VIDREND_OPTIMIZEDVIDEO
  3602.     HX_RESULT retVal = HXR_FAIL;
  3603.     IHXVideoSurface* pVideoSurface;
  3604.     IHXVideoSurface2* pVideoSurface2;
  3605.     IHXSite2* pSite2;
  3606.     HX_ASSERT(pSite);
  3607.     if (SUCCEEDED(pSite->QueryInterface(IID_IHXSite2, (void**) &pSite2)))
  3608.     {
  3609. if (SUCCEEDED(pSite2->GetVideoSurface(pVideoSurface)))
  3610. {
  3611.     if (SUCCEEDED(pVideoSurface->QueryInterface(IID_IHXVideoSurface2,
  3612. (void**) &pVideoSurface2)))
  3613.     {
  3614. pVideoSurface2->Flush();
  3615. pVideoSurface2->Release();
  3616. retVal = HXR_OK;
  3617.     }
  3618.     pVideoSurface->Release();
  3619. }
  3620. pSite2->Release();
  3621.     }
  3622.     HX_ASSERT(SUCCEEDED(retVal));
  3623.     return retVal;
  3624. #else // HELIX_FEATURE_VIDREND_OPTIMIZEDVIDEO
  3625.     return HXR_NOTIMPL;
  3626. #endif // HELIX_FEATURE_VIDREND_OPTIMIZEDVIDEO
  3627. }
  3628. inline HX_RESULT CVideoRenderer::SwitchToVideoSurface1(void)
  3629. {
  3630. #ifdef HELIX_FEATURE_VIDREND_OPTIMIZEDVIDEO
  3631.     HX_RESULT retVal = HXR_OK;
  3632.     m_pVSMutex->Lock();
  3633.     m_bVideoSurface1Requested = TRUE;
  3634.     if (m_bUseVideoSurface2)
  3635.     {
  3636. HX_TRACE_THINGY("C:/trace.txt", "-->Switch to VS1", 0);
  3637. #ifdef SYNC_VS_SWITCHING
  3638. InitVideoSurface1(TRUE);
  3639. StartSchedulers();
  3640. #else // SYNC_VS_SWITCHING
  3641. // Force Video Surface reinitialization
  3642. m_bVideoSurfaceReinitRequested = TRUE;
  3643. #endif // SYNC_VS_SWITCHING
  3644.     }
  3645.     m_pVSMutex->Unlock();
  3646.     return retVal;
  3647. #else // HELIX_FEATURE_VIDREND_OPTIMIZEDVIDEO
  3648.     return HXR_NOTIMPL;
  3649. #endif // HELIX_FEATURE_VIDREND_OPTIMIZEDVIDEO
  3650. }
  3651. inline HX_RESULT CVideoRenderer::SwitchToVideoSurface2(void)
  3652. {
  3653. #ifdef HELIX_FEATURE_VIDREND_OPTIMIZEDVIDEO
  3654.     HX_RESULT retVal = HXR_OK;
  3655.     m_pVSMutex->Lock();
  3656.     m_bVideoSurface1Requested = FALSE;
  3657.     if (!m_bUseVideoSurface2)
  3658.     {
  3659. if (m_bTryVideoSurface2)
  3660. {
  3661.     HX_TRACE_THINGY("C:/trace.txt", "-->Switch to VS2", 0);
  3662. #ifdef SYNC_VS_SWITCHING
  3663.     InitVideoSurface2(m_SetWinSize.cx, m_SetWinSize.cy);
  3664.     StartSchedulers();
  3665. #else // SYNC_VS_SWITCHING
  3666.     // Force Video Surface reinitialization
  3667.     m_bVideoSurfaceReinitRequested = TRUE;
  3668. #endif // SYNC_VS_SWITCHING
  3669. }
  3670. else
  3671. {
  3672.     // VideoSurface2 is not allowed
  3673.     HX_TRACE_THINGY("C:/trace.txt", "-->Switch to VS2 Denied!", 0);
  3674.     retVal = HXR_FAIL;
  3675. }
  3676.     }
  3677.     m_pVSMutex->Unlock();
  3678.     return retVal;
  3679. #else // HELIX_FEATURE_VIDREND_OPTIMIZEDVIDEO
  3680.     return HXR_NOTIMPL;
  3681. #endif // HELIX_FEATURE_VIDREND_OPTIMIZEDVIDEO
  3682. }
  3683. /****************************************************************************
  3684.  *  Method:
  3685.  *    CVideoFormat::OnOptimizedVideo
  3686.  *
  3687.  */
  3688. HX_RESULT CVideoRenderer::OnOptimizedVideo(HX_RESULT status,
  3689.    const HXBitmapInfoHeader& sourceBIH,
  3690.    HXBitmapInfoHeader &targetBIH,
  3691.    ULONG32 &ulTargetBufCount)
  3692. {
  3693. #ifdef HELIX_FEATURE_VIDREND_OPTIMIZEDVIDEO
  3694.     HX_RESULT retVal = HXR_FAIL;
  3695.     if (SUCCEEDED(status) &&
  3696. (ulTargetBufCount > 0) &&
  3697. (GETBITMAPCOLOR(&sourceBIH) == CID_I420))
  3698.     {
  3699.         retVal = HXR_OK;
  3700.     }
  3701.     return retVal;
  3702. #else // HELIX_FEATURE_VIDREND_OPTIMIZEDVIDEO
  3703.     return HXR_NOTIMPL;
  3704. #endif // HELIX_FEATURE_VIDREND_OPTIMIZEDVIDEO
  3705. }
  3706. /****************************************************************************
  3707.  *  Method:
  3708.  *    CVideoFormat::OffOptimizedVideo
  3709.  *
  3710.  */
  3711. void CVideoRenderer::OffOptimizedVideo(void)
  3712. {
  3713.     return;
  3714. }
  3715. /****************************************************************************
  3716.  *  Method:
  3717.  *    CVideoFormat::TransferOptimizedVideo
  3718.  *
  3719.  */
  3720. HX_RESULT CVideoRenderer::TransferOptimizedVideo(IHXVideoSurface2* pVideoSurface2,
  3721.                                                  VideoMemStruct* pVideoMemoryInfo,
  3722.                                                  CMediaPacket* pVideoPacket,
  3723.                                                  const HXBitmapInfoHeader& sorcBIH,
  3724.                                                  HXxRect &destRect,
  3725.                                                  HXxRect &sorcRect)
  3726. {
  3727. #ifdef HELIX_FEATURE_VIDREND_OPTIMIZEDVIDEO
  3728.     SourceInputStruct input;
  3729.     UINT8* aSrcInput[3];
  3730.     INT32 aSrcPitch[3];
  3731.     HX_RESULT retVal = HXR_FAIL;
  3732.     input.aSrcInput = aSrcInput;
  3733.     input.aSrcPitch = aSrcPitch;
  3734.     input.nNumInputs = 3;
  3735.     if (GETBITMAPCOLOR(&sorcBIH) == CID_I420)
  3736.     {
  3737. aSrcInput[0] = pVideoPacket->m_pData;
  3738. aSrcInput[1] = aSrcInput[0] + (sorcBIH.biWidth * sorcBIH.biHeight);
  3739. aSrcInput[2] = aSrcInput[1] +
  3740.        ((sorcBIH.biWidth / 2) * (sorcBIH.biHeight / 2));
  3741. aSrcPitch[0] = sorcBIH.biWidth;
  3742. aSrcPitch[1] = sorcBIH.biWidth / 2;
  3743. aSrcPitch[2] = sorcBIH.biWidth / 2;
  3744.         CHXxSize sorcSize(sorcBIH.biWidth, sorcBIH.biHeight);
  3745.         retVal = pVideoSurface2->ColorConvert(HX_I420,
  3746.                                               &sorcSize,
  3747.                                               &sorcRect,
  3748.                                               &input,
  3749.                                               pVideoMemoryInfo->bmi.biCompression,
  3750.                                               pVideoMemoryInfo->pVidMem,
  3751.                                               &CHXxSize(pVideoMemoryInfo->bmi.biWidth,
  3752.                                                         pVideoMemoryInfo->bmi.biHeight),
  3753.                                               &destRect,
  3754.                                               pVideoMemoryInfo->lPitch);
  3755.         // Alpha blend subrects:
  3756.         for (UINT32 i = 0; i < pVideoMemoryInfo->ulCount; ++i)
  3757.         {
  3758.             HX_RESULT localResult = pVideoSurface2->ColorConvert(
  3759.                              HX_I420,
  3760.                              &sorcSize,
  3761.                              &pVideoMemoryInfo->pAlphaList[i].rcImageRect,
  3762.                              &input,
  3763.                              pVideoMemoryInfo->pAlphaList[i].ulFourCC,
  3764.                              pVideoMemoryInfo->pAlphaList[i].pBuffer,
  3765.                              &CHXxSize(pVideoMemoryInfo->pAlphaList[i].ulImageWidth,
  3766.                                        pVideoMemoryInfo->pAlphaList[i].ulImageHeight),
  3767.                              &pVideoMemoryInfo->pAlphaList[i].rcImageRect,
  3768.                              pVideoMemoryInfo->pAlphaList[i].lPitch);
  3769.             if (SUCCEEDED(retVal))
  3770.             {
  3771.                 retVal = localResult;
  3772.             }
  3773.         }
  3774.     }
  3775.     return retVal;
  3776. #else // HELIX_FEATURE_VIDREND_OPTIMIZEDVIDEO
  3777.     return HXR_NOTIMPL;
  3778. #endif // HELIX_FEATURE_VIDREND_OPTIMIZEDVIDEO
  3779. }
  3780. void CVideoRenderer::PresentFrame(void)
  3781. {
  3782. #ifdef HELIX_FEATURE_VIDREND_OPTIMIZEDVIDEO
  3783.     if (m_bUseVideoSurface2)
  3784.     {
  3785. SchedulerCallback(FALSE,    // not scheduled
  3786.   FALSE,    // do not resched
  3787.   TRUE);    // is VS2 call
  3788.     }
  3789.     else
  3790.     {
  3791. // Video Surface2 has been turned off
  3792. IHXPaceMaker* pBltr = m_pBltrPump;
  3793. if (pBltr)
  3794. {
  3795.     if (m_bTryVideoSurface2)
  3796.     {
  3797. // We might try VideoSurface2 again later - suspend the
  3798. // Bltr thread for now
  3799. pBltr->Suspend(TRUE);
  3800.     }
  3801.     else
  3802.     {
  3803. // We are not to try VideoSurface2 any more - stop the
  3804. // Bltr thread
  3805. pBltr->Stop();
  3806. pBltr->Signal();
  3807.     }
  3808. }
  3809.     }
  3810. #else // HELIX_FEATURE_VIDREND_OPTIMIZEDVIDEO
  3811.     ;
  3812. #endif // HELIX_FEATURE_VIDREND_OPTIMIZEDVIDEO
  3813. }