OpenCores
URL https://opencores.org/ocsvn/bluespec-h264/bluespec-h264/trunk

Subversion Repositories bluespec-h264

[/] [bluespec-h264/] [trunk/] [test/] [decoder/] [ldecod/] [src/] [erc_do_i.c] - Blame information for rev 100

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jamey.hick
 
2
/*!
3
 *************************************************************************************
4
 * \file
5
 *      erc_do_i.c
6
 *
7
 * \brief
8
 *      Intra (I) frame error concealment algorithms for decoder
9
 *
10
 *  \author
11
 *      - Ari Hourunranta              <ari.hourunranta@nokia.com>
12
 *      - Viktor Varsa                 <viktor.varsa@nokia.com>
13
 *      - Ye-Kui Wang                  <wyk@ieee.org>
14
 *
15
 *************************************************************************************
16
 */
17
 
18
#include <stdlib.h>
19
#include "global.h"
20
#include "erc_do.h"
21
 
22
static void concealBlocks( int lastColumn, int lastRow, int comp, frame *recfr, int picSizeX, int *condition );
23
static void pixMeanInterpolateBlock( imgpel *src[], imgpel *block, int blockSize, int frameWidth );
24
 
25
/*!
26
 ************************************************************************
27
 * \brief
28
 *      The main function for Intra frame concealment.
29
 *      Calls "concealBlocks" for each color component (Y,U,V) separately
30
 * \return
31
 *      0, if the concealment was not successful and simple concealment should be used
32
 *      1, otherwise (even if none of the blocks were concealed)
33
 * \param recfr
34
 *      Reconstructed frame buffer
35
 * \param picSizeX
36
 *      Width of the frame in pixels
37
 * \param picSizeY
38
 *      Height of the frame in pixels
39
 * \param errorVar
40
 *      Variables for error concealment
41
 ************************************************************************
42
 */
43
int ercConcealIntraFrame( frame *recfr, int picSizeX, int picSizeY, ercVariables_t *errorVar )
44
{
45
  int lastColumn = 0, lastRow = 0;
46
 
47
  // if concealment is on
48
  if ( errorVar && errorVar->concealment )
49
  {
50
    // if there are segments to be concealed
51
    if ( errorVar->nOfCorruptedSegments )
52
    {
53
      // Y
54
      lastRow = (int) (picSizeY>>3);
55
      lastColumn = (int) (picSizeX>>3);
56
      concealBlocks( lastColumn, lastRow, 0, recfr, picSizeX, errorVar->yCondition );
57
 
58
      // U (dimensions halved compared to Y)
59
      lastRow = (int) (picSizeY>>4);
60
      lastColumn = (int) (picSizeX>>4);
61
      concealBlocks( lastColumn, lastRow, 1, recfr, picSizeX, errorVar->uCondition );
62
 
63
      // V ( dimensions equal to U )
64
      concealBlocks( lastColumn, lastRow, 2, recfr, picSizeX, errorVar->vCondition );
65
    }
66
    return 1;
67
  }
68
  else
69
    return 0;
70
}
71
 
72
/*!
73
 ************************************************************************
74
 * \brief
75
 *      Conceals the MB at position (row, column) using pixels from predBlocks[]
76
 *      using pixMeanInterpolateBlock()
77
 * \param currFrame
78
 *      current frame
79
 * \param row
80
 *      y coordinate in blocks
81
 * \param column
82
 *      x coordinate in blocks
83
 * \param predBlocks[]
84
 *      list of neighboring source blocks (numbering 0 to 7, 1 means: use the neighbor)
85
 * \param frameWidth
86
 *      width of frame in pixels
87
 * \param mbWidthInBlocks
88
 *      2 for Y, 1 for U/V components
89
 ************************************************************************
90
 */
91
void ercPixConcealIMB(imgpel *currFrame, int row, int column, int predBlocks[], int frameWidth, int mbWidthInBlocks)
92
{
93
   imgpel *src[8]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
94
   imgpel *currBlock = NULL;
95
 
96
   // collect the reliable neighboring blocks
97
   if (predBlocks[0])
98
      src[0] = currFrame + (row-mbWidthInBlocks)*frameWidth*8 + (column+mbWidthInBlocks)*8;
99
   if (predBlocks[1])
100
      src[1] = currFrame + (row-mbWidthInBlocks)*frameWidth*8 + (column-mbWidthInBlocks)*8;
101
   if (predBlocks[2])
102
      src[2] = currFrame + (row+mbWidthInBlocks)*frameWidth*8 + (column-mbWidthInBlocks)*8;
103
   if (predBlocks[3])
104
      src[3] = currFrame + (row+mbWidthInBlocks)*frameWidth*8 + (column+mbWidthInBlocks)*8;
105
   if (predBlocks[4])
106
      src[4] = currFrame + (row-mbWidthInBlocks)*frameWidth*8 + column*8;
107
   if (predBlocks[5])
108
      src[5] = currFrame + row*frameWidth*8 + (column-mbWidthInBlocks)*8;
109
   if (predBlocks[6])
110
      src[6] = currFrame + (row+mbWidthInBlocks)*frameWidth*8 + column*8;
111
   if (predBlocks[7])
112
      src[7] = currFrame + row*frameWidth*8 + (column+mbWidthInBlocks)*8;
113
 
114
   currBlock = currFrame + row*frameWidth*8 + column*8;
115
   pixMeanInterpolateBlock( src, currBlock, mbWidthInBlocks*8, frameWidth );
116
}
117
 
118
/*!
119
 ************************************************************************
120
 * \brief
121
 *      This function checks the neighbors of a Macroblock for usability in
122
 *      concealment. First the OK macroblocks are marked, and if there is not
123
 *      enough of them, then the CONCEALED ones as well.
124
 *      A "1" in the the output array means reliable, a "0" non reliable MB.
125
 *      The block order in "predBlocks":
126
 *              1 4 0
127
 *              5 x 7
128
 *              2 6 3
129
 *      i.e., corners first.
130
 * \return
131
 *      Number of useable neighbor macroblocks for concealment.
132
 * \param predBlocks[]
133
 *      Array for indicating the valid neighbor blocks
134
 * \param currRow
135
 *      Current block row in the frame
136
 * \param currColumn
137
 *      Current block column in the frame
138
 * \param condition
139
 *      The block condition (ok, lost) table
140
 * \param maxRow
141
 *      Number of block rows in the frame
142
 * \param maxColumn
143
 *      Number of block columns in the frame
144
 * \param step
145
 *      Number of blocks belonging to a MB, when counting
146
 *      in vertical/horizontal direction. (Y:2 U,V:1)
147
 * \param fNoCornerNeigh
148
 *      No corner neighbors are considered
149
 ************************************************************************
150
 */
151
int ercCollect8PredBlocks( int predBlocks[], int currRow, int currColumn, int *condition,
152
                           int maxRow, int maxColumn, int step, byte fNoCornerNeigh )
153
{
154
  int srcCounter  = 0;
155
  int srcCountMin = (fNoCornerNeigh ? 2 : 4);
156
  int threshold   = ERC_BLOCK_OK;
157
 
158
  memset( predBlocks, 0, 8*sizeof(int) );
159
 
160
  // collect the reliable neighboring blocks
161
  do
162
  {
163
    srcCounter = 0;
164
    // top
165
    if (currRow > 0 && condition[ (currRow-1)*maxColumn + currColumn ] >= threshold )
166
    {                           //ERC_BLOCK_OK (3) or ERC_BLOCK_CONCEALED (2)
167
      predBlocks[4] = condition[ (currRow-1)*maxColumn + currColumn ];
168
      srcCounter++;
169
    }
170
    // bottom
171
    if ( currRow < (maxRow-step) && condition[ (currRow+step)*maxColumn + currColumn ] >= threshold )
172
    {
173
      predBlocks[6] = condition[ (currRow+step)*maxColumn + currColumn ];
174
      srcCounter++;
175
    }
176
 
177
    if ( currColumn > 0 )
178
    {
179
      // left
180
      if ( condition[ currRow*maxColumn + currColumn - 1 ] >= threshold )
181
      {
182
        predBlocks[5] = condition[ currRow*maxColumn + currColumn - 1 ];
183
        srcCounter++;
184
      }
185
 
186
      if ( !fNoCornerNeigh )
187
      {
188
        // top-left
189
        if ( currRow > 0 && condition[ (currRow-1)*maxColumn + currColumn - 1 ] >= threshold )
190
        {
191
          predBlocks[1] = condition[ (currRow-1)*maxColumn + currColumn - 1 ];
192
          srcCounter++;
193
        }
194
        // bottom-left
195
        if ( currRow < (maxRow-step) && condition[ (currRow+step)*maxColumn + currColumn - 1 ] >= threshold )
196
        {
197
          predBlocks[2] = condition[ (currRow+step)*maxColumn + currColumn - 1 ];
198
          srcCounter++;
199
        }
200
      }
201
    }
202
 
203
    if ( currColumn < (maxColumn-step) )
204
    {
205
      // right
206
      if ( condition[ currRow*maxColumn+currColumn + step ] >= threshold )
207
      {
208
        predBlocks[7] = condition[ currRow*maxColumn+currColumn + step ];
209
        srcCounter++;
210
      }
211
 
212
      if ( !fNoCornerNeigh )
213
      {
214
        // top-right
215
        if ( currRow > 0 && condition[ (currRow-1)*maxColumn + currColumn + step ] >= threshold )
216
        {
217
          predBlocks[0] = condition[ (currRow-1)*maxColumn + currColumn + step ];
218
          srcCounter++;
219
        }
220
        // bottom-right
221
        if ( currRow < (maxRow-step) && condition[ (currRow+step)*maxColumn + currColumn + step ] >= threshold )
222
        {
223
          predBlocks[3] = condition[ (currRow+step)*maxColumn + currColumn + step ];
224
          srcCounter++;
225
        }
226
      }
227
    }
228
    // prepare for the next round
229
    threshold--;
230
    if (threshold < ERC_BLOCK_CONCEALED)
231
      break;
232
  } while ( srcCounter < srcCountMin);
233
 
234
  return srcCounter;
235
}
236
 
237
/*!
238
 ************************************************************************
239
 * \brief
240
 *      collects prediction blocks only from the current column
241
 * \return
242
 *      Number of usable neighbour Macroblocks for concealment.
243
 * \param predBlocks[]
244
 *      Array for indicating the valid neighbor blocks
245
 * \param currRow
246
 *      Current block row in the frame
247
 * \param currColumn
248
 *      Current block column in the frame
249
 * \param condition
250
 *      The block condition (ok, lost) table
251
 * \param maxRow
252
 *      Number of block rows in the frame
253
 * \param maxColumn
254
 *      Number of block columns in the frame
255
 * \param step
256
 *      Number of blocks belonging to a MB, when counting
257
 *      in vertical/horizontal direction. (Y:2 U,V:1)
258
 ************************************************************************
259
 */
260
int ercCollectColumnBlocks( int predBlocks[], int currRow, int currColumn, int *condition, int maxRow, int maxColumn, int step )
261
{
262
  int srcCounter = 0, threshold = ERC_BLOCK_CORRUPTED;
263
 
264
  memset( predBlocks, 0, 8*sizeof(int) );
265
 
266
  // in this case, row > 0 and row < 17
267
  if ( condition[ (currRow-1)*maxColumn + currColumn ] > threshold )
268
  {
269
    predBlocks[4] = 1;
270
    srcCounter++;
271
  }
272
  if ( condition[ (currRow+step)*maxColumn + currColumn ] > threshold )
273
  {
274
    predBlocks[6] = 1;
275
    srcCounter++;
276
  }
277
 
278
  return srcCounter;
279
}
280
 
281
/*!
282
 ************************************************************************
283
 * \brief
284
 *      Core for the Intra blocks concealment.
285
 *      It is called for each color component (Y,U,V) separately
286
 *      Finds the corrupted blocks and calls pixel interpolation functions
287
 *      to correct them, one block at a time.
288
 *      Scanning is done vertically and each corrupted column is corrected
289
 *      bi-directionally, i.e., first block, last block, first block+1, last block -1 ...
290
 * \param lastColumn
291
 *      Number of block columns in the frame
292
 * \param lastRow
293
 *      Number of block rows in the frame
294
 * \param comp
295
 *      color component
296
 * \param recfr
297
 *      Reconstructed frame buffer
298
 * \param picSizeX
299
 *      Width of the frame in pixels
300
 * \param condition
301
 *      The block condition (ok, lost) table
302
 ************************************************************************
303
 */
304
static void concealBlocks( int lastColumn, int lastRow, int comp, frame *recfr, int picSizeX, int *condition )
305
{
306
  int row, column, srcCounter = 0,  thr = ERC_BLOCK_CORRUPTED,
307
      lastCorruptedRow = -1, firstCorruptedRow = -1, currRow = 0,
308
      areaHeight = 0, i = 0, smoothColumn = 0;
309
  int predBlocks[8], step = 1;
310
 
311
  // in the Y component do the concealment MB-wise (not block-wise):
312
  // this is useful if only whole MBs can be damaged or lost
313
  if ( comp == 0 )
314
    step = 2;
315
  else
316
    step = 1;
317
 
318
  for ( column = 0; column < lastColumn; column += step )
319
  {
320
    for ( row = 0; row < lastRow; row += step )
321
    {
322
      if ( condition[row*lastColumn+column] <= thr )
323
      {
324
        firstCorruptedRow = row;
325
        // find the last row which has corrupted blocks (in same continuous area)
326
        for ( lastCorruptedRow = row+step; lastCorruptedRow < lastRow; lastCorruptedRow += step )
327
        {
328
          // check blocks in the current column
329
          if ( condition[ lastCorruptedRow*lastColumn + column ] > thr )
330
          {
331
            // current one is already OK, so the last was the previous one
332
            lastCorruptedRow -= step;
333
            break;
334
          }
335
        }
336
        if ( lastCorruptedRow >= lastRow )
337
        {
338
          // correct only from above
339
          lastCorruptedRow = lastRow-step;
340
          for ( currRow = firstCorruptedRow; currRow < lastRow; currRow += step )
341
          {
342
            srcCounter = ercCollect8PredBlocks( predBlocks, currRow, column, condition, lastRow, lastColumn, step, 1 );
343
 
344
            switch( comp )
345
            {
346
            case 0 :
347
              ercPixConcealIMB( recfr->yptr, currRow, column, predBlocks, picSizeX, 2 );
348
              break;
349
            case 1 :
350
              ercPixConcealIMB( recfr->uptr, currRow, column, predBlocks, (picSizeX>>1), 1 );
351
              break;
352
            case 2 :
353
              ercPixConcealIMB( recfr->vptr, currRow, column, predBlocks, (picSizeX>>1), 1 );
354
              break;
355
            }
356
 
357
            if ( comp == 0 )
358
            {
359
              condition[ currRow*lastColumn+column] = ERC_BLOCK_CONCEALED;
360
              condition[ currRow*lastColumn+column + 1] = ERC_BLOCK_CONCEALED;
361
              condition[ currRow*lastColumn+column + lastColumn] = ERC_BLOCK_CONCEALED;
362
              condition[ currRow*lastColumn+column + lastColumn + 1] = ERC_BLOCK_CONCEALED;
363
            }
364
            else
365
            {
366
              condition[ currRow*lastColumn+column] = ERC_BLOCK_CONCEALED;
367
            }
368
 
369
          }
370
          row = lastRow;
371
        }
372
        else if ( firstCorruptedRow == 0 )
373
        {
374
          // correct only from below
375
          for ( currRow = lastCorruptedRow; currRow >= 0; currRow -= step )
376
          {
377
            srcCounter = ercCollect8PredBlocks( predBlocks, currRow, column, condition, lastRow, lastColumn, step, 1 );
378
 
379
            switch( comp )
380
            {
381
            case 0 :
382
              ercPixConcealIMB( recfr->yptr, currRow, column, predBlocks, picSizeX, 2 );
383
              break;
384
            case 1 :
385
              ercPixConcealIMB( recfr->uptr, currRow, column, predBlocks, (picSizeX>>1), 1 );
386
              break;
387
            case 2 :
388
              ercPixConcealIMB( recfr->vptr, currRow, column, predBlocks, (picSizeX>>1), 1 );
389
              break;
390
            }
391
 
392
            if ( comp == 0 )
393
            {
394
              condition[ currRow*lastColumn+column] = ERC_BLOCK_CONCEALED;
395
              condition[ currRow*lastColumn+column + 1] = ERC_BLOCK_CONCEALED;
396
              condition[ currRow*lastColumn+column + lastColumn] = ERC_BLOCK_CONCEALED;
397
              condition[ currRow*lastColumn+column + lastColumn + 1] = ERC_BLOCK_CONCEALED;
398
            }
399
            else
400
            {
401
              condition[ currRow*lastColumn+column] = ERC_BLOCK_CONCEALED;
402
            }
403
 
404
          }
405
 
406
          row = lastCorruptedRow+step;
407
        }
408
        else
409
        {
410
          // correct bi-directionally
411
 
412
          row = lastCorruptedRow+step;
413
          areaHeight = lastCorruptedRow-firstCorruptedRow+step;
414
 
415
          // Conceal the corrupted area switching between the up and the bottom rows
416
          for ( i = 0; i < areaHeight; i += step )
417
          {
418
            if ( i % 2 )
419
            {
420
              currRow = lastCorruptedRow;
421
              lastCorruptedRow -= step;
422
            }
423
            else
424
            {
425
              currRow = firstCorruptedRow;
426
              firstCorruptedRow += step;
427
            }
428
 
429
            if (smoothColumn > 0)
430
            {
431
              srcCounter = ercCollectColumnBlocks( predBlocks, currRow, column, condition, lastRow, lastColumn, step );
432
            }
433
            else
434
            {
435
              srcCounter = ercCollect8PredBlocks( predBlocks, currRow, column, condition, lastRow, lastColumn, step, 1 );
436
            }
437
 
438
            switch( comp )
439
            {
440
            case 0 :
441
              ercPixConcealIMB( recfr->yptr, currRow, column, predBlocks, picSizeX, 2 );
442
              break;
443
 
444
            case 1 :
445
              ercPixConcealIMB( recfr->uptr, currRow, column, predBlocks, (picSizeX>>1), 1 );
446
              break;
447
 
448
            case 2 :
449
              ercPixConcealIMB( recfr->vptr, currRow, column, predBlocks, (picSizeX>>1), 1 );
450
              break;
451
            }
452
 
453
            if ( comp == 0 )
454
            {
455
              condition[ currRow*lastColumn+column] = ERC_BLOCK_CONCEALED;
456
              condition[ currRow*lastColumn+column + 1] = ERC_BLOCK_CONCEALED;
457
              condition[ currRow*lastColumn+column + lastColumn] = ERC_BLOCK_CONCEALED;
458
              condition[ currRow*lastColumn+column + lastColumn + 1] = ERC_BLOCK_CONCEALED;
459
            }
460
            else
461
            {
462
              condition[ currRow*lastColumn+column ] = ERC_BLOCK_CONCEALED;
463
            }
464
          }
465
        }
466
 
467
        lastCorruptedRow = -1;
468
        firstCorruptedRow = -1;
469
 
470
      }
471
    }
472
  }
473
}
474
 
475
/*!
476
 ************************************************************************
477
 * \brief
478
 *      Does the actual pixel based interpolation for block[]
479
 *      using weighted average
480
 * \param src[]
481
 *      pointers to neighboring source blocks
482
 * \param block
483
 *      destination block
484
 * \param blockSize
485
 *      16 for Y, 8 for U/V components
486
 * \param frameWidth
487
 *      Width of the frame in pixels
488
 ************************************************************************
489
 */
490
static void pixMeanInterpolateBlock( imgpel *src[], imgpel *block, int blockSize, int frameWidth )
491
{
492
  int row, column, k, tmp, srcCounter = 0, weight = 0, bmax = blockSize - 1;
493
 
494
  k = 0;
495
  for ( row = 0; row < blockSize; row++ )
496
  {
497
    for ( column = 0; column < blockSize; column++ )
498
    {
499
      tmp = 0;
500
      srcCounter = 0;
501
      // above
502
      if ( src[4] != NULL )
503
      {
504
        weight = blockSize-row;
505
        tmp += weight * (*(src[4]+bmax*frameWidth+column));
506
        srcCounter += weight;
507
      }
508
      // left
509
      if ( src[5] != NULL )
510
      {
511
        weight = blockSize-column;
512
        tmp += weight * (*(src[5]+row*frameWidth+bmax));
513
        srcCounter += weight;
514
      }
515
      // below
516
      if ( src[6] != NULL )
517
      {
518
        weight = row+1;
519
        tmp += weight * (*(src[6]+column));
520
        srcCounter += weight;
521
      }
522
      // right
523
      if ( src[7] != NULL )
524
      {
525
        weight = column+1;
526
        tmp += weight * (*(src[7]+row*frameWidth));
527
        srcCounter += weight;
528
      }
529
 
530
      if ( srcCounter > 0 )
531
        block[ k + column ] = (byte)(tmp/srcCounter);
532
      else
533
        block[ k + column ] = blockSize == 8 ? img->dc_pred_value_chroma : img->dc_pred_value_luma;
534
    }
535
    k += frameWidth;
536
  }
537
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.