mp4gpyld.cpp
来自「symbian 下的helix player源代码」· C++ 代码 · 共 1,691 行 · 第 1/3 页
CPP
1,691 行
{
pAUFragments[ulIdx]->m_pData += ulAUStart;
}
}
else
{
// AU Headers are not present - rely on
// constant size configuration te determine the
// AU offsets
ulAUSizeSum = pBuffer->GetSize() - ulAUStart;
ulAUSize = m_Config.m_ulConstantSize;
if (ulAUSize == 0)
{
ulAUSize = ulAUSizeSum;
}
if (ulAUSize > 0)
{
if (ulAUSize <= ulAUSizeSum)
{
ulFixedSizeAUCount = ulAUSizeSum / ulAUSize;
}
else
{
// this can only happen if we have pre-configured AU sizes,
// no AU headers, and this AU has been fragmented.
if (ulAUSizeSum != 0)
{
ulFixedSizeAUCount = 1;
}
}
if (ulFixedSizeAUCount > 0)
{
ulIdx = 0;
retVal = HXR_OK;
do
{
pAUPacket = new CAUPacket;
if (!pAUPacket)
{
retVal = HXR_OUTOFMEMORY;
break;
}
// Buffer
pAUPacket->m_pBuffer = pBuffer;
pBuffer->AddRef();
// Data
pAUPacket->m_pData = pData + ulAUStart + ulIdx * ulAUSize;
// AU - size
pAUPacket->m_ulSize = ulAUSize;
// AU - index
pAUPacket->m_ulIdx = ulIdx;
// CTS
ulVal = ulIdx * m_TSConverter.ConvertVector(m_ulAUDuration);
pAUPacket->m_ulCTS = ulStartCTS + ulVal;
if ((ulVal == 0) && (ulIdx != 0))
{
pAUPacket->m_bMinTime = TRUE;
}
// DTS
pAUPacket->m_ulDTS = pAUPacket->m_ulCTS;
ulIdx++;
pAUFragments[ulNumAUFragments++] = pAUPacket;
} while (ulIdx < ulFixedSizeAUCount && ulNumAUFragments < ulMaxAUFragments);
}
}
}
}
return retVal;
}
HX_RESULT MP4GPayloadFormat::AggregateAUFragments(CAUPacket** &pAUPackets,
ULONG32 &ulNumAUPackets,
ULONG32 &ulMaxAUPackets,
CAUPacket** pAUFragments,
ULONG32 &ulNumAUFragments)
{
HX_RESULT retVal = HXR_OK;
FlushAUArray(pAUPackets, ulNumAUPackets);
if (IsFragmentCollection(pAUFragments, ulNumAUFragments))
{
// Compute actual fragment collection size
ULONG32 ulFragmentyIdx;
UINT32 ulHeaderSize;
ULONG32 ulActualCollectionSize = 0;
for (ulFragmentyIdx = 0;
ulFragmentyIdx < ulNumAUFragments;
ulFragmentyIdx++)
{
ulHeaderSize = (UINT32) (pAUFragments[ulFragmentyIdx]->m_pData -
pAUFragments[ulFragmentyIdx]->m_pBuffer->GetBuffer());
ulActualCollectionSize += (pAUFragments[ulFragmentyIdx]->m_pBuffer->GetSize() -
ulHeaderSize);
}
if (ulActualCollectionSize == pAUFragments[0]->m_ulSize)
{
// All fragments are accounted for - aggregate all
IHXBuffer* pBuffer = NULL;
CAUPacket* pAUPacket = new CAUPacket;
retVal = HXR_OUTOFMEMORY;
if (pAUPacket)
{
retVal = HXR_OK;
}
// Create Buffer
if (SUCCEEDED(retVal))
{
retVal = m_pClassFactory->CreateInstance(IID_IHXBuffer,
(void**) &pBuffer);
}
if (SUCCEEDED(retVal))
{
retVal = pBuffer->SetSize(ulActualCollectionSize);
}
// Aggregate into the Buffer
if (SUCCEEDED(retVal))
{
UINT8* pDataWriter = pBuffer->GetBuffer();
UINT32 ulFragmentSize;
for (ulFragmentyIdx = 0;
ulFragmentyIdx < ulNumAUFragments;
ulFragmentyIdx++)
{
ulHeaderSize = (UINT32) (pAUFragments[ulFragmentyIdx]->m_pData -
pAUFragments[ulFragmentyIdx]->m_pBuffer->GetBuffer());
ulFragmentSize = pAUFragments[ulFragmentyIdx]->m_pBuffer->GetSize() -
ulHeaderSize;
memcpy(pDataWriter, /* Flawfinder: ignore */
pAUFragments[ulFragmentyIdx]->m_pData,
ulFragmentSize);
pDataWriter += ulFragmentSize;
}
}
// Populate the aggregated AUPacket
if (SUCCEEDED(retVal))
{
// Buffer
pAUPacket->m_pBuffer = pBuffer;
pBuffer = NULL;
// Data
pAUPacket->m_pData = pAUPacket->m_pBuffer->GetBuffer();
// AU - size
pAUPacket->m_ulSize = ulActualCollectionSize;
// AU - index
pAUPacket->m_ulIdx = pAUFragments[0]->m_ulIdx;
// CTS
pAUPacket->m_ulCTS = pAUFragments[0]->m_ulCTS;
pAUPacket->m_bMinTime = pAUFragments[0]->m_bMinTime;
// DTS
pAUPacket->m_ulDTS = pAUFragments[0]->m_ulDTS;
// Set to output
pAUPackets[0] = pAUPacket;
ulNumAUPackets = 1;
pAUPacket = NULL;
}
HX_RELEASE(pBuffer);
HX_DELETE(pAUPacket);
}
else
{
// Something is missing or is corrupted - discard data
retVal = HXR_FAIL;
}
// Flush the input fragmants
FlushAUArray(pAUFragments, ulNumAUFragments);
}
else
{
// No aggregation necessary
ulNumAUPackets = ulNumAUFragments;
memcpy(pAUPackets, pAUFragments, sizeof(CAUPacket*) * ulNumAUFragments); /* Flawfinder: ignore */
memset(pAUFragments, 0, sizeof(CAUPacket*) * ulNumAUFragments);
ulNumAUFragments = 0;
}
return retVal;
}
BOOL MP4GPayloadFormat::IsFragmentCollection(CAUPacket** pAUFragments,
ULONG32 ulNumAUFragments)
{
BOOL bRetVal = FALSE;
if (ulNumAUFragments > 0)
{
// Even if we have only one fragment, this could still be a fragment
// collection in which all but one fragment were lost
UINT32 ulHeaderSize = (UINT32) (pAUFragments[0]->m_pData -
pAUFragments[0]->m_pBuffer->GetBuffer());
bRetVal = ((ulHeaderSize + pAUFragments[0]->m_ulSize)
> pAUFragments[0]->m_pBuffer->GetSize());
}
return bRetVal;
}
HX_RESULT MP4GPayloadFormat::DeinterleaveAUPackets(CAUPacket** pAUPackets,
ULONG32 &ulNumAUPackets)
{
ULONG32 ulIdx;
HX_RESULT retVal = HXR_OK;
for (ulIdx = 0; ulIdx < ulNumAUPackets; ulIdx++)
{
if (SUCCEEDED(DeinterleaveAUPacket(pAUPackets[ulIdx])))
{
pAUPackets[ulIdx] = NULL;
}
else
{
HX_DELETE(pAUPackets[ulIdx]);
}
}
ulNumAUPackets = 0;
return retVal;
}
HX_RESULT MP4GPayloadFormat::DeinterleaveAUPacket(CAUPacket* pAUPacket)
{
ULONG32 ulCount = m_DeinterleaveQueue.GetCount();
if (ulCount == 0)
{
m_DeinterleaveQueue.AddTail(pAUPacket);
}
else
{
CAUPacket* pListAUPacket;
LISTPOSITION lPos = m_DeinterleaveQueue.GetTailPosition();
LISTPOSITION lInsertPos = lPos;
ULONG32 ulPrevIdx = 0xFFFFFFFF;
pListAUPacket = (CAUPacket*) m_DeinterleaveQueue.GetAt(lPos);
do
{
if (!MayAUPacketPrecede(pAUPacket, pListAUPacket))
{
m_DeinterleaveQueue.InsertAfter(lInsertPos, pAUPacket);
break;
}
ulCount--;
if (ulCount == 0)
{
CAUPacket lastReapedAUPacket;
lastReapedAUPacket.m_ulDTS = m_ulLastReapedDTS;
lastReapedAUPacket.m_ulIdx = m_ulLastReapedIdx;
lastReapedAUPacket.m_bMinTime = m_bLastReapedMinTime;
if (m_bLastReapedSet &&
MayAUPacketPrecede(&lastReapedAUPacket, pAUPacket))
{
m_DeinterleaveQueue.InsertBefore(lPos, pAUPacket);
}
else
{
m_DeinterleaveQueue.InsertAfter(lInsertPos, pAUPacket);
}
break;
}
pListAUPacket = (CAUPacket*) m_DeinterleaveQueue.GetAtPrev(lPos);
if (MayAUPacketPrecede(pListAUPacket, pAUPacket))
{
lInsertPos = lPos;
}
} while (TRUE);
}
return HXR_OK;
}
HX_RESULT MP4GPayloadFormat::ReapMediaPacket(ULONG32 ulLastPacketTime)
{
CAUPacket* pAUPacket;
CMediaPacket* pMediaPacket;
HX_RESULT retVal = HXR_NO_DATA;
if (!m_DeinterleaveQueue.IsEmpty())
{
BOOL bTryAgain;
BOOL bUnknownTime;
if ((!m_bEarliestDeintTimeKnown) && (!m_bFlushed))
{
m_bEarliestDeintTimeKnown = FindEarliestKnownDeintTime(m_ulEarliestDeintTimeKnown);
}
do
{
bTryAgain = FALSE;
pAUPacket = (CAUPacket*) m_DeinterleaveQueue.GetHead();
if ((m_bEarliestDeintTimeKnown &&
(!TestTimeGreater(m_ulEarliestDeintTimeKnown, m_ulLastPacketTime)))
||
(m_bLastReapedSet &&
(IndexDiff(pAUPacket->m_ulIdx, m_ulLastReapedIdx) == 1))
||
m_bFlushed)
{
ULONG32 ulFlags = MDPCKT_USES_IHXBUFFER_FLAG;
pAUPacket = (CAUPacket*) m_DeinterleaveQueue.GetHead();
bUnknownTime = pAUPacket->m_bMinTime;
if (bUnknownTime)
{
ulFlags |= MDPCKT_HAS_UKNOWN_TIME_FLAG;
}
else
{
m_bEarliestDeintTimeKnown = FALSE;
}
if (m_bLastReapedSet)
{
if (IndexDiff(pAUPacket->m_ulIdx, m_ulLastReapedIdx) != 1)
{
ulFlags |= MDPCKT_FOLLOWS_LOSS_FLAG;
}
}
m_bLastReapedMinTime = pAUPacket->m_bMinTime;
m_ulLastReapedDTS = pAUPacket->m_ulCTS;
m_ulLastReapedIdx = pAUPacket->m_ulIdx;
m_bLastReapedSet = TRUE;
pMediaPacket = new CMediaPacket(pAUPacket->m_pBuffer,
pAUPacket->m_pData,
pAUPacket->m_ulSize,
pAUPacket->m_ulSize,
pAUPacket->m_ulCTS,
ulFlags,
NULL);
retVal = HXR_OUTOFMEMORY;
if (pMediaPacket)
{
m_DeinterleaveQueue.RemoveHead();
delete pAUPacket;
m_OutputQueue.AddTail(pMediaPacket);
bTryAgain = TRUE;
retVal = HXR_OK;
}
}
else if ((!m_bEarliestDeintTimeKnown) && (!m_bFlushed))
{
m_bEarliestDeintTimeKnown = FindEarliestKnownDeintTime(m_ulEarliestDeintTimeKnown);
bTryAgain = m_bEarliestDeintTimeKnown;
}
} while (bTryAgain &&
(!m_DeinterleaveQueue.IsEmpty()));
}
return retVal;
}
STDMETHODIMP
MP4GPayloadFormat::Flush()
{
m_bFlushed = TRUE;
return HXR_OK;
}
void MP4GPayloadFormat::FlushQueues(void)
{
FlushInputQueue(FLUSH_ALL_PACKETS);
FlushDeinterleaveQueue(FLUSH_ALL_PACKETS);
FlushOutputQueue(FLUSH_ALL_PACKETS);
}
void MP4GPayloadFormat::FlushInputQueue(ULONG32 ulCount)
{
IHXPacket* pDeadPacket;
while ((ulCount > 0) && (!m_InputQueue.IsEmpty()))
{
pDeadPacket = (IHXPacket*) m_InputQueue.RemoveHead();
HX_RELEASE(pDeadPacket);
if (ulCount != FLUSH_ALL_PACKETS)
{
ulCount--;
}
}
}
void MP4GPayloadFormat::FlushDeinterleaveQueue(ULONG32 ulCount)
{
CAUPacket* pDeadPacket;
while ((ulCount > 0) && (!m_DeinterleaveQueue.IsEmpty()))
{
pDeadPacket = (CAUPacket*) m_DeinterleaveQueue.RemoveHead();
HX_DELETE(pDeadPacket);
if (ulCount != FLUSH_ALL_PACKETS)
{
ulCount--;
}
}
m_bEarliestDeintTimeKnown = FALSE;
m_bLastReapedSet = FALSE;
}
void MP4GPayloadFormat::FlushOutputQueue(ULONG32 ulCount)
{
CMediaPacket* pDeadPacket;
while ((ulCount > 0) && (!m_OutputQueue.IsEmpty()))
{
pDeadPacket = (CMediaPacket*) m_OutputQueue.RemoveHead();
HX_DELETE(pDeadPacket);
if (ulCount != FLUSH_ALL_PACKETS)
{
ulCount--;
}
}
}
BOOL MP4GPayloadFormat::FindEarliestKnownDeintTime(ULONG32 &ulEarliestKnownDeintTime)
{
ULONG32 ulCount;
LISTPOSITION lPos;
CAUPacket* pPacket;
ulCount = m_DeinterleaveQueue.GetCount();
if (ulCount > 0)
{
lPos = m_DeinterleaveQueue.GetHeadPosition();
pPacket = (CAUPacket*) m_DeinterleaveQueue.GetHead();
do
{
if (!pPacket->m_bMinTime)
{
ulEarliestKnownDeintTime = pPacket->m_ulCTS;
return TRUE;
}
ulCount--;
if (ulCount == 0)
{
break;
}
pPacket = (CAUPacket*) m_DeinterleaveQueue.GetAtNext(lPos);
} while (TRUE);
}
return FALSE;
}
void MP4GPayloadFormat::FlushArrays(void)
{
FlushPacketArray(m_pPacketFragments, m_ulNumPacketFragments);
FlushAUArray(m_pAUFragments, m_ulNumAUFragments);
FlushAUArray(m_pAUPackets, m_ulNumAUPackets);
}
ULONG32 MP4GPayloadFormat::GetPacketTime(IHXPacket* pPacket)
{
ULONG32 ulTime;
HX_ASSERT(pPacket);
if (m_bUsesRTPPackets)
{
ulTime = ((IHXRTPPacket*) pPacket)->GetRTPTime();
}
else
{
ulTime = pPacket->GetTime();
}
ulTime = m_TSConverter.Convert(ulTime);
return ulTime;
}
ULONG32 MP4GPayloadFormat::SignBitField(ULONG32 ulVal, ULONG32 ulNumBits)
{
if (ulNumBits > 0)
{
if (ulVal >> (ulNumBits - 1))
{
ulVal = (0xFFFFFFFF & ulVal);
}
}
else
{
ulVal = 0;
}
return ulVal;
}
BOOL MP4GPayloadFormat::TestIndexGreater(ULONG32 ulIdx1, ULONG32 ulIdx2)
{
return (ulIdx1 > ulIdx2);
}
BOOL MP4GPayloadFormat::TestTimeGreater(ULONG32 ulTime1, ULONG32 ulTime2)
{
return (((LONG32) (ulTime1 - ulTime2)) > 0);
}
LONG32 MP4GPayloadFormat::IndexDiff(ULONG32 ulIdx1, ULONG32 ulIdx2)
{
return SignBitField(ulIdx1 - ulIdx2, m_Config.m_ulIndexLength);
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?