| /* |
| * 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 */ |
| |
| |