MPGUTIL.CPP
上传用户:hxb_1234
上传日期:2010-03-30
资源大小:8328k
文件大小:21k
源码类别:

VC书籍

开发平台:

Visual C++

  1. //==========================================================================;
  2. //
  3. //  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4. //  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5. //  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6. //  PURPOSE.
  7. //
  8. //  Copyright (c) 1996 - 1997  Microsoft Corporation.  All Rights Reserved.
  9. //
  10. //--------------------------------------------------------------------------;
  11. /*  MPEG 1 & 2 parsing routines */
  12. #include "stdafx.h"
  13. #include <streams.h>
  14. #include "mpegdef.h"
  15. #include <mmreg.h>
  16. #include "mpgutil.h"
  17. //#ifdef DEBUG
  18. LPCTSTR PictureTypes[8]   = { TEXT("forbidden frame type"),
  19.                               TEXT("I-Frame"),
  20.                               TEXT("P-Frame"),
  21.                               TEXT("B-Frame"),
  22.                               TEXT("D-Frame"),
  23.                               TEXT("Reserved frame type"),
  24.                               TEXT("Reserved frame type"),
  25.                               TEXT("Reserved frame type")
  26.                             };
  27. LPCTSTR PelAspectRatios[16] = { TEXT("Forbidden"),
  28.                                 TEXT("1.0000 - VGA etc"),
  29.                                 TEXT("0.6735"),
  30.                                 TEXT("0.7031 - 16:9, 625 line"),
  31.                                 TEXT("0.7615"),
  32.                                 TEXT("0.8055"),
  33.                                 TEXT("0.8437 - 16:9, 525 line"),
  34.                                 TEXT("0.8935"),
  35.                                 TEXT("0.9375 - CCIR601, 625 line"),
  36.                                 TEXT("0.9815"),
  37.                                 TEXT("1.0255"),
  38.                                 TEXT("1.0695"),
  39.                                 TEXT("1.1250 - CCIR601, 525 line"),
  40.                                 TEXT("1.1575"),
  41.                                 TEXT("1.2015"),
  42.                                 TEXT("Reserved") };
  43. LPCTSTR PictureRates[16] = { TEXT("Forbidden"),
  44.                              TEXT("23.976"),
  45.                              TEXT("24"),
  46.                              TEXT("25"),
  47.                              TEXT("29.97"),
  48.                              TEXT("30"),
  49.                              TEXT("50"),
  50.                              TEXT("59.94"),
  51.                              TEXT("60"),
  52.                              TEXT("Reserved"),
  53.                              TEXT("Reserved"),
  54.                              TEXT("Reserved"),
  55.                              TEXT("Reserved"),
  56.                              TEXT("Reserved"),
  57.                              TEXT("Reserved"),
  58.                              TEXT("Reserved") };
  59. //#endif // DBG
  60. const LONG PictureTimes[16] = { 0,
  61.                                 (LONG)((double)10000000 / 23.976),
  62.                                 (LONG)((double)10000000 / 24),
  63.                                 (LONG)((double)10000000 / 25),
  64.                                 (LONG)((double)10000000 / 29.97),
  65.                                 (LONG)((double)10000000 / 30),
  66.                                 (LONG)((double)10000000 / 50),
  67.                                 (LONG)((double)10000000 / 59.94),
  68.                                 (LONG)((double)10000000 / 60)
  69.                               };
  70. const float fPictureRates[] =
  71.    {
  72.      (float)0,
  73.      (float)23.976,
  74.      (float)24,
  75.      (float)25,
  76.      (float)29.97,
  77.      (float)30,
  78.      (float)50,
  79.      (float)59.94,
  80.      (float)60.0
  81.    };
  82. const LONG AspectRatios[16] = { 0,
  83.                                 393700,
  84.                                 (LONG)(393700.0 * 0.6735),
  85.                                 (LONG)(393700.0 * 0.7031),
  86.                                 (LONG)(393700.0 * 0.7615),
  87.                                 (LONG)(393700.0 * 0.8055),
  88.                                 (LONG)(393700.0 * 0.8437),
  89.                                 (LONG)(393700.0 * 0.8935),
  90.                                 (LONG)(393700.0 * 0.9375),
  91.                                 (LONG)(393700.0 * 0.9815),
  92.                                 (LONG)(393700.0 * 1.0255),
  93.                                 (LONG)(393700.0 * 1.0695),
  94.                                 (LONG)(393700.0 * 1.1250),
  95.                                 (LONG)(393700.0 * 1.1575),
  96.                                 (LONG)(393700.0 * 1.2015),
  97.                                 0
  98.                               };
  99. /*  Bit rate tables */
  100. const WORD BitRates[3][16] =
  101. {{  0, 32,  64,  96,  128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0 },
  102.  {  0, 32,  48,  56,   64,  80,  96, 112, 128, 160, 192, 224, 256, 320, 384, 0 },
  103.  {  0, 32,  40,  48,   56,  64,  80,  96, 112, 128, 160, 192, 224, 256, 320, 0 }
  104. };
  105. BOOL inline TESTBIT(const BYTE * pbData, int n)
  106. {
  107.     return 0 != (pbData[n >> 3] & (0x80 >> (n & 7)));
  108. }
  109. /*  Parse system header
  110.     Parameters :
  111.         pbData - pointer to data containing the system header
  112.         cbData - length of data
  113.     Returns :
  114.         Number of bytes processed (0 if the header doesn't fit
  115.         in the data or 4 if the header is invalid)
  116. */
  117. LONG ParseSystemHeader(const BYTE * pbData, DWORD cbData)
  118. {
  119.     BOOL bHasAudio = FALSE;
  120.     BOOL bHasVideo = FALSE;
  121.     ASSERT(cbData >= 4);
  122.     ASSERT(*(UNALIGNED DWORD *)pbData == DWORD_SWAP(SYSTEM_HEADER_START_CODE));
  123.     /*  Checkt the length */
  124.     if (cbData < 6) {
  125.         return 0;
  126.     }
  127.     DWORD dwLen = 6 + pbData[5] + (pbData[4] << 8);
  128.     if (dwLen < SYSTEM_HEADER_BASIC_LENGTH) {
  129.         DbgLog((LOG_ERROR, 1, TEXT("Invalid System Header length")));
  130.         return 4;
  131.     }
  132.     if (cbData < dwLen) {
  133.         return 0;
  134.     }
  135.     /*  Check the marker bits */
  136.     if (0 == (pbData[6] & 0x80) ||
  137.         0 == (pbData[8] & 0x01) ||
  138.         0 == (pbData[10] & 0x20)) {
  139.         DbgLog((LOG_ERROR, 1, TEXT("Invalid System Header Marker bits")));
  140.         return 4;
  141.     }
  142.     /*  Parse the 'buffer bounds and scale' list */
  143.     const BYTE * pbNext = pbData + SYSTEM_HEADER_BASIC_LENGTH;
  144.     DWORD cbLeft = dwLen - SYSTEM_HEADER_BASIC_LENGTH;
  145.     for ( ; cbLeft >= 3; cbLeft -= 3, pbNext += 3) {
  146.         if (pbNext[0] == AUDIO_GLOBAL) {
  147.             bHasAudio = TRUE;
  148.         } else
  149.         if (pbNext[0] == VIDEO_GLOBAL) {
  150.             bHasVideo = TRUE;
  151.         } else {
  152.             if (pbNext[0] < PROGRAM_STREAM_MAP) {
  153.                 DbgLog((LOG_ERROR, 1, TEXT("Invalid stream id in system header")));
  154.                 return 4;
  155.             }
  156.             if (IsVideoStreamId(pbNext[0])) {
  157.                 bHasVideo = TRUE;
  158.             } else
  159.             if (IsAudioStreamId(pbNext[0])) {
  160.                 bHasAudio = TRUE;
  161.             }
  162.         }
  163.     }
  164.     if (cbLeft != 0) {
  165.         DbgLog((LOG_ERROR, 1, TEXT("Invalid system header length")));
  166.         return 4;
  167.     }
  168.     DbgLog((LOG_TRACE, 4, TEXT("System Header %s, %s"),
  169.             bHasAudio ? TEXT("audio") : TEXT("No audio"),
  170.             bHasVideo ? TEXT("video") : TEXT("No video")));
  171.     return dwLen;
  172. }
  173. /*  Parse an MPEG-1 packet */
  174. DWORD ParseMPEG1Packet(
  175.     const BYTE * pbData,
  176.     DWORD cbData,
  177.     MPEG_PACKET_DATA *pPacketData,
  178. DWORD * Pts
  179. )
  180. {
  181.     ZeroMemory((PVOID)pPacketData, sizeof(*pPacketData));
  182.     DWORD dwStartCode = DWORD_SWAP(*(UNALIGNED DWORD *)pbData);
  183.     DbgLog((LOG_TRACE, 4, TEXT("Parse packet %d bytes"), cbData));
  184.     /*  Send it to the right stream */
  185.     if (cbData < 6) {
  186.         return 0;
  187.     }
  188.     /*  Find the length */
  189.     DWORD dwLen = ((LONG)pbData[4] << 8) + (LONG)pbData[5] + 6;
  190.     DbgLog((LOG_TRACE, 4, TEXT("Packet length %d bytes"), dwLen));
  191.     if (dwLen > cbData) {
  192.         return 0;
  193.     }
  194.     pPacketData->dwPacketLen = dwLen;
  195.     /*  Pull out PTS if any */
  196.     DWORD dwHeaderSize = 6;
  197.     if (dwStartCode != PRIVATE_STREAM_2) {
  198.         DWORD dwPts = 6;
  199.         for (;;) {
  200.             if (dwPts >= dwLen) {
  201.                 return 4;
  202.             }
  203.             if (pbData[dwPts] & 0x80) {
  204.                 /*  Stuffing byte */
  205.                 if (pbData[dwPts] != 0xFF) {
  206.                     return 4;
  207.                 }
  208.                 dwPts++;
  209.                 continue;
  210.             }
  211.             /*  Check for STD (nextbits == '01') -
  212.                 we know the next bit is 0 so check the next one after that
  213.             */
  214.             if (pbData[dwPts] & 0x40) { // STD stuff
  215.                 dwPts += 2;
  216.                 continue;
  217.             }
  218.             /*  No PTS - normal case */
  219.             if (pbData[dwPts] == 0x0F) {
  220.                 dwHeaderSize = dwPts + 1;
  221.                 break;
  222.             }
  223.             if ((pbData[dwPts] & 0xF0) == 0x20 ||
  224.                 (pbData[dwPts] & 0xF0) == 0x30) {
  225.                 /*  PTS or PTS and DTS */
  226.                 dwHeaderSize = (pbData[dwPts] & 0xF0) == 0x20 ? dwPts + 5 :
  227.                                                              dwPts + 10;
  228.                 if (dwHeaderSize > dwLen) {
  229.                     return 4;
  230.                 }
  231.                 if (!GetClock(pbData + dwPts, &pPacketData->llPts)) {
  232. *Pts = dwPts;
  233.                     return 4;
  234.                 }
  235.                 pPacketData->bHasPts = TRUE;
  236.                 break;
  237.             } else {
  238.                 return 4;
  239.                 break;
  240.             }
  241.         }
  242.     }
  243.     pPacketData->dwHeaderLen = dwHeaderSize;
  244.     return dwLen;
  245. }
  246. BOOL ParseSequenceHeader(const BYTE *pbData, LONG lData, SEQHDR_INFO *pInfo)
  247. {
  248.     ASSERT(*(UNALIGNED DWORD *)pbData == DWORD_SWAP(SEQUENCE_HEADER_CODE));
  249.     /*  Check random marker bit */
  250.     if (!(pbData[10] & 0x20)) {
  251.         DbgLog((LOG_ERROR, 2, TEXT("Sequence header invalid marker bit")));
  252.         return FALSE;
  253.     }
  254.     DWORD dwWidthAndHeight = ((DWORD)pbData[4] << 16) +
  255.                              ((DWORD)pbData[5] << 8) +
  256.                              ((DWORD)pbData[6]);
  257.     pInfo->lWidth = dwWidthAndHeight >> 12;
  258.     pInfo->lHeight = dwWidthAndHeight & 0xFFF;
  259.     DbgLog((LOG_TRACE, 2, TEXT("Width = %d, Height = %d"),
  260.         pInfo->lWidth,
  261.         pInfo->lHeight));
  262.     /* the '8' bit is the scramble flag used by sigma designs - ignore */
  263.     BYTE PelAspectRatioAndPictureRate = pbData[7];
  264.     if ((PelAspectRatioAndPictureRate & 0x0F) > 8) {
  265.         PelAspectRatioAndPictureRate &= 0xF7;
  266.     }
  267.     DbgLog((LOG_TRACE, 2, TEXT("Pel Aspect Ratio = %s"),
  268.         PelAspectRatios[PelAspectRatioAndPictureRate >> 4]));
  269.     DbgLog((LOG_TRACE, 2, TEXT("Picture Rate = %s"),
  270.         PictureRates[PelAspectRatioAndPictureRate & 0x0F]));
  271.     if ((PelAspectRatioAndPictureRate & 0xF0) == 0 ||
  272.         (PelAspectRatioAndPictureRate & 0x0F) == 0) {
  273.         DbgLog((LOG_ERROR, 2, TEXT("Sequence header invalid ratio/rate")));
  274.         return FALSE;
  275.     }
  276.     pInfo->tPictureTime = (LONGLONG)PictureTimes[PelAspectRatioAndPictureRate & 0x0F];
  277.     pInfo->fPictureRate = fPictureRates[PelAspectRatioAndPictureRate & 0x0F];
  278.     pInfo->lTimePerFrame = MulDiv((LONG)pInfo->tPictureTime, 9, 1000);
  279.     /*  Pull out the bit rate and aspect ratio for the type */
  280.     pInfo->dwBitRate = ((((DWORD)pbData[8] << 16) +
  281.                    ((DWORD)pbData[9] << 8) +
  282.                    (DWORD)pbData[10]) >> 6);
  283.     if (pInfo->dwBitRate == 0x3FFFF) {
  284.         DbgLog((LOG_TRACE, 2, TEXT("Variable video bit rate")));
  285.         pInfo->dwBitRate = 0;
  286.     } else {
  287.         pInfo->dwBitRate *= 400;
  288.         DbgLog((LOG_TRACE, 2, TEXT("Video bit rate is %d bits per second"),
  289.                pInfo->dwBitRate));
  290.     }
  291. #if 0
  292. #pragma message (REMIND("Get pel aspect ratio right don't call GDI - it will create a thread!"))
  293.     /*  Get a DC */
  294.     HDC hdc = GetDC(GetDesktopWindow());
  295.     ASSERT(hdc != NULL);
  296.     /*  Guess (randomly) 39.37 inches per meter */
  297.     LONG lNotionalPelsPerMeter = MulDiv((LONG)GetDeviceCaps(hdc, LOGICALPELSX),
  298.                                         3937, 100);
  299. #else
  300.     LONG lNotionalPelsPerMeter = 2000;
  301. #endif
  302.     pInfo->lXPelsPerMeter = lNotionalPelsPerMeter;
  303.     pInfo->lYPelsPerMeter = MulDiv(
  304.                               lNotionalPelsPerMeter,
  305.                               AspectRatios[PelAspectRatioAndPictureRate >> 4],
  306.                               10000);
  307.     /*  Pull out the vbv */
  308.     pInfo->lvbv = ((((LONG)pbData[10] & 0x1F) << 5) |
  309.              ((LONG)pbData[11] >> 3)) * 2048;
  310.     DbgLog((LOG_TRACE, 2, TEXT("vbv size is %d bytes"), pInfo->lvbv));
  311.     /*  Check constrained parameter stuff */
  312.     if (pbData[11] & 0x04) {
  313.         DbgLog((LOG_TRACE, 2, TEXT("Constrained parameter video stream")));
  314.         if (pInfo->lvbv > 40960) {
  315.             DbgLog((LOG_ERROR, 1, TEXT("Invalid vbv (%d) for Constrained stream"),
  316.                     pInfo->lvbv));
  317.             /*  Have to let this through too!  bisp.mpg has this */
  318.             /*  But constrain it since it might be random        */
  319.             pInfo->lvbv = 40960;
  320.         }
  321.     } else {
  322.         DbgLog((LOG_TRACE, 2, TEXT("Non-Constrained parameter video stream")));
  323.     }
  324.     /*  tp_orig has a vbv of 2048 (!) */
  325.     if (pInfo->lvbv < 20000) {
  326.         DbgLog((LOG_TRACE, 2, TEXT("Small vbv (%d) - setting to 40960"),
  327.                pInfo->lvbv));
  328.         pInfo->lvbv = 40960;
  329.     }
  330.     pInfo->lActualHeaderLen = SequenceHeaderSize(pbData);
  331.     CopyMemory((PVOID)pInfo->RawHeader, (PVOID)pbData, pInfo->lActualHeaderLen);
  332.     return TRUE;
  333. }
  334. HRESULT GetVideoMediaType(CMediaType *cmt, BOOL bPayload, const SEQHDR_INFO *pInfo)
  335. {
  336.     cmt->majortype = MEDIATYPE_Video;
  337.     cmt->subtype = bPayload ? MEDIASUBTYPE_MPEG1Payload :
  338.                               MEDIASUBTYPE_MPEG1Packet;
  339.     VIDEOINFO *videoInfo =
  340.         (VIDEOINFO *)cmt->AllocFormatBuffer(FIELD_OFFSET(MPEG1VIDEOINFO, bSequenceHeader[pInfo->lActualHeaderLen]));
  341.     if (videoInfo == NULL) {
  342.         return E_OUTOFMEMORY;
  343.     }
  344.     RESET_HEADER(videoInfo);
  345.     videoInfo->dwBitRate          = pInfo->dwBitRate;
  346.     videoInfo->rcSource.right     = pInfo->lWidth;
  347.     videoInfo->bmiHeader.biWidth  = pInfo->lWidth;
  348.     videoInfo->rcSource.bottom    = pInfo->lHeight;
  349.     videoInfo->bmiHeader.biHeight = pInfo->lHeight;
  350.     videoInfo->bmiHeader.biXPelsPerMeter = pInfo->lXPelsPerMeter;
  351.     videoInfo->bmiHeader.biYPelsPerMeter = pInfo->lYPelsPerMeter;
  352.     videoInfo->bmiHeader.biSize   = sizeof(BITMAPINFOHEADER);
  353.     videoInfo->AvgTimePerFrame = pInfo->tPictureTime;
  354.     MPEG1VIDEOINFO *mpgvideoInfo = (MPEG1VIDEOINFO *)videoInfo;
  355.     mpgvideoInfo->cbSequenceHeader = pInfo->lActualHeaderLen;
  356.     CopyMemory((PVOID)mpgvideoInfo->bSequenceHeader,
  357.                (PVOID)pInfo->RawHeader,
  358.                pInfo->lActualHeaderLen);
  359.     mpgvideoInfo->dwStartTimeCode = pInfo->dwStartTimeCode;
  360.     cmt->SetFormatType(&FORMAT_MPEGVideo);
  361.     return S_OK;
  362. }
  363. BOOL CheckAudioHeader(const BYTE * pbData)
  364. {
  365.     /*  Just check it's valid */
  366. #pragma message (REMIND("Check audio header"))
  367.     if ((pbData[2] & 0x0C) == 0x0C) {
  368.         DbgLog((LOG_ERROR, 2, TEXT("Invalid audio sampling frequency")));
  369.         return FALSE;
  370.     }
  371.     if ((pbData[1] & 0x08) != 0x08) {
  372.         DbgLog((LOG_ERROR, 2, TEXT("Invalid audio ID bit = 0")));
  373.         return FALSE;
  374.     }
  375.     if (((pbData[1] >> 1) & 3) == 0x00) {
  376.         DbgLog((LOG_ERROR, 2, TEXT("Invalid audio Layer")));
  377.         return FALSE;
  378.     }
  379.     if (((pbData[2] >> 2) & 3) == 3) {
  380.         DbgLog((LOG_ERROR, 2, TEXT("Invalid sample rate")));
  381.         return FALSE;
  382.     }
  383.     if ((pbData[2] >> 4) == 0x0F) {
  384.         DbgLog((LOG_ERROR, 2, TEXT("Invalid bit rate")));
  385.         return FALSE;
  386.     }
  387.     return TRUE;
  388. }
  389. LONG SampleRate(const BYTE * pbData)
  390. {
  391.     switch ((pbData[2] >> 2) & 3) {
  392.         case 0:
  393.             return 44100;
  394.         case 1:
  395.             return 48000;
  396.         case 2:
  397.             return 32000;
  398.         default:
  399.             DbgBreak("Unexpected Sample Rate");
  400.             return 44100;
  401.     }
  402. }
  403. BOOL ParseAudioHeader(const BYTE * pbData, MPEG1WAVEFORMAT *pFormat)
  404. {
  405.     if (!CheckAudioHeader(pbData)) {
  406.         return FALSE;
  407.     }
  408.     pFormat->wfx.wFormatTag = WAVE_FORMAT_MPEG;
  409.     /*  Get number of channels from Mode */
  410.     switch (pbData[3] >> 6) {
  411.     case 0x00:
  412.         pFormat->fwHeadMode = ACM_MPEG_STEREO;
  413.         break;
  414.     case 0x01:
  415.         pFormat->fwHeadMode = ACM_MPEG_JOINTSTEREO;
  416.         break;
  417.     case 0x02:
  418.         pFormat->fwHeadMode = ACM_MPEG_DUALCHANNEL;
  419.         break;
  420.     case 0x03:
  421.         pFormat->fwHeadMode = ACM_MPEG_SINGLECHANNEL;
  422.         break;
  423.     }
  424.     pFormat->wfx.nChannels =
  425.         (WORD)(pFormat->fwHeadMode == ACM_MPEG_SINGLECHANNEL ? 1 : 2);
  426.     pFormat->fwHeadModeExt = (WORD)(1 << (pbData[3] >> 4));
  427.     pFormat->wHeadEmphasis = (WORD)((pbData[3] & 0x03) + 1);
  428.     pFormat->fwHeadFlags   = (WORD)(((pbData[2] & 1) ? ACM_MPEG_PRIVATEBIT : 0) +
  429.                            ((pbData[3] & 8) ? ACM_MPEG_COPYRIGHT : 0) +
  430.                            ((pbData[3] & 4) ? ACM_MPEG_ORIGINALHOME : 0) +
  431.                            ((pbData[1] & 1) ? ACM_MPEG_PROTECTIONBIT : 0) +
  432.                            ((pbData[1] & 0x08) ? ACM_MPEG_ID_MPEG1 : 0));
  433.     int Layer;
  434.     /*  Get the layer so we can work out the bit rate */
  435.     switch ((pbData[1] >> 1) & 3) {
  436.         case 3:
  437.             pFormat->fwHeadLayer = ACM_MPEG_LAYER1;
  438.             Layer = 1;
  439.             break;
  440.         case 2:
  441.             pFormat->fwHeadLayer = ACM_MPEG_LAYER2;
  442.             Layer = 2;
  443.             break;
  444.         case 1:
  445.             pFormat->fwHeadLayer = ACM_MPEG_LAYER3;
  446.             Layer = 3;
  447.             break;
  448.         case 0:
  449.             return (FALSE);
  450.     }
  451.     /*  Get samples per second from sampling frequency */
  452.     pFormat->wfx.nSamplesPerSec = SampleRate(pbData);
  453.     pFormat->dwHeadBitrate =
  454.         (DWORD)BitRates[Layer - 1][pbData[2] >> 4] * 1000;
  455.     pFormat->wfx.nAvgBytesPerSec = pFormat->dwHeadBitrate / 8;
  456.     /*  Deal with free format (!) */
  457. #pragma message (REMIND("Handle variable bit rate (index 0)"))
  458.     if (pFormat->wfx.nSamplesPerSec != 44100 &&
  459.         /*  Layer 3 can sometimes switch bitrates */
  460.         !(Layer == 3 && /* !m_pStreamList->AudioLock() && */
  461.             (pbData[2] >> 4) == 0)) {
  462.         if (Layer == 1) {
  463.             pFormat->wfx.nBlockAlign = (WORD)
  464.                 (4 * ((pFormat->dwHeadBitrate * 12) / pFormat->wfx.nSamplesPerSec));
  465.         } else {
  466.             pFormat->wfx.nBlockAlign = (WORD)
  467.                 ((144 * pFormat->dwHeadBitrate) / pFormat->wfx.nSamplesPerSec);
  468.         }
  469.     } else {
  470.         pFormat->wfx.nBlockAlign = 1;
  471.     }
  472.     pFormat->wfx.wBitsPerSample = 0;
  473.     pFormat->wfx.cbSize = sizeof(MPEG1WAVEFORMAT) - sizeof(WAVEFORMATEX);
  474.     pFormat->dwPTSLow  = 0;
  475.     pFormat->dwPTSHigh = 0;
  476.     return TRUE;
  477. }
  478. BOOL GetClock(const BYTE * pData, LONGLONG *Clock)
  479. {
  480.     BYTE  Byte1 = pData[0];
  481.     DWORD Word2 = ((DWORD)pData[1] << 8) + (DWORD)pData[2];
  482.     DWORD Word3 = ((DWORD)pData[3] << 8) + (DWORD)pData[4];
  483.     /*  Do checks */
  484.     if ((Byte1 & 0xE0) != 0x20 ||
  485.         (Word2 & 1) != 1 ||
  486.         (Word3 & 1) != 1) {
  487.         DbgLog((LOG_TRACE, 2, TEXT("Invalid clock field - 0x%2.2X 0x%4.4X 0x%4.4X"),
  488.             Byte1, Word2, Word3));
  489.         return FALSE;
  490.     }
  491.     LARGE_INTEGER liClock;
  492.     liClock.HighPart = (Byte1 & 8) != 0;
  493.     liClock.LowPart  = (DWORD)((((DWORD)Byte1 & 0x6) << 29) +
  494.                        (((DWORD)Word2 & 0xFFFE) << 14) +
  495.                        ((DWORD)Word3 >> 1));
  496.     *Clock = liClock.QuadPart;
  497.     return TRUE;
  498. }
  499. BOOL SetClock(BYTE * pData, LONGLONG *Clock)
  500. {
  501.     LARGE_INTEGER liClock;
  502.     liClock.QuadPart = *Clock;
  503. BYTE Byte = ((BYTE)(liClock.HighPart & 1) << 3) + 
  504.  ((BYTE)(liClock.LowPart >> 29) & 0x06);
  505. pData[0] = (pData[0] & 0xf1 ) | Byte;
  506. Byte = (BYTE)(liClock.LowPart >> 22);
  507. pData[1] = Byte;
  508. Byte = (BYTE)(liClock.LowPart >> 14) & 0xfe;
  509. pData[2] = (pData[2] & 0x01) | Byte;
  510. Byte = (BYTE)(liClock.LowPart >> 7);
  511. pData[3] = Byte;
  512. Byte = (BYTE)(liClock.LowPart << 1) & 0xfe;
  513. pData[4] = (pData[4] &0x01) | Byte;
  514. /*
  515.     BYTE  Byte1 = pData[0];
  516.     DWORD Word2 = ((DWORD)pData[1] << 8) + (DWORD)pData[2];
  517.     DWORD Word3 = ((DWORD)pData[3] << 8) + (DWORD)pData[4];
  518. */
  519.     /*  Do checks */
  520. /*
  521.     if ((Byte1 & 0xE0) != 0x20 ||
  522.         (Word2 & 1) != 1 ||
  523.         (Word3 & 1) != 1) {
  524.         DbgLog((LOG_TRACE, 2, TEXT("Invalid clock field - 0x%2.2X 0x%4.4X 0x%4.4X"),
  525.             Byte1, Word2, Word3));
  526.         return FALSE;
  527.     }
  528.     liClock.HighPart = (Byte1 & 8) != 0;
  529.     liClock.LowPart  = (DWORD)((((DWORD)Byte1 & 0x6) << 29) +
  530.                        (((DWORD)Word2 & 0xFFFE) << 14) +
  531.                        ((DWORD)Word3 >> 1));
  532. */
  533.     return TRUE;
  534. }
  535. /*  Find the next start code */
  536. BOOL NextStartCode(const BYTE * *ppbData, DWORD *pdwLeft)
  537. {
  538.     const BYTE * pbData = *ppbData;
  539.     DWORD dwLeft = *pdwLeft;
  540.     while (dwLeft > 4 &&
  541.            (*(UNALIGNED DWORD *)pbData & 0x00FFFFFF) != 0x00010000) {
  542.         dwLeft--;
  543.         pbData++;
  544.     }
  545.     *ppbData = pbData;
  546.     *pdwLeft = dwLeft;
  547.     return dwLeft >= 4;
  548. }