1
2 /*!
3 *************************************************************************************
4 * \file
5 * erc_do_p.c
6 *
7 * \brief
8 * Inter (P) frame error concealment algorithms for decoder
9 *
10 * \author
11 * - Viktor Varsa <viktor.varsa@nokia.com>
12 * - Ye-Kui Wang <wyk@ieee.org>
13 * - Jill Boyce <jill.boyce@thomson.net>
14 * - Saurav K Bandyopadhyay <saurav@ieee.org>
15 * - Zhenyu Wu <Zhenyu.Wu@thomson.net>
16 * - Purvin Pandit <Purvin.Pandit@thomson.net>
17 *
18 *************************************************************************************
19 */
20
21 #include "global.h"
22 #include "mbuffer.h"
23 #include "memalloc.h"
24 #include "erc_do.h"
25 #include "image.h"
26 #include "mc_prediction.h"
27 #include "macroblock.h"
28
29
30 // static function declarations
31 static int concealByCopy(frame *recfr, int currMBNum, objectBuffer_t *object_list, int picSizeX);
32 static int concealByTrial(frame *recfr, imgpel *predMB,
33 int currMBNum, objectBuffer_t *object_list, int predBlocks[],
34 int picSizeX, int picSizeY, char *yCondition);
35 static int edgeDistortion (int predBlocks[], int currYBlockNum, imgpel *predMB,
36 imgpel *recY, int picSizeX, int regionSize);
37 static void copyBetweenFrames (frame *recfr, int currYBlockNum, int picSizeX, int regionSize);
38 static void buildPredRegionYUV(VideoParameters *p_Vid, int *mv, int x, int y, imgpel *predMB);
39
40 // picture error concealment
41 static void buildPredblockRegionYUV(VideoParameters *p_Vid, int *mv,
42 int x, int y, imgpel *predMB, int list, int mb);
43 static void CopyImgData(imgpel **inputY, imgpel ***inputUV, imgpel **outputY, imgpel ***outputUV,
44 int img_width, int img_height, int img_width_cr, int img_height_cr);
45
46 static void copyPredMB (int currYBlockNum, imgpel *predMB, frame *recfr,
47 int picSizeX, int regionSize);
48 static void add_node ( VideoParameters *p_Vid, struct concealment_node *ptr );
49 static void delete_node( VideoParameters *p_Vid, struct concealment_node *ptr );
50
51 static const int uv_div[2][4] = {{0, 1, 1, 0}, {0, 1, 0, 0}}; //[x/y][yuv_format]
52
53 /*!
54 ************************************************************************
55 * \brief
56 * The main function for Inter (P) frame concealment.
57 * \return
58 * 0, if the concealment was not successful and simple concealment should be used
59 * 1, otherwise (even if none of the blocks were concealed)
60 * \param recfr
61 * Reconstructed frame buffer
62 * \param object_list
63 * Motion info for all MBs in the frame
64 * \param picSizeX
65 * Width of the frame in pixels
66 * \param picSizeY
67 * Height of the frame in pixels
68 * \param errorVar
69 * Variables for error concealment
70 * \param chroma_format_idc
71 * Chroma format IDC
72 ************************************************************************
73 */
ercConcealInterFrame(frame * recfr,objectBuffer_t * object_list,int picSizeX,int picSizeY,ercVariables_t * errorVar,int chroma_format_idc)74 int ercConcealInterFrame(frame *recfr, objectBuffer_t *object_list,
75 int picSizeX, int picSizeY, ercVariables_t *errorVar, int chroma_format_idc )
76 {
77 VideoParameters *p_Vid = recfr->p_Vid;
78 int lastColumn = 0, lastRow = 0, predBlocks[8];
79 int lastCorruptedRow = -1, firstCorruptedRow = -1;
80 int currRow = 0, row, column, columnInd, areaHeight = 0, i = 0;
81 imgpel *predMB;
82
83 /* if concealment is on */
84 if ( errorVar && errorVar->concealment )
85 {
86 /* if there are segments to be concealed */
87 if ( errorVar->nOfCorruptedSegments )
88 {
89 if (chroma_format_idc != YUV400)
90 predMB = (imgpel *) malloc ( (256 + (p_Vid->mb_cr_size)*2) * sizeof (imgpel));
91 else
92 predMB = (imgpel *) malloc(256 * sizeof (imgpel));
93
94 if ( predMB == NULL ) no_mem_exit("ercConcealInterFrame: predMB");
95
96 lastRow = (int) (picSizeY>>4);
97 lastColumn = (int) (picSizeX>>4);
98
99 for ( columnInd = 0; columnInd < lastColumn; columnInd ++)
100 {
101
102 column = ((columnInd%2) ? (lastColumn - columnInd/2 -1) : (columnInd/2));
103
104 for ( row = 0; row < lastRow; row++)
105 {
106
107 if ( errorVar->yCondition[MBxy2YBlock(column, row, 0, picSizeX)] <= ERC_BLOCK_CORRUPTED )
108 { // ERC_BLOCK_CORRUPTED (1) or ERC_BLOCK_EMPTY (0)
109 firstCorruptedRow = row;
110 /* find the last row which has corrupted blocks (in same continuous area) */
111 for ( lastCorruptedRow = row+1; lastCorruptedRow < lastRow; lastCorruptedRow++)
112 {
113 /* check blocks in the current column */
114 if (errorVar->yCondition[MBxy2YBlock(column, lastCorruptedRow, 0, picSizeX)] > ERC_BLOCK_CORRUPTED)
115 {
116 /* current one is already OK, so the last was the previous one */
117 lastCorruptedRow --;
118 break;
119 }
120 }
121 if ( lastCorruptedRow >= lastRow )
122 {
123 /* correct only from above */
124 lastCorruptedRow = lastRow-1;
125 for ( currRow = firstCorruptedRow; currRow < lastRow; currRow++ )
126 {
127
128 ercCollect8PredBlocks (predBlocks, (currRow<<1), (column<<1),
129 errorVar->yCondition, (lastRow<<1), (lastColumn<<1), 2, 0);
130
131 if(p_Vid->erc_mvperMB >= MVPERMB_THR)
132 concealByTrial(recfr, predMB,
133 currRow*lastColumn+column, object_list, predBlocks,
134 picSizeX, picSizeY,
135 errorVar->yCondition);
136 else
137 concealByCopy(recfr, currRow*lastColumn+column,
138 object_list, picSizeX);
139
140 ercMarkCurrMBConcealed (currRow*lastColumn+column, -1, picSizeX, errorVar);
141 }
142 row = lastRow;
143 }
144 else if ( firstCorruptedRow == 0 )
145 {
146 /* correct only from below */
147 for ( currRow = lastCorruptedRow; currRow >= 0; currRow-- )
148 {
149
150 ercCollect8PredBlocks (predBlocks, (currRow<<1), (column<<1),
151 errorVar->yCondition, (lastRow<<1), (lastColumn<<1), 2, 0);
152
153 if(p_Vid->erc_mvperMB >= MVPERMB_THR)
154 concealByTrial(recfr, predMB,
155 currRow*lastColumn+column, object_list, predBlocks,
156 picSizeX, picSizeY,
157 errorVar->yCondition);
158 else
159 concealByCopy(recfr, currRow*lastColumn+column,
160 object_list, picSizeX);
161
162 ercMarkCurrMBConcealed (currRow*lastColumn+column, -1, picSizeX, errorVar);
163 }
164
165 row = lastCorruptedRow+1;
166 }
167 else
168 {
169 /* correct bi-directionally */
170
171 row = lastCorruptedRow+1;
172
173 areaHeight = lastCorruptedRow-firstCorruptedRow+1;
174
175 /*
176 * Conceal the corrupted area switching between the up and the bottom rows
177 */
178 for ( i = 0; i < areaHeight; i++)
179 {
180 if ( i % 2 )
181 {
182 currRow = lastCorruptedRow;
183 lastCorruptedRow --;
184 }
185 else
186 {
187 currRow = firstCorruptedRow;
188 firstCorruptedRow ++;
189 }
190
191 ercCollect8PredBlocks (predBlocks, (currRow<<1), (column<<1),
192 errorVar->yCondition, (lastRow<<1), (lastColumn<<1), 2, 0);
193
194 if(p_Vid->erc_mvperMB >= MVPERMB_THR)
195 concealByTrial(recfr, predMB,
196 currRow*lastColumn+column, object_list, predBlocks,
197 picSizeX, picSizeY,
198 errorVar->yCondition);
199 else
200 concealByCopy(recfr, currRow*lastColumn+column,
201 object_list, picSizeX);
202
203 ercMarkCurrMBConcealed (currRow*lastColumn+column, -1, picSizeX, errorVar);
204
205 }
206 }
207 lastCorruptedRow = -1;
208 firstCorruptedRow = -1;
209 }
210 }
211 }
212
213 free(predMB);
214 }
215 return 1;
216 }
217 else
218 return 0;
219 }
220
221 /*!
222 ************************************************************************
223 * \brief
224 * It conceals a given MB by simply copying the pixel area from the reference image
225 * that is at the same location as the macroblock in the current image. This correcponds
226 * to COPY MBs.
227 * \return
228 * Always zero (0).
229 * \param recfr
230 * Reconstructed frame buffer
231 * \param currMBNum
232 * current MB index
233 * \param object_list
234 * Motion info for all MBs in the frame
235 * \param picSizeX
236 * Width of the frame in pixels
237 ************************************************************************
238 */
concealByCopy(frame * recfr,int currMBNum,objectBuffer_t * object_list,int picSizeX)239 static int concealByCopy(frame *recfr, int currMBNum,
240 objectBuffer_t *object_list, int picSizeX)
241 {
242 objectBuffer_t *currRegion;
243
244 currRegion = object_list+(currMBNum<<2);
245 currRegion->regionMode = REGMODE_INTER_COPY;
246
247 currRegion->xMin = (xPosMB(currMBNum,picSizeX)<<4);
248 currRegion->yMin = (yPosMB(currMBNum,picSizeX)<<4);
249
250 copyBetweenFrames (recfr, MBNum2YBlock(currMBNum,0,picSizeX), picSizeX, 16);
251
252 return 0;
253 }
254
255 /*!
256 ************************************************************************
257 * \brief
258 * Copies the co-located pixel values from the reference to the current frame.
259 * Used by concealByCopy
260 * \param recfr
261 * Reconstructed frame buffer
262 * \param currYBlockNum
263 * index of the block (8x8) in the Y plane
264 * \param picSizeX
265 * Width of the frame in pixels
266 * \param regionSize
267 * can be 16 or 8 to tell the dimension of the region to copy
268 ************************************************************************
269 */
copyBetweenFrames(frame * recfr,int currYBlockNum,int picSizeX,int regionSize)270 static void copyBetweenFrames (frame *recfr, int currYBlockNum, int picSizeX, int regionSize)
271 {
272 VideoParameters *p_Vid = recfr->p_Vid;
273 StorablePicture *dec_picture = p_Vid->dec_picture;
274 int j, k, location, xmin, ymin;
275 StorablePicture* refPic = p_Vid->ppSliceList[0]->listX[0][0];
276
277 /* set the position of the region to be copied */
278 xmin = (xPosYBlock(currYBlockNum,picSizeX)<<3);
279 ymin = (yPosYBlock(currYBlockNum,picSizeX)<<3);
280
281 for (j = ymin; j < ymin + regionSize; j++)
282 for (k = xmin; k < xmin + regionSize; k++)
283 {
284 location = j * picSizeX + k;
285 //th recfr->yptr[location] = dec_picture->imgY[j][k];
286 recfr->yptr[location] = refPic->imgY[j][k];
287 }
288
289 for (j = ymin >> uv_div[1][dec_picture->chroma_format_idc]; j < (ymin + regionSize) >> uv_div[1][dec_picture->chroma_format_idc]; j++)
290 for (k = xmin >> uv_div[0][dec_picture->chroma_format_idc]; k < (xmin + regionSize) >> uv_div[0][dec_picture->chroma_format_idc]; k++)
291 {
292 // location = j * picSizeX / 2 + k;
293 location = ((j * picSizeX) >> uv_div[0][dec_picture->chroma_format_idc]) + k;
294
295 //th recfr->uptr[location] = dec_picture->imgUV[0][j][k];
296 //th recfr->vptr[location] = dec_picture->imgUV[1][j][k];
297 recfr->uptr[location] = refPic->imgUV[0][j][k];
298 recfr->vptr[location] = refPic->imgUV[1][j][k];
299 }
300 }
301
302 /*!
303 ************************************************************************
304 * \brief
305 * It conceals a given MB by using the motion vectors of one reliable neighbor. That MV of a
306 * neighbor is selected wich gives the lowest pixel difference at the edges of the MB
307 * (see function edgeDistortion). This corresponds to a spatial smoothness criteria.
308 * \return
309 * Always zero (0).
310 * \param recfr
311 * Reconstructed frame buffer
312 * \param predMB
313 * memory area for storing temporary pixel values for a macroblock
314 * the Y,U,V planes are concatenated y = predMB, u = predMB+256, v = predMB+320
315 * \param currMBNum
316 * current MB index
317 * \param object_list
318 * array of region structures storing region mode and mv for each region
319 * \param predBlocks
320 * status array of the neighboring blocks (if they are OK, concealed or lost)
321 * \param picSizeX
322 * Width of the frame in pixels
323 * \param picSizeY
324 * Height of the frame in pixels
325 * \param yCondition
326 * array for conditions of Y blocks from ercVariables_t
327 ************************************************************************
328 */
concealByTrial(frame * recfr,imgpel * predMB,int currMBNum,objectBuffer_t * object_list,int predBlocks[],int picSizeX,int picSizeY,char * yCondition)329 static int concealByTrial(frame *recfr, imgpel *predMB,
330 int currMBNum, objectBuffer_t *object_list, int predBlocks[],
331 int picSizeX, int picSizeY, char *yCondition)
332 {
333 VideoParameters *p_Vid = recfr->p_Vid;
334
335 int predMBNum = 0, numMBPerLine,
336 compSplit1 = 0, compSplit2 = 0, compLeft = 1, comp = 0, compPred, order = 1,
337 fInterNeighborExists, numIntraNeighbours,
338 fZeroMotionChecked, predSplitted = 0,
339 threshold = ERC_BLOCK_OK,
340 minDist, currDist, i, k;
341 int regionSize;
342 objectBuffer_t *currRegion;
343 int mvBest[3] = {0, 0, 0}, mvPred[3] = {0, 0, 0}, *mvptr;
344
345 numMBPerLine = (int) (picSizeX>>4);
346
347 comp = 0;
348 regionSize = 16;
349
350 do
351 { /* 4 blocks loop */
352
353 currRegion = object_list+(currMBNum<<2)+comp;
354
355 /* set the position of the region to be concealed */
356
357 currRegion->xMin = (xPosYBlock(MBNum2YBlock(currMBNum,comp,picSizeX),picSizeX)<<3);
358 currRegion->yMin = (yPosYBlock(MBNum2YBlock(currMBNum,comp,picSizeX),picSizeX)<<3);
359
360 do
361 { /* reliability loop */
362
363 minDist = 0;
364 fInterNeighborExists = 0;
365 numIntraNeighbours = 0;
366 fZeroMotionChecked = 0;
367
368 /* loop the 4 neighbours */
369 for (i = 4; i < 8; i++)
370 {
371
372 /* if reliable, try it */
373 if (predBlocks[i] >= threshold)
374 {
375 switch (i)
376 {
377 case 4:
378 predMBNum = currMBNum-numMBPerLine;
379 compSplit1 = 2;
380 compSplit2 = 3;
381 break;
382
383 case 5:
384 predMBNum = currMBNum-1;
385 compSplit1 = 1;
386 compSplit2 = 3;
387 break;
388
389 case 6:
390 predMBNum = currMBNum+numMBPerLine;
391 compSplit1 = 0;
392 compSplit2 = 1;
393 break;
394
395 case 7:
396 predMBNum = currMBNum+1;
397 compSplit1 = 0;
398 compSplit2 = 2;
399 break;
400 }
401
402 /* try the concealment with the Motion Info of the current neighbour
403 only try if the neighbour is not Intra */
404 if (isBlock(object_list,predMBNum,compSplit1,INTRA) ||
405 isBlock(object_list,predMBNum,compSplit2,INTRA))
406 {
407 numIntraNeighbours++;
408 }
409 else
410 {
411 /* if neighbour MB is splitted, try both neighbour blocks */
412 for (predSplitted = isSplitted(object_list, predMBNum),
413 compPred = compSplit1;
414 predSplitted >= 0;
415 compPred = compSplit2,
416 predSplitted -= ((compSplit1 == compSplit2) ? 2 : 1))
417 {
418
419 /* if Zero Motion Block, do the copying. This option is tried only once */
420 if (isBlock(object_list, predMBNum, compPred, INTER_COPY))
421 {
422
423 if (fZeroMotionChecked)
424 {
425 continue;
426 }
427 else
428 {
429 fZeroMotionChecked = 1;
430
431 mvPred[0] = mvPred[1] = 0;
432 mvPred[2] = 0;
433
434 buildPredRegionYUV(p_Vid->erc_img, mvPred, currRegion->xMin, currRegion->yMin, predMB);
435 }
436 }
437 /* build motion using the neighbour's Motion Parameters */
438 else if (isBlock(object_list,predMBNum,compPred,INTRA))
439 {
440 continue;
441 }
442 else
443 {
444 mvptr = getParam(object_list, predMBNum, compPred, mv);
445
446 mvPred[0] = mvptr[0];
447 mvPred[1] = mvptr[1];
448 mvPred[2] = mvptr[2];
449
450 buildPredRegionYUV(p_Vid->erc_img, mvPred, currRegion->xMin, currRegion->yMin, predMB);
451 }
452
453 /* measure absolute boundary pixel difference */
454 currDist = edgeDistortion(predBlocks,
455 MBNum2YBlock(currMBNum,comp,picSizeX),
456 predMB, recfr->yptr, picSizeX, regionSize);
457
458 /* if so far best -> store the pixels as the best concealment */
459 if (currDist < minDist || !fInterNeighborExists)
460 {
461
462 minDist = currDist;
463
464 for (k=0;k<3;k++)
465 mvBest[k] = mvPred[k];
466
467 currRegion->regionMode =
468 (isBlock(object_list, predMBNum, compPred, INTER_COPY)) ?
469 ((regionSize == 16) ? REGMODE_INTER_COPY : REGMODE_INTER_COPY_8x8) :
470 ((regionSize == 16) ? REGMODE_INTER_PRED : REGMODE_INTER_PRED_8x8);
471
472 copyPredMB(MBNum2YBlock(currMBNum,comp,picSizeX), predMB, recfr,
473 picSizeX, regionSize);
474 }
475
476 fInterNeighborExists = 1;
477 }
478 }
479 }
480 }
481
482 threshold--;
483
484 } while ((threshold >= ERC_BLOCK_CONCEALED) && (fInterNeighborExists == 0));
485
486 /* always try zero motion */
487 if (!fZeroMotionChecked)
488 {
489 mvPred[0] = mvPred[1] = 0;
490 mvPred[2] = 0;
491
492 buildPredRegionYUV(p_Vid->erc_img, mvPred, currRegion->xMin, currRegion->yMin, predMB);
493
494 currDist = edgeDistortion(predBlocks,
495 MBNum2YBlock(currMBNum,comp,picSizeX),
496 predMB, recfr->yptr, picSizeX, regionSize);
497
498 if (currDist < minDist || !fInterNeighborExists)
499 {
500
501 minDist = currDist;
502 for (k=0;k<3;k++)
503 mvBest[k] = mvPred[k];
504
505 currRegion->regionMode =
506 ((regionSize == 16) ? REGMODE_INTER_COPY : REGMODE_INTER_COPY_8x8);
507
508 copyPredMB(MBNum2YBlock(currMBNum,comp,picSizeX), predMB, recfr,
509 picSizeX, regionSize);
510 }
511 }
512
513 for (i=0; i<3; i++)
514 currRegion->mv[i] = mvBest[i];
515
516 yCondition[MBNum2YBlock(currMBNum,comp,picSizeX)] = ERC_BLOCK_CONCEALED;
517 comp = (comp+order+4)%4;
518 compLeft--;
519
520 } while (compLeft);
521
522 return 0;
523 }
524
525 /*!
526 ************************************************************************
527 * \brief
528 * Builds the motion prediction pixels from the given location (in 1/4 pixel units)
529 * of the reference frame. It not only copies the pixel values but builds the interpolation
530 * when the pixel positions to be copied from is not full pixel (any 1/4 pixel position).
531 * It copies the resulting pixel vlaues into predMB.
532 * \param p_Vid
533 * The pointer of video_par structure of current frame
534 * \param mv
535 * The pointer of the predicted MV of the current (being concealed) MB
536 * \param x
537 * The x-coordinate of the above-left corner pixel of the current MB
538 * \param y
539 * The y-coordinate of the above-left corner pixel of the current MB
540 * \param predMB
541 * memory area for storing temporary pixel values for a macroblock
542 * the Y,U,V planes are concatenated y = predMB, u = predMB+256, v = predMB+320
543 ************************************************************************
544 */
buildPredRegionYUV(VideoParameters * p_Vid,int * mv,int x,int y,imgpel * predMB)545 static void buildPredRegionYUV(VideoParameters *p_Vid, int *mv, int x, int y, imgpel *predMB)
546 {
547 imgpel **tmp_block;
548 int i=0, j=0, ii=0, jj=0,i1=0,j1=0,j4=0,i4=0;
549 int uv;
550 int vec1_x=0,vec1_y=0;
551 int ioff,joff;
552 imgpel *pMB = predMB;
553 Slice *currSlice;// = p_Vid->currentSlice;
554 StorablePicture *dec_picture = p_Vid->dec_picture;
555 int ii0,jj0,ii1,jj1,if1,jf1,if0,jf0;
556 int mv_mul;
557
558 //FRExt
559 int f1_x, f1_y, f2_x, f2_y, f3, f4;
560 int b8, b4;
561 int yuv = dec_picture->chroma_format_idc - 1;
562
563 int ref_frame = imax (mv[2], 0); // !!KS: quick fix, we sometimes seem to get negative ref_pic here, so restrict to zero and above
564 int mb_nr = y/16*(p_Vid->width/16)+x/16; ///currSlice->current_mb_nr;
565 int **tmp_res = NULL;
566
567 Macroblock *currMB = &p_Vid->mb_data[mb_nr]; // intialization code deleted, see below, StW
568 currSlice = currMB->p_Slice;
569 tmp_res = currSlice->tmp_res;
570
571 // This should be allocated only once.
572 get_mem2Dpel(&tmp_block, MB_BLOCK_SIZE, MB_BLOCK_SIZE);
573
574 /* Update coordinates of the current concealed macroblock */
575 currMB->mb.x = (short) (x/MB_BLOCK_SIZE);
576 currMB->mb.y = (short) (y/MB_BLOCK_SIZE);
577 currMB->block_y = currMB->mb.y * BLOCK_SIZE;
578 currMB->pix_c_y = currMB->mb.y * p_Vid->mb_cr_size_y;
579 currMB->block_x = currMB->mb.x * BLOCK_SIZE;
580 currMB->pix_c_x = currMB->mb.x * p_Vid->mb_cr_size_x;
581
582 mv_mul=4;
583
584 // luma *******************************************************
585
586 for(j=0;j<MB_BLOCK_SIZE/BLOCK_SIZE;j++)
587 {
588 joff=j*4;
589 j4=currMB->block_y+j;
590 for(i=0;i<MB_BLOCK_SIZE/BLOCK_SIZE;i++)
591 {
592 ioff=i*4;
593 i4=currMB->block_x+i;
594
595 vec1_x = i4*4*mv_mul + mv[0];
596 vec1_y = j4*4*mv_mul + mv[1];
597
598 get_block_luma(currSlice->listX[0][ref_frame], vec1_x, vec1_y, BLOCK_SIZE, BLOCK_SIZE,
599 tmp_block,
600 dec_picture->iLumaStride,dec_picture->size_x_m1,
601 (currMB->mb_field) ? (dec_picture->size_y >> 1) - 1 : dec_picture->size_y_m1,tmp_res,
602 p_Vid->max_pel_value_comp[PLANE_Y],(imgpel) p_Vid->dc_pred_value_comp[PLANE_Y], currMB);
603
604 for(ii=0;ii<BLOCK_SIZE;ii++)
605 for(jj=0;jj<MB_BLOCK_SIZE/BLOCK_SIZE;jj++)
606 currSlice->mb_pred[LumaComp][jj+joff][ii+ioff]=tmp_block[jj][ii];
607 }
608 }
609
610
611 for (j = 0; j < 16; j++)
612 {
613 for (i = 0; i < 16; i++)
614 {
615 pMB[j*16+i] = currSlice->mb_pred[LumaComp][j][i];
616 }
617 }
618 pMB += 256;
619
620 if (dec_picture->chroma_format_idc != YUV400)
621 {
622 // chroma *******************************************************
623 f1_x = 64/p_Vid->mb_cr_size_x;
624 f2_x=f1_x-1;
625
626 f1_y = 64/p_Vid->mb_cr_size_y;
627 f2_y=f1_y-1;
628
629 f3=f1_x*f1_y;
630 f4=f3>>1;
631
632 for(uv=0;uv<2;uv++)
633 {
634 for (b8=0;b8<(p_Vid->num_uv_blocks);b8++)
635 {
636 for(b4=0;b4<4;b4++)
637 {
638 joff = subblk_offset_y[yuv][b8][b4];
639 j4=currMB->pix_c_y+joff;
640 ioff = subblk_offset_x[yuv][b8][b4];
641 i4=currMB->pix_c_x+ioff;
642
643 for(jj=0;jj<4;jj++)
644 {
645 for(ii=0;ii<4;ii++)
646 {
647 i1=(i4+ii)*f1_x + mv[0];
648 j1=(j4+jj)*f1_y + mv[1];
649
650 ii0=iClip3 (0, dec_picture->size_x_cr-1, i1/f1_x);
651 jj0=iClip3 (0, dec_picture->size_y_cr-1, j1/f1_y);
652 ii1=iClip3 (0, dec_picture->size_x_cr-1, ((i1+f2_x)/f1_x));
653 jj1=iClip3 (0, dec_picture->size_y_cr-1, ((j1+f2_y)/f1_y));
654
655 if1=(i1 & f2_x);
656 jf1=(j1 & f2_y);
657 if0=f1_x-if1;
658 jf0=f1_y-jf1;
659
660 currSlice->mb_pred[uv + 1][jj+joff][ii+ioff] = (imgpel)
661 ((if0*jf0*currSlice->listX[0][ref_frame]->imgUV[uv][jj0][ii0]+
662 if1*jf0*currSlice->listX[0][ref_frame]->imgUV[uv][jj0][ii1]+
663 if0*jf1*currSlice->listX[0][ref_frame]->imgUV[uv][jj1][ii0]+
664 if1*jf1*currSlice->listX[0][ref_frame]->imgUV[uv][jj1][ii1]+f4)/f3);
665 }
666 }
667 }
668 }
669
670 for (j = 0; j < 8; j++)
671 {
672 for (i = 0; i < 8; i++)
673 {
674 pMB[j*8+i] = currSlice->mb_pred[uv + 1][j][i];
675 }
676 }
677 pMB += 64;
678
679 }
680 }
681 // We should allocate this memory only once.
682 free_mem2Dpel(tmp_block);
683 }
684 /*!
685 ************************************************************************
686 * \brief
687 * Copies pixel values between a YUV frame and the temporary pixel value storage place. This is
688 * used to save some pixel values temporarily before overwriting it, or to copy back to a given
689 * location in a frame the saved pixel values.
690 * \param currYBlockNum
691 * index of the block (8x8) in the Y plane
692 * \param predMB
693 * memory area where the temporary pixel values are stored
694 * the Y,U,V planes are concatenated y = predMB, u = predMB+256, v = predMB+320
695 * \param recfr
696 * pointer to a YUV frame
697 * \param picSizeX
698 * picture width in pixels
699 * \param regionSize
700 * can be 16 or 8 to tell the dimension of the region to copy
701 ************************************************************************
702 */
copyPredMB(int currYBlockNum,imgpel * predMB,frame * recfr,int picSizeX,int regionSize)703 static void copyPredMB (int currYBlockNum, imgpel *predMB, frame *recfr,
704 int picSizeX, int regionSize)
705 {
706 VideoParameters *p_Vid = recfr->p_Vid;
707 StorablePicture *dec_picture = p_Vid->dec_picture;
708 int j, k, xmin, ymin, xmax, ymax;
709 int locationTmp;
710 int uv_x = uv_div[0][dec_picture->chroma_format_idc];
711 int uv_y = uv_div[1][dec_picture->chroma_format_idc];
712
713 xmin = (xPosYBlock(currYBlockNum,picSizeX)<<3);
714 ymin = (yPosYBlock(currYBlockNum,picSizeX)<<3);
715 xmax = xmin + regionSize -1;
716 ymax = ymin + regionSize -1;
717
718 for (j = ymin; j <= ymax; j++)
719 {
720 for (k = xmin; k <= xmax; k++)
721 {
722 locationTmp = (j-ymin) * 16 + (k-xmin);
723 dec_picture->imgY[j][k] = predMB[locationTmp];
724 }
725 }
726
727 if (dec_picture->chroma_format_idc != YUV400)
728 {
729 for (j = (ymin>>uv_y); j <= (ymax>>uv_y); j++)
730 {
731 for (k = (xmin>>uv_x); k <= (xmax>>uv_x); k++)
732 {
733 locationTmp = (j-(ymin>>uv_y)) * p_Vid->mb_cr_size_x + (k-(xmin>>1)) + 256;
734 dec_picture->imgUV[0][j][k] = predMB[locationTmp];
735
736 locationTmp += 64;
737
738 dec_picture->imgUV[1][j][k] = predMB[locationTmp];
739 }
740 }
741 }
742 }
743
744 /*!
745 ************************************************************************
746 * \brief
747 * Calculates a weighted pixel difference between edge Y pixels of the macroblock stored in predMB
748 * and the pixels in the given Y plane of a frame (recY) that would become neighbor pixels if
749 * predMB was placed at currYBlockNum block position into the frame. This "edge distortion" value
750 * is used to determine how well the given macroblock in predMB would fit into the frame when
751 * considering spatial smoothness. If there are correctly received neighbor blocks (status stored
752 * in predBlocks) only they are used in calculating the edge distorion; otherwise also the already
753 * concealed neighbor blocks can also be used.
754 * \return
755 * The calculated weighted pixel difference at the edges of the MB.
756 * \param predBlocks
757 * status array of the neighboring blocks (if they are OK, concealed or lost)
758 * \param currYBlockNum
759 * index of the block (8x8) in the Y plane
760 * \param predMB
761 * memory area where the temporary pixel values are stored
762 * the Y,U,V planes are concatenated y = predMB, u = predMB+256, v = predMB+320
763 * \param recY
764 * pointer to a Y plane of a YUV frame
765 * \param picSizeX
766 * picture width in pixels
767 * \param regionSize
768 * can be 16 or 8 to tell the dimension of the region to copy
769 ************************************************************************
770 */
edgeDistortion(int predBlocks[],int currYBlockNum,imgpel * predMB,imgpel * recY,int picSizeX,int regionSize)771 static int edgeDistortion (int predBlocks[], int currYBlockNum, imgpel *predMB,
772 imgpel *recY, int picSizeX, int regionSize)
773 {
774 int i, j, distortion, numOfPredBlocks, threshold = ERC_BLOCK_OK;
775 imgpel *currBlock = NULL, *neighbor = NULL;
776 int currBlockOffset = 0;
777
778 currBlock = recY + (yPosYBlock(currYBlockNum,picSizeX)<<3)*picSizeX + (xPosYBlock(currYBlockNum,picSizeX)<<3);
779
780 do
781 {
782
783 distortion = 0; numOfPredBlocks = 0;
784
785 // loop the 4 neighbors
786 for (j = 4; j < 8; j++)
787 {
788 /* if reliable, count boundary pixel difference */
789 if (predBlocks[j] >= threshold)
790 {
791
792 switch (j)
793 {
794 case 4:
795 neighbor = currBlock - picSizeX;
796 for ( i = 0; i < regionSize; i++ )
797 {
798 distortion += iabs((int)(predMB[i] - neighbor[i]));
799 }
800 break;
801 case 5:
802 neighbor = currBlock - 1;
803 for ( i = 0; i < regionSize; i++ )
804 {
805 distortion += iabs((int)(predMB[i*16] - neighbor[i*picSizeX]));
806 }
807 break;
808 case 6:
809 neighbor = currBlock + regionSize*picSizeX;
810 currBlockOffset = (regionSize-1)*16;
811 for ( i = 0; i < regionSize; i++ )
812 {
813 distortion += iabs((int)(predMB[i+currBlockOffset] - neighbor[i]));
814 }
815 break;
816 case 7:
817 neighbor = currBlock + regionSize;
818 currBlockOffset = regionSize-1;
819 for ( i = 0; i < regionSize; i++ )
820 {
821 distortion += iabs((int)(predMB[i*16+currBlockOffset] - neighbor[i*picSizeX]));
822 }
823 break;
824 }
825
826 numOfPredBlocks++;
827 }
828 }
829
830 threshold--;
831 if (threshold < ERC_BLOCK_CONCEALED)
832 break;
833 } while (numOfPredBlocks == 0);
834
835 if(numOfPredBlocks == 0)
836 {
837 return 0;
838 // assert (numOfPredBlocks != 0); !!!KS hmm, trying to continue...
839 }
840 return (distortion/numOfPredBlocks);
841 }
842
843 // picture error concealment below
844
845 /*!
846 ************************************************************************
847 * \brief
848 * The motion prediction pixels are calculated from the given location (in
849 * 1/4 pixel units) of the referenced frame. It copies the sub block from the
850 * corresponding reference to the frame to be concealed.
851 *
852 *************************************************************************
853 */
buildPredblockRegionYUV(VideoParameters * p_Vid,int * mv,int x,int y,imgpel * predMB,int list,int current_mb_nr)854 static void buildPredblockRegionYUV(VideoParameters *p_Vid, int *mv,
855 int x, int y, imgpel *predMB, int list, int current_mb_nr)
856 {
857 imgpel **tmp_block;
858 int i=0,j=0,ii=0,jj=0,i1=0,j1=0,j4=0,i4=0;
859 int uv;
860 int vec1_x=0,vec1_y=0;
861 int ioff,joff;
862
863 StorablePicture *dec_picture = p_Vid->dec_picture;
864 imgpel *pMB = predMB;
865
866 int ii0,jj0,ii1,jj1,if1,jf1,if0,jf0;
867 int mv_mul;
868
869 //FRExt
870 int f1_x, f1_y, f2_x, f2_y, f3, f4;
871 int yuv = dec_picture->chroma_format_idc - 1;
872
873 int ref_frame = mv[2];
874 int mb_nr = current_mb_nr;
875
876 Macroblock *currMB = &p_Vid->mb_data[mb_nr]; // intialization code deleted, see below, StW
877 Slice *currSlice = currMB->p_Slice;
878
879 get_mem2Dpel(&tmp_block, MB_BLOCK_SIZE, MB_BLOCK_SIZE);
880
881 /* Update coordinates of the current concealed macroblock */
882
883 currMB->mb.x = (short) (x/BLOCK_SIZE);
884 currMB->mb.y = (short) (y/BLOCK_SIZE);
885 currMB->block_y = currMB->mb.y * BLOCK_SIZE;
886 currMB->pix_c_y = currMB->mb.y * p_Vid->mb_cr_size_y/4;
887 currMB->block_x = currMB->mb.x * BLOCK_SIZE;
888 currMB->pix_c_x = currMB->mb.x * p_Vid->mb_cr_size_x/4;
889
890 mv_mul=4;
891
892 // luma *******************************************************
893
894 vec1_x = x*mv_mul + mv[0];
895 vec1_y = y*mv_mul + mv[1];
896 get_block_luma(currSlice->listX[list][ref_frame], vec1_x, vec1_y, BLOCK_SIZE, BLOCK_SIZE, tmp_block,
897 dec_picture->iLumaStride,dec_picture->size_x_m1, (currMB->mb_field) ? (dec_picture->size_y >> 1) - 1 : dec_picture->size_y_m1,currSlice->tmp_res,
898 p_Vid->max_pel_value_comp[PLANE_Y],(imgpel) p_Vid->dc_pred_value_comp[PLANE_Y], currMB);
899
900 for(jj=0;jj<MB_BLOCK_SIZE/BLOCK_SIZE;jj++)
901 for(ii=0;ii<BLOCK_SIZE;ii++)
902 currSlice->mb_pred[LumaComp][jj][ii]=tmp_block[jj][ii];
903
904
905 for (j = 0; j < 4; j++)
906 {
907 for (i = 0; i < 4; i++)
908 {
909 pMB[j*4+i] = currSlice->mb_pred[LumaComp][j][i];
910 }
911 }
912 pMB += 16;
913
914 if (dec_picture->chroma_format_idc != YUV400)
915 {
916 // chroma *******************************************************
917 f1_x = 64/(p_Vid->mb_cr_size_x);
918 f2_x=f1_x-1;
919
920 f1_y = 64/(p_Vid->mb_cr_size_y);
921 f2_y=f1_y-1;
922
923 f3=f1_x*f1_y;
924 f4=f3>>1;
925
926 for(uv=0;uv<2;uv++)
927 {
928 joff = subblk_offset_y[yuv][0][0];
929 j4=currMB->pix_c_y+joff;
930 ioff = subblk_offset_x[yuv][0][0];
931 i4=currMB->pix_c_x+ioff;
932
933 for(jj=0;jj<2;jj++)
934 {
935 for(ii=0;ii<2;ii++)
936 {
937 i1=(i4+ii)*f1_x + mv[0];
938 j1=(j4+jj)*f1_y + mv[1];
939
940 ii0=iClip3 (0, dec_picture->size_x_cr-1, i1/f1_x);
941 jj0=iClip3 (0, dec_picture->size_y_cr-1, j1/f1_y);
942 ii1=iClip3 (0, dec_picture->size_x_cr-1, ((i1+f2_x)/f1_x));
943 jj1=iClip3 (0, dec_picture->size_y_cr-1, ((j1+f2_y)/f1_y));
944
945 if1=(i1 & f2_x);
946 jf1=(j1 & f2_y);
947 if0=f1_x-if1;
948 jf0=f1_y-jf1;
949
950 currSlice->mb_pred[uv + 1][jj][ii]=(imgpel) ((if0*jf0*currSlice->listX[list][ref_frame]->imgUV[uv][jj0][ii0]+
951 if1*jf0*currSlice->listX[list][ref_frame]->imgUV[uv][jj0][ii1]+
952 if0*jf1*currSlice->listX[list][ref_frame]->imgUV[uv][jj1][ii0]+
953 if1*jf1*currSlice->listX[list][ref_frame]->imgUV[uv][jj1][ii1]+f4)/f3);
954 }
955 }
956
957 for (j = 0; j < 2; j++)
958 {
959 for (i = 0; i < 2; i++)
960 {
961 pMB[j*2+i] = currSlice->mb_pred[uv + 1][j][i];
962 }
963 }
964 pMB += 4;
965
966 }
967 }
968 free_mem2Dpel(tmp_block);
969 }
970
971 /*!
972 ************************************************************************
973 * \brief
974 * compares two stored pictures by picture number for qsort in descending order
975 *
976 ************************************************************************
977 */
compare_pic_by_pic_num_desc(const void * arg1,const void * arg2)978 static inline int compare_pic_by_pic_num_desc( const void *arg1, const void *arg2 )
979 {
980 int pic_num1 = (*(StorablePicture**)arg1)->pic_num;
981 int pic_num2 = (*(StorablePicture**)arg2)->pic_num;
982
983 if (pic_num1 < pic_num2)
984 return 1;
985 if (pic_num1 > pic_num2)
986 return -1;
987 else
988 return 0;
989 }
990
991 /*!
992 ************************************************************************
993 * \brief
994 * compares two stored pictures by picture number for qsort in descending order
995 *
996 ************************************************************************
997 */
compare_pic_by_lt_pic_num_asc(const void * arg1,const void * arg2)998 static inline int compare_pic_by_lt_pic_num_asc( const void *arg1, const void *arg2 )
999 {
1000 int long_term_pic_num1 = (*(StorablePicture**)arg1)->long_term_pic_num;
1001 int long_term_pic_num2 = (*(StorablePicture**)arg2)->long_term_pic_num;
1002 if ( long_term_pic_num1 < long_term_pic_num2)
1003 return -1;
1004
1005 if ( long_term_pic_num1 > long_term_pic_num2)
1006 return 1;
1007 else
1008 return 0;
1009 }
1010
1011 /*!
1012 ************************************************************************
1013 * \brief
1014 * compares two stored pictures by poc for qsort in ascending order
1015 *
1016 ************************************************************************
1017 */
compare_pic_by_poc_asc(const void * arg1,const void * arg2)1018 static inline int compare_pic_by_poc_asc( const void *arg1, const void *arg2 )
1019 {
1020 int poc1 = (*(StorablePicture**)arg1)->poc;
1021 int poc2 = (*(StorablePicture**)arg2)->poc;
1022
1023 if ( poc1 < poc2)
1024 return -1;
1025 if ( poc1 > poc2)
1026 return 1;
1027 else
1028 return 0;
1029 }
1030
1031
1032 /*!
1033 ************************************************************************
1034 * \brief
1035 * compares two stored pictures by poc for qsort in descending order
1036 *
1037 ************************************************************************
1038 */
compare_pic_by_poc_desc(const void * arg1,const void * arg2)1039 static inline int compare_pic_by_poc_desc( const void *arg1, const void *arg2 )
1040 {
1041 int poc1 = (*(StorablePicture**)arg1)->poc;
1042 int poc2 = (*(StorablePicture**)arg2)->poc;
1043
1044 if (poc1 < poc2)
1045 return 1;
1046 if (poc1 > poc2)
1047 return -1;
1048 else
1049 return 0;
1050 }
1051
1052 /*!
1053 ************************************************************************
1054 * \brief
1055 * Copy image data from one array to another array
1056 ************************************************************************
1057 */
1058
CopyImgData(imgpel ** inputY,imgpel *** inputUV,imgpel ** outputY,imgpel *** outputUV,int img_width,int img_height,int img_width_cr,int img_height_cr)1059 static void CopyImgData(imgpel **inputY, imgpel ***inputUV, imgpel **outputY, imgpel ***outputUV,
1060 int img_width, int img_height, int img_width_cr, int img_height_cr)
1061 {
1062 int x, y;
1063
1064 for (y=0; y<img_height; y++)
1065 for (x=0; x<img_width; x++)
1066 outputY[y][x] = inputY[y][x];
1067
1068 for (y=0; y<img_height_cr; y++)
1069 for (x=0; x<img_width_cr; x++)
1070 {
1071 outputUV[0][y][x] = inputUV[0][y][x];
1072 outputUV[1][y][x] = inputUV[1][y][x];
1073 }
1074 }
1075
1076 /*!
1077 ************************************************************************
1078 * \brief
1079 * Copies the last reference frame for concealing reference frame loss.
1080 ************************************************************************
1081 */
1082
get_last_ref_pic_from_dpb(DecodedPictureBuffer * p_Dpb)1083 static StorablePicture* get_last_ref_pic_from_dpb(DecodedPictureBuffer *p_Dpb)
1084 {
1085 int used_size = p_Dpb->used_size - 1;
1086 int i;
1087
1088 for(i = used_size; i >= 0; i--)
1089 {
1090 if (p_Dpb->fs[i]->is_used==3)
1091 {
1092 if (((p_Dpb->fs[i]->frame->used_for_reference) &&
1093 (!p_Dpb->fs[i]->frame->is_long_term)) /*|| ((p_Dpb->fs[i]->frame->used_for_reference==0)
1094 && (p_Dpb->fs[i]->frame->slice_type == P_SLICE))*/ )
1095 {
1096 return p_Dpb->fs[i]->frame;
1097 }
1098 }
1099 }
1100
1101 return NULL;
1102 }
1103
1104 /*!
1105 ************************************************************************
1106 * \brief
1107 * Conceals the lost reference or non reference frame by either frame copy
1108 * or motion vector copy concealment.
1109 *
1110 ************************************************************************
1111 */
1112
copy_to_conceal(StorablePicture * src,StorablePicture * dst,VideoParameters * p_Vid)1113 static void copy_to_conceal(StorablePicture *src, StorablePicture *dst, VideoParameters *p_Vid)
1114 {
1115 int i=0;
1116 int mv[3];
1117 int multiplier;
1118 imgpel *predMB, *storeYUV;
1119 int j, y, x, mb_height, mb_width, ii=0, jj=0;
1120 int uv;
1121 int mm, nn;
1122 int scale = 1;
1123 StorablePicture *dec_picture = p_Vid->dec_picture;
1124 // InputParameters *test;
1125
1126 int current_mb_nr = 0;
1127
1128 dst->PicSizeInMbs = src->PicSizeInMbs;
1129
1130 dst->slice_type = src->slice_type = p_Vid->conceal_slice_type;
1131
1132 dst->idr_flag = FALSE; //since we do not want to clears the ref list
1133
1134 dst->no_output_of_prior_pics_flag = src->no_output_of_prior_pics_flag;
1135 dst->long_term_reference_flag = src->long_term_reference_flag;
1136 dst->adaptive_ref_pic_buffering_flag = src->adaptive_ref_pic_buffering_flag = 0;
1137 dst->chroma_format_idc = src->chroma_format_idc;
1138 dst->frame_mbs_only_flag = src->frame_mbs_only_flag;
1139 dst->frame_cropping_flag = src->frame_cropping_flag;
1140 dst->frame_crop_left_offset = src->frame_crop_left_offset;
1141 dst->frame_crop_right_offset = src->frame_crop_right_offset;
1142 dst->frame_crop_bottom_offset = src->frame_crop_bottom_offset;
1143 dst->frame_crop_top_offset = src->frame_crop_top_offset;
1144
1145 dst->qp = src->qp;
1146 dst->slice_qp_delta = src->slice_qp_delta;
1147
1148 dec_picture = src;
1149
1150 // Conceals the missing frame by frame copy concealment
1151 if (p_Vid->conceal_mode==1)
1152 {
1153 // We need these initializations for using deblocking filter for frame copy
1154 // concealment as well.
1155 dst->PicWidthInMbs = src->PicWidthInMbs;
1156 dst->PicSizeInMbs = src->PicSizeInMbs;
1157
1158 CopyImgData( src->imgY, src->imgUV, dst->imgY, dst->imgUV, p_Vid->width, p_Vid->height, p_Vid->width_cr, p_Vid->height_cr);
1159 }
1160
1161 // Conceals the missing frame by motion vector copy concealment
1162 if (p_Vid->conceal_mode==2)
1163 {
1164 if (dec_picture->chroma_format_idc != YUV400)
1165 {
1166 storeYUV = (imgpel *) malloc ( (16 + (p_Vid->mb_cr_size_x*p_Vid->mb_cr_size_y)*2/16) * sizeof (imgpel));
1167 }
1168 else
1169 {
1170 storeYUV = (imgpel *) malloc (16 * sizeof (imgpel));
1171 }
1172
1173 p_Vid->erc_img = p_Vid;
1174
1175 dst->PicWidthInMbs = src->PicWidthInMbs;
1176 dst->PicSizeInMbs = src->PicSizeInMbs;
1177 mb_width = dst->PicWidthInMbs;
1178 mb_height = (dst->PicSizeInMbs)/(dst->PicWidthInMbs);
1179 scale = (p_Vid->conceal_slice_type == B_SLICE) ? 2 : 1;
1180
1181 if(p_Vid->conceal_slice_type == B_SLICE)
1182 {
1183 init_lists_for_non_reference_loss(
1184 p_Vid->p_Dpb_layer[0],
1185 dst->slice_type, p_Vid->ppSliceList[0]->structure);
1186 }
1187 else
1188 p_Vid->ppSliceList[0]->init_lists(p_Vid->ppSliceList[0]); //p_Vid->currentSlice);
1189
1190 multiplier = BLOCK_SIZE;
1191
1192 for(i=0;i<mb_height*4;i++)
1193 {
1194 mm = i * BLOCK_SIZE;
1195 for(j=0;j<mb_width*4;j++)
1196 {
1197 nn = j * BLOCK_SIZE;
1198
1199 mv[0] = src->mv_info[i][j].mv[LIST_0].mv_x / scale;
1200 mv[1] = src->mv_info[i][j].mv[LIST_0].mv_y / scale;
1201 mv[2] = src->mv_info[i][j].ref_idx[LIST_0];
1202
1203 if(mv[2]<0)
1204 mv[2]=0;
1205
1206 dst->mv_info[i][j].mv[LIST_0].mv_x = (short) mv[0];
1207 dst->mv_info[i][j].mv[LIST_0].mv_y = (short) mv[1];
1208 dst->mv_info[i][j].ref_idx[LIST_0] = (char) mv[2];
1209
1210 x = (j) * multiplier;
1211 y = (i) * multiplier;
1212
1213 if ((mm%16==0) && (nn%16==0))
1214 current_mb_nr++;
1215
1216 buildPredblockRegionYUV(p_Vid->erc_img, mv, x, y, storeYUV, LIST_0, current_mb_nr);
1217
1218 predMB = storeYUV;
1219
1220 for(ii=0;ii<multiplier;ii++)
1221 {
1222 for(jj=0;jj<multiplier;jj++)
1223 {
1224 dst->imgY[i*multiplier+ii][j*multiplier+jj] = predMB[ii*(multiplier)+jj];
1225 }
1226 }
1227
1228 predMB = predMB + (multiplier*multiplier);
1229
1230 if (dec_picture->chroma_format_idc != YUV400)
1231 {
1232
1233 for(uv=0;uv<2;uv++)
1234 {
1235 for(ii=0;ii< (multiplier/2);ii++)
1236 {
1237 for(jj=0;jj< (multiplier/2);jj++)
1238 {
1239 dst->imgUV[uv][i*multiplier/2 +ii][j*multiplier/2 +jj] = predMB[ii*(multiplier/2)+jj];
1240 }
1241 }
1242 predMB = predMB + (multiplier*multiplier/4);
1243 }
1244 }
1245 }
1246 }
1247 free(storeYUV);
1248 }
1249 }
1250
1251 /*!
1252 ************************************************************************
1253 * \brief
1254 * Uses the previous reference pic for concealment of reference frames
1255 *
1256 ************************************************************************
1257 */
1258
1259 static void
copy_prev_pic_to_concealed_pic(StorablePicture * picture,DecodedPictureBuffer * p_Dpb)1260 copy_prev_pic_to_concealed_pic(StorablePicture *picture, DecodedPictureBuffer *p_Dpb)
1261 {
1262 VideoParameters *p_Vid = p_Dpb->p_Vid;
1263 /* get the last ref pic in dpb */
1264 StorablePicture *ref_pic = get_last_ref_pic_from_dpb(p_Dpb);
1265
1266 assert(ref_pic != NULL);
1267
1268 /* copy all the struc from this to current concealment pic */
1269 p_Vid->conceal_slice_type = P_SLICE;
1270 copy_to_conceal(ref_pic, picture, p_Vid);
1271 }
1272
1273
1274 /*!
1275 ************************************************************************
1276 * \brief
1277 * This function conceals a missing reference frame. The routine is called
1278 * based on the difference in frame number. It conceals an IDR frame loss
1279 * based on the sudden decrease in frame number.
1280 *
1281 ************************************************************************
1282 */
1283
conceal_lost_frames(DecodedPictureBuffer * p_Dpb,Slice * pSlice)1284 void conceal_lost_frames(DecodedPictureBuffer *p_Dpb, Slice *pSlice)
1285 {
1286 VideoParameters *p_Vid = p_Dpb->p_Vid;
1287 int CurrFrameNum;
1288 int UnusedShortTermFrameNum;
1289 StorablePicture *picture = NULL;
1290 int tmp1 = pSlice->delta_pic_order_cnt[0];
1291 int tmp2 = pSlice->delta_pic_order_cnt[1];
1292 int i;
1293
1294 pSlice->delta_pic_order_cnt[0] = pSlice->delta_pic_order_cnt[1] = 0;
1295
1296 // printf("A gap in frame number is found, try to fill it.\n");
1297
1298 if(p_Vid->IDR_concealment_flag == 1)
1299 {
1300 // Conceals an IDR frame loss. Uses the reference frame in the previous
1301 // GOP for concealment.
1302 UnusedShortTermFrameNum = 0;
1303 p_Vid->last_ref_pic_poc = -p_Vid->poc_gap;
1304 p_Vid->earlier_missing_poc = 0;
1305 }
1306 else
1307 UnusedShortTermFrameNum = (p_Vid->pre_frame_num + 1) % p_Vid->max_frame_num;
1308
1309 CurrFrameNum = pSlice->frame_num;
1310
1311 while (CurrFrameNum != UnusedShortTermFrameNum)
1312 {
1313 picture = alloc_storable_picture (p_Vid, FRAME, p_Vid->width, p_Vid->height, p_Vid->width_cr, p_Vid->height_cr, 1);
1314
1315 picture->coded_frame = 1;
1316 picture->pic_num = UnusedShortTermFrameNum;
1317 picture->frame_num = UnusedShortTermFrameNum;
1318 picture->non_existing = 0;
1319 picture->is_output = 0;
1320 picture->used_for_reference = 1;
1321 picture->concealed_pic = 1;
1322
1323 picture->adaptive_ref_pic_buffering_flag = 0;
1324
1325 pSlice->frame_num = UnusedShortTermFrameNum;
1326
1327 picture->top_poc=p_Vid->last_ref_pic_poc + p_Vid->ref_poc_gap;
1328 picture->bottom_poc=picture->top_poc;
1329 picture->frame_poc=picture->top_poc;
1330 picture->poc=picture->top_poc;
1331 p_Vid->last_ref_pic_poc = picture->poc;
1332
1333 copy_prev_pic_to_concealed_pic(picture, p_Dpb);
1334
1335 //if (UnusedShortTermFrameNum == 0)
1336 if(p_Vid->IDR_concealment_flag == 1)
1337 {
1338 picture->slice_type = I_SLICE;
1339 picture->idr_flag = TRUE;
1340 flush_dpb(p_Dpb);
1341 picture->top_poc= 0;
1342 picture->bottom_poc=picture->top_poc;
1343 picture->frame_poc=picture->top_poc;
1344 picture->poc=picture->top_poc;
1345 p_Vid->last_ref_pic_poc = picture->poc;
1346 }
1347
1348 store_picture_in_dpb(p_Vid->p_Dpb_layer[0], picture);
1349
1350 picture=NULL;
1351
1352 p_Vid->pre_frame_num = UnusedShortTermFrameNum;
1353 UnusedShortTermFrameNum = (UnusedShortTermFrameNum + 1) % p_Vid->max_frame_num;
1354
1355 // update reference flags and set current flag.
1356 for(i=16;i>0;i--)
1357 {
1358 pSlice->ref_flag[i] = pSlice->ref_flag[i-1];
1359 }
1360 pSlice->ref_flag[0] = 0;
1361 }
1362 pSlice->delta_pic_order_cnt[0] = tmp1;
1363 pSlice->delta_pic_order_cnt[1] = tmp2;
1364 pSlice->frame_num = CurrFrameNum;
1365 }
1366
1367 /*!
1368 ************************************************************************
1369 * \brief
1370 * Updates the reference list for motion vector copy concealment for non-
1371 * reference frame loss.
1372 *
1373 ************************************************************************
1374 */
1375
update_ref_list_for_concealment(DecodedPictureBuffer * p_Dpb)1376 void update_ref_list_for_concealment(DecodedPictureBuffer *p_Dpb)
1377 {
1378 VideoParameters *p_Vid = p_Dpb->p_Vid;
1379 unsigned i, j= 0;
1380
1381 for (i = 0; i < p_Dpb->used_size; i++)
1382 {
1383 if (p_Dpb->fs[i]->concealment_reference)
1384 {
1385 p_Dpb->fs_ref[j++] = p_Dpb->fs[i];
1386 }
1387 }
1388
1389 p_Dpb->ref_frames_in_buffer = p_Vid->active_pps->num_ref_idx_l0_default_active_minus1;
1390 }
1391
1392 /*!
1393 ************************************************************************
1394 * \brief
1395 * Initialize the list based on the B frame or non reference 'p' frame
1396 * to be concealed. The function initialize currSlice->listX[0] and list 1 depending
1397 * on current picture type
1398 *
1399 ************************************************************************
1400 */
init_lists_for_non_reference_loss(DecodedPictureBuffer * p_Dpb,int currSliceType,PictureStructure currPicStructure)1401 void init_lists_for_non_reference_loss(DecodedPictureBuffer *p_Dpb, int currSliceType, PictureStructure currPicStructure)
1402 {
1403 VideoParameters *p_Vid = p_Dpb->p_Vid;
1404 seq_parameter_set_rbsp_t *active_sps = p_Vid->active_sps;
1405
1406 unsigned i;
1407 int j;
1408 int max_frame_num = 1 << (active_sps->log2_max_frame_num_minus4 + 4);
1409 int diff;
1410
1411 int list0idx = 0;
1412 int list0idx_1 = 0;
1413
1414 StorablePicture *tmp_s;
1415
1416 if (currPicStructure == FRAME)
1417 {
1418 for(i=0;i<p_Dpb->ref_frames_in_buffer; i++)
1419 {
1420 if(p_Dpb->fs[i]->concealment_reference == 1)
1421 {
1422 if(p_Dpb->fs[i]->frame_num > p_Vid->frame_to_conceal)
1423 p_Dpb->fs_ref[i]->frame_num_wrap = p_Dpb->fs[i]->frame_num - max_frame_num;
1424 else
1425 p_Dpb->fs_ref[i]->frame_num_wrap = p_Dpb->fs[i]->frame_num;
1426 p_Dpb->fs_ref[i]->frame->pic_num = p_Dpb->fs_ref[i]->frame_num_wrap;
1427 }
1428 }
1429 }
1430
1431 if (currSliceType == P_SLICE)
1432 {
1433 // Calculate FrameNumWrap and PicNum
1434 if (currPicStructure == FRAME)
1435 {
1436 for(i=0;i<p_Dpb->used_size; i++)
1437 {
1438 if(p_Dpb->fs[i]->concealment_reference == 1)
1439 {
1440 p_Vid->ppSliceList[0]->listX[0][list0idx++] = p_Dpb->fs[i]->frame;
1441 }
1442 }
1443 // order list 0 by PicNum
1444 qsort((void *)p_Vid->ppSliceList[0]->listX[0], list0idx, sizeof(StorablePicture*), compare_pic_by_pic_num_desc);
1445 p_Vid->ppSliceList[0]->listXsize[0] = (char) list0idx;
1446 }
1447 }
1448
1449 if (currSliceType == B_SLICE)
1450 {
1451 if (currPicStructure == FRAME)
1452 {
1453 // for(i=0;i<p_Dpb->ref_frames_in_buffer; i++)
1454 for(i=0;i<p_Dpb->used_size; i++)
1455 {
1456 if(p_Dpb->fs[i]->concealment_reference == 1)
1457 {
1458 if(p_Vid->earlier_missing_poc > p_Dpb->fs[i]->frame->poc)
1459 p_Vid->ppSliceList[0]->listX[0][list0idx++] = p_Dpb->fs[i]->frame;
1460 }
1461 }
1462
1463 qsort((void *)p_Vid->ppSliceList[0]->listX[0], list0idx, sizeof(StorablePicture*), compare_pic_by_poc_desc);
1464 list0idx_1 = list0idx;
1465
1466 // for(i=0;i<p_Dpb->ref_frames_in_buffer; i++)
1467 for(i=0;i<p_Dpb->used_size; i++)
1468 {
1469 if(p_Dpb->fs[i]->concealment_reference == 1)
1470 {
1471 if(p_Vid->earlier_missing_poc < p_Dpb->fs[i]->frame->poc)
1472 p_Vid->ppSliceList[0]->listX[0][list0idx++] = p_Dpb->fs[i]->frame;
1473 }
1474 }
1475
1476 qsort((void *)&p_Vid->ppSliceList[0]->listX[0][list0idx_1], list0idx-list0idx_1, sizeof(StorablePicture*), compare_pic_by_poc_asc);
1477
1478 for (j=0; j<list0idx_1; j++)
1479 {
1480 p_Vid->ppSliceList[0]->listX[1][list0idx-list0idx_1+j]=p_Vid->ppSliceList[0]->listX[0][j];
1481 }
1482 for (j=list0idx_1; j<list0idx; j++)
1483 {
1484 p_Vid->ppSliceList[0]->listX[1][j-list0idx_1]=p_Vid->ppSliceList[0]->listX[0][j];
1485 }
1486
1487 p_Vid->ppSliceList[0]->listXsize[0] = p_Vid->ppSliceList[0]->listXsize[1] = (char) list0idx;
1488
1489 qsort((void *)&p_Vid->ppSliceList[0]->listX[0][(short) p_Vid->ppSliceList[0]->listXsize[0]], list0idx-p_Vid->ppSliceList[0]->listXsize[0], sizeof(StorablePicture*), compare_pic_by_lt_pic_num_asc);
1490 qsort((void *)&p_Vid->ppSliceList[0]->listX[1][(short) p_Vid->ppSliceList[0]->listXsize[0]], list0idx-p_Vid->ppSliceList[0]->listXsize[0], sizeof(StorablePicture*), compare_pic_by_lt_pic_num_asc);
1491 p_Vid->ppSliceList[0]->listXsize[0] = p_Vid->ppSliceList[0]->listXsize[1] = (char) list0idx;
1492 }
1493 }
1494
1495 if ((p_Vid->ppSliceList[0]->listXsize[0] == p_Vid->ppSliceList[0]->listXsize[1]) && (p_Vid->ppSliceList[0]->listXsize[0] > 1))
1496 {
1497 // check if lists are identical, if yes swap first two elements of listX[1]
1498 diff=0;
1499 for (j = 0; j< p_Vid->ppSliceList[0]->listXsize[0]; j++)
1500 {
1501 if (p_Vid->ppSliceList[0]->listX[0][j]!=p_Vid->ppSliceList[0]->listX[1][j])
1502 diff=1;
1503 }
1504 if (!diff)
1505 {
1506 tmp_s = p_Vid->ppSliceList[0]->listX[1][0];
1507 p_Vid->ppSliceList[0]->listX[1][0]=p_Vid->ppSliceList[0]->listX[1][1];
1508 p_Vid->ppSliceList[0]->listX[1][1]=tmp_s;
1509 }
1510 }
1511
1512 // set max size
1513 p_Vid->ppSliceList[0]->listXsize[0] = (char) imin (p_Vid->ppSliceList[0]->listXsize[0], (int)active_sps->num_ref_frames);
1514 p_Vid->ppSliceList[0]->listXsize[1] = (char) imin (p_Vid->ppSliceList[0]->listXsize[1], (int)active_sps->num_ref_frames);
1515
1516 p_Vid->ppSliceList[0]->listXsize[1] = 0;
1517 // set the unused list entries to NULL
1518 for (i=p_Vid->ppSliceList[0]->listXsize[0]; i< (MAX_LIST_SIZE) ; i++)
1519 {
1520 p_Vid->ppSliceList[0]->listX[0][i] = NULL;
1521 }
1522 for (i=p_Vid->ppSliceList[0]->listXsize[1]; i< (MAX_LIST_SIZE) ; i++)
1523 {
1524 p_Vid->ppSliceList[0]->listX[1][i] = NULL;
1525 }
1526 }
1527
1528
1529 /*!
1530 ************************************************************************
1531 * \brief
1532 * Get from the dpb the picture corresponding to a POC. The POC varies
1533 * depending on whether it is a frame copy or motion vector copy concealment.
1534 * The frame corresponding to the POC is returned.
1535 *
1536 ************************************************************************
1537 */
1538
get_pic_from_dpb(DecodedPictureBuffer * p_Dpb,int missingpoc,unsigned int * pos)1539 StorablePicture *get_pic_from_dpb(DecodedPictureBuffer *p_Dpb, int missingpoc, unsigned int *pos)
1540 {
1541 VideoParameters *p_Vid = p_Dpb->p_Vid;
1542 int used_size = p_Dpb->used_size - 1;
1543 int i, concealfrom = 0;
1544
1545 if(p_Vid->conceal_mode == 1)
1546 concealfrom = missingpoc - p_Vid->poc_gap;
1547 else if (p_Vid->conceal_mode == 2)
1548 concealfrom = missingpoc + p_Vid->poc_gap;
1549
1550 for(i = used_size; i >= 0; i--)
1551 {
1552 if(p_Dpb->fs[i]->poc == concealfrom)
1553 {
1554 *pos = i;
1555 return p_Dpb->fs[i]->frame;
1556 }
1557 }
1558
1559 return NULL;
1560 }
1561
1562 /*!
1563 ************************************************************************
1564 * \brief
1565 * Function to sort the POC and find the lowest number in the POC list
1566 * Compare the integers
1567 *
1568 ************************************************************************
1569 */
1570
comp(const void * i,const void * j)1571 int comp(const void *i, const void *j)
1572 {
1573 return *(int *)i - *(int *)j;
1574 }
1575
1576 /*!
1577 ************************************************************************
1578 * \brief
1579 * Initialises a node, allocates memory for the node, and returns
1580 * a pointer to the new node.
1581 *
1582 ************************************************************************
1583 */
1584
init_node(StorablePicture * picture,int missingpoc)1585 struct concealment_node * init_node( StorablePicture* picture, int missingpoc )
1586 {
1587 struct concealment_node *ptr;
1588
1589 ptr = (struct concealment_node *) calloc( 1, sizeof(struct concealment_node ) );
1590
1591 if( ptr == NULL )
1592 return (struct concealment_node *) NULL;
1593 else {
1594 ptr->picture = picture;
1595 ptr->missingpocs = missingpoc;
1596 ptr->next = NULL;
1597 return ptr;
1598 }
1599 }
1600
1601 /*!
1602 ************************************************************************
1603 * \brief
1604 * Prints the details of a node
1605 *
1606 ************************************************************************
1607 */
1608
print_node(struct concealment_node * ptr)1609 void print_node( struct concealment_node *ptr )
1610 {
1611 printf("Missing POC=%d\n", ptr->missingpocs );
1612 }
1613
1614
1615 /*!
1616 ************************************************************************
1617 * \brief
1618 * Prints all nodes from the current address passed to it.
1619 *
1620 ************************************************************************
1621 */
1622
print_list(struct concealment_node * ptr)1623 void print_list( struct concealment_node *ptr )
1624 {
1625 while( ptr != NULL )
1626 {
1627 print_node( ptr );
1628 ptr = ptr->next;
1629 }
1630 }
1631
1632 /*!
1633 ************************************************************************
1634 * \brief
1635 * Adds a node to the end of the list.
1636 *
1637 ************************************************************************
1638 */
1639
1640
add_node(VideoParameters * p_Vid,struct concealment_node * concealment_new)1641 static void add_node( VideoParameters *p_Vid, struct concealment_node *concealment_new )
1642 {
1643 if( p_Vid->concealment_head == NULL )
1644 {
1645 p_Vid->concealment_end = p_Vid->concealment_head = concealment_new;
1646 return;
1647 }
1648 p_Vid->concealment_end->next = concealment_new;
1649 p_Vid->concealment_end = concealment_new;
1650 }
1651
1652
1653 /*!
1654 ************************************************************************
1655 * \brief
1656 * Deletes the specified node pointed to by 'ptr' from the list
1657 *
1658 ************************************************************************
1659 */
1660
1661
delete_node(VideoParameters * p_Vid,struct concealment_node * ptr)1662 static void delete_node( VideoParameters *p_Vid, struct concealment_node *ptr )
1663 {
1664 // We only need to delete the first node in the linked list
1665 if( ptr == p_Vid->concealment_head )
1666 {
1667 p_Vid->concealment_head = p_Vid->concealment_head->next;
1668 if( p_Vid->concealment_end == ptr )
1669 p_Vid->concealment_end = p_Vid->concealment_end->next;
1670 free(ptr);
1671 }
1672 }
1673
1674 /*!
1675 ************************************************************************
1676 * \brief
1677 * Deletes all nodes from the place specified by ptr
1678 *
1679 ************************************************************************
1680 */
1681
delete_list(VideoParameters * p_Vid,struct concealment_node * ptr)1682 void delete_list( VideoParameters *p_Vid, struct concealment_node *ptr )
1683 {
1684 struct concealment_node *temp;
1685
1686 if( p_Vid->concealment_head == NULL ) return;
1687
1688 if( ptr == p_Vid->concealment_head )
1689 {
1690 p_Vid->concealment_head = NULL;
1691 p_Vid->concealment_end = NULL;
1692 }
1693 else
1694 {
1695 temp = p_Vid->concealment_head;
1696
1697 while( temp->next != ptr )
1698 temp = temp->next;
1699 p_Vid->concealment_end = temp;
1700 }
1701
1702 while( ptr != NULL )
1703 {
1704 temp = ptr->next;
1705 free( ptr );
1706 ptr = temp;
1707 }
1708 }
1709
1710 /*!
1711 ************************************************************************
1712 * \brief
1713 * Stores the missing non reference frames in the concealment buffer. The
1714 * detection is based on the POC difference in the sorted POC array. A missing
1715 * non reference frame is detected when the dpb is full. A singly linked list
1716 * is maintained for storing the missing non reference frames.
1717 *
1718 ************************************************************************
1719 */
1720
conceal_non_ref_pics(DecodedPictureBuffer * p_Dpb,int diff)1721 void conceal_non_ref_pics(DecodedPictureBuffer *p_Dpb, int diff)
1722 {
1723 VideoParameters *p_Vid = p_Dpb->p_Vid;
1724 int missingpoc = 0;
1725 unsigned int i, pos = 0;
1726 StorablePicture *conceal_from_picture = NULL;
1727 StorablePicture *conceal_to_picture = NULL;
1728 struct concealment_node *concealment_ptr = NULL;
1729 int temp_used_size = p_Dpb->used_size;
1730
1731 if(p_Dpb->used_size == 0 )
1732 return;
1733
1734 qsort(p_Vid->pocs_in_dpb, p_Dpb->size, sizeof(int), comp);
1735
1736 for(i=0;i<p_Dpb->size-diff;i++)
1737 {
1738 p_Dpb->used_size = p_Dpb->size;
1739 if((p_Vid->pocs_in_dpb[i+1] - p_Vid->pocs_in_dpb[i]) > p_Vid->poc_gap)
1740 {
1741 conceal_to_picture = alloc_storable_picture (p_Vid, FRAME, p_Vid->width, p_Vid->height, p_Vid->width_cr, p_Vid->height_cr, 1);
1742
1743 missingpoc = p_Vid->pocs_in_dpb[i] + p_Vid->poc_gap;
1744 // Diagnostics
1745 // printf("\n missingpoc = %d\n",missingpoc);
1746
1747 if(missingpoc > p_Vid->earlier_missing_poc)
1748 {
1749 p_Vid->earlier_missing_poc = missingpoc;
1750 conceal_to_picture->top_poc = missingpoc;
1751 conceal_to_picture->bottom_poc = missingpoc;
1752 conceal_to_picture->frame_poc = missingpoc;
1753 conceal_to_picture->poc = missingpoc;
1754 conceal_from_picture = get_pic_from_dpb(p_Dpb, missingpoc, &pos);
1755
1756 assert(conceal_from_picture != NULL);
1757
1758 p_Dpb->used_size = pos + 1;
1759
1760 p_Vid->frame_to_conceal = conceal_from_picture->frame_num + 1;
1761
1762 update_ref_list_for_concealment(p_Dpb);
1763 p_Vid->conceal_slice_type = B_SLICE;
1764 copy_to_conceal(conceal_from_picture, conceal_to_picture, p_Vid);
1765 concealment_ptr = init_node( conceal_to_picture, missingpoc );
1766 add_node(p_Vid, concealment_ptr);
1767 // Diagnostics
1768 // print_node(concealment_ptr);
1769 }
1770 }
1771 }
1772
1773 //restore the original value
1774 //p_Dpb->used_size = p_Dpb->size;
1775 p_Dpb->used_size = temp_used_size;
1776 }
1777
1778 /*!
1779 ************************************************************************
1780 * \brief
1781 * Perform Sliding window decoded reference picture marking process. It
1782 * maintains the POC s stored in the dpb at a specific instance.
1783 *
1784 ************************************************************************
1785 */
1786
sliding_window_poc_management(DecodedPictureBuffer * p_Dpb,StorablePicture * p)1787 void sliding_window_poc_management(DecodedPictureBuffer *p_Dpb, StorablePicture *p)
1788 {
1789 if (p_Dpb->used_size == p_Dpb->size)
1790 {
1791 VideoParameters *p_Vid = p_Dpb->p_Vid;
1792 unsigned int i;
1793
1794 for(i=0;i<p_Dpb->size-1; i++)
1795 p_Vid->pocs_in_dpb[i] = p_Vid->pocs_in_dpb[i+1];
1796 }
1797 }
1798
1799
1800 /*!
1801 ************************************************************************
1802 * \brief
1803 * Outputs the non reference frames. The POCs in the concealment buffer are
1804 * sorted in ascending order and outputted when the lowest POC in the
1805 * concealment buffer is lower than the lowest in the p_Dpb-> The linked list
1806 * entry corresponding to the outputted POC is immediately deleted.
1807 *
1808 ************************************************************************
1809 */
1810
write_lost_non_ref_pic(DecodedPictureBuffer * p_Dpb,int poc,int p_out)1811 void write_lost_non_ref_pic(DecodedPictureBuffer *p_Dpb, int poc, int p_out)
1812 {
1813 VideoParameters *p_Vid = p_Dpb->p_Vid;
1814 FrameStore concealment_fs;
1815 if(poc > 0)
1816 {
1817 if((poc - p_Dpb->last_output_poc) > p_Vid->poc_gap)
1818 {
1819
1820 concealment_fs.frame = p_Vid->concealment_head->picture;
1821 concealment_fs.is_output = 0;
1822 concealment_fs.is_reference = 0;
1823 concealment_fs.is_used = 3;
1824
1825 write_stored_frame(p_Vid, &concealment_fs, p_out);
1826 delete_node(p_Vid, p_Vid->concealment_head);
1827 }
1828 }
1829 }
1830
1831 /*!
1832 ************************************************************************
1833 * \brief
1834 * Conceals frame loss immediately after the IDR. This special case produces
1835 * the same result for either frame copy or motion vector copy concealment.
1836 *
1837 ************************************************************************
1838 */
1839
write_lost_ref_after_idr(DecodedPictureBuffer * p_Dpb,int pos)1840 void write_lost_ref_after_idr(DecodedPictureBuffer *p_Dpb, int pos)
1841 {
1842 VideoParameters *p_Vid = p_Dpb->p_Vid;
1843
1844 int temp = 1;
1845
1846 if(p_Vid->last_out_fs->frame == NULL)
1847 {
1848 p_Vid->last_out_fs->frame = alloc_storable_picture (p_Vid, FRAME, p_Vid->width, p_Vid->height,
1849 p_Vid->width_cr, p_Vid->height_cr, 1);
1850 p_Vid->last_out_fs->is_used = 3;
1851 }
1852
1853 if(p_Vid->conceal_mode == 2)
1854 {
1855 temp = 2;
1856 p_Vid->conceal_mode = 1;
1857 }
1858 copy_to_conceal(p_Dpb->fs[pos]->frame, p_Vid->last_out_fs->frame, p_Vid);
1859
1860 p_Vid->conceal_mode = temp;
1861 }
1862
1863