Home | History | Annotate | Download | only in source
      1 /*
      2  * Copyright (C) 2009 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 /*------------------------------------------------------------------------------
     18 
     19     Table of contents
     20 
     21      1. Include headers
     22      2. External compiler flags
     23      3. Module defines
     24      4. Local function prototypes
     25      5. Functions
     26           h264bsdConceal
     27           ConcealMb
     28           Transform
     29 
     30 ------------------------------------------------------------------------------*/
     31 
     32 /*------------------------------------------------------------------------------
     33     1. Include headers
     34 ------------------------------------------------------------------------------*/
     35 
     36 #include "h264bsd_conceal.h"
     37 #include "h264bsd_util.h"
     38 #include "h264bsd_reconstruct.h"
     39 #include "h264bsd_dpb.h"
     40 
     41 /*------------------------------------------------------------------------------
     42     2. External compiler flags
     43 --------------------------------------------------------------------------------
     44 
     45 --------------------------------------------------------------------------------
     46     3. Module defines
     47 ------------------------------------------------------------------------------*/
     48 
     49 /*lint -e702 disable lint warning on right shift of signed quantity */
     50 
     51 /*------------------------------------------------------------------------------
     52     4. Local function prototypes
     53 ------------------------------------------------------------------------------*/
     54 
     55 static u32 ConcealMb(mbStorage_t *pMb, image_t *currImage, u32 row, u32 col,
     56     u32 sliceType, u8 *data);
     57 
     58 static void Transform(i32 *data);
     59 
     60 /*------------------------------------------------------------------------------
     61 
     62     Function name: h264bsdConceal
     63 
     64         Functional description:
     65             Perform error concealment for a picture. Two types of concealment
     66             is performed based on sliceType:
     67                 1) copy from previous picture for P-slices.
     68                 2) concealment from neighbour pixels for I-slices
     69 
     70             I-type concealment is based on ideas presented by Jarno Tulkki.
     71             The concealment algorithm determines frequency domain coefficients
     72             from the neighbour pixels, applies integer transform (the same
     73             transform used in the residual processing) and uses the results as
     74             pixel values for concealed macroblocks. Transform produces 4x4
     75             array and one pixel value has to be used for 4x4 luma blocks and
     76             2x2 chroma blocks.
     77 
     78             Similar concealment is performed for whole picture (the choise
     79             of the type is based on last successfully decoded slice header of
     80             the picture but it is handled by the calling function). It is
     81             acknowledged that this may result in wrong type of concealment
     82             when a picture contains both types of slices. However,
     83             determination of slice type macroblock-by-macroblock cannot
     84             be done due to the fact that it is impossible to know to which
     85             slice each corrupted (not successfully decoded) macroblock
     86             belongs.
     87 
     88             The error concealment is started by searching the first propoerly
     89             decoded macroblock and concealing the row containing the macroblock
     90             in question. After that all macroblocks above the row in question
     91             are concealed. Finally concealment of rows below is performed.
     92             The order of concealment for 4x4 picture where macroblock 9 is the
     93             first properly decoded one is as follows (properly decoded
     94             macroblocks marked with 'x', numbers indicating the order of
     95             concealment):
     96 
     97                4  6  8 10
     98                3  5  7  9
     99                1  x  x  2
    100               11 12 13 14
    101 
    102             If all macroblocks of the picture are lost, the concealment is
    103             copy of previous picture for P-type and setting the image to
    104             constant gray (pixel value 128) for I-type.
    105 
    106             Concealment sets quantization parameter of the concealed
    107             macroblocks to value 40 and macroblock type to intra to enable
    108             deblocking filter to smooth the edges of the concealed areas.
    109 
    110         Inputs:
    111             pStorage        pointer to storage structure
    112             currImage       pointer to current image structure
    113             sliceType       type of the slice
    114 
    115         Outputs:
    116             currImage       concealed macroblocks will be written here
    117 
    118         Returns:
    119             HANTRO_OK
    120 
    121 ------------------------------------------------------------------------------*/
    122 
    123 u32 h264bsdConceal(storage_t *pStorage, image_t *currImage, u32 sliceType)
    124 {
    125 
    126 /* Variables */
    127 
    128     u32 i, j;
    129     u32 row, col;
    130     u32 width, height;
    131     u8 *refData;
    132     mbStorage_t *mb;
    133 
    134 /* Code */
    135 
    136     ASSERT(pStorage);
    137     ASSERT(currImage);
    138 
    139     DEBUG(("Concealing %s slice\n", IS_I_SLICE(sliceType) ?
    140             "intra" : "inter"));
    141 
    142     width = currImage->width;
    143     height = currImage->height;
    144     refData = NULL;
    145     /* use reference picture with smallest available index */
    146     if (IS_P_SLICE(sliceType) || (pStorage->intraConcealmentFlag != 0))
    147     {
    148         i = 0;
    149         do
    150         {
    151             refData = h264bsdGetRefPicData(pStorage->dpb, i);
    152             i++;
    153             if (i >= 16)
    154                 break;
    155         } while (refData == NULL);
    156     }
    157 
    158     i = row = col = 0;
    159     /* find first properly decoded macroblock -> start point for concealment */
    160     while (i < pStorage->picSizeInMbs && !pStorage->mb[i].decoded)
    161     {
    162         i++;
    163         col++;
    164         if (col == width)
    165         {
    166             row++;
    167             col = 0;
    168         }
    169     }
    170 
    171     /* whole picture lost -> copy previous or set grey */
    172     if (i == pStorage->picSizeInMbs)
    173     {
    174         if ( (IS_I_SLICE(sliceType) && (pStorage->intraConcealmentFlag == 0)) ||
    175              refData == NULL)
    176             H264SwDecMemset(currImage->data, 128, width*height*384);
    177         else
    178             H264SwDecMemcpy(currImage->data, refData, width*height*384);
    179 
    180         pStorage->numConcealedMbs = pStorage->picSizeInMbs;
    181 
    182         /* no filtering if whole picture concealed */
    183         for (i = 0; i < pStorage->picSizeInMbs; i++)
    184             pStorage->mb[i].disableDeblockingFilterIdc = 1;
    185 
    186         return(HANTRO_OK);
    187     }
    188 
    189     /* start from the row containing the first correct macroblock, conceal the
    190      * row in question, all rows above that row and then continue downwards */
    191     mb = pStorage->mb + row * width;
    192     for (j = col; j--;)
    193     {
    194         ConcealMb(mb+j, currImage, row, j, sliceType, refData);
    195         mb[j].decoded = 1;
    196         pStorage->numConcealedMbs++;
    197     }
    198     for (j = col + 1; j < width; j++)
    199     {
    200         if (!mb[j].decoded)
    201         {
    202             ConcealMb(mb+j, currImage, row, j, sliceType, refData);
    203             mb[j].decoded = 1;
    204             pStorage->numConcealedMbs++;
    205         }
    206     }
    207     /* if previous row(s) could not be concealed -> conceal them now */
    208     if (row)
    209     {
    210         for (j = 0; j < width; j++)
    211         {
    212             i = row - 1;
    213             mb = pStorage->mb + i*width + j;
    214             do
    215             {
    216                 ConcealMb(mb, currImage, i, j, sliceType, refData);
    217                 mb->decoded = 1;
    218                 pStorage->numConcealedMbs++;
    219                 mb -= width;
    220             } while(i--);
    221         }
    222     }
    223 
    224     /* process rows below the one containing the first correct macroblock */
    225     for (i = row + 1; i < height; i++)
    226     {
    227         mb = pStorage->mb + i * width;
    228 
    229         for (j = 0; j < width; j++)
    230         {
    231             if (!mb[j].decoded)
    232             {
    233                 ConcealMb(mb+j, currImage, i, j, sliceType, refData);
    234                 mb[j].decoded = 1;
    235                 pStorage->numConcealedMbs++;
    236             }
    237         }
    238     }
    239 
    240     return(HANTRO_OK);
    241 }
    242 
    243 /*------------------------------------------------------------------------------
    244 
    245     Function name: ConcealMb
    246 
    247         Functional description:
    248             Perform error concealment for one macroblock, location of the
    249             macroblock in the picture indicated by row and col
    250 
    251 ------------------------------------------------------------------------------*/
    252 
    253 u32 ConcealMb(mbStorage_t *pMb, image_t *currImage, u32 row, u32 col,
    254     u32 sliceType, u8 *refData)
    255 {
    256 
    257 /* Variables */
    258 
    259     u32 i, j, comp;
    260     u32 hor, ver;
    261     u32 mbNum;
    262     u32 width, height;
    263     u8 *mbPos;
    264     u8 data[384];
    265     u8 *pData;
    266     i32 tmp;
    267     i32 firstPhase[16];
    268     i32 *pTmp;
    269     /* neighbours above, below, left and right */
    270     i32 a[4] = { 0,0,0,0 }, b[4], l[4] = { 0,0,0,0 }, r[4];
    271     u32 A, B, L, R;
    272 #ifdef H264DEC_OMXDL
    273     u8 fillBuff[32*21 + 15 + 32];
    274     u8 *pFill;
    275 #endif
    276 /* Code */
    277 
    278     ASSERT(pMb);
    279     ASSERT(!pMb->decoded);
    280     ASSERT(currImage);
    281     ASSERT(col < currImage->width);
    282     ASSERT(row < currImage->height);
    283 
    284 #ifdef H264DEC_OMXDL
    285     pFill = ALIGN(fillBuff, 16);
    286 #endif
    287     width = currImage->width;
    288     height = currImage->height;
    289     mbNum = row * width + col;
    290 
    291     h264bsdSetCurrImageMbPointers(currImage, mbNum);
    292 
    293     mbPos = currImage->data + row * 16 * width * 16 + col * 16;
    294     A = B = L = R = HANTRO_FALSE;
    295 
    296     /* set qpY to 40 to enable some filtering in deblocking (stetson value) */
    297     pMb->qpY = 40;
    298     pMb->disableDeblockingFilterIdc = 0;
    299     /* mbType set to intra to perform filtering despite the values of other
    300      * boundary strength determination fields */
    301     pMb->mbType = I_4x4;
    302     pMb->filterOffsetA = 0;
    303     pMb->filterOffsetB = 0;
    304     pMb->chromaQpIndexOffset = 0;
    305 
    306     if (IS_I_SLICE(sliceType))
    307         H264SwDecMemset(data, 0, sizeof(data));
    308     else
    309     {
    310         mv_t mv = {0,0};
    311         image_t refImage;
    312         refImage.width = width;
    313         refImage.height = height;
    314         refImage.data = refData;
    315         if (refImage.data)
    316         {
    317 #ifndef H264DEC_OMXDL
    318             h264bsdPredictSamples(data, &mv, &refImage, col*16, row*16,
    319                 0, 0, 16, 16);
    320 #else
    321             h264bsdPredictSamples(data, &mv, &refImage,
    322                     ((row*16) + ((col*16)<<16)),
    323                     0x00001010, pFill);
    324 #endif
    325             h264bsdWriteMacroblock(currImage, data);
    326 
    327             return(HANTRO_OK);
    328         }
    329         else
    330             H264SwDecMemset(data, 0, sizeof(data));
    331     }
    332 
    333     H264SwDecMemset(firstPhase, 0, sizeof(firstPhase));
    334 
    335     /* counter for number of neighbours used */
    336     j = 0;
    337     hor = ver = 0;
    338     if (row && (pMb-width)->decoded)
    339     {
    340         A = HANTRO_TRUE;
    341         pData = mbPos - width*16;
    342         a[0] = *pData++; a[0] += *pData++; a[0] += *pData++; a[0] += *pData++;
    343         a[1] = *pData++; a[1] += *pData++; a[1] += *pData++; a[1] += *pData++;
    344         a[2] = *pData++; a[2] += *pData++; a[2] += *pData++; a[2] += *pData++;
    345         a[3] = *pData++; a[3] += *pData++; a[3] += *pData++; a[3] += *pData++;
    346         j++;
    347         hor++;
    348         firstPhase[0] += a[0] + a[1] + a[2] + a[3];
    349         firstPhase[1] += a[0] + a[1] - a[2] - a[3];
    350     }
    351     if ((row != height - 1) && (pMb+width)->decoded)
    352     {
    353         B = HANTRO_TRUE;
    354         pData = mbPos + 16*width*16;
    355         b[0] = *pData++; b[0] += *pData++; b[0] += *pData++; b[0] += *pData++;
    356         b[1] = *pData++; b[1] += *pData++; b[1] += *pData++; b[1] += *pData++;
    357         b[2] = *pData++; b[2] += *pData++; b[2] += *pData++; b[2] += *pData++;
    358         b[3] = *pData++; b[3] += *pData++; b[3] += *pData++; b[3] += *pData++;
    359         j++;
    360         hor++;
    361         firstPhase[0] += b[0] + b[1] + b[2] + b[3];
    362         firstPhase[1] += b[0] + b[1] - b[2] - b[3];
    363     }
    364     if (col && (pMb-1)->decoded)
    365     {
    366         L = HANTRO_TRUE;
    367         pData = mbPos - 1;
    368         l[0] = pData[0]; l[0] += pData[16*width];
    369         l[0] += pData[32*width]; l[0] += pData[48*width];
    370         pData += 64*width;
    371         l[1] = pData[0]; l[1] += pData[16*width];
    372         l[1] += pData[32*width]; l[1] += pData[48*width];
    373         pData += 64*width;
    374         l[2] = pData[0]; l[2] += pData[16*width];
    375         l[2] += pData[32*width]; l[2] += pData[48*width];
    376         pData += 64*width;
    377         l[3] = pData[0]; l[3] += pData[16*width];
    378         l[3] += pData[32*width]; l[3] += pData[48*width];
    379         j++;
    380         ver++;
    381         firstPhase[0] += l[0] + l[1] + l[2] + l[3];
    382         firstPhase[4] += l[0] + l[1] - l[2] - l[3];
    383     }
    384     if ((col != width - 1) && (pMb+1)->decoded)
    385     {
    386         R = HANTRO_TRUE;
    387         pData = mbPos + 16;
    388         r[0] = pData[0]; r[0] += pData[16*width];
    389         r[0] += pData[32*width]; r[0] += pData[48*width];
    390         pData += 64*width;
    391         r[1] = pData[0]; r[1] += pData[16*width];
    392         r[1] += pData[32*width]; r[1] += pData[48*width];
    393         pData += 64*width;
    394         r[2] = pData[0]; r[2] += pData[16*width];
    395         r[2] += pData[32*width]; r[2] += pData[48*width];
    396         pData += 64*width;
    397         r[3] = pData[0]; r[3] += pData[16*width];
    398         r[3] += pData[32*width]; r[3] += pData[48*width];
    399         j++;
    400         ver++;
    401         firstPhase[0] += r[0] + r[1] + r[2] + r[3];
    402         firstPhase[4] += r[0] + r[1] - r[2] - r[3];
    403     }
    404 
    405     /* at least one properly decoded neighbour available */
    406     ASSERT(j);
    407 
    408     /*lint -esym(644,l,r,a,b) variable initialized above */
    409     if (!hor && L && R)
    410         firstPhase[1] = (l[0]+l[1]+l[2]+l[3]-r[0]-r[1]-r[2]-r[3]) >> 5;
    411     else if (hor)
    412         firstPhase[1] >>= (3+hor);
    413 
    414     if (!ver && A && B)
    415         firstPhase[4] = (a[0]+a[1]+a[2]+a[3]-b[0]-b[1]-b[2]-b[3]) >> 5;
    416     else if (ver)
    417         firstPhase[4] >>= (3+ver);
    418 
    419     switch (j)
    420     {
    421         case 1:
    422             firstPhase[0] >>= 4;
    423             break;
    424 
    425         case 2:
    426             firstPhase[0] >>= 5;
    427             break;
    428 
    429         case 3:
    430             /* approximate (firstPhase[0]*4/3)>>6 */
    431             firstPhase[0] = (21 * firstPhase[0]) >> 10;
    432             break;
    433 
    434         default: /* 4 */
    435             firstPhase[0] >>= 6;
    436             break;
    437 
    438     }
    439 
    440 
    441     Transform(firstPhase);
    442 
    443     for (i = 0, pData = data, pTmp = firstPhase; i < 256;)
    444     {
    445         tmp = pTmp[(i & 0xF)>>2];
    446         /*lint -e734 CLIP1 macro results in value that fits into 8 bits */
    447         *pData++ = CLIP1(tmp);
    448         /*lint +e734 */
    449 
    450         i++;
    451         if (!(i & 0x3F))
    452             pTmp += 4;
    453     }
    454 
    455     /* chroma components */
    456     mbPos = currImage->data + width * height * 256 +
    457        row * 8 * width * 8 + col * 8;
    458     for (comp = 0; comp < 2; comp++)
    459     {
    460 
    461         H264SwDecMemset(firstPhase, 0, sizeof(firstPhase));
    462 
    463         /* counter for number of neighbours used */
    464         j = 0;
    465         hor = ver = 0;
    466         if (A)
    467         {
    468             pData = mbPos - width*8;
    469             a[0] = *pData++; a[0] += *pData++;
    470             a[1] = *pData++; a[1] += *pData++;
    471             a[2] = *pData++; a[2] += *pData++;
    472             a[3] = *pData++; a[3] += *pData++;
    473             j++;
    474             hor++;
    475             firstPhase[0] += a[0] + a[1] + a[2] + a[3];
    476             firstPhase[1] += a[0] + a[1] - a[2] - a[3];
    477         }
    478         if (B)
    479         {
    480             pData = mbPos + 8*width*8;
    481             b[0] = *pData++; b[0] += *pData++;
    482             b[1] = *pData++; b[1] += *pData++;
    483             b[2] = *pData++; b[2] += *pData++;
    484             b[3] = *pData++; b[3] += *pData++;
    485             j++;
    486             hor++;
    487             firstPhase[0] += b[0] + b[1] + b[2] + b[3];
    488             firstPhase[1] += b[0] + b[1] - b[2] - b[3];
    489         }
    490         if (L)
    491         {
    492             pData = mbPos - 1;
    493             l[0] = pData[0]; l[0] += pData[8*width];
    494             pData += 16*width;
    495             l[1] = pData[0]; l[1] += pData[8*width];
    496             pData += 16*width;
    497             l[2] = pData[0]; l[2] += pData[8*width];
    498             pData += 16*width;
    499             l[3] = pData[0]; l[3] += pData[8*width];
    500             j++;
    501             ver++;
    502             firstPhase[0] += l[0] + l[1] + l[2] + l[3];
    503             firstPhase[4] += l[0] + l[1] - l[2] - l[3];
    504         }
    505         if (R)
    506         {
    507             pData = mbPos + 8;
    508             r[0] = pData[0]; r[0] += pData[8*width];
    509             pData += 16*width;
    510             r[1] = pData[0]; r[1] += pData[8*width];
    511             pData += 16*width;
    512             r[2] = pData[0]; r[2] += pData[8*width];
    513             pData += 16*width;
    514             r[3] = pData[0]; r[3] += pData[8*width];
    515             j++;
    516             ver++;
    517             firstPhase[0] += r[0] + r[1] + r[2] + r[3];
    518             firstPhase[4] += r[0] + r[1] - r[2] - r[3];
    519         }
    520         if (!hor && L && R)
    521             firstPhase[1] = (l[0]+l[1]+l[2]+l[3]-r[0]-r[1]-r[2]-r[3]) >> 4;
    522         else if (hor)
    523             firstPhase[1] >>= (2+hor);
    524 
    525         if (!ver && A && B)
    526             firstPhase[4] = (a[0]+a[1]+a[2]+a[3]-b[0]-b[1]-b[2]-b[3]) >> 4;
    527         else if (ver)
    528             firstPhase[4] >>= (2+ver);
    529 
    530         switch (j)
    531         {
    532             case 1:
    533                 firstPhase[0] >>= 3;
    534                 break;
    535 
    536             case 2:
    537                 firstPhase[0] >>= 4;
    538                 break;
    539 
    540             case 3:
    541                 /* approximate (firstPhase[0]*4/3)>>5 */
    542                 firstPhase[0] = (21 * firstPhase[0]) >> 9;
    543                 break;
    544 
    545             default: /* 4 */
    546                 firstPhase[0] >>= 5;
    547                 break;
    548 
    549         }
    550 
    551         Transform(firstPhase);
    552 
    553         pData = data + 256 + comp*64;
    554         for (i = 0, pTmp = firstPhase; i < 64;)
    555         {
    556             tmp = pTmp[(i & 0x7)>>1];
    557             /*lint -e734 CLIP1 macro results in value that fits into 8 bits */
    558             *pData++ = CLIP1(tmp);
    559             /*lint +e734 */
    560 
    561             i++;
    562             if (!(i & 0xF))
    563                 pTmp += 4;
    564         }
    565 
    566         /* increment pointers for cr */
    567         mbPos += width * height * 64;
    568     }
    569 
    570     h264bsdWriteMacroblock(currImage, data);
    571 
    572     return(HANTRO_OK);
    573 
    574 }
    575 
    576 
    577 /*------------------------------------------------------------------------------
    578 
    579     Function name: Transform
    580 
    581         Functional description:
    582             Simplified transform, assuming that only dc component and lowest
    583             horizontal and lowest vertical component may be non-zero
    584 
    585 ------------------------------------------------------------------------------*/
    586 
    587 void Transform(i32 *data)
    588 {
    589 
    590     u32 col;
    591     i32 tmp0, tmp1;
    592 
    593     if (!data[1] && !data[4])
    594     {
    595         data[1]  = data[2]  = data[3]  = data[4]  = data[5]  =
    596         data[6]  = data[7]  = data[8]  = data[9]  = data[10] =
    597         data[11] = data[12] = data[13] = data[14] = data[15] = data[0];
    598         return;
    599     }
    600     /* first horizontal transform for rows 0 and 1 */
    601     tmp0 = data[0];
    602     tmp1 = data[1];
    603     data[0] = tmp0 + tmp1;
    604     data[1] = tmp0 + (tmp1>>1);
    605     data[2] = tmp0 - (tmp1>>1);
    606     data[3] = tmp0 - tmp1;
    607 
    608     tmp0 = data[4];
    609     data[5] = tmp0;
    610     data[6] = tmp0;
    611     data[7] = tmp0;
    612 
    613     /* then vertical transform */
    614     for (col = 4; col--; data++)
    615     {
    616         tmp0 = data[0];
    617         tmp1 = data[4];
    618         data[0] = tmp0 + tmp1;
    619         data[4] = tmp0 + (tmp1>>1);
    620         data[8] = tmp0 - (tmp1>>1);
    621         data[12] = tmp0 - tmp1;
    622     }
    623 
    624 }
    625 /*lint +e702 */
    626 
    627