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 + -
显示快捷键?