📄 robpktparse.cpp
字号:
}
// We don't have a time stamp, but there are no more packets coming
dPresTime = m_dNextPts;
}
// If this is the first frame, set the time accordingly
if(m_bFirstFrame)
{
#if defined(WIN32) && defined(_DEBUG)
char str[256]; /* Flawfinder: ignore */
SafeSprintf(str, 256, "First decode, setting time to %lf\n", dPresTime);
OutputDebugString(OS_STRING(str));
#endif // defined(WIN32) && defined(_DEBUG)
m_dNextPts = dPresTime;
}
if(!m_bFirstFrame && dPresTime - m_dNextPts >= m_dFrameTime)
{
// We have frames lost before this one
#if defined(WIN32) && defined(_DEBUG)
char str[256]; /* Flawfinder: ignore */
SafeSprintf(str, 256, "Apparent packet loss: Index: %d, Cycle: %d, "
"PresTime: %lf, NextPts: %lf, FrameTime: %lf\n",
ulIndex, pCycle->nCycleIndex, dPresTime, m_dNextPts,
m_dFrameTime);
OutputDebugString(OS_STRING(str));
#endif // defined(WIN32) && defined(_DEBUG)
bLost = TRUE;
}
if(pFrameInfo && pFrameInfo->ulADUSize < 2)
{
// this frame is too small. skip it and do loss recovery
HX_DELETE(pCycle->pFrames[ulIndex]);
m_ulIndex = ulIndex + 1;
bLost = TRUE;
}
// If the frame was lost, we reuse the one already in the buffer,
// so don't need to copy or anything
if(!bLost)
{
IHXBuffer* pPacketBuf;
SFrameData* pFrameData;
UINT32 ulSize;
UCHAR* pBuf;
UCHAR* pDecBuf = m_pDecBuffer;
m_ulDecBufBytes = 0;
// Copy the frame into the decode buffer
for(pFrameData= pFrameInfo->pFrameData; pFrameData != NULL;
pFrameData = pFrameData->pNext)
{
pPacketBuf = pFrameData->pPacketBuf;
if(pPacketBuf)
{
pPacketBuf->Get(pBuf, ulSize);
if(pBuf && ulSize >= pFrameData->ulOffset + 2)
{
// seek to the frame offset
ulSize -= pFrameData->ulOffset;
pBuf += pFrameData->ulOffset;
if(pFrameInfo->ulADUSize < ulSize)
{
ulSize = pFrameInfo->ulADUSize;
}
// Make sure it will actually fit
if(ulSize > DEC_BUFFER_SIZE - m_ulDecBufBytes)
{
ulSize = DEC_BUFFER_SIZE - m_ulDecBufBytes;
}
memcpy(pDecBuf, pBuf, ulSize); /* Flawfinder: ignore */
m_ulDecBufBytes += ulSize;
pDecBuf += ulSize;
}
}
}
HX_DELETE(pCycle->pFrames[ulIndex]);
m_ulIndex = ulIndex + 1;
// Clear the main_data_begin (since we're reformatted)
m_pFmt->ClearMainDataBegin(m_pDecBuffer);
}
pFrameBuffer = m_pDecBuffer;
dTime = dPresTime;
m_dNextPts = dPresTime + m_dFrameTime;
m_bFirstFrame = FALSE;
return m_ulDecBufBytes;
}
UINT32 CRobustPacketParser::GetFrameInfo(IHXBuffer* pPacket, UINT32 ulOffset,
double dTime)
{
if(pPacket->GetSize() <= ulOffset)
{
return pPacket->GetSize();
}
UCHAR* pBuf = pPacket->GetBuffer() + ulOffset;
// bit 0: continuation bit
BOOL bCont = (pBuf[0] & 0x80) == 0 ? FALSE : TRUE;
// bit 1: Descriptor type flag
int nDescSize = (pBuf[0] & 0x40) == 0 ? 1 : 2;
if(pPacket->GetSize() - ulOffset < (UINT32)nDescSize + 2)
{
return pPacket->GetSize();
}
UINT32 ulADUSize;
int nIndex;
int nCycle;
// in a one byte descriptor, bits 2-7 are the ADU size
// in a two byte descriptor, bits 2-15 are the size
ulADUSize = nDescSize == 1 ? (pBuf[0] & 0x3F) :
((UINT32)(pBuf[0] & 0x3F) << 8) + pBuf[1];
pBuf += nDescSize;
// MPEG audio sync word is the first 12 bits, first 11 always set.
// if the sync word is in tact, we are not reordered
if(pBuf[0] == 0xFF && (pBuf[1] & 0xE0) == 0xE0)
{
nIndex = 0;
nCycle = -1;
}
// otherwise, the first 11 bits of the sync word are re-used to
// identify the frame order
else
{
// bits 0-7: frame index
nIndex = pBuf[0];
// bits 8-10: cycle
nCycle = (pBuf[1] & 0xE0) >> 5;
}
SCycle* pCycle = m_Cycles.IsEmpty() ? NULL : (SCycle*)m_Cycles.GetTail();
if(!pCycle || nCycle != pCycle->nCycleIndex || nCycle < 0)
{
// This is a new cycle
pCycle = new SCycle(nCycle);
if(pCycle == NULL)
{
return pPacket->GetSize();
}
pCycle->nMaxIndex = nIndex;
m_Cycles.AddTail(pCycle);
}
else if(nIndex > pCycle->nMaxIndex)
{
pCycle->nMaxIndex = nIndex;
}
SFrameData* pFrameData = new SFrameData();
SFrameData* pIterator;
pPacket->AddRef();
pFrameData->pPacketBuf = pPacket;
pFrameData->ulOffset = ulOffset + nDescSize;
pFrameData->bCont = bCont;
SFrameInfo* pInfo = pCycle->pFrames[nIndex];
if(pInfo != NULL)
{
// We have a frag. Note that the spec only accounts for a frame being
// split accross two packets when reordered. If one is split across
// more than two packets, we will assume the cont frags are in order
if(bCont || (pCycle->pFrames[nIndex]->pFrameData &&
!pCycle->pFrames[nIndex]->pFrameData->bCont))
{
pIterator = pCycle->pFrames[nIndex]->pFrameData;
if(pIterator)
{
while(pIterator->pNext != NULL)
pIterator = pIterator->pNext;
pFrameData->pNext = NULL;
pIterator->pNext = pFrameData;
}
else
{
pFrameData->pNext = pCycle->pFrames[nIndex]->pFrameData;
pCycle->pFrames[nIndex]->pFrameData = pFrameData;
}
}
// If this is not a continuation frame, it is the first frag
else
{
pFrameData->pNext = pCycle->pFrames[nIndex]->pFrameData;
pCycle->pFrames[nIndex]->pFrameData = pFrameData;
}
}
else
{
pFrameData->pNext = NULL;
pInfo = new SFrameInfo();
pInfo->nIndex = nIndex;
pInfo->ulADUSize = ulADUSize;
pInfo->pFrameData = pFrameData;
pInfo->dTime = dTime;
pCycle->pFrames[nIndex] = pInfo;
}
UINT32 ulSize = 0;
for(pIterator = pCycle->pFrames[nIndex]->pFrameData; pIterator!= NULL;
pIterator = pIterator->pNext)
{
HX_ASSERT(pIterator->pPacketBuf);
ulSize += pIterator->pPacketBuf->GetSize() - pIterator->ulOffset;
}
pInfo->bComplete = ulSize >= pInfo->ulADUSize ? TRUE : FALSE;
// Set first 11 bits
pBuf[0] = 0xFF;
pBuf[1] |= 0xE0;
// Init our decoder if needed
if(m_pDecoder || InitDecoder(pBuf, pPacket->GetSize() - ulOffset, FALSE))
{
// set the first frame's presentation time
if(dTime >= 0)
{
if(pCycle->dStartTime < 0)
{
pCycle->dStartTime = dTime - m_dFrameTime*(nIndex);
}
}
}
return min(pFrameData->ulOffset + ulADUSize, pPacket->GetSize());
}
HX_RESULT
CRobustPacketParser::RenderAll()
{
if(!m_pRenderer || !m_pFmt)
{
return HXR_FAIL;
}
UCHAR* pFrameBuf;
UINT32 ulSize;
BOOL bPacketLoss;
double dTime;
for(;;)
{
ulSize = GetFrame(pFrameBuf, dTime, bPacketLoss);
if(!pFrameBuf || !ulSize)
{
return HXR_OK;
}
if(!m_pDecoder && !InitDecoder(pFrameBuf, ulSize, TRUE))
{
return HXR_FAIL;
}
DecodeAndRender(pFrameBuf, ulSize, dTime, bPacketLoss);
}
}
void
CRobustPacketParser::PreSeek()
{
m_Cycles.DeleteAll();
m_ulIndex = 0;
m_bFirstFrame = TRUE;
CPacketParser::PreSeek();
}
void
CRobustPacketParser::PostSeek(UINT32 time)
{
m_Cycles.DeleteAll();
m_ulIndex = 0;
m_bFirstFrame = TRUE;
CPacketParser::PostSeek(time);
HX_DELETE(m_pTsConvert);
}
void
CRobustPacketParser::EndOfPackets()
{
m_bEndOfPackets = TRUE;
// Decode and render any frames left queued.
RenderAll();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -