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;
};