diff -r 000000000000 -r 951a5db380a0 videoeditorengine/avcedit/src/macroblock.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/videoeditorengine/avcedit/src/macroblock.cpp Fri Jan 29 14:08:33 2010 +0200 @@ -0,0 +1,612 @@ +/* +* Copyright (c) 2010 Ixonos Plc. +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of the "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - Initial contribution +* +* Contributors: +* Ixonos Plc +* +* Description: +* +*/ + + +#include "globals.h" +#include "bitbuffer.h" +#include "macroblock.h" +#include "motcomp.h" +#include "framebuffer.h" +#include "vld.h" +#include "parameterset.h" + +#ifdef USE_CLIPBUF +#include "clipbuf.h" +#endif + +/* + * Static functions + */ + +static int getMacroblock(macroblock_s *mb, int numRefFrames, + int8 *ipTab, int8 **numCoefUpPred, int diffVecs[][2], + int picType, int chromaQpIdx, bitbuffer_s *bitbuf); + +static int getMbAvailability(macroblock_s *mb, mbAttributes_s *mbData, + int picWidth, int constrainedIntra); + + +#ifdef USE_CLIPBUF +const u_int8 *mcpGetClip8Buf() +{ + return clip8Buf; +} +#endif + +/* + * + * getMacroblock: + * + * Parameters: + * mb Macroblock parameters + * multRef 1 -> multiple reference frames used + * ipTab Macroblock intra pred. modes + * numCoefUpPred Block coefficient counts of upper MBs + * diffVecs Macroblock delta motion vectors + * picType Picture type (intra/inter) + * chromaQpIdx Chroma QP index relative to luma QP + * bitbuf Bitbuffer handle + * + * Function: + * Get macroblock parameters from bitbuffer + * + * Returns: + * MBK_OK for no error, MBK_ERROR for error + * + */ +static int getMacroblock(macroblock_s *mb, int numRefFrames, + int8 *ipTab, int8 **numCoefUpPred, int diffVecs[][2], + int picType, int chromaQpIdx, bitbuffer_s *bitbuf) +{ + vldMBtype_s hdr; + int numVecs; + int delta_qp; + int i; + int8 *numCoefPtrY, *numCoefPtrU, *numCoefPtrV; + int retCode; + + + numCoefPtrY = &numCoefUpPred[0][mb->blkX]; + numCoefPtrU = &numCoefUpPred[1][mb->blkX>>1]; + numCoefPtrV = &numCoefUpPred[2][mb->blkX>>1]; + + /* + * Get Macroblock type + */ + + /* Check if we have to fetch run indicator */ + if (IS_SLICE_P(picType) && mb->numSkipped < 0) { + + mb->numSkipped = vldGetRunIndicator(bitbuf); + + if (bibGetStatus(bitbuf) < 0) + return MBK_ERROR; + } + + if (IS_SLICE_P(picType) && mb->numSkipped > 0) { + + /* If skipped MBs, set MB to COPY */ + mb->type = MBK_INTER; + mb->interMode = MOT_COPY; + mb->refNum[0] = 0; + mb->cbpY = mb->cbpChromaDC = mb->cbpC = 0; + mb->numSkipped -= 1; + + vldGetZeroLumaCoeffs(numCoefPtrY, mb->numCoefLeftPred); + vldGetZeroChromaCoeffs(numCoefPtrU, numCoefPtrV, mb->numCoefLeftPredC); + + return MBK_OK; + } + else { + + if (vldGetMBtype(bitbuf, &hdr, picType) < 0) { + PRINT((_L("Error: illegal MB type\n"))); + return MBK_ERROR; + } + + mb->type = hdr.type; + mb->intraType = hdr.intraType; + mb->intraMode = hdr.intraMode; + mb->interMode = hdr.interMode; + + for (i = 0; i < 4; i++) + mb->inter8x8modes[i] = hdr.inter8x8modes[i]; + + mb->cbpY = hdr.cbpY; + mb->cbpChromaDC = hdr.cbpChromaDC; + mb->cbpC = hdr.cbpC; + + mb->numSkipped -= 1; + } + + if (mb->type == MBK_INTRA && mb->intraType == MBK_INTRA_TYPE_PCM) { + vldGetAllCoeffs(numCoefPtrY, numCoefPtrU, numCoefPtrV, + mb->numCoefLeftPred, mb->numCoefLeftPredC); + return MBK_OK; + } + + /* + * 4x4 intra prediction modes + */ + if (mb->type == MBK_INTRA && mb->intraType == MBK_INTRA_TYPE1) { + + if (vldGetIntraPred(bitbuf, ipTab) < 0) { + PRINT((_L("Error: illegal intra pred\n"))); + return MBK_ERROR; + } + } + + /* + * 8x8 chroma intra prediction mode + */ + if (mb->type == MBK_INTRA) { + + mb->intraModeChroma = vldGetChromaIntraPred(bitbuf); + + if (mb->intraModeChroma < 0) { + PRINT((_L("Error: illegal chroma intra pred\n"))); + return MBK_ERROR; + } + } + + /* + * Reference frame number and motion vectors + */ + if (mb->type == MBK_INTER) { + + numVecs = mcpGetNumMotVecs(mb->interMode, mb->inter8x8modes); + mb->numMotVecs = numVecs; + + retCode = vldGetMotVecs(bitbuf, mb->interMode, numRefFrames, + mb->refNum, diffVecs, numVecs); + + if (retCode < 0) { + PRINT((_L("Error: illegal motion vectors\n"))); + return MBK_ERROR; + } + } + + /* + * Coded block pattern + */ + if (!(mb->type == MBK_INTRA && mb->intraType == MBK_INTRA_TYPE2)) { + + retCode = vldGetCBP(bitbuf, mb->type, &mb->cbpY, &mb->cbpChromaDC, &mb->cbpC); + + if (retCode < 0) { + PRINT((_L("Error: illegal CBP\n"))); + return MBK_ERROR; + } + } + + + /* Delta QP */ + if ((mb->type == MBK_INTRA && mb->intraType == MBK_INTRA_TYPE2) || + (mb->cbpY | mb->cbpChromaDC | mb->cbpC) != 0) + { + retCode = vldGetDeltaqp(bitbuf, &delta_qp); + + if (retCode < 0 || delta_qp < -(MAX_QP-MIN_QP+1)/2 || delta_qp >= (MAX_QP-MIN_QP+1)/2) { + PRINT((_L("Error: illegal delta qp\n"))); + return MBK_ERROR; + } + + if (delta_qp != 0) { + int qp = mb->qp + delta_qp; + if (qp < MIN_QP) + qp += (MAX_QP-MIN_QP+1); + if (qp > MAX_QP) + qp -= (MAX_QP-MIN_QP+1); + mb->qp = qp; + mb->qpC = qpChroma[clip(MIN_QP, MAX_QP, mb->qp + chromaQpIdx)]; + } + } + + + /* + * Get transform coefficients + */ + + /* + * Luma DC coefficients (if 16x16 intra) + */ + if (mb->type == MBK_INTRA && mb->intraType == MBK_INTRA_TYPE2) { + + retCode = vldGetLumaDCcoeffs(bitbuf, mb->dcCoefY, numCoefPtrY, + mb->numCoefLeftPred, mb->mbAvailBits); + if (retCode < 0) { + PRINT((_L("Error: illegal luma DC coefficient\n"))); + return MBK_ERROR; + } + } + + /* + * Luma AC coefficients + */ + if (mb->cbpY != 0) { + + retCode = vldGetLumaCoeffs(bitbuf, mb->type, mb->intraType, &mb->cbpY, + mb->coefY, numCoefPtrY, mb->numCoefLeftPred, + mb->mbAvailBits); + if (retCode < 0) { + PRINT((_L("Error: illegal luma AC coefficient\n"))); + return MBK_ERROR; + } + } + else + vldGetZeroLumaCoeffs(numCoefPtrY, mb->numCoefLeftPred); + + /* + * Chroma DC coefficients + */ + if (mb->cbpChromaDC != 0) { + + retCode = vldGetChromaDCcoeffs(bitbuf, mb->dcCoefC, &mb->cbpChromaDC); + + if (retCode < 0) { + PRINT((_L("Error: illegal chroma DC coefficient\n"))); + return MBK_ERROR; + } + } + + /* + * Chroma AC coefficients + */ + if (mb->cbpC != 0) { + + retCode = vldGetChromaCoeffs(bitbuf, mb->coefC, &mb->cbpC, numCoefPtrU, numCoefPtrV, + mb->numCoefLeftPredC[0], mb->numCoefLeftPredC[1], mb->mbAvailBits); + if (retCode < 0) { + PRINT((_L("Error: illegal chroma AC coefficient\n"))); + return MBK_ERROR; + } + } + else { + vldGetZeroChromaCoeffs(numCoefPtrU, numCoefPtrV, mb->numCoefLeftPredC); + } + + return MBK_OK; +} + + +/* + * + * mbkSetInitialQP: + * + * Parameters: + * mb Macroblock object + * qp Quantization parameter + * chromaQpIdx Chroma QP index relative to luma QP + * + * Function: + * Set macroblock qp. + * + * Returns: + * - + * + */ +void mbkSetInitialQP(macroblock_s *mb, int qp, int chromaQpIdx) +{ + mb->qp = qp; + mb->qpC = qpChroma[clip(MIN_QP, MAX_QP, qp + chromaQpIdx)]; + + mb->numSkipped = -1; +} + + +/* + * + * getMbAvailability: + * + * Parameters: + * mb Macroblock object + * mbData Buffers for for macroblock attributes + * picWidth Picture width + * constrainedIntra Constrained intra prediction flag + * + * Function: + * Get neighboring macroblock availability info + * + * Returns: + * Macroblock availability bits: + * bit 0 : left macroblock + * bit 1 : upper macroblock + * bit 2 : upper-right macroblock + * bit 3 : upper-left macroblock + * bit 4 : left macroblock (intra) + * bit 5 : upper macroblock (intra) + * bit 6 : upper-right macroblock (intra) + * bit 7 : upper-left macroblock (intra) + */ +static int getMbAvailability(macroblock_s *mb, mbAttributes_s *mbData, + int picWidth, int constrainedIntra) +{ + int mbsPerLine; + int mbAddr; + int currSliceIdx; + int *sliceMap; + int8 *mbTypeTable; + int mbAvailBits; + + mbsPerLine = picWidth/MBK_SIZE; + mbAddr = mb->idxY*mbsPerLine+mb->idxX; + + sliceMap = & mbData->sliceMap[mbAddr]; + currSliceIdx = sliceMap[0]; + + mbAvailBits = 0; + + /* Check availability of left macroblock */ + if (mb->idxX > 0 && sliceMap[-1] == currSliceIdx) + mbAvailBits |= 0x11; + + /* Check availability of upper, upper-left and upper-right macroblocks */ + + if (mb->idxY > 0) { + + sliceMap -= mbsPerLine; + + /* Check availability of upper macroblock */ + if (sliceMap[0] == currSliceIdx) + mbAvailBits |= 0x22; + + /* Check availability of upper-right macroblock */ + if (mb->idxX+1 < mbsPerLine && sliceMap[1] == currSliceIdx) + mbAvailBits |= 0x44; + + /* Check availability of upper-left macroblock */ + if (mb->idxX > 0 && sliceMap[-1] == currSliceIdx) + mbAvailBits |= 0x88; + } + + + /* + * Check availability of intra MB if constrained intra is enabled + */ + + if (constrainedIntra) { + + mbTypeTable = & mbData->mbTypeTable[mbAddr]; + + /* Check availability of left intra macroblock */ + if ((mbAvailBits & 0x10) && mbTypeTable[-1] != MBK_INTRA) + mbAvailBits &= ~0x10; + + /* Check availability of upper, upper-left and upper-right intra macroblocks */ + + if (mbAvailBits & (0x20|0x40|0x80)) { + + mbTypeTable -= mbsPerLine; + + /* Check availability of upper intra macroblock */ + if ((mbAvailBits & 0x20) && mbTypeTable[0] != MBK_INTRA) + mbAvailBits &= ~0x20; + + /* Check availability of upper-right intra macroblock */ + if ((mbAvailBits & 0x40) && mbTypeTable[1] != MBK_INTRA) + mbAvailBits &= ~0x40; + + /* Check availability of upper-left intra macroblock */ + if ((mbAvailBits & 0x80) && mbTypeTable[-1] != MBK_INTRA) + mbAvailBits &= ~0x80; + } + } + + return mbAvailBits; +} + + +// mbkParse +// Parses the input macroblock. If PCM coding is used then re-aligns the byte +// alignment if previous (slice header) modifications have broken the alignment. +TInt mbkParse(macroblock_s *mb, TInt numRefFrames, mbAttributes_s *mbData, + TInt picWidth, TInt picType, TInt constIpred, TInt chromaQpIdx, + TInt mbIdxX, TInt mbIdxY, void *streamBuf, TInt aBitOffset) +{ + TInt8 ipTab[BLK_PER_MB*BLK_PER_MB]; + TInt diffVecs[BLK_PER_MB*BLK_PER_MB][2]; +// TInt hasDc; +// TInt pixOffset; + TInt constrainedIntra; + TInt copyMbFlag; + TInt mbAddr; + TInt pcmMbFlag; + TInt retCode; + + mb->idxX = mbIdxX; + mb->idxY = mbIdxY; + + mb->blkX = mbIdxX*BLK_PER_MB; + mb->blkY = mbIdxY*BLK_PER_MB; + + mb->pixX = mbIdxX*MBK_SIZE; + mb->pixY = mbIdxY*MBK_SIZE; + + mbAddr = mb->idxY*(picWidth/MBK_SIZE)+mb->idxX; + + copyMbFlag = pcmMbFlag = 0; + + constrainedIntra = constIpred && !(IS_SLICE_I(picType)); + + mb->mbAvailBits = getMbAvailability(mb, mbData, picWidth, constrainedIntra); + + // Read macroblock bits + retCode = getMacroblock(mb, numRefFrames, ipTab, mbData->numCoefUpPred, diffVecs, + picType, chromaQpIdx, (bitbuffer_s *)streamBuf); + + if (retCode < 0) + return retCode; + + // Set PCM flag + if (mb->type == MBK_INTRA && mb->intraType == MBK_INTRA_TYPE_PCM) + pcmMbFlag = 1; + + + // Get intra/inter prediction + if (mb->type == MBK_INTRA) + { + mbData->mbTypeTable[mbAddr] = MBK_INTRA; + + if (pcmMbFlag) + { + bitbuffer_s* tempBitBuffer = (bitbuffer_s *)streamBuf; + + // Synchronize bitbuffer bit position to get it between 1 and 8 + syncBitBufferBitpos(tempBitBuffer); + + // To find out how much we have to shift to reach the byte alignment again, + // we have to first find out the old alignment + // oldAlignment is the place of the bitpos before the aBitOffset, i.e. it is + // the amount of zero alignment bits plus one + TInt oldAlignmentBits = tempBitBuffer->bitpos + aBitOffset - 1; + TInt shiftAmount; + + + // If Bit-wise shift, i.e. aBitOffset is zero, do nothing + // Fix the possible bit buffer byte alignment + if (aBitOffset > 0) + { + + // aBitOffset > 0 indicates a bitshift to the right + + // To counter the shift to right we have to shift left by the same amount + // unless shift is larger than the number of original alignment bits in + // which case we have to shift more to the right + + // If the computed old alignment bits value is larger than eight, + //the correct value is (computed value) % 8 + oldAlignmentBits = oldAlignmentBits % 8; + + if ( oldAlignmentBits < aBitOffset ) + { + // When the amount of shift is larger than the number of original alignment bits, + // shift right to fill up the rest of the current byte with zeros + shiftAmount = 8 - aBitOffset; + + // Here we can't shift back left since there were not enough alignment bits originally, + // thus we have to shift right by new bit position - tempBitBuffer->bitpos + + // E.g. original alignment bits 2, right shift by 4 bits: + ///////////////////////////////////////////////////////////////// + // original after bit shift byte alignment reset + // 1. byte: 2. byte: 1. byte: 2. byte: 1. byte: 2. byte: 3. byte: + // xxxxxx00 yyyyyyyy -> xxxxxxxx xx00yyyy -> xxxxxxxx xx000000 yyyyyyyy + ///////////////////////////////////////////////////////////////// + ShiftBitBufferBitsRight(tempBitBuffer, shiftAmount); + } + else + { + // In this case, the old alignment bits are more than enough + // to shift back left by the aBitOffset amount + + // E.g. original alignment bits 4, right shift by 2 bits: + ///////////////////////////////////////////////////////////////// + // original after bit shift byte alignment reset + // 1. byte: 2. byte: 1. byte: 2. byte: 1. byte: 2. byte: + // xxxx0000 yyyyyyyy -> xxxxxx00 00yyyyyy -> xxxxxx00 yyyyyyyy + ///////////////////////////////////////////////////////////////// + ShiftBitBufferBitsLeft(tempBitBuffer, aBitOffset); + } + } + else if(aBitOffset < 0) + { + // There was a bit shift to left + // Change the aBitOffset sign to positive + aBitOffset = -aBitOffset; + + // If the computed alignment bits is negative the correct value is -(computed value) + if ( oldAlignmentBits < 0 ) + { + oldAlignmentBits = -oldAlignmentBits; + } + + if ( oldAlignmentBits + aBitOffset >= 8 ) + { + // When old alignment bits plus the shift are at least 8, then + // we have to shift left by the 8 - shift to reach byte alignment. + shiftAmount = 8 - aBitOffset; + + // E.g. original alignment bits 6, left shift by 4 bits: + ///////////////////////////////////////////////////////////////// + // original after bit shift byte alignment reset + // 1. byte: 2. byte: 1. byte: 2. byte: 1. byte: 2. byte: + // xx000000 yyyyyyyy -> xxxxxx00 0000yyyy -> xxxxxx00 yyyyyyyy + ///////////////////////////////////////////////////////////////// + ShiftBitBufferBitsLeft(tempBitBuffer, shiftAmount); + } + else + { + + // Here we can just shift right by the amount of bits shifted left to reach + // the byte alignment + + // E.g. original alignment bits 2, left shift by 4 bits: + ///////////////////////////////////////////////////////////////// + // original after bit shift byte alignment reset + // 1. byte: 2. byte: 1. byte: 2. byte: 1. byte: 2. byte: + // xxxxxx00 yyyyyyyy -> xx00yyyy yyyyyyyy -> xx000000 yyyyyyyy + ///////////////////////////////////////////////////////////////// + ShiftBitBufferBitsRight(tempBitBuffer, aBitOffset); + } + } + + return MBK_PCM_FOUND; + + } + } + else + { + + mbData->mbTypeTable[mbAddr] = (TInt8)(mb->interMode+1); + + // If COPY MB, put skip motion vectors + if (mb->interMode == MOT_COPY) + { + mb->interMode = MOT_16x16; + } + + } + + + // Decode prediction error & reconstruct MB + if (!copyMbFlag && !pcmMbFlag) + { + + // If 4x4 intra mode, luma prediction error is already transformed + if (!(mb->type == MBK_INTRA && mb->intraType == MBK_INTRA_TYPE1)) + { + +// hasDc = (mb->type == MBK_INTRA && mb->intraType == MBK_INTRA_TYPE2) ? 1 : 0; + + } + +// pixOffset = ((mb->pixY*picWidth)>>2)+(mb->pixX>>1); + } + + + // Store qp and coded block pattern for current macroblock + if (pcmMbFlag) + mbData->qpTable[mbAddr] = 0; + else + mbData->qpTable[mbAddr] = (TInt8)mb->qp; + + mbData->cbpTable[mbAddr] = mb->cbpY; + + return MBK_OK; +} +