MPEG2.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) 1996 - 1997  Microsoft Corporation.  All Rights Reserved. 
// 
//--------------------------------------------------------------------------; 
/*  Structures and definitions for MPEG2 filter stuff */ 
 
/*  Implement type checking and CompleteConnect */ 
class CMPEG2SplitterFilter : public CBaseSplitterFilter 
{ 
public: 
    /* This goes in the factory template table to create new instances */ 
    static CUnknown *CreateInstance(LPUNKNOWN, HRESULT *); 
 
    //  Constructor and destructor 
    CMPEG2SplitterFilter( 
       LPUNKNOWN pUnk, 
       HRESULT *phr); 
 
    //  Support self-registration 
    LPAMOVIESETUP_FILTER GetSetupData(); 
 
    //  Override type checking 
    HRESULT CheckInputType(const CMediaType *pmt); 
 
    //  Create the parser for this filter 
    CBaseParser *CreateParser(CParserNotify *pNotify, CMediaType *pType); 
}; 
 
/*  MPEG-2 parsing 
 
    We decide which streams we have by a 2-stage process: 
 
        We find a system header. 
 
        If this lists a program stream map we use that for finding 
        stream information. 
 
        Otherwise we use the list in the system stream header. 
 
*/ 
 
/*  Parser */ 
class CMPEG2Parser : public CBaseParser 
{ 
public: 
    CMPEG2Parser(CParserNotify *pNotify, HRESULT *phr) : 
        CBaseParser(pNotify, phr), 
        m_bGotFirstPts(FALSE), 
        m_llFirstPts(0), 
        m_uCurrentAudioStream(0), 
        m_uCurrentVideoStream(0), 
        m_bHasAudio(FALSE), 
        m_bHasVideo(FALSE), 
        m_uAudioStreamId(0), 
        m_uVideoStreamId(0) 
    { 
    } 
 
    /*  Initialize a parser 
 
        pmt     - type of stream if known - can be NULL 
        pRdr    - way to read the source medium - can be NULL 
    */ 
    HRESULT Init(CParseReader *pRdr); 
 
 
    /*  Initialize a stream - make this virtual so we can override 
        some streams in a derived class 
    */ 
    virtual HRESULT InitStream( 
        UCHAR uStreamId, 
        const BYTE * pbFirstPacket, 
        DWORD dwLen 
    ); 
 
    /*  Initialize a stream */ 
    HRESULT InitAudioStream( 
        UCHAR uStreamId, 
        const BYTE * pbFirstPacket, 
        DWORD dwLen 
    ); 
 
    /*  Initialize a stream */ 
    HRESULT InitVideoStream( 
        UCHAR uStreamId, 
        const BYTE *pbFirstPacket, 
        DWORD dwLen 
    ); 
 
    /*  Initialize a stream */ 
    HRESULT InitPrivateStream1( 
        UCHAR uStreamId, 
        const BYTE * pbFirstPacket, 
        DWORD dwLen 
    ); 
 
    /*  Initialize AC3 */ 
    HRESULT InitAC3( 
        UCHAR uStreamId, 
        const BYTE * pbFirstPacket, 
        DWORD dwLen 
    ); 
 
    /*  Initialize subpicture */ 
    HRESULT InitSubPicture( 
        UCHAR uStreamId, 
        const BYTE * pbFirstPacket, 
        DWORD dwLen 
    ); 
 
    /*  Get the size and count of buffers preferred based on the 
        actual content 
    */ 
    void GetSizeAndCount(LONG *plSize, LONG *plCount); 
 
    /*  Call this to reinitialize for a new stream */ 
    void StreamReset(); 
 
    /*  Call this to pass new stream data : 
 
        pbData        - pointer to data 
        lData         - length of data 
        plProcessed   - Amount of data consumed 
    */ 
    HRESULT Process( 
        const BYTE * pbData, 
        LONG lData, 
        LONG *plProcessed 
    ); 
 
private: 
    /*  Helper to set timestamps */ 
    REFERENCE_TIME TimeStamp(LONGLONG llPts) 
    { 
        ASSERT(m_bGotFirstPts); 
        LARGE_INTEGER liPtsOffset; 
        liPtsOffset.QuadPart = llPts - m_llFirstPts; 
        liPtsOffset.HighPart &= 1; 
        liPtsOffset.HighPart = -liPtsOffset.HighPart; 
        return llMulDiv(liPtsOffset.QuadPart, 
                        UNITS, 
                        MPEG_TIME_DIVISOR, 
                        0); 
    } 
private: 
    /*  Parsing structures */ 
    class CStream 
    { 
    public: 
        CStream(BYTE uStreamId, BOOL bHasSubId, BYTE uSubId) : 
                    m_uStreamId(uStreamId), 
                    m_uSubId(uSubId), 
                    m_bHasSubId(bHasSubId), 
                    m_pNotify(NULL), 
                    m_dwSkip(0), 
                    m_pNext(NULL) {} 
        virtual ~CStream() {}          // So we can delete as a CStream 
        BOOL Initialized() 
        { 
            return m_pNotify != NULL && m_uStreamId != 0xFF; 
        } 
        BYTE           m_uStreamId; 
        BYTE           m_uSubId; 
        BOOL           m_bHasSubId; 
        BOOL           m_bDoPES; 
        DWORD          m_dwSkip; 
        CStreamNotify *m_pNotify; 
        CStream       *m_pNext; 
    }; 
 
    HRESULT CreateDefaultStream( 
        UCHAR   uStreamId, 
        LPCWSTR lpszName, 
        CMediaType *pmt, 
        BOOL  bDoPES = TRUE, 
        BOOL  bHasSubId = FALSE, 
        BOOL  buSubId = 0 
    ); 
 
 
    /*  Select audio and video streams - there could be multiple of 
        each 
    */ 
    BOOL     m_bHasAudio; 
    UCHAR    m_uCurrentAudioStream; 
    BOOL     m_bHasVideo; 
    UCHAR    m_uCurrentVideoStream; 
 
    /*  One stream per possible stream */ 
    class CStreamInfo { 
    public: 
        CStreamInfo() : m_pStream(NULL), m_bExists(FALSE) {} 
        CStream  *m_pStream; 
        BOOL      m_bExists; 
 
        ~CStreamInfo() 
        { 
            while (m_pStream != NULL) { 
                CStream *pStream = m_pStream; 
                m_pStream = pStream->m_pNext; 
                delete pStream; 
            } 
        } 
        CStream *FindStream(UCHAR uSubId) 
        { 
            for (CStream *pSearch = m_pStream; 
                 pSearch != NULL; 
                 pSearch = pSearch->m_pNext) { 
                if (!pSearch->m_bHasSubId || pSearch->m_uSubId == uSubId) { 
                    /*  Done this one */ 
                    return pSearch; 
                } 
            } 
            return NULL; 
        } 
    }; 
 
    /*  Get a stream corresponding to an id */ 
    CStreamInfo *StreamInfo(UCHAR id) 
    { 
        ASSERT(id >= PROGRAM_STREAM_MAP && 
               id <= PROGRAM_STREAM_DIRECTORY); 
        return &m_Streams[id - PROGRAM_STREAM_MAP]; 
    } 
 
    CStreamInfo m_Streams[PROGRAM_STREAM_DIRECTORY - PROGRAM_STREAM_MAP + 1]; 
    LONGLONG    m_llFirstPts; 
    BOOL        m_bGotFirstPts; 
 
    BYTE        m_uAudioStreamId; 
    BYTE        m_uVideoStreamId; 
};