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

📄 mp3ff.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
        //pHeaderObj->SetPropertyBuffer("OpaqueData", pHeader);

        // Move back to the beginning of the file
        m_pFileObj->Seek(MY_FILE_HEADER_START+m_ulFileOffset, FALSE);

        // do not allow recording of MP3 audio at this time
        //pHeaderObj->SetPropertyULONG32("Flags",HX_SAVE_ENABLED);

#if defined(HELIX_FEATURE_MP3FF_ONDEMANDMETAINFO)
        // If additional meta info has been requested, then
        // provide it here.
        if (m_bAcceptMetaInfo)
        {
            if (m_bAllMetaInfo)
            {
                SetMetaInfo(pHeaderObj, "SrcCodec");
                SetMetaInfo(pHeaderObj, "SrcBitRate");
                SetMetaInfo(pHeaderObj, "SrcVBREnabled");
                SetMetaInfo(pHeaderObj, "SrcInterleaved");
                SetMetaInfo(pHeaderObj, "SrcSamplesPerSecond");
                SetMetaInfo(pHeaderObj, "SrcBitsPerSample");
                SetMetaInfo(pHeaderObj, "SrcNumChannels");
            }
            else
            {
                if (m_pMetaProps)
                {
                    const char* pszProp = NULL;
                    UINT32      ulTmp   = 0;
                    HX_RESULT rv = m_pMetaProps->GetFirstPropertyULONG32(pszProp, ulTmp);
                    while (SUCCEEDED(rv))
                    {
                        SetMetaInfo(pHeaderObj, pszProp);
                        rv = m_pMetaProps->GetNextPropertyULONG32(pszProp, ulTmp);
                    }

                }

            }
        }
#endif /* #if defined(HELIX_FEATURE_MP3FF_ONDEMANDMETAINFO) */

        // Notify the RMA core that header object is ready
        m_pStatus->FileHeaderReady(status, pHeaderObj);

        // Release the object since we are done with it
        pHeaderObj->Release();
    }

    return HXR_OK;
}

///////////////////////////////////////////////////////////////////////////////
//  IHXFileFormatObject::GetStreamHeader                    ref:  hxformt.h
//
//  This routine returns to the RMA core an object containing the stream
//  header information for a particular stream. Several routines are actually
//  required to complete the process due to the asynchronous nature of the
//  RMA file system. This method is called (after the file header has been
//  read) by the RMA core for each stream in the file format.
//
STDMETHODIMP CRnMp3Fmt::GetStreamHeader(UINT16 streamNo)
{
    if ((m_State != Ready) || (streamNo != MY_STREAM_NO))
        return HXR_UNEXPECTED;

    if (eHXUnknown == m_Info.eType)
        return HXR_INVALID_FILE;
                
    m_State = GetStreamHeaderSeekPending;
    MyCreateStreamHeaderObj_v(HX_STATUS_OK, NULL);

    return HXR_OK;
}


///////////////////////////////////////////////////////////////////////////////
//  CRnMp3Fmt::MyCreateStreamHeaderObj_v            ref:  filefmt1.h
//
//  This routine creates a "stream header" object and passes it off to the
//  RMA core, which in turn transports it to the renderer. This object must
//  contain certain properties required to characterize the stream. Any
//  additional stream information read from the file can also be placed in
//  this object. This method is called after the stream header data from the
//  file has been completely read.
void
CRnMp3Fmt::MyCreateStreamHeaderObj_v(HX_RESULT   status,
                                     IHXBuffer* pStreamHeader)
{
    m_State = Ready;

    // Create new object containing the stream header data
    IHXValues* pStreamHeaderObj = NULL;
    m_pClassFactory->CreateInstance(CLSID_IHXValues,
                                     (void**)&pStreamHeaderObj);
    if (pStreamHeaderObj != NULL)
    {
        // REQUIRED Properties:
        pStreamHeaderObj->SetPropertyULONG32("StreamNumber", MY_STREAM_NO);
        pStreamHeaderObj->SetPropertyULONG32("AvgBitRate", m_Info.ulBitRate);
        pStreamHeaderObj->SetPropertyULONG32("SampleRate", m_ulMaxSampRate);
        pStreamHeaderObj->SetPropertyULONG32("NumChannels", m_nChannels);

        UINT32 ulPreRoll = 1000;
        if (m_pFileObj->Advise(HX_FILEADVISE_RANDOMACCESS) == HXR_ADVISE_PREFER_LINEAR)
            ulPreRoll += 2000;

        pStreamHeaderObj->SetPropertyULONG32("Preroll", ulPreRoll);

        m_Info.nPacketSize = min(m_Info.nPacketSize, kReadSize);

        double dDur;
        dDur = m_ulFileSize / (double)(m_Info.ulBitRate>>3) * 1000.0;
        
        pStreamHeaderObj->SetPropertyULONG32("Duration", (UINT32)dDur);
        pStreamHeaderObj->SetPropertyULONG32("MaxPacketSize", 1024);
        pStreamHeaderObj->SetPropertyULONG32("AvgPacketSize", m_Info.nPacketSize);

        pStreamHeaderObj->SetPropertyULONG32("StartTime", 0);

#if defined (MPA_FMT_DRAFT00)
        // MPA is 14 Dynamic is > 96
        if (m_bRtp)
        {
            pStreamHeaderObj->SetPropertyULONG32("RTPPayloadType", 14);
            pStreamHeaderObj->SetPropertyULONG32("RTPTimestampConversionFactor", 90);
            pStreamHeaderObj->SetPropertyULONG32("HXTimestampConversionFactor", 1);
        }
#endif //MPA_FMT_DRAFT00
        
        // "MimeType": this stream's MIME type. This associates this
        // stream type with a particular renderer.
        const char* pszTmp = MY_LOCAL_MIME_TYPE;
#if defined (MPA_FMT_DRAFT00)
        if (m_bStreaming)
        {
            if(m_bRtp)
                pszTmp = MY_RTP_MIME_TYPE;
            else
                pszTmp = MY_STREAM_MIME_TYPE;
        }
#endif //MPA_FMT_DRAFT00
        SetCStringProperty(pStreamHeaderObj, "MimeType", pszTmp, m_pContext);

        // Set the ASM rule book
        char* pRuleBook = new char[sizeof(char) * 100];
        if (pRuleBook)
        {
            // Create the string
            if (m_bRtp)
            {
                SafeSprintf(pRuleBook, 100,
                            "marker=0, AverageBandwidth=%ld, Priority=9, "
                            "timestampdelivery=true;",
                            m_Info.ulBitRate); 
            }
            else
            {
                SafeSprintf(pRuleBook, 100,
                            "AverageBandwidth=%ld, AverageBandwidthStd=0, "
                            "Priority=9;",
                            m_Info.ulBitRate);
            }
            // Set it into the stream header
            SetCStringProperty(pStreamHeaderObj, "ASMRuleBook",
                               (const char*) pRuleBook, m_pContext);
        }
        HX_VECTOR_DELETE(pRuleBook);

#if defined(HELIX_FEATURE_SERVER)
        if (!m_bLicensed)
        {
            if (m_pError)
            {
                m_pError->Report(HXLOG_ALERT, HXR_NOT_LICENSED, 
                        0, "This server is NOT licensed to deliver MPEG Audio "
                        "streams. A Player attempting to access MPEG Audio content "
                        "has been disconnected. Please contact RealNetworks to "
                        "obtain a license for this feature.\n", NULL);
            }

            status = HXR_NOT_LICENSED;
        }
#endif /* #if defined(HELIX_FEATURE_SERVER) */
        
        // Notify the RMA core that stream header object is ready
        m_pStatus->StreamHeaderReady(status, pStreamHeaderObj);

        // Release the object since we are done with it
        pStreamHeaderObj->Release();
    }
}

///////////////////////////////////////////////////////////////////////////////
//  IHXFileFormatObject::GetPacket                          ref:  hxformt.h
//
//  This routine returns to the RMA core an object containing the packet
//  data for a particular stream. Several routines are actually required to
//  complete the process due to the asynchronous nature of the RMA file
//  system. This method is called by the RMA core each time it needs another
//  packet.
//
STDMETHODIMP
CRnMp3Fmt::GetPacket(UINT16 streamNo)
{
    // with asyncfsys it is possible that a GetPacket() call is outstanding
    // even after Close() has been called. so check for m_bClosed for that
    // case (b'cuz m_pFileObj is released inside Close())
    if (m_bClosed || (m_State != Ready) || (streamNo != MY_STREAM_NO))
        return HXR_UNEXPECTED;

    // Read our first buffer
    if (!m_ReadBuf.pReadBuffer)
    {
        m_bNeedPacket = 1;

        m_State = GetPacketReadPending;
        m_pFileObj->Read(kReadSize);

        return HXR_OK;
    }

    return MyCreatePacketObj_hr(m_ReadBuf.status, &m_ReadBuf);
}


///////////////////////////////////////////////////////////////////////////////
//  CRnMp3Fmt::MyCreatePacketObj_hr                 ref:  filefmt1.h
//
//  This routine creates a packet object and passes it off to the RMA core,
//  which in turn transports it to the renderer. The object contains the
//  packet data read from the file along with the time when it should be
//  delivered to the renderer. If there are no more packets available for
//  this stream, the RMA core is notified. This method is called after the
//  packet data from the file has been read.
//
HX_RESULT
CRnMp3Fmt::MyCreatePacketObj_hr(HX_RESULT   status,
                                tReadBuffer* pPacketData)
{
    m_State = Ready;

    if (status == HX_STATUS_OK)
    {
        // Create new object containing the packet data
        IHXPacket* pPacketObj = NULL;
        m_pClassFactory->CreateInstance(CLSID_IHXPacket,
                                         (void**)&pPacketObj);
        if (pPacketObj != NULL)
        {
            // Fill in the packet
            UINT32 deliveryTime = m_ulNextPacketDeliveryTime;
            UINT16 streamNo     = MY_STREAM_NO;
            UINT8  ASMFlags     = HX_ASM_SWITCH_ON | HX_ASM_SWITCH_OFF;
            UINT16 ASMRuleNo    = 0;
    
            IHXBuffer* pPacketBuffer = NULL;
TOP:
            int     nSyncSize = 0;
            UCHAR   *pModFrameStart = NULL;

            // Extract an audio frame from the read buffer
            pModFrameStart = GetMP3Frame_p(pPacketData, nSyncSize);

            // Handle read buffer wraps
            if (!pModFrameStart)
            {
                UCHAR   bNoData = m_bEOF;
                
                // Check for mp3 streams w/ garbage on the end (non-SureStream)
                // If the next 2 bytes are not a sync word, stop playback
                if (pPacketData->dwBytesRemaining >= 2)
                {
                    if (pPacketData->pBuffer[0] != 0xFF ||
                        !m_pMp3Fmt->IsValidSyncWord(pPacketData->pBuffer[1]))
                    {
                        // The rest of this buffer does not contain
                        // a syncword, so skip the buffer
                        m_bCheckBadData = 1;
                    }
                    else
                    {
                        // We have a syncword, but just not
                        // enough data in the buffer to complete the
                        // frame. So this is NOT bad data, just another
                        // read is necessary
                        m_bCheckBadData = 0;
                    }
                }
                
                if (bNoData)
                {
#if defined (MPA_FMT_DRAFT00)
                     // Check for last frame when streaming - we buffer one frame   
                     if (m_bStreaming && !m_bRtp)   
                     {   
                         UINT32 ulTemp = 0;   
                         pModFrameStart = m_pFmtBuf->GetReadPointer(ulTemp);   
                            
                         bNoData = (ulTemp == 0);   
                     }
#endif //MPA_FMT_DRAFT00
    
                     if (bNoData)   
                     { 
                    
                        HX_RELEASE(pPacketData->pReadBuffer);
                        pPacketData->dwBytesRemaining = 0;

                        m_bEOF = TRUE;
                        m_pStatus->StreamDone(0);

                        pPacketObj->Release();

                        if (pPacketBuffer)
                            pPacketBuffer->Release();

                        return HXR_OK;
                    }
                }
                
                // If we need more data, seek back the number of bytes
                // we have left and read more.
                if (!pModFrameStart)
                {
                    m_bNeedPacket = 1;
                    m_State = GetPacketSeekPending;

                    // XXXMEH - if m_bCheckBadData == 0, then we
                    // found a frame, but it is just incomplete.
                    // Therefore, we need to read some more to
                    // complete the frame. This is a normal occurrence.
                    // We will seek to the end of the last frame we 
                    // found and do a read. This should allow us to
                    // get the entire frame in the read buffer.
                    // However, if m_bCheckBadData == 1, then we
                    // didn't find a frame in the rest of the buffer
                    // we currently have. Therefore, don't want to 
                    // seek to the end of the last frame, we want to
                    // seek to the end of where we just read, thus
                    // skipping this data in which we know no frames
                    // are present.
                    if (!m_bCheckBadData)
                    {
                        m_ulBytesRead -= pPacketData->dwBytesRemaining;
                    }
                    else
                    {
                        // Add to the amount of bad data we're skipping
                        m_ulGarbageBytesRead += pPacketData->dwBytesRemaining;
                    }

                    pPacketData->dwBytesRemaining = 0;
                    HX_RELEASE(pPacketData->pReadBuffer);

                    if (m_ulGarbageBytesRead < MAX_GARBAGE_BYTES)
                    {

⌨️ 快捷键说明

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