⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mpgutil.cpp

📁 VC++视频开发实例集锦(包括“远程视频监控”"语音识别系统"等13个经典例子)
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//==========================================================================;
//
//  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 + -