📄 umc_frame_constructor.cpp
字号:
while (0 == bs.GetBits(8)); // skip all zeroes and one
bs.GetBits(8); // skip nal_ref_idc and nal_unit_type
Ipp8u uiPPSId = (Ipp8u)bs.GetUE();
if (uiPPSId >= MAX_NUM_PPS_PARSETS)
return UMC_ERR_INVALID_STREAM;
FCH264PicParSet *pPPS = &pHeaders->m_PPS[uiPPSId];
pPPS->seq_parameter_set_id = (Ipp8u)bs.GetUE();
if (pPPS->seq_parameter_set_id >= MAX_NUM_SPS_PARSETS)
return UMC_ERR_INVALID_STREAM;
bs.GetBit(); // entropy_coding_mode
pPPS->pic_order_present_flag = (Ipp8u)bs.GetBit();
// if no error validate PPS
pPPS->pic_parameter_set_id = uiPPSId;
return UMC_OK;
}
Status H264FrameConstructor::ParseSliceHeader(Ipp8u *buf, Ipp32s iLen, H264HeaderSet *pHeaders, Mpeg2TrackInfo *pInfo)
{
iLen;
InterlaceType interlace_type = PROGRESSIVE;
FCH264SliceHeader sh;
H264BitstreamReader bs;
bs.Init(buf);
while (0 == bs.GetBits(8)); // skip all zeroes and one
bs.GetBit(); // skip forbidden zero bit
sh.nal_ref_idc = (Ipp8u)bs.GetBits(2);
sh.idr_flag = (5 == bs.GetBits(5));
bs.GetUE(); // first_mb_in_slice
sh.slice_type = (Ipp8u)bs.GetUE();
if (sh.slice_type > 9)
return UMC_ERR_INVALID_STREAM;
sh.pic_parameter_set_id = (Ipp8u)bs.GetUE();
if (sh.pic_parameter_set_id >= MAX_NUM_PPS_PARSETS)
return UMC_ERR_INVALID_STREAM;
FCH264PicParSet *pPPS = &pHeaders->m_PPS[sh.pic_parameter_set_id];
if (MAX_NUM_PPS_PARSETS == pPPS->pic_parameter_set_id)
{
sh.pic_parameter_set_id = MAX_NUM_PPS_PARSETS; // invalidate slice
return UMC_ERR_INVALID_STREAM; // wrong reference
}
FCH264SeqParSet *pSPS = &pHeaders->m_SPS[pPPS->seq_parameter_set_id];
if (MAX_NUM_SPS_PARSETS == pSPS->seq_parameter_set_id)
return UMC_ERR_INVALID_STREAM; // wrong reference
sh.frame_num = bs.GetBits(pSPS->log2_max_frame_num);
if (0 == pSPS->frame_mbs_only_flag)
{
sh.field_pic_flag = (Ipp8u)bs.GetBit();
if (0 != sh.field_pic_flag)
{
sh.bottom_field_flag = (Ipp8u)bs.GetBit();
interlace_type = sh.bottom_field_flag ? INTERLEAVED_BOTTOM_FIELD_FIRST : INTERLEAVED_TOP_FIELD_FIRST;
}
}
if (sh.idr_flag)
sh.idr_pic_id = bs.GetUE();
if (0 == pSPS->pic_order_cnt_type)
{
sh.pic_order_cnt_lsb = bs.GetBits(pSPS->log2_max_pic_order_cnt_lsb);
if (pPPS->pic_order_present_flag && !sh.field_pic_flag)
sh.delta_pic_order_cnt_bottom = bs.GetSE();
}
if (1 == pSPS->pic_order_cnt_type && 0 == pSPS->delta_pic_order_always_zero_flag)
{
sh.delta_pic_order_cnt[0] = bs.GetSE();
if (pPPS->pic_order_present_flag && !sh.field_pic_flag)
sh.delta_pic_order_cnt[1] = bs.GetSE();
}
if (pHeaders->iShCount == 1)
pHeaders->m_PrevSH = pHeaders->m_LastSH;
pHeaders->m_LastSH = sh;
pHeaders->iShCount++;
if (pInfo)
((VideoStreamInfo *)pInfo->m_pStreamInfo)->interlace_type = interlace_type;
return UMC_OK;
}
bool H264FrameConstructor::IsFirstVLCNALUnit(H264HeaderSet *pHeaders)
{
FCH264SeqParSet *pSPS = pHeaders->m_SPS;
FCH264PicParSet *pPPS = pHeaders->m_PPS;
FCH264SliceHeader *pLastSH = &pHeaders->m_LastSH;
FCH264SliceHeader *pPrevSH = &pHeaders->m_PrevSH;
if (pHeaders->iShCount < 2)
return false;
// one of slices refers to invalid PPS
if (MAX_NUM_PPS_PARSETS == pLastSH->pic_parameter_set_id ||
MAX_NUM_PPS_PARSETS == pPrevSH->pic_parameter_set_id)
return true;
// frame_num differs in value
if (pLastSH->frame_num != pPrevSH->frame_num)
return true;
// pic_parameter_set_id differs in value
if (pLastSH->pic_parameter_set_id != pPrevSH->pic_parameter_set_id)
return true;
// field_pic_flag differs in value
if (pLastSH->field_pic_flag != pPrevSH->field_pic_flag)
return true;
// bottom_pic_flag is present in both and differs in value
if (pLastSH->field_pic_flag && pPrevSH->field_pic_flag)
if (pLastSH->bottom_field_flag != pPrevSH->bottom_field_flag)
return true;
// nal_ref_idc differs in value with one of the nal_ref_idc values being equal to 0
if (0 != pLastSH->nal_ref_idc && pHeaders->bOneOfNALRefIdcEqualTo0)
return true;
// pic_order_cnt_type is equal to 0 for both and
// either pic_order_cnt_lsb differs in value, or delta_pic_order_cnt_bottom differs in value
if (0 == pSPS[pPPS[pLastSH->pic_parameter_set_id].seq_parameter_set_id].pic_order_cnt_type &&
0 == pSPS[pPPS[pPrevSH->pic_parameter_set_id].seq_parameter_set_id].pic_order_cnt_type)
if (pLastSH->pic_order_cnt_lsb != pPrevSH->pic_order_cnt_lsb ||
pLastSH->delta_pic_order_cnt_bottom != pPrevSH->delta_pic_order_cnt_bottom)
return true;
// pic_order_cnt_type is equal to 1 for both and
// either delta_pic_order_cnt[0] differs in value, or delta_pic_order_cnt[1] differs in value
if (1 == pSPS[pPPS[pLastSH->pic_parameter_set_id].seq_parameter_set_id].pic_order_cnt_type &&
1 == pSPS[pPPS[pPrevSH->pic_parameter_set_id].seq_parameter_set_id].pic_order_cnt_type)
if (pLastSH->delta_pic_order_cnt[0] != pPrevSH->delta_pic_order_cnt[0] ||
pLastSH->delta_pic_order_cnt[1] != pPrevSH->delta_pic_order_cnt[1])
return true;
// nal_unit_type differs in value with one of the nal_unit_type values being equal to 5
if (!pLastSH->idr_flag && pHeaders->bOneOfNALUnitTypeEqualTo5)
return true;
// nal_unit_type is equal to 5 for both and idr_pic_id differs in value
if (pLastSH->idr_flag && pPrevSH->idr_flag)
if (pLastSH->idr_pic_id != pPrevSH->idr_pic_id)
return true;
return false;
}
FrameConstructorParams::FrameConstructorParams()
{
m_pInfo = NULL;
m_lBufferSize = 0;
m_nOfFrames = 0;
m_pMemoryAllocator = NULL;
}
FrameConstructor::FrameConstructor()
{
// reset variables
m_midAllocatedBuffer = MID_INVALID;
m_pMemoryAllocator = NULL;
m_pAllocated = NULL;
m_pBuf = NULL;
m_pInfo = NULL;
m_bEndOfStream = false;
m_bIsOutputBufferLocked = false;
m_bInfoFilled = false;
m_lBufferSize = 0;
m_lLastBytePos = 0;
m_lFirstBytePos = 0;
m_lCurPos = 0;
m_lCurPicStart = 0;
m_iCurrentLevel = 0;
m_uiCommitedFrames = 0;
m_uiTotalFrames = 0;
m_iFirstInDecOrderIdx = 0;
m_dRate = 1.0;
m_LastFrame.SetBufferPointer(NULL, 0);
m_LastFrame.SetAbsPos(0);
m_LastFrame.SetTime(-1.0, -1.0);
// reset mutex
vm_mutex_set_invalid(&m_synchro);
}
FrameConstructor::~FrameConstructor()
{
Close();
// destroy mutex
if (1 == vm_mutex_is_valid(&m_synchro))
vm_mutex_destroy(&m_synchro);
}
Status FrameConstructor::Stop()
{
return UMC_OK;
}
Status FrameConstructor::Init(MediaReceiverParams *pInit)
{
FrameConstructorParams *pParams = DynamicCast<FrameConstructorParams> (pInit);
if (NULL == pParams)
return UMC_ERR_NULL_PTR;
if (0 == pParams->m_nOfFrames || 0 == pParams->m_lBufferSize)
return UMC_ERR_INIT;
Close();
// init mutex
if (0 == vm_mutex_is_valid(&m_synchro))
if (VM_OK != vm_mutex_init(&m_synchro))
return UMC_ERR_INIT;
// allocate buffer (one more)
m_lBufferSize = (Ipp32s)pParams->m_lBufferSize;
if (pParams->m_pMemoryAllocator)
{ // use the external memory allocator
m_pMemoryAllocator = pParams->m_pMemoryAllocator;
}
else
{ // allocate default memory allocator
m_pAllocated = new DefaultMemoryAllocator();
if (NULL == m_pAllocated)
return UMC_ERR_ALLOC;
m_pMemoryAllocator = m_pAllocated;
}
Status umcRes = m_pMemoryAllocator->Alloc(&m_midAllocatedBuffer, m_lBufferSize + 4, UMC_ALLOC_PERSISTENT, 16);
if (UMC_OK != umcRes)
return UMC_ERR_ALLOC;
m_pBuf = (Ipp8u *)m_pMemoryAllocator->Lock(m_midAllocatedBuffer);
if (NULL == m_pBuf)
return UMC_ERR_ALLOC;
m_iCurrentLevel = 0;
m_pInfo = new Mpeg2TrackInfo;
if (NULL == m_pInfo)
return UMC_ERR_ALLOC;
if (pParams->m_pInfo)
{
umcRes = m_pInfo->CopyFrom(pParams->m_pInfo);
}
else
{
umcRes = m_pInfo->Alloc();
}
if (UMC_OK != umcRes)
return umcRes;
m_dRate = 1.0;
return UMC_OK;
}
Status FrameConstructor::Close()
{
Reset();
// delete buffer
if (m_pBuf && m_pMemoryAllocator)
{
m_pMemoryAllocator->Unlock(m_midAllocatedBuffer);
m_pMemoryAllocator->Free(m_midAllocatedBuffer);
m_pBuf = NULL;
}
// delete allocator if was allocated internally
if (m_pAllocated)
{
delete m_pAllocated;
m_pAllocated = NULL;
}
if (m_pInfo)
{
m_pInfo->ReleaseAll();
delete m_pInfo;
m_pInfo = NULL;
}
m_midAllocatedBuffer = MID_INVALID;
m_pMemoryAllocator = NULL;
m_lBufferSize = 0;
m_iCurrentLevel = 0;
m_uiCommitedFrames = 0;
m_uiTotalFrames = 0;
m_bInfoFilled = false;
m_bIsOutputBufferLocked = false;
return UMC_OK;
}
Status FrameConstructor::Reset()
{
AutomaticMutex guard(m_synchro);
while (UMC_OK == m_OutputQueue.Remove());
m_bEndOfStream = false;
m_bIsOutputBufferLocked = false;
m_lLastBytePos = 0;
m_lFirstBytePos = 0;
m_lCurPos = 0;
m_lCurPicStart = 0;
m_iCurrentLevel = 0;
m_uiCommitedFrames = 0;
m_uiTotalFrames = 0;
m_CurFrame.Reset();
m_LastFrame.SetBufferPointer(NULL, 0);
m_LastFrame.SetAbsPos(0);
m_LastFrame.SetTime(-1.0, -1.0);
return UMC_OK;
}
Status FrameConstructor::SoftReset()
{
AutomaticMutex guard(m_synchro);
m_bEndOfStream = false;
if (m_uiTotalFrames > 0)
{
m_lCurPicStart = m_lCurPos = m_lLastBytePos = m_OutputQueue.LastBO()->iBufOffset + m_OutputQueue.LastBO()->uiSize;
m_CurFrame.iBufOffset = m_lLastBytePos;
m_CurFrame.dPTS = -1.0;
m_CurFrame.dDTS = -1.0;
}
else
{
m_lCurPicStart = m_lCurPos = m_lLastBytePos = m_CurFrame.iBufOffset = m_lFirstBytePos = 0;
m_CurFrame.Reset();
}
m_PrevSample.uiSize = 0;
m_LastSample.uiSize = 0;
return UMC_OK;
}
void FrameConstructor::SetRate(Ipp64f dRate)
{
m_dRate = dRate;
}
Status FrameConstructor::LockInputBuffer(MediaData *in)
{
AutomaticMutex guard(m_synchro);
Ipp32s lChunkSize;
// check error(s)
if (NULL == in)
return UMC_ERR_NULL_PTR;
lChunkSize = (Ipp32s)in->GetDataSize();
if ((m_lFirstBytePos > m_lLastBytePos) && (m_lLastBytePos + lChunkSize + 4 >= m_lFirstBytePos))
return UMC_ERR_NOT_ENOUGH_BUFFER; // at least 4 bytes gap between last and first bytes
if ((m_lFirstBytePos <= m_lLastBytePos) && (m_lLastBytePos + lChunkSize > m_lBufferSize))
{
if (m_lLastBytePos + lChunkSize - m_CurFrame.iBufOffset >= m_lFirstBytePos)
return UMC_ERR_NOT_ENOUGH_BUFFER;
ippsCopy_8u(m_pBuf + m_CurFrame.iBufOffset, m_pBuf, m_lLastBytePos - m_CurFrame.iBufOffset);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -