//==========================================================================;
//
//  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) 1992 - 1997  Microsoft Corporation.  All Rights Reserved.
//
//--------------------------------------------------------------------------;
//
/******************************Module*Header*******************************\
* Module Name: Decoder.cpp
*
* Implements a prototype Mpeg Audio Software codec.  It just consumes
* the passed in audio frames.
*
*
\**************************************************************************/
#include "MpgAudio.h"



/* -------------------------------------------------------------------------
** CAudioDecoder
** -------------------------------------------------------------------------
*/

/******************************Public*Routine******************************\
* CAudioDecoder
*
* Constructor and destructor
*
*
\**************************************************************************/
CAudioDecoder::CAudioDecoder(CMpegAudioCodec *pMpegCodec)
    : m_pCodec(pMpegCodec) {}



/******************************Public*Routine******************************\
* ResetAudio
*
*
\**************************************************************************/
DWORD
CAudioDecoder::ResetAudio()
{
    CAutoLock lck(this);
    return DECODE_SUCCESS;
}


/******************************Public*Routine******************************\
* DecodeFrame
*
*
\**************************************************************************/
DWORD
CAudioDecoder::DecodeAudioFrame(
    AudioCtrl *pCtrl
    )
{
    CAutoLock   lck(this);
    DWORD       rc = DECODE_SUCCESS;

    m_pCtrl = pCtrl;


    for (DWORD i = 0; i < m_pCtrl->dwNumFrames; i++) {

        // Skip the sync word
        m_pCtrl->pCmprRead += 2;

        // skip the rest of the frame
        if (!SkipFrame()) {
            m_pCtrl->dwOutBuffUsed = 0L;
            return DECODE_ERR_DATA;
        }
    }

    ZeroMemory(m_pCtrl->pOutBuffer, m_pCtrl->dwOutBuffSize);
    m_pCtrl->dwOutBuffUsed = m_pCtrl->dwOutBuffSize;

    return rc;
}


/*****************************Private*Routine******************************\
* SkipFrame
*
*
\**************************************************************************/
BOOL
CAudioDecoder::SkipFrame()
{
    LPBYTE  lpCurr = m_pCtrl->pCmprRead;
    LPBYTE  lpEnd = m_pCtrl->pCmprWrite;
    int sm = 0;

    while (lpCurr < lpEnd && sm < 2)  {

        switch (sm) {
        case 0:
            sm = (*lpCurr == 0xff);
            break;

        case 1:
            if ((*lpCurr & 0xf0) == 0xf0) sm = 2; /* sync found */
            else sm = (*lpCurr == 0xff);
            break;
        }
        lpCurr++;
    }

    //
    // When we get here we have either run out of buffer or found the first
    // "sm" bytes of a valid sync word.
    //
    // Don't forget to put back the sync word bytes that we have just
    // read otherwise they would be lost forever.
    //
    lpCurr -= sm;
    m_pCtrl->pCmprRead = lpCurr;

    if (sm < 2) {
        return FALSE;   // sync not found.
    }

    return TRUE;
}
