diff options
Diffstat (limited to 'Src/mpeg4dec/mp4decvopi.c')
-rw-r--r-- | Src/mpeg4dec/mp4decvopi.c | 408 |
1 files changed, 408 insertions, 0 deletions
diff --git a/Src/mpeg4dec/mp4decvopi.c b/Src/mpeg4dec/mp4decvopi.c new file mode 100644 index 00000000..2ec2fb84 --- /dev/null +++ b/Src/mpeg4dec/mp4decvopi.c @@ -0,0 +1,408 @@ +/* /////////////////////////////////////////////////////////////////////// +// +// 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) 2001-2007 Intel Corporation. All Rights Reserved. +// +// Description: Decodes I-VOPs +// +*/ + +#include "mp4def.h" +#include "mp4dec.h" + +/* +// decode mcbpc and set MBtype and ChromaPattern +*/ +/*static*/ mp4_Status mp4_DecodeMCBPC_I(mp4_Info* pInfo, int32_t *mbType, int32_t *mbPattern) +{ + uint32_t code; + int32_t type, pattern, fb; + + code = mp4_ShowBits9(pInfo, 9); + if (code == 1) { + type = IPPVC_MB_STUFFING; + pattern = 0; + fb = 9; + } else if (code >= 64) { + type = IPPVC_MBTYPE_INTRA; + pattern = code >> 6; + if (pattern >= 4) { + pattern = 0; + fb = 1; + } else + fb = 3; + } else { + type = IPPVC_MBTYPE_INTRA_Q; + pattern = code >> 3; + if (pattern >= 4) { + pattern = 0; + fb = 4; + } else if (code >= 8) { + fb = 6; + } else { + mp4_Error("Error: decoding MCBPC"); + return MP4_STATUS_ERROR; + } + } + mp4_FlushBits(pInfo, fb); + *mbType = type; + *mbPattern = pattern; + if (type == IPPVC_MBTYPE_INTRA) + mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nMB_INTRA); + else if (type == IPPVC_MBTYPE_INTRA_Q) + mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nMB_INTRA_Q); + return MP4_STATUS_OK; +} + + +/* +// decode IVOP +*/ +mp4_Status mp4_DecodeVOP_I(mp4_Info* pInfo) +{ + int32_t quant, quantPred, dcVLC, mb_type, cbpc, cbpy, ac_pred_flag; + int32_t i, j, nmb, nmbgob, stepYc, stepCbc, stepCrc, stepFc[6], mbCurr, mbInVideoPacket, colNum, rowNum, mbPerRow, mbPerCol; + uint8_t *pFc[6]; + mp4_Status sts; + + if (pInfo->VisualObject.cFrame) + { + DebugBreak(); + } + pInfo->VisualObject.cFrame = CreateFrame(&pInfo->VisualObject); + stepYc = pInfo->VisualObject.cFrame->stepY; + stepCbc = pInfo->VisualObject.cFrame->stepCb; + stepCrc = pInfo->VisualObject.cFrame->stepCr; + mbPerRow = pInfo->VisualObject.VideoObject.MacroBlockPerRow; + mbPerCol = pInfo->VisualObject.VideoObject.MacroBlockPerCol; + stepFc[0] = stepFc[1] = stepFc[2] = stepFc[3] = stepYc; stepFc[4] = stepCbc; stepFc[5] = stepCrc; + pFc[0] = pInfo->VisualObject.cFrame->pY; pFc[1] = pInfo->VisualObject.cFrame->pY + 8; + pFc[2] = pInfo->VisualObject.cFrame->pY + 8 * stepYc; pFc[3] = pInfo->VisualObject.cFrame->pY + 8 * stepYc + 8; + pFc[4] = pInfo->VisualObject.cFrame->pCb; pFc[5] = pInfo->VisualObject.cFrame->pCr; + nmb = pInfo->VisualObject.VideoObject.MacroBlockPerVOP; + mbCurr = colNum = rowNum = 0; + sts = MP4_STATUS_OK; +// decode short_video_header I-VOP + if (pInfo->VisualObject.VideoObject.short_video_header) + { + quant = pInfo->VisualObject.VideoObject.VideoObjectPlaneH263.vop_quant; + nmbgob = 0; + pInfo->VisualObject.VideoObject.VideoObjectPlaneH263.gob_number = 0; + for (;;) + { + do + { + if (mp4_DecodeMCBPC_I(pInfo, &mb_type, &cbpc) != MP4_STATUS_OK) + goto Err_1; + } while (mb_type == IPPVC_MB_STUFFING); + if (mp4_DecodeCBPY_I(pInfo, &cbpy) != MP4_STATUS_OK) + goto Err_1; + if (mb_type == IPPVC_MBTYPE_INTRA_Q) + mp4_UpdateQuant(pInfo, quant); + if (mp4_DecodeIntraMB_SVH(pInfo, (cbpy << 2) + cbpc, quant, pFc, stepFc) != MP4_STATUS_OK) + goto Err_1; + colNum ++; + if (colNum == mbPerRow) { + colNum = 0; + rowNum ++; + if (rowNum == mbPerCol) + break; + pFc[0] += (2 * MP4_NUM_EXT_MB + 1) * 16 + (stepYc << 4) - stepYc; + pFc[1] += (2 * MP4_NUM_EXT_MB + 1) * 16 + (stepYc << 4) - stepYc; + pFc[2] += (2 * MP4_NUM_EXT_MB + 1) * 16 + (stepYc << 4) - stepYc; + pFc[3] += (2 * MP4_NUM_EXT_MB + 1) * 16 + (stepYc << 4) - stepYc; + pFc[4] += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCbc << 3) - stepCbc; + pFc[5] += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCrc << 3) - stepCrc; + } + else + { + pFc[0] += 16; pFc[1] += 16; pFc[2] += 16; pFc[3] += 16; pFc[4] += 8; pFc[5] += 8; + } + nmbgob ++; + if (nmbgob == pInfo->VisualObject.VideoObject.VideoObjectPlaneH263.num_macroblocks_in_gob && pInfo->VisualObject.VideoObject.VideoObjectPlaneH263.gob_number < (pInfo->VisualObject.VideoObject.VideoObjectPlaneH263.num_gobs_in_vop - 1)) { +ErrRet_1: + if (mp4_CheckDecodeGOB_SVH(pInfo) != MP4_STATUS_OK) + goto Err_1; + if (!pInfo->VisualObject.VideoObject.VideoObjectPlaneH263.gob_header_empty) + { + quant = pInfo->VisualObject.VideoObject.VideoObjectPlaneH263.quant_scale; + i = pInfo->VisualObject.VideoObject.VideoObjectPlaneH263.gob_number * pInfo->VisualObject.VideoObject.VideoObjectPlaneH263.num_rows_in_gob; + mp4_CopyMacroBlocks(pInfo->VisualObject.rFrame, pInfo->VisualObject.cFrame, mbPerRow, rowNum, colNum, (i - rowNum) * mbPerRow - colNum); + rowNum = i; + colNum = 0; + pFc[0] = pInfo->VisualObject.cFrame->pY + i * stepYc * 16; pFc[1] = pFc[0] + 8; pFc[2] = pFc[0] + 8 * stepYc; pFc[3] = pFc[2] + 8; + pFc[4] = pInfo->VisualObject.cFrame->pCb + i * stepCbc * 8; pFc[5] = pInfo->VisualObject.cFrame->pCr + i * stepCrc * 8; + } + nmbgob = 0; + } + } + mp4_AlignBits(pInfo); + return sts; +Err_1: + sts = MP4_STATUS_ERROR; + if (pInfo->stopOnErr) + return sts; + if (!mp4_SeekGOBMarker(pInfo)) + { + mp4_CopyMacroBlocks(pInfo->VisualObject.rFrame, pInfo->VisualObject.cFrame, mbPerRow, rowNum, colNum, pInfo->VisualObject.VideoObject.MacroBlockPerVOP - rowNum * mbPerRow - colNum); + return sts; + } + goto ErrRet_1; + } + quant = pInfo->VisualObject.VideoObject.VideoObjectPlane.quant; + if (pInfo->VisualObject.VideoObject.sprite_enable != MP4_SPRITE_STATIC) + ippsZero_8u((uint8_t*)pInfo->VisualObject.VideoObject.MBinfo, nmb * sizeof(mp4_MacroBlock)); +// decode data_partitioned I-VOP + if (pInfo->VisualObject.VideoObject.data_partitioned) + { + mp4_DataPartMacroBlock *pMBdp; + + for (;;) + { + // reset Intra prediction buffer on new Video_packet + mp4_ResetIntraPredBuffer(pInfo); + mbInVideoPacket = 0; + pMBdp = &pInfo->VisualObject.VideoObject.DataPartBuff[mbCurr]; + // decode mb_type/cbpc/dquant/DC part + for (;;) + { + if (mp4_DecodeMCBPC_I(pInfo, &mb_type, &cbpc) != MP4_STATUS_OK) + goto Err_2; + if (mb_type != IPPVC_MB_STUFFING) + { + if (mbInVideoPacket == nmb - mbCurr) + { + mp4_Error("DC Marker missed"); + goto Err_2; + } + quantPred = quant; + if (mb_type == IPPVC_MBTYPE_INTRA_Q) + mp4_UpdateQuant(pInfo, quant); + if (mbInVideoPacket == 0) + quantPred = quant; + dcVLC = (quantPred < mp4_DC_vlc_Threshold[pInfo->VisualObject.VideoObject.VideoObjectPlane.intra_dc_vlc_thr]) ? 1 : 0; + if (dcVLC) { + for (i = 0; i < 6; i ++) { + if (ippiDecodeDCIntra_MPEG4_1u16s(&pInfo->bufptr, &pInfo->bitoff, &pMBdp->dct_dc[i], (i < 4) ? IPPVC_BLOCK_LUMA : IPPVC_BLOCK_CHROMA) != ippStsNoErr) + goto Err_2; + } + } + pMBdp->quant = (uint8_t)quant; + pMBdp->type = (uint8_t)mb_type; + pMBdp->pat = (uint8_t)cbpc; + pMBdp ++; + mbInVideoPacket ++; + } + if (mp4_ShowBits(pInfo, 19) == MP4_DC_MARKER) + { + mp4_GetBits(pInfo, 19); + break; + } + } + pMBdp = &pInfo->VisualObject.VideoObject.DataPartBuff[mbCurr]; + // decode ac_pred_flag/cbpy part + for (i = 0; i < mbInVideoPacket; i ++) + { + pMBdp[i].ac_pred_flag = (uint8_t)mp4_GetBit(pInfo); + if (mp4_DecodeCBPY_I(pInfo, &cbpy) != MP4_STATUS_OK) + { + if (pInfo->stopOnErr) + goto Err_2; + for (j = i + 1; j < mbInVideoPacket; j ++) + pMBdp[j].ac_pred_flag = 1; + break; + } + pMBdp[i].pat = (uint8_t)((cbpy << 2) + pMBdp[i].pat); + } + // decode AC part and reconstruct macroblocks + for (i = 0; i < mbInVideoPacket; i ++) { + if (colNum == 0) { + // reset B-prediction blocks on new row + mp4_ResetIntraPredBblock(pInfo); + } + quant = pMBdp[i].quant; + quantPred = (i == 0) ? quant : pMBdp[i-1].quant; + dcVLC = (quantPred < mp4_DC_vlc_Threshold[pInfo->VisualObject.VideoObject.VideoObjectPlane.intra_dc_vlc_thr]) ? 1 : 0; + ac_pred_flag = pMBdp[i].ac_pred_flag; + if (mp4_DecodeIntraMB_DP(pInfo, pMBdp[i].dct_dc, colNum, pMBdp[i].pat, quant, dcVLC, ac_pred_flag, pFc, stepFc) != MP4_STATUS_OK) + //if (!pInfo->VisualObject.VideoObject.reversible_vlc) + goto Err_2; + //else + // goto Err_RVLC; + colNum ++; + if (colNum == mbPerRow) + { + colNum = 0; + rowNum ++; + if (rowNum == mbPerCol) + return sts; + pFc[0] += (2 * MP4_NUM_EXT_MB + 1) * 16 + (stepYc << 4) - stepYc; + pFc[1] += (2 * MP4_NUM_EXT_MB + 1) * 16 + (stepYc << 4) - stepYc; + pFc[2] += (2 * MP4_NUM_EXT_MB + 1) * 16 + (stepYc << 4) - stepYc; + pFc[3] += (2 * MP4_NUM_EXT_MB + 1) * 16 + (stepYc << 4) - stepYc; + pFc[4] += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCbc << 3) - stepCbc; + pFc[5] += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCrc << 3) - stepCrc; + } + else + { + pFc[0] += 16; pFc[1] += 16; pFc[2] += 16; pFc[3] += 16; pFc[4] += 8; pFc[5] += 8; + } + } + mbCurr += mbInVideoPacket; + if (!pInfo->VisualObject.VideoObject.resync_marker_disable) + { + int32_t found; +ErrRet_2: + if (mp4_CheckDecodeVideoPacket(pInfo, &found) == MP4_STATUS_OK) + { + if (found) + { + quant = pInfo->VisualObject.VideoObject.VideoObjectPlane.quant_scale; + mbCurr = pInfo->VisualObject.VideoObject.VideoObjectPlane.macroblock_num; + mp4_CopyMacroBlocks(pInfo->VisualObject.rFrame, pInfo->VisualObject.cFrame, mbPerRow, rowNum, colNum, mbCurr - rowNum * mbPerRow - colNum); + rowNum = mbCurr / mbPerRow; + colNum = mbCurr % mbPerRow; + pFc[0] = pInfo->VisualObject.cFrame->pY + (rowNum * stepYc + colNum) * 16; pFc[1] = pFc[0] + 8; pFc[2] = pFc[0] + stepYc * 8; pFc[3] = pFc[2] + 8; + pFc[4] = pInfo->VisualObject.cFrame->pCb + (rowNum * stepCbc + colNum) * 8; pFc[5] = pInfo->VisualObject.cFrame->pCr + (rowNum * stepCrc + colNum) * 8; + } + else + goto Err_2; + } + else + goto Err_2; + } + } +Err_2: + sts = MP4_STATUS_ERROR; + if (pInfo->stopOnErr) + return sts; + if (pInfo->VisualObject.VideoObject.resync_marker_disable || !mp4_SeekResyncMarker(pInfo)) + { + mp4_CopyMacroBlocks(pInfo->VisualObject.rFrame, pInfo->VisualObject.cFrame, mbPerRow, rowNum, colNum, pInfo->VisualObject.VideoObject.MacroBlockPerVOP - rowNum * mbPerRow - colNum); + return sts; + } + goto ErrRet_2; +#if 0 +Err_RVLC: + { + uint8_t *sBufptr = pInfo->bufptr; + int32_t sBitoff = pInfo->bitoff; + + pInfo->bitoff --; + if (pInfo->bitoff == -1) { + pInfo->bitoff = 7; + pInfo->bufptr --; + } + // decode AC part and reconstruct macroblocks + for (j = mbInVideoPacket - 1; j >= i; j --) { + int32_t lnz, quantPred, dcVLC; + + quantPred = ((j == 0) ? pMBdp[j].quant : pMBdp[j-1].quant); + dcVLC = (quantPred < mp4_DC_vlc_Threshold[pInfo->VisualObject.VideoObject.VideoObjectPlane.intra_dc_vlc_thr]) ? 1 : 0; + if (ippiDecodeCoeffsIntraRVLCBack_MPEG4_1u16s(&pInfo->bufptr, &pInfo->bitoff, pDCTdp[j*64*6], &lnz, dcVLC) != ippStsNoErr) + break; + } + pInfo->bufptr = sBufptr; + pInfo->bitoff = sBitoff; + } + goto ErrRet_2; +#endif + } +// decode not data partitioned I-VOP + else { + int32_t stepY = stepYc, dct_type = 0, pYoff23 = 8 * stepYc; + for (;;) { + // reset Intra prediction buffer on new Video_packet + mp4_ResetIntraPredBuffer(pInfo); + mbInVideoPacket = 0; + // decode blocks + for (;;) { + if (colNum == 0) { + // reset B-prediction blocks on new row + mp4_ResetIntraPredBblock(pInfo); + } + if (mp4_DecodeMCBPC_I(pInfo, &mb_type, &cbpc) != MP4_STATUS_OK) + goto Err_3; + if (mb_type != IPPVC_MB_STUFFING) { + ac_pred_flag = mp4_GetBit(pInfo); + if (mp4_DecodeCBPY_I(pInfo, &cbpy) != MP4_STATUS_OK) + goto Err_3; + quantPred = quant; + if (mb_type == IPPVC_MBTYPE_INTRA_Q) + mp4_UpdateQuant(pInfo, quant); + if (mbInVideoPacket == 0) + quantPred = quant; + dcVLC = (quantPred < mp4_DC_vlc_Threshold[pInfo->VisualObject.VideoObject.VideoObjectPlane.intra_dc_vlc_thr]) ? 1 : 0; + if (pInfo->VisualObject.VideoObject.interlaced) { + dct_type = mp4_GetBit(pInfo); + if (dct_type) { + stepY = stepYc * 2; + pYoff23 = stepYc; + } else { + stepY = stepYc; + pYoff23 = 8 * stepYc; + } + stepFc[0] = stepFc[1] = stepFc[2] = stepFc[3] = stepY; + } + pFc[2] = pFc[0] + pYoff23; pFc[3] = pFc[1] + pYoff23; + if (mp4_DecodeIntraMB(pInfo, colNum, (cbpy << 2) + cbpc, quant, dcVLC, ac_pred_flag, pFc, stepFc) != MP4_STATUS_OK) + goto Err_3; + mbInVideoPacket ++; + colNum ++; + if (colNum == mbPerRow) { + colNum = 0; + rowNum ++; + if (rowNum == mbPerCol) { + // skip stuffing + while (mp4_ShowBits9(pInfo, 9) == 1) + mp4_FlushBits(pInfo, 9); + return sts; + } + pFc[0] += (2 * MP4_NUM_EXT_MB + 1) * 16 + (stepYc << 4) - stepYc; + pFc[1] += (2 * MP4_NUM_EXT_MB + 1) * 16 + (stepYc << 4) - stepYc; + pFc[4] += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCbc << 3) - stepCbc; + pFc[5] += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCrc << 3) - stepCrc; + } else { + pFc[0] += 16; pFc[1] += 16; pFc[4] += 8; pFc[5] += 8; + } + } + if (!pInfo->VisualObject.VideoObject.resync_marker_disable) + { + int32_t found; +ErrRet_3: + if (mp4_CheckDecodeVideoPacket(pInfo, &found) == MP4_STATUS_OK) + { + if (found) + { + quant = pInfo->VisualObject.VideoObject.VideoObjectPlane.quant_scale; + mbCurr = pInfo->VisualObject.VideoObject.VideoObjectPlane.macroblock_num; + mp4_CopyMacroBlocks(pInfo->VisualObject.rFrame, pInfo->VisualObject.cFrame, mbPerRow, rowNum, colNum, mbCurr - rowNum * mbPerRow - colNum); + rowNum = mbCurr / mbPerRow; + colNum = mbCurr % mbPerRow; + pFc[0] = pInfo->VisualObject.cFrame->pY + (rowNum * stepYc + colNum) * 16; pFc[1] = pFc[0] + 8; + pFc[4] = pInfo->VisualObject.cFrame->pCb + (rowNum * stepCbc + colNum) * 8; pFc[5] = pInfo->VisualObject.cFrame->pCr + (rowNum * stepCrc + colNum) * 8; + break; + } + } + else + goto Err_3; + } + } + } +Err_3: + sts = MP4_STATUS_ERROR; + if (pInfo->stopOnErr) + return sts; + if (pInfo->VisualObject.VideoObject.resync_marker_disable || !mp4_SeekResyncMarker(pInfo)) + { + mp4_CopyMacroBlocks(pInfo->VisualObject.rFrame, pInfo->VisualObject.cFrame, mbPerRow, rowNum, colNum, pInfo->VisualObject.VideoObject.MacroBlockPerVOP - rowNum * mbPerRow - colNum); + return sts; + } + goto ErrRet_3; + } +} + + |