bool H264Slice::Reset(H264NalExtension *pNalExt) { int32_t iMBInFrame; int32_t iFieldIndex; m_BitStream.Reset((uint8_t *) m_pSource.GetPointer(), (uint32_t) m_pSource.GetDataSize()); // decode slice header if (m_pSource.GetDataSize() && false == DecodeSliceHeader(pNalExt)) { ZeroedMembers(); 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_bFirstDebThreadedCall = true; m_bError = false; // set conditional flags m_bDecoded = false; m_bPrevDeblocked = false; m_bDeblocked = (m_SliceHeader.disable_deblocking_filter_idc == DEBLOCK_FILTER_OFF); // frame is not associated yet m_pCurrentFrame = NULL; m_bInited = true; m_pSeqParamSet->IncrementReference(); m_pPicParamSet->IncrementReference(); if (m_pSeqParamSetEx) m_pSeqParamSetEx->IncrementReference(); if (m_pSeqParamSetMvcEx) m_pSeqParamSetMvcEx->IncrementReference(); if (m_pSeqParamSetSvcEx) m_pSeqParamSetSvcEx->IncrementReference(); return true; } // bool H264Slice::Reset(void *pSource, size_t nSourceSize, int32_t iNumber)
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::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)
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)