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

📄 mpgutil.cpp

📁 在vc下实现远程视频监控的基本功能的代码。
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    if (pInfo->dwBitRate == 0x3FFFF) {
        DbgLog((LOG_TRACE, 2, TEXT("Variable video bit rate")));
        pInfo->dwBitRate = 0;
    } else {
        pInfo->dwBitRate *= 400;
        DbgLog((LOG_TRACE, 2, TEXT("Video bit rate is %d bits per second"),
               pInfo->dwBitRate));
    }

#if 0
#pragma message (REMIND("Get pel aspect ratio right don't call GDI - it will create a thread!"))
    /*  Get a DC */
    HDC hdc = GetDC(GetDesktopWindow());

    ASSERT(hdc != NULL);
    /*  Guess (randomly) 39.37 inches per meter */
    LONG lNotionalPelsPerMeter = MulDiv((LONG)GetDeviceCaps(hdc, LOGICALPELSX),
                                        3937, 100);
#else
    LONG lNotionalPelsPerMeter = 2000;
#endif

    pInfo->lXPelsPerMeter = lNotionalPelsPerMeter;

    pInfo->lYPelsPerMeter = MulDiv(
                              lNotionalPelsPerMeter,
                              AspectRatios[PelAspectRatioAndPictureRate >> 4],
                              10000);
    /*  Pull out the vbv */
    pInfo->lvbv = ((((LONG)pbData[10] & 0x1F) << 5) |
             ((LONG)pbData[11] >> 3)) * 2048;

    DbgLog((LOG_TRACE, 2, TEXT("vbv size is %d bytes"), pInfo->lvbv));

    /*  Check constrained parameter stuff */
    if (pbData[11] & 0x04) {
        DbgLog((LOG_TRACE, 2, TEXT("Constrained parameter video stream")));

        if (pInfo->lvbv > 40960) {
            DbgLog((LOG_ERROR, 1, TEXT("Invalid vbv (%d) for Constrained stream"),
                    pInfo->lvbv));

            /*  Have to let this through too!  bisp.mpg has this */
            /*  But constrain it since it might be random        */
            pInfo->lvbv = 40960;
        }
    } else {
        DbgLog((LOG_TRACE, 2, TEXT("Non-Constrained parameter video stream")));
    }

    /*  tp_orig has a vbv of 2048 (!) */
    if (pInfo->lvbv < 20000) {
        DbgLog((LOG_TRACE, 2, TEXT("Small vbv (%d) - setting to 40960"),
               pInfo->lvbv));
        pInfo->lvbv = 40960;
    }

    pInfo->lActualHeaderLen = SequenceHeaderSize(pbData);
    CopyMemory((PVOID)pInfo->RawHeader, (PVOID)pbData, pInfo->lActualHeaderLen);
    return TRUE;
}

HRESULT GetVideoMediaType(CMediaType *cmt, BOOL bPayload, const SEQHDR_INFO *pInfo)
{
    cmt->majortype = MEDIATYPE_Video;
    cmt->subtype = bPayload ? MEDIASUBTYPE_MPEG1Payload :
                              MEDIASUBTYPE_MPEG1Packet;
    VIDEOINFO *videoInfo =
        (VIDEOINFO *)cmt->AllocFormatBuffer(FIELD_OFFSET(MPEG1VIDEOINFO, bSequenceHeader[pInfo->lActualHeaderLen]));
    if (videoInfo == NULL) {
        return E_OUTOFMEMORY;
    }
    RESET_HEADER(videoInfo);

    videoInfo->dwBitRate          = pInfo->dwBitRate;
    videoInfo->rcSource.right     = pInfo->lWidth;
    videoInfo->bmiHeader.biWidth  = pInfo->lWidth;
    videoInfo->rcSource.bottom    = pInfo->lHeight;
    videoInfo->bmiHeader.biHeight = pInfo->lHeight;
    videoInfo->bmiHeader.biXPelsPerMeter = pInfo->lXPelsPerMeter;
    videoInfo->bmiHeader.biYPelsPerMeter = pInfo->lYPelsPerMeter;
    videoInfo->bmiHeader.biSize   = sizeof(BITMAPINFOHEADER);

    videoInfo->AvgTimePerFrame = pInfo->tPictureTime;
    MPEG1VIDEOINFO *mpgvideoInfo = (MPEG1VIDEOINFO *)videoInfo;
    mpgvideoInfo->cbSequenceHeader = pInfo->lActualHeaderLen;
    CopyMemory((PVOID)mpgvideoInfo->bSequenceHeader,
               (PVOID)pInfo->RawHeader,
               pInfo->lActualHeaderLen);
    mpgvideoInfo->dwStartTimeCode = pInfo->dwStartTimeCode;


    cmt->SetFormatType(&FORMAT_MPEGVideo);
    return S_OK;
}

BOOL CheckAudioHeader(const BYTE * pbData)
{
    /*  Just check it's valid */
#pragma message (REMIND("Check audio header"))
    if ((pbData[2] & 0x0C) == 0x0C) {
        DbgLog((LOG_ERROR, 2, TEXT("Invalid audio sampling frequency")));
        return FALSE;
    }
    if ((pbData[1] & 0x08) != 0x08) {
        DbgLog((LOG_ERROR, 2, TEXT("Invalid audio ID bit = 0")));
        return FALSE;
    }
    if (((pbData[1] >> 1) & 3) == 0x00) {
        DbgLog((LOG_ERROR, 2, TEXT("Invalid audio Layer")));
        return FALSE;
    }

    if (((pbData[2] >> 2) & 3) == 3) {
        DbgLog((LOG_ERROR, 2, TEXT("Invalid sample rate")));
        return FALSE;
    }
    if ((pbData[2] >> 4) == 0x0F) {
        DbgLog((LOG_ERROR, 2, TEXT("Invalid bit rate")));
        return FALSE;
    }

    return TRUE;
}

LONG SampleRate(const BYTE * pbData)
{
    switch ((pbData[2] >> 2) & 3) {
        case 0:
            return 44100;

        case 1:
            return 48000;

        case 2:
            return 32000;

        default:
            DbgBreak("Unexpected Sample Rate");
            return 44100;
    }
}

BOOL ParseAudioHeader(const BYTE * pbData, MPEG1WAVEFORMAT *pFormat)
{
    if (!CheckAudioHeader(pbData)) {
        return FALSE;
    }
    pFormat->wfx.wFormatTag = WAVE_FORMAT_MPEG;

    /*  Get number of channels from Mode */
    switch (pbData[3] >> 6) {
    case 0x00:
        pFormat->fwHeadMode = ACM_MPEG_STEREO;
        break;
    case 0x01:
        pFormat->fwHeadMode = ACM_MPEG_JOINTSTEREO;
        break;
    case 0x02:
        pFormat->fwHeadMode = ACM_MPEG_DUALCHANNEL;
        break;
    case 0x03:
        pFormat->fwHeadMode = ACM_MPEG_SINGLECHANNEL;
        break;
    }
    pFormat->wfx.nChannels =
        (WORD)(pFormat->fwHeadMode == ACM_MPEG_SINGLECHANNEL ? 1 : 2);
    pFormat->fwHeadModeExt = (WORD)(1 << (pbData[3] >> 4));
    pFormat->wHeadEmphasis = (WORD)((pbData[3] & 0x03) + 1);
    pFormat->fwHeadFlags   = (WORD)(((pbData[2] & 1) ? ACM_MPEG_PRIVATEBIT : 0) +
                           ((pbData[3] & 8) ? ACM_MPEG_COPYRIGHT : 0) +
                           ((pbData[3] & 4) ? ACM_MPEG_ORIGINALHOME : 0) +
                           ((pbData[1] & 1) ? ACM_MPEG_PROTECTIONBIT : 0) +
                           ((pbData[1] & 0x08) ? ACM_MPEG_ID_MPEG1 : 0));

    int Layer;

    /*  Get the layer so we can work out the bit rate */
    switch ((pbData[1] >> 1) & 3) {
        case 3:
            pFormat->fwHeadLayer = ACM_MPEG_LAYER1;
            Layer = 1;
            break;
        case 2:
            pFormat->fwHeadLayer = ACM_MPEG_LAYER2;
            Layer = 2;
            break;
        case 1:
            pFormat->fwHeadLayer = ACM_MPEG_LAYER3;
            Layer = 3;
            break;
        case 0:
            return (FALSE);
    }

    /*  Get samples per second from sampling frequency */
    pFormat->wfx.nSamplesPerSec = SampleRate(pbData);
    pFormat->dwHeadBitrate =
        (DWORD)BitRates[Layer - 1][pbData[2] >> 4] * 1000;
    pFormat->wfx.nAvgBytesPerSec = pFormat->dwHeadBitrate / 8;

    /*  Deal with free format (!) */
#pragma message (REMIND("Handle variable bit rate (index 0)"))

    if (pFormat->wfx.nSamplesPerSec != 44100 &&
        /*  Layer 3 can sometimes switch bitrates */
        !(Layer == 3 && /* !m_pStreamList->AudioLock() && */
            (pbData[2] >> 4) == 0)) {

        if (Layer == 1) {
            pFormat->wfx.nBlockAlign = (WORD)
                (4 * ((pFormat->dwHeadBitrate * 12) / pFormat->wfx.nSamplesPerSec));
        } else {
            pFormat->wfx.nBlockAlign = (WORD)
                ((144 * pFormat->dwHeadBitrate) / pFormat->wfx.nSamplesPerSec);
        }
    } else {
        pFormat->wfx.nBlockAlign = 1;
    }


    pFormat->wfx.wBitsPerSample = 0;
    pFormat->wfx.cbSize = sizeof(MPEG1WAVEFORMAT) - sizeof(WAVEFORMATEX);

    pFormat->dwPTSLow  = 0;
    pFormat->dwPTSHigh = 0;

    return TRUE;
}

BOOL GetClock(const BYTE * pData, LONGLONG *Clock)
{
    BYTE  Byte1 = pData[0];
    DWORD Word2 = ((DWORD)pData[1] << 8) + (DWORD)pData[2];
    DWORD Word3 = ((DWORD)pData[3] << 8) + (DWORD)pData[4];

    /*  Do checks */
    if ((Byte1 & 0xE0) != 0x20 ||
        (Word2 & 1) != 1 ||
        (Word3 & 1) != 1) {
        DbgLog((LOG_TRACE, 2, TEXT("Invalid clock field - 0x%2.2X 0x%4.4X 0x%4.4X"),
            Byte1, Word2, Word3));
        return FALSE;
    }

    LARGE_INTEGER liClock;
    liClock.HighPart = (Byte1 & 8) != 0;
    liClock.LowPart  = (DWORD)((((DWORD)Byte1 & 0x6) << 29) +
                       (((DWORD)Word2 & 0xFFFE) << 14) +
                       ((DWORD)Word3 >> 1));

    *Clock = liClock.QuadPart;

    return TRUE;
}

BOOL SetClock(BYTE * pData, LONGLONG *Clock)
{
    LARGE_INTEGER liClock;
    liClock.QuadPart = *Clock;

	BYTE Byte = ((BYTE)(liClock.HighPart & 1) << 3) + 
				 ((BYTE)(liClock.LowPart >> 29) & 0x06);
	pData[0] = (pData[0] & 0xf1 ) | Byte;

	Byte = (BYTE)(liClock.LowPart >> 22);
	pData[1] = Byte;

	Byte = (BYTE)(liClock.LowPart >> 14) & 0xfe;
	pData[2] = (pData[2] & 0x01) | Byte;

	Byte = (BYTE)(liClock.LowPart >> 7);
	pData[3] = Byte;

	Byte = (BYTE)(liClock.LowPart << 1) & 0xfe;
	pData[4] = (pData[4] &0x01) | Byte;

	/*
    BYTE  Byte1 = pData[0];
    DWORD Word2 = ((DWORD)pData[1] << 8) + (DWORD)pData[2];
    DWORD Word3 = ((DWORD)pData[3] << 8) + (DWORD)pData[4];
*/
    /*  Do checks */
	/*
    if ((Byte1 & 0xE0) != 0x20 ||
        (Word2 & 1) != 1 ||
        (Word3 & 1) != 1) {
        DbgLog((LOG_TRACE, 2, TEXT("Invalid clock field - 0x%2.2X 0x%4.4X 0x%4.4X"),
            Byte1, Word2, Word3));
        return FALSE;
    }

    liClock.HighPart = (Byte1 & 8) != 0;
    liClock.LowPart  = (DWORD)((((DWORD)Byte1 & 0x6) << 29) +
                       (((DWORD)Word2 & 0xFFFE) << 14) +
                       ((DWORD)Word3 >> 1));

*/
    return TRUE;
}
/*  Find the next start code */
BOOL NextStartCode(const BYTE * *ppbData, DWORD *pdwLeft)
{
    const BYTE * pbData = *ppbData;
    DWORD dwLeft = *pdwLeft;

    while (dwLeft > 4 &&
           (*(UNALIGNED DWORD *)pbData & 0x00FFFFFF) != 0x00010000) {
        dwLeft--;
        pbData++;
    }
    *ppbData = pbData;
    *pdwLeft = dwLeft;
    return dwLeft >= 4;
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -