📄 umc_h261_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) 2005-2007 Intel Corporation. All Rights Reserved.
//
//
*/
#include <string.h>
#include "vm_debug.h"
#include "umc_h261_video_decoder.h"
#include "umc_video_data.h"
#include "h261decoder.h"
namespace UMC
{
Status H261VideoDecoder::AllocateBuffers()
{
Status status = UMC_OK;
Ipp32s w, h;
Ipp8u *p;
w = m_decInfo->picture_width;
h = m_decInfo->picture_height;
status = m_pMemoryAllocator->Alloc(&m_decInfo->mid_cur, w * h + (w * h >> 1), UMC_ALLOC_PERSISTENT);
if (status != UMC_OK)
return status;
p = (Ipp8u*)m_pMemoryAllocator->Lock(m_decInfo->mid_cur);
ippsSet_8u(0, p, w * h);
ippsSet_8u(128, p + w * h, w * h >> 1);
status = m_pMemoryAllocator->Unlock(m_decInfo->mid_cur);
if (status != UMC_OK)
return status;
status = m_pMemoryAllocator->Alloc(&m_decInfo->mid_ref, w * h + (w * h >> 1), UMC_ALLOC_PERSISTENT);
if (status != UMC_OK)
return status;
p = (Ipp8u*)m_pMemoryAllocator->Lock(m_decInfo->mid_ref);
ippsSet_8u(0, p, w * h);
ippsSet_8u(128, p + w * h, w * h >> 1);
status = m_pMemoryAllocator->Unlock(m_decInfo->mid_ref);
if (status != UMC_OK)
return status;
return status;
}
Status H261VideoDecoder::FreeBuffers()
{
Status status = UMC_OK;
if (m_decInfo->mid_cur) {
status = m_pMemoryAllocator->Free(m_decInfo->mid_cur);
if (status != UMC_OK)
return status;
}
if (m_decInfo->mid_ref) {
status = m_pMemoryAllocator->Free(m_decInfo->mid_ref);
if (status != UMC_OK)
return status;
}
return status;
}
void H261VideoDecoder::LockBuffers()
{
Ipp32s w, h;
w = m_decInfo->picture_width;
h = m_decInfo->picture_height;
m_decInfo->curPic[0] = (Ipp8u*)m_pMemoryAllocator->Lock(m_decInfo->mid_cur);
m_decInfo->curPic[1] = m_decInfo->curPic[0] + w * h;
m_decInfo->curPic[2] = m_decInfo->curPic[1] + (w * h >> 2);
m_decInfo->refPic[0] = (Ipp8u*)m_pMemoryAllocator->Lock(m_decInfo->mid_ref);
m_decInfo->refPic[1] = m_decInfo->refPic[0] + w * h;
m_decInfo->refPic[2] = m_decInfo->refPic[1] + (w * h >> 2);
}
Status H261VideoDecoder::UnlockBuffers()
{
Status status = UMC_OK;
status = m_pMemoryAllocator->Unlock(m_decInfo->mid_cur);
if (status != UMC_OK)
return status;
status = m_pMemoryAllocator->Unlock(m_decInfo->mid_ref);
if (status != UMC_OK)
return status;
return status;
}
Status H261VideoDecoder::Init(BaseCodecParams *lpInit)
{
Status status = UMC_OK;
VideoDecoderParams *pParam = DynamicCast<VideoDecoderParams> (lpInit);
Close();
if (NULL == pParam)
return UMC_ERR_NULL_PTR;
// create default memory allocator
status = BaseCodec::Init(lpInit);
if (status != UMC_OK)
return status;
m_dec_time_base = -1.0;
m_Param = *pParam;
m_IsInit = false;
memset(m_decInfo, 0, sizeof(H261DEC_STATE));
m_decInfo->tr = 255;
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->buffer = reinterpret_cast<Ipp8u *> (pParam->m_pData->GetDataPointer());
status = InsideInit(&m_Param);
}
}
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->picture_width == 0 && m_decInfo->picture_height == 0)
return UMC_ERR_INIT;
else {
pParam->info.clip_info.width = m_Param.info.clip_info.width; // = m_decInfo->picture_width;
pParam->info.clip_info.height = m_Param.info.clip_info.height; // = m_decInfo->picture_height;
}
}
}
m_ClipInfo = m_Param.info;
m_IsInitBase = true;
return status;
}
Status H261VideoDecoder::InsideInit(VideoDecoderParams *pParam)
{
Status status = UMC_OK;
Ipp32s ret;
if ((ret = initDecoder(m_decInfo)) != 0) {
status = UMC_ERR_SYNC;
return status;
}
pParam->info.clip_info.width = m_decInfo->picture_width;
pParam->info.clip_info.height = m_decInfo->picture_height;
status = AllocateBuffers();
if (status != UMC_OK)
return status;
m_IsInit = true;
return status;
}
Status H261VideoDecoder::GetFrame(MediaData* in, MediaData* out)
{
Status status = UMC_OK;
Ipp64f pts;
Ipp32s ret;
if (!m_IsInitBase)
return UMC_ERR_NOT_INITIALIZED;
if (out == NULL)
return UMC_ERR_NULL_PTR;
if (in) {
m_decInfo->bufptr = m_decInfo->buffer = (Ipp8u*)in->GetDataPointer();
m_decInfo->buflen = in->GetDataSize();
// find bit-offset of start code (it can be not byte-aligned)
for (m_decInfo->bitoff = 0; m_decInfo->bitoff < 9; m_decInfo->bitoff++) {
Ipp32s sc = (m_decInfo->bufptr[0] << (m_decInfo->bitoff + 24)) +
(m_decInfo->bufptr[1] << (m_decInfo->bitoff + 16)) +
(m_decInfo->bufptr[2] << (m_decInfo->bitoff + 8)) +
(m_decInfo->bufptr[3] << (m_decInfo->bitoff));
if ((sc & 0xfffff000) == 0x00010000)
break;
}
if (m_decInfo->bitoff > 8)
return UMC_ERR_SYNC;
if (m_decInfo->bitoff == 8) {
m_decInfo->bufptr++;
m_decInfo->bitoff = 0;
}
}
if (!m_IsInit) {
if (in == NULL)
return UMC_ERR_NOT_ENOUGH_DATA;
m_Param.m_pData = in;
status = InsideInit(&m_Param);
if (status != UMC_OK) {
in->MoveDataPointer(in->GetDataSize() - m_decInfo->buflen);
return UMC_ERR_INIT;
}
}
LockBuffers();
for (;;) {
if (in == NULL) {
UnlockBuffers();
return UMC_ERR_NOT_ENOUGH_DATA;
} else {
if ((ret = getPictureHeader(m_decInfo)) != 0) {
status = UMC_ERR_SYNC;
break;
}
if (getPicture(m_decInfo) != 0) {
status = UMC_WRN_INVALID_STREAM;
}
}
break;
};
pts = -1.0;
if (in) {
if (in->GetTime() >= 0.0 && m_dec_time_base < 0.0) {
m_dec_time_base = in->GetTime();
m_decInfo->time = 0;
}
pts = in->GetTime();
}
if (pts < 0) {
pts = (Ipp64f)m_decInfo->time * (1001.0 / 30000.0);
if (m_dec_time_base >= 0.0)
pts += m_dec_time_base;
}
if (UMC_OK == status || UMC_WRN_INVALID_STREAM == status) {
Status pp_status;
if (m_LastDecodedFrame.GetColorFormat() != YUV420) {
m_LastDecodedFrame.Init(m_decInfo->picture_width,
m_decInfo->picture_height,
YUV420);
}
m_LastDecodedFrame.SetFrameType(m_decInfo->picType == 0 ? I_PICTURE : P_PICTURE);
m_LastDecodedFrame.SetTime(pts);
// m_LastDecodedFrame.SetPlanePointer(m_decInfo->refPic[0], 0);
// m_LastDecodedFrame.SetPlanePointer(m_decInfo->refPic[1], 1);
// m_LastDecodedFrame.SetPlanePointer(m_decInfo->refPic[2], 2);
m_LastDecodedFrame.SetPlanePointer(m_decInfo->curPic[0], 0);
m_LastDecodedFrame.SetPlanePointer(m_decInfo->curPic[1], 1);
m_LastDecodedFrame.SetPlanePointer(m_decInfo->curPic[2], 2);
m_LastDecodedFrame.SetPlanePitch(m_decInfo->picture_width, 0);
m_LastDecodedFrame.SetPlanePitch(m_decInfo->picture_width >> 1, 1);
m_LastDecodedFrame.SetPlanePitch(m_decInfo->picture_width >> 1, 2);
if (!m_PostProcessing) {
m_PostProcessing = m_allocatedPostProcessing = createVideoProcessing();
}
pp_status = m_PostProcessing->GetFrame(&m_LastDecodedFrame, out);
if (pp_status != UMC_OK)
status = pp_status;
}
if (in) {
size_t stDecidedData;
if ((size_t)m_decInfo->bufptr - (size_t)m_decInfo->buffer < (size_t)m_decInfo->buflen)
stDecidedData = m_decInfo->buflen - ((size_t)m_decInfo->bufptr - (size_t)m_decInfo->buffer);
else
stDecidedData = 0;
in->MoveDataPointer(in->GetDataSize() - static_cast<Ipp32u>(stDecidedData));
// can't calculate time for the next frame
in->SetTime(-1.0);
}
UnlockBuffers();
return status;
}
Status H261VideoDecoder::Close(void)
{
m_IsInitBase = false;
if (m_IsInit) {
FreeBuffers();
// close default memory allocator
BaseCodec::Close();
m_IsInit = false;
}
return UMC_OK;
}
H261VideoDecoder::H261VideoDecoder(void)
{
m_IsInit = m_IsInitBase = false;
m_decInfo = new H261DEC_STATE;
}
H261VideoDecoder::~H261VideoDecoder(void)
{
Close();
delete m_decInfo;
}
Status H261VideoDecoder::GetInfo(BaseCodecParams* info)
{
VideoDecoderParams *pParams;
if (!m_IsInitBase)
return UMC_ERR_NOT_INITIALIZED;
if (info == NULL)
return UMC_ERR_NULL_PTR;
pParams = DynamicCast<VideoDecoderParams> (info);
if (NULL != pParams) {
*pParams = m_Param;
} else {
if (!m_IsInit)
return UMC_ERR_NOT_INITIALIZED;
// info->profile = m_Param.profile;
// info->level = m_Param.level;
}
return UMC_OK;
}
Status H261VideoDecoder::ResetSkipCount()
{
return UMC_ERR_NOT_IMPLEMENTED;
}
Status H261VideoDecoder::SkipVideoFrame(Ipp32s /*count*/)
{
return UMC_ERR_NOT_IMPLEMENTED;
}
Ipp32u H261VideoDecoder::GetNumOfSkippedFrames(void)
{
return 0;
}
Status H261VideoDecoder::Reset(void)
{
if (!m_IsInitBase)
return UMC_ERR_NOT_INITIALIZED;
if (m_IsInit) {
m_dec_time_base = -1.0;
m_decInfo->tr = 255;
m_decInfo->time = 0;
}
return UMC_OK;
}
Status H261VideoDecoder::GetPerformance(Ipp64f * /*perf*/)
{
return UMC_ERR_NOT_IMPLEMENTED;
}
} // end namespace UMC
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -