//==========================================================================; // // 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 - 1998 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; };