mp4vpyld.cpp
来自「symbian 下的helix player源代码」· C++ 代码 · 共 1,393 行 · 第 1/2 页
CPP
1,393 行
retVal = m_pClassFactory->CreateInstance(CLSID_IHXBuffer,
(void**) &pNewBuffer);
}
// Set Buffer
if (SUCCEEDED(retVal))
{
retVal = pNewBuffer->Set(pRemainingData, ulFragmentSize);
}
// Set the new packet
if (SUCCEEDED(retVal))
{
if (SUCCEEDED(retVal))
{
if (m_bUsesRTPPackets)
{
retVal = ((IHXRTPPacket*) pNewPacket)->SetRTP(
pNewBuffer,
pRTPPacket->GetTime(),
pRTPPacket->GetRTPTime(),
pRTPPacket->GetStreamNumber(),
pRTPPacket->GetASMFlags(),
(ulRemainingSize > m_ulMaxPacketDataSize) ?
0 : pRTPPacket->GetASMRuleNumber());
}
else
{
retVal = ((IHXRTPPacket*) pNewPacket)->Set(
pNewBuffer,
pPacket->GetTime(),
pPacket->GetStreamNumber(),
pPacket->GetASMFlags(),
(ulRemainingSize > m_ulMaxPacketDataSize) ?
0 : pPacket->GetASMRuleNumber());
}
}
}
pRemainingData += ulFragmentSize;
ulRemainingSize -= ulFragmentSize;
if (ulRemainingSize < ulFragmentSize)
{
ulFragmentSize = ulRemainingSize;
}
if (SUCCEEDED(retVal))
{
pNewPacket->AddRef();
m_OutputPackets.AddTail(pNewPacket);
}
HX_RELEASE(pNewBuffer);
HX_RELEASE(pNewPacket);
} while (SUCCEEDED(retVal) && (ulRemainingSize > 0));
HX_RELEASE(pRTPPacket);
}
else
{
pPacket->AddRef();
m_OutputPackets.AddTail(pPacket);
}
HX_RELEASE(pPacketBuffer);
return retVal;
}
HX_RESULT MP4VPayloadFormat::GetRawPacketizerPacket(IHXPacket* &pOutPacket)
{
IHXPacket* pPacket;
IHXPacket* pAfterPacket = NULL;
IHXRTPPacket* pRTPPacket = NULL;
UINT16 uASMRuleNumber;
BOOL bMarker = TRUE;
BOOL bNewPictureStart = TRUE;
HX_RESULT retVal = HXR_INCOMPLETE;
if ((m_InputPackets.GetCount() > 1) ||
m_bFlushed)
{
retVal = HXR_OK;
pPacket = (IHXPacket*) m_InputPackets.RemoveHead();
if (!m_bPictureStarted)
{
m_bPictureStarted = IsPictureStart(pPacket);
}
if (m_bFirstPacket)
{
m_bFirstPacket = FALSE;
}
// Determine marker usage
if (m_InputPackets.GetCount() > 0)
{
pAfterPacket = (IHXPacket*) m_InputPackets.GetHead();
}
if (pAfterPacket)
{
bNewPictureStart = IsPictureStart(pAfterPacket);
bMarker = ((GetPacketTime(pPacket) != GetPacketTime(pAfterPacket)) ||
(bNewPictureStart && m_bPictureStarted));
if (bMarker)
{
m_bPictureStarted = bNewPictureStart;
}
}
else
{
bMarker = m_bFlushed;
}
uASMRuleNumber = bMarker ? 1 : 0;
// If rule number must change, create new packet
if (uASMRuleNumber != pPacket->GetASMRuleNumber())
{
IHXPacket* pNewPacket = NULL;
if (m_bUsesRTPPackets)
{
retVal = m_pClassFactory->CreateInstance(CLSID_IHXRTPPacket,
(void**) &pNewPacket);
if (SUCCEEDED(retVal))
{
retVal = pPacket->QueryInterface(IID_IHXRTPPacket,
(void**) &pRTPPacket);
}
}
else
{
retVal = m_pClassFactory->CreateInstance(CLSID_IHXPacket,
(void**) &pNewPacket);
}
if (SUCCEEDED(retVal))
{
IHXBuffer* pBuffer = pPacket->GetBuffer();
if (m_bUsesRTPPackets)
{
retVal = ((IHXRTPPacket*) pNewPacket)->SetRTP(
pBuffer,
pRTPPacket->GetTime(),
pRTPPacket->GetRTPTime(),
pRTPPacket->GetStreamNumber(),
pRTPPacket->GetASMFlags(),
uASMRuleNumber);
}
else
{
retVal = ((IHXRTPPacket*) pNewPacket)->Set(
pBuffer,
pPacket->GetTime(),
pPacket->GetStreamNumber(),
pPacket->GetASMFlags(),
uASMRuleNumber);
}
HX_RELEASE(pBuffer);
}
pPacket->Release();
pPacket = NULL;
if (SUCCEEDED(retVal))
{
pPacket = pNewPacket;
pNewPacket = NULL;
}
HX_RELEASE(pNewPacket);
HX_RELEASE(pRTPPacket);
}
if (SUCCEEDED(retVal))
{
pOutPacket = pPacket;
}
}
return retVal;
}
HX_RESULT MP4VPayloadFormat::GetAssemblerPacket(IHXPacket* &pOutPacket)
{
HX_RESULT retVal = HXR_NOTIMPL;
return retVal;
}
void MP4VPayloadFormat::FlushPackets(ULONG32 ulCount)
{
IHXPacket* pDeadPacket;
while ((ulCount > 0) && (!m_InputPackets.IsEmpty()))
{
pDeadPacket = (IHXPacket*) m_InputPackets.RemoveHead();
HX_RELEASE(pDeadPacket);
if (ulCount != FLUSH_ALL_PACKETS)
{
ulCount--;
}
}
}
ULONG32 MP4VPayloadFormat::CountValidPackets(ULONG32 ulCount)
{
IHXPacket* pPacket;
LISTPOSITION listPos;
ULONG32 ulValidCount = 0;
listPos = m_InputPackets.GetHeadPosition();
while ((ulCount > 0) && (listPos != NULL))
{
pPacket = (IHXPacket*) m_InputPackets.GetNext(listPos);
HX_ASSERT(pPacket);
if (!pPacket->IsLost())
{
ulValidCount++;
}
ulCount--;
}
return ulValidCount;
}
ULONG32 MP4VPayloadFormat::SumPacketSizes(ULONG32 ulCount)
{
IHXPacket* pPacket;
IHXBuffer* pBuffer;
LISTPOSITION listPos;
ULONG32 ulSize = 0;
listPos = m_InputPackets.GetHeadPosition();
while ((ulCount > 0) && (listPos != NULL))
{
pPacket = (IHXPacket*) m_InputPackets.GetNext(listPos);
HX_ASSERT(pPacket);
if (!pPacket->IsLost())
{
pBuffer = pPacket->GetBuffer();
if (pBuffer)
{
ulSize += pBuffer->GetSize();
pBuffer->Release();
}
}
ulCount--;
}
return ulSize;
}
HX_RESULT MP4VPayloadFormat::CreateHXCodecPacket(UINT32* &pHXCodecDataOut)
{
HX_RESULT retVal = HXR_INCOMPLETE;
if (m_ulFrameCount > 0)
{
// Compute frame size and count segments
ULONG32 ulFrameSize = 0;
ULONG32 ulSegmentCount = 0;
ULONG32 ulSegmentSize;
ULONG32 ulFrameTime = 0;
ULONG32 ulValidSegmentCount = 0;
IHXPacket* pPacket;
IHXBuffer* pBuffer = NULL;
LISTPOSITION listPos;
ULONG32 ulIdx;
BOOL bIsLost;
BOOL bPictureStarted = FALSE;
BOOL bNewPictureStart;
HXCODEC_DATA* pHXCodecData = NULL;
HXCODEC_SEGMENTINFO* pHXCodecSegmentInfo;
ULONG32* pData = NULL;
retVal = HXR_OK;
// Gather Frame Information - until valid frame detected
do
{
listPos = m_InputPackets.GetHeadPosition();
if( listPos == NULL )
{
return HXR_OUTOFMEMORY;
}
do
{
if (ulSegmentCount >= MAX_FRAME_SEGMENTS)
{
HX_ASSERT(pPacket);
FlushPackets(ulSegmentCount - NUM_OVERLAP_SEGMENTS);
ulSegmentCount = NUM_OVERLAP_SEGMENTS;
ulFrameSize = SumPacketSizes(NUM_OVERLAP_SEGMENTS);
ulValidSegmentCount = CountValidPackets(NUM_OVERLAP_SEGMENTS);
}
pPacket = (IHXPacket*) m_InputPackets.GetNext(listPos);
if (!pPacket->IsLost())
{
bNewPictureStart = IsPictureStart(pPacket);
if (ulValidSegmentCount > 0)
{
if ((GetPacketTime(pPacket) != ulFrameTime) ||
(bPictureStarted && bNewPictureStart))
{
break;
}
}
else
{
ulFrameTime = GetPacketTime(pPacket);
}
if (!bPictureStarted)
{
bPictureStarted = bNewPictureStart;
}
ulValidSegmentCount++;
pBuffer = pPacket->GetBuffer();
}
if (pBuffer)
{
ulFrameSize += pBuffer->GetSize();
pBuffer->Release();
pBuffer = NULL;
}
ulSegmentCount++;
} while (pPacket->GetASMRuleNumber() != 1);
m_ulFrameCount--;
} while ((ulValidSegmentCount == 0) &&
(m_ulFrameCount > 0));
if (ulValidSegmentCount == 0)
{
retVal = HXR_INCOMPLETE;
}
// Allocate codec data header
if (retVal == HXR_OK)
{
HX_ASSERT(ulSegmentCount != 0);
HX_ASSERT(ulValidSegmentCount != 0);
#ifdef _APPEND_VOL_HEADER
if (m_bFirstFrame)
{
ulFrameSize += m_ulVOLHeaderSize;
}
#endif // _APPEND_VOL_HEADER
pData = new ULONG32[(sizeof(HXCODEC_DATA) +
sizeof(HXCODEC_SEGMENTINFO) *
(ulSegmentCount - 1)) / 4 + 1];
retVal = HXR_OUTOFMEMORY;
if (pData)
{
retVal = HXR_OK;
}
}
// Init. codec data header
if (retVal == HXR_OK)
{
pHXCodecData = (HXCODEC_DATA*) pData;
pHXCodecData->dataLength = ulFrameSize;
pHXCodecData->timestamp = ulFrameTime;
pHXCodecData->sequenceNum = m_uSeqNumber;
pHXCodecData->flags = 0;
pHXCodecData->lastPacket = FALSE;
pHXCodecData->numSegments = ulSegmentCount;
pHXCodecData->data = NULL;
if ((ulFrameSize > 0)
#ifndef _OVERALLOC_CODEC_DATA
&&
(
(ulValidSegmentCount > 1) ||
(m_pAllocator == NULL)
#ifdef _APPEND_VOL_HEADER
|| m_bFirstFrame
#endif // _APPEND_VOL_HEADER
)
#endif // _OVERALLOC_CODEC_DATA
)
{
#ifdef _OVERALLOC_CODEC_DATA
ulFrameSize += _OVERALLOC_CODEC_DATA; // over allocate since codec reads 24bits at a time
#endif // _OVERALLOC_CODEC_DATA
if (m_pAllocator)
{
IHXUnknown* pIUnkn = NULL;
HX20ALLOCPROPS allocRequest;
HX20ALLOCPROPS allocActual;
allocRequest.uBufferSize = ulFrameSize;
allocRequest.nNumBuffers = 0;
m_pAllocator->SetProperties(&allocRequest, &allocActual);
pHXCodecData->data = m_pAllocator->GetPacketBuffer(&pIUnkn);
}
else
{
pHXCodecData->data = (UINT8*) new ULONG32 [ulFrameSize / 4 + 1];
}
if (pHXCodecData->data == NULL)
{
retVal = HXR_OUTOFMEMORY;
}
}
}
// Build Codec Data
if (retVal == HXR_OK)
{
BOOL bNoneLost = TRUE;
pHXCodecSegmentInfo = (HXCODEC_SEGMENTINFO*) &(pHXCodecData->Segments[0]);
ulFrameSize = 0;
for (ulIdx = 0; ulIdx < ulSegmentCount; ulIdx++)
{
HX_ASSERT(!m_InputPackets.IsEmpty());
pPacket = (IHXPacket*) m_InputPackets.RemoveHead();
HX_ASSERT(pPacket);
ulSegmentSize = 0;
pHXCodecSegmentInfo[ulIdx].ulSegmentOffset = ulFrameSize;
bIsLost = pPacket->IsLost();
if (!bIsLost)
{
pBuffer = pPacket->GetBuffer();
if (pHXCodecData->data)
{
if (m_bFirstFrame)
{
#ifdef _APPEND_VOL_HEADER
memcpy(pHXCodecData->data, m_pVOLHeader, m_ulVOLHeaderSize); /* Flawfinder: ignore */
ulFrameSize += m_ulVOLHeaderSize;
#endif // _APPEND_VOL_HEADER
m_bFirstFrame = FALSE;
}
if (pBuffer)
{
ulSegmentSize = pBuffer->GetSize();
HX_ASSERT(pHXCodecData->dataLength >= (ulFrameSize + ulSegmentSize));
memcpy(pHXCodecData->data + ulFrameSize, /* Flawfinder: ignore */
pBuffer->GetBuffer(),
ulSegmentSize);
pBuffer->Release();
}
}
else
{
HX_ASSERT(m_pAllocator);
HX_ASSERT(ulValidSegmentCount == 1);
#ifdef _APPEND_VOL_HEADER
HX_ASSERT(m_bFirstFrame == FALSE);
#endif // _APPEND_VOL_HEADER
if (pBuffer)
{
ulSegmentSize = pBuffer->GetSize();
pHXCodecData->data = m_pAllocator->AddBuffer(pBuffer);
pBuffer->Release();
}
}
ulFrameSize += ulSegmentSize;
}
pHXCodecSegmentInfo[ulIdx].bIsValid = !bIsLost;
bNoneLost = (bNoneLost && (!bIsLost));
pPacket->Release();
}
if (bNoneLost)
{
pHXCodecData->numSegments = 1;
}
#ifdef _ASSERT_ON_LOSS
else
{
HX_ASSERT(FALSE);
}
#endif // _ASSERT_ON_LOSS
#ifdef _DONOT_SEGMENT
pHXCodecData->numSegments = 1;
pHXCodecSegmentInfo[0].bIsValid = bNoneLost;
#endif // _DONOT_SEGMENT
}
// Finalize Results
if (retVal == HXR_OK)
{
pHXCodecDataOut = pData;
}
else
{
if (pHXCodecData && pHXCodecData->data)
{
m_pAllocator->ReleasePacketPtr(pHXCodecData->data);
}
HX_VECTOR_DELETE(pData);
}
#ifdef _DUMP_FIRST_NFRAMES
if (m_uSeqNumber < _DUMP_FIRST_NFRAMES)
{
char pFileName[100]; /* Flawfinder: ignore */
SafeSprintf(pFileName, 100, "%s%d", "c:\\fframe.bin", m_uSeqNumber);
FILE* pFile = fopen(pFileName, "wb");
if (pFile)
{
fprintf(pFile, "T=%ld;B=%ld:", pHXCodecData->timestamp, pHXCodecData->dataLength);
fwrite(pHXCodecData->data, sizeof(UINT8), pHXCodecData->dataLength, pFile);
fclose(pFile);
}
}
#endif // _DUMP_FIRST_NFRAMES
m_uSeqNumber++;
}
return retVal;
}
STDMETHODIMP
MP4VPayloadFormat::Flush()
{
m_bFlushed = TRUE;
return HXR_OK;
}
BOOL MP4VPayloadFormat::IsPictureStart(IHXPacket* pPacket)
{
if (m_PayloadID == PYID_X_HX_MP4)
{
ULONG32 ulIdx;
ULONG32 ulSize = 0;
UINT8* pData = NULL;
IHXBuffer* pBuffer;
pBuffer = pPacket->GetBuffer();
if (pBuffer)
{
ulSize = pBuffer->GetSize();
if (ulSize >= 4)
{
ulSize -= 4;
pData = pBuffer->GetBuffer();
}
pBuffer->Release();
}
if (pData)
{
ulIdx = 0;
do
{
if (pData[ulIdx++] == 0x00)
{
if (pData[ulIdx++] == 0x00)
{
if (pData[ulIdx] == 0x01)
{
ulIdx++;
if (pData[ulIdx] == 0xb6)
{
return TRUE;
}
}
else
{
ulIdx--;
}
}
}
} while (ulIdx < ulSize);
}
}
return FALSE;
}
BOOL MP4VPayloadFormat::IsValidPacket(IHXPacket* pPacket)
{
if (m_PayloadID == PYID_X_HX_MP4)
{
ULONG32 ulSize;
UINT8* pData = NULL;
IHXBuffer* pBuffer = pPacket->GetBuffer();
if (pBuffer)
{
ulSize = pBuffer->GetSize();
if (ulSize >= 4)
{
ulSize -= 4;
pData = pBuffer->GetBuffer();
}
pBuffer->Release();
}
if (pData)
{
// Should be more sophisiticated here and fully parse the
// headeres and make sure there is no data of substance
// following the headers - for this prototype code it
// is good enough
if ((pData[0] == 0x00) &&
(pData[1] == 0x00) &&
(pData[2] == 0x01) &&
((pData[3] == 0x00) ||
(pData[3] == 0x20)))
{
return FALSE;
}
}
}
return TRUE;
}
ULONG32 MP4VPayloadFormat::GetPacketTime(IHXPacket* pPacket)
{
ULONG32 ulTime;
HX_ASSERT(pPacket);
if (m_bUsesRTPPackets && (m_ulSamplesPerSecond != 0))
{
ulTime = ((IHXRTPPacket*) pPacket)->GetRTPTime();
ulTime = m_TSConverter.Convert(ulTime);
}
else
{
ulTime = pPacket->GetTime();
}
return ulTime;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?