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