//==========================================================================;
//
// 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.
//
//--------------------------------------------------------------------------;
/* MPEG-2 utility functions */
/* Packet header info */
typedef struct tag_MPEG_PACKET_DATA {
DWORD dwHeaderLen;
DWORD dwPacketLen;
BOOL bHasPts;
LONGLONG llPts;
} MPEG_PACKET_DATA;
/* Read an normal MPEG-1 style clock */
BOOL GetClock(const BYTE * pData, LONGLONG *Clock);
/* Read an extended clock */
BOOL GetExtendedClock(const BYTE * pbData, LONGLONG *pllClock);
inline GetStartCode(const BYTE * pbData)
{
return DWORD_SWAP(*(UNALIGNED DWORD *)pbData);
}
/* Since dwCode is normally a constant just swap that instead */
inline BOOL IsStartCode(const BYTE * pbData, DWORD dwCode)
{
return DWORD_SWAP(dwCode) == *(UNALIGNED DWORD *)pbData;
}
/* Parse pack header
Parameters :
pbData - pointer to data containing the system header
cbData - length of data
Returns :
Number of bytes processed (0 if the header doesn't fit
in the data or 4 if the header is invalid)
We will return 0 if we can't see the next start code to
check whether it's a system header start code
*/
DWORD ParseMPEG2PackHeader(const BYTE * pbData, DWORD cbData);
/* Length of pack header - returns 0 if < cbData */
inline DWORD MPEG2PackHeaderLength(const BYTE * pbData, DWORD cbData)
{
/* Need more data */
if (cbData < 14) {
return 0;
} else {
DWORD dwLen = 14 + (pbData[13] & 0x07);
if (dwLen > cbData) {
return 0;
} else {
return dwLen;
}
}
}
/* Parse system header
Parameters :
pbData - pointer to data containing the system header
cbData - length of data
Returns :
Number of bytes processed (0 if the header doesn't fit
in the data or 4 if the header is invalid)
*/
LONG ParseSystemHeader(const BYTE * pbData, DWORD cbData);
/* Parse an MPEG2 packet and extract information */
DWORD ParseMPEG2Packet(
const BYTE * pbData,
DWORD cbData,
MPEG_PACKET_DATA *pPacketData
);
/* Parse an MPEG1 packet and extract information */
DWORD ParseMPEG1Packet(
const BYTE * pbData,
DWORD cbData,
MPEG_PACKET_DATA *pPacketData
);
BOOL ParseMPEG2PacketHeader(
const BYTE * pbData,
DWORD dwLen,
MPEG_PACKET_DATA *pPacketData
);
/* Inlines to get PTSs from MPEG2 packets */
inline BOOL MPEG2PacketHasPTS(const BYTE * pbPacket)
{
/* Just check if the PTS_DTS_flags are 10 or 11 (ie the first
bit is one
*/
return 0 != (pbPacket[7] & 0x80);
}
/* Get the PTS from an MPEG2 packet */
LONGLONG MPEG2PacketPTS(const BYTE * pbPacket);
typedef struct {
DWORD dwProfile; // Profile - MPEG2 only
DWORD dwLevel; // Level - MPEG2 only
LONG lWidth; // Native Width in pixels
LONG lHeight; // Native Height in pixels
LONG lvbv; // vbv
REFERENCE_TIME tPictureTime; // Time per picture in 100ns units
float fPictureRate; // In frames per second
LONG lTimePerFrame; // Time per picture in MPEG units
LONG dwBitRate; // Bits per second
LONG lXPelsPerMeter; // Pel aspect ratio
LONG lYPelsPerMeter; // Pel aspect ratio
DWORD dwStartTimeCode; // First GOP time code (or -1)
LONG lActualHeaderLen; // Length of valid bytes in raw seq hdr
BYTE RawHeader[140]; // The real sequence header
} SEQHDR_INFO;
/* MPEG2 stuff */
typedef struct {
BOOL bExtensionPresent;
BOOL bDisplayExtensionPresent;
BOOL bScalableExtensionPresent;
SEQHDR_INFO seqhdrInfo;
} MPEG2_SEQHDR_INFO;
/* Helper */
int inline SequenceHeaderSize(const BYTE *pb)
{
/* No quantization matrices ? */
if ((pb[11] & 0x03) == 0x00) {
return 12;
}
/* Just non-intra quantization matrix ? */
if ((pb[11] & 0x03) == 0x01) {
return 12 + 64;
}
/* Intra found - is there a non-intra ? */
if (pb[11 + 64] & 0x01) {
return 12 + 64 + 64;
} else {
return 12 + 64;
}
}
/* Extract info from video sequence header
Returns FALSE if the sequence header is invalid
*/
BOOL ParseSequenceHeader(const BYTE *pbData, LONG lData, SEQHDR_INFO *hdrInfo);
BOOL ParseAudioHeader(const BYTE * pbData, MPEG1WAVEFORMAT *pFormat);
/* Construct a media type from the video info */
HRESULT GetVideoMediaType(CMediaType *cmt, BOOL bPayload, const SEQHDR_INFO *pInfo);
/* Find the next start code */
BOOL NextStartCode(const BYTE * *ppbData, DWORD *pdwLeft);
/* Parse AC3 header */
BOOL ParseAC3Header(const BYTE * pbData, DOLBYAC3WAVEFORMAT *pwf);