mfxStatus AVC_Spl::AddSliceNalUnit(mfxBitstream * nalUnit, AVCSlice * slice) { static mfxU8 start_code_prefix[] = {0, 0, 1}; mfxU32 sliceLength = (mfxU32)(nalUnit->DataLength + sizeof(start_code_prefix)); if (m_frame.DataLength + sliceLength >= BUFFER_SIZE) return MFX_ERR_NOT_ENOUGH_BUFFER; MSDK_MEMCPY_BUF(m_frame.Data, m_frame.DataLength, BUFFER_SIZE, start_code_prefix, sizeof(start_code_prefix)); MSDK_MEMCPY_BUF(m_frame.Data, m_frame.DataLength + sizeof(start_code_prefix), BUFFER_SIZE, nalUnit->Data + nalUnit->DataOffset, nalUnit->DataLength); if (!m_frame.SliceNum) { m_frame.TimeStamp = nalUnit->TimeStamp; } m_frame.SliceNum++; if (m_slices.size() <= m_frame.SliceNum) { m_slices.resize(m_frame.SliceNum + 10); m_frame.Slice = &m_slices[0]; } SliceSplitterInfo & newSlice = m_slices[m_frame.SliceNum - 1]; AVCHeadersBitstream * bs = slice->GetBitStream(); newSlice.HeaderLength = (mfxU32)bs->BytesDecoded(); // add number of 003 sequence to HeaderLength for(mfxU8 *ptr = nalUnit->Data + sizeof(start_code_prefix); ptr < nalUnit->Data + sizeof(start_code_prefix) + newSlice.HeaderLength; ptr++) { if (ptr[0]==0 && ptr[1]==0 && ptr[2]==3) { newSlice.HeaderLength++; } } newSlice.HeaderLength += sizeof(start_code_prefix) + 1; newSlice.DataLength = sliceLength; newSlice.DataOffset = m_frame.DataLength; if(IS_I_SLICE(slice->GetSliceHeader()->slice_type)) newSlice.SliceType = TYPE_I; else if(IS_P_SLICE(slice->GetSliceHeader()->slice_type)) newSlice.SliceType = TYPE_P; else if(IS_B_SLICE(slice->GetSliceHeader()->slice_type)) newSlice.SliceType = TYPE_B; m_frame.DataLength += sliceLength; if (!m_currentInfo->m_index) m_frame.FirstFieldSliceNum++; return MFX_ERR_NONE; }
u32 ConcealMb(mbStorage_t *pMb, image_t *currImage, u32 row, u32 col, u32 sliceType, u8 *refData) { /* Variables */ u32 i, j, comp; u32 hor, ver; u32 mbNum; u32 width, height; u8 *mbPos; u8 data[384]; u8 *pData; i32 tmp; i32 firstPhase[16]; i32 *pTmp; /* neighbours above, below, left and right */ i32 a[4] = { 0,0,0,0 }, b[4], l[4] = { 0,0,0,0 }, r[4]; u32 A, B, L, R; #ifdef H264DEC_OMXDL u8 fillBuff[32*21 + 15 + 32]; u8 *pFill; #endif /* Code */ ASSERT(pMb); ASSERT(!pMb->decoded); ASSERT(currImage); ASSERT(col < currImage->width); ASSERT(row < currImage->height); #ifdef H264DEC_OMXDL pFill = ALIGN(fillBuff, 16); #endif width = currImage->width; height = currImage->height; mbNum = row * width + col; h264bsdSetCurrImageMbPointers(currImage, mbNum); mbPos = currImage->data + row * 16 * width * 16 + col * 16; A = B = L = R = HANTRO_FALSE; /* set qpY to 40 to enable some filtering in deblocking (stetson value) */ pMb->qpY = 40; pMb->disableDeblockingFilterIdc = 0; /* mbType set to intra to perform filtering despite the values of other * boundary strength determination fields */ pMb->mbType = I_4x4; pMb->filterOffsetA = 0; pMb->filterOffsetB = 0; pMb->chromaQpIndexOffset = 0; if (IS_I_SLICE(sliceType)) memset(data, 0, sizeof(data)); else { mv_t mv = {0,0}; image_t refImage; refImage.width = width; refImage.height = height; refImage.data = refData; if (refImage.data) { #ifndef H264DEC_OMXDL h264bsdPredictSamples(data, &mv, &refImage, col*16, row*16, 0, 0, 16, 16); #else h264bsdPredictSamples(data, &mv, &refImage, ((row*16) + ((col*16)<<16)), 0x00001010, pFill); #endif h264bsdWriteMacroblock(currImage, data); return(HANTRO_OK); } else memset(data, 0, sizeof(data)); } memset(firstPhase, 0, sizeof(firstPhase)); /* counter for number of neighbours used */ j = 0; hor = ver = 0; if (row && (pMb-width)->decoded) { A = HANTRO_TRUE; pData = mbPos - width*16; a[0] = *pData++; a[0] += *pData++; a[0] += *pData++; a[0] += *pData++; a[1] = *pData++; a[1] += *pData++; a[1] += *pData++; a[1] += *pData++; a[2] = *pData++; a[2] += *pData++; a[2] += *pData++; a[2] += *pData++; a[3] = *pData++; a[3] += *pData++; a[3] += *pData++; a[3] += *pData++; j++; hor++; firstPhase[0] += a[0] + a[1] + a[2] + a[3]; firstPhase[1] += a[0] + a[1] - a[2] - a[3]; } if ((row != height - 1) && (pMb+width)->decoded) { B = HANTRO_TRUE; pData = mbPos + 16*width*16; b[0] = *pData++; b[0] += *pData++; b[0] += *pData++; b[0] += *pData++; b[1] = *pData++; b[1] += *pData++; b[1] += *pData++; b[1] += *pData++; b[2] = *pData++; b[2] += *pData++; b[2] += *pData++; b[2] += *pData++; b[3] = *pData++; b[3] += *pData++; b[3] += *pData++; b[3] += *pData++; j++; hor++; firstPhase[0] += b[0] + b[1] + b[2] + b[3]; firstPhase[1] += b[0] + b[1] - b[2] - b[3]; } if (col && (pMb-1)->decoded) { L = HANTRO_TRUE; pData = mbPos - 1; l[0] = pData[0]; l[0] += pData[16*width]; l[0] += pData[32*width]; l[0] += pData[48*width]; pData += 64*width; l[1] = pData[0]; l[1] += pData[16*width]; l[1] += pData[32*width]; l[1] += pData[48*width]; pData += 64*width; l[2] = pData[0]; l[2] += pData[16*width]; l[2] += pData[32*width]; l[2] += pData[48*width]; pData += 64*width; l[3] = pData[0]; l[3] += pData[16*width]; l[3] += pData[32*width]; l[3] += pData[48*width]; j++; ver++; firstPhase[0] += l[0] + l[1] + l[2] + l[3]; firstPhase[4] += l[0] + l[1] - l[2] - l[3]; } if ((col != width - 1) && (pMb+1)->decoded) { R = HANTRO_TRUE; pData = mbPos + 16; r[0] = pData[0]; r[0] += pData[16*width]; r[0] += pData[32*width]; r[0] += pData[48*width]; pData += 64*width; r[1] = pData[0]; r[1] += pData[16*width]; r[1] += pData[32*width]; r[1] += pData[48*width]; pData += 64*width; r[2] = pData[0]; r[2] += pData[16*width]; r[2] += pData[32*width]; r[2] += pData[48*width]; pData += 64*width; r[3] = pData[0]; r[3] += pData[16*width]; r[3] += pData[32*width]; r[3] += pData[48*width]; j++; ver++; firstPhase[0] += r[0] + r[1] + r[2] + r[3]; firstPhase[4] += r[0] + r[1] - r[2] - r[3]; } /* at least one properly decoded neighbour available */ ASSERT(j); /*lint -esym(644,l,r,a,b) variable initialized above */ if (!hor && L && R) firstPhase[1] = (l[0]+l[1]+l[2]+l[3]-r[0]-r[1]-r[2]-r[3]) >> 5; else if (hor)
u32 h264bsdConceal(storage_t *pStorage, image_t *currImage, u32 sliceType) { /* Variables */ u32 i, j; u32 row, col; u32 width, height; u8 *refData; mbStorage_t *mb; /* Code */ ASSERT(pStorage); ASSERT(currImage); DEBUG(("Concealing %s slice\n", IS_I_SLICE(sliceType) ? "intra" : "inter")); width = currImage->width; height = currImage->height; refData = NULL; /* use reference picture with smallest available index */ if (IS_P_SLICE(sliceType) || (pStorage->intraConcealmentFlag != 0)) { i = 0; do { refData = h264bsdGetRefPicData(pStorage->dpb, i); i++; if (i >= 16) break; } while (refData == NULL); } i = row = col = 0; /* find first properly decoded macroblock -> start point for concealment */ while (i < pStorage->picSizeInMbs && !pStorage->mb[i].decoded) { i++; col++; if (col == width) { row++; col = 0; } } /* whole picture lost -> copy previous or set grey */ if (i == pStorage->picSizeInMbs) { if ( (IS_I_SLICE(sliceType) && (pStorage->intraConcealmentFlag == 0)) || refData == NULL) { memset(currImage->data, 128, width*height*384); } else { #ifndef FLASCC memcpy(currImage->data, refData, width*height*384); #else int ii = 0; int size = width*height*384; u8* curr_data = currImage->data; for (ii = 0; ii < size;ii++) curr_data[i] = refData[i]; #endif } pStorage->numConcealedMbs = pStorage->picSizeInMbs; /* no filtering if whole picture concealed */ for (i = 0; i < pStorage->picSizeInMbs; i++) pStorage->mb[i].disableDeblockingFilterIdc = 1; return(HANTRO_OK); } /* start from the row containing the first correct macroblock, conceal the * row in question, all rows above that row and then continue downwards */ mb = pStorage->mb + row * width; for (j = col; j--;) { ConcealMb(mb+j, currImage, row, j, sliceType, refData); mb[j].decoded = 1; pStorage->numConcealedMbs++; } for (j = col + 1; j < width; j++) { if (!mb[j].decoded) { ConcealMb(mb+j, currImage, row, j, sliceType, refData); mb[j].decoded = 1; pStorage->numConcealedMbs++; } } /* if previous row(s) could not be concealed -> conceal them now */ if (row) { for (j = 0; j < width; j++) { i = row - 1; mb = pStorage->mb + i*width + j; do { ConcealMb(mb, currImage, i, j, sliceType, refData); mb->decoded = 1; pStorage->numConcealedMbs++; mb -= width; } while(i--); } } /* process rows below the one containing the first correct macroblock */ for (i = row + 1; i < height; i++) { mb = pStorage->mb + i * width; for (j = 0; j < width; j++) { if (!mb[j].decoded) { ConcealMb(mb+j, currImage, i, j, sliceType, refData); mb[j].decoded = 1; pStorage->numConcealedMbs++; } } } return(HANTRO_OK); }
u32 h264bsdDecodeSliceData(strmData_t *pStrmData, storage_t *pStorage, image_t *currImage, sliceHeader_t *pSliceHeader) { /* Variables */ u8 mbData[384 + 15 + 32]; u8 *data; u32 tmp; u32 skipRun; u32 prevSkipped; u32 currMbAddr; u32 moreMbs; u32 mbCount; i32 qpY; macroblockLayer_t *mbLayer; /* Code */ ASSERT(pStrmData); ASSERT(pSliceHeader); ASSERT(pStorage); ASSERT(pSliceHeader->firstMbInSlice < pStorage->picSizeInMbs); /* ensure 16-byte alignment */ data = (u8*)ALIGN(mbData, 16); mbLayer = pStorage->mbLayer; currMbAddr = pSliceHeader->firstMbInSlice; skipRun = 0; prevSkipped = HANTRO_FALSE; /* increment slice index, will be one for decoding of the first slice of * the picture */ pStorage->slice->sliceId++; /* lastMbAddr stores address of the macroblock that was last successfully * decoded, needed for error handling */ pStorage->slice->lastMbAddr = 0; mbCount = 0; /* initial quantization parameter for the slice is obtained as the sum of * initial QP for the picture and sliceQpDelta for the current slice */ qpY = (i32)pStorage->activePps->picInitQp + pSliceHeader->sliceQpDelta; do { /* primary picture and already decoded macroblock -> error */ if (!pSliceHeader->redundantPicCnt && pStorage->mb[currMbAddr].decoded) { EPRINT("Primary and already decoded"); return(HANTRO_NOK); } SetMbParams(pStorage->mb + currMbAddr, pSliceHeader, pStorage->slice->sliceId, pStorage->activePps->chromaQpIndexOffset); if (!IS_I_SLICE(pSliceHeader->sliceType)) { if (!prevSkipped) { tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &skipRun); if (tmp != HANTRO_OK) return(tmp); /* skip_run shall be less than or equal to number of * macroblocks left */ if (skipRun > (pStorage->picSizeInMbs - currMbAddr)) { EPRINT("skip_run"); return(HANTRO_NOK); } if (skipRun) { prevSkipped = HANTRO_TRUE; memset(&mbLayer->mbPred, 0, sizeof(mbPred_t)); /* mark current macroblock skipped */ mbLayer->mbType = P_Skip; } } } if (skipRun) { DEBUG(("Skipping macroblock %d\n", currMbAddr)); skipRun--; } else { prevSkipped = HANTRO_FALSE; tmp = h264bsdDecodeMacroblockLayer(pStrmData, mbLayer, pStorage->mb + currMbAddr, pSliceHeader->sliceType, pSliceHeader->numRefIdxL0Active); if (tmp != HANTRO_OK) { EPRINT("macroblock_layer"); return(tmp); } } tmp = h264bsdDecodeMacroblock(pStorage->mb + currMbAddr, mbLayer, currImage, pStorage->dpb, &qpY, currMbAddr, pStorage->activePps->constrainedIntraPredFlag, data); if (tmp != HANTRO_OK) { EPRINT("MACRO_BLOCK"); return(tmp); } /* increment macroblock count only for macroblocks that were decoded * for the first time (redundant slices) */ if (pStorage->mb[currMbAddr].decoded == 1) mbCount++; /* keep on processing as long as there is stream data left or * processing of macroblocks to be skipped based on the last skipRun is * not finished */ moreMbs = (h264bsdMoreRbspData(pStrmData) || skipRun) ? HANTRO_TRUE : HANTRO_FALSE; /* lastMbAddr is only updated for intra slices (all macroblocks of * inter slices will be lost in case of an error) */ if (IS_I_SLICE(pSliceHeader->sliceType)) pStorage->slice->lastMbAddr = currMbAddr; currMbAddr = h264bsdNextMbAddress(pStorage->sliceGroupMap, pStorage->picSizeInMbs, currMbAddr); /* data left in the buffer but no more macroblocks for current slice * group -> error */ if (moreMbs && !currMbAddr) { EPRINT("Next mb address"); return(HANTRO_NOK); } } while (moreMbs); if ((pStorage->slice->numDecodedMbs + mbCount) > pStorage->picSizeInMbs) { EPRINT("Num decoded mbs"); return(HANTRO_NOK); } pStorage->slice->numDecodedMbs += mbCount; return(HANTRO_OK); }
u32 h264bsdDecodeSliceHeader(strmData_t *pStrmData, sliceHeader_t *pSliceHeader, seqParamSet_t *pSeqParamSet, picParamSet_t *pPicParamSet, nalUnit_t *pNalUnit) { /* Variables */ u32 tmp, i, value; i32 itmp; u32 picSizeInMbs; /* Code */ ASSERT(pStrmData); ASSERT(pSliceHeader); ASSERT(pSeqParamSet); ASSERT(pPicParamSet); ASSERT( pNalUnit->nalUnitType == NAL_CODED_SLICE || pNalUnit->nalUnitType == NAL_CODED_SLICE_IDR ); H264SwDecMemset(pSliceHeader, 0, sizeof(sliceHeader_t)); picSizeInMbs = pSeqParamSet->picWidthInMbs * pSeqParamSet->picHeightInMbs; tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); pSliceHeader->firstMbInSlice = value; if (value >= picSizeInMbs) { EPRINT("first_mb_in_slice"); return(HANTRO_NOK); } tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); pSliceHeader->sliceType = value; /* slice type has to be either I or P slice. P slice is not allowed when * current NAL unit is an IDR NAL unit or num_ref_frames is 0 */ if ( !IS_I_SLICE(pSliceHeader->sliceType) && ( !IS_P_SLICE(pSliceHeader->sliceType) || IS_IDR_NAL_UNIT(pNalUnit) || !pSeqParamSet->numRefFrames ) ) { EPRINT("slice_type"); return(HANTRO_NOK); } tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); pSliceHeader->picParameterSetId = value; if (pSliceHeader->picParameterSetId != pPicParamSet->picParameterSetId) { EPRINT("pic_parameter_set_id"); return(HANTRO_NOK); } /* log2(maxFrameNum) -> num bits to represent frame_num */ i = 0; while (pSeqParamSet->maxFrameNum >> i) i++; i--; tmp = h264bsdGetBits(pStrmData, i); if (tmp == END_OF_STREAM) return(HANTRO_NOK); if (IS_IDR_NAL_UNIT(pNalUnit) && tmp != 0) { EPRINT("frame_num"); return(HANTRO_NOK); } pSliceHeader->frameNum = tmp; if (IS_IDR_NAL_UNIT(pNalUnit)) { tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); pSliceHeader->idrPicId = value; if (value > 65535) { EPRINT("idr_pic_id"); return(HANTRO_NOK); } } if (pSeqParamSet->picOrderCntType == 0) { /* log2(maxPicOrderCntLsb) -> num bits to represent pic_order_cnt_lsb */ i = 0; while (pSeqParamSet->maxPicOrderCntLsb >> i) i++; i--; tmp = h264bsdGetBits(pStrmData, i); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pSliceHeader->picOrderCntLsb = tmp; if (pPicParamSet->picOrderPresentFlag) { tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp); if (tmp != HANTRO_OK) return(tmp); pSliceHeader->deltaPicOrderCntBottom = itmp; } /* check that picOrderCnt for IDR picture will be zero. See * DecodePicOrderCnt function to understand the logic here */ if ( IS_IDR_NAL_UNIT(pNalUnit) && ( (pSliceHeader->picOrderCntLsb > pSeqParamSet->maxPicOrderCntLsb/2) || MIN((i32)pSliceHeader->picOrderCntLsb, (i32)pSliceHeader->picOrderCntLsb + pSliceHeader->deltaPicOrderCntBottom) != 0 ) ) { return(HANTRO_NOK); } }
u32 h264bsdDecodeMacroblockLayer(strmData_t *pStrmData, macroblockLayer_t *pMbLayer, mbStorage_t *pMb, u32 sliceType, u32 numRefIdxActive) { /* Variables */ u32 tmp, i, value; i32 itmp; mbPartPredMode_e partMode; /* Code */ ASSERT(pStrmData); ASSERT(pMbLayer); #ifdef H264DEC_NEON h264bsdClearMbLayer(pMbLayer, ((sizeof(macroblockLayer_t) + 63) & ~0x3F)); #else H264SwDecMemset(pMbLayer, 0, sizeof(macroblockLayer_t)); #endif tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (IS_I_SLICE(sliceType)) { if ((value + 6) > 31 || tmp != HANTRO_OK) return(HANTRO_NOK); pMbLayer->mbType = (mbType_e)(value + 6); } else { if ((value + 1) > 31 || tmp != HANTRO_OK) return(HANTRO_NOK); pMbLayer->mbType = (mbType_e)(value + 1); } if (pMbLayer->mbType == I_PCM) { i32 *level; while( !h264bsdIsByteAligned(pStrmData) ) { /* pcm_alignment_zero_bit */ tmp = h264bsdGetBits(pStrmData, 1); if (tmp) return(HANTRO_NOK); } level = pMbLayer->residual.level[0]; for (i = 0; i < 384; i++) { value = h264bsdGetBits(pStrmData, 8); if (value == END_OF_STREAM) return(HANTRO_NOK); *level++ = (i32)value; } } else { partMode = h264bsdMbPartPredMode(pMbLayer->mbType); if ( (partMode == PRED_MODE_INTER) && (h264bsdNumMbPart(pMbLayer->mbType) == 4) ) { tmp = DecodeSubMbPred(pStrmData, &pMbLayer->subMbPred, pMbLayer->mbType, numRefIdxActive); } else { tmp = DecodeMbPred(pStrmData, &pMbLayer->mbPred, pMbLayer->mbType, numRefIdxActive); } if (tmp != HANTRO_OK) return(tmp); if (partMode != PRED_MODE_INTRA16x16) { tmp = h264bsdDecodeExpGolombMapped(pStrmData, &value, (u32)(partMode == PRED_MODE_INTRA4x4)); if (tmp != HANTRO_OK) return(tmp); pMbLayer->codedBlockPattern = value; } else { pMbLayer->codedBlockPattern = CbpIntra16x16(pMbLayer->mbType); } if ( pMbLayer->codedBlockPattern || (partMode == PRED_MODE_INTRA16x16) ) { tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp); if (tmp != HANTRO_OK || (itmp < -26) || (itmp > 25) ) return(HANTRO_NOK); pMbLayer->mbQpDelta = itmp; tmp = DecodeResidual(pStrmData, &pMbLayer->residual, pMb, pMbLayer->mbType, pMbLayer->codedBlockPattern); pStrmData->strmBuffReadBits = (u32)(pStrmData->pStrmCurrPos - pStrmData->pStrmBuffStart) * 8 + pStrmData->bitPosInWord; if (tmp != HANTRO_OK) return(tmp); } } return(HANTRO_OK); }
u32 h264bsdDecodeMacroblockLayerCavlc(strmData_t * pStrmData, macroblockLayer_t * pMbLayer, mbStorage_t * pMb, const sliceHeader_t * pSliceHdr ) { /* Variables */ u32 tmp, i, value; i32 itmp; mbPartPredMode_e partMode; /* Code */ ASSERT(pStrmData); ASSERT(pMbLayer); (void)DWLmemset(pMbLayer->residual.totalCoeff, 0, 24); tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if(IS_I_SLICE(pSliceHdr->sliceType)) { if((value + 6) > 31 || tmp != HANTRO_OK) return (HANTRO_NOK); pMbLayer->mbType = (mbType_e) (value + 6); } else { if((value + 1) > 31 || tmp != HANTRO_OK) return (HANTRO_NOK); pMbLayer->mbType = (mbType_e) (value + 1); } if(pMbLayer->mbType == I_PCM) { u8 *level; while(!h264bsdIsByteAligned(pStrmData)) { /* pcm_alignment_zero_bit */ tmp = h264bsdGetBits(pStrmData, 1); if(tmp) return (HANTRO_NOK); } level = (u8 *) pMbLayer->residual.rlc; for(i = 384; i > 0; i--) { value = h264bsdGetBits(pStrmData, 8); if(value == END_OF_STREAM) return (HANTRO_NOK); *level++ = (u8) value; } } else { partMode = h264bsdMbPartPredMode(pMbLayer->mbType); if((partMode == PRED_MODE_INTER) && (h264bsdNumMbPart(pMbLayer->mbType) == 4)) { tmp = DecodeSubMbPred(pStrmData, &pMbLayer->subMbPred, pMbLayer->mbType, pSliceHdr->numRefIdxL0Active, pMb ); } else { tmp = DecodeMbPred(pStrmData, &pMbLayer->mbPred, pMbLayer->mbType, pSliceHdr->numRefIdxL0Active, pMb ); } if(tmp != HANTRO_OK) return (tmp); if(partMode != PRED_MODE_INTRA16x16) { tmp = h264bsdDecodeExpGolombMapped(pStrmData, &value, (u32) (partMode == PRED_MODE_INTRA4x4)); if(tmp != HANTRO_OK) return (tmp); pMbLayer->codedBlockPattern = value; } else { pMbLayer->codedBlockPattern = CbpIntra16x16(pMbLayer->mbType); } if(pMbLayer->codedBlockPattern || (partMode == PRED_MODE_INTRA16x16)) { tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp); if(tmp != HANTRO_OK || (u32) (itmp + 26) > 51U /*(itmp >= -26) || (itmp < 26) */ ) return (HANTRO_NOK); pMbLayer->mbQpDelta = itmp; tmp = DecodeResidual(pStrmData, pMbLayer, pMb); if(tmp != HANTRO_OK) return (tmp); } } return (HANTRO_OK); }