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