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 
h264bsdConceal(storage_t * pStorage,image_t * currImage,u32 sliceType)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 
ConcealMb(mbStorage_t * pMb,image_t * currImage,u32 row,u32 col,u32 sliceType,u8 * refData)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 
Transform(i32 * data)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