144 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			144 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|  | //------------------------------------------------------------------------------
 | ||
|  | // File: VTrans.h
 | ||
|  | //
 | ||
|  | // Desc: DirectShow base classes - defines a video transform class.
 | ||
|  | //
 | ||
|  | // Copyright (c) 1992-2001 Microsoft Corporation.  All rights reserved.
 | ||
|  | //------------------------------------------------------------------------------
 | ||
|  | 
 | ||
|  | 
 | ||
|  | // This class is derived from CTransformFilter, but is specialised to handle
 | ||
|  | // the requirements of video quality control by frame dropping.
 | ||
|  | // This is a non-in-place transform, (i.e. it copies the data) such as a decoder.
 | ||
|  | 
 | ||
|  | class CVideoTransformFilter : public CTransformFilter | ||
|  | { | ||
|  |   public: | ||
|  | 
 | ||
|  |     CVideoTransformFilter(__in_opt LPCTSTR, __inout_opt LPUNKNOWN, REFCLSID clsid); | ||
|  |     ~CVideoTransformFilter(); | ||
|  |     HRESULT EndFlush(); | ||
|  | 
 | ||
|  |     // =================================================================
 | ||
|  |     // ----- override these bits ---------------------------------------
 | ||
|  |     // =================================================================
 | ||
|  |     // The following methods are in CTransformFilter which is inherited.
 | ||
|  |     // They are mentioned here for completeness
 | ||
|  |     //
 | ||
|  |     // These MUST be supplied in a derived class
 | ||
|  |     //
 | ||
|  |     // NOTE:
 | ||
|  |     // virtual HRESULT Transform(IMediaSample * pIn, IMediaSample *pOut);
 | ||
|  |     // virtual HRESULT CheckInputType(const CMediaType* mtIn) PURE;
 | ||
|  |     // virtual HRESULT CheckTransform
 | ||
|  |     //     (const CMediaType* mtIn, const CMediaType* mtOut) PURE;
 | ||
|  |     // static CCOMObject * CreateInstance(LPUNKNOWN, HRESULT *);
 | ||
|  |     // virtual HRESULT DecideBufferSize
 | ||
|  |     //     (IMemAllocator * pAllocator, ALLOCATOR_PROPERTIES *pprop) PURE;
 | ||
|  |     // virtual HRESULT GetMediaType(int iPosition, CMediaType *pMediaType) PURE;
 | ||
|  |     //
 | ||
|  |     // These MAY also be overridden
 | ||
|  |     //
 | ||
|  |     // virtual HRESULT StopStreaming();
 | ||
|  |     // virtual HRESULT SetMediaType(PIN_DIRECTION direction,const CMediaType *pmt);
 | ||
|  |     // virtual HRESULT CheckConnect(PIN_DIRECTION dir,IPin *pPin);
 | ||
|  |     // virtual HRESULT BreakConnect(PIN_DIRECTION dir);
 | ||
|  |     // virtual HRESULT CompleteConnect(PIN_DIRECTION direction,IPin *pReceivePin);
 | ||
|  |     // virtual HRESULT EndOfStream(void);
 | ||
|  |     // virtual HRESULT BeginFlush(void);
 | ||
|  |     // virtual HRESULT EndFlush(void);
 | ||
|  |     // virtual HRESULT NewSegment
 | ||
|  |     //     (REFERENCE_TIME tStart,REFERENCE_TIME tStop,double dRate);
 | ||
|  | #ifdef PERF
 | ||
|  | 
 | ||
|  |     // If you override this - ensure that you register all these ids
 | ||
|  |     // as well as any of your own,
 | ||
|  |     virtual void RegisterPerfId() { | ||
|  |         m_idSkip        = MSR_REGISTER(TEXT("Video Transform Skip frame")); | ||
|  |         m_idFrameType   = MSR_REGISTER(TEXT("Video transform frame type")); | ||
|  |         m_idLate        = MSR_REGISTER(TEXT("Video Transform Lateness")); | ||
|  |         m_idTimeTillKey = MSR_REGISTER(TEXT("Video Transform Estd. time to next key")); | ||
|  |         CTransformFilter::RegisterPerfId(); | ||
|  |     } | ||
|  | #endif
 | ||
|  | 
 | ||
|  |   protected: | ||
|  | 
 | ||
|  |     // =========== QUALITY MANAGEMENT IMPLEMENTATION ========================
 | ||
|  |     // Frames are assumed to come in three types:
 | ||
|  |     // Type 1: an AVI key frame or an MPEG I frame.
 | ||
|  |     //        This frame can be decoded with no history.
 | ||
|  |     //        Dropping this frame means that no further frame can be decoded
 | ||
|  |     //        until the next type 1 frame.
 | ||
|  |     //        Type 1 frames are sync points.
 | ||
|  |     // Type 2: an AVI non-key frame or an MPEG P frame.
 | ||
|  |     //        This frame cannot be decoded unless the previous type 1 frame was
 | ||
|  |     //        decoded and all type 2 frames since have been decoded.
 | ||
|  |     //        Dropping this frame means that no further frame can be decoded
 | ||
|  |     //        until the next type 1 frame.
 | ||
|  |     // Type 3: An MPEG B frame.
 | ||
|  |     //        This frame cannot be decoded unless the previous type 1 or 2 frame
 | ||
|  |     //        has been decoded AND the subsequent type 1 or 2 frame has also
 | ||
|  |     //        been decoded.  (This requires decoding the frames out of sequence).
 | ||
|  |     //        Dropping this frame affects no other frames.  This implementation
 | ||
|  |     //        does not allow for these.  All non-sync-point frames are treated
 | ||
|  |     //        as being type 2.
 | ||
|  |     //
 | ||
|  |     // The spacing of frames of type 1 in a file is not guaranteed.  There MUST
 | ||
|  |     // be a type 1 frame at (well, near) the start of the file in order to start
 | ||
|  |     // decoding at all.  After that there could be one every half second or so,
 | ||
|  |     // there could be one at the start of each scene (aka "cut", "shot") or
 | ||
|  |     // there could be no more at all.
 | ||
|  |     // If there is only a single type 1 frame then NO FRAMES CAN BE DROPPED
 | ||
|  |     // without losing all the rest of the movie.  There is no way to tell whether
 | ||
|  |     // this is the case, so we find that we are in the gambling business.
 | ||
|  |     // To try to improve the odds, we record the greatest interval between type 1s
 | ||
|  |     // that we have seen and we bet on things being no worse than this in the
 | ||
|  |     // future.
 | ||
|  | 
 | ||
|  |     // You can tell if it's a type 1 frame by calling IsSyncPoint().
 | ||
|  |     // there is no architected way to test for a type 3, so you should override
 | ||
|  |     // the quality management here if you have B-frames.
 | ||
|  | 
 | ||
|  |     int m_nKeyFramePeriod; // the largest observed interval between type 1 frames
 | ||
|  |                            // 1 means every frame is type 1, 2 means every other.
 | ||
|  | 
 | ||
|  |     int m_nFramesSinceKeyFrame; // Used to count frames since the last type 1.
 | ||
|  |                                 // becomes the new m_nKeyFramePeriod if greater.
 | ||
|  | 
 | ||
|  |     BOOL m_bSkipping;           // we are skipping to the next type 1 frame
 | ||
|  | 
 | ||
|  | #ifdef PERF
 | ||
|  |     int m_idFrameType;          // MSR id Frame type.  1=Key, 2="non-key"
 | ||
|  |     int m_idSkip;               // MSR id skipping
 | ||
|  |     int m_idLate;               // MSR id lateness
 | ||
|  |     int m_idTimeTillKey;        // MSR id for guessed time till next key frame.
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  |     virtual HRESULT StartStreaming(); | ||
|  | 
 | ||
|  |     HRESULT AbortPlayback(HRESULT hr);	// if something bad happens
 | ||
|  | 
 | ||
|  |     HRESULT Receive(IMediaSample *pSample); | ||
|  | 
 | ||
|  |     HRESULT AlterQuality(Quality q); | ||
|  | 
 | ||
|  |     BOOL ShouldSkipFrame(IMediaSample * pIn); | ||
|  | 
 | ||
|  |     int m_itrLate;              // lateness from last Quality message
 | ||
|  |                                 // (this overflows at 214 secs late).
 | ||
|  |     int m_tDecodeStart;         // timeGetTime when decode started.
 | ||
|  |     int m_itrAvgDecode;         // Average decode time in reference units.
 | ||
|  | 
 | ||
|  |     BOOL m_bNoSkip;             // debug - no skipping.
 | ||
|  | 
 | ||
|  |     // We send an EC_QUALITY_CHANGE notification to the app if we have to degrade.
 | ||
|  |     // We send one when we start degrading, not one for every frame, this means
 | ||
|  |     // we track whether we've sent one yet.
 | ||
|  |     BOOL m_bQualityChanged; | ||
|  | 
 | ||
|  |     // When non-zero, don't pass anything to renderer until next keyframe
 | ||
|  |     // If there are few keys, give up and eventually draw something
 | ||
|  |     int m_nWaitForKey; | ||
|  | }; |