📄 mpgutil.cpp
字号:
//==========================================================================;
//
// 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 1 & 2 parsing routines */
#include "stdafx.h"
#include <streams.h>
#include "mpegdef.h"
#include <mmreg.h>
#include "mpgutil.h"
//#ifdef DEBUG
LPCTSTR PictureTypes[8] = { TEXT("forbidden frame type"),
TEXT("I-Frame"),
TEXT("P-Frame"),
TEXT("B-Frame"),
TEXT("D-Frame"),
TEXT("Reserved frame type"),
TEXT("Reserved frame type"),
TEXT("Reserved frame type")
};
LPCTSTR PelAspectRatios[16] = { TEXT("Forbidden"),
TEXT("1.0000 - VGA etc"),
TEXT("0.6735"),
TEXT("0.7031 - 16:9, 625 line"),
TEXT("0.7615"),
TEXT("0.8055"),
TEXT("0.8437 - 16:9, 525 line"),
TEXT("0.8935"),
TEXT("0.9375 - CCIR601, 625 line"),
TEXT("0.9815"),
TEXT("1.0255"),
TEXT("1.0695"),
TEXT("1.1250 - CCIR601, 525 line"),
TEXT("1.1575"),
TEXT("1.2015"),
TEXT("Reserved") };
LPCTSTR PictureRates[16] = { TEXT("Forbidden"),
TEXT("23.976"),
TEXT("24"),
TEXT("25"),
TEXT("29.97"),
TEXT("30"),
TEXT("50"),
TEXT("59.94"),
TEXT("60"),
TEXT("Reserved"),
TEXT("Reserved"),
TEXT("Reserved"),
TEXT("Reserved"),
TEXT("Reserved"),
TEXT("Reserved"),
TEXT("Reserved") };
//#endif // DBG
const LONG PictureTimes[16] = { 0,
(LONG)((double)10000000 / 23.976),
(LONG)((double)10000000 / 24),
(LONG)((double)10000000 / 25),
(LONG)((double)10000000 / 29.97),
(LONG)((double)10000000 / 30),
(LONG)((double)10000000 / 50),
(LONG)((double)10000000 / 59.94),
(LONG)((double)10000000 / 60)
};
const float fPictureRates[] =
{
(float)0,
(float)23.976,
(float)24,
(float)25,
(float)29.97,
(float)30,
(float)50,
(float)59.94,
(float)60.0
};
const LONG AspectRatios[16] = { 0,
393700,
(LONG)(393700.0 * 0.6735),
(LONG)(393700.0 * 0.7031),
(LONG)(393700.0 * 0.7615),
(LONG)(393700.0 * 0.8055),
(LONG)(393700.0 * 0.8437),
(LONG)(393700.0 * 0.8935),
(LONG)(393700.0 * 0.9375),
(LONG)(393700.0 * 0.9815),
(LONG)(393700.0 * 1.0255),
(LONG)(393700.0 * 1.0695),
(LONG)(393700.0 * 1.1250),
(LONG)(393700.0 * 1.1575),
(LONG)(393700.0 * 1.2015),
0
};
/* Bit rate tables */
const WORD BitRates[3][16] =
{{ 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0 },
{ 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0 },
{ 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0 }
};
BOOL inline TESTBIT(const BYTE * pbData, int n)
{
return 0 != (pbData[n >> 3] & (0x80 >> (n & 7)));
}
/* 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)
{
BOOL bHasAudio = FALSE;
BOOL bHasVideo = FALSE;
ASSERT(cbData >= 4);
ASSERT(*(UNALIGNED DWORD *)pbData == DWORD_SWAP(SYSTEM_HEADER_START_CODE));
/* Checkt the length */
if (cbData < 6) {
return 0;
}
DWORD dwLen = 6 + pbData[5] + (pbData[4] << 8);
if (dwLen < SYSTEM_HEADER_BASIC_LENGTH) {
DbgLog((LOG_ERROR, 1, TEXT("Invalid System Header length")));
return 4;
}
if (cbData < dwLen) {
return 0;
}
/* Check the marker bits */
if (0 == (pbData[6] & 0x80) ||
0 == (pbData[8] & 0x01) ||
0 == (pbData[10] & 0x20)) {
DbgLog((LOG_ERROR, 1, TEXT("Invalid System Header Marker bits")));
return 4;
}
/* Parse the 'buffer bounds and scale' list */
const BYTE * pbNext = pbData + SYSTEM_HEADER_BASIC_LENGTH;
DWORD cbLeft = dwLen - SYSTEM_HEADER_BASIC_LENGTH;
for ( ; cbLeft >= 3; cbLeft -= 3, pbNext += 3) {
if (pbNext[0] == AUDIO_GLOBAL) {
bHasAudio = TRUE;
} else
if (pbNext[0] == VIDEO_GLOBAL) {
bHasVideo = TRUE;
} else {
if (pbNext[0] < PROGRAM_STREAM_MAP) {
DbgLog((LOG_ERROR, 1, TEXT("Invalid stream id in system header")));
return 4;
}
if (IsVideoStreamId(pbNext[0])) {
bHasVideo = TRUE;
} else
if (IsAudioStreamId(pbNext[0])) {
bHasAudio = TRUE;
}
}
}
if (cbLeft != 0) {
DbgLog((LOG_ERROR, 1, TEXT("Invalid system header length")));
return 4;
}
DbgLog((LOG_TRACE, 4, TEXT("System Header %s, %s"),
bHasAudio ? TEXT("audio") : TEXT("No audio"),
bHasVideo ? TEXT("video") : TEXT("No video")));
return dwLen;
}
/* Parse an MPEG-1 packet */
DWORD ParseMPEG1Packet(
const BYTE * pbData,
DWORD cbData,
MPEG_PACKET_DATA *pPacketData,
DWORD * Pts
)
{
ZeroMemory((PVOID)pPacketData, sizeof(*pPacketData));
DWORD dwStartCode = DWORD_SWAP(*(UNALIGNED DWORD *)pbData);
DbgLog((LOG_TRACE, 4, TEXT("Parse packet %d bytes"), cbData));
/* Send it to the right stream */
if (cbData < 6) {
return 0;
}
/* Find the length */
DWORD dwLen = ((LONG)pbData[4] << 8) + (LONG)pbData[5] + 6;
DbgLog((LOG_TRACE, 4, TEXT("Packet length %d bytes"), dwLen));
if (dwLen > cbData) {
return 0;
}
pPacketData->dwPacketLen = dwLen;
/* Pull out PTS if any */
DWORD dwHeaderSize = 6;
if (dwStartCode != PRIVATE_STREAM_2) {
DWORD dwPts = 6;
for (;;) {
if (dwPts >= dwLen) {
return 4;
}
if (pbData[dwPts] & 0x80) {
/* Stuffing byte */
if (pbData[dwPts] != 0xFF) {
return 4;
}
dwPts++;
continue;
}
/* Check for STD (nextbits == '01') -
we know the next bit is 0 so check the next one after that
*/
if (pbData[dwPts] & 0x40) { // STD stuff
dwPts += 2;
continue;
}
/* No PTS - normal case */
if (pbData[dwPts] == 0x0F) {
dwHeaderSize = dwPts + 1;
break;
}
if ((pbData[dwPts] & 0xF0) == 0x20 ||
(pbData[dwPts] & 0xF0) == 0x30) {
/* PTS or PTS and DTS */
dwHeaderSize = (pbData[dwPts] & 0xF0) == 0x20 ? dwPts + 5 :
dwPts + 10;
if (dwHeaderSize > dwLen) {
return 4;
}
if (!GetClock(pbData + dwPts, &pPacketData->llPts)) {
*Pts = dwPts;
return 4;
}
pPacketData->bHasPts = TRUE;
break;
} else {
return 4;
break;
}
}
}
pPacketData->dwHeaderLen = dwHeaderSize;
return dwLen;
}
BOOL ParseSequenceHeader(const BYTE *pbData, LONG lData, SEQHDR_INFO *pInfo)
{
ASSERT(*(UNALIGNED DWORD *)pbData == DWORD_SWAP(SEQUENCE_HEADER_CODE));
/* Check random marker bit */
if (!(pbData[10] & 0x20)) {
DbgLog((LOG_ERROR, 2, TEXT("Sequence header invalid marker bit")));
return FALSE;
}
DWORD dwWidthAndHeight = ((DWORD)pbData[4] << 16) +
((DWORD)pbData[5] << 8) +
((DWORD)pbData[6]);
pInfo->lWidth = dwWidthAndHeight >> 12;
pInfo->lHeight = dwWidthAndHeight & 0xFFF;
DbgLog((LOG_TRACE, 2, TEXT("Width = %d, Height = %d"),
pInfo->lWidth,
pInfo->lHeight));
/* the '8' bit is the scramble flag used by sigma designs - ignore */
BYTE PelAspectRatioAndPictureRate = pbData[7];
if ((PelAspectRatioAndPictureRate & 0x0F) > 8) {
PelAspectRatioAndPictureRate &= 0xF7;
}
DbgLog((LOG_TRACE, 2, TEXT("Pel Aspect Ratio = %s"),
PelAspectRatios[PelAspectRatioAndPictureRate >> 4]));
DbgLog((LOG_TRACE, 2, TEXT("Picture Rate = %s"),
PictureRates[PelAspectRatioAndPictureRate & 0x0F]));
if ((PelAspectRatioAndPictureRate & 0xF0) == 0 ||
(PelAspectRatioAndPictureRate & 0x0F) == 0) {
DbgLog((LOG_ERROR, 2, TEXT("Sequence header invalid ratio/rate")));
return FALSE;
}
pInfo->tPictureTime = (LONGLONG)PictureTimes[PelAspectRatioAndPictureRate & 0x0F];
pInfo->fPictureRate = fPictureRates[PelAspectRatioAndPictureRate & 0x0F];
pInfo->lTimePerFrame = MulDiv((LONG)pInfo->tPictureTime, 9, 1000);
/* Pull out the bit rate and aspect ratio for the type */
pInfo->dwBitRate = ((((DWORD)pbData[8] << 16) +
((DWORD)pbData[9] << 8) +
(DWORD)pbData[10]) >> 6);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -