📄 mp3ff.cpp
字号:
m_pFileObj->Seek(m_ulBytesRead, FALSE);
}
else
{
m_State = Ready;
m_pStatus->StreamDone(0);
}
pPacketObj->Release();
if (pPacketBuffer)
pPacketBuffer->Release();
return HXR_OK;
}
}
else
{
UINT32 ulOffset = m_ulBytesRead - pPacketData->dwBytesRemaining;
// char szDbgStr[256];
// sprintf(szDbgStr, "Frame of size %d found at offset %lu (%02x %02x %02x %02x) next offset = %lu\n",
// nSyncSize, ulOffset, pPacketData->pBuffer[0], pPacketData->pBuffer[1],
// pPacketData->pBuffer[2], pPacketData->pBuffer[3], ulOffset + nSyncSize);
// OutputDebugString(szDbgStr);
}
// Reformat the current MP3 frame if we are streaming
int nModFrameSize = nSyncSize;
#if defined (MPA_FMT_DRAFT00)
if (m_bStreaming && !m_bRtp)
{
// We need 1+ audio frames
UINT32 ulReadSize = 0;
pModFrameStart = m_pFmtBuf->GetReadPointer(ulReadSize);
UINT32 nSync = m_pMp3Fmt->CheckValidFrame(pModFrameStart, ulReadSize);
if (ulReadSize >= nSync + 6 ||
m_bEOF)
{
nModFrameSize = m_pMp3Fmt->ReformatMP3Frame(&pModFrameStart,
ulReadSize,
m_pFmtBuf->GetPrevBytes());
// If we did not have enough back data to reformat, skip this frame
// in the format buffer
if (!nModFrameSize)
m_pFmtBuf->AdvanceRead(nSync);
}
else
nModFrameSize = 0;
if (nModFrameSize)
m_pFmtBuf->AdvanceRead(nSync);
else
{
// Are we advancing the buffer by some
// positive amount?
if (nSyncSize > 0)
{
// Move to next sync word
pPacketData->pBuffer += nSyncSize;
pPacketData->dwBytesRemaining -= nSyncSize;
goto TOP;
}
else
{
// If we get here, then we have gotten
// lost on parsing this file, and likely
// the file is corrupt or unsupported.
// If we had tried to advance the buffer
// by zero, we would have entered an infinite
// loop. Therefore, we bail out.
HX_RELEASE(pPacketData->pReadBuffer);
m_pStatus->StreamDone(0);
return HXR_OK;
}
}
}
#endif //MPA_FMT_DRAFT00
// We need the pPacketBuffer here, but not before.
pPacketBuffer = (*m_pCreatePacketFunction)( m_pClassFactory,
pPacketData->pReadBuffer,
pModFrameStart,
nModFrameSize );
// Set packet data
if (nModFrameSize)
{
#if defined (MPA_FMT_DRAFT00)
// Copy the rtp payload header
if (m_bRtp)
{
pPacketBuffer->SetSize(nModFrameSize+m_RtpPackets.ulHeaderSize);
if (pPacketBuffer->GetSize() != (UINT32)nModFrameSize+m_RtpPackets.ulHeaderSize)
{
HX_RELEASE(pPacketBuffer);
HX_RELEASE(pPacketObj);
return HXR_OUTOFMEMORY;
}
memcpy(pPacketBuffer->GetBuffer(), /* Flawfinder: ignore */
m_RtpPackets.aHeader,
m_RtpPackets.ulHeaderSize);
memcpy(pPacketBuffer->GetBuffer()+m_RtpPackets.ulHeaderSize, /* Flawfinder: ignore */
pModFrameStart,
nModFrameSize);
// Reset rtp packet values
memset(&m_RtpPackets.aHeader, 0, sizeof(m_RtpPackets.aHeader));
m_RtpPackets.bPacketReady = 0;
m_RtpPackets.ulHeaders = 0;
m_RtpPackets.ulDataChunks = 0;
m_RtpPackets.ulBytesFree = RTP_PACKET_SIZE;
}
#endif //MPA_FMT_DRAFT00
if( m_bStreaming || m_bRtp || m_pMp3Fmt->GetMetaRepeat() )
{
pPacketBuffer->Set(pModFrameStart,nModFrameSize);
}
#if defined(HELIX_FEATURE_MP3FF_SHOUTCAST)
// If this packet has meta data, left shift the mp3
// data over the meta data.
if (m_bMetaPacket)
{
UCHAR *pTemp = pPacketBuffer->GetBuffer();
if (m_bRtp)
pTemp += 4;
UINT32 ulBytesToTitle = m_ulNextMetaPos -
(m_ulBytesRead - pPacketData->dwBytesRemaining);
for (UINT32 i=ulBytesToTitle;
i<(UINT32)nModFrameSize - m_ulMetaLength; i++)
pTemp[i] = pTemp[i+m_ulMetaLength];
pPacketBuffer->SetSize(pPacketBuffer->GetSize()-m_ulMetaLength);
// Set next meta data offset
m_ulNextMetaPos += m_pMp3Fmt->GetMetaRepeat() + m_ulMetaLength;
m_ulMetaLength = 0;
m_bMetaPacket = 0;
}
#endif //HELIX_FEATURE_MP3FF_SHOUTCAST
pPacketObj->Set(pPacketBuffer, deliveryTime, streamNo,
ASMFlags, ASMRuleNo);
}
// We know we've read good data now, so clear the
// amount of consecutive garbage bytes we've read.
m_ulGarbageBytesRead = 0;
// Set the delivery time for the next packet. Note that each
// packet is stamped with a delivery time which is used to pace
// the delivery of packets to the rendering plug-ins.
m_dNextPts += m_Info.dTimePerFrame;
m_ulNextPacketDeliveryTime = (UINT32)m_dNextPts;
// Move to next sync word
pPacketData->pBuffer += nSyncSize;
pPacketData->dwBytesRemaining -= nSyncSize;
// Notify the RMA core that the packet object is ready
if (nModFrameSize)
m_pStatus->PacketReady(status, pPacketObj);
// Release the object since we are done with it
pPacketObj->Release();
if (pPacketBuffer)
pPacketBuffer->Release();
}
else
return HXR_OUTOFMEMORY;
}
// No more packets are available for this stream
else
{
// Notify the RMA core that the stream is done
m_pStatus->StreamDone(0);
}
return HXR_OK;
}
///////////////////////////////////////////////////////////////////////////////
// IHXFileResponse::SeekDone ref: hxfiles.h
//
// This routine is automatically called when the Seek() operation in the
// file is complete. Other actions are then taken dependent on the current
// processing state.
//
STDMETHODIMP
CRnMp3Fmt::SeekDone(HX_RESULT status)
{
switch (m_State)
{
case SeekSeekPending:
// We are in the process of handling a Seek() request...
m_State = Ready;
// Notify the RMA core that the Seek() has completed
m_pStatus->SeekDone(status);
break;
case GetId3HeaderSeekPending:
// Return to default access
m_pFileObj->Advise(HX_FILEADVISE_ANYACCESS);
// If we failed,then we need to try again with
// this new HX_FILEADVISE_ANYACCESS mode. If we
// succeeded, then we can go ahead and read.
if (SUCCEEDED(status))
{
// We successfully seeked, so now read the ID3 tags, if any
m_State = GetId3HeaderReadPending;
m_pFileObj->Read(ID3HeaderLen+BytesBeforeID3Header);
}
else
{
// We tried to seek to the end of the file
// in order to get the ID3 tags, but the seek
// failed (that can sometimes happen if we're
// playing via http and we have a HTTP 1.0 server)
// If this happens, then we won't worry about getting
// the ID3 tags - we'll simply go ahead and seek
// back to the beginning of the file like we do
// after we read the ID3 tags.
m_State = GetFileHeaderSeekPending;
m_pFileObj->Seek(MY_FILE_HEADER_START, FALSE);
}
break;
case GetFileHeaderSeekPending:
{
m_State = GetFileHeaderReadPending;
// Read the file header data from the file.
// Read more when we are streaming - we need more
// accurate avg bitrate for vbrs when streaming.
UINT32 ulReadSize = MY_FILE_HEADER_LENGTH << 3;
if (m_bLive ||
m_pFileObj->Advise(HX_FILEADVISE_RANDOMACCESS) == HXR_ADVISE_PREFER_LINEAR)
{
ulReadSize = MY_FILE_HEADER_LENGTH;
}
m_pFileObj->Read(ulReadSize);
}
break;
case GetStreamHeaderSeekPending:
MyCreateStreamHeaderObj_v(HX_STATUS_OK, NULL);
break;
case GetPacketSeekPending:
{
m_State = GetPacketReadPending;
UINT32 ulReadSize = kReadSize;
#if defined(HELIX_FEATURE_MP3FF_SHOUTCAST)
if (m_ulMetaReadSize)
{
ulReadSize += m_ulMetaReadSize;
m_ulMetaReadSize = 0;
}
#endif //HELIX_FEATURE_MP3FF_SHOUTCAST
m_pFileObj->Read(ulReadSize);
break;
}
case SeekToOffsetNoRead:
m_State = Ready;
break;
default:
return HXR_UNEXPECTED;
}
return HXR_OK;
}
///////////////////////////////////////////////////////////////////////////////
// IHXFileResponse::ReadDone ref: hxfiles.h
//
// This routine is automatically called when the Read() from the file is
// done. Other actions are then taken dependent on the current processing
// state.
//
STDMETHODIMP
CRnMp3Fmt::ReadDone(HX_RESULT status,
IHXBuffer* pBufferRead)
{
/* This may happen in HTTP streaming when the file system
* is in still a seeking mode when the next seek is issued.
* The file system will then call SeekDone with a status of
* HXR_CANCELLED for the pending seek.
*/
if (status == HXR_CANCELLED)
{
return HXR_OK;
}
switch (m_State)
{
case GetId3HeaderReadPending:
{
if (pBufferRead)
{
// Try to extract ID3v1 header data
INT32 lTemp;
m_pMp3Fmt->CheckForHeaders(pBufferRead->GetBuffer()+BytesBeforeID3Header,
pBufferRead->GetSize()-BytesBeforeID3Header,
lTemp);
}
// Go back to the beginning and init the stream
m_State = GetFileHeaderSeekPending;
m_pFileObj->Seek(MY_FILE_HEADER_START, FALSE);
break;
}
case GetFileHeaderReadPending:
if (!pBufferRead)
return HXR_UNEXPECTED;
return MyCreateFileHeaderObj_hr(status, pBufferRead);
break;
case GetStreamHeaderReadPending:
if (!pBufferRead)
return HXR_UNEXPECTED;
MyCreateStreamHeaderObj_v(status, pBufferRead);
break;
case GetPacketReadPending:
{
// Buffer the read packet
if (HXR_OK == status && pBufferRead && pBufferRead->GetSize())
{
m_ulBytesRead += pBufferRead->GetSize();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -