home *** CD-ROM | disk | FTP | other *** search
/ The Net: Ultimate Internet Guide / WWLCD1.ISO / mac / SiteBldr / AMOVIE / SDK / _SETUP / COMMON.Z / mpgaudio.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-19  |  33.8 KB  |  1,211 lines

  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) 1992 - 1996  Microsoft Corporation.  All Rights Reserved.
  9. //
  10. //--------------------------------------------------------------------------;
  11. //
  12. /******************************Module*Header*******************************\
  13. * Module Name: MpgAudio.cpp
  14. *
  15. * Implements a prototype Mpeg Audio Software codec.  It just consume
  16. * the passed in packets.
  17. *
  18. *
  19. \**************************************************************************/
  20.  
  21. #include "MpgAudio.h"
  22.  
  23. // define the GUIDs for streams and my CLSID in this file
  24. #include <initguid.h>
  25.  
  26. #include "MpegUids.h"
  27.  
  28. // setup data
  29.  
  30. AMOVIESETUP_MEDIATYPE psudIpPinTypes[] = { { &MEDIATYPE_Audio                // clsMajorType
  31.                                            , &MEDIASUBTYPE_MPEG1Packet  }    // clsMinorType
  32.                                          , { &MEDIATYPE_Audio                // clsMajorType
  33.                                            , &MEDIASUBTYPE_MPEG1Payload }    // clsMinorType
  34.                                          , { &MEDIATYPE_Stream               // clsMajorType
  35.                                            , &MEDIASUBTYPE_MPEG1Audio   } }; // clsMinorType
  36.  
  37. AMOVIESETUP_MEDIATYPE sudOpPinTypes = { &MEDIATYPE_Audio      // clsMajorType
  38.                                       , &MEDIASUBTYPE_NULL }; // clsMinorType
  39.  
  40. AMOVIESETUP_PIN psudPins[] = { { L"Input"            // strName
  41.                                , FALSE               // bRendered
  42.                                , FALSE               // bOutput
  43.                                , FALSE               // bZero
  44.                                , FALSE               // bMany
  45.                                , &CLSID_NULL         // clsConnectsToFilter
  46.                                , L"Output"           // strConnectsToPin
  47.                                , 3                   // nTypes
  48.                                , psudIpPinTypes }    // lpTypes
  49.                              , { L"Output"           // strName
  50.                                , FALSE               // bRendered
  51.                                , TRUE                // bOutput
  52.                                , FALSE               // bZero
  53.                                , FALSE               // bMany
  54.                                , &CLSID_NULL         // clsConnectsToFilter
  55.                                , L"Input"            // strConnectsToPin
  56.                                , 1                   // nTypes
  57.                                , &sudOpPinTypes } }; // lpTypes
  58.  
  59.  
  60.  
  61. AMOVIESETUP_FILTER sudMPEGAudio = { &CLSID_CMpegFrameworkAudioCodec // clsID
  62.                                   , L"MPEG Framework Audio Codec"   // strName
  63.                                   , 0x00680000                      // dwMerit
  64.                                   , 2                               // nPins
  65.                                   , psudPins };                     // lpPin
  66.  
  67.  
  68. /* -------------------------------------------------------------------------
  69. ** list of class ids and creator functions for class factory
  70. ** -------------------------------------------------------------------------
  71. */
  72. CFactoryTemplate g_Templates[] = {
  73.     {L"MPEG Framework Audio Codec", &CLSID_CMpegFrameworkAudioCodec, CMpegAudioCodec::CreateInstance, NULL},
  74. };
  75. int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
  76.  
  77.  
  78. /* -------------------------------------------------------------------------
  79. ** Decoder strings
  80. ** -------------------------------------------------------------------------
  81. */
  82. const TCHAR chAudioChannels[]      = TEXT("AudioChannels");
  83. const TCHAR chAudioFreqDivider[]   = TEXT("AudioFreqDivider");
  84. const TCHAR chAudioQuality[]       = TEXT("AudioQuality");
  85. const TCHAR chAudioQuarterInt[]    = TEXT("AudioQuarterInt");
  86. const TCHAR chAudioBits[]          = TEXT("AudioBits");
  87.  
  88.  
  89.  
  90. // --- CMpegAudioCodec ----------------------------------------
  91. CMpegAudioCodec::CMpegAudioCodec(TCHAR *pName, LPUNKNOWN pUnk, HRESULT *phr)
  92.     : CTransformFilter(pName, pUnk, CLSID_CMpegAudioCodec, phr),
  93.     m_pAudioDecoder(NULL)
  94. {
  95.     m_FreqDiv  = GetDecoderInteger(chAudioFreqDivider, 4);
  96.     m_PrefChan = GetDecoderInteger(chAudioChannels, 1);
  97.     m_Quality  = GetDecoderInteger(chAudioQuality, 0);
  98.     m_QuarterInt = GetDecoderInteger(chAudioQuarterInt, 0);
  99.     m_WordSize = GetDecoderInteger(chAudioBits, 16);
  100.     if (m_QuarterInt) {
  101.         m_FreqDiv = 4;
  102.     }
  103. }
  104.  
  105. CMpegAudioCodec::~CMpegAudioCodec()
  106. {
  107.     delete m_pAudioDecoder;
  108.     m_pAudioDecoder = NULL;
  109. }
  110.  
  111.  
  112. /******************************Public*Routine******************************\
  113. * CreateInstance
  114. *
  115. * this goes in the factory template table to create new instances
  116. *
  117. *
  118. \**************************************************************************/
  119. CUnknown *
  120. CMpegAudioCodec::CreateInstance(
  121.     LPUNKNOWN pUnk,
  122.     HRESULT *phr
  123.     )
  124. {
  125.     DbgLog((LOG_TRACE, 2, TEXT("CMpegAudioCodec::CreateInstance")));
  126.     return new CMpegAudioCodec(TEXT("MPEG Audio Codec Filter"), pUnk, phr);
  127. }
  128.  
  129.  
  130. /******************************Public*Routine******************************\
  131. * NonDelegatingQueryInterface
  132. *
  133. * Reveals ISpecifyPropertyPages
  134. *
  135. *
  136. \**************************************************************************/
  137. STDMETHODIMP
  138. CMpegAudioCodec::NonDelegatingQueryInterface(
  139.     REFIID riid,
  140.     void ** ppv
  141.     )
  142. {
  143.     return CTransformFilter::NonDelegatingQueryInterface(riid, ppv);
  144. }
  145.  
  146.  
  147. /******************************Public*Routine******************************\
  148. * EndOfStream
  149. *
  150. *
  151. \**************************************************************************/
  152. HRESULT
  153. CMpegAudioCodec::EndOfStream()
  154. {
  155.     DbgLog((LOG_TRACE, 2, TEXT("End of stream called")));
  156.     CAutoLock lck(&m_csReceive);
  157.  
  158.     //
  159.     // Here we would normally decode the remainder of the buffer.  However,
  160.     // the audio codec is designed such that its buffer never contains
  161.     // any full frames of coded data, so all we have to do is reset the
  162.     // audio codec.
  163.     //
  164.  
  165.     if (m_pAudioDecoder == NULL) {
  166.         return VFW_E_WRONG_STATE;
  167.     }
  168.  
  169.     ResetAudioDecoder();
  170.     return CTransformFilter::EndOfStream();
  171. }
  172.  
  173.  
  174. /******************************Public*Routine******************************\
  175. * EndFlush
  176. *
  177. *
  178. \**************************************************************************/
  179. HRESULT
  180. CMpegAudioCodec::EndFlush()
  181. {
  182.     DbgLog((LOG_TRACE, 2, TEXT("End flush called")));
  183.     CAutoLock lck(&m_csReceive);
  184.  
  185.     ResetAudioDecoder();
  186.     return CTransformFilter::EndFlush();
  187. }
  188.  
  189.  
  190. /*****************************Private*Routine******************************\
  191. * ProcessDiscontiuity
  192. *
  193. *
  194. \**************************************************************************/
  195. void
  196. CMpegAudioCodec::ProcessDiscontiuity(
  197.     IMediaSample *pSample
  198.     )
  199. {
  200.     ResetAudioDecoder();
  201.  
  202.     //
  203.     //  Find out what the current stop time is
  204.     //
  205.  
  206.     //
  207.     //  Get logical duration from upstream
  208.     //
  209.     REFTIME dStart, dStop;
  210.     IMediaPosition *pPosition;
  211.  
  212.     if (SUCCEEDED(m_pInput->GetConnected()->QueryInterface(IID_IMediaPosition,
  213.                      (void **)&pPosition))
  214.      && SUCCEEDED(pPosition->get_CurrentPosition(&dStart))
  215.      && SUCCEEDED(pPosition->get_StopTime(&dStop)))
  216.     {
  217.         m_tStop = (CRefTime)(COARefTime)dStop - (CRefTime)(COARefTime)dStart;
  218.     }
  219.     else {
  220.         m_tStop = 0x7FFFFFFFFFFFFFFF;
  221.     }
  222.  
  223.     if (pPosition != NULL) {
  224.         pPosition->Release();
  225.     }
  226.  
  227.     DbgLog((LOG_TRACE, 2,
  228.            TEXT("Receive() : Discontinuity - setting stop time to %s"),
  229.            (LPCTSTR)CDisp(m_tStop)));
  230. }
  231.  
  232.  
  233. /*****************************Private*Routine******************************\
  234. * ProcessSyncPoint
  235. *
  236. *
  237. \**************************************************************************/
  238. void
  239. CMpegAudioCodec::ProcessSyncPoint(
  240.     IMediaSample *pSample,
  241.     BYTE *pSrc
  242.     )
  243. {
  244.     CRefTime  tStart, tStop;
  245.  
  246.     pSample->GetTime((REFERENCE_TIME*)&tStart,
  247.                      (REFERENCE_TIME*)&tStop);
  248.  
  249.     m_TimeAtLastSyncPoint = tStart;
  250.     m_TimeSinceLastSyncPoint = 0;
  251.  
  252.     //
  253.     // If our buffer contains a partial audio frame adjust the
  254.     // sync point time by one frame.  Note that LookForSyncWord advances
  255.     // the m_lpCurr buffer pointer, if there is no sync word found
  256.     // m_lpCurr should equal m_lpEnd, if the last byte in our audio buffer
  257.     // is the first byte of the audio sync word m_lpCurr will equal
  258.     // m_lpEnd - 1.
  259.     // This can fail because sync words can be found other than at
  260.     // frame start!
  261.     //
  262.     if (LookForSyncWord()) {
  263.         m_TimeAtLastSyncPoint -= m_TimePerFrame;
  264.     }
  265.     else {
  266.  
  267.         ASSERT(m_lpCurr <= m_lpEnd);
  268.  
  269.         //
  270.         // Now check that there was not a pertial sync word left in our
  271.         // buffer.
  272.         //
  273.         if (m_lpCurr < m_lpEnd) {
  274.             if ((*m_lpCurr == 0xFF) && (pSrc[0] & 0xF0) == 0xF0) {
  275.                 m_TimeAtLastSyncPoint -= m_TimePerFrame;
  276.             }
  277.         }
  278.     }
  279. }
  280.  
  281.  
  282.  
  283. /*****************************Private*Routine******************************\
  284. * DeliverSample
  285. *
  286. *
  287. \**************************************************************************/
  288. HRESULT
  289. CMpegAudioCodec::DeliverSample(
  290.     IMediaSample *pOutSample,
  291.     CRefTime &TimeDecoded,
  292.     int nActBytesWritten
  293.     )
  294. {
  295.     CRefTime tStart, tStop;
  296.  
  297.     //
  298.     // decompressed frames are always key
  299.     //
  300.     pOutSample->SetSyncPoint(TRUE);
  301.     pOutSample->SetActualDataLength(nActBytesWritten);
  302.  
  303.     //
  304.     // Extrapolate the correct time stamp.
  305.     //
  306.     tStart = m_TimeAtLastSyncPoint + m_TimeSinceLastSyncPoint;
  307.     if (tStart < (LONG)0) {
  308.  
  309.         /*  Only play from the start */
  310.     }
  311.  
  312.     tStop = tStart + TimeDecoded;
  313.     m_TimeSinceLastSyncPoint += TimeDecoded;
  314.     pOutSample->SetTime((REFERENCE_TIME*)&tStart,
  315.                         (REFERENCE_TIME*)&tStop);
  316.  
  317.     DbgLog((LOG_TRACE, 3, TEXT("Writing %ld bytes with time stamp %s"),
  318.             nActBytesWritten, (LPCTSTR)CDisp(tStart) ));
  319.  
  320.     return m_pOutput->Deliver(pOutSample);
  321. }
  322.  
  323.  
  324. /******************************Public*Routine******************************\
  325. * Receive
  326. *
  327. * Copy the input sample into our buffer.  Loop while the buffer size is
  328. * greater than or equal to the size required to decode a frame of audio data.
  329. * Decode the audio frame and pass it along to the output pin for rendering.
  330. *
  331. *
  332. \**************************************************************************/
  333. HRESULT
  334. CMpegAudioCodec::Receive(
  335.     IMediaSample *pSample
  336.     )
  337. {
  338.     //  Make sure the pin doesn't go inactive on us
  339.     CAutoLock lck(&m_csReceive);
  340.     if (m_pAudioDecoder == NULL) {
  341.         return E_UNEXPECTED;
  342.     }
  343.  
  344.     IMediaSample    *pOutSample;
  345.     BYTE            *pDst;
  346.     BYTE            *pSrc;
  347.     BYTE            *lpPacket;
  348.     HRESULT         hr;
  349.     long            LenLeftInBuffer = 0L;
  350.     long            LenLeftInPacket;
  351.  
  352.     DbgLog((LOG_TRACE, 2, TEXT("CMpegAudioCodec::Receive")));
  353.  
  354.     //
  355.     // Check for a discontinuity, if one is found just reset the decoder
  356.     // and then continue processing the current sample.  We do not have to
  357.     // decode any frames left in the audio buffer because the audio codec
  358.     // always consumes all the complete audio data frames copied to
  359.     // the buffer.
  360.     //
  361.     if (pSample->IsDiscontinuity() == S_OK) {
  362.         ProcessDiscontiuity(pSample);
  363.     }
  364.  
  365.     hr = pSample->GetPointer(&pSrc);
  366.     if (FAILED(hr)) {
  367.         return hr;
  368.     }
  369.  
  370.     //
  371.     // Get a pointer to the actual mpeg data and determine the
  372.     // length of data supplied.
  373.     //
  374.     if (m_bPayloadOnly) {
  375.         lpPacket = pSrc;
  376.         LenLeftInPacket = pSample->GetActualDataLength();
  377.     }
  378.     else {
  379.         lpPacket = SkipToPacketData(pSrc, LenLeftInPacket);
  380.         if (lpPacket == NULL) {
  381.             NotifyEvent(EC_STREAM_ERROR_STILLPLAYING, E_INVALIDARG, 0);
  382.             return S_OK;
  383.         }
  384.     }
  385.     DbgLog((LOG_TRACE, 2, TEXT("Left in Packet %ld"), LenLeftInPacket ));
  386.  
  387.  
  388.     //
  389.     // If this sample is a sync point we need to update our clock and
  390.     // reset the count of samples received since the last sync point.
  391.     // If our buffer contains a partial audio frame we need to make a suitable
  392.     // adjustment to the sync point time as the time refers to the first audio
  393.     // frame in the current sample which would not necessarly be the first
  394.     // sample decoded.
  395.     //
  396.  
  397.     if (pSample->IsSyncPoint() == S_OK) {
  398.         ProcessSyncPoint(pSample, pSrc);
  399.     }
  400.  
  401.  
  402.     //
  403.     // Now, decode the sample data passed to us.
  404.     //
  405.  
  406.     do {
  407.  
  408.         LPBYTE      lpDstEnd;
  409.         CRefTime    TimeDecoded;
  410.         DWORD       rc;
  411.         int         nActBytesWritten = 0;
  412.  
  413.         GetNextPacketChunk(lpPacket, LenLeftInBuffer, LenLeftInPacket);
  414.  
  415.         DbgLog((LOG_TRACE, 3, TEXT("Left in Buffer %ld"), LenLeftInBuffer ));
  416.         DbgLog((LOG_TRACE, 3, TEXT("Left in Packet %ld"), LenLeftInPacket ));
  417.  
  418.         if (LenLeftInBuffer < m_FrameSize && LenLeftInPacket == 0L) {
  419.              break;
  420.         }
  421.  
  422.         //
  423.         // this may block for an indeterminate amount of time
  424.         //
  425.         hr = m_pOutput->GetDeliveryBuffer(&pOutSample,NULL,NULL,0);
  426.         if (FAILED(hr)) {
  427.             break;
  428.         }
  429.         ASSERT(pOutSample);
  430.  
  431.         hr = pOutSample->GetPointer(&pDst);
  432.         if (FAILED(hr)) {
  433.             break;
  434.         }
  435.         ASSERT(pDst);
  436.  
  437.  
  438.         //
  439.         // Initialize the audio control structure
  440.         //
  441.         m_AudioControl.dwNumFrames   = 1;
  442.         m_AudioControl.dwOutBuffSize = m_pOutput->CurrentMediaType().GetSampleSize();
  443.         m_AudioControl.dwOutBuffUsed = 0;
  444.         m_AudioControl.pCmprRead  = m_lpStart;
  445.         m_AudioControl.pCmprWrite = m_lpEnd;
  446.  
  447.  
  448.         //
  449.         // Determine the end of the output buffer so that we don't try to
  450.         // decode data beyond it.  m_BytesPerFrame is the number of bytes
  451.         // one frame of Mpeg audio data will expand to after it has been
  452.         // decoded.
  453.         //
  454.         lpDstEnd = pDst + m_AudioControl.dwOutBuffSize - m_FrameSizeOutput;
  455.         TimeDecoded = 0;
  456.  
  457.  
  458.         //
  459.         // While there is an audio frame in the buffer and the frame is
  460.         // complete and there is space in the output buffer to store the
  461.         // decompressed frame, decompress it !!
  462.         //
  463.  
  464.         while (LookForSyncWord()
  465.            && (m_lpCurr + m_FrameSize + Padding() < m_lpEnd)
  466.            && (pDst <= lpDstEnd)) {
  467.  
  468.             m_AudioControl.pOutBuffer  = pDst;
  469.             m_AudioControl.pCmprRead   = m_lpCurr;
  470.             m_AudioControl.dwMpegError = 0;
  471.  
  472.             rc = m_pAudioDecoder->DecodeAudioFrame(&m_AudioControl);
  473.             switch (rc) {
  474.  
  475.             case 0:
  476.                 //
  477.                 // We have successfully decoded an audio frame.
  478.                 //
  479.                 if (m_FrameSize == 0L) {
  480.                     m_FrameSize = (LPBYTE)m_AudioControl.pCmprRead -
  481.                                           m_lpCurr - Padding();
  482.                 }
  483.                 m_lpCurr = (LPBYTE)m_AudioControl.pCmprRead;
  484.                 pDst += m_AudioControl.dwOutBuffUsed;
  485.                 nActBytesWritten += m_AudioControl.dwOutBuffUsed;
  486.                 m_AudioControl.dwOutBuffSize -= m_AudioControl.dwOutBuffUsed;
  487.                 TimeDecoded += m_TimePerFrame;
  488.                 break;
  489.  
  490.  
  491.             case 2:
  492.                 //
  493.                 // We did not have enough data available to decode the
  494.                 // current audio frame.  This is buffer underflow.
  495.                 //
  496.                 DbgLog((LOG_ERROR, 1, TEXT("Buffer underflow !!")));
  497.  
  498.             default:
  499.                 //
  500.                 // Some sort of error occurred, throw the remainder of the
  501.                 // buffer away and skip this packet.
  502.                 //
  503.                 DbgLog((LOG_ERROR, 1, TEXT("Bad return code from audio codec!")));
  504.                 m_lpCurr = m_lpEnd;
  505.                 NotifyEvent(EC_STREAM_ERROR_STILLPLAYING, E_INVALIDARG, 0);
  506.                 hr = S_OK;
  507.                 break;
  508.             }
  509.         }
  510.  
  511.  
  512.         //
  513.         // Have we decoded any data ?  If so we need to deliver the data to
  514.         // to the filter that receives our output, usually the audio
  515.         // rendering filter.
  516.         //
  517.  
  518.         if (TimeDecoded > (LONG)0) {
  519.  
  520.             hr = DeliverSample(pOutSample, TimeDecoded, nActBytesWritten);
  521.             if (FAILED(hr)) {
  522.                 DbgLog((LOG_ERROR, 2,
  523.                         TEXT("CMpegAudioCodec::Deliver failed 0x%8.8X"), hr));
  524.                 pOutSample->Release();
  525.                 break;
  526.             }
  527.         }
  528.  
  529.         //
  530.         // Release the output buffer. If the connected pin still needs it,
  531.         // it will have addrefed it itself.
  532.         //
  533.         pOutSample->Release();
  534.  
  535.  
  536.         //
  537.         // Stop decoding when we have consumed all the data in the input
  538.         // media sample.
  539.         //
  540.  
  541.     } while (LenLeftInPacket != 0L);
  542.  
  543.     //
  544.     //  We notify the filter graph of problems but return S_FALSE
  545.     //  back to the caller to notify end of stream
  546.     //
  547.  
  548.     // if (hr != S_OK) {
  549.     //     NotifyEvent(hr == S_FALSE ? EC_COMPLETE : EC_ERRORABORT, 0, 0);
  550.     // }
  551.     return hr;
  552. }
  553.  
  554.  
  555.  
  556. /*****************************Private*Routine******************************\
  557. * ResetAudioDecoder
  558. *
  559. *
  560. \**************************************************************************/
  561. void
  562. CMpegAudioCodec::ResetAudioDecoder()
  563. {
  564.     m_pAudioDecoder->ResetAudio();
  565.     m_lpStart = m_lpCurr = m_lpEnd = &m_Buffer[0];
  566.     m_FrameSize = 0L;
  567. }
  568.  
  569.  
  570.  
  571. /******************************Public*Routine******************************\
  572. * GetNextPacketChunk
  573. *
  574. *
  575. \**************************************************************************/
  576. void
  577. CMpegAudioCodec::GetNextPacketChunk(
  578.     LPBYTE  &lpPacket,
  579.     long    &LenLeftInBuffer,
  580.     long    &LenLeftInPacket
  581.     )
  582. {
  583.     long AmountToCopy;
  584.  
  585.     LenLeftInBuffer = m_lpEnd - m_lpCurr;
  586.  
  587.     //
  588.     // Move what remains in the audio data buffer to the top of
  589.     // the buffer and append the new audio data to it.
  590.     //
  591.     AmountToCopy = min( (AUDIO_BUFF_SIZE - LenLeftInBuffer), LenLeftInPacket);
  592.  
  593.     MoveMemory(m_lpStart, m_lpCurr, LenLeftInBuffer);
  594.     CopyMemory(m_lpStart + LenLeftInBuffer, lpPacket,  AmountToCopy);
  595.  
  596.     LenLeftInPacket -= AmountToCopy;
  597.     lpPacket += AmountToCopy;
  598.  
  599.  
  600.     //
  601.     // Adjust the buffer pointers so that m_lpCurr points to
  602.     // the start of the buffer and m_lpEnd points to the last
  603.     // valid audio byte in buffer.
  604.     //
  605.     m_lpCurr = m_lpStart;
  606.     m_lpEnd = m_lpStart + LenLeftInBuffer + AmountToCopy;
  607.     LenLeftInBuffer = m_lpEnd - m_lpCurr;
  608. }
  609.  
  610.  
  611. /******************************Public*Routine******************************\
  612. * LookForSyncWord
  613. *
  614. *
  615. \**************************************************************************/
  616. BOOL
  617. CMpegAudioCodec::LookForSyncWord()
  618. {
  619.     /* now look for sync */
  620.     int sm = 0;
  621.  
  622.     while (m_lpCurr < m_lpEnd && sm < 2)  {
  623.  
  624.         switch (sm) {
  625.         case 0:
  626.             sm = (*m_lpCurr == 0xff);
  627.             break;
  628.  
  629.         case 1:
  630.             if ((*m_lpCurr & 0xf0) == 0xf0) sm = 2; /* sync found */
  631.             else sm = (*m_lpCurr == 0xff);
  632.             break;
  633.         }
  634.         m_lpCurr++;
  635.     }
  636.  
  637.     //
  638.     // When we get here we have either run out of buffer or found the first
  639.     // "sm" bytes of a valid sync word.
  640.     //
  641.     // Don't forget to put back the sync word bytes that we have just
  642.     // read otherwise they would be lost forever.
  643.     //
  644.     m_lpCurr -= sm;
  645.  
  646.     if (sm < 2) {
  647.         return FALSE;   // sync not found.
  648.     }
  649.  
  650.     return TRUE;
  651. }
  652.  
  653.  
  654. /******************************Public*Routine******************************\
  655. * Padding
  656. *
  657. * Returns 1 if the padding bit is set, zero otherwise
  658. *
  659. *
  660. \**************************************************************************/
  661. int
  662. CMpegAudioCodec::Padding()
  663. {
  664.     DWORD dw1 = *(UNALIGNED DWORD *)m_lpCurr;
  665.  
  666.     //
  667.     // Determine the audio layer for the given frame
  668.     //
  669.     switch (dw1 & 0x600) {
  670.  
  671.     case 0x200:     // Layer 1
  672.         return (dw1 & 0x20000) ? 4 : 0;
  673.  
  674.     case 0x400:
  675.     case 0x600:     // Layer 2 or Layer 3
  676.         return (dw1 & 0x20000) ? 1 : 0;
  677.  
  678.     default:        // Error !!
  679.         return 0;
  680.     }
  681. }
  682.  
  683.  
  684.  
  685.  
  686. /******************************Public*Routine******************************\
  687. * CheckInputType
  688. *
  689. *
  690. * check if you can support mtIn
  691. *
  692. *
  693. \**************************************************************************/
  694. HRESULT
  695. CMpegAudioCodec::CheckInputType(
  696.     const CMediaType* pmtIn
  697.     )
  698. {
  699.     DbgLog((LOG_TRACE, 2, TEXT("CMpegAudioCodec::CheckInputType")));
  700.  
  701.     //  Check for native streams
  702.     if (*pmtIn->Type() == MEDIATYPE_Stream &&
  703.         *pmtIn->Subtype() == MEDIASUBTYPE_MPEG1Audio) {
  704.  
  705.         /*  This will be checked a bit more in Connect() */
  706.         return S_OK;
  707.     }
  708.  
  709.  
  710.     // check this is an MPEG audio format type
  711.     if (*pmtIn->FormatType() != FORMAT_WaveFormatEx) {
  712.         DbgLog((LOG_ERROR, 2, TEXT("\tFormat not FORMAT_WaveFormatEx")));
  713.         return E_INVALIDARG;
  714.     }
  715.  
  716.     // we only support MEDIATYPE_Audio
  717.     if (*pmtIn->Type() != MEDIATYPE_Audio) {
  718.         DbgLog((LOG_ERROR, 2, TEXT("\tNot MEDIATYPE_Audio")));
  719.         return E_INVALIDARG;
  720.     }
  721.  
  722.     if (*pmtIn->Subtype() != MEDIASUBTYPE_MPEG1Packet &&
  723.         *pmtIn->Subtype() != MEDIASUBTYPE_MPEG1Payload) {
  724.         DbgLog((LOG_ERROR, 2, TEXT("\tNot MEDIASUBTYPE_MPEG1Packet or Payload")));
  725.         return E_INVALIDARG;
  726.     }
  727.  
  728.     //
  729.     // Make sure that we have not been given layer III data, we don't know
  730.     // how to decode layer III.
  731.     //
  732.     if (((LPMPEG1WAVEFORMAT)pmtIn->pbFormat)->fwHeadLayer == ACM_MPEG_LAYER3) {
  733.         DbgLog((LOG_ERROR, 2, TEXT("\tCan't decode layer III data")));
  734.         return E_INVALIDARG;
  735.     }
  736.  
  737.     CopyMemory(&m_Format, pmtIn->pbFormat, sizeof(MPEG1WAVEFORMAT));
  738.     return S_OK;
  739. }
  740.  
  741.  
  742.  
  743. /******************************Public*Routine******************************\
  744. * CheckTransform
  745. *
  746. * check if you can support the transform from this input to this output
  747. *
  748. *
  749. \**************************************************************************/
  750. HRESULT
  751. CMpegAudioCodec::CheckTransform(
  752.     const CMediaType* pmtIn,
  753.     const CMediaType* pmtOut
  754.     )
  755. {
  756.     DbgLog((LOG_TRACE, 2, TEXT("CMpegAudioCodec::CheckTransform")));
  757.  
  758.     // we only output audio
  759.     if (*pmtOut->Type() != MEDIATYPE_Audio) {
  760.         return S_FALSE;
  761.     }
  762.  
  763.     return S_OK;
  764. }
  765.  
  766.  
  767. /******************************Public*Routine******************************\
  768. * SetMediaType
  769. *
  770. * overriden to know when the media type is actually set
  771. *
  772. *
  773. \**************************************************************************/
  774. HRESULT
  775. CMpegAudioCodec::SetMediaType(
  776.     PIN_DIRECTION direction,
  777.     const CMediaType *pmt
  778.     )
  779. {
  780.     if (direction == PINDIR_INPUT) {
  781.  
  782.         //
  783.         // Get the data type
  784.         //
  785.         if (*pmt->Subtype() == MEDIASUBTYPE_MPEG1Packet) {
  786.             m_bPayloadOnly = FALSE;
  787.         }
  788.         else {
  789.             ASSERT(*pmt->Subtype() == MEDIASUBTYPE_MPEG1Payload ||
  790.                    *pmt->Subtype() == MEDIASUBTYPE_MPEG1Audio);
  791.             m_bPayloadOnly = TRUE;
  792.         }
  793.     }
  794.     else {
  795.  
  796.         LPWAVEFORMATEX lpWf = (LPWAVEFORMATEX)pmt->pbFormat;
  797.         int SamplesPerFrame;
  798.  
  799.         if (m_QuarterInt) {
  800.             m_dwCtrl = DECODE_QUART_INT | DECODE_QUARTER;
  801.         }
  802.         else {
  803.             switch (m_FreqDiv) {
  804.             case 1:
  805.                 m_dwCtrl = DECODE_FULL;
  806.                 break;
  807.  
  808.             case 2:
  809.                 m_dwCtrl = DECODE_HALF;
  810.                 break;
  811.  
  812.             case 4:
  813.                 m_dwCtrl = DECODE_QUARTER;
  814.                 break;
  815.             }
  816.         }
  817.  
  818.         switch (lpWf->wBitsPerSample) {
  819.         case 16:
  820.             m_dwCtrl |= DECODE_16BIT;
  821.             break;
  822.  
  823.         case 8:
  824.             m_dwCtrl |= DECODE_8BIT;
  825.             break;
  826.         }
  827.  
  828.         switch (m_Quality) {
  829.         case DECODE_HALF_FULLQ:
  830.             m_dwCtrl |= DECODE_HALF_FULLQ;
  831.             break;
  832.  
  833.         case DECODE_HALF_HIQ:
  834.             m_dwCtrl |= DECODE_HALF_HIQ;
  835.             break;
  836.         }
  837.  
  838.         switch (lpWf->nChannels) {
  839.         case 2:
  840.             m_dwCtrl |= DECODE_STEREO;
  841.             break;
  842.  
  843.         case 1:
  844.             m_dwCtrl |= DECODE_MONO;
  845.             break;
  846.         }
  847.  
  848.         if (m_Format.fwHeadLayer == ACM_MPEG_LAYER1) {
  849.             SamplesPerFrame = 384;
  850.         }
  851.         else {
  852.             SamplesPerFrame = 1152;
  853.         }
  854.  
  855.         m_TimePerFrame = MulDiv(SamplesPerFrame, 10000000,
  856.                                 m_Format.wfx.nSamplesPerSec);
  857.  
  858.         m_FrameSizeOutput = MulDiv(MulDiv(SamplesPerFrame,
  859.                                           lpWf->wBitsPerSample, 8),
  860.                                    lpWf->nChannels, m_FreqDiv);
  861.     }
  862.     return S_OK;
  863. }
  864.  
  865.  
  866.  
  867.  
  868. /******************************Public*Routine******************************\
  869. * GetMediaType
  870. *
  871. * Return our preferred output media types (in order)
  872. *
  873. *
  874. \**************************************************************************/
  875. HRESULT
  876. CMpegAudioCodec::GetMediaType(
  877.     int iPosition,
  878.     CMediaType *pmt
  879.     )
  880. {
  881.     LPWAVEFORMATEX      lpWf;
  882.     LPWAVEFORMATEX      lpWfIn;
  883.     LPMPEG1WAVEFORMAT   lpWfInMpeg;
  884.     CMediaType          cmt;
  885.     int                 SamplesPerFrame;
  886.     WORD                nChannels;
  887.     WORD                nBitsPerSample;
  888.  
  889.     if (iPosition < 0) {
  890.         return E_INVALIDARG;
  891.     }
  892.  
  893.     //
  894.     // If the requested output word size is 8 bits do not reveal the 16 bits
  895.     // per sample option.
  896.     //
  897.     if (m_WordSize == 8) {
  898.         if (iPosition > 0) {
  899.             return VFW_S_NO_MORE_ITEMS;
  900.         }
  901.         iPosition = 1;
  902.     }
  903.  
  904.     switch (iPosition) {
  905.     case 0:
  906.         nBitsPerSample = 16;
  907.         break;
  908.  
  909.     case 1:
  910.         nBitsPerSample = 8;
  911.         break;
  912.  
  913.     default:
  914.         return VFW_S_NO_MORE_ITEMS;
  915.     }
  916.  
  917.     lpWf = (LPWAVEFORMATEX)pmt->AllocFormatBuffer(sizeof(WAVEFORMATEX));
  918.     if (lpWf == NULL) {
  919.         return E_OUTOFMEMORY;
  920.     }
  921.     if (*m_pInput->CurrentMediaType().Type() == MEDIATYPE_Stream) {
  922.         lpWfIn = &m_Format.wfx;
  923.         lpWfInMpeg = &m_Format;
  924.     } else {
  925.         lpWfIn = (LPWAVEFORMATEX)m_pInput->CurrentMediaType().pbFormat;
  926.         lpWfInMpeg = (LPMPEG1WAVEFORMAT)m_pInput->CurrentMediaType().pbFormat;
  927.     }
  928.     ASSERT(lpWfIn != NULL);
  929.  
  930.  
  931.     //
  932.     // Dump the input format
  933.     //
  934.     DbgLog((LOG_TRACE, 2, TEXT("nSamplesPerSec = %ld"), lpWfIn->nSamplesPerSec));
  935.     DbgLog((LOG_TRACE, 2, TEXT("nChannels      = %hd"), lpWfIn->nChannels));
  936.     DbgLog((LOG_TRACE, 2, TEXT("Layer          = %hd"), lpWfInMpeg->fwHeadLayer));
  937.  
  938.     //
  939.     // If the number of channels available matches the number preferred
  940.     // we decode all the channels available.  Otherwise we decode the
  941.     // minimum of the chanels available and the channels preferred.
  942.     //
  943.     if (lpWfIn->nChannels == m_PrefChan) {
  944.         nChannels = m_PrefChan;
  945.     }
  946.     else {
  947.         nChannels = min(m_PrefChan, lpWfIn->nChannels);
  948.     }
  949.  
  950.     lpWf->wFormatTag       = WAVE_FORMAT_PCM;
  951.     lpWf->nChannels        = nChannels;
  952.     lpWf->nSamplesPerSec   = lpWfIn->nSamplesPerSec / m_FreqDiv;
  953.     lpWf->nBlockAlign      = (nBitsPerSample * nChannels) / 8;
  954.     lpWf->nAvgBytesPerSec  = lpWf->nSamplesPerSec * lpWf->nBlockAlign;
  955.     lpWf->wBitsPerSample   = nBitsPerSample;
  956.     lpWf->cbSize           = 0;
  957.  
  958.     //
  959.     // Dump the ouput format
  960.     //
  961.     DbgLog((LOG_TRACE, 2, TEXT("!!nSamplesPerSec = %ld"), lpWf->nSamplesPerSec));
  962.     DbgLog((LOG_TRACE, 2, TEXT("!!nChannels      = %hd"), lpWf->nChannels));
  963.     DbgLog((LOG_TRACE, 2, TEXT("!!nBlockAlign    = %hd"), lpWf->nBlockAlign));
  964.     DbgLog((LOG_TRACE, 2, TEXT("!!wBitsPerSample = %hd"), lpWf->wBitsPerSample));
  965.     DbgLog((LOG_TRACE, 2, TEXT("!!nAvgBytesPerSec= %ld\n"), lpWf->nAvgBytesPerSec));
  966.  
  967.     //
  968.     // we assume the output format is uncompressed
  969.     //
  970.     pmt->SetType(&MEDIATYPE_Audio);
  971.     pmt->SetSubtype(&GUID_NULL);
  972.     pmt->SetFormatType(&FORMAT_WaveFormatEx);
  973.     pmt->SetTemporalCompression(FALSE);
  974.  
  975.     //
  976.     // The time per frame and output sample size depend on the layer
  977.     // of mpeg audio data being compressed.
  978.     //
  979.     if (lpWfInMpeg->fwHeadLayer == ACM_MPEG_LAYER1) {
  980.         SamplesPerFrame = 384;
  981.     }
  982.     else {
  983.         SamplesPerFrame = 1152;
  984.     }
  985.  
  986.     m_TimePerFrame = MulDiv(SamplesPerFrame, 10000000, lpWfIn->nSamplesPerSec);
  987.     m_FrameSizeOutput = MulDiv(MulDiv(SamplesPerFrame, nBitsPerSample, 8),
  988.                                nChannels, m_FreqDiv);
  989.  
  990.     pmt->SetSampleSize(m_FrameSizeOutput * MAX_FRAMES_PER_OUTPUT_SAMPLE);
  991.     return S_OK;
  992. }
  993.  
  994.  
  995. /******************************Public*Routine******************************\
  996. * DecideBufferSize
  997. *
  998. *
  999. * Called from CBaseOutputPin to prepare the allocator's count
  1000. * of buffers and sizes
  1001. *
  1002. *
  1003. \**************************************************************************/
  1004. HRESULT
  1005. CMpegAudioCodec::DecideBufferSize(
  1006.     IMemAllocator *pAllocator,
  1007.     ALLOCATOR_PROPERTIES * pProperties
  1008.     )
  1009. {
  1010.     DbgLog((LOG_TRACE, 2, TEXT("CMpegAudioCodec::DecideBufferSize")));
  1011.  
  1012.     ASSERT(pAllocator);
  1013.     ASSERT(pProperties);
  1014.     HRESULT hr = NOERROR;
  1015.  
  1016.     pProperties->cBuffers = 8;
  1017.     pProperties->cbBuffer = m_pOutput->CurrentMediaType().GetSampleSize();
  1018.  
  1019.     ASSERT(pProperties->cbBuffer);
  1020.     DbgLog((LOG_TRACE, 2, TEXT("Sample size = %ld\n"), pProperties->cbBuffer));
  1021.  
  1022.     // Ask the allocator to reserve us some sample memory, NOTE the function
  1023.     // can succeed (that is return NOERROR) but still not have allocated the
  1024.     // memory that we requested, so we must check we got whatever we wanted
  1025.  
  1026.     ALLOCATOR_PROPERTIES Actual;
  1027.     hr = pAllocator->SetProperties(pProperties,&Actual);
  1028.     if (FAILED(hr)) {
  1029.         return hr;
  1030.     }
  1031.  
  1032.     ASSERT(Actual.cbAlign == 1);
  1033.     ASSERT(Actual.cbPrefix == 0);
  1034.  
  1035.     if (Actual.cbBuffer < pProperties->cbBuffer ||
  1036.         Actual.cBuffers < pProperties->cBuffers) {
  1037.  
  1038.             // can't use this allocator
  1039.             return E_INVALIDARG;
  1040.     }
  1041.     return S_OK;
  1042. }
  1043.  
  1044.  
  1045. /******************************Public*Routine******************************\
  1046. * StartStreaming
  1047. *
  1048. *
  1049. \**************************************************************************/
  1050. HRESULT
  1051. CMpegAudioCodec::StartStreaming()
  1052. {
  1053.     CAutoLock       lock(&m_csFilter);
  1054.  
  1055.     DbgLog((LOG_TRACE, 2, TEXT("CMpegAudioCodec::StartStreaming")));
  1056.  
  1057.     m_pAudioDecoder = new CAudioDecoder(this);
  1058.     if (m_pAudioDecoder == NULL) {
  1059.         return E_OUTOFMEMORY;
  1060.     }
  1061.  
  1062.     ResetAudioDecoder();
  1063.     return S_OK;
  1064. }
  1065.  
  1066.  
  1067. /******************************Public*Routine******************************\
  1068. * StopStreaming
  1069. *
  1070. *
  1071. \**************************************************************************/
  1072. HRESULT
  1073. CMpegAudioCodec::StopStreaming()
  1074. {
  1075.     CAutoLock lock(&m_csFilter);
  1076.     CAutoLock lck(&m_csReceive);
  1077.     DbgLog((LOG_TRACE, 2, TEXT("CMpegAudioCodec::StopStreaming")));
  1078.  
  1079.     ASSERT(m_pAudioDecoder != NULL);
  1080.  
  1081.     delete m_pAudioDecoder;
  1082.     m_pAudioDecoder = NULL;
  1083.  
  1084.     return S_OK;
  1085. }
  1086.  
  1087.  
  1088. /******************************Public*Routine******************************\
  1089. * GetSetupData
  1090. *
  1091. *
  1092. *
  1093. * History:
  1094. *
  1095. \**************************************************************************/
  1096. LPAMOVIESETUP_FILTER
  1097. CMpegAudioCodec::GetSetupData()
  1098. {
  1099.   return &sudMPEGAudio;
  1100. }
  1101.  
  1102.  
  1103. /******************************Public*Routine******************************\
  1104. * GetDecoderInteger
  1105. *
  1106. *
  1107. \**************************************************************************/
  1108. int
  1109. GetDecoderInteger(
  1110.     const TCHAR *pKey,
  1111.     int iDefault
  1112.     )
  1113. {
  1114.     return GetProfileInt(TEXT("Quartz"), pKey, iDefault);
  1115. }
  1116.  
  1117. /******************************Public*Routine******************************\
  1118. * SkipToPacketData
  1119. *
  1120. *
  1121. \**************************************************************************/
  1122. LPBYTE
  1123. SkipToPacketData(
  1124.     LPBYTE pSrc,
  1125.     long &LenLeftInPacket
  1126.     )
  1127. {
  1128.     LPBYTE  lpPacketStart;
  1129.     DWORD   bData;
  1130.     long    Length;
  1131.  
  1132.  
  1133.     //
  1134.     // Skip the stream ID and extract the packet length
  1135.     //
  1136.     pSrc += 4;
  1137.     bData = *pSrc++;
  1138.     Length = (long)((bData << 8) + *pSrc++);
  1139.     DbgLog((LOG_TRACE, 3, TEXT("Packet length %ld"), Length ));
  1140.  
  1141.  
  1142.     //
  1143.     // Record position of first byte after packet length
  1144.     //
  1145.     lpPacketStart = pSrc;
  1146.  
  1147.  
  1148.     //
  1149.     // Remove stuffing bytes
  1150.     //
  1151.     for (; ; ) {
  1152.         bData = *pSrc++;
  1153.         if (!(bData & 0x80)) {
  1154.             break;
  1155.         }
  1156.     }
  1157.  
  1158.     if ((bData & 0xC0) == 0x40) {
  1159.         pSrc++;
  1160.         bData = *pSrc++;
  1161.     }
  1162.  
  1163.     switch (bData & 0xF1) {
  1164.  
  1165.     case 0x21:
  1166.         pSrc += 4;
  1167.         break;
  1168.  
  1169.     case 0x31:
  1170.         pSrc += 9;
  1171.         break;
  1172.  
  1173.     default:
  1174.         if (bData != 0x0F) {
  1175.             DbgLog((LOG_TRACE, 2, TEXT("Invalid packet - 0x%2.2X\n"), bData));
  1176.             return NULL;
  1177.         }
  1178.     }
  1179.  
  1180.     //
  1181.     // The length left in the packet is the original length of the packet
  1182.     // less those bytes that we have just skipped over.
  1183.     //
  1184.     LenLeftInPacket = Length - (pSrc - lpPacketStart);
  1185.     return pSrc;
  1186. }
  1187.  
  1188.  
  1189. /******************************Public*Routine******************************\
  1190. * exported entry points for registration and
  1191. * unregistration (in this case they only call
  1192. * through to default implmentations).
  1193. *
  1194. *
  1195. *
  1196. * History:
  1197. *
  1198. \**************************************************************************/
  1199. HRESULT
  1200. DllRegisterServer()
  1201. {
  1202.   return AMovieDllRegisterServer();
  1203. }
  1204.  
  1205. HRESULT
  1206. DllUnregisterServer()
  1207. {
  1208.   return AMovieDllUnregisterServer();
  1209. }
  1210.  
  1211.