📄 umc_h264_segment_decoder_mt.cpp
字号:
/*
//
// INTEL CORPORATION PROPRIETARY INFORMATION
// This software is supplied under the terms of a license agreement or
// nondisclosure agreement with Intel Corporation and may not be copied
// or disclosed except in accordance with the terms of that agreement.
// Copyright (c) 2003-2007 Intel Corporation. All Rights Reserved.
//
//
*/
#include "umc_defs.h"
#if defined (UMC_ENABLE_H264_VIDEO_DECODER)
#include "umc_h264_segment_decoder_mt.h"
#include "vm_event.h"
#include "vm_semaphore.h"
#include "vm_thread.h"
#include "umc_h264_bitstream_inlines.h"
#include "umc_h264_segment_decoder_templates.h"
#include "umc_h264_task_broker.h"
#include "umc_h264_frame_info.h"
#include "umc_h264_task_supplier.h"
#include "umc_h264_frame_list.h"
#include "umc_h264_timing.h"
namespace UMC
{
static
#ifdef __ICL
__declspec(align(16))
#endif
const Ipp8u BlkOrder[16] =
{
0, 1, 4, 5, 2, 3, 6, 7, 8, 9, 12, 13, 10, 11, 14, 15
};
H264SegmentDecoderMultiThreaded::H264SegmentDecoderMultiThreaded(TaskBroker * pTaskBroker)
: H264SegmentDecoder(pTaskBroker)
{
InitializeSDCreator();
} // H264SegmentDecoderMultiThreaded::H264SegmentDecoderMultiThreaded(H264SliceStore *Store)
H264SegmentDecoderMultiThreaded::~H264SegmentDecoderMultiThreaded(void)
{
Release();
} // H264SegmentDecoderMultiThreaded::~H264SegmentDecoderMultiThreaded(void)
Status H264SegmentDecoderMultiThreaded::Init(Ipp32s iNumber)
{
// release object before initialization
Release();
// call parent's Init
return H264SegmentDecoder::Init(iNumber);
} // Status H264SegmentDecoderMultiThreaded::Init(Ipp32u nNumber)
void H264SegmentDecoderMultiThreaded::StartProcessingSegment(H264Task &Task)
{
switch (Task.m_iTaskID)
{
case TASK_DEB_FRAME:
// reset decoding variables
m_pSlice = NULL;
m_pCurrentFrame = Task.m_pSlice->GetCurrentFrame();
m_pSliceHeader = NULL;
m_field_index = Task.m_pSlice->GetSliceHeader()->bottom_field_flag;
break;
default:
{
m_pSlice = Task.m_pSlice;
m_pCurrentFrame = m_pSlice->GetCurrentFrame();
m_pSliceHeader = m_pSlice->GetSliceHeader();
m_field_index = m_pSliceHeader->bottom_field_flag;
// reset decoding variables
m_pBitStream = m_pSlice->GetBitStream();
mb_height = m_pSlice->GetMBHeight();
mb_width = m_pSlice->GetMBWidth();
m_pPicParamSet = m_pSlice->GetPicParam();
m_pPredWeight[0] = m_pSlice->GetPredWeigthTable(0);
m_pPredWeight[1] = m_pSlice->GetPredWeigthTable(1);
m_pSeqParamSet = m_pSlice->GetSeqParam();
m_pCoeffBlocksWrite = m_psBuffer = Task.m_pBuffer;
m_pMBIntraTypes = m_pSlice->GetMBIntraTypes();
m_bNeedToCheckMBSliceEdges = m_pSlice->NeedToCheckSliceEdges();
m_mbinfo = m_pSlice->GetMBInfo();
bit_depth_luma = m_pCurrentFrame->IsAuxiliaryFrame() ? m_pSlice->GetSeqParamEx()->bit_depth_aux :
m_pSeqParamSet->bit_depth_luma;
bit_depth_chroma = m_pCurrentFrame->IsAuxiliaryFrame() ? 8 : m_pSeqParamSet->bit_depth_chroma;
m_SD = CreateSegmentDecoder();
m_MVDistortion[0] = 0;
m_MVDistortion[1] = 0;
}
break;
}
m_gmbinfo = &(m_pCurrentFrame->m_mbinfo);
if (TASK_PROCESS != Task.m_iTaskID && TASK_DEC != Task.m_iTaskID
&& TASK_REC != Task.m_iTaskID && TASK_DEC_REC != Task.m_iTaskID)
return;
// DEBUG : ADB - should initialize context only for reconstruction or decoding tasks
// InitContext
bool is_field = m_pCurrentFrame->m_PictureStructureForDec < FRM_STRUCTURE;
m_isMBAFF = 0 != m_pSliceHeader->MbaffFrameFlag;
m_IsUseSpatialDirectMode = (m_pSliceHeader->direct_spatial_mv_pred_flag != 0);
//static ReferenceFlags pFields_stub = {0};
Ipp32s sliceNum = m_pSlice->GetSliceNum();
m_pFields[0] = m_pCurrentFrame->GetRefPicList(sliceNum, 0)->m_Flags;
m_pFields[1] = m_pCurrentFrame->GetRefPicList(sliceNum, 1)->m_Flags;
m_pRefPicList[0] = m_pCurrentFrame->GetRefPicList(sliceNum, 0)->m_RefPicList;
m_pRefPicList[1] = m_pCurrentFrame->GetRefPicList(sliceNum, 1)->m_RefPicList;
if (TASK_PROCESS == Task.m_iTaskID || TASK_DEC == Task.m_iTaskID || TASK_DEC_REC == Task.m_iTaskID)
m_pSlice->GetStateVariables(m_MBSkipCount, m_QuantPrev, m_prev_dquant);
m_IsUseConstrainedIntra = (m_pPicParamSet->constrained_intra_pred_flag != 0);
m_IsUseDirect8x8Inference = (m_pSeqParamSet->direct_8x8_inference_flag != 0);
m_IsBSlice = (m_pSliceHeader->slice_type == BPREDSLICE);
m_uPitchLuma = m_pCurrentFrame->pitch_luma();
m_uPitchChroma = m_pCurrentFrame->pitch_chroma();
m_pYPlane = m_pCurrentFrame->m_pYPlane;
m_pUPlane = m_pCurrentFrame->m_pUPlane;
m_pVPlane = m_pCurrentFrame->m_pVPlane;
if (is_field)
{
if(m_field_index)
{
Ipp32s pixel_luma_sz = bit_depth_luma > 8 ? 2 : 1;
Ipp32s pixel_chroma_sz = bit_depth_chroma > 8 ? 2 : 1;
m_pYPlane += m_uPitchLuma*pixel_luma_sz;
m_pUPlane += m_uPitchChroma*pixel_chroma_sz;
m_pVPlane += m_uPitchChroma*pixel_chroma_sz;
}
m_uPitchLuma *= 2;
m_uPitchChroma *= 2;
}
// reset neighbouringing blocks numbers
m_cur_mb.CurrentBlockNeighbours.m_bInited = 0;
}
void H264SegmentDecoderMultiThreaded::EndProcessingSegment(H264Task &Task)
{
// return performed task
Task.m_WrittenSize = (Ipp8u*)m_pCoeffBlocksWrite - (Ipp8u*)Task.m_pBuffer;
if (Task.m_bError)
{
Task.m_WrittenSize += COEFFICIENTS_BUFFER_SIZE;
}
if (TASK_DEC == Task.m_iTaskID)
{
m_MVDistortion[0] = (m_MVDistortion[0] + 6) >> INTERP_SHIFT;
m_MVDistortion[1] = (m_MVDistortion[1] + 6) >> INTERP_SHIFT;
if (m_pSlice->IsField() || m_pSlice->GetSliceHeader()->MbaffFrameFlag)
{
m_MVDistortion[0] <<= 1;
m_MVDistortion[1] <<= 1;
}
m_MVDistortion[0] = IPP_MAX(m_MVDistortion[0], m_MVDistortion[1]);
m_pTaskBroker->Lock();
m_pSlice->m_MVsDistortion = IPP_MAX(m_MVDistortion[0], m_pSlice->m_MVsDistortion);
m_pTaskBroker->Unlock();
}
m_pTaskBroker->AddPerformedTask(&Task);
}
Status H264SegmentDecoderMultiThreaded::ProcessSegment(void)
{
H264Task Task(m_iNumber);
while (m_pTaskBroker->GetNextTask(&Task))
{
Status umcRes = UMC_OK;
VM_ASSERT(Task.pFunction);
StartProcessingSegment(Task);
if (!m_pCurrentFrame->IsSkipped() && (!m_pSlice || !m_pSlice->IsError()))
{
try // do decoding
{
Ipp32s firstMB = Task.m_iFirstMB;
if (m_field_index)
{
firstMB += mb_width*mb_height / 2;
}
umcRes = (this->*(Task.pFunction))(firstMB, Task.m_iMBToProcess);
if (UMC_ERR_END_OF_STREAM == umcRes)
{
Task.m_iMaxMB = Task.m_iFirstMB + Task.m_iMBToProcess;
VM_ASSERT(m_pSlice);
// if we decode less macroblocks if we need try to recovery:
RestoreErrorRect(Task.m_iFirstMB + Task.m_iMBToProcess, m_pSlice->GetMaxMB(), m_pSlice);
umcRes = UMC_OK;
}
else if (UMC_OK != umcRes)
{
umcRes = UMC_ERR_INVALID_STREAM;
}
Task.m_bDone = true;
} catch(const h264_exception & ex)
{
umcRes = ex.GetStatus();
} catch(...)
{
umcRes = UMC_ERR_INVALID_STREAM;
}
}
if (umcRes != UMC_OK)
{
Task.m_bError = true;
Task.m_iMaxMB = Task.m_iFirstMB + Task.m_iMBToProcess;
if (m_pSlice)
RestoreErrorRect(Task.m_iFirstMB + Task.m_iMBToProcess, m_pSlice->GetMaxMB(), m_pSlice);
// break; // DEBUG : ADB should we return if error occur??
}
EndProcessingSegment(Task);
}
return UMC_OK;
} // Status H264SegmentDecoderMultiThreaded::ProcessSegment(void)
void H264SegmentDecoderMultiThreaded::RestoreErrorRect(Ipp32s startMb, Ipp32s endMb, H264Slice * pSlice)
{
m_pSlice = pSlice;
if (startMb >= endMb || !m_pSlice || m_pSlice->IsSliceGroups())
return;
try
{
H264DecoderFrame * pCurrentFrame = m_pSlice->GetCurrentFrame();
if (!pCurrentFrame)
{
VM_ASSERT(false);
return;
}
H264DecoderFrame * pRefFrame = pCurrentFrame->GetRefPicList(m_pSlice->GetSliceNum(), 0)->m_RefPicList[0];
pCurrentFrame->SetFrameExistFlag(false);
pCurrentFrame->SetError(1);
if (!pRefFrame || pRefFrame->IsSkipped())
{
pRefFrame = m_pTaskBroker->m_pTaskSupplier->GetDPBList()->FindClosest(pCurrentFrame);
}
m_SD->RestoreErrorRect(startMb, endMb, pRefFrame, this);
} catch (...)
{
// nothing to do
}
}
Status H264SegmentDecoderMultiThreaded::DecodeSegment(Ipp32s iCurMBNumber, Ipp32s &iMBToDecode)
{
Status umcRes;
Ipp32u iBorder = iCurMBNumber + iMBToDecode;
START_TICK
if (m_pPicParamSet->entropy_coding_mode)
{
umcRes = DecodeMacroBlockCABAC(iCurMBNumber, iBorder);
}
else
{
umcRes = DecodeMacroBlockCAVLC(iCurMBNumber, iBorder);
}
END_TICK(decode_time)
if (UMC_ERR_END_OF_STREAM == umcRes)
iMBToDecode = iBorder - iCurMBNumber;
return umcRes;
} // Status H264SegmentDecoderMultiThreaded::DecodeSegment(Ipp32s iCurMBNumber, Ipp32s &iMBToDecode)
Status H264SegmentDecoderMultiThreaded::ReconstructSegment(Ipp32s iCurMBNumber, Ipp32s &iMaxMBToReconstruct)
{
Status umcRes;
Ipp32s iBorder = iCurMBNumber + iMaxMBToReconstruct;
START_TICK
if (m_pPicParamSet->entropy_coding_mode)
{
umcRes = ReconstructMacroBlockCABAC(iCurMBNumber, iBorder);
}
else
{
umcRes = ReconstructMacroBlockCAVLC(iCurMBNumber, iBorder);
}
END_TICK(reconstruction_time)
return umcRes;
} // Status H264SegmentDecoderMultiThreaded::ReconstructSegment(Ipp32s iCurMBNumber, Ipp32s &iMBToReconstruct)
Status H264SegmentDecoderMultiThreaded::DecRecSegment(Ipp32s iCurMBNumber, Ipp32s &iMaxMBToDecRec)
{
Status umcRes;
//Ipp32s iBorder = iCurMBNumber + iMaxMBToDecRec;
m_psBuffer = align_pointer<UMC::CoeffsPtrCommon> (m_pCoefficientsBuffer, DEFAULT_ALIGN_VALUE);
if (0 == m_pPicParamSet->entropy_coding_mode)
{
umcRes = m_SD->DecodeSegmentCAVLC_Single(&iCurMBNumber, iMaxMBToDecRec, this);
}
else
{
umcRes = m_SD->DecodeSegmentCABAC_Single(&iCurMBNumber, iMaxMBToDecRec, this);
}
return umcRes;
} // Status H264SegmentDecoderMultiThreaded::DecRecSegment(Ipp32s iCurMBNumber, Ipp32s &iMBToReconstruct)
Status H264SegmentDecoderMultiThreaded::DeblockSegmentTask(Ipp32s iCurMBNumber, Ipp32s &iMBToDeblock)
{
START_TICK
// when there is slice groups or threaded deblocking
if (NULL == m_pSlice)
H264SegmentDecoder::DeblockFrame(iCurMBNumber, iMBToDeblock);
else
H264SegmentDecoder::DeblockSegment(iCurMBNumber, iMBToDeblock);
END_TICK(deblocking_time)
return UMC_OK;
} // Status H264SegmentDecoderMultiThreaded::DeblockSegmentTask(Ipp32s iCurMBNumber, Ipp32s &iMBToDeblock)
void H264SegmentDecoderMultiThreaded::DecodeMotionVectors_CABAC(void)
{
Ipp32s curmb_fdf = pGetMBFieldDecodingFlag(m_cur_mb.GlobalMacroblockInfo);
// initialize blocks coding pattern maps
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -