📄 umc_vc1_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) 2004-2007 Intel Corporation. All Rights Reserved.
//
*/
#include "umc_defs.h"
#if defined (UMC_ENABLE_VC1_VIDEO_DECODER)
#include "umc_vc1_video_decoder.h"
#include "umc_video_data.h"
#include "vm_time.h"
#include "umc_media_data_ex.h"
#include "umc_vc1_dec_debug.h"
#include "umc_vc1_dec_seq.h"
#include "vm_sys_info.h"
#include "vm_thread.h"
#include "vm_types.h"
#include "umc_vc1_dec_task_store.h"
#include "umc_vc1_dec_task.h"
#include "umc_color_space_conversion.h"
#include "umc_memory_allocator.h"
#include "umc_vc1_dec_time_statistics.h"
#include "umc_vc1_common.h"
#include "umc_vc1_common_defs.h"
#include "assert.h"
#include "umc_vc1_dec_exception.h"
#include "ipps.h"
using namespace UMC;
using namespace UMC::VC1Common;
using namespace UMC::VC1Exceptions;
namespace UMC
{
VideoDecoder *CreateVC1Decoder() { return (new VC1VideoDecoder); }
}
VC1VideoDecoder::VC1VideoDecoder():m_pContext(NULL),
m_pdecoder(NULL),
m_iThreadDecoderNum(0),
m_dataBuffer(NULL),
m_frameData(NULL),
m_stCodes(NULL),
m_decoderInitFlag(0),
m_decoderFlags(0),
m_pNewMemID((MemID)(-1)),
m_pts(0),
m_pts_dif(0),
m_bIsWMPSplitter(false),
m_iMaxFramesInProcessing(0),
m_bIsFrameToOut(false),
m_iRefFramesDst(0),
m_iBFramesDst(0),
m_pPrevDescriptor(NULL),
m_lFrameCount(0),
m_bLastFrameNeedDisplay(false),
m_bIsWarningStream(false),
m_pSelfDecoder(NULL),
m_pStore(NULL),
m_va(NULL),
m_CurrentMode(Routine)
#ifdef CREATE_ES
,m_fPureVideo(NULL)
#endif
{
#ifdef VC1_THREAD_STATISTIC
m_parallelStat = NULL;
#endif
}
VC1VideoDecoder::~VC1VideoDecoder()
{
#ifdef VC1_THREAD_STATISTIC
if (m_parallelStat)
fclose(m_parallelStat);
#endif
Close();
}
Status VC1VideoDecoder::Init(BaseCodecParams *pInit)
{
MediaData *data;
Status umcRes = UMC_OK;
Ipp32u i;
Ipp32u frameSize;
Ipp32u readSize = 0;
m_pSelfDecoder = this;
Close();
VideoDecoderParams *init = DynamicCast<VideoDecoderParams, BaseCodecParams>(pInit);
if(!init)
return UMC_ERR_INIT;
assert(init->info.stream_subtype != 0);
m_decoderFlags = init->lFlags;
data = init->m_pData;
m_ClipInfo = init->info;
if (WMV_VIDEO == init->info.stream_type)
m_bIsWMPSplitter = true;
m_PostProcessing = init->pPostProcessing;
//MEMORY ALLOCATION
{
//common context for all Frame Descriptors
m_pContext = (VC1Context*)ippsMalloc_8u(sizeof(VC1Context));
if(!m_pContext)
{
Close();
return UMC_ERR_ALLOC;
}
memset(m_pContext, 0, sizeof(VC1Context));
m_pContext->m_seqLayerHeader = (VC1SequenceLayerHeader*)ippsMalloc_8u(sizeof(VC1SequenceLayerHeader));
if(!m_pContext->m_seqLayerHeader)
{
Close();
return UMC_ERR_ALLOC;
}
memset(m_pContext->m_seqLayerHeader, 0, sizeof(VC1SequenceLayerHeader));
////VLCTables
m_pContext->m_vlcTbl = (VC1VLCTables*)ippsMalloc_8u(sizeof(VC1VLCTables));
if(!m_pContext->m_vlcTbl)
{
Close();
return UMC_ERR_ALLOC;
}
memset(m_pContext->m_vlcTbl, 0, sizeof(VC1VLCTables));
}
m_pContext->m_bIntensityCompensation = 0;
if(data!=NULL && (Ipp32s*)data->GetDataPointer() != NULL)
{
if(!((m_decoderFlags & FLAG_VDEC_4BYTE_ACCESS) == FLAG_VDEC_4BYTE_ACCESS))
{
//need to create buffer for swap data
CreateFrameBuffer();
m_pContext->m_FrameSize = (Ipp32u)data->GetDataSize();
if(init->info.stream_subtype == VC1_VIDEO_VC1)
{
umcRes = GetStartCodes(data, m_frameData, &readSize);
m_pContext->m_FrameSize = m_frameData->GetDataSize();
}
else
{
if(data->GetDataSize()<= m_frameData->GetBufferSize())
ippsCopy_8u((Ipp8u*)data->GetBufferPointer(), m_dataBuffer, (Ipp32u)data->GetDataSize());
else
{
while(data->GetDataSize() > m_frameData->GetBufferSize())
ResizeBuffer();
ippsCopy_8u((Ipp8u*)data->GetBufferPointer(), m_dataBuffer, (Ipp32u)data->GetDataSize());
}
readSize = m_pContext->m_FrameSize;
}
m_pContext->m_pBufferStart = (Ipp8u*)m_dataBuffer;
m_pContext->m_bitstream.pBitstream = (Ipp32u*)(m_pContext->m_pBufferStart);
//swap data
SwapData((Ipp8u*)m_frameData->GetBufferPointer(),
(Ipp32u)m_frameData->GetDataSize());
}
else
{
m_pContext->m_bitstream.pBitstream = (Ipp32u*)data->GetDataPointer();
m_pContext->m_pBufferStart = (Ipp8u*)data->GetBufferPointer();
m_pContext->m_FrameSize = (Ipp32u)data->GetDataSize();
}
m_pContext->m_bitstream.bitOffset = 31;
frameSize = DecodeBegin(m_pContext, init->info.stream_subtype);
if ( (WMV_VIDEO == init->info.stream_type)&&
(WMV3_VIDEO == init->info.stream_subtype) )
{
Ipp32u height;
Ipp32u width;
m_pContext->m_seqLayerHeader->MAX_CODED_HEIGHT = init->info.clip_info.height/2 - 1;
m_pContext->m_seqLayerHeader->MAX_CODED_WIDTH = init->info.clip_info.width/2 - 1;
m_pContext->m_seqLayerHeader->widthMB
= (Ipp16u)((init->info.clip_info.width+15)/VC1_PIXEL_IN_LUMA);
m_pContext->m_seqLayerHeader->heightMB
= (Ipp16u)((init->info.clip_info.height+15)/VC1_PIXEL_IN_LUMA);
height = m_pContext->m_seqLayerHeader->heightMB*VC1_PIXEL_IN_LUMA;
width = ((m_pContext->m_seqLayerHeader->widthMB * VC1_PIXEL_IN_LUMA) & 0xFFFFFF80)+ 0x080;
frameSize = (height + 128)*(width + 128)
+ ((height / 2 + 64)*(width / 2 + 64))*2;
}
// extract pure video from wmv
#ifdef CREATE_ES
if (!m_fPureVideo)
{
m_fPureVideo = fopen("output_es.es","wb");
if (!m_fPureVideo)
return UMC_ERR_ALLOC;
Ipp32u begin = 0x0000000F;
fwrite(&begin, 1, 3, m_fPureVideo);
begin = 0xC5;
fwrite(&begin, 1, 1, m_fPureVideo);
begin = 0x0000004;
fwrite(&begin, 1, 4, m_fPureVideo);
Ipp32u seqHead = *m_pContext->m_pBufferStart;
SwapData((Ipp8u*)(m_pContext->m_pBufferStart),4);
fwrite(m_pContext->m_pBufferStart, 1, 4, m_fPureVideo);
Ipp32u picSize[2] = {(m_pContext->m_seqLayerHeader->MAX_CODED_HEIGHT+1)*2, (m_pContext->m_seqLayerHeader->MAX_CODED_WIDTH+1)*2};
fwrite(picSize, 1, 8, m_fPureVideo);
begin = 0x0000000C;
fwrite(&begin, 1, 4, m_fPureVideo);
fwrite(&begin, 1, 12, m_fPureVideo);
}
#endif
if(frameSize == 0)
{
Close();
return UMC_ERR_SYNC;
}
GetFPS();
GetPTS(data->GetTime());
data->MoveDataPointer(readSize);
m_decoderInitFlag = 1;
}
else
{
//NULL input data, no sequence header
Ipp32u width = 0;
Ipp32u height = 0;
if(init->info.stream_subtype == VC1_VIDEO_VC1)
m_pContext->m_seqLayerHeader->PROFILE = VC1_PROFILE_ADVANCED;
else
m_pContext->m_seqLayerHeader->PROFILE = VC1_PROFILE_MAIN;
m_pContext->m_seqLayerHeader->MAX_CODED_HEIGHT = init->info.clip_info.height/2 - 1;
m_pContext->m_seqLayerHeader->MAX_CODED_WIDTH = init->info.clip_info.width/2 - 1;
m_pContext->m_seqLayerHeader->widthMB
= (Ipp16u)((init->info.clip_info.width+15)/VC1_PIXEL_IN_LUMA);
m_pContext->m_seqLayerHeader->heightMB
= (Ipp16u)((init->info.clip_info.height+15)/VC1_PIXEL_IN_LUMA);
if(init->info.interlace_type)
m_pContext->m_seqLayerHeader->INTERLACE = 1;
height = m_pContext->m_seqLayerHeader->heightMB*VC1_PIXEL_IN_LUMA;
width = ((m_pContext->m_seqLayerHeader->widthMB * VC1_PIXEL_IN_LUMA) & 0xFFFFFF80)+ 0x080;
frameSize = (height + 128)*(width + 128) + ((height / 2 + 64)*(width / 2 + 64))*2;
if(!((m_decoderFlags & FLAG_VDEC_4BYTE_ACCESS) == FLAG_VDEC_4BYTE_ACCESS))
{
//need to create buffer for swap data
CreateFrameBuffer();
}
}
//MEMORY ALLOCATOR
if (UMC_OK != BaseCodec::Init(pInit) )
{
Close();
return UMC_ERR_INIT;
}
// get allowed thread numbers
Ipp32s nAllowedThreadNumber = init->numThreads;
printf("nAllowedThreadNumber = %d\n",nAllowedThreadNumber);
#if defined (_WIN32) && (_DEBUG)
#ifdef VC1_DEBUG_ON
VM_Debug::GetInstance(VC1DebugAlloc);
#endif
#endif
#ifdef THREADS
nAllowedThreadNumber = THREADS_NUM;
#endif
if(nAllowedThreadNumber < 0) nAllowedThreadNumber = 0;
else
if(nAllowedThreadNumber > 8) nAllowedThreadNumber = 8;
//nAllowedThreadNumber = 1;
m_iThreadDecoderNum = (0 == nAllowedThreadNumber) ? (vm_sys_info_get_cpu_num()) : (nAllowedThreadNumber);
umcRes = InitVAEnvironment(frameSize);
if (umcRes != UMC_OK)
return umcRes;
if (!m_pSelfDecoder->InitAlloc(m_pContext,m_iMaxFramesInProcessing))
return UMC_ERR_ALLOC;
if(!((m_decoderFlags & FLAG_VDEC_4BYTE_ACCESS) == FLAG_VDEC_4BYTE_ACCESS))
{
ResizeBuffer();
}
try
// memory allocation and Init all env for frames/tasks store - VC1TaskStore object
{
m_pStore = new VC1TaskStore(m_pMemoryAllocator);
if (!m_pStore->Init(m_iThreadDecoderNum,
m_iMaxFramesInProcessing,
this) )
return UMC_ERR_ALLOC;
m_pStore->CreateDSQueue(m_pContext);
m_pStore->CreateOutBuffersQueue();
m_pStore->SetDefinition(m_pContext->m_seqLayerHeader);
}
catch(...)
{
// only allocation here
return UMC_ERR_ALLOC;
}
// create thread decoders for multithreading support
{
m_pdecoder = new VC1ThreadDecoder *[m_iThreadDecoderNum];
if (NULL == m_pdecoder)
return UMC_ERR_ALLOC;
memset(m_pdecoder, 0, sizeof(VC1ThreadDecoder*) * m_iThreadDecoderNum);
printf("ThreadNum = %d\n",m_iThreadDecoderNum);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -