aboutsummaryrefslogtreecommitdiff
path: root/Src/mpeg4dec/mp4decvopi.c
diff options
context:
space:
mode:
Diffstat (limited to 'Src/mpeg4dec/mp4decvopi.c')
-rw-r--r--Src/mpeg4dec/mp4decvopi.c408
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;
+ }
+}
+
+