--- /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;
+}
+