📄 umc_h264_deblocking_tools.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-2007 Intel Corporation. All Rights Reserved.
//
//
*/
#include "umc_h264_deblocking_tools.h"
#include "umc_h264_video_encoder.h"
#include "umc_h264_core_enc.h"
using namespace UMC;
namespace UMC_H264_ENCODER
{
template <class PixType, class CoeffsType>
void H264EncoderThreadedDeblockingTools<PixType, CoeffsType> ::Release(void)
{
// terminate second thread(s)
if (vm_thread_is_valid(&m_hDeblockingSliceSecondThread))
{
m_bQuit = true;
vm_event_signal(&m_hBeginRow);
vm_thread_wait(&m_hDeblockingSliceSecondThread);
vm_thread_close(&m_hDeblockingSliceSecondThread);
}
if (vm_thread_is_valid(&m_hDeblockingSliceAsyncSecondThread))
{
m_bQuit = true;
vm_event_signal(&m_hBeginSlice);
vm_thread_wait(&m_hDeblockingSliceAsyncSecondThread);
vm_thread_close(&m_hDeblockingSliceAsyncSecondThread);
}
// destroy objects
if (vm_event_is_valid(&m_hBeginFrame))
vm_event_destroy(&m_hBeginFrame);
if (vm_event_is_valid(&m_hBeginSlice))
vm_event_destroy(&m_hBeginSlice);
if (vm_event_is_valid(&m_hBeginRow))
vm_event_destroy(&m_hBeginRow);
if (vm_event_is_valid(&m_hDoneBorder))
vm_event_destroy(&m_hDoneBorder);
if (vm_event_is_valid(&m_hDoneRow))
vm_event_destroy(&m_hDoneRow);
if (vm_event_is_valid(&m_hDoneSlice))
vm_event_destroy(&m_hDoneSlice);
vm_thread_set_invalid(&m_hDeblockingSliceSecondThread);
vm_thread_set_invalid(&m_hDeblockingSliceAsyncSecondThread);
vm_event_set_invalid(&m_hBeginFrame);
vm_event_set_invalid(&m_hBeginSlice);
vm_event_set_invalid(&m_hBeginRow);
vm_event_set_invalid(&m_hDoneBorder);
vm_event_set_invalid(&m_hDoneRow);
vm_event_set_invalid(&m_hDoneSlice);
m_bQuit = false;
} // void H264EncoderThreadedDeblockingTools<PixType, CoeffsType> ::Release(void)
template <class PixType, class CoeffsType>
Status H264EncoderThreadedDeblockingTools<PixType, CoeffsType> ::Initialize(H264CoreEncoder<PixType, CoeffsType> *pDecoder)
{
vm_status res;
// release object before initialization
Release();
// save pointer
m_pDecoder = pDecoder;
// create objects
res = vm_event_init(&m_hBeginFrame, 0, 0);
if (VM_OK != res)
return UMC_ERR_INIT;
res = vm_event_init(&m_hBeginSlice, 0, 0);
if (VM_OK != res)
return UMC_ERR_INIT;
res = vm_event_init(&m_hBeginRow, 0, 0);
if (VM_OK != res)
return UMC_ERR_INIT;
res = vm_event_init(&m_hDoneBorder, 0, 0);
if (VM_OK != res)
return UMC_ERR_INIT;
res = vm_event_init(&m_hDoneRow, 0, 0);
if (VM_OK != res)
return UMC_ERR_INIT;
res = vm_event_init(&m_hDoneSlice, 0, 1);
if (VM_OK != res)
return UMC_ERR_INIT;
// run second thread(s)
{
Ipp32s res;
res = vm_thread_create(&m_hDeblockingSliceSecondThread, DeblockSliceSecondThread, this);
if (0 == res)
return UMC_ERR_INIT;
res = vm_thread_create(&m_hDeblockingSliceAsyncSecondThread, DeblockSliceAsyncSecondThread, this);
if (0 == res)
return UMC_ERR_INIT;
}
return UMC_OK;
} // Status H264EncoderThreadedDeblockingTools<PixType, CoeffsType> ::Initialize(H264CoreEncoder *pDecoder)
template <class PixType, class CoeffsType>
H264EncoderThreadedDeblockingTools<PixType, CoeffsType> ::H264EncoderThreadedDeblockingTools (void)
{
vm_thread_set_invalid(&m_hDeblockingSliceSecondThread);
vm_thread_set_invalid(&m_hDeblockingSliceAsyncSecondThread);
vm_event_set_invalid(&m_hBeginFrame);
vm_event_set_invalid(&m_hBeginSlice);
vm_event_set_invalid(&m_hBeginRow);
vm_event_set_invalid(&m_hDoneBorder);
vm_event_set_invalid(&m_hDoneRow);
vm_event_set_invalid(&m_hDoneSlice);
m_bQuit = false;
} // H264EncoderThreadedDeblockingTools<PixType, CoeffsType> ::H264EncoderThreadedDeblockingTools<PixType, CoeffsType> (void)
template <class PixType, class CoeffsType>
H264EncoderThreadedDeblockingTools<PixType, CoeffsType> ::~H264EncoderThreadedDeblockingTools(void)
{
Release();
} // H264EncoderThreadedDeblockingTools<PixType, CoeffsType> ::~H264EncoderThreadedDeblockingTools<PixType, CoeffsType> (void)
template <class PixType, class CoeffsType>
void H264EncoderThreadedDeblockingTools<PixType, CoeffsType> ::DeblockSliceTwoThreaded(Ipp32u uFirstMB, Ipp32u unumMBs, typename H264CoreEncoder<PixType,CoeffsType>::DeblockingFunction pDeblocking)
{
Ipp32u mb_width = m_pDecoder->m_WidthInMBs << m_nMBAFF;
Ipp32u nBorder = (mb_width / 2) & (~m_nMBAFF);
Ipp32u i, nCurrMB, nMaxMB;
// reset border signal to avoid complex logic
vm_event_reset(&m_hDoneBorder);
// set maximum MB number
nMaxMB = uFirstMB + unumMBs;
// deblock blocks in first row before border
nCurrMB = uFirstMB;
for (i = uFirstMB % mb_width;(i < nBorder) && (nCurrMB < nMaxMB);i += 1, nCurrMB += 1)
(m_pDecoder->*(pDeblocking))(nCurrMB);
if (nCurrMB < nMaxMB)
{
// fill thread interaction parameters
m_nFirstMB = nCurrMB;
m_nNumMB = nMaxMB - nCurrMB;
m_pDeblocking = pDeblocking;
// send signal to second thread
vm_event_signal(&m_hBeginRow);
// align macroblock number to new line
nCurrMB += mb_width - nCurrMB % mb_width;
while (nCurrMB < nMaxMB)
{
// deblock row up to border macroblock(s)
for (i = 0;(i < (nBorder - 1 - m_nMBAFF)) && (nCurrMB < nMaxMB);i += 1, nCurrMB += 1)
(m_pDecoder->*(pDeblocking))(nCurrMB);
// wait response from second thread
vm_event_wait(&m_hDoneBorder);
if (nCurrMB < nMaxMB)
{
// deblock border macroblock(s)
for (;(i < (nBorder)) && (nCurrMB < nMaxMB);i += 1, nCurrMB += 1)
(m_pDecoder->*(pDeblocking))(nCurrMB);
// send signal to second thread
if (nCurrMB < nMaxMB)
vm_event_signal(&m_hBeginRow);
nCurrMB += mb_width - nBorder;
}
}
// wait for second thread
vm_event_wait(&m_hDoneRow);
}
// set event of slice is done
vm_event_signal(&m_hDoneSlice);
} // void H264EncoderThreadedDeblockingTools<PixType, CoeffsType> ::DeblockSliceTwoThreaded(Ipp32u uFirstMB, Ipp32u unumMBs, H264CoreEncoder::DeblockingFunction pDeblocking)
template <class PixType, class CoeffsType>
void H264EncoderThreadedDeblockingTools<PixType, CoeffsType> ::DeblockSliceAsync(Ipp32u uFirstMB, Ipp32u unumMBs, typename H264CoreEncoder<PixType, CoeffsType>::DeblockingFunction pDeblocking)
{
// fill thread interaction parameters
m_nFirstMB = uFirstMB;
m_nNumMB = unumMBs;
m_pDeblocking = pDeblocking;
vm_event_signal(&m_hBeginSlice);
} // void H264EncoderThreadedDeblockingTools<PixType, CoeffsType> ::DeblockSliceAsync(Ipp32u uFirstMB, Ipp32u unumMBs, H264CoreEncoder::DeblockingFunction pDeblocking)
template <class PixType, class CoeffsType>
void H264EncoderThreadedDeblockingTools<PixType, CoeffsType> ::WaitEndOfSlice(void)
{
vm_event_wait(&m_hDoneSlice);
} // void H264EncoderThreadedDeblockingTools<PixType, CoeffsType> ::WaitEndOfSlice(void)
template <class PixType, class CoeffsType>
Ipp32u VM_THREAD_CALLCONVENTION H264EncoderThreadedDeblockingTools<PixType, CoeffsType> ::DeblockSliceSecondThread(void *p)
{
H264EncoderThreadedDeblockingTools<PixType, CoeffsType> *pTools = (H264EncoderThreadedDeblockingTools<PixType, CoeffsType> *) p;
H264CoreEncoder<PixType, CoeffsType> *pDec;
// check error(s)
VM_ASSERT(pTools);
if (NULL == pTools)
return 0x0bad;
pDec = pTools->m_pDecoder;
{
vm_event *phBeginRow = &(pTools->m_hBeginRow);
vm_event *phDoneRow = &(pTools->m_hDoneRow);
vm_event *phDoneBorder = &(pTools->m_hDoneBorder);
// wait response from main thread
vm_event_wait(phBeginRow);
// is it exit ?
while (false == pTools->m_bQuit)
{
Ipp32u i, nCurrMB;
Ipp32u nMaxMB = pTools->m_nFirstMB + pTools->m_nNumMB;
typename H264CoreEncoder<PixType, CoeffsType>::DeblockingFunction pDeblocking = pTools->m_pDeblocking;
Ipp32u mb_width = pDec->m_WidthInMBs << pTools->m_nMBAFF;
Ipp32u nBorder = (mb_width / 2) & (~(pTools->m_nMBAFF));
nCurrMB = pTools->m_nFirstMB;
while (nCurrMB < nMaxMB)
{
// wait response from main thread
if (nCurrMB != pTools->m_nFirstMB)
vm_event_wait(phBeginRow);
// deblock border macroblock(s)
if (nCurrMB % mb_width == nBorder)
{
for (i = 0;i < (1 + pTools->m_nMBAFF);i += 1, nCurrMB += 1)
(pDec->*(pDeblocking))(nCurrMB);
i = nBorder + 1 + pTools->m_nMBAFF;
}
else
i = nCurrMB % mb_width;
// send signal to main thread, even border macroblock wasn't processed
vm_event_signal(phDoneBorder);
// deblock all macroblock up to end of row
for (;(i < mb_width) && (nCurrMB < nMaxMB);i += 1, nCurrMB += 1)
(pDec->*(pDeblocking))(nCurrMB);
nCurrMB += nBorder;
}
// send signal to main thread
vm_event_signal(phDoneRow);
// wait response from main thread
vm_event_wait(phBeginRow);
}
}
return 1;
} // Ipp32u VM_THREAD_CALLCONVENTION H264EncoderThreadedDeblockingTools<PixType, CoeffsType> ::DeblockSliceSecondThread(void *p)
template <class PixType, class CoeffsType>
Ipp32u H264EncoderThreadedDeblockingTools<PixType, CoeffsType> ::DeblockSliceAsyncSecondThread(void *p)
{
H264EncoderThreadedDeblockingTools<PixType, CoeffsType> *pTools = (H264EncoderThreadedDeblockingTools<PixType, CoeffsType> *) p;
H264CoreEncoder<PixType, CoeffsType> *pDec;
// check error(s)
VM_ASSERT(pTools);
if (NULL == pTools)
return 0x0bad;
pDec = pTools->m_pDecoder;
{
vm_event *phBeginSlice = &(pTools->m_hBeginSlice);
vm_event *phDoneSlice = &(pTools->m_hDoneSlice);
// wait response from main thread
vm_event_wait(phBeginSlice);
// is it exit ?
while (false == pTools->m_bQuit)
{
Ipp32u i;
typename H264CoreEncoder<PixType, CoeffsType>::DeblockingFunction pDeblocking = pTools->m_pDeblocking;
Ipp32u nFirstMB = pTools->m_nFirstMB;
Ipp32u nNumMB = pTools->m_nNumMB;
// deblock macroblocks
for (i = nFirstMB; i < nFirstMB + nNumMB; i++)
(pDec->*(pDeblocking))(i);
// send signal to main thread
vm_event_signal(phDoneSlice);
// wait response from main thread
vm_event_wait(phBeginSlice);
}
}
return 1;
} // Ipp32u H264EncoderThreadedDeblockingTools<PixType, CoeffsType> ::DeblockSliceAsyncSecondThread(void *p)
template class H264EncoderThreadedDeblockingTools<Ipp8u, Ipp16s>;
#if defined BITDEPTH_9_12
template class H264EncoderThreadedDeblockingTools<Ipp16u, Ipp32s>;
#endif // BITDEPTH_9_12
} // namespace UMC_H264_ENCODER
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -