📄 umc_mpeg2_dec.cpp
字号:
Status MPEG2VideoDecoderBase::GetInfo(BaseCodecParams* info)
{
VideoDecoderParams *pParams;
if(info == NULL)
return UMC_ERR_NULL_PTR;
// BaseCodecParams
info->profile = sequenceHeader.profile;
info->level = sequenceHeader.level;
pParams = DynamicCast<VideoDecoderParams> (info);
if (NULL != pParams) {
pParams->info = m_ClipInfo;
//VideoDecoder::GetInfo(pParams);
pParams->lFlags = m_lFlags;
if(m_bOwnAllocator)
pParams->lpMemoryAllocator = 0;
else
pParams->lpMemoryAllocator = m_pMemoryAllocator;
pParams->pPostProcessing = m_PostProcessing;
pParams->numThreads = m_nNumberOfThreads;
}
return UMC_OK;
}
Status MPEG2VideoDecoderBase::GetPerformance (Ipp64f * /*perf*/)
{
return UMC_OK;
}
Status MPEG2VideoDecoderBase::SaveFrame(Ipp32s index, Ipp64f dTime, MediaData *output)
{
Status ret;
if (m_LastDecodedFrame.GetColorFormat() != m_ClipInfo.color_format ||
m_LastDecodedFrame.GetWidth() != m_ClipInfo.clip_info.width ||
m_LastDecodedFrame.GetHeight() != m_ClipInfo.clip_info.height) {
m_LastDecodedFrame.Init(m_ClipInfo.clip_info.width, m_ClipInfo.clip_info.height, m_ClipInfo.color_format);
}
m_LastDecodedFrame.SetFrameType(frame_buffer.frame_p_c_n[index].frame_type);
m_LastDecodedFrame.SetTime(dTime);
m_LastDecodedFrame.SetPlanePitch(frame_buffer.Y_comp_pitch, 0);
m_LastDecodedFrame.SetPlanePitch(frame_buffer.U_comp_pitch, 1);
m_LastDecodedFrame.SetPlanePitch(frame_buffer.V_comp_pitch, 2);
if (sequenceHeader.progressive_sequence || PictureHeader.progressive_frame) {
m_LastDecodedFrame.SetPictureStructure(PS_FRAME);
} else {
if(PictureHeader.picture_structure == FRAME_PICTURE)
m_LastDecodedFrame.SetPictureStructure(
(PictureHeader.top_field_first) ? PS_TOP_FIELD_FIRST : PS_BOTTOM_FIELD_FIRST);
else
m_LastDecodedFrame.SetPictureStructure( // check last field type
(PictureHeader.picture_structure == BOTTOM_FIELD) ? PS_TOP_FIELD_FIRST : PS_BOTTOM_FIELD_FIRST);
}
if (!m_PostProcessing) {
m_PostProcessing = m_allocatedPostProcessing = new VideoProcessing;
}
if (UMC_OK != (ret = LockBuffers()))
return ret;
m_LastDecodedFrame.SetPlanePointer(frame_buffer.frame_p_c_n[index].Y_comp_data, 0);
m_LastDecodedFrame.SetPlanePointer(frame_buffer.frame_p_c_n[index].U_comp_data, 1);
m_LastDecodedFrame.SetPlanePointer(frame_buffer.frame_p_c_n[index].V_comp_data, 2);
ret = m_PostProcessing->GetFrame(&m_LastDecodedFrame, output);
UnlockBuffers();
return ret;
}
void MPEG2VideoDecoderBase::ReadCCData()
{
Status umcRes = UMC_OK;
MediaData ccData;
//we will not wait if there is not buffer
//while(umcRes != UMC_OK)
{
umcRes = m_pCCData->LockInputBuffer(&ccData);
//vm_time_sleep(1);
}
if(umcRes == UMC_OK)
{
IppVideoContext* video = Video[0];
Ipp8u* ptr;
Ipp8u* readptr;
Ipp32s size;
Ipp32s inputsize;
Ipp32s code;
ptr = (Ipp8u*)ccData.GetDataPointer() + ccData.GetDataSize();
size = (Ipp32s)((Ipp8u*)ccData.GetBufferPointer() + ccData.GetBufferSize() - ptr);
if(ptr==0 || size<4)
return;
inputsize = GET_REMAINED_BYTES(video->bs);
readptr = GET_BYTE_PTR(video->bs);
FIND_START_CODE(video->bs, code);
if(code != UMC_ERR_NOT_ENOUGH_DATA)
inputsize = GET_BYTE_PTR(video->bs) - readptr;
ptr[0] = 0; ptr[1] = 0; ptr[2] = 1; ptr[3] = 0xb2;
size -= 4;
size = IPP_MIN(size, inputsize);
ippsCopy_8u(readptr, ptr+4, size);
ccData.SetDataSize(ccData.GetDataSize() + size+4);
umcRes = m_pCCData->UnLockInputBuffer(&ccData);
if(code == UMC_ERR_NOT_ENOUGH_DATA) {
ptr = GET_END_PTR(video->bs);
if(ptr[-1] <= 1) ptr--;
if(ptr[-1] == 0) ptr--;
if(ptr[-1] == 0) ptr--;
SET_PTR(video->bs, ptr);
}
}
}
MPEG2VideoDecoder::MPEG2VideoDecoder()
{
m_pDec = NULL;
}
MPEG2VideoDecoder::~MPEG2VideoDecoder(void)
{
Close();
}
Status MPEG2VideoDecoder::Init(BaseCodecParams *init)
{
Close();
m_pDec = new MPEG2VideoDecoderBase;
if(!m_pDec) return UMC_ERR_ALLOC;
Status res = m_pDec->Init(init);
if (UMC_OK != res) {
Close();
}
return res;
}
Status MPEG2VideoDecoder::GetFrame(MediaData* in, MediaData* out)
{
if(m_pDec)
{
return m_pDec->GetFrame(in, out);
}
return UMC_ERR_NOT_INITIALIZED;
}
Status MPEG2VideoDecoder::Close()
{
if(m_pDec)
{
m_pDec->Close();
delete m_pDec;
m_pDec = NULL;
}
return UMC_OK;
}
Status MPEG2VideoDecoder::Reset()
{
if(m_pDec)
{
return m_pDec->Reset();
}
return UMC_ERR_NOT_INITIALIZED;
}
Status MPEG2VideoDecoder::GetInfo(BaseCodecParams* info)
{
if(m_pDec)
{
return m_pDec->GetInfo(info);
}
return UMC_ERR_NOT_INITIALIZED;
}
Status MPEG2VideoDecoder::GetPerformance(Ipp64f *perf)
{
if(m_pDec)
{
return m_pDec->GetPerformance(perf);
}
return UMC_ERR_NOT_INITIALIZED;
}
Status MPEG2VideoDecoder::ResetSkipCount()
{
if(m_pDec)
{
return m_pDec->ResetSkipCount();
}
return UMC_ERR_NOT_INITIALIZED;
}
Status MPEG2VideoDecoder::SkipVideoFrame(Ipp32s count)
{
if(m_pDec)
{
return m_pDec->SkipVideoFrame(count);
}
return UMC_ERR_NOT_INITIALIZED;
}
Ipp32u MPEG2VideoDecoder::GetNumOfSkippedFrames()
{
if(m_pDec)
{
return m_pDec->GetNumOfSkippedFrames();
}
return (Ipp32u)(-1); // nobody check for -1 really
}
Status MPEG2VideoDecoder::PreviewLastFrame(VideoData *out, BaseCodec *pPostProcessing)
{
if(m_pDec)
{
return m_pDec->PreviewLastFrame(out, pPostProcessing);
}
return UMC_ERR_NOT_INITIALIZED;
}
Status MPEG2VideoDecoder::GetUserData(MediaData* pCC)
{
if(m_pDec)
{
return m_pDec->GetUserData(pCC);
}
return UMC_ERR_NOT_INITIALIZED;
}
Status MPEG2VideoDecoder::SetParams(BaseCodecParams* params)
{
if(m_pDec)
{
return m_pDec->SetParams(params);
}
return UMC_ERR_NOT_INITIALIZED;
}
Status MPEG2VideoDecoderBase::SetParams(BaseCodecParams* params)
{
VideoDecoderParams *pParams = DynamicCast<VideoDecoderParams>(params);
if (NULL == pParams)
return UMC_ERR_NULL_PTR;
if(pParams->lTrickModesFlag == 3)
{
m_bNoBframes = true;
m_bNoPframes = false;
}
else if(pParams->lTrickModesFlag == 5)
{
m_bNoBframes = true;
m_bNoPframes = true;
}
else
{
m_bNoBframes = false;
m_bNoPframes = false;
}
if(pParams->lTrickModesFlag == 7)
{
m_dPlaybackRate = pParams->dPlaybackRate;
}
return UMC_OK;
}
Status MPEG2VideoDecoderBase::UpdateFrameBuffer(void)
{
Ipp32s pitch_l, pitch_c;
Ipp32s size_l, size_c;
Ipp8u* ptr;
Ipp32s i;
Ipp32s buff_size;
if(frame_buffer.allocated_mb_width == sequenceHeader.mb_width &&
frame_buffer.allocated_mb_height == sequenceHeader.mb_height &&
frame_buffer.allocated_cformat == m_ClipInfo.color_format)
return UMC_OK; // all is the same
pitch_l = align_value<Ipp32s>(sequenceHeader.mb_width*16, ALIGN_VALUE);
size_l = sequenceHeader.mb_height*16*pitch_l;
if (m_ClipInfo.color_format != YUV444) {
pitch_c = align_value<Ipp32s>(sequenceHeader.mb_width*8, ALIGN_VALUE);
size_c = sequenceHeader.mb_height*8*pitch_c;
if (m_ClipInfo.color_format == YUV422)
size_c *= 2;
} else {
pitch_c = pitch_l;
size_c = size_l;
}
frame_buffer.Y_comp_pitch = pitch_l;
frame_buffer.U_comp_pitch = pitch_c;
frame_buffer.V_comp_pitch = pitch_c;
frame_buffer.pic_size = size_l;
blkOffsets[0][0] = 0;
blkOffsets[0][1] = 8;
blkOffsets[0][2] = 8*pitch_l;
blkOffsets[0][3] = 8*pitch_l + 8;
blkOffsets[0][4] = 0;
blkOffsets[0][5] = 0;
blkOffsets[0][6] = 8*pitch_c;
blkOffsets[0][7] = 8*pitch_c;
blkOffsets[1][0] = 0;
blkOffsets[1][1] = 8;
blkOffsets[1][2] = pitch_l;
blkOffsets[1][3] = pitch_l + 8;
blkOffsets[1][4] = 0;
blkOffsets[1][5] = 0;
blkOffsets[1][6] = pitch_c;
blkOffsets[1][7] = pitch_c;
blkOffsets[2][0] = 0;
blkOffsets[2][1] = 8;
blkOffsets[2][2] = 16*pitch_l;
blkOffsets[2][3] = 16*pitch_l + 8;
blkOffsets[2][4] = 0;
blkOffsets[2][5] = 0;
blkOffsets[2][6] = 16*pitch_c;
blkOffsets[2][7] = 16*pitch_c;
blkPitches[0][0] = pitch_l;
blkPitches[0][1] = pitch_c;
blkPitches[1][0] = 2*pitch_l;
blkPitches[1][1] = pitch_c;
if (m_ClipInfo.color_format != YUV420) blkPitches[1][1] = 2 * pitch_c;
blkPitches[2][0] = 2*pitch_l;
blkPitches[2][1] = 2*pitch_c;
if(frame_buffer.allocated_mb_width >= sequenceHeader.mb_width &&
frame_buffer.allocated_mb_height >= sequenceHeader.mb_height &&
frame_buffer.allocated_cformat >= m_ClipInfo.color_format)
return UMC_OK; // use allocated before
frame_buffer.allocated_mb_width = sequenceHeader.mb_width;
frame_buffer.allocated_mb_height = sequenceHeader.mb_height;
frame_buffer.allocated_cformat = m_ClipInfo.color_format;
for (i = 0; i < 3; i++)
{
frame_buffer.frame_p_c_n[i].va_index = -1;
}
// Alloc frames
if(frame_buffer.mid_context_data != MID_INVALID)
m_pMemoryAllocator->Free(frame_buffer.mid_context_data);
buff_size = 3*size_l + 6*size_c;
#ifdef KEEP_HISTORY
buff_size += 3*sequenceHeader.numMB;
#endif
if(UMC_OK != m_pMemoryAllocator->Alloc(&frame_buffer.mid_context_data,
buff_size, UMC_ALLOC_PERSISTENT, ALIGN_VALUE)) {
vm_debug_trace(VM_DEBUG_ERROR, VM_STRING("External allocation failed\n"));
return UMC_ERR_ALLOC;
}
frame_buffer.ptr_context_data = (Ipp8u*)m_pMemoryAllocator->Lock(frame_buffer.mid_context_data);
if(!frame_buffer.ptr_context_data) {
vm_debug_trace(VM_DEBUG_ERROR, VM_STRING("External Lock failed\n"));
return UMC_ERR_ALLOC;
}
ptr = frame_buffer.ptr_context_data;
ptr = align_pointer<Ipp8u*>(ptr, ALIGN_VALUE);
for (i = 0; i < 3; i++) {
frame_buffer.frame_p_c_n[i].Y_comp_data = ptr;
ptr += size_l;
frame_buffer.frame_p_c_n[i].U_comp_data = ptr;
ptr += size_c;
frame_buffer.frame_p_c_n[i].V_comp_data = ptr;
ptr += size_c;
}
#ifdef KEEP_HISTORY
ippsSet_8u(0, ptr, 3*sequenceHeader.numMB);
frame_buffer.frame_p_c_n[0].frame_history = ptr;
frame_buffer.frame_p_c_n[1].frame_history = ptr + sequenceHeader.numMB;
frame_buffer.frame_p_c_n[2].frame_history = ptr + 2*sequenceHeader.numMB;
#endif
if (UMC_OK != m_pMemoryAllocator->Unlock(frame_buffer.mid_context_data)) {
vm_debug_trace(VM_DEBUG_ERROR, VM_STRING("External Unlock failed\n"));
}
return UMC_OK;
}
#define SHIFT_PTR(oldptr, oldbase, newbase) \
( (newbase) + ( (Ipp8u*)(oldptr) - (Ipp8u*)(oldbase) ) )
Status MPEG2VideoDecoderBase::LockBuffers(void)
{
Ipp32s i;
Ipp8u* newptr;
if (frame_buffer.ptr_context_data == 0) // wasn't allocated, error
return UMC_ERR_NOT_INITIALIZED;
newptr = (Ipp8u*) m_pMemoryAllocator->Lock(frame_buffer.mid_context_data);
if(newptr == frame_buffer.ptr_context_data) //ptr not changed
return UMC_OK;
// else need to reset pointers
for (i = 0; i < 3; i++) {
frame_buffer.frame_p_c_n[i].Y_comp_data =
(Ipp8u*)SHIFT_PTR(frame_buffer.frame_p_c_n[i].Y_comp_data,
frame_buffer.ptr_context_data, newptr);
frame_buffer.frame_p_c_n[i].U_comp_data =
(Ipp8u*)SHIFT_PTR(frame_buffer.frame_p_c_n[i].U_comp_data,
frame_buffer.ptr_context_data, newptr);
frame_buffer.frame_p_c_n[i].V_comp_data =
(Ipp8u*)SHIFT_PTR(frame_buffer.frame_p_c_n[i].V_comp_data,
frame_buffer.ptr_context_data, newptr);
#ifdef KEEP_HISTORY
frame_buffer.frame_p_c_n[i].frame_history =
(Ipp8u*)SHIFT_PTR(frame_buffer.frame_p_c_n[i].frame_history,
frame_buffer.ptr_context_data, newptr);
#endif
}
frame_buffer.ptr_context_data = newptr;
return UMC_OK;
}
Status MPEG2VideoDecoderBase::UnlockBuffers(void)
{
return m_pMemoryAllocator->Unlock(frame_buffer.mid_context_data);
}
// need to lock internal buffer before call
Status MPEG2VideoDecoderBase::PreviewLastFrame(VideoData *out, BaseCodec *pPostProcessing)
{
Status ret = UMC_ERR_NOT_ENOUGH_DATA;
if (frame_buffer.retrieve < 0 || UMC_OK != (ret = LockBuffers()))
return ret;
m_LastDecodedFrame.SetPlanePointer(frame_buffer.frame_p_c_n[frame_buffer.retrieve].Y_comp_data, 0);
m_LastDecodedFrame.SetPlanePointer(frame_buffer.frame_p_c_n[frame_buffer.retrieve].U_comp_data, 1);
m_LastDecodedFrame.SetPlanePointer(frame_buffer.frame_p_c_n[frame_buffer.retrieve].V_comp_data, 2);
ret = VideoDecoder::PreviewLastFrame(out, pPostProcessing);
UnlockBuffers();
return ret;
}
#endif // UMC_ENABLE_MPEG2_VIDEO_DECODER
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -