📄 umc_avs_splitter_buffer.cpp
字号:
// unlock the main buffer
return m_mainBuffer.UnLockOutputBuffer(&m_latestSample);
} // Status AVSSampleBuffer::UnLockOutputBuffer(MediaData *pSrc)
void AVSSampleBuffer::CollectStartCodes(size_t nSourceSize)
{
Ipp8u *pbSource = m_pbSampleEnd;
// update end of the being collected sample
m_pbSampleEnd += nSourceSize;
// set up pointer to the beginning of the current frame
{
size_t iRollBack = IPP_MIN(pbSource - m_pbSample, 3);
// roll back the pointer a little bit
// to handle splitted start codes
pbSource -= iRollBack;
}
// check amount of data
if (4 > (m_pbSampleEnd - pbSource))
return;
// skip first 3 bytes
pbSource += 3;
// try to find all start codes
do
{
// we can skip 3 bytes when
// the previous byte is greater than 1
if (1 < pbSource[-1])
{
pbSource += 3;
}
// we can skip 2 bytes when
// two precending the previous byte byte is not 0
else if (0 < pbSource[-2])
{
pbSource += 2;
}
// in other case we have to analyze stream byte by byte
else
{
if (1 == pbSource[-1])
{
if (0 == pbSource[-3])
{
// fill start code's info
m_startCodes[m_iNumberOfStartCodes].m_startCode = pbSource[0];
m_startCodes[m_iNumberOfStartCodes].m_startCodeOffset = (Ipp32u) (pbSource - 3 - m_pbSample);
// increment number of start codes
m_iNumberOfStartCodes += 1;
pbSource += 3;
}
else
{
pbSource += 2;
}
}
pbSource += 1;
}
} while (pbSource < m_pbSampleEnd);
// we have read garbage
if (0 == m_iNumberOfStartCodes)
{
size_t iRollBack = IPP_MIN(m_pbSample - m_pbBuffer, 3);
m_pbSample = m_pbSampleEnd - iRollBack;
}
} // void AVSSampleBuffer::CollectStartCodes(size_t nSourceSize)
Status AVSSampleBuffer::MoveCollectedSample(Status streamStatus)
{
Ipp32s iNALUnits;
Status umcRes;
// sometimes we need to set 'EOB' having zero data
if ((UMC_OK != streamStatus) &&
(0 == m_iNumberOfStartCodes))
{
m_mainBuffer.UnLockInputBuffer(NULL, UMC_ERR_END_OF_STREAM);
return UMC_OK;
}
// move collected samples to the main buffer
iNALUnits = GetNALUnitsNumber();
while (iNALUnits)
{
size_t nSampleSize, nEncodedDataSize;
MediaData mediaDst;
Ipp32s i;
// calculate the sample's size
nEncodedDataSize = m_startCodes[iNALUnits].m_startCodeOffset -
m_startCodes[0].m_startCodeOffset;
nSampleSize = align_value<size_t> (nEncodedDataSize, sizeof(Ipp32u)) +
sizeof(Ipp32u) * (iNALUnits * 2 + 2);
// get the destination
umcRes = m_mainBuffer.LockInputBuffer(&mediaDst, nSampleSize);
if (UMC_OK != umcRes)
return umcRes;
// copy sample & start codes' info
{
Ipp8u *pbDst = (Ipp8u *) mediaDst.GetBufferPointer();
Ipp32u *pCodes;
// copy sample
memcpy(pbDst, m_pbSample + m_startCodes[0].m_startCodeOffset, nEncodedDataSize);
pbDst += nEncodedDataSize;
// align destination pointer
while ((pbDst - (Ipp8u *) 0) & 3)
{
*pbDst = 0;
pbDst += 1;
}
// copy start codes
pCodes = (Ipp32u *) pbDst;
for (i = 0; i < iNALUnits; i += 1)
{
pCodes[i] = m_startCodes[i].m_startCode;
pCodes[i + iNALUnits] = m_startCodes[i].m_startCodeOffset - m_startCodes[0].m_startCodeOffset;
}
// set the number of start codes
pCodes[iNALUnits * 2] = iNALUnits;
// set the real data size
pCodes[iNALUnits * 2 + 1] = (Ipp32u) nEncodedDataSize;
}
// finalize the sample
mediaDst.SetDataSize(nSampleSize);
m_mainBuffer.UnLockInputBuffer(&mediaDst, streamStatus);
// update array of start codes
SkipStartCodes(iNALUnits);
// try to find the next sample
iNALUnits = GetNALUnitsNumber();
}
// update the temporal buffer, move collected data to the beginning
if (m_pbSample != m_pbBuffer)
{
Ipp8u *pbSrc, *pbDst;
size_t nAvailable, nMaxChunk;
nAvailable = m_pbSampleEnd - m_pbSample;
nMaxChunk = m_pbSample - m_pbBuffer;
pbDst = m_pbBuffer;
pbSrc = m_pbSample;
while (nAvailable)
{
size_t nToCopy = IPP_MIN(nMaxChunk, nAvailable);
memcpy(pbDst, pbSrc, nToCopy);
pbDst += nToCopy;
pbSrc += nToCopy;
nAvailable -= nToCopy;
}
m_pbSampleEnd = m_pbBuffer + (m_pbSampleEnd - m_pbSample);
m_pbSample = m_pbBuffer;
}
return UMC_OK;
} // Status AVSSampleBuffer::MoveCollectedSample(Status streamStatus)
void AVSSampleBuffer::SkipStartCodes(Ipp32s numCodes)
{
Ipp32s i;
size_t nAdvanceSize;
// check the following code
if (VIDEO_SEQUENCE_END_CODE == m_startCodes[numCodes].m_startCode)
{
// skip filled buffer
nAdvanceSize = m_startCodes[numCodes].m_startCodeOffset + sizeof(Ipp32u);
numCodes += 1;
}
else
{
nAdvanceSize = m_startCodes[numCodes].m_startCodeOffset;
}
// skip filled buffer
m_pbSample += nAdvanceSize;
// skip codes info
for (i = 0; i < (m_iNumberOfStartCodes - numCodes); i += 1)
{
m_startCodes[i].m_startCode = m_startCodes[i + numCodes].m_startCode;
m_startCodes[i].m_startCodeOffset = (Ipp32u) (m_startCodes[i + numCodes].m_startCodeOffset - nAdvanceSize);
}
m_iNumberOfStartCodes -= numCodes;
} // void AVSSampleBuffer::SkipStartCodes(Ipp32s numCodes)
Ipp32s AVSSampleBuffer::GetNALUnitsNumber(void)
{
Ipp32s i;
bool bFoundPictureHeader = false;
bool bFoundSequenceHeader = false;
bool bFoundSlice = false;
bool bPictureDone = false;
if (0 >= m_iNumberOfStartCodes)
return 0;
// find the first slice start code or second other header
for (i = 0; i < m_iNumberOfStartCodes; i += 1)
{
switch (m_startCodes[i].m_startCode)
{
case VIDEO_SEQUENCE_START_CODE:
// the picture is complete, when it is not the first NAL unit
if (i)
bPictureDone = true;
else
{
bFoundSequenceHeader = true;
m_bFoundSequenceHeader = true;
}
break;
case VIDEO_SEQUENCE_END_CODE:
bPictureDone = true;
break;
case USER_DATA_START_CODE:
// picture data before user data is not allowed
if (bFoundSlice)
bPictureDone = true;
break;
case I_PICTURE_START_CODE:
// two header per frame is not allowed
if ((bFoundSlice) || (bFoundPictureHeader))
bPictureDone = true;
else
bFoundPictureHeader = true;
break;
case EXTENSION_START_CODE:
// picture data before extension data is not allowed
if (bFoundSlice)
bPictureDone = true;
break;
case BP_PICTURE_START_CODE:
if ((bFoundSlice) || (bFoundPictureHeader))
bPictureDone = true;
else
bFoundPictureHeader = true;
break;
case VIDEO_EDIT_CODE:
// video edit code shall be the beginning
if ((bFoundSlice) || (bFoundPictureHeader))
bPictureDone = true;
break;
// slices data
default:
// we should provide a sequence header as a single frame
if ((bFoundSequenceHeader) && (false == bFoundPictureHeader))
bPictureDone = true;
else if (LAST_SLICE_START_CODE >= m_startCodes[i].m_startCode)
bFoundSlice = true;
break;
}
// is the picture composed
if (bPictureDone)
{
// frame is incomplete.
// there are only two conditions:
// we found a sequence header or
// we found a picture header and a sequence header had been found before
if ((bFoundSequenceHeader) ||
(bFoundPictureHeader && m_bFoundSequenceHeader))
return i;
else
{
SkipStartCodes(i);
// try to compose another frame
i = -1;
bFoundPictureHeader = false;
bFoundSequenceHeader = false;
bFoundSlice = false;
bPictureDone = false;
}
}
}
return 0;
} // Ipp32s AVSSampleBuffer::GetNALUnitsNumber(void)
} // namespace UMC
#endif // #if defined(UMC_ENABLE_AVS_SPLITTER)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -