| /* ------------------------------------------------------------------ |
| * Copyright (C) 1998-2009 PacketVideo |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either |
| * express or implied. |
| * See the License for the specific language governing permissions |
| * and limitations under the License. |
| * ------------------------------------------------------------------- |
| */ |
| #include "mp4dec_lib.h" /* video decoder function prototypes */ |
| #include "vlc_decode.h" |
| #include "bitstream.h" |
| #include "scaling.h" |
| #include "mbtype_mode.h" |
| |
| #define OSCL_DISABLE_WARNING_CONDITIONAL_IS_CONSTANT |
| /* ======================================================================== */ |
| /* Function : DecodeFrameCombinedMode() */ |
| /* Purpose : Decode a frame of MPEG4 bitstream in combined mode. */ |
| /* In/out : */ |
| /* Return : */ |
| /* Modified : */ |
| /* */ |
| /* 03/30/2000 : Cleaned up and optimized the code. */ |
| /* 03/31/2000 : Added proper handling of MB stuffing. */ |
| /* 04/13/2000 : Rewrote this combined mode path completely */ |
| /* so that it handles "Combined Mode With Error */ |
| /* Resilience." Now the code resembles the */ |
| /* pseudo codes in MPEG-4 standard better. */ |
| /* 10/13/2000 : Add fast VLC+dequant */ |
| /* 04/13/2001 : fix MB_stuffing */ |
| /* 08/07/2001 : remove MBzero */ |
| /* ======================================================================== */ |
| PV_STATUS DecodeFrameCombinedMode(VideoDecData *video) |
| { |
| PV_STATUS status; |
| int mbnum; |
| Vop *currVop = video->currVop; |
| BitstreamDecVideo *stream = video->bitstream; |
| int shortVideoHeader = video->shortVideoHeader; |
| int16 QP, *QPMB = video->QPMB; |
| uint8 *Mode = video->headerInfo.Mode; |
| int nTotalMB = video->nTotalMB; |
| int nMBPerRow = video->nMBPerRow; |
| int slice_counter; |
| uint32 tmpvar, long_zero_bits; |
| uint code; |
| int valid_stuffing; |
| int resync_marker_length; |
| int stuffing_length; |
| |
| /* add this for error resilient, 05/18/2000 */ |
| int32 startPacket; |
| int mb_start; |
| /* copy and pad to prev_Vop for INTER coding */ |
| switch (currVop->predictionType) |
| { |
| case I_VOP : |
| // oscl_memset(Mode, MODE_INTRA, sizeof(uint8)*nTotalMB); |
| resync_marker_length = 17; |
| stuffing_length = 9; |
| break; |
| case P_VOP : |
| oscl_memset(video->motX, 0, sizeof(MOT)*4*nTotalMB); |
| oscl_memset(video->motY, 0, sizeof(MOT)*4*nTotalMB); |
| // oscl_memset(Mode, MODE_INTER, sizeof(uint8)*nTotalMB); |
| resync_marker_length = 16 + currVop->fcodeForward; |
| stuffing_length = 10; |
| break; |
| default : |
| mp4dec_log("DecodeFrameCombinedMode(): Vop type not supported.\n"); |
| return PV_FAIL; |
| } |
| #ifdef PV_ANNEX_IJKT_SUPPORT |
| if (video->shortVideoHeader) |
| { |
| if (video->advanced_INTRA) |
| { |
| if (video->modified_quant) |
| { |
| video->vlcDecCoeffIntra = &VlcDecTCOEFShortHeader_AnnexIT; |
| video->vlcDecCoeffInter = &VlcDecTCOEFShortHeader_AnnexT; |
| } |
| else |
| { |
| video->vlcDecCoeffIntra = &VlcDecTCOEFShortHeader_AnnexI; |
| video->vlcDecCoeffInter = &VlcDecTCOEFShortHeader; |
| } |
| } |
| else |
| { |
| if (video->modified_quant) |
| { |
| video->vlcDecCoeffInter = video->vlcDecCoeffIntra = &VlcDecTCOEFShortHeader_AnnexT; |
| } |
| else |
| { |
| video->vlcDecCoeffInter = video->vlcDecCoeffIntra = &VlcDecTCOEFShortHeader; |
| } |
| } |
| } |
| |
| #endif |
| |
| /** Initialize sliceNo ***/ |
| mbnum = slice_counter = 0; |
| // oscl_memset(video->sliceNo, 0, sizeof(uint8)*nTotalMB); |
| QP = video->currVop->quantizer; |
| |
| do |
| { |
| /* This section is equivalent to motion_shape_texture() */ |
| /* in the MPEG-4 standard. 04/13/2000 */ |
| mb_start = mbnum; |
| video->usePrevQP = 0; /* 04/27/01 */ |
| startPacket = getPointer(stream); |
| |
| #ifdef PV_ANNEX_IJKT_SUPPORT |
| if (video->modified_quant) |
| { |
| video->QP_CHR = MQ_chroma_QP_table[QP]; |
| } |
| else |
| { |
| video->QP_CHR = QP; /* ANNEX_T */ |
| } |
| #endif |
| /* remove any stuffing bits */ |
| BitstreamShowBits16(stream, stuffing_length, &code); |
| while (code == 1) |
| { |
| PV_BitstreamFlushBits(stream, stuffing_length); |
| BitstreamShowBits16(stream, stuffing_length, &code); |
| } |
| |
| do |
| { |
| /* we need video->mbnum in lower level functions */ |
| video->mbnum = mbnum; |
| video->mbnum_row = PV_GET_ROW(mbnum, nMBPerRow); |
| video->mbnum_col = mbnum - video->mbnum_row * nMBPerRow; |
| /* assign slice number for each macroblocks */ |
| video->sliceNo[mbnum] = (uint8) slice_counter; |
| |
| /* decode COD, MCBPC, ACpred_flag, CPBY and DQUANT */ |
| /* We have to discard stuffed MB header */ |
| status = GetMBheader(video, &QP); |
| |
| if (status != PV_SUCCESS) |
| { |
| VideoDecoderErrorDetected(video); |
| video->mbnum = mb_start; |
| movePointerTo(stream, (startPacket & -8)); |
| break; |
| } |
| |
| /* Store the QP value for later use in AC prediction */ |
| QPMB[mbnum] = QP; |
| |
| if (Mode[mbnum] != MODE_SKIPPED) |
| { |
| /* decode the DCT coeficients for the MB */ |
| status = GetMBData(video); |
| if (status != PV_SUCCESS) |
| { |
| VideoDecoderErrorDetected(video); |
| video->mbnum = mb_start; |
| movePointerTo(stream, (startPacket & -8)); |
| break; |
| } |
| } |
| else /* MODE_SKIPPED */ |
| { |
| SkippedMBMotionComp(video); /* 08/04/05 */ |
| } |
| // Motion compensation and put video->mblock->pred_block |
| mbnum++; |
| |
| /* remove any stuffing bits */ |
| BitstreamShowBits16(stream, stuffing_length, &code); |
| while (code == 1) |
| { |
| PV_BitstreamFlushBits(stream, stuffing_length); |
| BitstreamShowBits16(stream, stuffing_length, &code); |
| } |
| |
| /* have we reached the end of the video packet or vop? */ |
| if (shortVideoHeader) |
| { |
| #ifdef PV_ANNEX_IJKT_SUPPORT |
| if (!video->slice_structure) |
| { |
| #endif |
| if (mbnum >= (int)(video->mbnum_row + 1)*video->nMBinGOB) /* 10/11/01 */ |
| { |
| if (mbnum >= nTotalMB) return PV_SUCCESS; |
| status = BitstreamShowBits32(stream, GOB_RESYNC_MARKER_LENGTH, &tmpvar); |
| |
| if (tmpvar == GOB_RESYNC_MARKER) |
| { |
| break; |
| } |
| else |
| { |
| status = PV_BitstreamShowBitsByteAlign(stream, GOB_RESYNC_MARKER_LENGTH, &tmpvar); |
| if (tmpvar == GOB_RESYNC_MARKER) break; |
| } |
| } |
| #ifdef PV_ANNEX_IJKT_SUPPORT |
| } |
| else |
| { |
| |
| if (mbnum >= nTotalMB) /* in case no valid stuffing 06/23/01 */ |
| { |
| valid_stuffing = validStuffing_h263(stream); |
| if (valid_stuffing == 0) |
| { |
| VideoDecoderErrorDetected(video); |
| ConcealPacket(video, mb_start, nTotalMB, slice_counter); |
| } |
| return PV_SUCCESS; |
| } |
| /* ANNEX_K */ |
| PV_BitstreamShowBitsByteAlignNoForceStuffing(stream, 17, &tmpvar); |
| if (tmpvar == RESYNC_MARKER) |
| { |
| valid_stuffing = validStuffing_h263(stream); |
| if (valid_stuffing) |
| break; /* 06/21/01 */ |
| } |
| |
| } |
| #endif |
| } |
| else |
| { |
| if (mbnum >= nTotalMB) /* in case no valid stuffing 06/23/01 */ |
| { |
| /* 11/01/2002 if we are at the end of the frame and there is some garbage data |
| at the end of the frame (i.e. no next startcode) break if the stuffing is valid */ |
| valid_stuffing = validStuffing(stream); |
| if (valid_stuffing == 0) |
| { |
| /* end 11/01/2002 */ |
| VideoDecoderErrorDetected(video); |
| ConcealPacket(video, mb_start, nTotalMB, slice_counter); |
| } |
| PV_BitstreamByteAlign(stream); |
| return PV_SUCCESS; |
| } |
| |
| status = PV_BitstreamShowBitsByteAlign(stream, 23, &tmpvar); /* this call is valid for f_code < 8 */ |
| long_zero_bits = !tmpvar; |
| |
| if ((tmpvar >> (23 - resync_marker_length)) == RESYNC_MARKER || long_zero_bits) |
| { |
| valid_stuffing = validStuffing(stream); |
| if (valid_stuffing) |
| break; /* 06/21/01 */ |
| } |
| |
| } |
| } |
| while (TRUE); |
| |
| if (shortVideoHeader) |
| { /* We need to check newgob to refresh quantizer */ |
| #ifdef PV_ANNEX_IJKT_SUPPORT |
| if (!video->slice_structure) |
| { |
| #endif |
| while ((status = PV_GobHeader(video)) == PV_FAIL) |
| { |
| if ((status = quickSearchGOBHeader(stream)) != PV_SUCCESS) |
| { |
| break; |
| } |
| } |
| |
| mbnum = currVop->gobNumber * video->nMBinGOB; |
| #ifdef PV_ANNEX_IJKT_SUPPORT |
| } |
| else |
| { |
| while ((status = PV_H263SliceHeader(video, &mbnum)) == PV_FAIL) |
| { |
| if ((status = quickSearchH263SliceHeader(stream)) != PV_SUCCESS) |
| { |
| break; |
| } |
| } |
| } |
| |
| #endif |
| } |
| else |
| { |
| while ((status = PV_ReadVideoPacketHeader(video, &mbnum)) == PV_FAIL) |
| { |
| if ((status = quickSearchVideoPacketHeader(stream, resync_marker_length)) != PV_SUCCESS) |
| { |
| break; |
| } |
| } |
| } |
| |
| if (status == PV_END_OF_VOP) |
| { |
| mbnum = nTotalMB; |
| } |
| |
| if (mbnum > video->mbnum + 1) |
| { |
| ConcealPacket(video, video->mbnum, mbnum, slice_counter); |
| } |
| QP = video->currVop->quantizer; |
| slice_counter++; |
| if (mbnum >= nTotalMB) break; |
| |
| } |
| while (TRUE); |
| return PV_SUCCESS; |
| } |
| |
| |
| /* ============================================================================ */ |
| /* Function : GetMBHeader() */ |
| /* Purpose : Decode MB header, not_coded, mcbpc, ac_pred_flag, cbpy, dquant. */ |
| /* In/out : */ |
| /* Return : */ |
| /* Modified : */ |
| /* */ |
| /* 3/29/00 : Changed the returned value and optimized the code. */ |
| /* 4/01/01 : new ACDC prediction structure */ |
| /* ============================================================================ */ |
| PV_STATUS GetMBheader(VideoDecData *video, int16 *QP) |
| { |
| BitstreamDecVideo *stream = video->bitstream; |
| int mbnum = video->mbnum; |
| uint8 *Mode = video->headerInfo.Mode; |
| int x_pos = video->mbnum_col; |
| typeDCStore *DC = video->predDC + mbnum; |
| typeDCACStore *DCAC_row = video->predDCAC_row + x_pos; |
| typeDCACStore *DCAC_col = video->predDCAC_col; |
| const static int16 DQ_tab[4] = { -1, -2, 1, 2}; |
| |
| int CBPY, CBPC; |
| int MBtype, VopType; |
| int MCBPC; |
| uint DQUANT; |
| int comp; |
| Bool mb_coded; |
| |
| VopType = video->currVop->predictionType; |
| mb_coded = ((VopType == I_VOP) ? TRUE : !BitstreamRead1Bits_INLINE(stream)); |
| |
| if (!mb_coded) |
| { |
| /* skipped macroblock */ |
| Mode[mbnum] = MODE_SKIPPED; |
| //oscl_memset(DCAC_row, 0, sizeof(typeDCACStore)); /* SKIPPED_ACDC */ |
| //oscl_memset(DCAC_col, 0, sizeof(typeDCACStore)); |
| ZERO_OUT_64BYTES(DCAC_row); |
| ZERO_OUT_64BYTES(DCAC_col); /* 08/12/05 */ |
| |
| for (comp = 0; comp < 6; comp++) |
| { |
| (*DC)[comp] = mid_gray; |
| } |
| } |
| else |
| { |
| /* coded macroblock */ |
| if (VopType == I_VOP) |
| { |
| MCBPC = PV_VlcDecMCBPC_com_intra(stream); |
| } |
| else |
| { |
| #ifdef PV_ANNEX_IJKT_SUPPORT |
| if (!video->deblocking) |
| { |
| MCBPC = PV_VlcDecMCBPC_com_inter(stream); |
| } |
| else |
| { |
| MCBPC = PV_VlcDecMCBPC_com_inter_H263(stream); |
| } |
| #else |
| MCBPC = PV_VlcDecMCBPC_com_inter(stream); |
| #endif |
| } |
| |
| if (VLC_ERROR_DETECTED(MCBPC)) |
| { |
| return PV_FAIL; |
| } |
| |
| Mode[mbnum] = (uint8)(MBtype = MBtype_mode[MCBPC & 7]); |
| CBPC = (MCBPC >> 4) & 3; |
| |
| #ifdef PV_ANNEX_IJKT_SUPPORT |
| if (MBtype & INTRA_MASK) |
| { |
| if (!video->shortVideoHeader) |
| { |
| video->acPredFlag[mbnum] = (uint8) BitstreamRead1Bits(stream); |
| } |
| else |
| { |
| if (video->advanced_INTRA) |
| { |
| if (!BitstreamRead1Bits(stream)) |
| { |
| video->acPredFlag[mbnum] = 0; |
| } |
| else |
| { |
| video->acPredFlag[mbnum] = 1; |
| if (BitstreamRead1Bits(stream)) |
| { |
| video->mblock->direction = 0; |
| } |
| else |
| { |
| video->mblock->direction = 1; |
| } |
| } |
| } |
| else |
| { |
| video->acPredFlag[mbnum] = 0; |
| } |
| } |
| } |
| #else |
| if ((MBtype & INTRA_MASK) && !video->shortVideoHeader) |
| { |
| video->acPredFlag[mbnum] = (uint8) BitstreamRead1Bits_INLINE(stream); |
| } |
| else |
| { |
| video->acPredFlag[mbnum] = 0; |
| } |
| #endif |
| CBPY = PV_VlcDecCBPY(stream, MBtype & INTRA_MASK); /* INTRA || INTRA_Q */ |
| if (CBPY < 0) |
| { |
| return PV_FAIL; |
| } |
| |
| // GW 04/23/99 |
| video->headerInfo.CBP[mbnum] = (uint8)(CBPY << 2 | (CBPC & 3)); |
| #ifdef PV_ANNEX_IJKT_SUPPORT |
| if (MBtype & Q_MASK) |
| { |
| if (!video->modified_quant) |
| { |
| DQUANT = BitstreamReadBits16(stream, 2); |
| *QP += DQ_tab[DQUANT]; |
| |
| if (*QP < 1) *QP = 1; |
| else if (*QP > 31) *QP = 31; |
| video->QP_CHR = *QP; /* ANNEX_T */ |
| } |
| else |
| { |
| if (BitstreamRead1Bits(stream)) |
| { |
| if (BitstreamRead1Bits(stream)) |
| { |
| *QP += DQ_tab_Annex_T_11[*QP]; |
| } |
| else |
| { |
| *QP += DQ_tab_Annex_T_10[*QP]; |
| } |
| if (*QP < 1) *QP = 1; |
| else if (*QP > 31) *QP = 31; |
| } |
| else |
| { |
| *QP = (int16)BitstreamReadBits16(stream, 5); |
| } |
| video->QP_CHR = MQ_chroma_QP_table[*QP]; |
| } |
| } |
| #else |
| if (MBtype & Q_MASK) |
| { |
| DQUANT = BitstreamReadBits16(stream, 2); |
| *QP += DQ_tab[DQUANT]; |
| |
| if (*QP < 1) *QP = 1; |
| else if (*QP > 31) *QP = 31; |
| } |
| #endif |
| } |
| return PV_SUCCESS; |
| } |
| |
| |
| |
| |
| |
| /***********************************************************CommentBegin****** |
| * 3/10/00 : initial modification to the |
| * new PV-Decoder Lib format. |
| * 4/2/2000 : Cleanup and error-handling modification. This |
| * function has been divided into several sub-functions for |
| * better coding style and maintainance reason. I also |
| * greatly shrunk the code size here. |
| * 9/18/2000 : VlcDecode+Dequant optimization * |
| * 4/01/2001 : new ACDC prediction structure |
| * 3/29/2002 : removed GetIntraMB and GetInterMB |
| ***********************************************************CommentEnd********/ |
| PV_STATUS GetMBData(VideoDecData *video) |
| { |
| BitstreamDecVideo *stream = video->bitstream; |
| int mbnum = video->mbnum; |
| MacroBlock *mblock = video->mblock; |
| int16 *dataBlock; |
| PIXEL *c_comp; |
| uint mode = video->headerInfo.Mode[mbnum]; |
| uint CBP = video->headerInfo.CBP[mbnum]; |
| typeDCStore *DC = video->predDC + mbnum; |
| int intra_dc_vlc_thr = video->currVop->intraDCVlcThr; |
| int16 QP = video->QPMB[mbnum]; |
| int16 QP_tmp = QP; |
| int width = video->width; |
| int comp; |
| int switched; |
| int ncoeffs[6] = {0, 0, 0, 0, 0, 0}; |
| int *no_coeff = mblock->no_coeff; |
| int16 DC_coeff; |
| PV_STATUS status; |
| |
| #ifdef PV_POSTPROC_ON |
| /* post-processing */ |
| uint8 *pp_mod[6]; |
| int TotalMB = video->nTotalMB; |
| int MB_in_width = video->nMBPerRow; |
| #endif |
| int y_pos = video->mbnum_row; |
| int x_pos = video->mbnum_col; |
| int32 offset = (int32)(y_pos << 4) * width + (x_pos << 4); |
| |
| /* Decode each 8-by-8 blocks. comp 0 ~ 3 are luminance blocks, 4 ~ 5 */ |
| /* are chrominance blocks. 04/03/2000. */ |
| #ifdef PV_POSTPROC_ON |
| if (video->postFilterType != PV_NO_POST_PROC) |
| { |
| /** post-processing ***/ |
| pp_mod[0] = video->pstprcTypCur + (y_pos << 1) * (MB_in_width << 1) + (x_pos << 1); |
| pp_mod[1] = pp_mod[0] + 1; |
| pp_mod[2] = pp_mod[0] + (MB_in_width << 1); |
| pp_mod[3] = pp_mod[2] + 1; |
| pp_mod[4] = video->pstprcTypCur + (TotalMB << 2) + mbnum; |
| pp_mod[5] = pp_mod[4] + TotalMB; |
| } |
| #endif |
| |
| /* oscl_memset(mblock->block, 0, sizeof(typeMBStore)); Aug 9,2005 */ |
| |
| if (mode & INTRA_MASK) /* MODE_INTRA || MODE_INTRA_Q */ |
| { |
| switched = 0; |
| if (intra_dc_vlc_thr) |
| { |
| if (video->usePrevQP) |
| QP_tmp = video->QPMB[mbnum-1]; /* running QP 04/26/01 */ |
| |
| switched = (intra_dc_vlc_thr == 7 || QP_tmp >= intra_dc_vlc_thr * 2 + 11); |
| } |
| |
| mblock->DCScalarLum = cal_dc_scaler(QP, LUMINANCE_DC_TYPE); /* 3/01/01 */ |
| mblock->DCScalarChr = cal_dc_scaler(QP, CHROMINANCE_DC_TYPE); |
| |
| for (comp = 0; comp < 6; comp++) |
| { |
| dataBlock = mblock->block[comp]; /* 10/20/2000 */ |
| |
| if (video->shortVideoHeader) |
| { |
| #ifdef PV_ANNEX_IJKT_SUPPORT |
| if (!video->advanced_INTRA) |
| { |
| #endif |
| DC_coeff = (int16) BitstreamReadBits16_INLINE(stream, 8); |
| |
| if ((DC_coeff & 0x7f) == 0) /* 128 & 0 */ |
| { |
| /* currently we will only signal FAIL for 128. We will ignore the 0 case */ |
| if (DC_coeff == 128) |
| { |
| return PV_FAIL; |
| } |
| else |
| { |
| VideoDecoderErrorDetected(video); |
| } |
| } |
| if (DC_coeff == 255) |
| { |
| DC_coeff = 128; |
| } |
| dataBlock[0] = (int16) DC_coeff; |
| #ifdef PV_ANNEX_IJKT_SUPPORT |
| } |
| #endif |
| ncoeffs[comp] = VlcDequantH263IntraBlock_SH(video, comp, mblock->bitmapcol[comp], &mblock->bitmaprow[comp]); |
| |
| } |
| else |
| { |
| if (switched == 0) |
| { |
| status = PV_DecodePredictedIntraDC(comp, stream, &DC_coeff); |
| if (status != PV_SUCCESS) return PV_FAIL; |
| |
| dataBlock[0] = (int16) DC_coeff; |
| } |
| ncoeffs[comp] = VlcDequantH263IntraBlock(video, comp, |
| switched, mblock->bitmapcol[comp], &mblock->bitmaprow[comp]); |
| } |
| |
| if (VLC_ERROR_DETECTED(ncoeffs[comp])) |
| { |
| if (switched) |
| return PV_FAIL; |
| else |
| { |
| ncoeffs[comp] = 1; |
| oscl_memset((dataBlock + 1), 0, sizeof(int16)*63); |
| } |
| } |
| no_coeff[comp] = ncoeffs[comp]; |
| |
| #ifdef PV_POSTPROC_ON |
| if (video->postFilterType != PV_NO_POST_PROC) |
| *pp_mod[comp] = (uint8) PostProcSemaphore(dataBlock); |
| #endif |
| } |
| MBlockIDCT(video); |
| } |
| else /* INTER modes */ |
| { /* moved it here Aug 15, 2005 */ |
| /* decode the motion vector (if there are any) */ |
| status = PV_GetMBvectors(video, mode); |
| if (status != PV_SUCCESS) |
| { |
| return status; |
| } |
| |
| |
| MBMotionComp(video, CBP); |
| c_comp = video->currVop->yChan + offset; |
| |
| #ifdef PV_ANNEX_IJKT_SUPPORT |
| for (comp = 0; comp < 4; comp++) |
| { |
| (*DC)[comp] = mid_gray; |
| if (CBP & (1 << (5 - comp))) |
| { |
| ncoeffs[comp] = VlcDequantH263InterBlock(video, comp, mblock->bitmapcol[comp], &mblock->bitmaprow[comp]); |
| if (VLC_ERROR_DETECTED(ncoeffs[comp])) return PV_FAIL; |
| |
| BlockIDCT(c_comp + (comp&2)*(width << 2) + 8*(comp&1), mblock->pred_block + (comp&2)*64 + 8*(comp&1), mblock->block[comp], width, ncoeffs[comp], |
| mblock->bitmapcol[comp], mblock->bitmaprow[comp]); |
| |
| #ifdef PV_POSTPROC_ON |
| /* for inter just test for ringing */ |
| if (video->postFilterType != PV_NO_POST_PROC) |
| *pp_mod[comp] = (uint8)((ncoeffs[comp] > 3) ? 4 : 0); |
| #endif |
| } |
| else |
| { |
| /* no IDCT for all zeros blocks 03/28/2002 */ |
| /* BlockIDCT(); */ |
| #ifdef PV_POSTPROC_ON |
| if (video->postFilterType != PV_NO_POST_PROC) |
| *pp_mod[comp] = 0; |
| #endif |
| } |
| } |
| |
| video->QPMB[mbnum] = video->QP_CHR; /* ANNEX_T */ |
| |
| |
| |
| (*DC)[4] = mid_gray; |
| if (CBP & 2) |
| { |
| ncoeffs[4] = VlcDequantH263InterBlock(video, 4, mblock->bitmapcol[4], &mblock->bitmaprow[4]); |
| if (VLC_ERROR_DETECTED(ncoeffs[4])) return PV_FAIL; |
| |
| BlockIDCT(video->currVop->uChan + (offset >> 2) + (x_pos << 2), mblock->pred_block + 256, mblock->block[4], width >> 1, ncoeffs[4], |
| mblock->bitmapcol[4], mblock->bitmaprow[4]); |
| |
| #ifdef PV_POSTPROC_ON |
| /* for inter just test for ringing */ |
| if (video->postFilterType != PV_NO_POST_PROC) |
| *pp_mod[4] = (uint8)((ncoeffs[4] > 3) ? 4 : 0); |
| #endif |
| } |
| else |
| { |
| /* no IDCT for all zeros blocks 03/28/2002 */ |
| /* BlockIDCT(); */ |
| #ifdef PV_POSTPROC_ON |
| if (video->postFilterType != PV_NO_POST_PROC) |
| *pp_mod[4] = 0; |
| #endif |
| } |
| (*DC)[5] = mid_gray; |
| if (CBP & 1) |
| { |
| ncoeffs[5] = VlcDequantH263InterBlock(video, 5, mblock->bitmapcol[5], &mblock->bitmaprow[5]); |
| if (VLC_ERROR_DETECTED(ncoeffs[5])) return PV_FAIL; |
| |
| BlockIDCT(video->currVop->vChan + (offset >> 2) + (x_pos << 2), mblock->pred_block + 264, mblock->block[5], width >> 1, ncoeffs[5], |
| mblock->bitmapcol[5], mblock->bitmaprow[5]); |
| |
| #ifdef PV_POSTPROC_ON |
| /* for inter just test for ringing */ |
| if (video->postFilterType != PV_NO_POST_PROC) |
| *pp_mod[5] = (uint8)((ncoeffs[5] > 3) ? 4 : 0); |
| #endif |
| } |
| else |
| { |
| /* no IDCT for all zeros blocks 03/28/2002 */ |
| /* BlockIDCT(); */ |
| #ifdef PV_POSTPROC_ON |
| if (video->postFilterType != PV_NO_POST_PROC) |
| *pp_mod[5] = 0; |
| #endif |
| } |
| video->QPMB[mbnum] = QP; /* restore the QP values ANNEX_T*/ |
| #else |
| for (comp = 0; comp < 4; comp++) |
| { |
| (*DC)[comp] = mid_gray; |
| if (CBP & (1 << (5 - comp))) |
| { |
| ncoeffs[comp] = VlcDequantH263InterBlock(video, comp, mblock->bitmapcol[comp], &mblock->bitmaprow[comp]); |
| if (VLC_ERROR_DETECTED(ncoeffs[comp])) return PV_FAIL; |
| |
| BlockIDCT(c_comp + (comp&2)*(width << 2) + 8*(comp&1), mblock->pred_block + (comp&2)*64 + 8*(comp&1), mblock->block[comp], width, ncoeffs[comp], |
| mblock->bitmapcol[comp], mblock->bitmaprow[comp]); |
| |
| #ifdef PV_POSTPROC_ON |
| /* for inter just test for ringing */ |
| if (video->postFilterType != PV_NO_POST_PROC) |
| *pp_mod[comp] = (uint8)((ncoeffs[comp] > 3) ? 4 : 0); |
| #endif |
| } |
| else |
| { |
| /* no IDCT for all zeros blocks 03/28/2002 */ |
| /* BlockIDCT(); */ |
| #ifdef PV_POSTPROC_ON |
| if (video->postFilterType != PV_NO_POST_PROC) |
| *pp_mod[comp] = 0; |
| #endif |
| } |
| } |
| |
| (*DC)[4] = mid_gray; |
| if (CBP & 2) |
| { |
| ncoeffs[4] = VlcDequantH263InterBlock(video, 4, mblock->bitmapcol[4], &mblock->bitmaprow[4]); |
| if (VLC_ERROR_DETECTED(ncoeffs[4])) return PV_FAIL; |
| |
| BlockIDCT(video->currVop->uChan + (offset >> 2) + (x_pos << 2), mblock->pred_block + 256, mblock->block[4], width >> 1, ncoeffs[4], |
| mblock->bitmapcol[4], mblock->bitmaprow[4]); |
| |
| #ifdef PV_POSTPROC_ON |
| /* for inter just test for ringing */ |
| if (video->postFilterType != PV_NO_POST_PROC) |
| *pp_mod[4] = (uint8)((ncoeffs[4] > 3) ? 4 : 0); |
| #endif |
| } |
| else |
| { |
| /* no IDCT for all zeros blocks 03/28/2002 */ |
| /* BlockIDCT(); */ |
| #ifdef PV_POSTPROC_ON |
| if (video->postFilterType != PV_NO_POST_PROC) |
| *pp_mod[4] = 0; |
| #endif |
| } |
| (*DC)[5] = mid_gray; |
| if (CBP & 1) |
| { |
| ncoeffs[5] = VlcDequantH263InterBlock(video, 5, mblock->bitmapcol[5], &mblock->bitmaprow[5]); |
| if (VLC_ERROR_DETECTED(ncoeffs[5])) return PV_FAIL; |
| |
| BlockIDCT(video->currVop->vChan + (offset >> 2) + (x_pos << 2), mblock->pred_block + 264, mblock->block[5], width >> 1, ncoeffs[5], |
| mblock->bitmapcol[5], mblock->bitmaprow[5]); |
| |
| #ifdef PV_POSTPROC_ON |
| /* for inter just test for ringing */ |
| if (video->postFilterType != PV_NO_POST_PROC) |
| *pp_mod[5] = (uint8)((ncoeffs[5] > 3) ? 4 : 0); |
| #endif |
| } |
| else |
| { |
| /* no IDCT for all zeros blocks 03/28/2002 */ |
| /* BlockIDCT(); */ |
| #ifdef PV_POSTPROC_ON |
| if (video->postFilterType != PV_NO_POST_PROC) |
| *pp_mod[5] = 0; |
| #endif |
| #endif // PV_ANNEX_IJKT_SUPPORT |
| |
| |
| |
| |
| |
| |
| } |
| |
| video->usePrevQP = 1; /* should be set after decoding the first Coded 04/27/01 */ |
| return PV_SUCCESS; |
| } |
| |
| |
| |