/* /////////////////////////////////////////////////////////////////////// | |
// | |
// 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) 2008 Intel Corporation. All Rights Reserved. | |
// | |
// Description: Parses VC-1 picture layer for advanced profile. | |
// | |
*/ | |
#include "vc1parse.h" | |
#include "viddec_fw_debug.h" | |
/*------------------------------------------------------------------------------ | |
* Parse picture layer. This function parses the picture header for advanced | |
* profile down to POSTPROC syntax element. | |
* Table 18 of SMPTE 421M for progressive I or BI picture. | |
* Table 20 of SMPTE 421M for progressive P picture. | |
* Table 22 of SMPTE 421M for progressive B picture. | |
* Table 23 of SMPTE 421M for skipped picture. | |
* Table 82 of SMPTE 421M for interlace I or BI frame. | |
* Table 83 of SMPTE 421M for interlace P frame. | |
* Table 84 of SMPTE 421M for interlace B frame. | |
*------------------------------------------------------------------------------ | |
*/ | |
vc1_Status vc1_ParsePictureHeader_Adv(void* ctxt, vc1_Info *pInfo) | |
{ | |
uint32_t i = 0; | |
uint32_t tempValue; | |
vc1_Status status = VC1_STATUS_OK; | |
uint32_t number_of_pan_scan_window; | |
vc1_metadata_t *md = &pInfo->metadata; | |
vc1_PictureLayerHeader *picLayerHeader = &pInfo->picLayerHeader; | |
if (md->INTERLACE == 1) | |
{ | |
VC1_GET_BITS9(1, picLayerHeader->FCM); | |
if (picLayerHeader->FCM) | |
{ | |
VC1_GET_BITS9(1, picLayerHeader->FCM); | |
if (picLayerHeader->FCM) | |
{ | |
picLayerHeader->FCM = VC1_FCM_FIELD_INTERLACE; | |
return VC1_STATUS_PARSE_ERROR; | |
} | |
else | |
picLayerHeader->FCM = VC1_FCM_FRAME_INTERLACE; | |
} | |
else | |
picLayerHeader->FCM = VC1_FCM_PROGRESSIVE; | |
} | |
else | |
picLayerHeader->FCM = VC1_FCM_PROGRESSIVE; | |
VC1_GET_BITS9(1, picLayerHeader->PTYPE); | |
if (picLayerHeader->PTYPE) | |
{ | |
VC1_GET_BITS9(1, picLayerHeader->PTYPE); | |
if (picLayerHeader->PTYPE) | |
{ | |
VC1_GET_BITS9(1, picLayerHeader->PTYPE); | |
if (picLayerHeader->PTYPE) | |
{ | |
VC1_GET_BITS9(1, picLayerHeader->PTYPE); | |
if (picLayerHeader->PTYPE) | |
picLayerHeader->PTYPE = VC1_SKIPPED_FRAME; | |
else | |
picLayerHeader->PTYPE = VC1_BI_FRAME; | |
} | |
else | |
picLayerHeader->PTYPE = VC1_I_FRAME; | |
} | |
else | |
picLayerHeader->PTYPE = VC1_B_FRAME; | |
} | |
else | |
picLayerHeader->PTYPE = VC1_P_FRAME; | |
if (picLayerHeader->PTYPE != VC1_SKIPPED_FRAME) | |
{ | |
if (md->TFCNTRFLAG) | |
{ | |
VC1_GET_BITS9(8, picLayerHeader->TFCNTR); /* TFCNTR. */ | |
} | |
} | |
if (md->PULLDOWN) | |
{ | |
if ((md->INTERLACE == 0) || (md->PSF == 1)) | |
{ | |
VC1_GET_BITS9(2, picLayerHeader->RPTFRM); | |
} | |
else | |
{ | |
VC1_GET_BITS9(1, picLayerHeader->TFF); | |
VC1_GET_BITS9(1, picLayerHeader->RFF); | |
} | |
} | |
if (md->PANSCAN_FLAG == 1) | |
{ | |
VC1_GET_BITS9(1, picLayerHeader->PS_PRESENT); /* PS_PRESENT. */ | |
if (picLayerHeader->PS_PRESENT == 1) | |
{ | |
if ((md->INTERLACE == 1) && | |
(md->PSF == 0)) | |
{ | |
if (md->PULLDOWN == 1) | |
number_of_pan_scan_window = 2 + picLayerHeader->RFF; | |
else | |
number_of_pan_scan_window = 2; | |
} | |
else | |
{ | |
if (md->PULLDOWN == 1) | |
number_of_pan_scan_window = 1 + picLayerHeader->RPTFRM; | |
else | |
number_of_pan_scan_window = 1; | |
} | |
picLayerHeader->number_of_pan_scan_window = number_of_pan_scan_window; | |
for (i = 0; i < number_of_pan_scan_window; i++) | |
{ | |
VC1_GET_BITS(18, picLayerHeader->PAN_SCAN_WINDOW[i].hoffset); /* PS_HOFFSET. */ | |
VC1_GET_BITS(18, picLayerHeader->PAN_SCAN_WINDOW[i].voffset); /* PS_VOFFSET. */ | |
VC1_GET_BITS(14, picLayerHeader->PAN_SCAN_WINDOW[i].width); /* PS_WIDTH. */ | |
VC1_GET_BITS(14, picLayerHeader->PAN_SCAN_WINDOW[i].height); /* PS_HEIGHT. */ | |
} | |
} | |
} | |
if (picLayerHeader->PTYPE != VC1_SKIPPED_FRAME) | |
{ | |
VC1_GET_BITS9(1, picLayerHeader->RNDCTRL); | |
md->RNDCTRL = picLayerHeader->RNDCTRL; | |
if ((md->INTERLACE == 1) || | |
(picLayerHeader->FCM != VC1_FCM_PROGRESSIVE)) | |
{ | |
VC1_GET_BITS9(1, picLayerHeader->UVSAMP); | |
} | |
if ((md->FINTERPFLAG == 1) && | |
(picLayerHeader->FCM == VC1_FCM_PROGRESSIVE)) | |
{ | |
VC1_GET_BITS9(1, tempValue); /* INTERPFRM. */ | |
} | |
if ((picLayerHeader->PTYPE == VC1_B_FRAME) && | |
(picLayerHeader->FCM == VC1_FCM_PROGRESSIVE)) | |
{ | |
if ((status = vc1_DecodeHuffmanPair(ctxt, VC1_BFRACTION_TBL, | |
&picLayerHeader->BFRACTION_NUM, &picLayerHeader->BFRACTION_DEN)) | |
!= VC1_STATUS_OK) | |
{ | |
return status; | |
} | |
} | |
VC1_GET_BITS9(5, picLayerHeader->PQINDEX); | |
if ((status = vc1_CalculatePQuant(pInfo)) != VC1_STATUS_OK) | |
return status; | |
if (picLayerHeader->PQINDEX <= 8) | |
{ | |
VC1_GET_BITS9(1, picLayerHeader->HALFQP); | |
} | |
else | |
picLayerHeader->HALFQP = 0; | |
if (md->QUANTIZER == 1) | |
{ | |
VC1_GET_BITS9(1, picLayerHeader->PQUANTIZER); | |
picLayerHeader->UniformQuant = picLayerHeader->PQUANTIZER; | |
} | |
if (md->POSTPROCFLAG == 1) | |
{ | |
VC1_GET_BITS9(2, picLayerHeader->POSTPROC); | |
} | |
} | |
return vc1_ParsePictureFieldHeader_Adv(ctxt, pInfo); | |
} | |
/*------------------------------------------------------------------------------ | |
* Parse picture layer. This function parses the picture header for advanced | |
* profile down to BFRACTION syntax element. | |
* Table 85 of SMPTE 421M. | |
*------------------------------------------------------------------------------ | |
*/ | |
vc1_Status vc1_ParseFieldHeader_Adv(void* ctxt, vc1_Info *pInfo) | |
{ | |
uint32_t i = 0; | |
vc1_Status status = VC1_STATUS_OK; | |
uint32_t number_of_pan_scan_window; | |
vc1_metadata_t *md = &pInfo->metadata; | |
vc1_PictureLayerHeader *picLayerHeader = &pInfo->picLayerHeader; | |
VC1_GET_BITS9(1, picLayerHeader->FCM); | |
if (picLayerHeader->FCM) | |
{ | |
VC1_GET_BITS9(1, picLayerHeader->FCM); | |
if (picLayerHeader->FCM) | |
picLayerHeader->FCM = VC1_FCM_FIELD_INTERLACE; | |
else | |
picLayerHeader->FCM = VC1_FCM_FRAME_INTERLACE; | |
} | |
else | |
picLayerHeader->FCM = VC1_FCM_PROGRESSIVE; | |
if (picLayerHeader->FCM != VC1_FCM_FIELD_INTERLACE) | |
return VC1_STATUS_PARSE_ERROR; | |
VC1_GET_BITS9(3, picLayerHeader->FPTYPE); | |
if (picLayerHeader->FPTYPE == 0) | |
{ | |
picLayerHeader->PTypeField1 = VC1_I_FRAME; | |
picLayerHeader->PTypeField2 = VC1_I_FRAME; | |
} | |
else if (picLayerHeader->FPTYPE == 1) | |
{ | |
picLayerHeader->PTypeField1 = VC1_I_FRAME; | |
picLayerHeader->PTypeField2 = VC1_P_FRAME; | |
} | |
else if (picLayerHeader->FPTYPE == 2) | |
{ | |
picLayerHeader->PTypeField1 = VC1_P_FRAME; | |
picLayerHeader->PTypeField2 = VC1_I_FRAME; | |
} | |
else if (picLayerHeader->FPTYPE == 3) | |
{ | |
picLayerHeader->PTypeField1 = VC1_P_FRAME; | |
picLayerHeader->PTypeField2 = VC1_P_FRAME; | |
} | |
else if (picLayerHeader->FPTYPE == 4) | |
{ | |
picLayerHeader->PTypeField1 = VC1_B_FRAME; | |
picLayerHeader->PTypeField2 = VC1_B_FRAME; | |
} | |
else if (picLayerHeader->FPTYPE == 5) | |
{ | |
picLayerHeader->PTypeField1 = VC1_B_FRAME; | |
picLayerHeader->PTypeField2 = VC1_BI_FRAME; | |
} | |
else if (picLayerHeader->FPTYPE == 6) | |
{ | |
picLayerHeader->PTypeField1 = VC1_BI_FRAME; | |
picLayerHeader->PTypeField2 = VC1_B_FRAME; | |
} | |
else if (picLayerHeader->FPTYPE == 7) | |
{ | |
picLayerHeader->PTypeField1 = VC1_BI_FRAME; | |
picLayerHeader->PTypeField2 = VC1_BI_FRAME; | |
} | |
if (md->TFCNTRFLAG) | |
{ | |
VC1_GET_BITS9(8, picLayerHeader->TFCNTR); | |
} | |
if (md->PULLDOWN == 1) | |
{ | |
if (md->PSF == 1) | |
{ | |
VC1_GET_BITS9(2, picLayerHeader->RPTFRM); | |
} | |
else | |
{ | |
VC1_GET_BITS9(1, picLayerHeader->TFF); | |
VC1_GET_BITS9(1, picLayerHeader->RFF); | |
} | |
} else | |
picLayerHeader->TFF = 1; | |
if (md->PANSCAN_FLAG == 1) | |
{ | |
VC1_GET_BITS9(1, picLayerHeader->PS_PRESENT); | |
if (picLayerHeader->PS_PRESENT) | |
{ | |
if (md->PULLDOWN) | |
number_of_pan_scan_window = 2 + picLayerHeader->RFF; | |
else | |
number_of_pan_scan_window = 2; | |
picLayerHeader->number_of_pan_scan_window =number_of_pan_scan_window; | |
for (i = 0; i < number_of_pan_scan_window; i++) | |
{ | |
VC1_GET_BITS(18, picLayerHeader->PAN_SCAN_WINDOW[i].hoffset); /* PS_HOFFSET. */ | |
VC1_GET_BITS(18, picLayerHeader->PAN_SCAN_WINDOW[i].voffset); /* PS_VOFFSET. */ | |
VC1_GET_BITS(14, picLayerHeader->PAN_SCAN_WINDOW[i].width); /* PS_WIDTH. */ | |
VC1_GET_BITS(14, picLayerHeader->PAN_SCAN_WINDOW[i].height); /* PS_HEIGHT. */ | |
} | |
} | |
} | |
VC1_GET_BITS9(1, md->RNDCTRL); | |
#ifdef VBP | |
picLayerHeader->RNDCTRL = md->RNDCTRL; | |
#endif | |
VC1_GET_BITS9(1, picLayerHeader->UVSAMP); | |
if ((md->REFDIST_FLAG == 1) && (picLayerHeader->FPTYPE <= 3)) | |
{ | |
int32_t tmp; | |
if ((status = vc1_DecodeHuffmanOne(ctxt, &tmp, | |
VC1_REFDIST_TBL)) != VC1_STATUS_OK) | |
{ | |
return status; | |
} | |
md->REFDIST = tmp; | |
} | |
if ((picLayerHeader->FPTYPE >= 4) && (picLayerHeader->FPTYPE <= 7)) | |
{ | |
if ((status = vc1_DecodeHuffmanPair(ctxt, VC1_BFRACTION_TBL, | |
&picLayerHeader->BFRACTION_NUM, &picLayerHeader->BFRACTION_DEN)) != | |
VC1_STATUS_OK) | |
{ | |
return status; | |
} | |
} | |
if (picLayerHeader->CurrField == 0) | |
{ | |
picLayerHeader->PTYPE = picLayerHeader->PTypeField1; | |
picLayerHeader->BottomField = (uint8_t) (1 - picLayerHeader->TFF); | |
} | |
else | |
{ | |
picLayerHeader->BottomField = (uint8_t) (picLayerHeader->TFF); | |
picLayerHeader->PTYPE = picLayerHeader->PTypeField2; | |
} | |
return vc1_ParsePictureFieldHeader_Adv(ctxt, pInfo); | |
} | |
/*------------------------------------------------------------------------------ | |
* Parse picture layer. This function calls the appropriate function to further | |
* parse the picture header for advanced profile down to macroblock layer. | |
*------------------------------------------------------------------------------ | |
*/ | |
vc1_Status vc1_ParsePictureFieldHeader_Adv(void* ctxt, vc1_Info *pInfo) | |
{ | |
vc1_Status status = VC1_STATUS_PARSE_ERROR; | |
if (pInfo->picLayerHeader.FCM == VC1_FCM_PROGRESSIVE) | |
{ | |
if ((pInfo->picLayerHeader.PTYPE == VC1_I_FRAME) || | |
(pInfo->picLayerHeader.PTYPE == VC1_BI_FRAME)) | |
{ | |
status = vc1_ParsePictureHeader_ProgressiveIpicture_Adv(ctxt, pInfo); | |
} | |
else if (pInfo->picLayerHeader.PTYPE == VC1_P_FRAME) | |
status = vc1_ParsePictureHeader_ProgressivePpicture_Adv(ctxt, pInfo); | |
else if (pInfo->picLayerHeader.PTYPE == VC1_B_FRAME) | |
status = vc1_ParsePictureHeader_ProgressiveBpicture_Adv(ctxt, pInfo); | |
else if (pInfo->picLayerHeader.PTYPE == VC1_SKIPPED_FRAME) | |
status = VC1_STATUS_OK; | |
} | |
else if (pInfo->picLayerHeader.FCM == VC1_FCM_FRAME_INTERLACE) | |
{ | |
if ((pInfo->picLayerHeader.PTYPE == VC1_I_FRAME) || | |
(pInfo->picLayerHeader.PTYPE == VC1_BI_FRAME)) | |
{ | |
status = vc1_ParsePictureHeader_InterlaceIpicture_Adv(ctxt, pInfo); | |
} | |
else if (pInfo->picLayerHeader.PTYPE == VC1_P_FRAME) | |
status = vc1_ParsePictureHeader_InterlacePpicture_Adv(ctxt, pInfo); | |
else if (pInfo->picLayerHeader.PTYPE == VC1_B_FRAME) | |
status = vc1_ParsePictureHeader_InterlaceBpicture_Adv(ctxt, pInfo); | |
else if (pInfo->picLayerHeader.PTYPE == VC1_SKIPPED_FRAME) | |
status = VC1_STATUS_OK; | |
} | |
else if (pInfo->picLayerHeader.FCM == VC1_FCM_FIELD_INTERLACE) | |
{ | |
int ptype; | |
if( pInfo->picLayerHeader.CurrField == 0) | |
ptype = pInfo->picLayerHeader.PTypeField1; | |
else | |
ptype = pInfo->picLayerHeader.PTypeField2; | |
if ((ptype == VC1_I_FRAME) || | |
(ptype == VC1_BI_FRAME)) | |
{ | |
status = vc1_ParseFieldHeader_InterlaceIpicture_Adv(ctxt, pInfo); | |
} | |
else if (ptype == VC1_P_FRAME) | |
status = vc1_ParseFieldHeader_InterlacePpicture_Adv(ctxt, pInfo); | |
else if (ptype == VC1_B_FRAME) | |
status = vc1_ParseFieldHeader_InterlaceBpicture_Adv(ctxt, pInfo); | |
else if (ptype == VC1_SKIPPED_FRAME) | |
status = VC1_STATUS_OK; | |
} | |
return status; | |
} |