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