📄 mmutils.cpp
字号:
case 0: // Program association table (section)
if (wPid != 0)
continue;
{
BYTE bCode = 0;
WORD wLength = 0;
if (dwBufferIndex >= dwLength)
continue;
bCode = *(pBuffer + dwBufferIndex++);
INT bSecSyntaxIndicator = bCode >> 7; // Bit 7
if ((bSecSyntaxIndicator != 1) || ((bCode & 0x40) != 0))
continue;
INT wSectionLength = (bCode & 0xF); // Bits 3-0
if (dwBufferIndex >= dwLength)
continue;
wSectionLength = (wSectionLength << 8) | *(pBuffer + dwBufferIndex++);
if (((wSectionLength & 0xC00) != 0) || (wSectionLength > 1021))
continue;
// Transport stream id, 2 bytes
dwBufferIndex += 2;
if (dwBufferIndex >= dwLength)
continue;
// Version number and current next indicator
bCode = *(pBuffer + dwBufferIndex++);
if (dwBufferIndex >= dwLength)
continue;
BYTE bSectionNum = *(pBuffer + dwBufferIndex++);
if (dwBufferIndex >= dwLength)
continue;
BYTE bLastSectionNum = *(pBuffer + dwBufferIndex++);
wLength += 5;
while (TRUE)
{
if (dwBufferIndex + 1 >= dwLength)
continue;
INT wProgramNum = *(pBuffer + dwBufferIndex++);
wProgramNum = (wProgramNum << 8) | *(pBuffer + dwBufferIndex++);
dwBufferIndex += 2;
iCounter++;
wLength += 4;
if ((wLength + 4) == wSectionLength)
break;
}
return iCounter;
}
break;
case 1: // Conditional access table (section)
if ((wPid != 0) || (bScrambling == 0))
continue;
break;
case 2: // Program Map Table (section). Look for stream type.
if (wPid < 0x00010 || wPid > 0x1FFE)
continue;
break;
default:
break;
}
wBytesAdvanced += wLength;
// Don't think there's PES payload after each section table.
// Advance to first byte of next packet.
dwBufferIndex += (187 - wBytesAdvanced);
continue;
}
else
{
dwBufferIndex -= (bPointerField + 2);
dwBufferIndex += (187 - wBytesAdvanced);
continue;
}
}
dwBufferIndex += (187 - wBytesAdvanced);
}
}
}
return iCounter;
}
////////////////////////////////////////////////////////////////////
/****f* MMDemux/GetAVChannelCounter
* USAGE
* void GetAVChannelCounter(char* pFile, int* iAudio, int* iVideo, int iStreamType = FT_UNKNOWN)
* void GetAVChannelCounter(const BYTE* pBuffer, DWORD dwLength, int* iAudio, int* iVideo,
* int iStreamType = FT_UNKNOWN)
* DESCRIPTION
* Determines the number of video and audio channels
* PARAMETERS
* const BYTE *pBuffer - a pointer to the data buffer to search.
* DWORD dwLength - size of the search buffer.
* int* iAudio - pointer to an int that will hold the number of audio channels.
* int* iVideo - pointer to an int that will hold the number of video channels.
* RETURN VALUE
* None
/**********************************************************************/
void GetAVChannelCounter(char* pFile, int* iAudio, int* iVideo, int iStreamType)
{
BYTE bBuffer[READ_BUFFERSIZE];
DWORD dwReadSize = 0;
FILE *pPlayfile;
if ((pPlayfile = fopen(pFile, "rb")) == NULL)
{
MmDebugLogfile((MmDebugLevelTrace, "Unable to open file!"));
return;
}
dwReadSize = fread(bBuffer, sizeof(char), READ_BUFFERSIZE, pPlayfile);
fclose(pPlayfile);
GetAVChannelCounter(bBuffer, dwReadSize, iAudio, iVideo, iStreamType);
}
/////////////////////////////////////////////////////////////////////////////
void GetAVChannelCounter(const BYTE* pBuffer, DWORD dwLength, int* iAudio, int* iVideo,
int iStreamType)
{
DWORD dwCode = 0;
DWORD dwIndex = 0;
DWORD dwMpeg1AudioMask = 0x0000;
DWORD dwAc3Mask = 0x00;
DWORD dwDtsMask = 0x00;
DWORD dwPcmMask = 0x00;
DWORD dwVideoMask = 0x0000;
*iAudio = 0;
*iVideo = 0;
if (iStreamType == FT_UNKNOWN)
iStreamType = IdentifyHeader(pBuffer, dwLength);
if (iStreamType == FT_MPEG2_TRANSPORT)
{
*iAudio = 1;
*iVideo = 1;
return;
}
else if ((iStreamType == FT_MPEG_AUDIO) || (iStreamType == FT_AC3_AUDIO) || (iStreamType == FT_DTS_AUDIO))
{
*iAudio = 1;
return;
}
/*
while (dwIndex < dwLength)
{
dwCode = (dwCode << 8) | *(pBuffer + dwIndex++);
if (dwCode == SYSTEM_START_CODE)
{
if (dwIndex >= dwLength)
break;
WORD wHeaderLength = *(pBuffer + dwIndex++);
if (dwIndex >= dwLength)
break;
wHeaderLength = (wHeaderLength << 8) | *(pBuffer + dwIndex++);
// Rate bound and marker bits (3 bytes).
dwIndex += 3;
// Audio bound, fixed flag, CSPS flag.
if (dwIndex >= dwLength)
break;
BYTE bAudioBound = *(pBuffer + dwIndex++) >> 2;
// System audio clock flag, system video clock flag, marker bit, video bound bits.
if (dwIndex>= dwLength)
break;
BYTE bVideoBound = *(pBuffer + dwIndex++) & 0x1F;
*iAudio = bAudioBound;
*iVideo = bVideoBound;
break;
// No need to finish the rest!!!
}
}
*/
while (dwIndex < dwLength)
{
dwCode = (dwCode << 8) | *(pBuffer + dwIndex++);
if (((dwCode & 0xFFFFFFF0) == AUDIO_STREAM) ||
((dwCode & 0xFFFFFFF0) == VIDEO_STREAM) || (dwCode == AC3_PCM_DTS_STREAM))
{
INT wPacketHeaderLength = 0;
INT wPacketLength = 0;
DWORD dwSavedIndex = dwIndex;
wPacketLength = *(pBuffer + dwIndex++);
if (dwIndex >= dwLength)
break;
wPacketLength = (wPacketLength << 8) | *(pBuffer + dwIndex++);
// Skip byte containing scrambling control, priority, alignment, copyright
// and original or copy bits.
dwIndex++;
wPacketHeaderLength++;
// Get PTS, DTS, ESCR, ESRate, DSM trick mode, additional copy info, CRC and
// extension flags.
if (dwIndex >= dwLength)
break;
BYTE byte = *(pBuffer + dwIndex++);
wPacketHeaderLength++;
INT bPtsFlag = byte >> 6; // Bits 7 & 6, PTS or no
// INT bESCRFlag = byte & 0x20; // Bit 5, should be 0
// INT bESRateFlag = byte & 0x10; // Bit 4, should be 0
// INT bDSMTrickModeFlag = byte & 0x8; // Bit 3, should be 0
// INT bAddCopyInfoFlag = byte & 0x4; // Bit 2, should be 0
// INT bCRCFlag = byte & 0x2; // Bit 1, should be 0
INT bExtFlag = byte & 0x1; // Bit 0, 0 or 1
// Get Header Data Length
if (dwIndex >= dwLength)
break;
BYTE bHeaderDataLength = *(pBuffer + dwIndex++);
wPacketHeaderLength++;
// Keep current # of advanced bytes after the PES_header_data_length field.
// Use this to calculate the stuffing bytes.
BYTE bCurHeaderDataLength = 0;
// Get PTS
if (bPtsFlag == 0x2) // '10'
{
dwIndex += 5;
bCurHeaderDataLength += 5;
}
// Check if Extension flag is set to 1 to skip bytes
if (bExtFlag == 1)
{
// Get private data flag, pack header field flag, program packet sequence
// counter flag, P-STD buffer flag, reserved and PES extention flag2 bits.
if (dwIndex >= dwLength)
break;
byte = *(pBuffer + dwIndex++);
bCurHeaderDataLength++;
// INT bPrivateDataFlag = byte >> 7; // Bit 7, should be 0
// INT bPackHeaderFieldFlag = byte & 0x40; // Bit 6, should be 0
// INT bSeqCounterFlag = byte & 0x20; // Bit 5, should be 0
INT bSTDBufferFlag = byte & 0x10; // Bit 4, should be 1
// INT bReserved = byte & 0xE; // Bits 3-1, should be 111b
// INT bExtFlag2 = byte & 0x1; // Bit 0, should be 0
// Check if STD Buffer flag is set to 1 to skip STD buffer scale and
// buffer size (2 bytes).
if (bSTDBufferFlag == 0x10) // 10000b or bit 4 is 1
{
dwIndex += 2;
bCurHeaderDataLength += 2;
}
}
// Skip stuffing bytes
INT wStuffingByte = bHeaderDataLength - bCurHeaderDataLength;
dwIndex += wStuffingByte;
wPacketHeaderLength += bHeaderDataLength ;
if (wPacketLength <= wPacketHeaderLength) // wrong pes payload
{
dwIndex = dwSavedIndex;
continue;
}
if (dwCode == AC3_PCM_DTS_STREAM)
{
// Sub stream id: AC3 (10000***b), DTS (10001***b), PCM (10100***b), SUB (001*****b)
if (dwIndex >= dwLength)
break;
BYTE bSubStreamId = *(pBuffer + dwIndex++);
if ((bSubStreamId >> 5) != SUB_SUBSTREAM_ID)
{
// Skip number of frame headers and first access unit pointer
dwIndex += 3;
wPacketHeaderLength += 4;
DWORD shiftCount = bSubStreamId & 0x7;
DWORD newMask = 1 << shiftCount;
switch (bSubStreamId >> 3)
{
case AC3_SUBSTREAM_ID:
if (!((dwAc3Mask >> shiftCount) & 0x1))
{
dwAc3Mask = dwAc3Mask | newMask;
(*iAudio)++;
}
break;
case DTS_SUBSTREAM_ID:
if (!((dwDtsMask >> shiftCount) & 0x1))
{
dwDtsMask = dwDtsMask | newMask;
(*iAudio)++;
}
break;
case PCM_SUBSTREAM_ID:
if (!((dwPcmMask >> shiftCount) & 0x1))
{
dwPcmMask = dwPcmMask | newMask;
(*iAudio)++;
}
break;
}
}
}
else
{
DWORD shiftCount = dwCode & 0xF;
DWORD newMask = 1 << shiftCount;
if ((dwCode & 0xFFFFFFF0) == AUDIO_STREAM)
{
if (!((dwMpeg1AudioMask >> shiftCount) & 0x1))
{
dwMpeg1AudioMask = dwMpeg1AudioMask | newMask;
(*iAudio)++;
}
}
else
{
if (!((dwVideoMask >> shiftCount) & 0x1))
{
dwVideoMask = dwVideoMask | newMask;
(*iVideo)++;
}
}
}
dwIndex += (wPacketLength - wPacketHeaderLength);
dwCode = 0;
}
}
}
////////////////////////////////////////////////////////////////////
/****f* MMDemux/GetAc3SyncWordAddr
* USAGE
* BOOL SetFirstAccessUnitPtr(const unsigned char* pBuffer, unsigned long dwLength,
* BYTE* addr)
* DESCRIPTION
* Set the first access unit pointer for transport stream.
* PARAMETERS
* const unsigned char* pBuffer - buffer contains the AC3 audio payload
* unsigned long dwLength - length of the payload
* WORD* firstAccessPointer -
* RETURN VALUE
* TRUE if first access unit pointer is found
* FALSE if not.
/**********************************************************************/
BOOL SetFirstAccessUnitPtr(const unsigned char* pBuffer, unsigned long dwLength,
WORD* firstAccessPointer)
{
DWORD dwBufferIndex = 0;
WORD wSyncCode = 0;
INT iRelativeBytes = 0;
*firstAccessPointer = 0;
while (dwBufferIndex < dwLength)
{
iRelativeBytes++;
wSyncCode = (wSyncCode << 8) + *(pBuffer + dwBufferIndex++);
if ((wSyncCode & 0xFFFF) == AC3_HEADER)
{
// Found the first access unit.
*firstAccessPointer = iRelativeBytes-1;
// MmDebugLogfile((MmDebugLevelTrace, "%d", *firstAccessPointer));
return TRUE;
}
}
return FALSE;
}
////////////////////////////////////////////////////////////////////
void MMSleep(DWORD milliSeconds)
{
clock_t goal;
clock_t cur;
goal = (clock_t)milliSeconds + clock();
while (TRUE)
{
cur = clock();
if ((cur >= goal) || (cur == -1))
break;
}
}
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Defines basic file I/O functions
MM_FILE_HANDLE MMOpenFile(char* file, int options)
{
#if defined(_LINUXAPPS_) || defined(_ANSI_FILE_)
char szOpts[10];
memset(szOpts, 0, 10);
if (options & MM_RDONLY)
strcpy(szOpts, "r");
else if (options & MM_WRONLY)
strcpy(szOpts, "w");
else if (options & MM_RDWR)
strcpy(szOpts, "w+");
if (options & MM_BINARY)
strcat(szOpts, "b");
return fopen(file, szOpts);
#else
int oflag = 0;
int pmode = 0;
if (options & MM_RDONLY)
oflag = _O_RDONLY;
else if (options & MM_WRONLY)
oflag = _O_WRONLY;
else if (options & MM_RDWR)
oflag = _O_RDWR;
if (options & MM_BINARY)
oflag |= _O_BINARY;
if (options & MM_CREAT)
{
oflag |= _O_CREAT;
if (options & MM_S_IREAD)
pmode = _S_IREAD; // = 400
if (options & MM_S_IWRITE)
pmode |= _S_IWRITE; // = 200
}
return _open(file, oflag, pmode);
#endif
}
////////////////////////////////////////////////////////////////////
INT MMCloseFile(MM_FILE_HANDLE fileHandle)
{
#if defined(_LINUXAPPS_) || defined(_ANSI_FILE_)
return fclose(fileHandle);
#else
return _close(fileHandle);
#endif
}
////////////////////////////////////////////////////////////////////
LONG MMReadFile(MM_FILE_HANDLE fileHandle, void* pBuffer, UINT size)
{
#if defined(_LINUXAPPS_) || defined(_ANSI_FILE_)
return fread(pBuffer, sizeof(char), size, fileHandle);
#else
return _read(fileHandle, pBuffer, size);
#endif
}
////////////////////////////////////////////////////////////////////
LONG MMWriteFile(MM_FILE_HANDLE fileHandle, const void* pBuffer, UINT size)
{
#if defined(_LINUXAPPS_) || defined(_ANSI_FILE_)
return fwrite(pBuffer, sizeof(char), size, fileHandle);
#else
return _write(fileHandle, pBuffer, size);
#endif
}
////////////////////////////////////////////////////////////////////
LONGLONG MMSeekFile(MM_FILE_HANDLE fileHandle, LONGLONG offset, INT origin)
{
#if defined(_LINUXAPPS_) || defined(_ANSI_FILE_)
return fseek(fileHandle, (LONG)offset, origin);
#else
return _lseeki64(fileHandle, offset, origin);
#endif
}
////////////////////////////////////////////////////////////////////
LONGLONG MMTellFile(MM_FILE_HANDLE fileHandle)
{
#if defined(_LINUXAPPS_) || defined(_ANSI_FILE_)
return ftell(fileHandle);
#else
return _telli64(fileHandle);
#endif
}
////////////////////////////////////////////////////////////////////
INT MMChSize(MM_FILE_HANDLE fileHandle, LONG size)
{
#if defined(_LINUXAPPS_) || defined(_ANSI_FILE_)
return 0;
#else
return _chsize(fileHandle, size);
#endif
}
////////////////////////////////////////////////////////////////////
void MMRewindFile(MM_FILE_HANDLE fileHandle)
{
#if defined(_LINUXAPPS_) || defined(_ANSI_FILE_)
rewind(fileHandle);
#else
_lseeki64(fileHandle, 0, SEEK_SET);
#endif
}
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -