📄 umc_dv100_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) 2006-2007 Intel Corporation. All Rights Reserved.
//
*/
#include <ippi.h>
#include <ipps.h>
#include <ippvc.h>
#include "umc_dv100_decoder.h"
#include "umc_video_data.h"
#include "umc_dv_internal.h"
#include "vm_event.h"
#include "vm_thread.h"
#include "vm_sys_info.h"
#include "umc_dv_decoder.h"
#include "umc_memory_allocator.h"
#ifdef _OPENMP
#include "omp.h"
#endif
namespace UMC
{
DV100VideoDecoder::DV100VideoDecoder(void) :
m_pHuffTable(NULL),
m_ppDecodedDCTBlocks(NULL),
m_pDestination(NULL),
m_System(SystemUnknown),
m_pInternalFrameBuffer(NULL),
m_pThreads(NULL),
m_pStartEvents(NULL),
m_pStopEvents(NULL),
m_pThreadsID(NULL),
m_DCTBlocksBufferMID(0),
m_InternalFrameBufferMID(0),
m_nSystem720_LastDecodedChannel(0),
m_bInitSuccess(false)
{
vm_event_set_invalid(&m_Quit);
}
DV100VideoDecoder::~DV100VideoDecoder(void)
{
}
static const Ipp32s DV100_VideoSegmentSize = 64 * 8 * 5 * sizeof(Ipp16s);
// Initialize DV decoder
Status DV100VideoDecoder::Init(BaseCodecParams *lpInit)
{
Ipp32s ThreadNum;
VideoDecoderParams *pParams = DynamicCast<VideoDecoderParams> (lpInit);
if (NULL == pParams)
return UMC_ERR_NULL_PTR;
Close();
// Initializes external memory allocator
if (UMC_OK != BaseCodec::Init(lpInit))
return UMC_ERR_INIT;
if(pParams->numThreads == 0)
{
#ifdef _OPENMP
m_nNumberOfThreads = omp_get_max_threads();
#else //_OPENMP
m_nNumberOfThreads = vm_sys_info_get_cpu_num();
#endif //_OPENMP
}
else
m_nNumberOfThreads = pParams->numThreads;
if (0 >= m_nNumberOfThreads)
m_nNumberOfThreads = 1;
else if (8 < m_nNumberOfThreads)
m_nNumberOfThreads = 8;
//Alloc internal buffers for DCT blocks
if( m_pMemoryAllocator->Alloc(&m_DCTBlocksBufferMID,
DV100_VideoSegmentSize * m_nNumberOfThreads,
UMC_ALLOC_PERSISTENT,
16) != UMC_OK )
return UMC_ERR_ALLOC;
m_ppDecodedDCTBlocks = new Ipp16s* [m_nNumberOfThreads];
if (NULL == m_ppDecodedDCTBlocks)
return UMC_ERR_ALLOC;
// create threading tools
if (1 < m_nNumberOfThreads)
{
// create quit event
if (VM_OK != vm_event_init(&m_Quit, 1, 0))
return UMC_ERR_INIT;
// create start event(s)
m_pStartEvents = new vm_event[m_nNumberOfThreads];
if (NULL == m_pStartEvents)
return UMC_ERR_ALLOC;
for (ThreadNum = 1;ThreadNum < m_nNumberOfThreads;ThreadNum += 1)
{
vm_event_set_invalid(m_pStartEvents + ThreadNum);
if (VM_OK != vm_event_init(m_pStartEvents + ThreadNum, 0, 0))
return UMC_ERR_INIT;
}
// create stop event(s)
m_pStopEvents = new vm_event[m_nNumberOfThreads];
if (NULL == m_pStopEvents)
return UMC_ERR_ALLOC;
for (ThreadNum = 1;ThreadNum < m_nNumberOfThreads;ThreadNum += 1)
{
vm_event_set_invalid(m_pStopEvents + ThreadNum);
if (VM_OK != vm_event_init(m_pStopEvents + ThreadNum, 0, 0))
return UMC_ERR_INIT;
}
// allocate thread ID(s)
m_pThreadsID = new THREAD_ID[m_nNumberOfThreads];
if (NULL == m_pThreadsID)
return UMC_ERR_ALLOC;
// starting thread(s)
m_pThreads = new vm_thread[m_nNumberOfThreads];
if (NULL == m_pThreads)
return UMC_ERR_ALLOC;
for (ThreadNum = 1;ThreadNum < m_nNumberOfThreads;ThreadNum += 1)
{
vm_thread_set_invalid(m_pThreads + ThreadNum);
m_pThreadsID[ThreadNum].m_nNumber = ThreadNum;
m_pThreadsID[ThreadNum].m_lpOwner = this;
if (0 == vm_thread_create(m_pThreads + ThreadNum, ThreadWorkingRoutine, m_pThreadsID + ThreadNum))
return UMC_ERR_INIT;
}
}
m_nHeight = pParams->info.clip_info.height;
m_nWidth = pParams->info.clip_info.width;
// check parameters
if ( !((SYSTEM_1080_WIDTH == m_nWidth && SYSTEM_1080_HEIGHT == m_nHeight) ||
(SYSTEM_720_WIDTH == m_nWidth && SYSTEM_720_HEIGHT == m_nHeight) ||
(960 == m_nWidth && SYSTEM_720_HEIGHT == m_nHeight) ||
(1280 == m_nWidth && SYSTEM_1080_HEIGHT == m_nHeight) ||
(1400 == m_nWidth && SYSTEM_1080_HEIGHT == m_nHeight) ))
{
return UMC_ERR_INVALID_STREAM;
}
m_ClipInfo = pParams->info;
//Codec always alloc maximal internal buffer 1920*1080*2 = 4147200 byte
//Internal color format is YUY2
m_nDestPitch = align_value<Ipp32s> (2 * 1920, WIDTH_ALIGN);
if( m_pMemoryAllocator->Alloc(&m_InternalFrameBufferMID,
m_nDestPitch * m_nHeight,
UMC_ALLOC_PERSISTENT,
16) != UMC_OK )
return UMC_ERR_ALLOC;
m_PostProcessing = pParams->pPostProcessing;
if (ippStsOk != ippiInitAllocHuffmanTable_DV_32u(DVVideoDecoder::dvTable1, DVVideoDecoder::dvTable2, &m_pHuffTable))
return UMC_ERR_ALLOC;
m_bInitSuccess = true;
return UMC_OK;
}
// Close decoder
Status DV100VideoDecoder::Close()
{
Ipp32s ThreadNum;
// let all threads exit
if (m_pThreads)
{
vm_event_signal(&m_Quit);
for (ThreadNum = 1;ThreadNum < m_nNumberOfThreads;ThreadNum += 1)
vm_event_signal(m_pStartEvents + ThreadNum);
for (ThreadNum = 1;ThreadNum < m_nNumberOfThreads;ThreadNum += 1)
{
if (vm_thread_is_valid(m_pThreads + ThreadNum))
vm_thread_wait(m_pThreads + ThreadNum);
}
}
// delete all threading tools
if (vm_event_is_valid(&m_Quit))
{
vm_event_destroy(&m_Quit);
vm_event_set_invalid(&m_Quit);
}
if (m_pThreads)
{
for (ThreadNum = 1;ThreadNum < m_nNumberOfThreads;ThreadNum += 1)
vm_thread_set_invalid(m_pThreads + ThreadNum);
delete [] m_pThreads;
m_pThreads = NULL;
}
if (m_pStartEvents)
{
for (ThreadNum = 1;ThreadNum < m_nNumberOfThreads;ThreadNum += 1)
{
if (vm_event_is_valid(m_pStartEvents + ThreadNum))
{
vm_event_destroy(m_pStartEvents + ThreadNum);
vm_event_set_invalid(m_pStartEvents + ThreadNum);
}
}
delete [] m_pStartEvents;
m_pStartEvents = NULL;
}
if (m_pStopEvents)
{
for (ThreadNum = 1;ThreadNum < m_nNumberOfThreads;ThreadNum += 1)
{
if (vm_event_is_valid(m_pStopEvents + ThreadNum))
{
vm_event_destroy(m_pStopEvents + ThreadNum);
vm_event_set_invalid(m_pStopEvents + ThreadNum);
}
}
delete [] m_pStopEvents;
m_pStopEvents = NULL;
}
if (m_pThreadsID)
{
delete [] m_pThreadsID;
m_pThreadsID = NULL;
}
if(m_pHuffTable != NULL)
ippiFreeHuffmanTable_DV_32u(m_pHuffTable);
m_pHuffTable = NULL;
if(m_ppDecodedDCTBlocks != NULL)
delete[] m_ppDecodedDCTBlocks;
m_ppDecodedDCTBlocks = NULL;
if( m_pMemoryAllocator )
{
if(m_DCTBlocksBufferMID != 0)
{
m_pMemoryAllocator->Free(m_DCTBlocksBufferMID);
m_DCTBlocksBufferMID= 0;
}
if(m_InternalFrameBufferMID != 0)
{
m_pMemoryAllocator->Free(m_InternalFrameBufferMID);
m_InternalFrameBufferMID = 0;
}
}
// delete memory allocator if internal
BaseCodec::Close();
m_System = SystemUnknown;
return UMC_OK;
}
//Distinguish 1080/60i and 1080/50i systems
Status DV100VideoDecoder::GetSystemSubtype()
{
Ipp8u vaux_framerate = 0;
Ipp8u vaux_system = 0;
Ipp8u byte_PC0_of_VAUX = 0;
Ipp8u byte_PC3_of_VAUX = 0;
//VAUX section 3, offfset from start of a DIF sequence 3*80 = 240 byte
//Length of each section is 80 byte
//Offset to VAUX source pack is 3 + 5*9 = 48 byte
byte_PC0_of_VAUX = (Ipp8u) m_pStreamStart[240 + 48 + 0 + 2*80];
byte_PC3_of_VAUX = (Ipp8u) m_pStreamStart[240 + 48 + 3 + 2*80];
//check VAUX section
if (0x60 != byte_PC0_of_VAUX)
return UMC_ERR_INVALID_STREAM;
else
{
vaux_framerate = (byte_PC3_of_VAUX>>5) &0x1;
vaux_system = byte_PC3_of_VAUX &0x1f;
if ((0 == vaux_framerate) &&( (0x14 == vaux_system) || (0x15 == vaux_system)) )
{
m_System = System1080_60i;
m_nWidth = SYSTEM_1080_60I_WIDTH_NOT_STRETCHED;
m_nHeight = SYSTEM_1080_HEIGHT;
}
if ((0 == vaux_framerate) && (0x18 == vaux_system) )
{
m_System = System720_60p;
m_nWidth = SYSTEM_720_WIDTH_NOT_STRETCHED;
m_nHeight = SYSTEM_720_HEIGHT;
}
if ((1 == vaux_framerate) && (0x14 == vaux_system) )
{
m_System = System1080_50i;
m_nWidth = SYSTEM_1080_50I_WIDTH_NOT_STRETCHED;
m_nHeight = SYSTEM_1080_HEIGHT;
}
if ((1 == vaux_framerate) && (0x18 == vaux_system) )
{
m_System = System720_50p;
m_nWidth = SYSTEM_720_WIDTH_NOT_STRETCHED;
m_nHeight = SYSTEM_720_HEIGHT;
}
}
m_ClipInfo.clip_info.width = m_nWidth;
m_ClipInfo.clip_info.height = m_nHeight;
return UMC_OK;
}
const size_t DIFSequenceLength = 150 * 80; //150 DIF blocks by 80 bytes
// Decode next frame
Status DV100VideoDecoder::GetFrame(MediaData *pInData, MediaData *pOutData)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -