📄 mp3ff.cpp
字号:
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 + -