📄 umc_mpeg2_dec.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-2005 Intel Corporation. All Rights Reserved.//*/#include "umc_mpeg2_dec_base.h"#include "umc_mpeg2_dec.h"#include "umc_mpeg2_dec_tbl.h"#include "umc_media_data_ex.h"#include "umc_video_data.h"#include "vm_sys_info.h"#include "vm_time.h"using namespace UMC;bool MPEG2VideoDecoderBase::InitColorConverter(BaseCodecParams *pInit){ VideoDecoderParams *init = DynamicCast<VideoDecoderParams, BaseCodecParams>(pInit); if(!init) return false; memset(&m_Convert, 0, sizeof(ColorConversionParams)); memset(&m_ConvertPreview, 0, sizeof(ColorConversionParams)); m_lpConverter = NULL; m_maxThreads = 1; m_decodedFrameNum = 0; m_lpConverter = init->lpConverter; if(init->lpConvertInit) { // initialize convertion param(s) m_Convert.ConversionInit = *(init->lpConvertInit); init->lFlags &= ~FLAG_VDEC_UVMERGED; m_Convert.ConversionInit.FormatSource = YUV420; // if second picture desired if (NULL != init->lpConvertInitPreview) { m_bTwoPictures = true; m_ConvertPreview.ConversionInit = *(init->lpConvertInitPreview); m_ConvertPreview.ConversionInit.FormatSource = YUV420; } else { m_bTwoPictures = false; } } return true;}static IppStatus mp2_HuffmanTableInitAlloc(Ipp32s *tbl, int bits_table0, mp2_VLCTable *vlc){ Ipp32s *ptbl; Ipp16s bad_value = 0; int max_bits; int num_tbl; int i, j, k, m, n; int bits, code, value; int bits0, bits1; int min_value, max_value, spec_value; int min_code0, min_code1; int max_code0, max_code1; int prefix_code1 = -1; int bits_table1 = 0; int *buffer = NULL; int *codes; int *cbits; int *values; Ipp16s *table0 = NULL; Ipp16s *table1 = NULL; /* get number of entries (n) */ max_bits = *tbl++; num_tbl = *tbl++; for (i = 0; i < num_tbl; i++) { *tbl++; } n = 0; ptbl = tbl; for (bits = 1; bits <= max_bits; bits++) { m = *ptbl; if (m < 0) break; n += m; ptbl += 2*m + 1; } /* alloc internal table */ buffer = new int[3*n]; if (!buffer) return ippStsErr; codes = buffer; cbits = buffer + n; values = buffer + 2*n; /* read VLC to internal table */ min_value = 0x7fffffff; max_value = 0; spec_value = 0; ptbl = tbl; k = 0; for (bits = 1; bits <= max_bits; bits++) { if (*ptbl < 0) break; m = *ptbl++; for (i = 0; i < m; i++) { code = *ptbl++; value = *ptbl++; code &= ((1 << bits) - 1); if (value < min_value) min_value = value; if (value > max_value) { if (!spec_value && value >= 0xffff) { spec_value = value; } else { max_value = value; } } codes[k] = code << (30 - bits); cbits[k] = bits; values[k] = value; k++; } } if (!bits_table0) { bits_table0 = max_bits; bits_table1 = 0; vlc->threshold_table0 = 0; } bits0 = bits_table0; if (bits0 > 0 && bits0 < max_bits) { min_code0 = min_code1 = 0x7fffffff; max_code0 = max_code1 = 0; for (i = 0; i < n; i++) { code = codes[i]; bits = cbits[i]; if (bits <= bits0) { if (code > max_code0) max_code0 = code; if (code < min_code0) min_code0 = code; } else { if (code > max_code1) max_code1 = code; if (code < min_code1) min_code1 = code; } } if ((max_code0 < min_code1) || (max_code1 < min_code0)) { for (j = 0; j < 29; j++) { if ((min_code1 ^ max_code1) & (1 << (29 - j))) break; } bits1 = max_bits - j; if (bits0 == bits_table0) { bits_table1 = bits1; prefix_code1 = min_code1 >> (30 - bits0); vlc->threshold_table0 = min_code0 >> (30 - max_bits); } } } if (bits_table0 > 0 && bits_table0 < max_bits && !bits_table1) { if (buffer) delete[] buffer; return ippStsErr; } bad_value = (bad_value << 8) | VLC_BAD; table0 = ippsMalloc_16s(1 << bits_table0); ippsSet_16s(bad_value, table0, 1 << bits_table0); if (bits_table1) { table1 = ippsMalloc_16s(1 << bits_table1); ippsSet_16s(bad_value, table1, 1 << bits_table1); } for (i = 0; i < n; i++) { code = codes[i]; bits = cbits[i]; value = values[i]; if (bits <= bits_table0) { code = code >> (30 - bits_table0); for (j = 0; j < (1 << (bits_table0 - bits)); j++) { table0[code + j] = (Ipp16s)((value << 8) | bits); } } else { code = code >> (30 - max_bits); code = code & ((1 << bits_table1) - 1); for (j = 0; j < (1 << (max_bits - bits)); j++) { table1[code + j] = (Ipp16s)((value << 8) | bits); } } } if (bits_table1) { // fill VLC_NEXTTABLE if (prefix_code1 == -1) { if (buffer) delete[] buffer; return ippStsErr; } bad_value = (bad_value &~ 255) | VLC_NEXTTABLE; for (j = 0; j < (1 << ((bits_table0 - (max_bits - bits_table1)))); j++) { table0[prefix_code1 + j] = bad_value; } } vlc->max_bits = max_bits; vlc->bits_table0 = bits_table0; vlc->bits_table1 = bits_table1; vlc->table0 = table0; vlc->table1 = table1; if (buffer) delete[] buffer; return ippStsNoErr;}static void mp2_HuffmanTableFree(mp2_VLCTable *vlc) { if (vlc->table0) { ippsFree(vlc->table0); vlc->table0 = NULL; } if (vlc->table1) { ippsFree(vlc->table1); vlc->table1 = NULL; }}bool MPEG2VideoDecoderBase::InitTables(){ if (ippStsNoErr != mp2_HuffmanTableInitAlloc(MBAdressing, 5, &vlcMBAdressing)) return false; if (ippStsNoErr != mp2_HuffmanTableInitAlloc(IMBType, 0, &vlcMBType[0])) return false; if (ippStsNoErr != mp2_HuffmanTableInitAlloc(PMBType, 0, &vlcMBType[1])) return false; if (ippStsNoErr != mp2_HuffmanTableInitAlloc(BMBType, 0, &vlcMBType[2])) return false; if (ippStsNoErr != mp2_HuffmanTableInitAlloc(MBPattern, 5, &vlcMBPattern)) return false; if (ippStsNoErr != mp2_HuffmanTableInitAlloc(MotionVector, 5, &vlcMotionVector)) return false; if (ippStsNoErr != mp2_HuffmanTableInitAlloc(dct_dc_size_luma, 5, &vlcDctDcSizeLuma)) return false; if (ippStsNoErr != mp2_HuffmanTableInitAlloc(dct_dc_size_chroma, 5, &vlcDctDcSizeChroma)) return false; memset(&vlcTables, 0, sizeof(vlcTables)); if (ippStsNoErr != ippiHuffmanTableInitAlloc_32s(dct_dc_size_luma, &vlcTables.ippTableB5a)) return false; if (ippStsNoErr != ippiHuffmanTableInitAlloc_32s(dct_dc_size_chroma, &vlcTables.ippTableB5b)) return false; return true;}bool MPEG2VideoDecoderBase::DeleteTables(){ // release tools if(Video) {#ifdef KEEP_HISTORY if(Video[0].frame_buffer.frame_p_c_n[0].frame_history) { ippsFree(Video[0].frame_buffer.frame_p_c_n[0].frame_history); Video[0].frame_buffer.frame_p_c_n[0].frame_history = NULL; } if(Video[0].frame_buffer.frame_p_c_n[1].frame_history) { ippsFree(Video[0].frame_buffer.frame_p_c_n[1].frame_history); Video[0].frame_buffer.frame_p_c_n[1].frame_history = NULL; } if(Video[0].frame_buffer.frame_p_c_n[2].frame_history) { ippsFree(Video[0].frame_buffer.frame_p_c_n[2].frame_history); Video[0].frame_buffer.frame_p_c_n[2].frame_history = NULL; }#endif for(int i = 0; i < m_nNumberOfAllocatedThreads; i++) { if(Video[i].block.idct) { ippsFree((void*)Video[i].block.idct); Video[i].block.idct = NULL; } if(Video[i].block.dq) { ippsFree((void*)Video[i].block.dq); Video[i].block.dq = NULL; } } ippsFree(Video); Video = NULL; } if(sequenceHeader.ptr_context_data) { ippsFree(sequenceHeader.ptr_context_data); sequenceHeader.ptr_context_data = NULL; } // release tables mp2_HuffmanTableFree(&vlcMBAdressing); mp2_HuffmanTableFree(&vlcMBType[0]); mp2_HuffmanTableFree(&vlcMBType[1]); mp2_HuffmanTableFree(&vlcMBType[2]); mp2_HuffmanTableFree(&vlcMBPattern); mp2_HuffmanTableFree(&vlcMotionVector); mp2_HuffmanTableFree(&vlcDctDcSizeLuma); mp2_HuffmanTableFree(&vlcDctDcSizeChroma); if(vlcTables.ippTableB5a) { ippiHuffmanTableFree_32s(vlcTables.ippTableB5a); vlcTables.ippTableB5a = NULL; } if(vlcTables.ippTableB5b) { ippiHuffmanTableFree_32s(vlcTables.ippTableB5b); vlcTables.ippTableB5b = NULL; } return UMC_OK;}unsigned int MPEG2VideoDecoderBase::ThreadWorkingRoutine(void *lpv){ THREAD_ID * lpThreadId; MPEG2VideoDecoderBase * lpOwner; // check error(s) if (NULL == lpv) return 0xbaadf00d; lpThreadId = reinterpret_cast<THREAD_ID *> (lpv); lpOwner = reinterpret_cast<MPEG2VideoDecoderBase *> (lpThreadId->m_lpOwner); // wait for start vm_event_wait(lpOwner->m_lpStartEvent + lpThreadId->m_nNumber); while (VM_TIMEOUT == vm_event_timed_wait(&(lpOwner->m_lpQuit[lpThreadId->m_nNumber]), 0)) { lpOwner->DecodeSlices(lpThreadId->m_nNumber); // set finish vm_event_signal(lpOwner->m_lpStopEvent + lpThreadId->m_nNumber); // wait for start vm_event_wait(lpOwner->m_lpStartEvent + lpThreadId->m_nNumber); } return lpThreadId->m_nNumber;}Status MPEG2VideoDecoderBase::ThreadingSetup(){ int i; Video = (IppVideoContext*)ippsMalloc_8u(m_nNumberOfThreads*sizeof(IppVideoContext)); if(!Video) return UMC_ALLOC; memset(Video, 0, m_nNumberOfThreads*sizeof(IppVideoContext)); for(i = 0; i < m_nNumberOfThreads; i++) { Video[i].block.idct = ippsMalloc_16s(128*12); if(!Video[i].block.idct) return UMC_ALLOC; Video[i].block.dq = ippsMalloc_16s(128); if(!Video[i].block.dq) return UMC_ALLOC; } // create threading tools if (1 < m_nNumberOfThreads) { // create exit event(s) m_lpQuit = new vm_event[m_nNumberOfThreads]; if (NULL == m_lpQuit) return UMC_FAILED_TO_ALLOCATE_BUFFER; for (i = 1; i < m_nNumberOfThreads; i++) { vm_event_set_invalid(m_lpQuit + i); if (VM_OK != vm_event_init(m_lpQuit + i, 0, 0)) return UMC_FAILED_TO_INITIALIZE; } // create start event(s) m_lpStartEvent = new vm_event[m_nNumberOfThreads]; if (NULL == m_lpStartEvent) return UMC_FAILED_TO_ALLOCATE_BUFFER; for (i = 1; i < m_nNumberOfThreads; i++) { vm_event_set_invalid(m_lpStartEvent + i); if (VM_OK != vm_event_init(m_lpStartEvent + i, 0, 0)) return UMC_FAILED_TO_INITIALIZE; } // create stop event(s) m_lpStopEvent = new vm_event[m_nNumberOfThreads]; if (NULL == m_lpStopEvent) return UMC_FAILED_TO_ALLOCATE_BUFFER; for (i = 1;i < m_nNumberOfThreads;i += 1) { vm_event_set_invalid(m_lpStopEvent + i); if (VM_OK != vm_event_init(m_lpStopEvent + i, 0, 0)) return UMC_FAILED_TO_INITIALIZE; } // allocate thread ID(s) m_lpThreadsID = new THREAD_ID[m_nNumberOfThreads]; if (NULL == m_lpThreadsID) return UMC_FAILED_TO_ALLOCATE_BUFFER; // starting thread(s) m_lpThreads = new vm_thread[m_nNumberOfThreads]; if (NULL == m_lpThreads) return UMC_FAILED_TO_ALLOCATE_BUFFER; for (i = 1;i < m_nNumberOfThreads;i += 1) { vm_thread_set_invalid(m_lpThreads + i); m_lpThreadsID[i].m_nNumber = i; m_lpThreadsID[i].m_lpOwner = this; if (0 == vm_thread_create(m_lpThreads + i, ThreadWorkingRoutine, m_lpThreadsID + i)) return UMC_FAILED_TO_INITIALIZE; } } m_nNumberOfAllocatedThreads = m_nNumberOfThreads; return UMC_OK;}Status MPEG2VideoDecoderBase::Init(BaseCodecParams *pInit){ MediaData *data; if((m_lFlags & FLAG_VSPL_4BYTE_ACCESS) != 0) return UMC_UNSUPPORTED; decodeIntraSpec = (IppiDecodeIntraSpec_MPEG2*)(intraBuff + ((16 - (int)intraBuff) & 15)); decodeInterSpec = (IppiDecodeInterSpec_MPEG2*)(interBuff + ((16 - (int)interBuff) & 15)); ippiDecodeInterInit_MPEG2(NULL, IPPVC_MPEG1_STREAM, decodeInterSpec); decodeIntraSpec->intraVLCFormat = PictureHeader.intra_vlc_format = 0; decodeIntraSpec->intraShiftDC = PictureHeader.curr_intra_dc_multi = intra_dc_multi[0]; VideoDecoderParams *init = DynamicCast<VideoDecoderParams, BaseCodecParams>(pInit); if(!init) return UMC_FAILED_TO_INITIALIZE; m_pConverter = init->lpConverter; if (false == InitColorConverter(init)) return UMC_FAILED_TO_INITIALIZE; if (false == InitTables()) return UMC_FAILED_TO_INITIALIZE; data = init->m_pData; m_bNoBframes = false; m_bNoPframes = false; m_ccCurrData.SetBufferPointer(NULL, 0); m_pCCData = new SampleBuffer; if(m_pCCData) { Status res = UMC_OK; MediaBufferParams initPar; initPar.m_prefInputBufferSize = initPar.m_prefOutputBufferSize = 1024; initPar.m_numberOfFrames = 20; res = m_pCCData->Init(&initPar); if(res != UMC_OK) { m_pCCData->Close(); delete m_pCCData; m_pCCData = NULL; } } m_ClipInfo = init->info; if(!init->lpConvertInit) ulResized = 1; else switch(init->lpConvertInit->lFlags) { case FLAG_CCNV_NONE: case FLAG_CCNV_CONVERT: ulResized = 1; break; case FLAG_CCNV_RESIZE_2S: ulResized = 2; break; case FLAG_CCNV_RESIZE_4S: ulResized = 4; break; case FLAG_CCNV_RESIZE_8S: ulResized = 8; break; case FLAG_CCNV_RESIZE_CUSTOM: default: ulResized = 0; break; } m_lFlags = init->lFlags; if(init->uiLimitThreads == 0) m_nNumberOfThreads = vm_sys_info_get_cpu_num(); else m_nNumberOfThreads = init->uiLimitThreads; if (0 >= m_nNumberOfThreads) m_nNumberOfThreads = 1; else if (8 < m_nNumberOfThreads) m_nNumberOfThreads = 8; if(UMC_OK != ThreadingSetup()) return UMC_ALLOC; sequenceHeader.frame_rate_extension_d = 0; sequenceHeader.frame_rate_extension_n = 0; if(data) { sequenceHeader.first_i_occure = 0; sequenceHeader.first_p_occure = 0; sequenceHeader.continues_pts = 1; sequenceHeader.stream_type = UNDEF_VIDEO; sequenceHeader.broken_link = 0; sequenceHeader.closed_gop = 0; sequenceHeader.gop_picture = 0; sequenceHeader.gop_second = 0; m_decodedFrameNum = 0; PrepareBuffer(data); if(UMC_OK > DecodeBegin(data->GetTime(), &init->info)) { return UMC_NULL_PTR; } FlushBuffer(data, false); m_ClipInfo.clip_info.width = sequenceHeader.horizontal_size; m_ClipInfo.clip_info.height = sequenceHeader.vertical_size; m_ClipInfo.framerate = 1.0 / sequenceHeader.delta_frame_time; return UMC_OK; } else return UMC_NULL_PTR;}Status MPEG2VideoDecoderBase::FlushBuffer(MediaData* data, bool threaded){ if((m_lFlags & FLAG_VDEC_COMPATIBLE)) { IppVideoContext *video = &Video[0]; // it decodes tail of frame Ipp8u* plast = GET_BYTE_PTR(video->bs); Ipp8u* pend = GET_END_PTR(video->bs); Ipp8u* plasta = plast - ((int)plast & 3); if (plasta > pend) { plasta = pend; } return data->MoveDataPointer(plasta - (Ipp8u*)data->GetDataPointer()); } /* else if not m_lFlags & FLAG_VDEC_COMPATIBLE */ Status umcRes = UMC_OK; unsigned int code; int stDataLeft = 0; IppVideoContext* video = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -