Intel® Integrated Performance Primitives
Deliberate problems developing high-performance vision, signal, security, and storage applications.
Announcements
FPGA community forums and blogs have moved to the Altera Community. Existing Intel Community members can sign in with their current credentials.
6818 Discussions

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

anonymous210
Novice
529 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
529 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