Intel® Integrated Performance Primitives
Deliberate problems developing high-performance vision, signal, security, and storage applications.
6708 Discussions

UMC::ThreadedDemuxer.GetInfo() is not correct if the input is MPEG2 video interlaced BOTTOM_FIELD_FIRST

anonymous210
Novice
273 Views
Hi,

IPP v6 and V7

If the input file is MPEG PS with mpeg2 video iterlaced BOTTOM_FIELD_FIRST then UMC::ThreadedDemuxer.GetInfo() reports incorrect info. The iterlaced type in UMC::SplitterInfo returned by UMC::ThreadedDemuxer.GetInfo() is TOP_FIELD_FIRST.

I traced the problem to Mpeg2FrameConstructor::GetFrame()

The original code from IPP v6 is:


Status Mpeg2FrameConstructor::GetFrame(SplMediaData *frame)
{
Status umcRes;
Ipp8u *buf = m_pBuf;
bool bFound = false;

while (!bFound)
{
// Find and parse sequence header
if (!m_bSeqSCFound)
{
if (!m_bInfoFilled)
{ // we havn't yet parsed sequence header
while (m_lCurPos < m_lLastBytePos - 3 && !IS_CODE(&m_pBuf[m_lCurPos], 0xb3))
m_lCurPos++;
if (m_lCurPos >= m_lLastBytePos - 3)
return m_bEndOfStream ? UMC_ERR_END_OF_STREAM : UMC_ERR_SYNC;

Ipp32s seqEnd = m_lCurPos + 4;
while (seqEnd < m_lLastBytePos - 3 && !IS_CODE_4(&m_pBuf[seqEnd], 0x00, 0xb3, 0xb7, 0xb8))
seqEnd++;
if (seqEnd >= m_lLastBytePos - 3)
return m_bEndOfStream ? UMC_ERR_END_OF_STREAM : UMC_ERR_SYNC;

umcRes = ParseSequenceHeader(&m_pBuf[m_lCurPos], m_lLastBytePos - m_lCurPos, m_bInfoFilled ? NULL : m_pInfo);
if (UMC_OK != umcRes)
return m_bEndOfStream ? UMC_ERR_END_OF_STREAM : UMC_ERR_NOT_ENOUGH_DATA;

if (!m_pInfo->m_pDecSpecInfo)
{
// populate decoder specific info with sequence header with all extensions
m_pInfo->m_pDecSpecInfo = new MediaData(seqEnd - m_lCurPos);
m_pInfo->m_pDecSpecInfo->SetDataSize(seqEnd - m_lCurPos);
memcpy(
m_pInfo->m_pDecSpecInfo->GetDataPointer(),
m_pBuf + m_lCurPos,
seqEnd - m_lCurPos);
}

m_bInfoFilled = true;
m_CurFrame.iBufOffset = m_lCurPos;
m_lCurPos += 4;
m_bSeqSCFound = true;
m_bFrameBegFound = true;

AssignAbsPos(m_CurFrame.iBufOffset);
}
else
{ // we are after reposition, just wait for new sequence header or I-picture
while (m_lCurPos < m_lLastBytePos - 5 &&
!(IS_CODE(&m_pBuf[m_lCurPos], 0xb3)) &&
!(IS_CODE(&m_pBuf[m_lCurPos], 0x00) && ((m_pBuf[m_lCurPos + 5] >> 3) & 0x07) == I_PICTURE))
m_lCurPos++;
if (m_lCurPos >= m_lLastBytePos - 5)
return m_bEndOfStream ? UMC_ERR_END_OF_STREAM : UMC_ERR_SYNC;

m_CurFrame.iBufOffset = m_lCurPos;
m_bSeqSCFound = true;
AssignAbsPos(m_CurFrame.iBufOffset);
}
}

// Find begin of frame
if (!m_bFrameBegFound)
{
Ipp32s savePos = m_lCurPos;
while (m_lCurPos < m_lLastBytePos - 3 && !IS_CODE_3(&m_pBuf[m_lCurPos], 0xb3, 0xb8, 0x00))
m_lCurPos++;
if (m_lCurPos >= m_lLastBytePos - 3)
{
if (m_bEndOfStream)
return UMC_ERR_END_OF_STREAM;

CutInterval(m_PrevSample, m_LastSample, m_pBuf, savePos, m_lCurPos, m_lLastBytePos, m_bPureStream);
m_lLastBytePos -= m_lCurPos - savePos;
m_lCurPos -= m_lCurPos - savePos;
return UMC_ERR_NOT_ENOUGH_DATA;
}

m_CurFrame.iBufOffset = m_lCurPos;
m_bFrameBegFound = true;

AssignAbsPos(m_CurFrame.iBufOffset);
}

// Find picture start code
if (!m_bPicSCFound)
{
while (m_lCurPos < m_lLastBytePos - 5 && !IS_CODE(&m_pBuf[m_lCurPos], 0x00))
m_lCurPos++;
if (m_lCurPos >= m_lLastBytePos - 5)
return m_bEndOfStream ? UMC_ERR_END_OF_STREAM : UMC_ERR_NOT_ENOUGH_DATA;

VideoStreamInfo *pVSI = (VideoStreamInfo *)m_pInfo->m_pStreamInfo;
if (!m_bInfoFilled && MPEG2_VIDEO == pVSI->stream_type && PROGRESSIVE != pVSI->interlace_type)
{
umcRes = ParsePictureHeader(&m_pBuf[m_lCurPos], m_lLastBytePos - m_lCurPos, m_bInfoFilled ? NULL : m_pInfo);
if (UMC_OK != umcRes)
return umcRes;
}
m_bInfoFilled = true;

// set time stamps
AssignTimeStamps(m_lCurPos);

// set frame type
m_CurFrame.SetFrameType((buf[m_lCurPos + 5] >> 3) & 0x07);
m_lCurPos += 6;
m_bPicSCFound = true;
}

// Find begin of the next frame
if (m_bFrameBegFound && m_bPicSCFound)
{
while (m_lCurPos < m_lLastBytePos - 3 && !IS_CODE_4(&m_pBuf[m_lCurPos], 0xb3, 0xb7, 0xb8, 0x00))
m_lCurPos++;

if (m_lCurPos >= m_lLastBytePos - 3)
{
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
m_CurFrame.uiSize = m_lCurPos - m_CurFrame.iBufOffset;
if (IsSampleComplyWithTmPolicy(m_CurFrame, m_dRate))
{
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_bPureStream);
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;
}






To fix the interlaced type problem I modified it this way:






Status Mpeg2FrameConstructor::GetFrame(SplMediaData *frame)
{
Status umcRes;
Ipp8u *buf = m_pBuf;
bool bFound = false;

while (!bFound)
{
// Find and parse sequence header
if (!m_bSeqSCFound)
{
if (!m_bInfoFilled)
{ // we havn't yet parsed sequence header
while (m_lCurPos < m_lLastBytePos - 3 && !IS_CODE(&m_pBuf[m_lCurPos], 0xb3))
m_lCurPos++;
if (m_lCurPos >= m_lLastBytePos - 3)
return m_bEndOfStream ? UMC_ERR_END_OF_STREAM : UMC_ERR_SYNC;

Ipp32s seqEnd = m_lCurPos + 4;
while (seqEnd < m_lLastBytePos - 3 && !IS_CODE_4(&m_pBuf[seqEnd], 0x00, 0xb3, 0xb7, 0xb8))
seqEnd++;
if (seqEnd >= m_lLastBytePos - 3)
return m_bEndOfStream ? UMC_ERR_END_OF_STREAM : UMC_ERR_SYNC;

umcRes = ParseSequenceHeader(&m_pBuf[m_lCurPos], m_lLastBytePos - m_lCurPos, m_bInfoFilled ? NULL : m_pInfo);
if (UMC_OK != umcRes)
return m_bEndOfStream ? UMC_ERR_END_OF_STREAM : UMC_ERR_NOT_ENOUGH_DATA;

if (!m_pInfo->m_pDecSpecInfo)
{
// populate decoder specific info with sequence header with all extensions
m_pInfo->m_pDecSpecInfo = new MediaData(seqEnd - m_lCurPos);
m_pInfo->m_pDecSpecInfo->SetDataSize(seqEnd - m_lCurPos);
memcpy(
m_pInfo->m_pDecSpecInfo->GetDataPointer(),
m_pBuf + m_lCurPos,
seqEnd - m_lCurPos);
}

m_CurFrame.iBufOffset = m_lCurPos;
m_lCurPos += 4;
m_bSeqSCFound = true;
m_bFrameBegFound = true;

if(m_bSeqSCFound && m_bPicSCFound)
m_bInfoFilled = true;

AssignAbsPos(m_CurFrame.iBufOffset);
}
else
{ // we are after reposition, just wait for new sequence header or I-picture
while (m_lCurPos < m_lLastBytePos - 5 &&
!(IS_CODE(&m_pBuf[m_lCurPos], 0xb3)) &&
!(IS_CODE(&m_pBuf[m_lCurPos], 0x00) && ((m_pBuf[m_lCurPos + 5] >> 3) & 0x07) == I_PICTURE))
m_lCurPos++;
if (m_lCurPos >= m_lLastBytePos - 5)
return m_bEndOfStream ? UMC_ERR_END_OF_STREAM : UMC_ERR_SYNC;

m_CurFrame.iBufOffset = m_lCurPos;
m_bSeqSCFound = true;
AssignAbsPos(m_CurFrame.iBufOffset);
}
}

// Find begin of frame
if (!m_bFrameBegFound)
{
Ipp32s savePos = m_lCurPos;
while (m_lCurPos < m_lLastBytePos - 3 && !IS_CODE_3(&m_pBuf[m_lCurPos], 0xb3, 0xb8, 0x00))
m_lCurPos++;
if (m_lCurPos >= m_lLastBytePos - 3)
{
if (m_bEndOfStream)
return UMC_ERR_END_OF_STREAM;

CutInterval(m_PrevSample, m_LastSample, m_pBuf, savePos, m_lCurPos, m_lLastBytePos, m_bPureStream);
m_lLastBytePos -= m_lCurPos - savePos;
m_lCurPos -= m_lCurPos - savePos;
return UMC_ERR_NOT_ENOUGH_DATA;
}

m_CurFrame.iBufOffset = m_lCurPos;
m_bFrameBegFound = true;

AssignAbsPos(m_CurFrame.iBufOffset);
}

// Find picture start code
if (!m_bPicSCFound)
{
while (m_lCurPos < m_lLastBytePos - 5 && !IS_CODE(&m_pBuf[m_lCurPos], 0x00))
m_lCurPos++;
if (m_lCurPos >= m_lLastBytePos - 5)
return m_bEndOfStream ? UMC_ERR_END_OF_STREAM : UMC_ERR_NOT_ENOUGH_DATA;

VideoStreamInfo *pVSI = (VideoStreamInfo *)m_pInfo->m_pStreamInfo;
if (!m_bInfoFilled && MPEG2_VIDEO == pVSI->stream_type && PROGRESSIVE != pVSI->interlace_type)
{
umcRes = ParsePictureHeader(&m_pBuf[m_lCurPos], m_lLastBytePos - m_lCurPos, m_bInfoFilled ? NULL : m_pInfo);
if (UMC_OK != umcRes)
return umcRes;
}

// set time stamps
AssignTimeStamps(m_lCurPos);

// set frame type
m_CurFrame.SetFrameType((buf[m_lCurPos + 5] >> 3) & 0x07);
m_lCurPos += 6;
m_bPicSCFound = true;

if(m_bSeqSCFound && m_bPicSCFound)
m_bInfoFilled = true;

}

// Find begin of the next frame
if (m_bFrameBegFound && m_bPicSCFound)
{
while (m_lCurPos < m_lLastBytePos - 3 && !IS_CODE_4(&m_pBuf[m_lCurPos], 0xb3, 0xb7, 0xb8, 0x00))
m_lCurPos++;

if (m_lCurPos >= m_lLastBytePos - 3)
{
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
m_CurFrame.uiSize = m_lCurPos - m_CurFrame.iBufOffset;
if (IsSampleComplyWithTmPolicy(m_CurFrame, m_dRate))
{
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_bPureStream);
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;
}






Thanks
Anonymous2
0 Kudos
1 Reply
Naveen_G_Intel
Employee
273 Views

Hi,

We have fixed this issue in IPP 7.0 Update 3 release, its available now to download.

For more information, refer to forum announcement - Intel IPP 7.0 update 3 is shipping as of March 28, 2011.

Regards,

Naveen Gv


0 Kudos
Reply