bool H264Slice::DecodeSliceHeader(bool bFullInitialization)
{
    Status umcRes = UMC_OK;
    // Locals for additional slice data to be read into, the data
    // was read and saved from the first slice header of the picture,
    // is not supposed to change within the picture, so can be
    // discarded when read again here.
    bool bIsIDRPic = false;
    NAL_Unit_Type NALUType;
    Ipp8u nal_ref_idc;
    Ipp32s iSQUANT;

    try
    {
        memset(&m_SliceHeader, 0, sizeof(m_SliceHeader));

        umcRes = m_BitStream.GetNALUnitType(NALUType, nal_ref_idc);
        if (UMC_OK != umcRes)
            return false;

        if ((NALUType != NAL_UT_SLICE) && (NALUType != NAL_UT_IDR_SLICE) &&
            (NALUType != NAL_UT_AUXILIARY))
        {
            VM_ASSERT((NALUType == NAL_UT_SLICE) || (NALUType == NAL_UT_IDR_SLICE) || (NALUType == NAL_UT_AUXILIARY));
            return false;
        }

        m_SliceHeader.nal_unit_type = NALUType;
        bIsIDRPic = (NALUType == NAL_UT_IDR_SLICE);

        if (NALUType == NAL_UT_AUXILIARY)
        {
            if (!m_pCurrentFrame || !GetSeqParamEx())
                return false;

            bIsIDRPic = m_pCurrentFrame->m_bIDRFlag;
            NALUType = bIsIDRPic ? NAL_UT_IDR_SLICE : NAL_UT_SLICE;
            m_SliceHeader.nal_unit_type = NALUType;
            m_SliceHeader.is_auxiliary = true;
        }

        // decode first part of slice header
        umcRes = m_BitStream.GetSliceHeaderPart1(&m_SliceHeader);
        if (UMC_OK != umcRes)
            return false;

        m_CurrentPicParamSet = m_SliceHeader.pic_parameter_set_id;
        m_CurrentSeqParamSet = m_pPicParamSet->seq_parameter_set_id;

        // decode second part of slice header
        umcRes = m_BitStream.GetSliceHeaderPart2(&m_SliceHeader,
                                                 m_pPicParamSet,
                                                 bIsIDRPic,
                                                 m_pSeqParamSet,
                                                 nal_ref_idc);
        if (UMC_OK != umcRes)
            return false;

        // when we require only slice header
        if (false == bFullInitialization)
            return true;

        // decode second part of slice header
        umcRes = m_BitStream.GetSliceHeaderPart3(&m_SliceHeader,
                                                 m_PredWeight[0],
                                                 m_PredWeight[1],
                                                 &ReorderInfoL0,
                                                 &ReorderInfoL1,
                                                 &m_AdaptiveMarkingInfo,
                                                 m_pPicParamSet,
                                                 m_pSeqParamSet,
                                                 nal_ref_idc);
        if (UMC_OK != umcRes)
            return false;

        m_iMBWidth = m_pSeqParamSet->frame_width_in_mbs;
        m_iMBHeight = m_pSeqParamSet->frame_height_in_mbs;

        if (m_bPermanentTurnOffDeblocking)
            m_SliceHeader.disable_deblocking_filter_idc = DEBLOCK_FILTER_OFF;

        // redundant slice, discard
        if (m_SliceHeader.redundant_pic_cnt)
            return false;

        // Set next MB.
        if (m_SliceHeader.first_mb_in_slice >= (Ipp32s) (m_iMBWidth * m_iMBHeight))
        {
            return false;
        }

        Ipp32s bit_depth_luma = m_SliceHeader.is_auxiliary ?
            GetSeqParamEx()->bit_depth_aux : GetSeqParam()->bit_depth_luma;

        iSQUANT = m_pPicParamSet->pic_init_qp +
                  m_SliceHeader.slice_qp_delta;
        if (iSQUANT < QP_MIN - 6*(bit_depth_luma - 8)
            || iSQUANT > QP_MAX)
        {
            return false;
        }

        if (m_pPicParamSet->entropy_coding_mode)
            m_BitStream.AlignPointerRight();
    }
    catch(const h264_exception &)
    {
        return false;
    }
    catch(...)
    {
        return false;
    }

    return (UMC_OK == umcRes);

} // bool H264Slice::DecodeSliceHeader(bool bFullInitialization)
Ejemplo n.º 2
0
bool H264Slice::DecodeSliceHeader(H264NalExtension *pNalExt)
{
    Status umcRes = UMC_OK;
    // Locals for additional slice data to be read into, the data
    // was read and saved from the first slice header of the picture,
    // is not supposed to change within the picture, so can be
    // discarded when read again here.
    int32_t iSQUANT;

    try
    {
        memset(&m_SliceHeader, 0, sizeof(m_SliceHeader));

        umcRes = m_BitStream.GetNALUnitType(m_SliceHeader.nal_unit_type,
                                            m_SliceHeader.nal_ref_idc);
        if (UMC_OK != umcRes)
            return false;

        if (pNalExt && (NAL_UT_CODED_SLICE_EXTENSION != m_SliceHeader.nal_unit_type))
        {
            if (pNalExt->extension_present)
                m_SliceHeader.nal_ext = *pNalExt;
            pNalExt->extension_present = 0;
        }

        // adjust slice type for auxilary slice
        if (NAL_UT_AUXILIARY == m_SliceHeader.nal_unit_type)
        {
            if (!m_pCurrentFrame || !GetSeqParamEx())
                return false;

            m_SliceHeader.nal_unit_type = m_pCurrentFrame->m_bIDRFlag ?
                                          NAL_UT_IDR_SLICE :
                                          NAL_UT_SLICE;
            m_SliceHeader.is_auxiliary = true;
        }

        // decode first part of slice header
        umcRes = m_BitStream.GetSliceHeaderPart1(&m_SliceHeader);
        if (UMC_OK != umcRes)
            return false;


        // decode second part of slice header
        umcRes = m_BitStream.GetSliceHeaderPart2(&m_SliceHeader,
                                                 m_pPicParamSet,
                                                 m_pSeqParamSet);
        if (UMC_OK != umcRes)
            return false;

        // decode second part of slice header
        umcRes = m_BitStream.GetSliceHeaderPart3(&m_SliceHeader,
                                                 m_PredWeight[0],
                                                 m_PredWeight[1],
                                                 &ReorderInfoL0,
                                                 &ReorderInfoL1,
                                                 &m_AdaptiveMarkingInfo,
                                                 &m_BaseAdaptiveMarkingInfo,
                                                 m_pPicParamSet,
                                                 m_pSeqParamSet,
                                                 m_pSeqParamSetSvcEx);
        if (UMC_OK != umcRes)
            return false;

        //7.4.3 Slice header semantics
        //If the current picture is an IDR picture, frame_num shall be equal to 0
        //If this restrictions is violated, clear LT flag to avoid ref. pic. marking process corruption
        if (m_SliceHeader.IdrPicFlag && m_SliceHeader.frame_num != 0)
            m_SliceHeader.long_term_reference_flag = 0;

        // decode 4 part of slice header
        umcRes = m_BitStream.GetSliceHeaderPart4(&m_SliceHeader, m_pSeqParamSetSvcEx);
        if (UMC_OK != umcRes)
            return false;

        m_iMBWidth = m_pSeqParamSet->frame_width_in_mbs;
        m_iMBHeight = m_pSeqParamSet->frame_height_in_mbs;

        // redundant slice, discard
        if (m_SliceHeader.redundant_pic_cnt)
            return false;

        // Set next MB.
        if (m_SliceHeader.first_mb_in_slice >= (int32_t) (m_iMBWidth * m_iMBHeight))
        {
            return false;
        }

        int32_t bit_depth_luma = m_SliceHeader.is_auxiliary ?
            GetSeqParamEx()->bit_depth_aux : GetSeqParam()->bit_depth_luma;

        iSQUANT = m_pPicParamSet->pic_init_qp +
                  m_SliceHeader.slice_qp_delta;
        if (iSQUANT < QP_MIN - 6*(bit_depth_luma - 8)
            || iSQUANT > QP_MAX)
        {
            return false;
        }

        m_SliceHeader.hw_wa_redundant_elimination_bits[2] = (uint32_t)m_BitStream.BitsDecoded();

        if (m_pPicParamSet->entropy_coding_mode)
            m_BitStream.AlignPointerRight();
    }
    catch(const h264_exception & )
    {
        return false;
    }
    catch(...)
    {
        return false;
    }

    return (UMC_OK == umcRes);

}
bool H264Slice::Reset(void *pSource, size_t nSourceSize, Ipp32s iConsumerNumber)
{
    Ipp32s iMBInFrame;
    Ipp32s iFieldIndex;

    m_BitStream.Reset((Ipp8u *) pSource, (Ipp32u) nSourceSize);

    // decode slice header
    if (nSourceSize && false == DecodeSliceHeader())
        return false;

    m_iMBWidth  = GetSeqParam()->frame_width_in_mbs;
    m_iMBHeight = GetSeqParam()->frame_height_in_mbs;

    iMBInFrame = (m_iMBWidth * m_iMBHeight) / ((m_SliceHeader.field_pic_flag) ? (2) : (1));
    iFieldIndex = (m_SliceHeader.field_pic_flag && m_SliceHeader.bottom_field_flag) ? (1) : (0);

    // set slice variables
    m_iFirstMB = m_SliceHeader.first_mb_in_slice;
    m_iMaxMB = iMBInFrame;

    m_iFirstMBFld = m_SliceHeader.first_mb_in_slice + iMBInFrame * iFieldIndex;

    m_iAvailableMB = iMBInFrame;

    if (m_iFirstMB >= m_iAvailableMB)
        return false;

    // reset all internal variables
    m_iCurMBToDec = m_iFirstMB;
    m_iCurMBToRec = m_iFirstMB;
    m_iCurMBToDeb = m_iFirstMB;

    m_bInProcess = false;
    m_bDecVacant = 1;
    m_bRecVacant = 1;
    m_bDebVacant = 1;
    m_bFirstDebThreadedCall = true;
    m_bError = false;

    m_MVsDistortion = 0;

    // reallocate internal buffer
    if (false == IsSliceGroups() && iConsumerNumber > 1)
    {
        Ipp32s iMBRowSize = GetMBRowWidth();
        Ipp32s iMBRowBuffers;
        Ipp32s bit_depth_luma, bit_depth_chroma;
        if (m_SliceHeader.is_auxiliary)
        {
            bit_depth_luma = GetSeqParamEx()->bit_depth_aux;
            bit_depth_chroma = 8;
        } else {
            bit_depth_luma = GetSeqParam()->bit_depth_luma;
            bit_depth_chroma = GetSeqParam()->bit_depth_chroma;
        }

        Ipp32s isU16Mode = (bit_depth_luma > 8 || bit_depth_chroma > 8) ? 2 : 1;

        // decide number of buffers
        iMBRowBuffers = IPP_MAX(MINIMUM_NUMBER_OF_ROWS, MB_BUFFER_SIZE / iMBRowSize);
        iMBRowBuffers = IPP_MIN(MAXIMUM_NUMBER_OF_ROWS, iMBRowBuffers);

        m_CoeffsBuffers.Init(iMBRowBuffers, (Ipp32s)sizeof(Ipp16s) * isU16Mode * (iMBRowSize * COEFFICIENTS_BUFFER_SIZE + DEFAULT_ALIGN_VALUE));
    }

    m_CoeffsBuffers.Reset();

    // reset through-decoding variables
    m_nMBSkipCount = 0;
    m_nQuantPrev = m_pPicParamSet->pic_init_qp +
                   m_SliceHeader.slice_qp_delta;
    m_prev_dquant = 0;
    m_field_index = iFieldIndex;

    if (IsSliceGroups())
        m_bNeedToCheckMBSliceEdges = true;
    else
        m_bNeedToCheckMBSliceEdges = (0 == m_SliceHeader.first_mb_in_slice) ? (false) : (true);

    // set conditional flags
    m_bDecoded = false;
    m_bPrevDeblocked = false;
    m_bDeblocked = (m_SliceHeader.disable_deblocking_filter_idc == DEBLOCK_FILTER_OFF);

    if (m_bDeblocked)
    {
        m_bDebVacant = 0;
        m_iCurMBToDeb = m_iMaxMB;
    }

    // frame is not associated yet
    m_pCurrentFrame = NULL;

    return true;

} // bool H264Slice::Reset(void *pSource, size_t nSourceSize, Ipp32s iNumber)