renbase.h 21 KB

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