renbase.h 20 KB

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