PageRenderTime 113ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/H264Dec/source/h264bsd_conceal.c

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