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