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

Symbian

开发平台:

Visual C++

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