VTRANS.H
//==========================================================================; 
// 
//  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 
//  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 
//  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR 
//  PURPOSE. 
// 
//  Copyright (c) 1992 - 1997  Microsoft Corporation.  All Rights Reserved. 
// 
//--------------------------------------------------------------------------; 
 
// Video transform base class. 
// 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(TCHAR *, 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("Video Transform Skip frame"); 
        m_idFrameType   = MSR_REGISTER("Video transform frame type"); 
        m_idLate        = MSR_REGISTER("Video Transform Lateness"); 
        m_idTimeTillKey = MSR_REGISTER("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.  This is of course a poor show, but it's "the only show in town". 
 
    // 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 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; 
};