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

📄 mp3ff.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
                m_ReadBuf.pReadBuffer = pBufferRead;
                m_ReadBuf.pReadBuffer->AddRef();
                m_ReadBuf.pBuffer = pBufferRead->GetBuffer();
                m_ReadBuf.dwBytesRemaining = pBufferRead->GetSize();
                m_ReadBuf.dwBufferSize = pBufferRead->GetSize();

                if (m_ReadBuf.dwBufferSize < kReadSize)
                    m_bEOF = TRUE;
                else
                    m_bEOF = FALSE;

#if defined(HELIX_FEATURE_MP3FF_SHOUTCAST)
               
                // Check for the first shoutcast song title meta data.
                // Some servers do not send the data when we expect them
                // to so sync the first location.
                if (m_bFirstMeta)
                {
                    int nBytes = m_ReadBuf.dwBufferSize;
                    char *pScan = (char*)m_ReadBuf.pBuffer;
                    char *p = NULL;

                    // Look for "StreamTitle" in the binary buffer.  Since meta
                    // data is text inside of a binary stream, we can not use
                    // string functions.
                    while (nBytes>0)
                    {
                        p = (char*)memchr((const char *)pScan, 'S', nBytes);

                        if (p)
                        {
                            nBytes -= p - pScan;

                            if (nBytes > 10 && 
                                !strncmp((const char *)p, "StreamTitle", 11))
                            {
                                // Meta data starts one byte before "StreamTitle"
                                int offset = (PTR_INT)p - (PTR_INT)m_ReadBuf.pBuffer - 1;
                                HX_ASSERT(m_ulNextMetaPos == m_ulBytesRead - m_ReadBuf.dwBytesRemaining + offset);
                                
                                m_ulNextMetaPos = m_ulBytesRead - m_ReadBuf.dwBytesRemaining + offset;
                                m_bFirstMeta = FALSE;

                                break;
                            }
                            
                            pScan = p+1;
                            --nBytes;
                        }
                        else
                        {
                            break;
                        }
                    }
                }
               
                // Find the length of the next ShoutCast meta packet
                if (m_ulNextMetaPos < m_ulBytesRead && !m_ulMetaLength)
                {
                    UINT32 ulBytesToMeta = m_ulNextMetaPos - (m_ulBytesRead - 
                        m_ReadBuf.dwBytesRemaining);

                    m_ulMetaLength = m_ReadBuf.pBuffer[ulBytesToMeta] * 16 + 1;

                    // The meta data spans this buffer.  So, move the file pointer
                    // to the start of the meta data and change the properties of
                    // m_ReadBuf to exclude the partial meta data.  This way, we
                    // will get the meta data on our next read.
                    if (m_ulMetaLength + ulBytesToMeta > m_ReadBuf.dwBufferSize)
                    {
                        if(m_ulMetaLength < MAX_METADATA)
                        {
                            m_ulBytesRead -= m_ReadBuf.dwBufferSize - 
                                ulBytesToMeta;
                            m_ReadBuf.dwBufferSize -= m_ReadBuf.dwBufferSize -
                                ulBytesToMeta;
                            m_ReadBuf.dwBytesRemaining = 
                                m_ReadBuf.dwBufferSize;
                            m_ulMetaReadSize = m_ulMetaLength;
                            m_ulMetaLength = 0;
                        
                            m_State = SeekToOffsetNoRead;
                            m_pFileObj->Seek(m_ulBytesRead, FALSE);
                        }
                        // this is not good meta data
                        else
                        {
                            m_ulNextMetaPos += m_pMp3Fmt->GetMetaRepeat();
                            m_ulMetaLength = 0;
                        }
                    }

                    unsigned char *pTemp = &m_ReadBuf.pBuffer[ulBytesToMeta+1];

                    // Update player's gui with the new song title
                    if (m_ulMetaLength > 1 && 
                        !strncmp((const char *)pTemp, "StreamTitle", 11))
                    {
                        IHXBuffer  *pTitle = NULL;
                        m_pClassFactory->CreateInstance(CLSID_IHXBuffer, 
                            (void**)&pTitle);
                        if (pTitle)
                        {
                            pTemp = m_ReadBuf.pBuffer+ulBytesToMeta+14;
                            size_t nLen;

                            // Get the length of just the song title
                            pTemp = (unsigned char*)dbcsFindChar(
                                    (const char*)pTemp, ';', m_ulMetaLength);
                            
                            if(pTemp)
                            {
                                nLen = pTemp - 1 -
                                    (m_ReadBuf.pBuffer+ulBytesToMeta+14);
                            }
                            else
                            {
                                nLen = dbcsStrSize((const char*)
                                    (m_ReadBuf.pBuffer+ulBytesToMeta+14), 
                                    m_ulMetaLength);

                                if(nLen == m_ulMetaLength)
                                {
                                    // Not good metadata
                                    m_ulNextMetaPos += 
                                        m_pMp3Fmt->GetMetaRepeat();
                                    m_ulMetaLength = 0;
                                }
                            }

#if defined(HELIX_FEATURE_REGISTRY)
                            if(m_ulMetaLength)
                            {
                                // Put the song title in an IHXBuffer
                                pTitle->Set(m_ReadBuf.pBuffer+ulBytesToMeta+14,
                                    nLen+1);
                                pTitle->GetBuffer()[nLen] = '\0';

                                m_pRegistry->SetStrByName(
                                    (char*)m_szPlayerReg->GetBuffer(), pTitle);
                                HX_RELEASE(pTitle);

                                m_pClassFactory->CreateInstance(
                                    CLSID_IHXBuffer, (void**)&pTitle);

                                // Set station as title
                                int nTitle = 0;
                                m_pMp3Fmt->GetId3Title(nTitle);
                                if (nTitle && pTitle)
                                {
                                    pTitle->Set(m_pMp3Fmt->GetId3Title(nTitle),
                                        nTitle+1);

                                    // Put the song title in the registry
                                    char szTitle[128]; /* Flawfinder: ignore */
                                    
                                    SafeStrCpy(szTitle, 
                                         (char*)m_szPlayerReg->GetBuffer(), 128); 
                                    strcpy(&szTitle[strlen(szTitle)-6], /* Flawfinder: ignore */
                                        "Title");
                                    m_pRegistry->SetStrByName(szTitle, pTitle);
                                }
                            }
#endif /* #if defined(HELIX_FEATURE_REGISTRY) */

                            HX_RELEASE(pTitle);
                        }
                    }
                }
#endif //HELIX_FEATURE_MP3FF_SHOUTCAST
            }
            
            // If there was an error, set EOF
            else
            {
                m_bEOF = TRUE;
                
                HX_RELEASE(m_ReadBuf.pReadBuffer);
                m_pStatus->StreamDone(0);

                return HXR_OK;
            }

            m_ReadBuf.status = status;

            // If the read call did not finish inside of GetPacket
            // (http streaming), then create a packet when the read finished.
            if (m_bNeedPacket && m_ReadBuf.dwBytesRemaining)
            {
                m_bNeedPacket = 0;

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

        default:
            return HXR_UNEXPECTED;
    }

    return HXR_OK;
}


///////////////////////////////////////////////////////////////////////////////
//  Method:
//      IHXFileStatResponse::StatDone
//  Purpose:
//      Called in response to a Stat call on a IHXFileStat object
//      
//
STDMETHODIMP
CRnMp3Fmt::StatDone(HX_RESULT status,
                    UINT32 ulSize,
                    UINT32 ulCreationTime,
                    UINT32 ulAccessTime,
                    UINT32 ulModificationTime,
                    UINT32 ulMode)
{
    // If we do not know the file length, assume it is a live file
    if (HXR_OK == status && !ulSize)
        ulSize = 54000000;
    
    m_ulFileSize = ulSize;

    if (m_ulFileSize == 54000000 ||
        m_ulFileSize == 34000000 ||
        m_ulFileSize == 99999999)
        m_bLive = 1;

    return HXR_OK;
}

///////////////////////////////////////////////////////////////////////////////
//  IHXFileFormatObject::Seek                               ref:  hxformt.h
//
//  This routine moves to the packet nearest to the requested time in the
//  file. It is called, for example, in response to the user moving the
//  slider to a different location in the playback timeline.
//
STDMETHODIMP
CRnMp3Fmt::Seek(UINT32 requestedTime)
{
    // Find nearest packet to the requested time
    UINT32 ulPacketNo = (UINT32)(requestedTime / m_Info.dTimePerFrame);
    UINT32 ulPacketStart = ulPacketNo * m_Info.nPacketSize + m_ulFileOffset;

    m_dNextPts = ulPacketNo * m_Info.dTimePerFrame;
    m_ulNextPacketDeliveryTime = (UINT32)(m_dNextPts);

    // Note state, since Seek() is asynchronous
    m_State = SeekSeekPending;

    // Release our buffered reads
    DiscardReadBuffers_v();

    m_bEOF = FALSE;

#if defined (MPA_FMT_DRAFT00)
    // If we are reformatting mp3 frames, make sure we
    // skip the vbr header at the start of the file.
    if (!ulPacketStart && m_bStreaming && !m_bRtp)
        m_bSkipVbrHdr = m_bHasVbrHdr;

    memset(&m_RtpPackets, 0, sizeof(m_RtpPackets));
    m_RtpPackets.ulBytesFree = RTP_PACKET_SIZE;
    m_RtpPackets.dScr = m_dNextPts;
    m_RtpPackets.dPts = m_dNextPts;
#endif //MPA_FMT_DRAFT00
    
    // Move to the requested location in the file
    m_ulBytesRead = ulPacketStart;
    m_pFileObj->Seek(ulPacketStart, FALSE);

    return HXR_OK;
}

///////////////////////////////////////////////////////////////////////////////
//  IHXFileFormatObject::Close                              ref:  hxformt.h
//
//  This routine handles any cleanup required before closing the plug-in. All
//  references to objects should be released and memory deallocated. This is
//  called by the RMA core when the playback is finished or stopped.
//
STDMETHODIMP
CRnMp3Fmt::Close(void)
{
    m_bClosed = TRUE;
    
    if (m_pFileObj != NULL)
    {
        m_pFileObj->Close();
        m_pFileObj->Release();
        m_pFileObj = NULL;
    }

#if defined(HELIX_FEATURE_REGISTRY)
    if (m_pRegistry && m_szPlayerReg)
    {   
        m_pRegistry->SetStrByName((char*)m_szPlayerReg->GetBuffer(), NULL);
    }
    HX_RELEASE(m_pRegistry);
#endif /* #if defined(HELIX_FEATURE_REGISTRY) */

    HX_RELEASE(m_pStatus);
    HX_RELEASE(m_pError);
    HX_RELEASE(m_szPlayerReg);
    HX_RELEASE(m_pClassFactory);
    HX_RELEASE(m_pContext);
    HX_RELEASE(m_pMetaProps);
    
#if defined(MPA_FMT_DRAFT00)
    HX_DELETE(m_pFmtBuf);
#endif /* #if defined(MPA_FMT_DRAFT00) */

    return HXR_OK;
}

///////////////////////////////////////////////////////////////////////////////
//  IHXFileResponse::CloseDone, WriteDone                   ref:  hxfiles.h
//
//  This routines are not used in this example, but are required to complete
//  the IHXFileResponse interface.
//
STDMETHODIMP CRnMp3Fmt::CloseDone(HX_RESULT /* result */)
{
    return HXR_OK;
}

STDMETHODIMP CRnMp3Fmt::WriteDone(HX_RESULT /* result */)
{
    return HXR_OK;
}


///////////////////////////////////////////////////////////////////////////////
//  CRnMp3Fmt::~CRnMp3Fmt              ref:  filefmt1.h
//
//  Destructor
//
CRnMp3Fmt::~CRnMp3Fmt(void)
{
    Close();
    DiscardReadBuffers_v();

    HX_DELETE(m_pMp3Fmt);
}


// IUnknown COM Interface Methods

///////////////////////////////////////////////////////////////////////////////
//  IUnknown::AddRef                                            ref:  hxcom.h
//
//  This routine increases the object reference count in a thread safe
//  manner. The reference count is used to manage the

⌨️ 快捷键说明

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