📄 umc_frame_constructor.cpp
字号:
if (!m_bEndOfStream)
return UMC_ERR_NOT_ENOUGH_DATA;
ippsZero_8u(&m_pBuf[m_lLastBytePos], 4);
m_lLastBytePos += 4;
m_lCurPos = m_lLastBytePos;
}
// Frame found, check type and playback rate
if (IsSampleComplyWithTmPolicy(m_CurFrame, m_dRate))
{
m_CurFrame.uiSize = m_lCurPos - m_CurFrame.iBufOffset;
m_CurFrame.CopyTo(frame[0], m_pBuf);
// prepare for next frame
m_CurFrame.dPTS = m_CurFrame.dDTS = -1.0;
m_CurFrame.iBufOffset = m_lCurPos;
bFound = true;
}
else
{
CutInterval(m_PrevSample, m_LastSample, m_pBuf, m_CurFrame.iBufOffset, m_lCurPos, m_lLastBytePos);
m_lLastBytePos -= m_lCurPos - m_CurFrame.iBufOffset;
m_lCurPos = m_CurFrame.iBufOffset;
m_CurFrame.dPTS = m_CurFrame.dDTS = -1.0;
m_CurFrame.iBufOffset = m_lCurPos;
}
// start finding next frame
m_bFrameBegFound = false;
m_bPicSCFound = false;
}
}
return UMC_OK;
}
Status Mpeg4FrameConstructor::GetFrame(SplMediaData *frame)
{
Status umcRes;
Ipp8u *buf = m_pBuf;
bool bFrameFound = false;
// initialization loop
while (!m_bSeqSCFound)
{
while (m_lCurPos < m_lLastBytePos - 3 && !IS_CODE_INT(&buf[m_lCurPos], 0x00, 0x2F) && !IS_CODE(&buf[m_lCurPos], 0xb0))
m_lCurPos++;
if (m_lCurPos >= m_lLastBytePos - 3)
return m_bEndOfStream ? UMC_ERR_END_OF_STREAM : UMC_ERR_SYNC;
m_CurFrame.iBufOffset = m_lCurPos;
AssignAbsPos(m_CurFrame.iBufOffset);
Ipp32s offset = 0;
while (m_lCurPos + offset < m_lLastBytePos - 3 && !IS_CODE(&m_pBuf[m_lCurPos + offset], 0xb6))
offset++;
if (m_lCurPos + offset >= m_lLastBytePos - 5)
return m_bEndOfStream ? UMC_ERR_END_OF_STREAM : UMC_ERR_NOT_ENOUGH_DATA;
umcRes = ParseVideoObjectLayer(&m_pBuf[m_lCurPos], -1, m_bInfoFilled ? NULL : m_pInfo);
if (UMC_OK == umcRes)
{
m_bInfoFilled = true;
m_bSeqSCFound = true;
m_CurFrame.SetFrameType((buf[m_lCurPos + offset + 4] >> 6) + 1);
AssignTimeStamps(m_lCurPos + offset);
m_lCurPos += offset + 4;
}
else
{
m_lCurPos++;
}
}
while (!bFrameFound)
{
while ((m_lCurPos < m_lLastBytePos - 3) && !IS_CODE(&buf[m_lCurPos + 0], 0xb6))
m_lCurPos++;
if (m_lCurPos >= m_lLastBytePos - 4)
{
if (!m_bEndOfStream)
return UMC_ERR_NOT_ENOUGH_DATA;
if (m_lCurPos >= m_lLastBytePos)
return UMC_ERR_END_OF_STREAM;
m_lCurPos = m_lLastBytePos;
}
//frame found, check type and playback rate
if (IsSampleComplyWithTmPolicy(m_CurFrame, m_dRate))
{
m_CurFrame.uiSize = m_lCurPos - m_CurFrame.iBufOffset;
m_CurFrame.CopyTo(frame[0], m_pBuf);
bFrameFound = true;
}
m_CurFrame.iBufOffset = m_lCurPos;
m_CurFrame.SetFrameType((buf[m_lCurPos + 4] >> 6) + 1);
AssignTimeStamps(m_CurFrame.iBufOffset);
AssignAbsPos(m_CurFrame.iBufOffset);
m_lCurPos += 4;
}
return UMC_OK;
}
Status H261FrameConstructor::GetFrame(SplMediaData *frame)
{
Status umcRes;
Ipp8u *buf = m_pBuf;
bool bFrameFound = false;
while (!m_bSeqSCFound)
{
while ((m_lCurPos < m_lLastBytePos - 2) &&
(buf[m_lCurPos + 0] != 0 ||
buf[m_lCurPos + 1] != 1 ||
(buf[m_lCurPos + 2] & 0xf0) != 0))
m_lCurPos++;
umcRes = ParseHeader(&m_pBuf[m_lCurPos], m_lLastBytePos - m_lCurPos, m_bInfoFilled ? NULL : m_pInfo);
if (UMC_ERR_INVALID_STREAM == umcRes)
{
m_lCurPos += 1;
continue;
}
else if (UMC_ERR_NOT_ENOUGH_DATA == umcRes)
return m_bEndOfStream ? UMC_ERR_END_OF_STREAM : UMC_ERR_SYNC;
m_bSeqSCFound = true;
m_CurFrame.iBufOffset = m_lCurPos;
m_CurFrame.SetFrameType(NONE_PICTURE);
AssignTimeStamps(m_CurFrame.iBufOffset);
AssignAbsPos(m_CurFrame.iBufOffset);
m_lCurPos += 3;
}
while (!bFrameFound)
{
while ((m_lCurPos < m_lLastBytePos - 2) &&
(buf[m_lCurPos + 0] != 0 ||
buf[m_lCurPos + 1] != 1 ||
(buf[m_lCurPos + 2] & 0xf0) != 0))
m_lCurPos++;
if (m_lCurPos + 3 >= m_lLastBytePos)
{
if (!m_bEndOfStream)
return UMC_ERR_NOT_ENOUGH_DATA;
if (m_lCurPos >= m_lLastBytePos)
return UMC_ERR_END_OF_STREAM;
m_lCurPos = m_lLastBytePos;
}
// found frame
m_CurFrame.uiSize = m_lCurPos - m_CurFrame.iBufOffset;
m_CurFrame.CopyTo(frame[0], m_pBuf);
bFrameFound = true;
// next frame
m_CurFrame.iBufOffset = m_lCurPos;
m_CurFrame.SetFrameType(NONE_PICTURE);
AssignTimeStamps(m_CurFrame.iBufOffset);
AssignAbsPos(m_CurFrame.iBufOffset);
m_lCurPos += 3;
}
return UMC_OK;
}
Status H263FrameConstructor::GetFrame(SplMediaData *frame)
{
Status umcRes;
Ipp8u *buf = m_pBuf;
bool bFrameFound = false;
while (!m_bSeqSCFound)
{
while ((m_lCurPos < m_lLastBytePos - 2) &&
(buf[m_lCurPos + 0] != 0 ||
buf[m_lCurPos + 1] != 0 ||
(buf[m_lCurPos + 2] & 0xfc) != 0x80))
m_lCurPos++;
umcRes = ParseHeader(&m_pBuf[m_lCurPos], m_lLastBytePos - m_lCurPos, m_bInfoFilled ? NULL : m_pInfo);
if (UMC_ERR_INVALID_STREAM == umcRes)
{
m_lCurPos += 1;
continue;
}
else if (UMC_ERR_NOT_ENOUGH_DATA == umcRes)
return m_bEndOfStream ? UMC_ERR_END_OF_STREAM : UMC_ERR_SYNC;
m_bSeqSCFound = true;
m_CurFrame.iBufOffset = m_lCurPos;
m_CurFrame.SetFrameType(NONE_PICTURE);
AssignTimeStamps(m_CurFrame.iBufOffset);
AssignAbsPos(m_CurFrame.iBufOffset);
m_lCurPos += 3;
}
while (!bFrameFound)
{
while ((m_lCurPos < m_lLastBytePos - 2) &&
(buf[m_lCurPos + 0] != 0 ||
buf[m_lCurPos + 1] != 0 ||
(buf[m_lCurPos + 2] & 0xfc) != 0x80))
m_lCurPos++;
if (m_lCurPos + 3 >= m_lLastBytePos)
{
if (!m_bEndOfStream)
return UMC_ERR_NOT_ENOUGH_DATA;
if (m_lCurPos >= m_lLastBytePos)
return UMC_ERR_END_OF_STREAM;
m_lCurPos = m_lLastBytePos;
}
// found frame
m_CurFrame.uiSize = m_lCurPos - m_CurFrame.iBufOffset;
m_CurFrame.CopyTo(frame[0], m_pBuf);
bFrameFound = true;
// next frame
m_CurFrame.iBufOffset = m_lCurPos;
m_CurFrame.SetFrameType(NONE_PICTURE);
AssignTimeStamps(m_CurFrame.iBufOffset);
AssignAbsPos(m_CurFrame.iBufOffset);
m_lCurPos += 3;
}
return UMC_OK;
}
Status H264FrameConstructor::Init(MediaReceiverParams *pInit)
{
m_h264Headers.bOneOfNALRefIdcEqualTo0 = false;
m_h264Headers.bOneOfNALUnitTypeEqualTo5 = false;
m_h264Headers.iShCount = 0;
m_bFirstVLCNALUnitDetected = false;
m_bIsCorrupted = false;
return VideoFrameConstructor::Init(pInit);
}
Status H264FrameConstructor::Reset(void)
{
m_bSeqSCFound = false;
m_bFirstVLCNALUnitDetected = false;
m_h264Headers.bOneOfNALRefIdcEqualTo0 = false;
m_h264Headers.bOneOfNALUnitTypeEqualTo5 = false;
m_h264Headers.iShCount = 0;
m_bIsCorrupted = false;
return VideoFrameConstructor::Reset();
}
Status H264FrameConstructor::SoftReset(void)
{
m_bSeqSCFound = false;
m_bFirstVLCNALUnitDetected = false;
m_h264Headers.bOneOfNALRefIdcEqualTo0 = false;
m_h264Headers.bOneOfNALUnitTypeEqualTo5 = false;
m_h264Headers.iShCount = 0;
m_bIsCorrupted = false;
return VideoFrameConstructor::SoftReset();
}
Status H264FrameConstructor::GetFrame(SplMediaData *frame)
{
Ipp8u *buf = m_pBuf;
bool bAccessUnitDetected = false;
Ipp8u uiNALUnitType = 0;
Ipp8u uiNALRefIdc = 0;
Ipp32s iNOfZeroes = 0;
FrameType curSliceType = NONE_PICTURE;
while (!bAccessUnitDetected)
{
// this loop finds next NAL unit
iNOfZeroes = 0;
for (; m_lCurPos + 3 < m_lLastBytePos; m_lCurPos++)
{
if (0 == buf[m_lCurPos] && 0 == buf[m_lCurPos + 1])
{ // two zeroes found
// skip and count other zeroes
for (iNOfZeroes = 2; m_lCurPos + iNOfZeroes + 1 < m_lLastBytePos; iNOfZeroes++)
if (0 != buf[m_lCurPos + iNOfZeroes])
break;
// 'one' follows more than two 'zero' is the NAL unit start code
if (m_lCurPos + iNOfZeroes + 1 < m_lLastBytePos && 1 == buf[m_lCurPos + iNOfZeroes])
break;
iNOfZeroes = 0;
}
}
if (iNOfZeroes > 3)
{
m_lCurPos += iNOfZeroes - 3;
iNOfZeroes -= iNOfZeroes - 3;
}
if (iNOfZeroes < 2)
{ // no NAL unit was found
if (!m_bSeqSCFound && 0 == m_uiTotalFrames)
{
m_CurFrame.iBufOffset = m_lFirstBytePos = m_lCurPos;
}
if (!m_bEndOfStream) // just not enough data
return UMC_ERR_NOT_ENOUGH_DATA;
else if (m_bIsFinalizeSequenceSent) // EOS received and last frame returned
return UMC_ERR_END_OF_STREAM;
// add 4 bytes to the end of last frame
ippsZero_8u(&m_pBuf[m_lLastBytePos], 4);
m_lLastBytePos += 4;
m_lCurPos = m_lLastBytePos;
uiNALUnitType = 0;
bAccessUnitDetected = true;
m_bIsFinalizeSequenceSent = true;
}
else
{
uiNALRefIdc = (buf[m_lCurPos + iNOfZeroes + 1] >> 5) & 0x03;
uiNALUnitType = buf[m_lCurPos + iNOfZeroes + 1] & 0x1f;
}
if (NALU_SPS == uiNALUnitType)
{
Ipp32s iSPSsize;
for (iSPSsize = iNOfZeroes; m_lCurPos + iSPSsize + 2 < m_lLastBytePos; iSPSsize++)
if (buf[m_lCurPos + iSPSsize + 0] == 0 &&
buf[m_lCurPos + iSPSsize + 1] == 0 &&
buf[m_lCurPos + iSPSsize + 2] == 1)
break;
if (m_lCurPos + iSPSsize + 2 >= m_lLastBytePos)
return m_bEndOfStream ? UMC_ERR_END_OF_STREAM : UMC_ERR_NOT_ENOUGH_DATA;
ParseSequenceParameterSet(&m_pBuf[m_lCurPos], -1, &m_h264Headers, m_bInfoFilled ? NULL : m_pInfo);
if (!m_bSeqSCFound)
{
m_CurFrame.iBufOffset = m_lCurPos;
AssignAbsPos(m_CurFrame.iBufOffset);
}
if (m_bFirstVLCNALUnitDetected)
{ // SPS unit is from next AU, current AU is completed
bAccessUnitDetected = true;
m_bFirstVLCNALUnitDetected = false;
if (MAX_NUM_PPS_PARSETS == m_h264Headers.m_PrevSH.pic_parameter_set_id)
m_bIsCorrupted = true;
}
m_bSeqSCFound = true;
}
else if (m_bSeqSCFound)
{
if (NALU_PPS == uiNALUnitType)
{
if (m_lCurPos + 3 + 16 >= m_lLastBytePos)
return m_bEndOfStream ? UMC_ERR_END_OF_STREAM : UMC_ERR_NOT_ENOUGH_DATA;
ParsePictureParameterSet(&m_pBuf[m_lCurPos], -1, &m_h264Headers);
m_bPicSCFound = true;
if (m_bFirstVLCNALUnitDetected)
{ // PPS unit is from next AU, current AU is completed
bAccessUnitDetected = true;
m_bFirstVLCNALUnitDetected = false;
if (MAX_NUM_PPS_PARSETS == m_h264Headers.m_PrevSH.pic_parameter_set_id)
m_bIsCorrupted = true;
}
}
else if (NALU_SEI == uiNALUnitType)
{
if (m_bFirstVLCNALUnitDetected)
{ // SEI unit is from next A
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -