/* * Copyright (C) 2009 The Android Open Source Project * * 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. */ /*------------------------------------------------------------------------------ Table of contents 1. Include headers 2. External compiler flags 3. Module defines 4. Local function prototypes 5. Functions h264bsdIntraPrediction h264bsdGetNeighbourPels h264bsdIntra16x16Prediction h264bsdIntra4x4Prediction h264bsdIntraChromaPrediction h264bsdAddResidual Intra16x16VerticalPrediction Intra16x16HorizontalPrediction Intra16x16DcPrediction Intra16x16PlanePrediction IntraChromaDcPrediction IntraChromaHorizontalPrediction IntraChromaVerticalPrediction IntraChromaPlanePrediction Get4x4NeighbourPels Write4x4To16x16 Intra4x4VerticalPrediction Intra4x4HorizontalPrediction Intra4x4DcPrediction Intra4x4DiagonalDownLeftPrediction Intra4x4DiagonalDownRightPrediction Intra4x4VerticalRightPrediction Intra4x4HorizontalDownPrediction Intra4x4VerticalLeftPrediction Intra4x4HorizontalUpPrediction DetermineIntra4x4PredMode ------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------ 1. Include headers ------------------------------------------------------------------------------*/ #include "h264bsd_intra_prediction.h" #include "h264bsd_util.h" #include "h264bsd_macroblock_layer.h" #include "h264bsd_neighbour.h" #include "h264bsd_image.h" #ifdef H264DEC_OMXDL #include "omxtypes.h" #include "omxVC.h" #endif /* H264DEC_OMXDL */ /*------------------------------------------------------------------------------ 2. External compiler flags -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- 3. Module defines ------------------------------------------------------------------------------*/ /* Switch off the following Lint messages for this file: * Info 702: Shift right of signed quantity (int) */ /*lint -e702 */ /* x- and y-coordinates for each block */ const u32 h264bsdBlockX[16] = { 0, 4, 0, 4, 8, 12, 8, 12, 0, 4, 0, 4, 8, 12, 8, 12 }; const u32 h264bsdBlockY[16] = { 0, 0, 4, 4, 0, 0, 4, 4, 8, 8, 12, 12, 8, 8, 12, 12 }; const u8 h264bsdClip[1280] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47, 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63, 64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79, 80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95, 96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111, 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255 }; #ifndef H264DEC_OMXDL /*------------------------------------------------------------------------------ 4. Local function prototypes ------------------------------------------------------------------------------*/ static void Get4x4NeighbourPels(u8 *a, u8 *l, u8 *data, u8 *above, u8 *left, u32 blockNum); static void Intra16x16VerticalPrediction(u8 *data, u8 *above); static void Intra16x16HorizontalPrediction(u8 *data, u8 *left); static void Intra16x16DcPrediction(u8 *data, u8 *above, u8 *left, u32 A, u32 B); static void Intra16x16PlanePrediction(u8 *data, u8 *above, u8 *left); static void IntraChromaDcPrediction(u8 *data, u8 *above, u8 *left, u32 A, u32 B); static void IntraChromaHorizontalPrediction(u8 *data, u8 *left); static void IntraChromaVerticalPrediction(u8 *data, u8 *above); static void IntraChromaPlanePrediction(u8 *data, u8 *above, u8 *left); static void Intra4x4VerticalPrediction(u8 *data, u8 *above); static void Intra4x4HorizontalPrediction(u8 *data, u8 *left); static void Intra4x4DcPrediction(u8 *data, u8 *above, u8 *left, u32 A, u32 B); static void Intra4x4DiagonalDownLeftPrediction(u8 *data, u8 *above); static void Intra4x4DiagonalDownRightPrediction(u8 *data, u8 *above, u8 *left); static void Intra4x4VerticalRightPrediction(u8 *data, u8 *above, u8 *left); static void Intra4x4HorizontalDownPrediction(u8 *data, u8 *above, u8 *left); static void Intra4x4VerticalLeftPrediction(u8 *data, u8 *above); static void Intra4x4HorizontalUpPrediction(u8 *data, u8 *left); void h264bsdAddResidual(u8 *data, i32 *residual, u32 blockNum); static void Write4x4To16x16(u8 *data, u8 *data4x4, u32 blockNum); #endif /* H264DEC_OMXDL */ static u32 DetermineIntra4x4PredMode(macroblockLayer_t *pMbLayer, u32 available, neighbour_t *nA, neighbour_t *nB, u32 index, mbStorage_t *nMbA, mbStorage_t *nMbB); #ifdef H264DEC_OMXDL /*------------------------------------------------------------------------------ Function: h264bsdIntra16x16Prediction Functional description: Perform intra 16x16 prediction mode for luma pixels and add residual into prediction. The resulting luma pixels are stored in macroblock array 'data'. ------------------------------------------------------------------------------*/ u32 h264bsdIntra16x16Prediction(mbStorage_t *pMb, u8 *data, u8 *ptr, u32 width, u32 constrainedIntraPred) { /* Variables */ u32 availableA, availableB, availableD; OMXResult omxRes; /* Code */ ASSERT(pMb); ASSERT(data); ASSERT(ptr); ASSERT(h264bsdPredModeIntra16x16(pMb->mbType) < 4); availableA = h264bsdIsNeighbourAvailable(pMb, pMb->mbA); if (availableA && constrainedIntraPred && (h264bsdMbPartPredMode(pMb->mbA->mbType) == PRED_MODE_INTER)) availableA = HANTRO_FALSE; availableB = h264bsdIsNeighbourAvailable(pMb, pMb->mbB); if (availableB && constrainedIntraPred && (h264bsdMbPartPredMode(pMb->mbB->mbType) == PRED_MODE_INTER)) availableB = HANTRO_FALSE; availableD = h264bsdIsNeighbourAvailable(pMb, pMb->mbD); if (availableD && constrainedIntraPred && (h264bsdMbPartPredMode(pMb->mbD->mbType) == PRED_MODE_INTER)) availableD = HANTRO_FALSE; omxRes = omxVCM4P10_PredictIntra_16x16( (ptr-1), (ptr - width), (ptr - width-1), data, (i32)width, 16, (OMXVCM4P10Intra16x16PredMode) h264bsdPredModeIntra16x16(pMb->mbType), (i32)(availableB + (availableA<<1) + (availableD<<5)) ); if (omxRes != OMX_Sts_NoErr) return HANTRO_NOK; else return(HANTRO_OK); } /*------------------------------------------------------------------------------ Function: h264bsdIntra4x4Prediction Functional description: Perform intra 4x4 prediction for luma pixels and add residual into prediction. The resulting luma pixels are stored in macroblock array 'data'. The intra 4x4 prediction mode for each block is stored in 'pMb' structure. ------------------------------------------------------------------------------*/ u32 h264bsdIntra4x4Prediction(mbStorage_t *pMb, u8 *data, macroblockLayer_t *mbLayer, u8 *ptr, u32 width, u32 constrainedIntraPred, u32 block) { /* Variables */ u32 mode; neighbour_t neighbour, neighbourB; mbStorage_t *nMb, *nMb2; u32 availableA, availableB, availableC, availableD; OMXResult omxRes; u32 x, y; u8 *l, *a, *al; /* Code */ ASSERT(pMb); ASSERT(data); ASSERT(mbLayer); ASSERT(ptr); ASSERT(pMb->intra4x4PredMode[block] < 9); neighbour = *h264bsdNeighbour4x4BlockA(block); nMb = h264bsdGetNeighbourMb(pMb, neighbour.mb); availableA = h264bsdIsNeighbourAvailable(pMb, nMb); if (availableA && constrainedIntraPred && ( h264bsdMbPartPredMode(nMb->mbType) == PRED_MODE_INTER) ) { availableA = HANTRO_FALSE; } neighbourB = *h264bsdNeighbour4x4BlockB(block); nMb2 = h264bsdGetNeighbourMb(pMb, neighbourB.mb); availableB = h264bsdIsNeighbourAvailable(pMb, nMb2); if (availableB && constrainedIntraPred && ( h264bsdMbPartPredMode(nMb2->mbType) == PRED_MODE_INTER) ) { availableB = HANTRO_FALSE; } mode = DetermineIntra4x4PredMode(mbLayer, (u32)(availableA && availableB), &neighbour, &neighbourB, block, nMb, nMb2); pMb->intra4x4PredMode[block] = (u8)mode; neighbour = *h264bsdNeighbour4x4BlockC(block); nMb = h264bsdGetNeighbourMb(pMb, neighbour.mb); availableC = h264bsdIsNeighbourAvailable(pMb, nMb); if (availableC && constrainedIntraPred && ( h264bsdMbPartPredMode(nMb->mbType) == PRED_MODE_INTER) ) { availableC = HANTRO_FALSE; } neighbour = *h264bsdNeighbour4x4BlockD(block); nMb = h264bsdGetNeighbourMb(pMb, neighbour.mb); availableD = h264bsdIsNeighbourAvailable(pMb, nMb); if (availableD && constrainedIntraPred && ( h264bsdMbPartPredMode(nMb->mbType) == PRED_MODE_INTER) ) { availableD = HANTRO_FALSE; } x = h264bsdBlockX[block]; y = h264bsdBlockY[block]; if (y == 0) a = ptr - width + x; else a = data-16; if (x == 0) l = ptr + y * width -1; else { l = data-1; width = 16; } if (x == 0) al = l-width; else al = a-1; omxRes = omxVCM4P10_PredictIntra_4x4( l, a, al, data, (i32)width, 16, (OMXVCM4P10Intra4x4PredMode)mode, (i32)(availableB + (availableA<<1) + (availableD<<5) + (availableC<<6)) ); if (omxRes != OMX_Sts_NoErr) return HANTRO_NOK; return(HANTRO_OK); } /*------------------------------------------------------------------------------ Function: h264bsdIntraChromaPrediction Functional description: Perform intra prediction for chroma pixels and add residual into prediction. The resulting chroma pixels are stored in 'data'. ------------------------------------------------------------------------------*/ u32 h264bsdIntraChromaPrediction(mbStorage_t *pMb, u8 *data, image_t *image, u32 predMode, u32 constrainedIntraPred) { /* Variables */ u32 availableA, availableB, availableD; OMXResult omxRes; u8 *ptr; u32 width; /* Code */ ASSERT(pMb); ASSERT(data); ASSERT(image); ASSERT(predMode < 4); availableA = h264bsdIsNeighbourAvailable(pMb, pMb->mbA); if (availableA && constrainedIntraPred && (h264bsdMbPartPredMode(pMb->mbA->mbType) == PRED_MODE_INTER)) availableA = HANTRO_FALSE; availableB = h264bsdIsNeighbourAvailable(pMb, pMb->mbB); if (availableB && constrainedIntraPred && (h264bsdMbPartPredMode(pMb->mbB->mbType) == PRED_MODE_INTER)) availableB = HANTRO_FALSE; availableD = h264bsdIsNeighbourAvailable(pMb, pMb->mbD); if (availableD && constrainedIntraPred && (h264bsdMbPartPredMode(pMb->mbD->mbType) == PRED_MODE_INTER)) availableD = HANTRO_FALSE; ptr = image->cb; width = image->width*8; omxRes = omxVCM4P10_PredictIntraChroma_8x8( (ptr-1), (ptr - width), (ptr - width -1), data, (i32)width, 8, (OMXVCM4P10IntraChromaPredMode) predMode, (i32)(availableB + (availableA<<1) + (availableD<<5)) ); if (omxRes != OMX_Sts_NoErr) return HANTRO_NOK; /* advance pointers */ data += 64; ptr = image->cr; omxRes = omxVCM4P10_PredictIntraChroma_8x8( (ptr-1), (ptr - width), (ptr - width -1), data, (i32)width, 8, (OMXVCM4P10IntraChromaPredMode) predMode, (i32)(availableB + (availableA<<1) + (availableD<<5)) ); if (omxRes != OMX_Sts_NoErr) return HANTRO_NOK; return(HANTRO_OK); } #else /* H264DEC_OMXDL */ /*------------------------------------------------------------------------------ Function: h264bsdIntraPrediction Functional description: Processes one intra macroblock. Performs intra prediction using specified prediction mode. Writes the final macroblock (prediction + residual) into the output image (image) Inputs: pMb pointer to macroblock specific information mbLayer pointer to current macroblock data from stream image pointer to output image mbNum current macroblock number constrainedIntraPred flag specifying if neighbouring inter macroblocks are used in intra prediction data pointer where output macroblock will be stored Outputs: pMb structure is updated with current macroblock image current macroblock is written into image data current macroblock is stored here Returns: HANTRO_OK success HANTRO_NOK error in intra prediction ------------------------------------------------------------------------------*/ u32 h264bsdIntraPrediction(mbStorage_t *pMb, macroblockLayer_t *mbLayer, image_t *image, u32 mbNum, u32 constrainedIntraPred, u8 *data) { /* Variables */ /* pelAbove and pelLeft contain samples above and left to the current * macroblock. Above array contains also sample above-left to the current * mb as well as 4 samples above-right to the current mb (latter only for * luma) */ /* lumD + lumB + lumC + cbD + cbB + crD + crB */ u8 pelAbove[1 + 16 + 4 + 1 + 8 + 1 + 8]; /* lumA + cbA + crA */ u8 pelLeft[16 + 8 + 8]; u32 tmp; /* Code */ ASSERT(pMb); ASSERT(image); ASSERT(mbNum < image->width * image->height); ASSERT(h264bsdMbPartPredMode(pMb->mbType) != PRED_MODE_INTER); h264bsdGetNeighbourPels(image, pelAbove, pelLeft, mbNum); if (h264bsdMbPartPredMode(pMb->mbType) == PRED_MODE_INTRA16x16) { tmp = h264bsdIntra16x16Prediction(pMb, data, mbLayer->residual.level, pelAbove, pelLeft, constrainedIntraPred); if (tmp != HANTRO_OK) return(tmp); } else { tmp = h264bsdIntra4x4Prediction(pMb, data, mbLayer, pelAbove, pelLeft, constrainedIntraPred); if (tmp != HANTRO_OK) return(tmp); } tmp = h264bsdIntraChromaPrediction(pMb, data + 256, mbLayer->residual.level+16, pelAbove + 21, pelLeft + 16, mbLayer->mbPred.intraChromaPredMode, constrainedIntraPred); if (tmp != HANTRO_OK) return(tmp); /* if decoded flag > 1 -> mb has already been successfully decoded and * written to output -> do not write again */ if (pMb->decoded > 1) return HANTRO_OK; h264bsdWriteMacroblock(image, data); return(HANTRO_OK); } /*------------------------------------------------------------------------------ Function: h264bsdGetNeighbourPels Functional description: Get pixel values from neighbouring macroblocks into 'above' and 'left' arrays. ------------------------------------------------------------------------------*/ void h264bsdGetNeighbourPels(image_t *image, u8 *above, u8 *left, u32 mbNum) { /* Variables */ u32 i; u32 width, picSize; u8 *ptr, *tmp; u32 row, col; /* Code */ ASSERT(image); ASSERT(above); ASSERT(left); ASSERT(mbNum < image->width * image->height); if (!mbNum) return; width = image->width; picSize = width * image->height; row = mbNum / width; col = mbNum - row * width; width *= 16; ptr = image->data + row * 16 * width + col * 16; /* note that luma samples above-right to current macroblock do not make * sense when current mb is the right-most mb in a row. Same applies to * sample above-left if col is zero. However, usage of pels in prediction * is controlled by neighbour availability information in actual prediction * process */ if (row) { tmp = ptr - (width + 1); for (i = 21; i--;) *above++ = *tmp++; } if (col) { ptr--; for (i = 16; i--; ptr+=width) *left++ = *ptr; } width >>= 1; ptr = image->data + picSize * 256 + row * 8 * width + col * 8; if (row) { tmp = ptr - (width + 1); for (i = 9; i--;) *above++ = *tmp++; tmp += (picSize * 64) - 9; for (i = 9; i--;) *above++ = *tmp++; } if (col) { ptr--; for (i = 8; i--; ptr+=width) *left++ = *ptr; ptr += (picSize * 64) - 8 * width; for (i = 8; i--; ptr+=width) *left++ = *ptr; } } /*------------------------------------------------------------------------------ Function: Intra16x16Prediction Functional description: Perform intra 16x16 prediction mode for luma pixels and add residual into prediction. The resulting luma pixels are stored in macroblock array 'data'. ------------------------------------------------------------------------------*/ u32 h264bsdIntra16x16Prediction(mbStorage_t *pMb, u8 *data, i32 residual[][16], u8 *above, u8 *left, u32 constrainedIntraPred) { /* Variables */ u32 i; u32 availableA, availableB, availableD; /* Code */ ASSERT(data); ASSERT(residual); ASSERT(above); ASSERT(left); ASSERT(h264bsdPredModeIntra16x16(pMb->mbType) < 4); availableA = h264bsdIsNeighbourAvailable(pMb, pMb->mbA); if (availableA && constrainedIntraPred && (h264bsdMbPartPredMode(pMb->mbA->mbType) == PRED_MODE_INTER)) availableA = HANTRO_FALSE; availableB = h264bsdIsNeighbourAvailable(pMb, pMb->mbB); if (availableB && constrainedIntraPred && (h264bsdMbPartPredMode(pMb->mbB->mbType) == PRED_MODE_INTER)) availableB = HANTRO_FALSE; availableD = h264bsdIsNeighbourAvailable(pMb, pMb->mbD); if (availableD && constrainedIntraPred && (h264bsdMbPartPredMode(pMb->mbD->mbType) == PRED_MODE_INTER)) availableD = HANTRO_FALSE; switch(h264bsdPredModeIntra16x16(pMb->mbType)) { case 0: /* Intra_16x16_Vertical */ if (!availableB) return(HANTRO_NOK); Intra16x16VerticalPrediction(data, above+1); break; case 1: /* Intra_16x16_Horizontal */ if (!availableA) return(HANTRO_NOK); Intra16x16HorizontalPrediction(data, left); break; case 2: /* Intra_16x16_DC */ Intra16x16DcPrediction(data, above+1, left, availableA, availableB); break; default: /* case 3: Intra_16x16_Plane */ if (!availableA || !availableB || !availableD) return(HANTRO_NOK); Intra16x16PlanePrediction(data, above+1, left); break; } /* add residual */ for (i = 0; i < 16; i++) h264bsdAddResidual(data, residual[i], i); return(HANTRO_OK); } /*------------------------------------------------------------------------------ Function: Intra4x4Prediction Functional description: Perform intra 4x4 prediction for luma pixels and add residual into prediction. The resulting luma pixels are stored in macroblock array 'data'. The intra 4x4 prediction mode for each block is stored in 'pMb' structure. ------------------------------------------------------------------------------*/ u32 h264bsdIntra4x4Prediction(mbStorage_t *pMb, u8 *data, macroblockLayer_t *mbLayer, u8 *above, u8 *left, u32 constrainedIntraPred) { /* Variables */ u32 block; u32 mode; neighbour_t neighbour, neighbourB; mbStorage_t *nMb, *nMb2; u8 a[1 + 4 + 4], l[1 + 4]; u32 data4x4[4]; u32 availableA, availableB, availableC, availableD; /* Code */ ASSERT(data); ASSERT(mbLayer); ASSERT(above); ASSERT(left); for (block = 0; block < 16; block++) { ASSERT(pMb->intra4x4PredMode[block] < 9); neighbour = *h264bsdNeighbour4x4BlockA(block); nMb = h264bsdGetNeighbourMb(pMb, neighbour.mb); availableA = h264bsdIsNeighbourAvailable(pMb, nMb); if (availableA && constrainedIntraPred && ( h264bsdMbPartPredMode(nMb->mbType) == PRED_MODE_INTER) ) { availableA = HANTRO_FALSE; } neighbourB = *h264bsdNeighbour4x4BlockB(block); nMb2 = h264bsdGetNeighbourMb(pMb, neighbourB.mb); availableB = h264bsdIsNeighbourAvailable(pMb, nMb2); if (availableB && constrainedIntraPred && ( h264bsdMbPartPredMode(nMb2->mbType) == PRED_MODE_INTER) ) { availableB = HANTRO_FALSE; } mode = DetermineIntra4x4PredMode(mbLayer, (u32)(availableA && availableB), &neighbour, &neighbourB, block, nMb, nMb2); pMb->intra4x4PredMode[block] = (u8)mode; neighbour = *h264bsdNeighbour4x4BlockC(block); nMb = h264bsdGetNeighbourMb(pMb, neighbour.mb); availableC = h264bsdIsNeighbourAvailable(pMb, nMb); if (availableC && constrainedIntraPred && ( h264bsdMbPartPredMode(nMb->mbType) == PRED_MODE_INTER) ) { availableC = HANTRO_FALSE; } neighbour = *h264bsdNeighbour4x4BlockD(block); nMb = h264bsdGetNeighbourMb(pMb, neighbour.mb); availableD = h264bsdIsNeighbourAvailable(pMb, nMb); if (availableD && constrainedIntraPred && ( h264bsdMbPartPredMode(nMb->mbType) == PRED_MODE_INTER) ) { availableD = HANTRO_FALSE; } Get4x4NeighbourPels(a, l, data, above, left, block); switch(mode) { case 0: /* Intra_4x4_Vertical */ if (!availableB) return(HANTRO_NOK); Intra4x4VerticalPrediction((u8*)data4x4, a + 1); break; case 1: /* Intra_4x4_Horizontal */ if (!availableA) return(HANTRO_NOK); Intra4x4HorizontalPrediction((u8*)data4x4, l + 1); break; case 2: /* Intra_4x4_DC */ Intra4x4DcPrediction((u8*)data4x4, a + 1, l + 1, availableA, availableB); break; case 3: /* Intra_4x4_Diagonal_Down_Left */ if (!availableB) return(HANTRO_NOK); if (!availableC) { a[5] = a[6] = a[7] = a[8] = a[4]; } Intra4x4DiagonalDownLeftPrediction((u8*)data4x4, a + 1); break; case 4: /* Intra_4x4_Diagonal_Down_Right */ if (!availableA || !availableB || !availableD) return(HANTRO_NOK); Intra4x4DiagonalDownRightPrediction((u8*)data4x4, a + 1, l + 1); break; case 5: /* Intra_4x4_Vertical_Right */ if (!availableA || !availableB || !availableD) return(HANTRO_NOK); Intra4x4VerticalRightPrediction((u8*)data4x4, a + 1, l + 1); break; case 6: /* Intra_4x4_Horizontal_Down */ if (!availableA || !availableB || !availableD) return(HANTRO_NOK); Intra4x4HorizontalDownPrediction((u8*)data4x4, a + 1, l + 1); break; case 7: /* Intra_4x4_Vertical_Left */ if (!availableB) return(HANTRO_NOK); if (!availableC) { a[5] = a[6] = a[7] = a[8] = a[4]; } Intra4x4VerticalLeftPrediction((u8*)data4x4, a + 1); break; default: /* case 8 Intra_4x4_Horizontal_Up */ if (!availableA) return(HANTRO_NOK); Intra4x4HorizontalUpPrediction((u8*)data4x4, l + 1); break; } Write4x4To16x16(data, (u8*)data4x4, block); h264bsdAddResidual(data, mbLayer->residual.level[block], block); } return(HANTRO_OK); } /*------------------------------------------------------------------------------ Function: IntraChromaPrediction Functional description: Perform intra prediction for chroma pixels and add residual into prediction. The resulting chroma pixels are stored in 'data'. ------------------------------------------------------------------------------*/ u32 h264bsdIntraChromaPrediction(mbStorage_t *pMb, u8 *data, i32 residual[][16], u8 *above, u8 *left, u32 predMode, u32 constrainedIntraPred) { /* Variables */ u32 i, comp, block; u32 availableA, availableB, availableD; /* Code */ ASSERT(data); ASSERT(residual); ASSERT(above); ASSERT(left); ASSERT(predMode < 4); availableA = h264bsdIsNeighbourAvailable(pMb, pMb->mbA); if (availableA && constrainedIntraPred && (h264bsdMbPartPredMode(pMb->mbA->mbType) == PRED_MODE_INTER)) availableA = HANTRO_FALSE; availableB = h264bsdIsNeighbourAvailable(pMb, pMb->mbB); if (availableB && constrainedIntraPred && (h264bsdMbPartPredMode(pMb->mbB->mbType) == PRED_MODE_INTER)) availableB = HANTRO_FALSE; availableD = h264bsdIsNeighbourAvailable(pMb, pMb->mbD); if (availableD && constrainedIntraPred && (h264bsdMbPartPredMode(pMb->mbD->mbType) == PRED_MODE_INTER)) availableD = HANTRO_FALSE; for (comp = 0, block = 16; comp < 2; comp++) { switch(predMode) { case 0: /* Intra_Chroma_DC */ IntraChromaDcPrediction(data, above+1, left, availableA, availableB); break; case 1: /* Intra_Chroma_Horizontal */ if (!availableA) return(HANTRO_NOK); IntraChromaHorizontalPrediction(data, left); break; case 2: /* Intra_Chroma_Vertical */ if (!availableB) return(HANTRO_NOK); IntraChromaVerticalPrediction(data, above+1); break; default: /* case 3: Intra_Chroma_Plane */ if (!availableA || !availableB || !availableD) return(HANTRO_NOK); IntraChromaPlanePrediction(data, above+1, left); break; } for (i = 0; i < 4; i++, block++) h264bsdAddResidual(data, residual[i], block); /* advance pointers */ data += 64; above += 9; left += 8; residual += 4; } return(HANTRO_OK); } /*------------------------------------------------------------------------------ Function: h264bsdAddResidual Functional description: Add residual of a block into prediction in macroblock array 'data'. The result (residual + prediction) is stored in 'data'. ------------------------------------------------------------------------------*/ #ifndef H264DEC_OMXDL void h264bsdAddResidual(u8 *data, i32 *residual, u32 blockNum) { /* Variables */ u32 i; u32 x, y; u32 width; i32 tmp1, tmp2, tmp3, tmp4; u8 *tmp; const u8 *clp = h264bsdClip + 512; /* Code */ ASSERT(data); ASSERT(residual); ASSERT(blockNum < 16 + 4 + 4); if (IS_RESIDUAL_EMPTY(residual)) return; RANGE_CHECK_ARRAY(residual, -512, 511, 16); if (blockNum < 16) { width = 16; x = h264bsdBlockX[blockNum]; y = h264bsdBlockY[blockNum]; } else { width = 8; x = h264bsdBlockX[blockNum & 0x3]; y = h264bsdBlockY[blockNum & 0x3]; } tmp = data + y*width + x; for (i = 4; i; i--) { tmp1 = *residual++; tmp2 = tmp[0]; tmp3 = *residual++; tmp4 = tmp[1]; tmp[0] = clp[tmp1 + tmp2]; tmp1 = *residual++; tmp2 = tmp[2]; tmp[1] = clp[tmp3 + tmp4]; tmp3 = *residual++; tmp4 = tmp[3]; tmp1 = clp[tmp1 + tmp2]; tmp3 = clp[tmp3 + tmp4]; tmp[2] = (u8)tmp1; tmp[3] = (u8)tmp3; tmp += width; } } #endif /*------------------------------------------------------------------------------ Function: Intra16x16VerticalPrediction Functional description: Perform intra 16x16 vertical prediction mode. ------------------------------------------------------------------------------*/ void Intra16x16VerticalPrediction(u8 *data, u8 *above) { /* Variables */ u32 i, j; /* Code */ ASSERT(data); ASSERT(above); for (i = 0; i < 16; i++) { for (j = 0; j < 16; j++) { *data++ = above[j]; } } } /*------------------------------------------------------------------------------ Function: Intra16x16HorizontalPrediction Functional description: Perform intra 16x16 horizontal prediction mode. ------------------------------------------------------------------------------*/ void Intra16x16HorizontalPrediction(u8 *data, u8 *left) { /* Variables */ u32 i, j; /* Code */ ASSERT(data); ASSERT(left); for (i = 0; i < 16; i++) { for (j = 0; j < 16; j++) { *data++ = left[i]; } } } /*------------------------------------------------------------------------------ Function: Intra16x16DcPrediction Functional description: Perform intra 16x16 DC prediction mode. ------------------------------------------------------------------------------*/ void Intra16x16DcPrediction(u8 *data, u8 *above, u8 *left, u32 availableA, u32 availableB) { /* Variables */ u32 i, tmp; /* Code */ ASSERT(data); ASSERT(above); ASSERT(left); if (availableA && availableB) { for (i = 0, tmp = 0; i < 16; i++) tmp += above[i] + left[i]; tmp = (tmp + 16) >> 5; } else if (availableA) { for (i = 0, tmp = 0; i < 16; i++) tmp += left[i]; tmp = (tmp + 8) >> 4; } else if (availableB) { for (i = 0, tmp = 0; i < 16; i++) tmp += above[i]; tmp = (tmp + 8) >> 4; } /* neither A nor B available */ else { tmp = 128; } for (i = 0; i < 256; i++) data[i] = (u8)tmp; } /*------------------------------------------------------------------------------ Function: Intra16x16PlanePrediction Functional description: Perform intra 16x16 plane prediction mode. ------------------------------------------------------------------------------*/ void Intra16x16PlanePrediction(u8 *data, u8 *above, u8 *left) { /* Variables */ i32 i, j; i32 a, b, c; i32 tmp; /* Code */ ASSERT(data); ASSERT(above); ASSERT(left); a = 16 * (above[15] + left[15]); for (i = 0, b = 0; i < 8; i++) b += (i + 1) * (above[8+i] - above[6-i]); b = (5 * b + 32) >> 6; for (i = 0, c = 0; i < 7; i++) c += (i + 1) * (left[8+i] - left[6-i]); /* p[-1,-1] has to be accessed through above pointer */ c += (i + 1) * (left[8+i] - above[-1]); c = (5 * c + 32) >> 6; for (i = 0; i < 16; i++) { for (j = 0; j < 16; j++) { tmp = (a + b * (j - 7) + c * (i - 7) + 16) >> 5; data[i*16+j] = (u8)CLIP1(tmp); } } } /*------------------------------------------------------------------------------ Function: IntraChromaDcPrediction Functional description: Perform intra chroma DC prediction mode. ------------------------------------------------------------------------------*/ void IntraChromaDcPrediction(u8 *data, u8 *above, u8 *left, u32 availableA, u32 availableB) { /* Variables */ u32 i; u32 tmp1, tmp2; /* Code */ ASSERT(data); ASSERT(above); ASSERT(left); /* y = 0..3 */ if (availableA && availableB) { tmp1 = above[0] + above[1] + above[2] + above[3] + left[0] + left[1] + left[2] + left[3]; tmp1 = (tmp1 + 4) >> 3; tmp2 = (above[4] + above[5] + above[6] + above[7] + 2) >> 2; } else if (availableB) { tmp1 = (above[0] + above[1] + above[2] + above[3] + 2) >> 2; tmp2 = (above[4] + above[5] + above[6] + above[7] + 2) >> 2; } else if (availableA) { tmp1 = (left[0] + left[1] + left[2] + left[3] + 2) >> 2; tmp2 = tmp1; } /* neither A nor B available */ else { tmp1 = tmp2 = 128; } ASSERT(tmp1 < 256 && tmp2 < 256); for (i = 4; i--;) { *data++ = (u8)tmp1; *data++ = (u8)tmp1; *data++ = (u8)tmp1; *data++ = (u8)tmp1; *data++ = (u8)tmp2; *data++ = (u8)tmp2; *data++ = (u8)tmp2; *data++ = (u8)tmp2; } /* y = 4...7 */ if (availableA) { tmp1 = (left[4] + left[5] + left[6] + left[7] + 2) >> 2; if (availableB) { tmp2 = above[4] + above[5] + above[6] + above[7] + left[4] + left[5] + left[6] + left[7]; tmp2 = (tmp2 + 4) >> 3; } else tmp2 = tmp1; } else if (availableB) { tmp1 = (above[0] + above[1] + above[2] + above[3] + 2) >> 2; tmp2 = (above[4] + above[5] + above[6] + above[7] + 2) >> 2; } else { tmp1 = tmp2 = 128; } ASSERT(tmp1 < 256 && tmp2 < 256); for (i = 4; i--;) { *data++ = (u8)tmp1; *data++ = (u8)tmp1; *data++ = (u8)tmp1; *data++ = (u8)tmp1; *data++ = (u8)tmp2; *data++ = (u8)tmp2; *data++ = (u8)tmp2; *data++ = (u8)tmp2; } } /*------------------------------------------------------------------------------ Function: IntraChromaHorizontalPrediction Functional description: Perform intra chroma horizontal prediction mode. ------------------------------------------------------------------------------*/ void IntraChromaHorizontalPrediction(u8 *data, u8 *left) { /* Variables */ u32 i; /* Code */ ASSERT(data); ASSERT(left); for (i = 8; i--;) { *data++ = *left; *data++ = *left; *data++ = *left; *data++ = *left; *data++ = *left; *data++ = *left; *data++ = *left; *data++ = *left++; } } /*------------------------------------------------------------------------------ Function: IntraChromaVerticalPrediction Functional description: Perform intra chroma vertical prediction mode. ------------------------------------------------------------------------------*/ void IntraChromaVerticalPrediction(u8 *data, u8 *above) { /* Variables */ u32 i; /* Code */ ASSERT(data); ASSERT(above); for (i = 8; i--;data++/*above-=8*/) { data[0] = *above; data[8] = *above; data[16] = *above; data[24] = *above; data[32] = *above; data[40] = *above; data[48] = *above; data[56] = *above++; } } /*------------------------------------------------------------------------------ Function: IntraChromaPlanePrediction Functional description: Perform intra chroma plane prediction mode. ------------------------------------------------------------------------------*/ void IntraChromaPlanePrediction(u8 *data, u8 *above, u8 *left) { /* Variables */ u32 i; i32 a, b, c; i32 tmp; const u8 *clp = h264bsdClip + 512; /* Code */ ASSERT(data); ASSERT(above); ASSERT(left); a = 16 * (above[7] + left[7]); b = (above[4] - above[2]) + 2 * (above[5] - above[1]) + 3 * (above[6] - above[0]) + 4 * (above[7] - above[-1]); b = (17 * b + 16) >> 5; /* p[-1,-1] has to be accessed through above pointer */ c = (left[4] - left[2]) + 2 * (left[5] - left[1]) + 3 * (left[6] - left[0]) + 4 * (left[7] - above[-1]); c = (17 * c + 16) >> 5; /*a += 16;*/ a = a - 3 * c + 16; for (i = 8; i--; a += c) { tmp = (a - 3 * b); *data++ = clp[tmp>>5]; tmp += b; *data++ = clp[tmp>>5]; tmp += b; *data++ = clp[tmp>>5]; tmp += b; *data++ = clp[tmp>>5]; tmp += b; *data++ = clp[tmp>>5]; tmp += b; *data++ = clp[tmp>>5]; tmp += b; *data++ = clp[tmp>>5]; tmp += b; *data++ = clp[tmp>>5]; } } /*------------------------------------------------------------------------------ Function: Get4x4NeighbourPels Functional description: Get neighbouring pixels of a 4x4 block into 'a' and 'l'. ------------------------------------------------------------------------------*/ void Get4x4NeighbourPels(u8 *a, u8 *l, u8 *data, u8 *above, u8 *left, u32 blockNum) { /* Variables */ u32 x, y; u8 t1, t2; /* Code */ ASSERT(a); ASSERT(l); ASSERT(data); ASSERT(above); ASSERT(left); ASSERT(blockNum < 16); x = h264bsdBlockX[blockNum]; y = h264bsdBlockY[blockNum]; /* A and D */ if (x == 0) { t1 = left[y ]; t2 = left[y + 1]; l[1] = t1; l[2] = t2; t1 = left[y + 2]; t2 = left[y + 3]; l[3] = t1; l[4] = t2; } else { t1 = data[y * 16 + x - 1 ]; t2 = data[y * 16 + x - 1 + 16]; l[1] = t1; l[2] = t2; t1 = data[y * 16 + x - 1 + 32]; t2 = data[y * 16 + x - 1 + 48]; l[3] = t1; l[4] = t2; } /* B, C and D */ if (y == 0) { t1 = above[x ]; t2 = above[x ]; l[0] = t1; a[0] = t2; t1 = above[x + 1]; t2 = above[x + 2]; a[1] = t1; a[2] = t2; t1 = above[x + 3]; t2 = above[x + 4]; a[3] = t1; a[4] = t2; t1 = above[x + 5]; t2 = above[x + 6]; a[5] = t1; a[6] = t2; t1 = above[x + 7]; t2 = above[x + 8]; a[7] = t1; a[8] = t2; } else { t1 = data[(y - 1) * 16 + x ]; t2 = data[(y - 1) * 16 + x + 1]; a[1] = t1; a[2] = t2; t1 = data[(y - 1) * 16 + x + 2]; t2 = data[(y - 1) * 16 + x + 3]; a[3] = t1; a[4] = t2; t1 = data[(y - 1) * 16 + x + 4]; t2 = data[(y - 1) * 16 + x + 5]; a[5] = t1; a[6] = t2; t1 = data[(y - 1) * 16 + x + 6]; t2 = data[(y - 1) * 16 + x + 7]; a[7] = t1; a[8] = t2; if (x == 0) l[0] = a[0] = left[y-1]; else l[0] = a[0] = data[(y - 1) * 16 + x - 1]; } } /*------------------------------------------------------------------------------ Function: Intra4x4VerticalPrediction Functional description: Perform intra 4x4 vertical prediction mode. ------------------------------------------------------------------------------*/ void Intra4x4VerticalPrediction(u8 *data, u8 *above) { /* Variables */ u8 t1, t2; /* Code */ ASSERT(data); ASSERT(above); t1 = above[0]; t2 = above[1]; data[0] = data[4] = data[8] = data[12] = t1; data[1] = data[5] = data[9] = data[13] = t2; t1 = above[2]; t2 = above[3]; data[2] = data[6] = data[10] = data[14] = t1; data[3] = data[7] = data[11] = data[15] = t2; } /*------------------------------------------------------------------------------ Function: Intra4x4HorizontalPrediction Functional description: Perform intra 4x4 horizontal prediction mode. ------------------------------------------------------------------------------*/ void Intra4x4HorizontalPrediction(u8 *data, u8 *left) { /* Variables */ u8 t1, t2; /* Code */ ASSERT(data); ASSERT(left); t1 = left[0]; t2 = left[1]; data[0] = data[1] = data[2] = data[3] = t1; data[4] = data[5] = data[6] = data[7] = t2; t1 = left[2]; t2 = left[3]; data[8] = data[9] = data[10] = data[11] = t1; data[12] = data[13] = data[14] = data[15] = t2; } /*------------------------------------------------------------------------------ Function: Intra4x4DcPrediction Functional description: Perform intra 4x4 DC prediction mode. ------------------------------------------------------------------------------*/ void Intra4x4DcPrediction(u8 *data, u8 *above, u8 *left, u32 availableA, u32 availableB) { /* Variables */ u32 tmp; u8 t1, t2, t3, t4; /* Code */ ASSERT(data); ASSERT(above); ASSERT(left); if (availableA && availableB) { t1 = above[0]; t2 = above[1]; t3 = above[2]; t4 = above[3]; tmp = t1 + t2 + t3 + t4; t1 = left[0]; t2 = left[1]; t3 = left[2]; t4 = left[3]; tmp += t1 + t2 + t3 + t4; tmp = (tmp + 4) >> 3; } else if (availableA) { t1 = left[0]; t2 = left[1]; t3 = left[2]; t4 = left[3]; tmp = (t1 + t2 + t3 + t4 + 2) >> 2; } else if (availableB) { t1 = above[0]; t2 = above[1]; t3 = above[2]; t4 = above[3]; tmp = (t1 + t2 + t3 + t4 + 2) >> 2; } else { tmp = 128; } ASSERT(tmp < 256); data[0] = data[1] = data[2] = data[3] = data[4] = data[5] = data[6] = data[7] = data[8] = data[9] = data[10] = data[11] = data[12] = data[13] = data[14] = data[15] = (u8)tmp; } /*------------------------------------------------------------------------------ Function: Intra4x4DiagonalDownLeftPrediction Functional description: Perform intra 4x4 diagonal down-left prediction mode. ------------------------------------------------------------------------------*/ void Intra4x4DiagonalDownLeftPrediction(u8 *data, u8 *above) { /* Variables */ /* Code */ ASSERT(data); ASSERT(above); data[ 0] = (above[0] + 2 * above[1] + above[2] + 2) >> 2; data[ 1] = (above[1] + 2 * above[2] + above[3] + 2) >> 2; data[ 4] = (above[1] + 2 * above[2] + above[3] + 2) >> 2; data[ 2] = (above[2] + 2 * above[3] + above[4] + 2) >> 2; data[ 5] = (above[2] + 2 * above[3] + above[4] + 2) >> 2; data[ 8] = (above[2] + 2 * above[3] + above[4] + 2) >> 2; data[ 3] = (above[3] + 2 * above[4] + above[5] + 2) >> 2; data[ 6] = (above[3] + 2 * above[4] + above[5] + 2) >> 2; data[ 9] = (above[3] + 2 * above[4] + above[5] + 2) >> 2; data[12] = (above[3] + 2 * above[4] + above[5] + 2) >> 2; data[ 7] = (above[4] + 2 * above[5] + above[6] + 2) >> 2; data[10] = (above[4] + 2 * above[5] + above[6] + 2) >> 2; data[13] = (above[4] + 2 * above[5] + above[6] + 2) >> 2; data[11] = (above[5] + 2 * above[6] + above[7] + 2) >> 2; data[14] = (above[5] + 2 * above[6] + above[7] + 2) >> 2; data[15] = (above[6] + 3 * above[7] + 2) >> 2; } /*------------------------------------------------------------------------------ Function: Intra4x4DiagonalDownRightPrediction Functional description: Perform intra 4x4 diagonal down-right prediction mode. ------------------------------------------------------------------------------*/ void Intra4x4DiagonalDownRightPrediction(u8 *data, u8 *above, u8 *left) { /* Variables */ /* Code */ ASSERT(data); ASSERT(above); ASSERT(left); data[ 0] = (above[0] + 2 * above[-1] + left[0] + 2) >> 2; data[ 5] = (above[0] + 2 * above[-1] + left[0] + 2) >> 2; data[10] = (above[0] + 2 * above[-1] + left[0] + 2) >> 2; data[15] = (above[0] + 2 * above[-1] + left[0] + 2) >> 2; data[ 1] = (above[-1] + 2 * above[0] + above[1] + 2) >> 2; data[ 6] = (above[-1] + 2 * above[0] + above[1] + 2) >> 2; data[11] = (above[-1] + 2 * above[0] + above[1] + 2) >> 2; data[ 2] = (above[0] + 2 * above[1] + above[2] + 2) >> 2; data[ 7] = (above[0] + 2 * above[1] + above[2] + 2) >> 2; data[ 3] = (above[1] + 2 * above[2] + above[3] + 2) >> 2; data[ 4] = (left[-1] + 2 * left[0] + left[1] + 2) >> 2; data[ 9] = (left[-1] + 2 * left[0] + left[1] + 2) >> 2; data[14] = (left[-1] + 2 * left[0] + left[1] + 2) >> 2; data[ 8] = (left[0] + 2 * left[1] + left[2] + 2) >> 2; data[13] = (left[0] + 2 * left[1] + left[2] + 2) >> 2; data[12] = (left[1] + 2 * left[2] + left[3] + 2) >> 2; } /*------------------------------------------------------------------------------ Function: Intra4x4VerticalRightPrediction Functional description: Perform intra 4x4 vertical right prediction mode. ------------------------------------------------------------------------------*/ void Intra4x4VerticalRightPrediction(u8 *data, u8 *above, u8 *left) { /* Variables */ /* Code */ ASSERT(data); ASSERT(above); ASSERT(left); data[ 0] = (above[-1] + above[0] + 1) >> 1; data[ 9] = (above[-1] + above[0] + 1) >> 1; data[ 5] = (above[-1] + 2 * above[0] + above[1] + 2) >> 2; data[14] = (above[-1] + 2 * above[0] + above[1] + 2) >> 2; data[ 4] = (above[0] + 2 * above[-1] + left[0] + 2) >> 2; data[13] = (above[0] + 2 * above[-1] + left[0] + 2) >> 2; data[ 1] = (above[0] + above[1] + 1) >> 1; data[10] = (above[0] + above[1] + 1) >> 1; data[ 6] = (above[0] + 2 * above[1] + above[2] + 2) >> 2; data[15] = (above[0] + 2 * above[1] + above[2] + 2) >> 2; data[ 2] = (above[1] + above[2] + 1) >> 1; data[11] = (above[1] + above[2] + 1) >> 1; data[ 7] = (above[1] + 2 * above[2] + above[3] + 2) >> 2; data[ 3] = (above[2] + above[3] + 1) >> 1; data[ 8] = (left[1] + 2 * left[0] + left[-1] + 2) >> 2; data[12] = (left[2] + 2 * left[1] + left[0] + 2) >> 2; } /*------------------------------------------------------------------------------ Function: Intra4x4HorizontalDownPrediction Functional description: Perform intra 4x4 horizontal down prediction mode. ------------------------------------------------------------------------------*/ void Intra4x4HorizontalDownPrediction(u8 *data, u8 *above, u8 *left) { /* Variables */ /* Code */ ASSERT(data); ASSERT(above); ASSERT(left); data[ 0] = (left[-1] + left[0] + 1) >> 1; data[ 6] = (left[-1] + left[0] + 1) >> 1; data[ 5] = (left[-1] + 2 * left[0] + left[1] + 2) >> 2; data[11] = (left[-1] + 2 * left[0] + left[1] + 2) >> 2; data[ 4] = (left[0] + left[1] + 1) >> 1; data[10] = (left[0] + left[1] + 1) >> 1; data[ 9] = (left[0] + 2 * left[1] + left[2] + 2) >> 2; data[15] = (left[0] + 2 * left[1] + left[2] + 2) >> 2; data[ 8] = (left[1] + left[2] + 1) >> 1; data[14] = (left[1] + left[2] + 1) >> 1; data[13] = (left[1] + 2 * left[2] + left[3] + 2) >> 2; data[12] = (left[2] + left[3] + 1) >> 1; data[ 1] = (above[0] + 2 * above[-1] + left[0] + 2) >> 2; data[ 7] = (above[0] + 2 * above[-1] + left[0] + 2) >> 2; data[ 2] = (above[1] + 2 * above[0] + above[-1] + 2) >> 2; data[ 3] = (above[2] + 2 * above[1] + above[0] + 2) >> 2; } /*------------------------------------------------------------------------------ Function: Intra4x4VerticalLeftPrediction Functional description: Perform intra 4x4 vertical left prediction mode. ------------------------------------------------------------------------------*/ void Intra4x4VerticalLeftPrediction(u8 *data, u8 *above) { /* Variables */ /* Code */ ASSERT(data); ASSERT(above); data[ 0] = (above[0] + above[1] + 1) >> 1; data[ 1] = (above[1] + above[2] + 1) >> 1; data[ 2] = (above[2] + above[3] + 1) >> 1; data[ 3] = (above[3] + above[4] + 1) >> 1; data[ 4] = (above[0] + 2 * above[1] + above[2] + 2) >> 2; data[ 5] = (above[1] + 2 * above[2] + above[3] + 2) >> 2; data[ 6] = (above[2] + 2 * above[3] + above[4] + 2) >> 2; data[ 7] = (above[3] + 2 * above[4] + above[5] + 2) >> 2; data[ 8] = (above[1] + above[2] + 1) >> 1; data[ 9] = (above[2] + above[3] + 1) >> 1; data[10] = (above[3] + above[4] + 1) >> 1; data[11] = (above[4] + above[5] + 1) >> 1; data[12] = (above[1] + 2 * above[2] + above[3] + 2) >> 2; data[13] = (above[2] + 2 * above[3] + above[4] + 2) >> 2; data[14] = (above[3] + 2 * above[4] + above[5] + 2) >> 2; data[15] = (above[4] + 2 * above[5] + above[6] + 2) >> 2; } /*------------------------------------------------------------------------------ Function: Intra4x4HorizontalUpPrediction Functional description: Perform intra 4x4 horizontal up prediction mode. ------------------------------------------------------------------------------*/ void Intra4x4HorizontalUpPrediction(u8 *data, u8 *left) { /* Variables */ /* Code */ ASSERT(data); ASSERT(left); data[ 0] = (left[0] + left[1] + 1) >> 1; data[ 1] = (left[0] + 2 * left[1] + left[2] + 2) >> 2; data[ 2] = (left[1] + left[2] + 1) >> 1; data[ 3] = (left[1] + 2 * left[2] + left[3] + 2) >> 2; data[ 4] = (left[1] + left[2] + 1) >> 1; data[ 5] = (left[1] + 2 * left[2] + left[3] + 2) >> 2; data[ 6] = (left[2] + left[3] + 1) >> 1; data[ 7] = (left[2] + 3 * left[3] + 2) >> 2; data[ 8] = (left[2] + left[3] + 1) >> 1; data[ 9] = (left[2] + 3 * left[3] + 2) >> 2; data[10] = left[3]; data[11] = left[3]; data[12] = left[3]; data[13] = left[3]; data[14] = left[3]; data[15] = left[3]; } #endif /* H264DEC_OMXDL */ /*------------------------------------------------------------------------------ Function: Write4x4To16x16 Functional description: Write a 4x4 block (data4x4) into correct position in 16x16 macroblock (data). ------------------------------------------------------------------------------*/ void Write4x4To16x16(u8 *data, u8 *data4x4, u32 blockNum) { /* Variables */ u32 x, y; u32 *in32, *out32; /* Code */ ASSERT(data); ASSERT(data4x4); ASSERT(blockNum < 16); x = h264bsdBlockX[blockNum]; y = h264bsdBlockY[blockNum]; data += y*16+x; ASSERT(((u32)data&0x3) == 0); /*lint --e(826) */ out32 = (u32 *)data; /*lint --e(826) */ in32 = (u32 *)data4x4; out32[0] = *in32++; out32[4] = *in32++; out32[8] = *in32++; out32[12] = *in32++; } /*------------------------------------------------------------------------------ Function: DetermineIntra4x4PredMode Functional description: Returns the intra 4x4 prediction mode of a block based on the neighbouring macroblocks and information parsed from stream. ------------------------------------------------------------------------------*/ u32 DetermineIntra4x4PredMode(macroblockLayer_t *pMbLayer, u32 available, neighbour_t *nA, neighbour_t *nB, u32 index, mbStorage_t *nMbA, mbStorage_t *nMbB) { /* Variables */ u32 mode1, mode2; mbStorage_t *pMb; /* Code */ ASSERT(pMbLayer); /* dc only prediction? */ if (!available) mode1 = 2; else { pMb = nMbA; if (h264bsdMbPartPredMode(pMb->mbType) == PRED_MODE_INTRA4x4) { mode1 = pMb->intra4x4PredMode[nA->index]; } else mode1 = 2; pMb = nMbB; if (h264bsdMbPartPredMode(pMb->mbType) == PRED_MODE_INTRA4x4) { mode2 = pMb->intra4x4PredMode[nB->index]; } else mode2 = 2; mode1 = MIN(mode1, mode2); } if (!pMbLayer->mbPred.prevIntra4x4PredModeFlag[index]) { if (pMbLayer->mbPred.remIntra4x4PredMode[index] < mode1) { mode1 = pMbLayer->mbPred.remIntra4x4PredMode[index]; } else { mode1 = pMbLayer->mbPred.remIntra4x4PredMode[index] + 1; } } return(mode1); } /*lint +e702 */