Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

483 lines
20 KiB

  1. //------------------------------------------------------------------------------
  2. // File: RenBase.h
  3. //
  4. // Desc: DirectShow base classes - defines a generic ActiveX base renderer
  5. // class.
  6. //
  7. //@@BEGIN_MSINTERNAL
  8. //
  9. // December 1995
  10. //
  11. //@@END_MSINTERNAL
  12. // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
  13. //------------------------------------------------------------------------------
  14. #ifndef __RENBASE__
  15. #define __RENBASE__
  16. // Forward class declarations
  17. class CBaseRenderer;
  18. class CBaseVideoRenderer;
  19. class CRendererInputPin;
  20. // This is our input pin class that channels calls to the renderer
  21. class CRendererInputPin : public CBaseInputPin
  22. {
  23. protected:
  24. CBaseRenderer *m_pRenderer;
  25. public:
  26. CRendererInputPin(CBaseRenderer *pRenderer,
  27. HRESULT *phr,
  28. LPCWSTR Name);
  29. // Overriden from the base pin classes
  30. HRESULT BreakConnect();
  31. HRESULT CompleteConnect(IPin *pReceivePin);
  32. HRESULT SetMediaType(const CMediaType *pmt);
  33. HRESULT CheckMediaType(const CMediaType *pmt);
  34. HRESULT Active();
  35. HRESULT Inactive();
  36. // Add rendering behaviour to interface functions
  37. STDMETHODIMP QueryId(LPWSTR *Id);
  38. STDMETHODIMP EndOfStream();
  39. STDMETHODIMP BeginFlush();
  40. STDMETHODIMP EndFlush();
  41. STDMETHODIMP Receive(IMediaSample *pMediaSample);
  42. // Helper
  43. IMemAllocator inline *Allocator() const
  44. {
  45. return m_pAllocator;
  46. }
  47. };
  48. // Main renderer class that handles synchronisation and state changes
  49. class CBaseRenderer : public CBaseFilter
  50. {
  51. protected:
  52. friend class CRendererInputPin;
  53. friend void CALLBACK EndOfStreamTimer(UINT uID, // Timer identifier
  54. UINT uMsg, // Not currently used
  55. DWORD_PTR dwUser, // User information
  56. DWORD_PTR dw1, // Windows reserved
  57. DWORD_PTR dw2); // Is also reserved
  58. CRendererPosPassThru *m_pPosition; // Media seeking pass by object
  59. CAMEvent m_RenderEvent; // Used to signal timer events
  60. CAMEvent m_ThreadSignal; // Signalled to release worker thread
  61. CAMEvent m_evComplete; // Signalled when state complete
  62. BOOL m_bAbort; // Stop us from rendering more data
  63. BOOL m_bStreaming; // Are we currently streaming
  64. DWORD_PTR m_dwAdvise; // Timer advise cookie
  65. IMediaSample *m_pMediaSample; // Current image media sample
  66. BOOL m_bEOS; // Any more samples in the stream
  67. BOOL m_bEOSDelivered; // Have we delivered an EC_COMPLETE
  68. CRendererInputPin *m_pInputPin; // Our renderer input pin object
  69. CCritSec m_InterfaceLock; // Critical section for interfaces
  70. CCritSec m_RendererLock; // Controls access to internals
  71. IQualityControl * m_pQSink; // QualityControl sink
  72. BOOL m_bRepaintStatus; // Can we signal an EC_REPAINT
  73. // Avoid some deadlocks by tracking filter during stop
  74. volatile BOOL m_bInReceive; // Inside Receive between PrepareReceive
  75. // And actually processing the sample
  76. REFERENCE_TIME m_SignalTime; // Time when we signal EC_COMPLETE
  77. UINT m_EndOfStreamTimer; // Used to signal end of stream
  78. CCritSec m_ObjectCreationLock; // This lock protects the creation and
  79. // of m_pPosition and m_pInputPin. It
  80. // ensures that two threads cannot create
  81. // either object simultaneously.
  82. public:
  83. CBaseRenderer(REFCLSID RenderClass, // CLSID for this renderer
  84. TCHAR *pName, // Debug ONLY description
  85. LPUNKNOWN pUnk, // Aggregated owner object
  86. HRESULT *phr); // General OLE return code
  87. ~CBaseRenderer();
  88. // Overriden to say what interfaces we support and where
  89. virtual HRESULT GetMediaPositionInterface(REFIID riid,void **ppv);
  90. STDMETHODIMP NonDelegatingQueryInterface(REFIID, void **);
  91. virtual HRESULT SourceThreadCanWait(BOOL bCanWait);
  92. #ifdef DEBUG
  93. // Debug only dump of the renderer state
  94. void DisplayRendererState();
  95. #endif
  96. virtual HRESULT WaitForRenderTime();
  97. virtual HRESULT CompleteStateChange(FILTER_STATE OldState);
  98. // Return internal information about this filter
  99. BOOL IsEndOfStream() { return m_bEOS; };
  100. BOOL IsEndOfStreamDelivered() { return m_bEOSDelivered; };
  101. BOOL IsStreaming() { return m_bStreaming; };
  102. void SetAbortSignal(BOOL bAbort) { m_bAbort = bAbort; };
  103. virtual void OnReceiveFirstSample(IMediaSample *pMediaSample) { };
  104. CAMEvent *GetRenderEvent() { return &m_RenderEvent; };
  105. // Permit access to the transition state
  106. void Ready() { m_evComplete.Set(); };
  107. void NotReady() { m_evComplete.Reset(); };
  108. BOOL CheckReady() { return m_evComplete.Check(); };
  109. virtual int GetPinCount();
  110. virtual CBasePin *GetPin(int n);
  111. FILTER_STATE GetRealState();
  112. void SendRepaint();
  113. void SendNotifyWindow(IPin *pPin,HWND hwnd);
  114. BOOL OnDisplayChange();
  115. void SetRepaintStatus(BOOL bRepaint);
  116. // Override the filter and pin interface functions
  117. STDMETHODIMP Stop();
  118. STDMETHODIMP Pause();
  119. STDMETHODIMP Run(REFERENCE_TIME StartTime);
  120. STDMETHODIMP GetState(DWORD dwMSecs,FILTER_STATE *State);
  121. STDMETHODIMP FindPin(LPCWSTR Id, IPin **ppPin);
  122. // These are available for a quality management implementation
  123. virtual void OnRenderStart(IMediaSample *pMediaSample);
  124. virtual void OnRenderEnd(IMediaSample *pMediaSample);
  125. virtual HRESULT OnStartStreaming() { return NOERROR; };
  126. virtual HRESULT OnStopStreaming() { return NOERROR; };
  127. virtual void OnWaitStart() { };
  128. virtual void OnWaitEnd() { };
  129. virtual void PrepareRender() { };
  130. #ifdef PERF
  131. REFERENCE_TIME m_trRenderStart; // Just before we started drawing
  132. // Set in OnRenderStart, Used in OnRenderEnd
  133. int m_idBaseStamp; // MSR_id for frame time stamp
  134. int m_idBaseRenderTime; // MSR_id for true wait time
  135. int m_idBaseAccuracy; // MSR_id for time frame is late (int)
  136. #endif
  137. // Quality management implementation for scheduling rendering
  138. virtual BOOL ScheduleSample(IMediaSample *pMediaSample);
  139. virtual HRESULT GetSampleTimes(IMediaSample *pMediaSample,
  140. REFERENCE_TIME *pStartTime,
  141. REFERENCE_TIME *pEndTime);
  142. virtual HRESULT ShouldDrawSampleNow(IMediaSample *pMediaSample,
  143. REFERENCE_TIME *ptrStart,
  144. REFERENCE_TIME *ptrEnd);
  145. // Lots of end of stream complexities
  146. void TimerCallback();
  147. void ResetEndOfStreamTimer();
  148. HRESULT NotifyEndOfStream();
  149. virtual HRESULT SendEndOfStream();
  150. virtual HRESULT ResetEndOfStream();
  151. virtual HRESULT EndOfStream();
  152. // Rendering is based around the clock
  153. void SignalTimerFired();
  154. virtual HRESULT CancelNotification();
  155. virtual HRESULT ClearPendingSample();
  156. // Called when the filter changes state
  157. virtual HRESULT Active();
  158. virtual HRESULT Inactive();
  159. virtual HRESULT StartStreaming();
  160. virtual HRESULT StopStreaming();
  161. virtual HRESULT BeginFlush();
  162. virtual HRESULT EndFlush();
  163. // Deal with connections and type changes
  164. virtual HRESULT BreakConnect();
  165. virtual HRESULT SetMediaType(const CMediaType *pmt);
  166. virtual HRESULT CompleteConnect(IPin *pReceivePin);
  167. // These look after the handling of data samples
  168. virtual HRESULT PrepareReceive(IMediaSample *pMediaSample);
  169. virtual HRESULT Receive(IMediaSample *pMediaSample);
  170. virtual BOOL HaveCurrentSample();
  171. virtual IMediaSample *GetCurrentSample();
  172. virtual HRESULT Render(IMediaSample *pMediaSample);
  173. // Derived classes MUST override these
  174. virtual HRESULT DoRenderSample(IMediaSample *pMediaSample) PURE;
  175. virtual HRESULT CheckMediaType(const CMediaType *) PURE;
  176. // Helper
  177. void WaitForReceiveToComplete();
  178. };
  179. // CBaseVideoRenderer is a renderer class (see its ancestor class) and
  180. // it handles scheduling of media samples so that they are drawn at the
  181. // correct time by the reference clock. It implements a degradation
  182. // strategy. Possible degradation modes are:
  183. // Drop frames here (only useful if the drawing takes significant time)
  184. // Signal supplier (upstream) to drop some frame(s) - i.e. one-off skip.
  185. // Signal supplier to change the frame rate - i.e. ongoing skipping.
  186. // Or any combination of the above.
  187. // In order to determine what's useful to try we need to know what's going
  188. // on. This is done by timing various operations (including the supplier).
  189. // This timing is done by using timeGetTime as it is accurate enough and
  190. // usually cheaper than calling the reference clock. It also tells the
  191. // truth if there is an audio break and the reference clock stops.
  192. // We provide a number of public entry points (named OnXxxStart, OnXxxEnd)
  193. // which the rest of the renderer calls at significant moments. These do
  194. // the timing.
  195. // the number of frames that the sliding averages are averaged over.
  196. // the rule is (1024*NewObservation + (AVGPERIOD-1) * PreviousAverage)/AVGPERIOD
  197. #define AVGPERIOD 4
  198. #define DO_MOVING_AVG(avg,obs) (avg = (1024*obs + (AVGPERIOD-1)*avg)/AVGPERIOD)
  199. // Spot the bug in this macro - I can't. but it doesn't work!
  200. class CBaseVideoRenderer : public CBaseRenderer, // Base renderer class
  201. public IQualProp, // Property page guff
  202. public IQualityControl // Allow throttling
  203. {
  204. protected:
  205. // Hungarian:
  206. // tFoo is the time Foo in mSec (beware m_tStart from filter.h)
  207. // trBar is the time Bar by the reference clock
  208. //******************************************************************
  209. // State variables to control synchronisation
  210. //******************************************************************
  211. // Control of sending Quality messages. We need to know whether
  212. // we are in trouble (e.g. frames being dropped) and where the time
  213. // is being spent.
  214. // When we drop a frame we play the next one early.
  215. // The frame after that is likely to wait before drawing and counting this
  216. // wait as spare time is unfair, so we count it as a zero wait.
  217. // We therefore need to know whether we are playing frames early or not.
  218. int m_nNormal; // The number of consecutive frames
  219. // drawn at their normal time (not early)
  220. // -1 means we just dropped a frame.
  221. #ifdef PERF
  222. BOOL m_bDrawLateFrames; // Don't drop any frames (debug and I'm
  223. // not keen on people using it!)
  224. #endif
  225. BOOL m_bSupplierHandlingQuality;// The response to Quality messages says
  226. // our supplier is handling things.
  227. // We will allow things to go extra late
  228. // before dropping frames. We will play
  229. // very early after he has dropped one.
  230. // Control of scheduling, frame dropping etc.
  231. // We need to know where the time is being spent so as to tell whether
  232. // we should be taking action here, signalling supplier or what.
  233. // The variables are initialised to a mode of NOT dropping frames.
  234. // They will tell the truth after a few frames.
  235. // We typically record a start time for an event, later we get the time
  236. // again and subtract to get the elapsed time, and we average this over
  237. // a few frames. The average is used to tell what mode we are in.
  238. // Although these are reference times (64 bit) they are all DIFFERENCES
  239. // between times which are small. An int will go up to 214 secs before
  240. // overflow. Avoiding 64 bit multiplications and divisions seems
  241. // worth while.
  242. // Audio-video throttling. If the user has turned up audio quality
  243. // very high (in principle it could be any other stream, not just audio)
  244. // then we can receive cries for help via the graph manager. In this case
  245. // we put in a wait for some time after rendering each frame.
  246. int m_trThrottle;
  247. // The time taken to render (i.e. BitBlt) frames controls which component
  248. // needs to degrade. If the blt is expensive, the renderer degrades.
  249. // If the blt is cheap it's done anyway and the supplier degrades.
  250. int m_trRenderAvg; // Time frames are taking to blt
  251. int m_trRenderLast; // Time for last frame blt
  252. int m_tRenderStart; // Just before we started drawing (mSec)
  253. // derived from timeGetTime.
  254. // When frames are dropped we will play the next frame as early as we can.
  255. // If it was a false alarm and the machine is fast we slide gently back to
  256. // normal timing. To do this, we record the offset showing just how early
  257. // we really are. This will normally be negative meaning early or zero.
  258. int m_trEarliness;
  259. // Target provides slow long-term feedback to try to reduce the
  260. // average sync offset to zero. Whenever a frame is actually rendered
  261. // early we add a msec or two, whenever late we take off a few.
  262. // We add or take off 1/32 of the error time.
  263. // Eventually we should be hovering around zero. For a really bad case
  264. // where we were (say) 300mSec off, it might take 100 odd frames to
  265. // settle down. The rate of change of this is intended to be slower
  266. // than any other mechanism in Quartz, thereby avoiding hunting.
  267. int m_trTarget;
  268. // The proportion of time spent waiting for the right moment to blt
  269. // controls whether we bother to drop a frame or whether we reckon that
  270. // we're doing well enough that we can stand a one-frame glitch.
  271. int m_trWaitAvg; // Average of last few wait times
  272. // (actually we just average how early
  273. // we were). Negative here means LATE.
  274. // The average inter-frame time.
  275. // This is used to calculate the proportion of the time used by the
  276. // three operations (supplying us, waiting, rendering)
  277. int m_trFrameAvg; // Average inter-frame time
  278. int m_trDuration; // duration of last frame.
  279. #ifdef PERF
  280. // Performance logging identifiers
  281. int m_idTimeStamp; // MSR_id for frame time stamp
  282. int m_idEarliness; // MSR_id for earliness fudge
  283. int m_idTarget; // MSR_id for Target fudge
  284. int m_idWaitReal; // MSR_id for true wait time
  285. int m_idWait; // MSR_id for wait time recorded
  286. int m_idFrameAccuracy; // MSR_id for time frame is late (int)
  287. int m_idRenderAvg; // MSR_id for Render time recorded (int)
  288. int m_idSchLateTime; // MSR_id for lateness at scheduler
  289. int m_idQualityRate; // MSR_id for Quality rate requested
  290. int m_idQualityTime; // MSR_id for Quality time requested
  291. int m_idDecision; // MSR_id for decision code
  292. int m_idDuration; // MSR_id for duration of a frame
  293. int m_idThrottle; // MSR_id for audio-video throttling
  294. //int m_idDebug; // MSR_id for trace style debugging
  295. //int m_idSendQuality; // MSR_id for timing the notifications per se
  296. #endif // PERF
  297. REFERENCE_TIME m_trRememberStampForPerf; // original time stamp of frame
  298. // with no earliness fudges etc.
  299. #ifdef PERF
  300. REFERENCE_TIME m_trRememberFrameForPerf; // time when previous frame rendered
  301. // debug...
  302. int m_idFrameAvg;
  303. int m_idWaitAvg;
  304. #endif
  305. // PROPERTY PAGE
  306. // This has edit fields that show the user what's happening
  307. // These member variables hold these counts.
  308. int m_cFramesDropped; // cumulative frames dropped IN THE RENDERER
  309. int m_cFramesDrawn; // Frames since streaming started seen BY THE
  310. // RENDERER (some may be dropped upstream)
  311. // Next two support average sync offset and standard deviation of sync offset.
  312. LONGLONG m_iTotAcc; // Sum of accuracies in mSec
  313. LONGLONG m_iSumSqAcc; // Sum of squares of (accuracies in mSec)
  314. // Next two allow jitter calculation. Jitter is std deviation of frame time.
  315. REFERENCE_TIME m_trLastDraw; // Time of prev frame (for inter-frame times)
  316. LONGLONG m_iSumSqFrameTime; // Sum of squares of (inter-frame time in mSec)
  317. LONGLONG m_iSumFrameTime; // Sum of inter-frame times in mSec
  318. // To get performance statistics on frame rate, jitter etc, we need
  319. // to record the lateness and inter-frame time. What we actually need are the
  320. // data above (sum, sum of squares and number of entries for each) but the data
  321. // is generated just ahead of time and only later do we discover whether the
  322. // frame was actually drawn or not. So we have to hang on to the data
  323. int m_trLate; // hold onto frame lateness
  324. int m_trFrame; // hold onto inter-frame time
  325. int m_tStreamingStart; // if streaming then time streaming started
  326. // else time of last streaming session
  327. // used for property page statistics
  328. #ifdef PERF
  329. LONGLONG m_llTimeOffset; // timeGetTime()*10000+m_llTimeOffset==ref time
  330. #endif
  331. public:
  332. CBaseVideoRenderer(REFCLSID RenderClass, // CLSID for this renderer
  333. TCHAR *pName, // Debug ONLY description
  334. LPUNKNOWN pUnk, // Aggregated owner object
  335. HRESULT *phr); // General OLE return code
  336. ~CBaseVideoRenderer();
  337. // IQualityControl methods - Notify allows audio-video throttling
  338. STDMETHODIMP SetSink( IQualityControl * piqc);
  339. STDMETHODIMP Notify( IBaseFilter * pSelf, Quality q);
  340. // These provide a full video quality management implementation
  341. void OnRenderStart(IMediaSample *pMediaSample);
  342. void OnRenderEnd(IMediaSample *pMediaSample);
  343. void OnWaitStart();
  344. void OnWaitEnd();
  345. HRESULT OnStartStreaming();
  346. HRESULT OnStopStreaming();
  347. void ThrottleWait();
  348. // Handle the statistics gathering for our quality management
  349. void PreparePerformanceData(int trLate, int trFrame);
  350. virtual void RecordFrameLateness(int trLate, int trFrame);
  351. virtual void OnDirectRender(IMediaSample *pMediaSample);
  352. virtual HRESULT ResetStreamingTimes();
  353. BOOL ScheduleSample(IMediaSample *pMediaSample);
  354. HRESULT ShouldDrawSampleNow(IMediaSample *pMediaSample,
  355. REFERENCE_TIME *ptrStart,
  356. REFERENCE_TIME *ptrEnd);
  357. virtual HRESULT SendQuality(REFERENCE_TIME trLate, REFERENCE_TIME trRealStream);
  358. STDMETHODIMP JoinFilterGraph(IFilterGraph * pGraph, LPCWSTR pName);
  359. //
  360. // Do estimates for standard deviations for per-frame
  361. // statistics
  362. //
  363. // *piResult = (llSumSq - iTot * iTot / m_cFramesDrawn - 1) /
  364. // (m_cFramesDrawn - 2)
  365. // or 0 if m_cFramesDrawn <= 3
  366. //
  367. HRESULT GetStdDev(
  368. int nSamples,
  369. int *piResult,
  370. LONGLONG llSumSq,
  371. LONGLONG iTot
  372. );
  373. public:
  374. // IQualProp property page support
  375. STDMETHODIMP get_FramesDroppedInRenderer(int *cFramesDropped);
  376. STDMETHODIMP get_FramesDrawn(int *pcFramesDrawn);
  377. STDMETHODIMP get_AvgFrameRate(int *piAvgFrameRate);
  378. STDMETHODIMP get_Jitter(int *piJitter);
  379. STDMETHODIMP get_AvgSyncOffset(int *piAvg);
  380. STDMETHODIMP get_DevSyncOffset(int *piDev);
  381. // Implement an IUnknown interface and expose IQualProp
  382. DECLARE_IUNKNOWN
  383. STDMETHODIMP NonDelegatingQueryInterface(REFIID riid,VOID **ppv);
  384. };
  385. #endif // __RENBASE__