📄 umc_mpeg4_video_decoder.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-2008 Intel Corporation. All Rights Reserved.
//
//
*/
#include "umc_defs.h"
#if defined (UMC_ENABLE_MPEG4_VIDEO_DECODER)
#include <string.h>
#include "vm_debug.h"
#include "umc_mpeg4_video_decoder.h"
#include "umc_video_data.h"
namespace UMC
{
VideoDecoder *CreateMPEG4Decoder() { return (new MPEG4VideoDecoder()); }
Status MPEG4VideoDecoder::AllocateInitFrame(mp4_Frame* pFrame)
{
Status status;
Ipp32s w, h;
Ipp8u *p;
w = (pFrame->mbPerRow + 2 * MP4_NUM_EXT_MB) << 4;
h = (pFrame->mbPerCol + 2 * MP4_NUM_EXT_MB) << 4;
status = m_pMemoryAllocator->Alloc(&pFrame->mid, w * h + (w * h >> 1), UMC_ALLOC_PERSISTENT);
if (status != UMC_OK)
return status;
p = (Ipp8u*)m_pMemoryAllocator->Lock(pFrame->mid);
ippsSet_8u(0, p, w * h);
ippsSet_8u(128, p + w * h, w * h >> 1);
status = m_pMemoryAllocator->Unlock(pFrame->mid);
if (status != UMC_OK)
return status;
pFrame->stepY = w;
pFrame->stepCb = w >> 1;
pFrame->stepCr = w >> 1;
return UMC_OK;
}
void MPEG4VideoDecoder::LockFrame(mp4_Frame* pFrame)
{
Ipp32u w, h;
w = (pFrame->mbPerRow + 2 * MP4_NUM_EXT_MB) << 4;
h = (pFrame->mbPerCol + 2 * MP4_NUM_EXT_MB) << 4;
pFrame->apY = (Ipp8u*)m_pMemoryAllocator->Lock(pFrame->mid);
pFrame->pY = pFrame->apY + w * 16 + 16;
pFrame->apCb = pFrame->apY + w * h;
w >>= 1;
h >>= 1;
pFrame->pCb = pFrame->apCb + w * 8 + 8;
pFrame->apCr = pFrame->apCb + w * h;
pFrame->pCr = pFrame->apCr + w * 8 + 8;
}
Status MPEG4VideoDecoder::AllocateBuffers()
{
Status status = UMC_OK;
// allocate only frame memory, may be extended for whole buffers
if (m_decInfo->VisualObject.VideoObject.shape == MP4_SHAPE_TYPE_RECTANGULAR) {
// current frame
m_decInfo->VisualObject.cFrame.mbPerRow = (m_decInfo->VisualObject.VideoObject.width + 15) >> 4;
m_decInfo->VisualObject.cFrame.mbPerCol = (m_decInfo->VisualObject.VideoObject.height + 15) >> 4;
status = AllocateInitFrame(&m_decInfo->VisualObject.cFrame);
if (status != UMC_OK)
return status;
if (m_decInfo->VisualObject.VideoObject.sprite_enable != MP4_SPRITE_STATIC) {
// ref in past frame
if (!m_decInfo->noPVOPs) {
m_decInfo->VisualObject.rFrame.mbPerRow = m_decInfo->VisualObject.cFrame.mbPerRow;
m_decInfo->VisualObject.rFrame.mbPerCol = m_decInfo->VisualObject.cFrame.mbPerCol;
status = AllocateInitFrame(&m_decInfo->VisualObject.rFrame);
if (status != UMC_OK)
return status;
}
// ref in future frame
if (!m_decInfo->noBVOPs) {
m_decInfo->VisualObject.nFrame.mbPerRow = m_decInfo->VisualObject.cFrame.mbPerRow;
m_decInfo->VisualObject.nFrame.mbPerCol = m_decInfo->VisualObject.cFrame.mbPerCol;
status = AllocateInitFrame(&m_decInfo->VisualObject.nFrame);
if (status != UMC_OK)
return status;
}
} else {
// data for static sprite
m_decInfo->VisualObject.sFrame.mbPerRow = (m_decInfo->VisualObject.VideoObject.sprite_width + 15) >> 4;
m_decInfo->VisualObject.sFrame.mbPerCol = (m_decInfo->VisualObject.VideoObject.sprite_height + 15) >> 4;
status = AllocateInitFrame(&m_decInfo->VisualObject.sFrame);
if (status != UMC_OK)
return status;
}
}
if (mp4_InitVOL(m_decInfo) != MP4_STATUS_OK) {
mp4_Error("Error: No memory to allocate internal buffers\n");
return UMC_ERR_ALLOC;
}
return status;
}
Status MPEG4VideoDecoder::FreeBuffers()
{
Status status = UMC_OK;
if (m_decInfo->VisualObject.VideoObject.shape == MP4_SHAPE_TYPE_RECTANGULAR) {
if (m_decInfo->VisualObject.cFrame.mid) {
status = m_pMemoryAllocator->Free(m_decInfo->VisualObject.cFrame.mid);
m_decInfo->VisualObject.cFrame.mid = 0;
if (status != UMC_OK)
return status;
}
if (m_decInfo->VisualObject.VideoObject.sprite_enable != MP4_SPRITE_STATIC) {
if (m_decInfo->VisualObject.rFrame.mid) {
if (!m_decInfo->noPVOPs)
status = m_pMemoryAllocator->Free(m_decInfo->VisualObject.rFrame.mid);
m_decInfo->VisualObject.rFrame.mid = 0;
if (status != UMC_OK)
return status;
}
if (m_decInfo->VisualObject.nFrame.mid) {
if (!m_decInfo->noBVOPs)
status = m_pMemoryAllocator->Free(m_decInfo->VisualObject.nFrame.mid);
m_decInfo->VisualObject.nFrame.mid = 0;
if (status != UMC_OK)
return status;
}
} else {
if (m_decInfo->VisualObject.sFrame.mid) {
status = m_pMemoryAllocator->Free(m_decInfo->VisualObject.sFrame.mid);
m_decInfo->VisualObject.sFrame.mid = 0;
if (status != UMC_OK)
return status;
}
}
}
mp4_FreeVOL(m_decInfo);
return status;
}
void MPEG4VideoDecoder::LockBuffers()
{
if (m_decInfo->VisualObject.VideoObject.shape == MP4_SHAPE_TYPE_RECTANGULAR) {
LockFrame(&m_decInfo->VisualObject.cFrame);
if (m_decInfo->VisualObject.VideoObject.sprite_enable != MP4_SPRITE_STATIC) {
LockFrame(&m_decInfo->VisualObject.rFrame);
LockFrame(&m_decInfo->VisualObject.nFrame);
} else {
LockFrame(&m_decInfo->VisualObject.sFrame);
}
}
}
Status MPEG4VideoDecoder::UnlockBuffers()
{
Status status = UMC_OK;
if (m_decInfo->VisualObject.VideoObject.shape == MP4_SHAPE_TYPE_RECTANGULAR) {
status = m_pMemoryAllocator->Unlock(m_decInfo->VisualObject.cFrame.mid);
if (status != UMC_OK)
return status;
if (m_decInfo->VisualObject.VideoObject.sprite_enable != MP4_SPRITE_STATIC) {
status = m_pMemoryAllocator->Unlock(m_decInfo->VisualObject.rFrame.mid);
if (status != UMC_OK)
return status;
status = m_pMemoryAllocator->Unlock(m_decInfo->VisualObject.nFrame.mid);
if (status != UMC_OK)
return status;
} else {
status = m_pMemoryAllocator->Unlock(m_decInfo->VisualObject.sFrame.mid);
if (status != UMC_OK)
return status;
}
}
return status;
}
Status MPEG4VideoDecoder::Init(BaseCodecParams *lpInit)
{
Status status = UMC_OK;
VideoDecoderParams *pParam = DynamicCast<VideoDecoderParams> (lpInit);
Close();
if (NULL == m_decInfo)
return UMC_ERR_ALLOC;
if (NULL == pParam)
return UMC_ERR_NULL_PTR;
// create default memory allocator if not exist
status = BaseCodec::Init(lpInit);
if (status != UMC_OK)
return status;
m_time_reset = 0;
m_dec_time_fr = 0.0;
m_dec_time_base = -1.0;
m_dec_time_prev = 0.0;
m_dec_time_frinc = (pParam->info.framerate > 0) ? 1.0 / pParam->info.framerate : 0.0;
m_is_skipped_b = m_skipped_fr = m_b_prev = 0;
m_Param = *pParam;
m_IsInit = m_IsInitBase = false;
memset(m_decInfo, 0, sizeof(mp4_Info));
m_decInfo->stopOnErr = 0;
m_decInfo->strictSyntaxCheck = 0;
m_decInfo->VisualObject.verid = 1;
m_DeringingProcPlane[0] = m_DeringingProcPlane[1] = m_DeringingProcPlane[2] = false;
m_DeblockingProcPlane[0] = m_DeblockingProcPlane[1] = m_DeblockingProcPlane[2] = false;
m_DeblockingTHR1 = 2;
m_DeblockingTHR2 = 6;
ppFrame0.mid = ppFrame1.mid = 0;
if (NULL != pParam->m_pData) {
if (pParam->m_pData->GetTime() >= 0.0)
m_dec_time_base = pParam->m_pData->GetTime();
m_decInfo->buflen = pParam->m_pData->GetDataSize();
if (m_decInfo->buflen > 0) {
m_decInfo->bufptr = m_decInfo->buffer = reinterpret_cast<Ipp8u *> (pParam->m_pData->GetDataPointer());
m_decInfo->bitoff = 0;
status = InsideInit();
pParam->m_pData->MoveDataPointer(static_cast<Ipp32u>((size_t)m_decInfo->bufptr - (size_t)m_decInfo->buffer));
}
}
if (UMC_OK == status) {
m_PostProcessing = pParam->pPostProcessing;
// set VOP size if it is unknown in splitter
if (pParam->info.clip_info.width == 0 || pParam->info.clip_info.height == 0) {
if (m_decInfo->VisualObject.VideoObject.width == 0 && m_decInfo->VisualObject.VideoObject.height== 0)
return UMC_ERR_INIT;
else {
pParam->info.clip_info.width = m_Param.info.clip_info.width = m_decInfo->VisualObject.VideoObject.width;
pParam->info.clip_info.height = m_Param.info.clip_info.height = m_decInfo->VisualObject.VideoObject.height;
}
}
m_ClipInfo = m_Param.info;
m_IsInitBase = true;
}
return status;
}
Status MPEG4VideoDecoder::InsideInit()
{
Status status;
Ipp32u code, h_vo_found = 0, h_vos_found = 0;
m_buffered_frame = m_Param.lFlags & FLAG_VDEC_REORDER;
if (m_Param.info.stream_subtype == MPEG4_VIDEO_DIVX5) {
m_decInfo->ftype = 2;
m_decInfo->ftype_f = 1;
} else if (m_Param.info.stream_subtype == MPEG4_VIDEO_QTIME) {
m_decInfo->ftype = 1;
m_decInfo->ftype_f = 0;
} else { // UNDEF_VIDEO_SUBTYPE
m_decInfo->ftype = 0;
m_decInfo->ftype_f = 0;
}
m_decInfo->num_threads = m_Param.numThreads;
for (;;) {
if (m_decInfo->strictSyntaxCheck) {
if (!mp4_SeekStartCodeOrShortPtr(m_decInfo)) {
mp4_Error("Error: Can't find Visual Object Sequence or start code or short_video_start_marker");
return MP4_STATUS_PARSE_ERROR;
}
// check short_video_start_marker
if (mp4_IsShortCode(m_decInfo)) {
if ((status = mp4_Parse_VideoObject(m_decInfo)) != MP4_STATUS_OK)
return status;
} else {
if (mp4_IsStartCodeValue(m_decInfo, MP4_VISUAL_OBJECT_SEQUENCE_SC, MP4_VISUAL_OBJECT_SEQUENCE_SC)) {
m_decInfo->bufptr ++;
if ((status = mp4_Parse_VisualObjectSequence(m_decInfo)) != MP4_STATUS_OK)
return status;
} else {
mp4_Error("Error: Can't find Visual Object Sequence start code");
return MP4_STATUS_PARSE_ERROR;
}
if (!mp4_SeekStartCodePtr(m_decInfo)) {
mp4_Error("Error: Can't find Visual Object start code");
return MP4_STATUS_PARSE_ERROR;
}
if (mp4_IsStartCodeValue(m_decInfo, MP4_VISUAL_OBJECT_SC, MP4_VISUAL_OBJECT_SC)) {
m_decInfo->bufptr ++;
if ((status = mp4_Parse_VisualObject(m_decInfo)) != MP4_STATUS_OK)
return status;
} else {
mp4_Error("Error: Can't find Visual Object start code");
return MP4_STATUS_PARSE_ERROR;
}
if (!mp4_SeekStartCodePtr(m_decInfo)) {
mp4_Error("Error: Can't find Video Object start code");
return MP4_STATUS_PARSE_ERROR;
}
if (mp4_IsStartCodeValue(m_decInfo, MP4_VIDEO_OBJECT_MIN_SC, MP4_VIDEO_OBJECT_MAX_SC)) {
m_decInfo->bufptr ++;
if ((status = mp4_Parse_VideoObject(m_decInfo)) != MP4_STATUS_OK)
return status;
} else {
mp4_Error("Error: Can't find Video Object start code");
return MP4_STATUS_PARSE_ERROR;
}
}
} else {
if (!mp4_SeekStartCodeOrShortPtr(m_decInfo)) {
mp4_Error("Error: Can't find Visual Object or Video Object start codes or short_video_start_marker\n");
return UMC_ERR_SYNC;
}
// check short_video_start_marker
if (mp4_IsShortCode(m_decInfo)) {
code = MP4_VIDEO_OBJECT_MIN_SC;
} else {
code = mp4_GetBits(m_decInfo, 8);
if (!h_vos_found && code == MP4_VISUAL_OBJECT_SEQUENCE_SC) {
h_vos_found = 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -