renbase.h
上传用户:liguizhu
上传日期:2015-11-01
资源大小:2422k
文件大小:20k
源码类别:

P2P编程

开发平台:

Visual C++

  1. //------------------------------------------------------------------------------
  2. // File: RenBase.h
  3. //
  4. // Desc: DirectShow base classes - defines a generic ActiveX base renderer
  5. //       class.
  6. //
  7. // Copyright (c) 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(CBaseRenderer *pRenderer,
  22.                       HRESULT *phr,
  23.                       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(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.                   TCHAR *pName,         // Debug ONLY description
  80.                   LPUNKNOWN pUnk,       // Aggregated owner object
  81.                   HRESULT *phr);        // General OLE return code
  82.     ~CBaseRenderer();
  83.     // Overriden to say what interfaces we support and where
  84.     virtual HRESULT GetMediaPositionInterface(REFIID riid,void **ppv);
  85.     STDMETHODIMP NonDelegatingQueryInterface(REFIID, 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,FILTER_STATE *State);
  116.     STDMETHODIMP FindPin(LPCWSTR Id, 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.                                    REFERENCE_TIME *pStartTime,
  136.                                    REFERENCE_TIME *pEndTime);
  137.     virtual HRESULT ShouldDrawSampleNow(IMediaSample *pMediaSample,
  138.                                         REFERENCE_TIME *ptrStart,
  139.                                         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.                        TCHAR *pName,         // Debug ONLY description
  329.                        LPUNKNOWN pUnk,       // Aggregated owner object
  330.                        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.                                 REFERENCE_TIME *ptrStart,
  351.                                 REFERENCE_TIME *ptrEnd);
  352.     virtual HRESULT SendQuality(REFERENCE_TIME trLate, REFERENCE_TIME trRealStream);
  353.     STDMETHODIMP JoinFilterGraph(IFilterGraph * pGraph, 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.         int *piResult,
  365.         LONGLONG llSumSq,
  366.         LONGLONG iTot
  367.     );
  368. public:
  369.     // IQualProp property page support
  370.     STDMETHODIMP get_FramesDroppedInRenderer(int *cFramesDropped);
  371.     STDMETHODIMP get_FramesDrawn(int *pcFramesDrawn);
  372.     STDMETHODIMP get_AvgFrameRate(int *piAvgFrameRate);
  373.     STDMETHODIMP get_Jitter(int *piJitter);
  374.     STDMETHODIMP get_AvgSyncOffset(int *piAvg);
  375.     STDMETHODIMP get_DevSyncOffset(int *piDev);
  376.     // Implement an IUnknown interface and expose IQualProp
  377.     DECLARE_IUNKNOWN
  378.     STDMETHODIMP NonDelegatingQueryInterface(REFIID riid,VOID **ppv);
  379. };
  380. #endif // __RENBASE__