📄 umc_demuxer.cpp
字号:
{
if (rCheckPoint.uiPos >= gap.uiPos)
rCheckPoint.dTime -= gap.dTime;
err = m_ListOfGaps.Next(gap);
}
if (m_dPrevValidSystemTime < 0.0)
{
m_dPrevValidSystemTime = rCheckPoint.dTime;
return isNewGapDetected;
}
// check for negative (even small ones) and positive jumps (only big)
if (rCheckPoint.dTime < m_dPrevValidSystemTime - 1.0 || rCheckPoint.dTime > m_dPrevValidSystemTime + 10.0)
{ // new gap is found
vm_debug_trace2(VM_DEBUG_WARNING, VM_STRING("TimeStampCorrector: discontinuity detected at pos=%d, gap=%.3f\n"), (Ipp32s)rCheckPoint.uiPos, rCheckPoint.dTime - m_dPrevValidSystemTime);
gap.uiPos = rCheckPoint.uiPos;
gap.dTime = rCheckPoint.dTime - m_dPrevValidSystemTime;
m_ListOfGaps.Add(gap);
rCheckPoint.dTime -= gap.dTime;
isNewGapDetected = true;
}
m_dPrevValidSystemTime = rCheckPoint.dTime;
return isNewGapDetected;
}
Status TimeStampCorrector::GetSystemTimeUpTo(CheckPoint &rCheckPoint, Ipp64u upToPos, bool *pIsGapDetectHere)
{
if (!m_pParser)
return UMC_ERR_NOT_INITIALIZED;
CheckPoint checkPoint;
Status umcRes = m_pParser->GetSystemTime(checkPoint, upToPos);
if (UMC_OK != umcRes)
return umcRes;
if(CorrectTime(checkPoint) && pIsGapDetectHere)
pIsGapDetectHere[0] = true;
rCheckPoint = checkPoint;
return UMC_OK;
}
Status TimeStampCorrector::GetSystemTime(CheckPoint &rCheckPoint, bool *pIsGapDetectHere)
{
return GetSystemTimeUpTo(rCheckPoint, (Ipp64u)-1, pIsGapDetectHere);
}
Segmentator::Segmentator(void)
{
m_pParser = NULL;
m_pVFC = NULL;
m_uiTrack = 0;
m_iSegFrames = 0;
m_uiSegStart = 0;
m_uiSegEnd = 0;
m_uiSegSize = 200000;
m_bEndOfStream = false;
m_bLastSegment = false;
m_bNewSegment = true;
}
void Segmentator::RestartSegmentation(StreamParser *pParser, Ipp32u uiTrack, VideoFrameConstructor *pVFC)
{
m_pParser = pParser;
m_uiTrack = uiTrack;
m_pVFC = pVFC;
m_iSegFrames = 0;
m_uiSegEnd = pParser->GetPosition();
m_uiSegStart = m_uiSegEnd - IPP_MIN(m_uiSegSize, m_uiSegEnd);
m_bEndOfStream = false;
m_bLastSegment = false;
m_bNewSegment = true;
}
void Segmentator::AdditionalJump(Ipp32s iJumpSize)
{
if (!m_bNewSegment)
return; // additional jumps are not allowed when current segment is not finished
if (iJumpSize < (Ipp32s)m_uiSegSize)
return; // jump is smaller that current segment size
if ((Ipp64u)iJumpSize >= m_uiSegEnd)
m_bEndOfStream = true;
m_uiSegEnd -= IPP_MIN(iJumpSize, m_uiSegEnd);
m_uiSegStart -= IPP_MIN(iJumpSize, m_uiSegStart);
}
Status Segmentator::PullSegment(SplMediaData *pData)
{
Status umcRes = UMC_OK;
Ipp32u curTrack;
Ipp64u uiCurChunkPos;
SplMediaData chunk;
SplMediaData *pChunk;
bool bEndOfSegment = false;
// we are at the beginning of the stream, last segment was pulled previously
if (m_bEndOfStream)
return UMC_ERR_END_OF_STREAM;
if (m_bNewSegment)
{
// go to start of next segment
m_pParser->SetPosition(m_uiSegStart);
m_bNewSegment = false;
}
chunk.SetBufferPointer((Ipp8u *)1, 0);
for (; !bEndOfSegment;)
{
// find next packet from video track
umcRes = CheckPacketFromTrack(&chunk);
if (UMC_OK != umcRes && UMC_ERR_END_OF_STREAM != umcRes)
return umcRes;
// save position of last chunk
uiCurChunkPos = (UMC_OK == umcRes) ? chunk.GetAbsPos() : m_uiSegEnd;
if (uiCurChunkPos >= m_uiSegEnd && (!m_pVFC->IsFrameStartFound() || UMC_ERR_END_OF_STREAM == umcRes))
{ // end of segment
break;
}
// order space for chunk in FC's buffer
umcRes = m_pVFC->LockInputBuffer(&chunk);
if (UMC_OK != umcRes)
return umcRes;
// copy chunk from parser to FC's buffer
umcRes = m_pParser->GetNextData(&chunk, &curTrack);
// parse received chunk
pChunk = &chunk;
for (; UMC_OK == umcRes;)
{
umcRes = m_pVFC->PreUnLockInputBuffer(pChunk);
pChunk = NULL;
if (UMC_OK == umcRes)
{
m_pVFC->GetLastFrame(pData);
m_iSegFrames += 1;
if (1 == m_iSegFrames)
{ // update bottom boundary of segment using position of first sample
m_pVFC->GetLastFrame(pData);
m_uiSegStart = pData->GetAbsPos();
}
if (uiCurChunkPos >= m_uiSegEnd)
{
bEndOfSegment = true;
break; // end of segment
}
}
}
}
// update segment boundaries
if (m_iSegFrames > 0 || m_pVFC->IsFrameStartFound())
{ // current segment size is enough
m_uiSegEnd = m_uiSegStart;
m_uiSegStart -= IPP_MIN(m_uiSegStart, m_uiSegSize);
}
else
{ // current segment size is too small
m_uiSegStart -= IPP_MIN(m_uiSegStart, m_uiSegSize);
m_uiSegSize *= 2;
}
m_bNewSegment = true;
if (0 == m_uiSegStart)
{
m_bEndOfStream = m_bLastSegment;
m_bLastSegment = true;
}
// at least one frame was found?
umcRes = m_iSegFrames > 0 ? UMC_OK : UMC_ERR_NOT_ENOUGH_DATA;
m_iSegFrames = 0;
// clean up remained bytes
m_pVFC->GetLastFrame(pData);
m_pVFC->SoftReset();
return umcRes;
}
Status Segmentator::CheckPacketFromTrack(SplMediaData *pData)
{
Ipp32u curTrack;
for (;;)
{
Status umcRes = m_pParser->CheckNextData(pData, &curTrack);
if (UMC_OK != umcRes || curTrack == m_uiTrack)
return umcRes;
if (curTrack != m_uiTrack)
umcRes = m_pParser->MoveToNextHeader();
}
}
SystemStreamType DetectSystem(DataReader* pDataReader)
{
Status umcRes = UMC_OK;
Ipp8u byteCode;
Ipp32u longCode;
if (!pDataReader)
return UNDEF_STREAM;
umcRes = pDataReader->Check8u(&byteCode, 0);
if (UMC_OK != umcRes)
return UNDEF_STREAM;
umcRes = pDataReader->Check32u(&longCode, 0);
if (UMC_OK != umcRes)
return UNDEF_STREAM;
if (longCode == 'RIFF') // RIFF
{
umcRes = pDataReader->Check32u(&longCode, 8);
if (UMC_OK != umcRes)
return UNDEF_STREAM;
if (longCode == 'AVI ')
return AVI_STREAM;
else
return WAVE_STREAM;
}
//search some MPEG2 PS start code, it can start from bunch of zeros before
if (0 == longCode)
{
Ipp32s offset = 1;
while (0 == longCode)
{
umcRes = pDataReader->Check32u(&longCode, offset);
if (UMC_OK != umcRes)
return UNDEF_STREAM;
offset++;
}
umcRes = pDataReader->Check32u(&longCode, offset);
if (UMC_OK != umcRes)
return UNDEF_STREAM;
if ((longCode & 0x0000fff0) == 0x0000fff0)
return MPEGx_PURE_AUDIO_STREAM;
}
if (ID_TS_SYNC == byteCode) //check if transport stream, 0x47 is sync byte for it
return MPEG2_TRANSPORT_STREAM;
else if ((0x100 | ID_PS_PACK) == longCode || 0x000001BC == (longCode & 0xFFFFFFFC)) //check if program stream
return MPEG2_PROGRAMM_STREAM;
else if ((longCode >= 0x000001C0) && (longCode <= 0x000001DF)) //check if PES audio stream,
return MPEG2_PES_PACKETS_STREAM;
else if ((longCode >= 0x000001E0) && (longCode <= 0x000001EF)) //check if PES video stream,
return MPEG2_PES_PACKETS_STREAM;
else if (SC_MPEG2_SEQ == longCode) //check if MPEG2 Sequence or Picture start code
return MPEG2_PURE_VIDEO_STREAM;
else if (SC_MPEG2_PIC == (longCode & (~0xff))) //check if MPEG2 Sequence or Picture start code
{
if (7 == (longCode & 0x1f))
return H264_PURE_VIDEO_STREAM;
// create MPEG4FC to assure that stream is actually mpeg4 video
Ipp32u uiSize = 32 * 1024;
Mpeg4FrameConstructor fc;
FrameConstructorParams fcPar;
fcPar.m_lBufferSize = uiSize;
fcPar.m_nOfFrames = 1;
umcRes = fc.Init(&fcPar);
if (UMC_OK != umcRes)
return UNDEF_STREAM;
// get buffer
MediaData data;
data.SetBufferPointer((Ipp8u *)1, uiSize);
data.SetDataSize(uiSize);
umcRes = fc.LockInputBuffer(&data);
if (UMC_OK != umcRes)
return UNDEF_STREAM;
// read data to buffer
umcRes = pDataReader->CheckData(data.GetDataPointer(), &uiSize, 0);
if (UMC_ERR_END_OF_STREAM == umcRes && uiSize > 0)
umcRes = UMC_OK;
if (UMC_OK != umcRes)
return UNDEF_STREAM;
data.SetDataSize(uiSize);
fc.UnLockInputBuffer(&data);
if (TRACK_MPEG4V == fc.GetInfo()->m_Type)
return MPEG4_PURE_VIDEO_STREAM;
}
else if ((longCode & 0xfffffc00) == 0x00008000) //check if H.263 pure video
return H263_PURE_VIDEO_STREAM;
else if ((longCode & 0xfffff000) == 0x00010000) //check if H.261 pure video
return H261_PURE_VIDEO_STREAM;
else if ((longCode & 0x1f) == 7 || (longCode == 0x00000001)) //check if H.264 pure video
return H264_PURE_VIDEO_STREAM;
else if ((longCode & 0xffe00000) == 0xffe00000 || (longCode & 0xffffff00) == 0x49443300 || (longCode == 0))
{
//skip ID3 header
if ((longCode & 0xffffff00) == 0x49443300)
{
Ipp8u byte;
Ipp32s id3size = 0;
pDataReader->Get8u(&byte); // 'I'
pDataReader->Get8u(&byte); // 'D'
pDataReader->Get8u(&byte); // '3'
pDataReader->Get8u(&byte); // major version != 0xFF
pDataReader->Get8u(&byte); // revision number != 0xFF
pDataReader->Get8u(&byte); // flags (only 3 first bits are used)
pDataReader->Get8u(&byte); // 21...27 bits of size < 0x80
id3size |= byte << 21;
pDataReader->Get8u(&byte); // 14...20 bits of size < 0x80
id3size |= byte << 14;
pDataReader->Get8u(&byte); // 07...13 bits of size < 0x80
id3size |= byte << 7;
pDataReader->Get8u(&byte); // 00...06 bits of size < 0x80
id3size |= byte;
pDataReader->MovePosition(id3size);
}
return MPEGx_PURE_AUDIO_STREAM;
}
else if ((longCode >> 16) == SC_AC3) //check if AC3 audio stream
return MPEGx_PURE_AUDIO_STREAM;
umcRes = pDataReader->Check8u(&byteCode,4);
if (UMC_OK != umcRes)
return UNDEF_STREAM;
if (0x47 == byteCode)
{
umcRes = pDataReader->Check8u(&byteCode,196);
if (UMC_OK != umcRes)
return UNDEF_STREAM;
if (0x47 == byteCode)
return MPEG2_TRANSPORT_STREAM_TTS;
}
// look over 3kb for MPEG2 system stream start codes
Ipp32s i;
for (i = 0; i < 3 * 1024; i++)
{
umcRes = pDataReader->Check32u(&longCode, i);
if (UMC_OK != umcRes)
return UNDEF_STREAM;
if ((0x100 | ID_PS_PACK) == longCode || 0x000001BC == (longCode & 0xFFFFFFFC))
return MPEG2_PROGRAMM_STREAM;
umcRes = pDataReader->Check8u(&byteCode, i);
if (UMC_OK != umcRes)
return UNDEF_STREAM;
if (ID_TS_SYNC == byteCode)
{
umcRes = pDataReader->Check8u(&byteCode, i + 188);
if (UMC_OK != umcRes)
return UNDEF_STREAM;
if (ID_TS_SYNC == byteCode)
{
umcRes = pDataReader->Check8u(&byteCode, i + 2 * 188);
if (UMC_OK != umcRes)
return UNDEF_STREAM;
if (ID_TS_SYNC == byteCode)
return MPEG2_TRANSPORT_STREAM;
}
umcRes = pDataReader->Check8u(&byteCode, i + 192);
if (UMC_OK != umcRes)
return UNDEF_STREAM;
if (ID_TS_SYNC == byteCode)
{
umcRes = pDataReader->Check8u(&byteCode, i + 2 * 192);
if (UMC_OK != umcRes)
return UNDEF_STREAM;
if (ID_TS_SYNC == byteCode)
return MPEG2_TRANSPORT_STREAM_TTS;
}
}
}
return UNDEF_STREAM;
}
} //namespace UMC
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -