u32 h264bsdDecodeSeqParamSet(strmData_t *pStrmData, seqParamSet_t *pSeqParamSet,
    u32 mvcFlag)
{

/* Variables */

    u32 tmp, i, value;

/* Code */

    ASSERT(pStrmData);
    ASSERT(pSeqParamSet);

    (void)DWLmemset(pSeqParamSet, 0, sizeof(seqParamSet_t));

    /* profile_idc */
    tmp = h264bsdGetBits(pStrmData, 8);
    if (tmp == END_OF_STREAM)
        return(HANTRO_NOK);
    if (tmp != 66)
    {
        DEBUG_PRINT(("NOT BASELINE PROFILE %d\n", tmp));
    }
    #ifdef ASIC_TRACE_SUPPORT 
    if (tmp==66)
        trace_h264DecodingTools.profileType.baseline = 1;
    if (tmp==77)
       	trace_h264DecodingTools.profileType.main = 1;
    if (tmp == 100)
	    trace_h264DecodingTools.profileType.high = 1;
    #endif 
    pSeqParamSet->profileIdc = tmp;

    /* constrained_set0_flag */
    tmp = h264bsdGetBits(pStrmData, 1);
    pSeqParamSet->constrained_set0_flag = tmp;
    /* constrained_set1_flag */
    tmp = h264bsdGetBits(pStrmData, 1);
    pSeqParamSet->constrained_set1_flag = tmp;
    /* constrained_set2_flag */
    tmp = h264bsdGetBits(pStrmData, 1);
    pSeqParamSet->constrained_set2_flag = tmp;
    /* constrained_set3_flag */
    tmp = h264bsdGetBits(pStrmData, 1);
    pSeqParamSet->constrained_set3_flag = tmp;
    if (tmp == END_OF_STREAM)
        return(HANTRO_NOK);

    /* reserved_zero_4bits, values of these bits shall be ignored */
    tmp = h264bsdGetBits(pStrmData, 4);
    if (tmp == END_OF_STREAM)
    {
        ERROR_PRINT("reserved_zero_4bits");
        return(HANTRO_NOK);
    }

    tmp = h264bsdGetBits(pStrmData, 8);
    if (tmp == END_OF_STREAM)
    {
        ERROR_PRINT("level_idc");
        return(HANTRO_NOK);
    }
    pSeqParamSet->levelIdc = tmp;

    tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
        &pSeqParamSet->seqParameterSetId);
    if (tmp != HANTRO_OK)
        return(tmp);
    if (pSeqParamSet->seqParameterSetId >= MAX_NUM_SEQ_PARAM_SETS)
    {
        ERROR_PRINT("seq_param_set_id");
        return(HANTRO_NOK);
    }

    if( pSeqParamSet->profileIdc >= 100 )
    {
        /* chroma_format_idc */
        tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
            &value);
        if (tmp != HANTRO_OK)
            return(tmp);
        if( tmp > 1 )
            return(HANTRO_NOK);
        pSeqParamSet->chromaFormatIdc = value;
        if (pSeqParamSet->chromaFormatIdc == 0)
            pSeqParamSet->monoChrome = 1;
        /* residual_colour_transform_flag (skipped) */

        /* bit_depth_luma_minus8 */
        tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
            &value);
        if (tmp != HANTRO_OK)
            return(tmp);

        /* bit_depth_chroma_minus8 */
        tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
            &value);
        if (tmp != HANTRO_OK)
            return(tmp);

        /* qpprime_y_zero_transform_bypass_flag */
        tmp = h264bsdGetBits(pStrmData, 1);
        if (tmp == END_OF_STREAM)
            return(HANTRO_NOK);

        /* seq_scaling_matrix_present_flag */
        tmp = h264bsdGetBits(pStrmData, 1);
	#ifdef ASIC_TRACE_SUPPORT 
        if (tmp)
        trace_h264DecodingTools.scalingMatrixPresentType.seq = 1;
        #endif 
        if (tmp == END_OF_STREAM)
            return(HANTRO_NOK);
        pSeqParamSet->scalingMatrixPresentFlag = tmp;
        if (tmp)
        {
            for (i = 0; i < 8; i++)
            {
                tmp = h264bsdGetBits(pStrmData, 1);
                pSeqParamSet->scalingListPresent[i] = tmp;
                if (tmp)
                {
                    ScalingList(pSeqParamSet->scalingList, pStrmData, i);
                }
                else
                    FallbackScaling(pSeqParamSet->scalingList, i);
            }
        }

    }
    else
    {
        pSeqParamSet->chromaFormatIdc = 1; /* 4:2:0 */
        pSeqParamSet->scalingMatrixPresentFlag = 0;
    }

    /* log2_max_frame_num_minus4 */
    tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
    if (tmp != HANTRO_OK)
    {
        ERROR_PRINT("log2_max_frame_num_minus4");
        return(tmp);
    }
    if (value > 12)
    {
        ERROR_PRINT("log2_max_frame_num_minus4");
        return(HANTRO_NOK);
    }
    /* maxFrameNum = 2^(log2_max_frame_num_minus4 + 4) */
    pSeqParamSet->maxFrameNum = 1 << (value+4);

    /* valid POC types are 0, 1 and 2 */
    tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
    if (tmp != HANTRO_OK)
    {
        ERROR_PRINT("pic_order_cnt_type");
        return(tmp);
    }
    if (value > 2)
    {
        ERROR_PRINT("pic_order_cnt_type");
        return(HANTRO_NOK);
    }
    pSeqParamSet->picOrderCntType = value;

    if (pSeqParamSet->picOrderCntType == 0)
    {
        /* log2_max_pic_order_cnt_lsb_minus4 */
        tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
        if (tmp != HANTRO_OK)
            return(tmp);
        if (value > 12)
        {
            ERROR_PRINT("log2_max_pic_order_cnt_lsb_minus4");
            return(HANTRO_NOK);
        }
        /* maxPicOrderCntLsb = 2^(log2_max_pic_order_cnt_lsb_minus4 + 4) */
        pSeqParamSet->maxPicOrderCntLsb = 1 << (value+4);
    }
    else if (pSeqParamSet->picOrderCntType == 1)
    {
        tmp = h264bsdGetBits(pStrmData, 1);
        if (tmp == END_OF_STREAM)
            return(HANTRO_NOK);
        pSeqParamSet->deltaPicOrderAlwaysZeroFlag = (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE;

        tmp = h264bsdDecodeExpGolombSigned(pStrmData,
            &pSeqParamSet->offsetForNonRefPic);
        if (tmp != HANTRO_OK)
            return(tmp);

        tmp = h264bsdDecodeExpGolombSigned(pStrmData,
            &pSeqParamSet->offsetForTopToBottomField);
        if (tmp != HANTRO_OK)
            return(tmp);

        tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
            &pSeqParamSet->numRefFramesInPicOrderCntCycle);
        if (tmp != HANTRO_OK)
            return(tmp);
        if (pSeqParamSet->numRefFramesInPicOrderCntCycle > 255)
        {
            ERROR_PRINT("num_ref_frames_in_pic_order_cnt_cycle");
            return(HANTRO_NOK);
        }

        if (pSeqParamSet->numRefFramesInPicOrderCntCycle)
        {
            /* NOTE: This has to be freed somewhere! */
            ALLOCATE(pSeqParamSet->offsetForRefFrame,
                     pSeqParamSet->numRefFramesInPicOrderCntCycle, i32);
            if (pSeqParamSet->offsetForRefFrame == NULL)
                return(MEMORY_ALLOCATION_ERROR);

            for (i = 0; i < pSeqParamSet->numRefFramesInPicOrderCntCycle; i++)
            {
                tmp =  h264bsdDecodeExpGolombSigned(pStrmData,
                    pSeqParamSet->offsetForRefFrame + i);
                if (tmp != HANTRO_OK)
                    return(tmp);
            }
        }
        else
        {
            pSeqParamSet->offsetForRefFrame = NULL;
        }
    }

    tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
        &pSeqParamSet->numRefFrames);
    if (tmp != HANTRO_OK)
        return(tmp);
    if (pSeqParamSet->numRefFrames > MAX_NUM_REF_PICS ||
        /* max num ref frames in mvc stereo high profile is actually 8, but
         * here we just check that it is less than 15 (base 15 used for 
         * inter view reference picture) */
        (mvcFlag && (pSeqParamSet->numRefFrames > 15)))
    {
        ERROR_PRINT("num_ref_frames");
        return(HANTRO_NOK);
    }

    tmp = h264bsdGetBits(pStrmData, 1);
    if (tmp == END_OF_STREAM)
        return(HANTRO_NOK);
    pSeqParamSet->gapsInFrameNumValueAllowedFlag = (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE;

    tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
    if (tmp != HANTRO_OK)
        return(tmp);
    pSeqParamSet->picWidthInMbs = value + 1;

    tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
    if (tmp != HANTRO_OK)
        return(tmp);
    pSeqParamSet->picHeightInMbs = value + 1;

    /* frame_mbs_only_flag, shall be 1 for baseline profile */
    tmp = h264bsdGetBits(pStrmData, 1);
    if (tmp == END_OF_STREAM)
        return(HANTRO_NOK);
    pSeqParamSet->frameMbsOnlyFlag = tmp;

    if (!pSeqParamSet->frameMbsOnlyFlag)
    {
        pSeqParamSet->mbAdaptiveFrameFieldFlag =
            h264bsdGetBits(pStrmData, 1);
        pSeqParamSet->picHeightInMbs *= 2;
    }

    /* direct_8x8_inference_flag */
    tmp = h264bsdGetBits(pStrmData, 1);
    if (tmp == END_OF_STREAM)
        return(HANTRO_NOK);
    pSeqParamSet->direct8x8InferenceFlag = tmp;

    tmp = h264bsdGetBits(pStrmData, 1);
    if (tmp == END_OF_STREAM)
        return(HANTRO_NOK);
    pSeqParamSet->frameCroppingFlag = (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE;
    
#ifdef ASIC_TRACE_SUPPORT
    if (tmp)
        trace_h264DecodingTools.imageCropping = 1;
#endif

    if (pSeqParamSet->frameCroppingFlag)
    {
        tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
            &pSeqParamSet->frameCropLeftOffset);
        if (tmp != HANTRO_OK)
            return(tmp);
        tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
            &pSeqParamSet->frameCropRightOffset);
        if (tmp != HANTRO_OK)
            return(tmp);
        tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
            &pSeqParamSet->frameCropTopOffset);
        if (tmp != HANTRO_OK)
            return(tmp);
        tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
            &pSeqParamSet->frameCropBottomOffset);
        if (tmp != HANTRO_OK)
            return(tmp);

        /* check that frame cropping params are valid, parameters shall
         * specify non-negative area within the original picture */
        if ( ( (i32)pSeqParamSet->frameCropLeftOffset >
               ( 8 * (i32)pSeqParamSet->picWidthInMbs -
                 ((i32)pSeqParamSet->frameCropRightOffset + 1) ) ) ||
             ( (i32)pSeqParamSet->frameCropTopOffset >
               ( 8 * (i32)pSeqParamSet->picHeightInMbs -
                 ((i32)pSeqParamSet->frameCropBottomOffset + 1) ) ) )
        {
            ERROR_PRINT("frame_cropping");
            return(HANTRO_NOK);
        }
    }

    /* check that image dimensions and levelIdc match */
    tmp = pSeqParamSet->picWidthInMbs * pSeqParamSet->picHeightInMbs;
    value = GetDpbSize(tmp, pSeqParamSet->levelIdc);
    if (value == INVALID_DPB_SIZE || pSeqParamSet->numRefFrames > value)
    {
        DEBUG_PRINT(("WARNING! Invalid DPB size based on SPS Level!\n"));
        DEBUG_PRINT(("WARNING! Using num_ref_frames =%d for DPB size!\n",
                        pSeqParamSet->numRefFrames));
        /* set maxDpbSize to 1 if numRefFrames is zero */
        value = pSeqParamSet->numRefFrames ? pSeqParamSet->numRefFrames : 1;
    }
    pSeqParamSet->maxDpbSize = value;

    tmp = h264bsdGetBits(pStrmData, 1);
    if (tmp == END_OF_STREAM)
        return(HANTRO_NOK);
    pSeqParamSet->vuiParametersPresentFlag = (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE;

    /* VUI */
    if (pSeqParamSet->vuiParametersPresentFlag)
    {
        ALLOCATE(pSeqParamSet->vuiParameters, 1, vuiParameters_t);
        if (pSeqParamSet->vuiParameters == NULL)
            return(MEMORY_ALLOCATION_ERROR);
        tmp = h264bsdDecodeVuiParameters(pStrmData,
            pSeqParamSet->vuiParameters);
        if (tmp == END_OF_STREAM)
        {
            pSeqParamSet->vuiParameters->bitstreamRestrictionFlag |= 1;
            pSeqParamSet->vuiParameters->maxDecFrameBuffering =
                pSeqParamSet->maxDpbSize;
        }
        else if (tmp != HANTRO_OK)
            return(tmp);
        /* check numReorderFrames and maxDecFrameBuffering */
        if (pSeqParamSet->vuiParameters->bitstreamRestrictionFlag)
        {
            if (pSeqParamSet->vuiParameters->numReorderFrames >
                    pSeqParamSet->vuiParameters->maxDecFrameBuffering ||
                pSeqParamSet->vuiParameters->maxDecFrameBuffering <
                    pSeqParamSet->numRefFrames ||
                pSeqParamSet->vuiParameters->maxDecFrameBuffering >
                    pSeqParamSet->maxDpbSize)
            {
                ERROR_PRINT("Not valid vuiParameters->bitstreamRestriction");
                return(HANTRO_NOK);
            }

            /* standard says that "the sequence shall not require a DPB with
             * size of more than max(1, maxDecFrameBuffering) */
            pSeqParamSet->maxDpbSize =
                MAX(1, pSeqParamSet->vuiParameters->maxDecFrameBuffering);
        }
    }

    if (mvcFlag)
    {
        if (pSeqParamSet->profileIdc == 118 || pSeqParamSet->profileIdc == 128)
        {
            /* bit_equal_to_one */
            tmp = h264bsdGetBits(pStrmData, 1);
            tmp = DecodeMvcExtension(pStrmData, pSeqParamSet);
            if (tmp != HANTRO_OK)
                return tmp;
        }

        /* additional_extension2_flag, shall be zero */
        tmp = h264bsdGetBits(pStrmData, 1);
        /* TODO: skip rest of the stuff if equal to 1 */
    }

    tmp = h264bsdRbspTrailingBits(pStrmData);

    /* ignore possible errors in trailing bits of parameters sets */
    return(HANTRO_OK);

}
Ejemplo n.º 2
0
bool 
SeqParamSet::Parse(NALUnit* pnalu)
{
    if (pnalu->Type() != NALUnit::NAL_Sequence_Params)
    {
        return false;
    }

    // with the UE/SE type encoding, we must decode all the values
    // to get through to the ones we want
    pnalu->ResetBitstream();
	pnalu->Skip(8);		// type
	m_Profile = pnalu->GetWord(8);
	m_Compatibility = (BYTE) pnalu->GetWord(8);
	m_Level = pnalu->GetWord(8);

	/*int seq_param_id =*/ pnalu->GetUE();

	if ((m_Profile == 100) || (m_Profile == 110) || (m_Profile == 122) || (m_Profile == 144))
	{
		int chroma_fmt = pnalu->GetUE();
		if (chroma_fmt == 3)
		{
			pnalu->Skip(1);
		}
		/* int bit_depth_luma_minus8 = */ pnalu->GetUE();
		/* int bit_depth_chroma_minus8 = */ pnalu->GetUE();
		pnalu->Skip(1);
		int seq_scaling_matrix_present = pnalu->GetBit();
		if (seq_scaling_matrix_present)
		{
			for (int i = 0; i < 8; i++)
			{
				if (pnalu->GetBit())
				{
					if (i < 6)
					{
						ScalingList(16, pnalu);
					}
					else
					{
						ScalingList(64, pnalu);
					}
				}
			}
		}
	}

    int log2_frame_minus4 = pnalu->GetUE();
    m_FrameBits = log2_frame_minus4 + 4;
    int POCtype = pnalu->GetUE();
    if (POCtype == 0)
    {
        /*int log2_poc_minus4 =*/ pnalu->GetUE();
    } else if (POCtype == 1) 
    {
        pnalu->Skip(1); // delta always zero
        /*int nsp_offset =*/ pnalu->GetSE();
        /*int nsp_top_to_bottom = */ pnalu->GetSE();
        int num_ref_in_cycle = pnalu->GetUE();
        for (int i = 0; i < num_ref_in_cycle; i++)
        {
            /*int sf_offset =*/ pnalu->GetSE();
        }
    } 
	else if (POCtype != 2)
	{
		return false;
	}
	// else for POCtype == 2, no additional data in stream
    
    /*int num_ref_frames =*/ pnalu->GetUE();
    /*int gaps_allowed =*/ pnalu->GetBit();

    int mbs_width = pnalu->GetUE();
    int mbs_height = pnalu->GetUE();
    m_cx = (mbs_width+1) * 16;
    m_cy = (mbs_height+1) * 16;

	// smoke test validation of sps
	if ((m_cx > 2000) || (m_cy > 2000))
	{
		return false;
	}

    // if this is false, then sizes are field sizes and need adjusting
    m_bFrameOnly = pnalu->GetBit() ? true : false;
    
    if (!m_bFrameOnly)
    {
        pnalu->Skip(1); // adaptive frame/field
    }
    pnalu->Skip(1);     // direct 8x8

#if 0
    SetRect(&m_rcFrame, 0, 0, 0, 0);
    bool bCrop = pnalu->GetBit() ? true : false;
    if (bCrop) {
        // get cropping rect 
        // store as exclusive, pixel parameters relative to frame
        m_rcFrame.left = pnalu->GetUE() * 2;
        m_rcFrame.right = pnalu->GetUE() * 2;
        m_rcFrame.top = pnalu->GetUE() * 2;
        m_rcFrame.bottom = pnalu->GetUE() * 2;
    }

    if (!IsRectEmpty(&m_rcFrame))
    {
        m_rcFrame.right = m_cx - m_rcFrame.right;
        m_rcFrame.bottom = m_cy - m_rcFrame.bottom;
    }
#endif
    // adjust rect from 2x2 units to pixels

    if (!m_bFrameOnly)
    {
        // adjust heights from field to frame
        m_cy *= 2;
#if 0
        m_rcFrame.top *= 2;
        m_rcFrame.bottom *= 2;
#endif
    }

    // .. rest are not interesting yet
    m_nalu = *pnalu;
    return true;
}