⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 umc_h264_segment_decoder_mt.cpp

📁 audio-video-codecs.rar语音编解码器
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/*
//
//              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_defs.h"
#if defined (UMC_ENABLE_H264_VIDEO_DECODER)

#include "umc_h264_segment_decoder_mt.h"
#include "vm_event.h"
#include "vm_semaphore.h"
#include "vm_thread.h"
#include "umc_h264_bitstream_inlines.h"
#include "umc_h264_segment_decoder_templates.h"

#include "umc_h264_task_broker.h"
#include "umc_h264_frame_info.h"

#include "umc_h264_task_supplier.h"
#include "umc_h264_frame_list.h"

#include "umc_h264_timing.h"

namespace UMC
{
static
#ifdef __ICL
    __declspec(align(16))
#endif
const Ipp8u BlkOrder[16] =
{
    0, 1, 4, 5, 2, 3, 6, 7, 8, 9, 12, 13, 10, 11, 14, 15
};

H264SegmentDecoderMultiThreaded::H264SegmentDecoderMultiThreaded(TaskBroker * pTaskBroker)
    : H264SegmentDecoder(pTaskBroker)
{
    InitializeSDCreator();
} // H264SegmentDecoderMultiThreaded::H264SegmentDecoderMultiThreaded(H264SliceStore *Store)

H264SegmentDecoderMultiThreaded::~H264SegmentDecoderMultiThreaded(void)
{
    Release();

} // H264SegmentDecoderMultiThreaded::~H264SegmentDecoderMultiThreaded(void)

Status H264SegmentDecoderMultiThreaded::Init(Ipp32s iNumber)
{
    // release object before initialization
    Release();

    // call parent's Init
    return H264SegmentDecoder::Init(iNumber);
} // Status H264SegmentDecoderMultiThreaded::Init(Ipp32u nNumber)

void H264SegmentDecoderMultiThreaded::StartProcessingSegment(H264Task &Task)
{
    switch (Task.m_iTaskID)
    {
    case TASK_DEB_FRAME:
                // reset decoding variables
        m_pSlice = NULL;
        m_pCurrentFrame = Task.m_pSlice->GetCurrentFrame();
        m_pSliceHeader = NULL;
        m_field_index = Task.m_pSlice->GetSliceHeader()->bottom_field_flag;
        break;
    default:
        {
            m_pSlice = Task.m_pSlice;
            m_pCurrentFrame = m_pSlice->GetCurrentFrame();
            m_pSliceHeader = m_pSlice->GetSliceHeader();
            m_field_index = m_pSliceHeader->bottom_field_flag;

            // reset decoding variables
            m_pBitStream = m_pSlice->GetBitStream();
            mb_height = m_pSlice->GetMBHeight();
            mb_width = m_pSlice->GetMBWidth();
            m_pPicParamSet = m_pSlice->GetPicParam();
            m_pPredWeight[0] = m_pSlice->GetPredWeigthTable(0);
            m_pPredWeight[1] = m_pSlice->GetPredWeigthTable(1);
            m_pSeqParamSet = m_pSlice->GetSeqParam();
            m_pCoeffBlocksWrite = m_psBuffer = Task.m_pBuffer;
            m_pMBIntraTypes = m_pSlice->GetMBIntraTypes();

            m_bNeedToCheckMBSliceEdges = m_pSlice->NeedToCheckSliceEdges();
            m_mbinfo = m_pSlice->GetMBInfo();

            bit_depth_luma = m_pCurrentFrame->IsAuxiliaryFrame() ? m_pSlice->GetSeqParamEx()->bit_depth_aux :
                                                    m_pSeqParamSet->bit_depth_luma;
            bit_depth_chroma = m_pCurrentFrame->IsAuxiliaryFrame() ? 8 : m_pSeqParamSet->bit_depth_chroma;

            m_SD = CreateSegmentDecoder();

            m_MVDistortion[0] = 0;
            m_MVDistortion[1] = 0;
        }
        break;
    }

    m_gmbinfo = &(m_pCurrentFrame->m_mbinfo);

    if (TASK_PROCESS != Task.m_iTaskID && TASK_DEC != Task.m_iTaskID
        && TASK_REC != Task.m_iTaskID && TASK_DEC_REC != Task.m_iTaskID)
        return;

    //  DEBUG : ADB - should initialize context only for reconstruction or decoding tasks
    // InitContext
    bool is_field = m_pCurrentFrame->m_PictureStructureForDec < FRM_STRUCTURE;
    m_isMBAFF = 0 != m_pSliceHeader->MbaffFrameFlag;

    m_IsUseSpatialDirectMode = (m_pSliceHeader->direct_spatial_mv_pred_flag != 0);

    //static ReferenceFlags pFields_stub = {0};
    Ipp32s sliceNum = m_pSlice->GetSliceNum();
    m_pFields[0] = m_pCurrentFrame->GetRefPicList(sliceNum, 0)->m_Flags;
    m_pFields[1] = m_pCurrentFrame->GetRefPicList(sliceNum, 1)->m_Flags;
    m_pRefPicList[0] = m_pCurrentFrame->GetRefPicList(sliceNum, 0)->m_RefPicList;
    m_pRefPicList[1] = m_pCurrentFrame->GetRefPicList(sliceNum, 1)->m_RefPicList;

    if (TASK_PROCESS == Task.m_iTaskID || TASK_DEC == Task.m_iTaskID || TASK_DEC_REC == Task.m_iTaskID)
        m_pSlice->GetStateVariables(m_MBSkipCount, m_QuantPrev, m_prev_dquant);

    m_IsUseConstrainedIntra = (m_pPicParamSet->constrained_intra_pred_flag != 0);
    m_IsUseDirect8x8Inference = (m_pSeqParamSet->direct_8x8_inference_flag != 0);
    m_IsBSlice = (m_pSliceHeader->slice_type == BPREDSLICE);

    m_uPitchLuma = m_pCurrentFrame->pitch_luma();
    m_uPitchChroma = m_pCurrentFrame->pitch_chroma();

    m_pYPlane = m_pCurrentFrame->m_pYPlane;
    m_pUPlane = m_pCurrentFrame->m_pUPlane;
    m_pVPlane = m_pCurrentFrame->m_pVPlane;

    if (is_field)
    {
        if(m_field_index)
        {
            Ipp32s pixel_luma_sz    = bit_depth_luma > 8 ? 2 : 1;
            Ipp32s pixel_chroma_sz  = bit_depth_chroma > 8 ? 2 : 1;

            m_pYPlane += m_uPitchLuma*pixel_luma_sz;
            m_pUPlane += m_uPitchChroma*pixel_chroma_sz;
            m_pVPlane += m_uPitchChroma*pixel_chroma_sz;
        }

        m_uPitchLuma *= 2;
        m_uPitchChroma *= 2;
    }

    // reset neighbouringing blocks numbers
    m_cur_mb.CurrentBlockNeighbours.m_bInited = 0;
}

void H264SegmentDecoderMultiThreaded::EndProcessingSegment(H264Task &Task)
{
    // return performed task
    Task.m_WrittenSize = (Ipp8u*)m_pCoeffBlocksWrite - (Ipp8u*)Task.m_pBuffer;
    if (Task.m_bError)
    {
        Task.m_WrittenSize += COEFFICIENTS_BUFFER_SIZE;
    }

    if (TASK_DEC == Task.m_iTaskID)
    {
        m_MVDistortion[0] = (m_MVDistortion[0] + 6) >> INTERP_SHIFT;
        m_MVDistortion[1] = (m_MVDistortion[1] + 6) >> INTERP_SHIFT;

        if (m_pSlice->IsField() || m_pSlice->GetSliceHeader()->MbaffFrameFlag)
        {
            m_MVDistortion[0] <<= 1;
            m_MVDistortion[1] <<= 1;
        }

        m_MVDistortion[0] = IPP_MAX(m_MVDistortion[0], m_MVDistortion[1]);
        m_pTaskBroker->Lock();
        m_pSlice->m_MVsDistortion = IPP_MAX(m_MVDistortion[0], m_pSlice->m_MVsDistortion);
        m_pTaskBroker->Unlock();
    }

    m_pTaskBroker->AddPerformedTask(&Task);
}

Status H264SegmentDecoderMultiThreaded::ProcessSegment(void)
{
    H264Task Task(m_iNumber);

    while (m_pTaskBroker->GetNextTask(&Task))
    {
        Status umcRes = UMC_OK;

        VM_ASSERT(Task.pFunction);

        StartProcessingSegment(Task);

        if (!m_pCurrentFrame->IsSkipped() && (!m_pSlice || !m_pSlice->IsError()))
        {
            try // do decoding
            {
                Ipp32s firstMB = Task.m_iFirstMB;
                if (m_field_index)
                {
                    firstMB += mb_width*mb_height / 2;
                }

                umcRes = (this->*(Task.pFunction))(firstMB, Task.m_iMBToProcess);

                if (UMC_ERR_END_OF_STREAM == umcRes)
                {
                    Task.m_iMaxMB = Task.m_iFirstMB + Task.m_iMBToProcess;
                    VM_ASSERT(m_pSlice);
                    // if we decode less macroblocks if we need try to recovery:
                    RestoreErrorRect(Task.m_iFirstMB + Task.m_iMBToProcess, m_pSlice->GetMaxMB(), m_pSlice);
                    umcRes = UMC_OK;
                }
                else if (UMC_OK != umcRes)
                {
                    umcRes = UMC_ERR_INVALID_STREAM;
                }

                Task.m_bDone = true;

            } catch(const h264_exception & ex)
            {
                umcRes = ex.GetStatus();
            } catch(...)
            {
                umcRes = UMC_ERR_INVALID_STREAM;
            }
        }

        if (umcRes != UMC_OK)
        {
            Task.m_bError = true;
            Task.m_iMaxMB = Task.m_iFirstMB + Task.m_iMBToProcess;
            if (m_pSlice)
                RestoreErrorRect(Task.m_iFirstMB + Task.m_iMBToProcess, m_pSlice->GetMaxMB(), m_pSlice);
            // break; // DEBUG : ADB should we return if error occur??
        }

        EndProcessingSegment(Task);
    }

    return UMC_OK;

} // Status H264SegmentDecoderMultiThreaded::ProcessSegment(void)

void H264SegmentDecoderMultiThreaded::RestoreErrorRect(Ipp32s startMb, Ipp32s endMb, H264Slice * pSlice)
{
    m_pSlice = pSlice;

    if (startMb >= endMb || !m_pSlice || m_pSlice->IsSliceGroups())
        return;

    try
    {
        H264DecoderFrame * pCurrentFrame = m_pSlice->GetCurrentFrame();

        if (!pCurrentFrame)
        {
            VM_ASSERT(false);
            return;
        }

        H264DecoderFrame * pRefFrame = pCurrentFrame->GetRefPicList(m_pSlice->GetSliceNum(), 0)->m_RefPicList[0];

        pCurrentFrame->SetFrameExistFlag(false);
        pCurrentFrame->SetError(1);

        if (!pRefFrame || pRefFrame->IsSkipped())
        {
            pRefFrame = m_pTaskBroker->m_pTaskSupplier->GetDPBList()->FindClosest(pCurrentFrame);
        }

        m_SD->RestoreErrorRect(startMb, endMb, pRefFrame, this);
    } catch (...)
    {
        // nothing to do
    }
}

Status H264SegmentDecoderMultiThreaded::DecodeSegment(Ipp32s iCurMBNumber, Ipp32s &iMBToDecode)
{
    Status umcRes;
    Ipp32u iBorder = iCurMBNumber + iMBToDecode;

    START_TICK
    if (m_pPicParamSet->entropy_coding_mode)
    {
        umcRes = DecodeMacroBlockCABAC(iCurMBNumber, iBorder);
    }
    else
    {
        umcRes = DecodeMacroBlockCAVLC(iCurMBNumber, iBorder);
    }
    END_TICK(decode_time)

    if (UMC_ERR_END_OF_STREAM == umcRes)
        iMBToDecode = iBorder - iCurMBNumber;

    return umcRes;

} // Status H264SegmentDecoderMultiThreaded::DecodeSegment(Ipp32s iCurMBNumber, Ipp32s &iMBToDecode)

Status H264SegmentDecoderMultiThreaded::ReconstructSegment(Ipp32s iCurMBNumber, Ipp32s &iMaxMBToReconstruct)
{
    Status umcRes;
    Ipp32s iBorder = iCurMBNumber + iMaxMBToReconstruct;

    START_TICK
    if (m_pPicParamSet->entropy_coding_mode)
    {
        umcRes = ReconstructMacroBlockCABAC(iCurMBNumber, iBorder);
    }
    else
    {
        umcRes = ReconstructMacroBlockCAVLC(iCurMBNumber, iBorder);
    }
    END_TICK(reconstruction_time)

    return umcRes;

} // Status H264SegmentDecoderMultiThreaded::ReconstructSegment(Ipp32s iCurMBNumber, Ipp32s &iMBToReconstruct)

Status H264SegmentDecoderMultiThreaded::DecRecSegment(Ipp32s iCurMBNumber, Ipp32s &iMaxMBToDecRec)
{
    Status umcRes;
    //Ipp32s iBorder = iCurMBNumber + iMaxMBToDecRec;

    m_psBuffer = align_pointer<UMC::CoeffsPtrCommon> (m_pCoefficientsBuffer, DEFAULT_ALIGN_VALUE);

    if (0 == m_pPicParamSet->entropy_coding_mode)
    {
        umcRes = m_SD->DecodeSegmentCAVLC_Single(&iCurMBNumber, iMaxMBToDecRec, this);
    }
    else
    {
        umcRes = m_SD->DecodeSegmentCABAC_Single(&iCurMBNumber, iMaxMBToDecRec, this);
    }

    return umcRes;

} // Status H264SegmentDecoderMultiThreaded::DecRecSegment(Ipp32s iCurMBNumber, Ipp32s &iMBToReconstruct)

Status H264SegmentDecoderMultiThreaded::DeblockSegmentTask(Ipp32s iCurMBNumber, Ipp32s &iMBToDeblock)
{
    START_TICK
    // when there is slice groups or threaded deblocking
    if (NULL == m_pSlice)
        H264SegmentDecoder::DeblockFrame(iCurMBNumber, iMBToDeblock);
    else
        H264SegmentDecoder::DeblockSegment(iCurMBNumber, iMBToDeblock);

    END_TICK(deblocking_time)

    return UMC_OK;

} // Status H264SegmentDecoderMultiThreaded::DeblockSegmentTask(Ipp32s iCurMBNumber, Ipp32s &iMBToDeblock)

void H264SegmentDecoderMultiThreaded::DecodeMotionVectors_CABAC(void)
{
    Ipp32s curmb_fdf = pGetMBFieldDecodingFlag(m_cur_mb.GlobalMacroblockInfo);
    // initialize blocks coding pattern maps

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -