amrff.cpp

来自「symbian 下的helix player源代码」· C++ 代码 · 共 914 行 · 第 1/3 页

CPP
914
字号
    {
        // Set the state
        m_eState = StateStreamHeaderSeekDonePending;
        // m_ulNextFileOffset should be set the offset of
        // the first AMR frame in the file
        retVal = m_pFileObject->Seek(m_ulNextFileOffset, FALSE);
    }
    else
    {
        retVal = HXR_UNEXPECTED;
    }

    return retVal;
}

STDMETHODIMP CAMRFileFormat::GetPacket(UINT16 unStreamNumber)
{
    HX_RESULT retVal = HXR_UNEXPECTED;

    if (m_eState == StateReady)
    {
        if (m_pPayloadFormat)
        {
            // Try and get a packet from the payload format object
            IHXPacket* pPacket = NULL;
            retVal = m_pPayloadFormat->GetPacket(pPacket);
            if (SUCCEEDED(retVal))
            {
                // The payload format object had a packet ready,
                // so send it. We don't have to change the state
                retVal = m_pFormatResponse->PacketReady(HXR_OK, pPacket);
            }
            else
            {
                // Clear the return value. It's not an error
                // if the payload format object doesn't have any
                // packets - it just means we need to provide more data.
                retVal = HXR_OK;
                // We need to provide the payload format object
                // some more of the file, so we will seek to the
                // new file offset.
                m_eState = StateGetPacketSeekDonePending;
                // Seek the file
                retVal = m_pFileObject->Seek(m_ulNextFileOffset, FALSE);
            }
            HX_RELEASE(pPacket);
        }
    }

    return retVal;
}

STDMETHODIMP CAMRFileFormat::Seek(ULONG32 ulOffset)
{
    HX_RESULT retVal = HXR_UNEXPECTED;

    if (m_pFormatResponse && m_pPayloadFormat)
    {
        // Clear out the packets from the payload format object
        m_pPayloadFormat->Reset();
        // First convert the time offset to a file offset,
        // assuming a constant bitrate and therefore a 
        // constant number of bytes per frame. We know that
        // AMR frames always have a duration of 20ms.
        UINT32 ulFrameNum   = ulOffset / 20;
        UINT32 ulFileOffset = ulFrameNum * m_ulBytesPerFrame + m_ulHeaderSize;
        // Compute the next time stamp
        m_ulNextTimeStamp = ulFrameNum * 20;
        // Set the next file offset
        m_ulNextFileOffset = ulFileOffset;
        // In the case of files where the bytes per frame is not constant
        // throughout the file, the following file seek might
        // not land on a frame boundary. Therefore, this flag
        // will tell us that we need to scan the buffer we read
        // for a frame boundary.
        m_bScanForFrameBegin = TRUE;
        // Tell the format response we're ready
        retVal = m_pFormatResponse->SeekDone(HXR_OK);
    }

    return retVal;
}

STDMETHODIMP CAMRFileFormat::InitDone(HX_RESULT status)
{
    HX_RESULT retVal = HXR_OK;

    if (m_eState == StateInitFileFormatInitDonePending)
    {
        // Get the IHXFileStat interface
        HX_RELEASE(m_pFileStat);
        retVal = m_pFileObject->QueryInterface(IID_IHXFileStat, (void**) &m_pFileStat);
        if (SUCCEEDED(retVal))
        {
            // Get our own IHXFileStatResponse interface
            IHXFileStatResponse* pStatResponse = NULL;
            retVal = QueryInterface(IID_IHXFileStatResponse, (void**) &pStatResponse);
            if (SUCCEEDED(retVal))
            {
                // Set the state
                m_eState = StateInitFileFormatStatDonePending;
                // Call Stat
                retVal = m_pFileStat->Stat(pStatResponse);
            }
            HX_RELEASE(pStatResponse);
        }
        if (FAILED(retVal))
        {
            // Set the state
            m_eState = StateReady;
            // Call back to the response
            retVal = m_pFormatResponse->InitDone(retVal);
        }
    }
    else
    {
        retVal = HXR_UNEXPECTED;
    }

    return retVal;
}

STDMETHODIMP CAMRFileFormat::SeekDone(HX_RESULT status)
{
    HX_RESULT retVal = HXR_OK;

    if (m_eState == StateFileHeaderSeekDonePending)
    {
        if (SUCCEEDED(status))
        {
            // Set the new state
            m_eState = StateFileHeaderReadDonePending;
            // Now read AMR_HEADER_READ_SIZE bytes
            retVal = m_pFileObject->Read(AMR_HEADER_READ_SIZE);
        }
        else
        {
            // Go back to the StateReady state
            m_eState = StateReady;
            // Fail out to the response interface
            retVal = m_pFormatResponse->FileHeaderReady(status, NULL);
        }
    }
    else if (m_eState == StateStreamHeaderSeekDonePending)
    {
        if (SUCCEEDED(status))
        {
            // Set the new state
            m_eState = StateStreamHeaderReadDonePending;
            // Now read AMR_READ_SIZE bytes
            retVal = m_pFileObject->Read(AMR_READ_SIZE);
        }
        else
        {
            // Go back to StateReady state
            m_eState = StateReady;
            // Fail out to response interface
            retVal = m_pFormatResponse->StreamHeaderReady(status, NULL);
        }
    }
    else if (m_eState == StateGetPacketSeekDonePending)
    {
        if (SUCCEEDED(status))
        {
            // Set the new state
            m_eState = StateGetPacketReadDonePending;
            // Read AMR_READ_SIZE more bytes
            retVal = m_pFileObject->Read(AMR_READ_SIZE);
        }
        else
        {
            // Go back to ready
            m_eState = StateReady;
            // Issue a StreamDone()
            retVal = m_pFormatResponse->StreamDone(0);
        }
    }
    else
    {
        retVal = HXR_UNEXPECTED;
    }

    return retVal;
}

STDMETHODIMP CAMRFileFormat::ReadDone(HX_RESULT status, IHXBuffer* pBuffer)
{
    HX_RESULT retVal = HXR_OK;

    if (m_eState == StateFileHeaderReadDonePending)
    {
        // Assume the worst
        retVal = HXR_FAIL;
        // Process the first few bytes of the file
        if (SUCCEEDED(status) && pBuffer)
        {
            // Check the first five bytes to identify
            // this as an AMR file
            BYTE* pBuf = (BYTE*) pBuffer->GetBuffer();
            if (pBuf)
            {
                // Test the magic number
                if (!memcmp(pBuf, m_pMagicSingle, sizeof(m_pMagicSingle)))
                {
                    m_bWideBand        = FALSE;
                    m_ulNumChannels    = 1;
                    m_ulHeaderSize = sizeof(m_pMagicSingle);
                    retVal             = HXR_OK;
                }
                else if (!memcmp(pBuf, m_pMagicSingleWB, sizeof(m_pMagicSingleWB)))
                {
                    m_bWideBand        = TRUE;
                    m_ulNumChannels    = 1;
                    m_ulHeaderSize = sizeof(m_pMagicSingleWB);
                    retVal             = HXR_OK;
                }
                else if (!memcmp(pBuf, m_pMagicMulti, sizeof(m_pMagicMulti)))
                {
                    m_bWideBand        = FALSE;
                    m_ulNumChannels    = m_ucNumChannelsMap[pBuf[sizeof(m_pMagicMulti) + 3] & 0x0F];
                    m_ulHeaderSize = sizeof(m_pMagicMulti) + 4;
                    if (m_ulNumChannels != 0)
                    {
                        retVal = HXR_OK;
                    }
                }
                else if (!memcmp(pBuf, m_pMagicMultiWB, sizeof(m_pMagicMultiWB)))
                {
                    m_bWideBand        = TRUE;
                    m_ulNumChannels    = m_ucNumChannelsMap[pBuf[sizeof(m_pMagicMultiWB) + 3] & 0x0F];
                    m_ulHeaderSize = sizeof(m_pMagicMultiWB) + 4;
                    if (m_ulNumChannels != 0)
                    {
                        retVal = HXR_OK;
                    }
                }
                else
                {
                    // This is not an AMR file
                    retVal = HXR_FAIL;
                }
                if (SUCCEEDED(retVal))
                {
                    // Set the next file offset to right after
                    // the file header
                    m_ulNextFileOffset = m_ulHeaderSize;
                    // Create an IHXValues
                    IHXValues* pHdr = NULL;
                    retVal = m_pCommonClassFactory->CreateInstance(CLSID_IHXValues, (void**) &pHdr);
                    if (SUCCEEDED(retVal))
                    {
                        // Set the StreamCount property
                        pHdr->SetPropertyULONG32("StreamCount", 1);
                        // Set the new state
                        m_eState = StateReady;
                        // Send the file header
                        retVal = m_pFormatResponse->FileHeaderReady(HXR_OK, pHdr);
                    }
                    HX_RELEASE(pHdr);
                }
            }
        }
        if (FAILED(retVal))
        {
            // Go back to the StateFileFormatInitialized state
            m_eState = StateReady;
            // Fail out to the response interface
            retVal = m_pFormatResponse->FileHeaderReady(retVal, NULL);
        }
    }
    else if (m_eState == StateStreamHeaderReadDonePending)
    {
        retVal = status;
        if (SUCCEEDED(retVal))
        {
            // Create our CHXAMRPayloadFormat object
            retVal = HXR_OUTOFMEMORY;
            HX_DELETE(m_pPayloadFormat);
            m_pPayloadFormat = new CHXAMRPayloadFormatPacketizer();
            if (m_pPayloadFormat)
            {
                // Init the payload format
                retVal = m_pPayloadFormat->Init(m_pContext, TRUE);
                if (SUCCEEDED(retVal))
                {
                    // Create an IHXValues
                    IHXValues* pHdr = NULL;
                    retVal = m_pCommonClassFactory->CreateInstance(CLSID_IHXValues, (void**) &pHdr);
                    if (SUCCEEDED(retVal))
                    {
                        // Set the MimeType
                        INT32 lIndx = (m_bWideBand ? 3 : 2);
                        SetCStringProperty(pHdr, "MimeType", m_ppszStreamMimeTypes[lIndx], m_pContext);
                        // Compute the average bitrate
                        UINT32 ulAvgBitRate = 0;
                        GetStreamInfo(pBuffer, 0, ulAvgBitRate, m_ulBytesPerFrame);
                        // Set the ASM rule book
                        char szASMRuleBook[64]; /* Flawfinder: ignore */
                        sprintf(szASMRuleBook, "AverageBandwidth=%lu,Priority=5;", ulAvgBitRate); /* Flawfinder: ignore */
                        SetCStringProperty(pHdr, "ASMRuleBook", szASMRuleBook, m_pContext);
                        // Compute the duration
                        UINT32 ulDur = 1000;
                        if (ulAvgBitRate != 0)
                        {
                            ulDur = m_ulFileSize * 8000 / ulAvgBitRate;

⌨️ 快捷键说明

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