videoeditorengine/avcedit/src/dpb.cpp
changeset 0 951a5db380a0
equal deleted inserted replaced
-1:000000000000 0:951a5db380a0
       
     1 /*
       
     2 * Copyright (c) 2010 Ixonos Plc.
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - Initial contribution
       
    11 *
       
    12 * Contributors:
       
    13 * Ixonos Plc
       
    14 *
       
    15 * Description:
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 #include <string.h>
       
    21 #include "globals.h"
       
    22 #include "framebuffer.h"
       
    23 #include "dpb.h"
       
    24 
       
    25 
       
    26 
       
    27 /*
       
    28  *
       
    29  * dpbOpen:
       
    30  *
       
    31  * Parameters:
       
    32  *
       
    33  * Function:
       
    34  *      Allocate DPB.
       
    35  *
       
    36  * Returns:
       
    37  *      Pointer to dpb or NULL
       
    38  *
       
    39  */
       
    40 dpb_s *dpbOpen()
       
    41 {
       
    42   dpb_s *dpb;
       
    43 
       
    44   dpb = (dpb_s *)User::Alloc(sizeof(dpb_s));
       
    45 
       
    46   if (dpb != NULL)
       
    47     memset(dpb, 0, sizeof(dpb_s));
       
    48 
       
    49   return dpb;
       
    50 }
       
    51 
       
    52 
       
    53 /*
       
    54  *
       
    55  * dpbClose:
       
    56  *
       
    57  * Parameters:
       
    58  *      dpb                   DPB object
       
    59  *
       
    60  * Function:
       
    61  *      Deinitialize DPB.
       
    62  *
       
    63  * Returns:
       
    64  *      -
       
    65  *
       
    66  */
       
    67 void dpbClose(dpb_s *dpb)
       
    68 {
       
    69   int i;
       
    70 
       
    71   for (i = 0; i < DPB_MAX_SIZE; i++)
       
    72     frmCloseRef(dpb->buffers[i]);
       
    73 
       
    74   User::Free(dpb);
       
    75 }
       
    76 
       
    77 
       
    78 /*
       
    79  *
       
    80  * dpbSetSize:
       
    81  *
       
    82  * Parameters:
       
    83  *      dpb                   DPB object
       
    84  *      dpbSize               New DPB size
       
    85  *
       
    86  * Function:
       
    87  *      Set DPB size in frames.
       
    88  *
       
    89  * Returns:
       
    90  *      -
       
    91  *
       
    92  */
       
    93 void dpbSetSize(dpb_s *dpb, int dpbSize)
       
    94 {
       
    95   int i;
       
    96 
       
    97   /* If new DPB size is smaller than old, close any unneeded frame buffers */
       
    98   for (i = dpbSize; i < dpb->size; i++) {
       
    99     frmCloseRef(dpb->buffers[i]);
       
   100     dpb->buffers[i] = NULL;
       
   101   }
       
   102 
       
   103   dpb->size = min(dpbSize, DPB_MAX_SIZE);
       
   104 }
       
   105 
       
   106 
       
   107 /*
       
   108  *
       
   109  * dpbGetNextOutputPic:
       
   110  *
       
   111  * Parameters:
       
   112  *      dpb                   DPB object
       
   113  *      dpbHasIDRorMMCO5      Set upon return if IDR picture or picture with
       
   114  *                            MMCO5 command is found in DPB
       
   115  *
       
   116  * Function:
       
   117  *      Find next frame to output (frame with the lowest POC).
       
   118  *      Search is started from the last active frame in dpb and is
       
   119  *      stopped if all frames have been checked or IDR picture or
       
   120  *      picture with MMCO5 is found.
       
   121  *
       
   122  * Returns:
       
   123  *      Framebuffer with the lowest POC or 0 if DPB is empty
       
   124  *
       
   125  */
       
   126 frmBuf_s *dpbGetNextOutputPic(dpb_s *dpb, int *dpbHasIDRorMMCO5)
       
   127 {
       
   128   frmBuf_s * tmpFrm;
       
   129   int i;
       
   130 
       
   131   tmpFrm = 0;
       
   132 
       
   133   /* Find first output pic in decoding order */
       
   134   for (i = dpb->fullness-1; i >= 0; i--) {
       
   135     if (dpb->buffers[i]->forOutput) {
       
   136       tmpFrm = dpb->buffers[i];
       
   137       break;
       
   138     }
       
   139   }
       
   140 
       
   141   *dpbHasIDRorMMCO5 = 0;
       
   142 
       
   143   /* Find picture with lowest poc. Stop search if IDR or MMCO5 is found */
       
   144   for (; i >= 0; i--) {
       
   145     if (dpb->buffers[i]->isIDR || dpb->buffers[i]->hasMMCO5) {
       
   146       *dpbHasIDRorMMCO5 = 1;
       
   147       break;
       
   148     }
       
   149     if (dpb->buffers[i]->forOutput && dpb->buffers[i]->poc < tmpFrm->poc)
       
   150       tmpFrm = dpb->buffers[i];
       
   151   }
       
   152 
       
   153   return tmpFrm;
       
   154 }
       
   155 
       
   156 
       
   157 /*
       
   158  *
       
   159  * dpbStorePicture:
       
   160  *
       
   161  * Parameters:
       
   162  *      dpb                   DPB object
       
   163  *      currPic               Current picture
       
   164  *      outputQueue           Output queue
       
   165  *
       
   166  * Function:
       
   167  *      - Remove unused frames (non-reference, non-output frames) from the DPB.
       
   168  *      - If there is room in the DPB, put picture to DPB.
       
   169  *      - If there is no room in DPB, put pictures to output queue
       
   170  *        until frame is available.
       
   171  *
       
   172  * Returns:
       
   173  *      The number of pictures in output queue or negative value for error.
       
   174  *
       
   175  */
       
   176 int dpbStorePicture(dpb_s *dpb, frmBuf_s *currPic, frmBuf_s *outputQueue[])
       
   177 {
       
   178   frmBuf_s *tmpRemList[DPB_MAX_SIZE];
       
   179   frmBuf_s *tmpFrm;
       
   180   int numFrm, numRemFrm;
       
   181   int i;
       
   182   int freeBufferFound;
       
   183   int numOutput;
       
   184   int dpbHasIDRorMMCO5;
       
   185 
       
   186   /*
       
   187    * If the current picture is a reference picture and DPB is already full of
       
   188    * reference pictures, we cannot insert current picture to DPB. Therefore,
       
   189    * we force one reference picture out of DPB to make space for current
       
   190    * picture. This situation can only happen with corrupted bitstreams.
       
   191    */
       
   192   if (currPic->refType != FRM_NON_REF_PIC &&
       
   193       (dpb->numShortTermPics+dpb->numLongTermPics) == dpb->size)
       
   194   {
       
   195     if (dpb->numLongTermPics == dpb->size)
       
   196       dpb->buffers[dpb->fullness-1]->refType = FRM_NON_REF_PIC;
       
   197     else
       
   198       dpbMarkLowestShortTermPicAsNonRef(dpb);
       
   199   }
       
   200 
       
   201   /*
       
   202    * Remove unused frames from dpb
       
   203    */
       
   204 
       
   205   numFrm = 0;
       
   206   numRemFrm = 0;
       
   207   for (i = 0; i < dpb->fullness; i++) {
       
   208     if (dpb->buffers[i]->refType != FRM_NON_REF_PIC || dpb->buffers[i]->forOutput) {
       
   209       dpb->buffers[numFrm] = dpb->buffers[i];
       
   210       numFrm++;
       
   211     }
       
   212     else {
       
   213       /* Put unsused pics to temporary list */
       
   214       tmpRemList[numRemFrm] = dpb->buffers[i];
       
   215       numRemFrm++;
       
   216     }
       
   217   }
       
   218 
       
   219   /* Copy unused pics after active pics */
       
   220   for (i = 0; i < numRemFrm; i++)
       
   221     dpb->buffers[numFrm+i] = tmpRemList[i];
       
   222 
       
   223   dpb->fullness = numFrm;
       
   224 
       
   225 
       
   226   /*
       
   227    * Try to store current pic to dpb. If there is no room in dpb, we have to
       
   228    * output some pictures to make room.
       
   229    */
       
   230 
       
   231   /* Case 1: if current pic is unused, it won't be stored in dpb */
       
   232   if (currPic->refType == FRM_NON_REF_PIC && !currPic->forOutput) {
       
   233     return 0;
       
   234   }
       
   235 
       
   236   /* Case 2: if there is space left in dpb, store current pic */
       
   237   if (dpb->fullness < dpb->size) {
       
   238 
       
   239     tmpFrm = dpb->buffers[dpb->fullness];   /* Unused frame */
       
   240 
       
   241     tmpFrm = frmMakeRefFrame(currPic, tmpFrm);
       
   242     if (tmpFrm == NULL)
       
   243       return DPB_ERR_MEM_ALLOC;
       
   244 
       
   245     /* Move frames one position toward end of the list */
       
   246     for (i = dpb->fullness; i > 0; i--)
       
   247       dpb->buffers[i] = dpb->buffers[i-1];
       
   248 
       
   249     /* Always insert new frame to the beginning of the list */
       
   250     dpb->buffers[0] = tmpFrm;
       
   251     dpb->fullness++;
       
   252 
       
   253     if (currPic->refType == FRM_SHORT_TERM_PIC)
       
   254       dpb->numShortTermPics++;
       
   255     else if (currPic->refType == FRM_LONG_TERM_PIC)
       
   256       dpb->numLongTermPics++;
       
   257 
       
   258     /* Current picture is marked unused */
       
   259     currPic->forOutput = 0;
       
   260     currPic->refType   = FRM_NON_REF_PIC;
       
   261 
       
   262     /* No pictures in ouput queue */
       
   263     return 0;
       
   264   }
       
   265 
       
   266   /* Case 3: output pictures with bumping process until there is space in dpb or
       
   267   *  current pic is non-reference and has lowest poc */
       
   268   freeBufferFound = 0;
       
   269   numOutput       = 0;
       
   270   while (!freeBufferFound) {
       
   271 
       
   272     /* Next picture to output is a picture having smallest POC in DPB */
       
   273     tmpFrm = dpbGetNextOutputPic(dpb, &dpbHasIDRorMMCO5);
       
   274 
       
   275     /* Current picture is output if it is non-reference picture having */
       
   276     /* smaller POC than any of the pictures in DPB                     */
       
   277     if (currPic->refType == FRM_NON_REF_PIC &&
       
   278         (tmpFrm == 0 || (!dpbHasIDRorMMCO5 && currPic->poc < tmpFrm->poc)))
       
   279     {
       
   280       /* Output current picture  */
       
   281       currPic->forOutput = 0;
       
   282       outputQueue[numOutput] = currPic;
       
   283       numOutput++;
       
   284       freeBufferFound = 1;
       
   285     }
       
   286     else {
       
   287       /* Output picture that we got from DPB */
       
   288       tmpFrm->forOutput = 0;
       
   289       outputQueue[numOutput] = tmpFrm;
       
   290       numOutput++;
       
   291       if (tmpFrm->refType == FRM_NON_REF_PIC)
       
   292         freeBufferFound = 1;
       
   293     }
       
   294   }
       
   295 
       
   296   return numOutput;
       
   297 }
       
   298 
       
   299 
       
   300 /*
       
   301  *
       
   302  * dpbUpdatePicNums:
       
   303  *
       
   304  * Parameters:
       
   305  *      dpb                   DPB object
       
   306  *      frameNum              Current picture frame number
       
   307  *      maxFrameNum           Maximum frame number
       
   308  *
       
   309  * Function:
       
   310  *      Compute picture numbers for all pictures in DPB.
       
   311  *
       
   312  * Returns:
       
   313  *      -
       
   314  *
       
   315  */
       
   316 void dpbUpdatePicNums(dpb_s *dpb, int32 frameNum, int32 maxFrameNum)
       
   317 {
       
   318   int i;
       
   319   frmBuf_s **refPicList;
       
   320 
       
   321   refPicList = dpb->buffers;
       
   322 
       
   323   for (i = 0; i < dpb->fullness; i++) {
       
   324     if (refPicList[i]->refType == FRM_SHORT_TERM_PIC) {
       
   325       /* Short term pictures */
       
   326       if (refPicList[i]->frameNum > frameNum)
       
   327         refPicList[i]->picNum = refPicList[i]->frameNum - maxFrameNum;
       
   328       else
       
   329         refPicList[i]->picNum = refPicList[i]->frameNum;
       
   330     }
       
   331     else if (refPicList[i]->refType == FRM_LONG_TERM_PIC)
       
   332       /* Long term pictures */
       
   333       refPicList[i]->longTermPicNum = refPicList[i]->longTermFrmIdx;
       
   334   }
       
   335 }
       
   336 
       
   337 
       
   338 /*
       
   339  *
       
   340  * dpbMarkAllPicsAsNonRef:
       
   341  *
       
   342  * Parameters:
       
   343  *      dpb                   DPB object
       
   344  *
       
   345  * Function:
       
   346  *      Mark all picrures as non-reference pictures.
       
   347  *
       
   348  * Returns:
       
   349  *      -
       
   350  *
       
   351  */
       
   352 void dpbMarkAllPicsAsNonRef(dpb_s *dpb)
       
   353 {
       
   354   int i;
       
   355 
       
   356   /* Mark all pictures as not used for reference */
       
   357   for (i = 0; i < dpb->fullness; i++)
       
   358     dpb->buffers[i]->refType = FRM_NON_REF_PIC;
       
   359 
       
   360   dpb->numShortTermPics = 0;
       
   361   dpb->numLongTermPics  = 0;
       
   362 }
       
   363 
       
   364 
       
   365 /*
       
   366  *
       
   367  * dpbMarkLowestShortTermPicAsNonRef:
       
   368  *
       
   369  * Parameters:
       
   370  *      dpb                   DPB object
       
   371  *
       
   372  * Function:
       
   373  *      Mark short-term picture having lowest picture number as
       
   374  *      non-reference pictures.
       
   375  *
       
   376  * Returns:
       
   377  *      -
       
   378  *
       
   379  */
       
   380 void dpbMarkLowestShortTermPicAsNonRef(dpb_s *dpb)
       
   381 {
       
   382   int picIdx;
       
   383   int i;
       
   384 
       
   385   /* Find short term pic with lowest picNum */
       
   386   picIdx = -1;
       
   387   for (i = dpb->fullness-1; i >= 0; i--) {
       
   388     if (dpb->buffers[i]->refType == FRM_SHORT_TERM_PIC &&
       
   389         (picIdx < 0 || dpb->buffers[i]->picNum < dpb->buffers[picIdx]->picNum))
       
   390       picIdx = i;
       
   391   }
       
   392 
       
   393   /* Mark short term pic with lowest picNum as not reference picture */
       
   394   if (picIdx >= 0) {
       
   395     dpb->buffers[picIdx]->refType = FRM_NON_REF_PIC;
       
   396     dpb->numShortTermPics--;
       
   397   }
       
   398 }
       
   399 
       
   400 
       
   401 /*
       
   402  *
       
   403  * dpbMarkShortTermPicAsNonRef:
       
   404  *
       
   405  * Parameters:
       
   406  *      dpb                   DPB object
       
   407  *      picNum                Picture number
       
   408  *
       
   409  * Function:
       
   410  *      Mark short-term picture having picture number picNum as
       
   411  *      non-reference picture.
       
   412  *
       
   413  * Returns:
       
   414  *      DPB_OK or DPB_ERR_PICTURE_NOT_FOUND
       
   415  *
       
   416  */
       
   417 int dpbMarkShortTermPicAsNonRef(dpb_s *dpb, int32 picNum)
       
   418 {
       
   419   int i;
       
   420 
       
   421   for (i = 0; i < dpb->fullness; i++) {
       
   422     if (dpb->buffers[i]->refType == FRM_SHORT_TERM_PIC &&
       
   423         dpb->buffers[i]->picNum == picNum)
       
   424     {
       
   425       dpb->buffers[i]->refType = FRM_NON_REF_PIC;
       
   426       dpb->numShortTermPics--;
       
   427       return DPB_OK;
       
   428     }
       
   429   }
       
   430 
       
   431   return DPB_ERR_PICTURE_NOT_FOUND;
       
   432 }
       
   433 
       
   434 
       
   435 /*
       
   436  *
       
   437  * dpbMarkLongTermPicAsNonRef:
       
   438  *
       
   439  * Parameters:
       
   440  *      dpb                   DPB object
       
   441  *      longTermPicNum        Long-term picture number
       
   442  *
       
   443  * Function:
       
   444  *      Mark long-term picture having long-term picture number longTermPicNum
       
   445  *      as non-reference picture.
       
   446  *
       
   447  * Returns:
       
   448  *      DPB_OK or DPB_ERR_PICTURE_NOT_FOUND
       
   449  *
       
   450  */
       
   451 int dpbMarkLongTermPicAsNonRef(dpb_s *dpb, int longTermPicNum)
       
   452 {
       
   453   int i;
       
   454 
       
   455   for (i = 0; i < dpb->fullness; i++) {
       
   456     if (dpb->buffers[i]->refType == FRM_LONG_TERM_PIC &&
       
   457         dpb->buffers[i]->longTermPicNum == longTermPicNum)
       
   458     {
       
   459       dpb->buffers[i]->refType = FRM_NON_REF_PIC;
       
   460       dpb->numLongTermPics--;
       
   461       return DPB_OK;
       
   462     }
       
   463   }
       
   464 
       
   465   return DPB_ERR_PICTURE_NOT_FOUND;
       
   466 }
       
   467 
       
   468 
       
   469 /*
       
   470  *
       
   471  * dpbVerifyLongTermFrmIdx:
       
   472  *
       
   473  * Parameters:
       
   474  *      dpb                   DPB object
       
   475  *      longTermFrmIdx        Long-term frame index
       
   476  *
       
   477  * Function:
       
   478  *      If there is a long-term picture having long term frame index
       
   479  *      longTermFrmIdx, mark that picture as non-reference picture.
       
   480  *
       
   481  * Returns:
       
   482  *      -
       
   483  *
       
   484  */
       
   485 void dpbVerifyLongTermFrmIdx(dpb_s *dpb, int longTermFrmIdx)
       
   486 {
       
   487   int i;
       
   488 
       
   489   /* Check if longTermFrmIdx is already in use */
       
   490   for (i = 0; i < dpb->fullness; i++) {
       
   491     if (dpb->buffers[i]->refType == FRM_LONG_TERM_PIC &&
       
   492         dpb->buffers[i]->longTermFrmIdx == longTermFrmIdx)
       
   493     {
       
   494       dpb->buffers[i]->refType = FRM_NON_REF_PIC;
       
   495       dpb->numLongTermPics--;
       
   496       break;
       
   497     }
       
   498   }
       
   499 }
       
   500 
       
   501 
       
   502 /*
       
   503  *
       
   504  * dpbMarkShortTermPicAsLongTerm:
       
   505  *
       
   506  * Parameters:
       
   507  *      dpb                   DPB object
       
   508  *      picNum                Picture number
       
   509  *      longTermFrmIdx        Long-term frame index
       
   510  *
       
   511  * Function:
       
   512  *      Mark short-term picture having picture number picNum as long-term
       
   513  *      picture having long-term frame index longTermFrmIdx.
       
   514  *
       
   515  * Returns:
       
   516  *      DPB_OK or DPB_ERR_PICTURE_NOT_FOUND
       
   517  *
       
   518  */
       
   519 int dpbMarkShortTermPicAsLongTerm(dpb_s *dpb, int32 picNum, int longTermFrmIdx)
       
   520 {
       
   521   int i;
       
   522 
       
   523   /* To avoid duplicate of longTermFrmIdx */
       
   524   dpbVerifyLongTermFrmIdx(dpb, longTermFrmIdx);
       
   525 
       
   526   /* Mark pic with picNum as long term and assign longTermFrmIdx to it */
       
   527   for (i = 0; i < dpb->fullness; i++) {
       
   528     if (dpb->buffers[i]->refType == FRM_SHORT_TERM_PIC &&
       
   529         dpb->buffers[i]->picNum == picNum)
       
   530     {
       
   531       dpb->buffers[i]->refType = FRM_LONG_TERM_PIC;
       
   532       dpb->buffers[i]->longTermFrmIdx = longTermFrmIdx;
       
   533       dpb->numShortTermPics--;
       
   534       dpb->numLongTermPics++;
       
   535       return DPB_OK;
       
   536     }
       
   537   }
       
   538 
       
   539   return DPB_ERR_PICTURE_NOT_FOUND;
       
   540 }
       
   541 
       
   542 
       
   543 /*
       
   544  *
       
   545  * dpbSetMaxLongTermFrameIdx:
       
   546  *
       
   547  * Parameters:
       
   548  *      dpb                     DPB object
       
   549  *      maxLongTermFrmIdxPlus1  Maximum long-term frame index plus 1
       
   550  *
       
   551  * Function:
       
   552  *      Set maximum long-term frame index. All long-term pictures having
       
   553  *      bigger long-term frame index than maxLongTermFrmIdxPlus1-1 are
       
   554  *      marked as non-reference pictures.
       
   555  *
       
   556  * Returns:
       
   557  *      -
       
   558  *
       
   559  */
       
   560 void dpbSetMaxLongTermFrameIdx(dpb_s *dpb, int maxLongTermFrmIdxPlus1)
       
   561 {
       
   562   int i;
       
   563 
       
   564   for (i = 0; i < dpb->fullness; i++) {
       
   565     if (dpb->buffers[i]->refType == FRM_LONG_TERM_PIC &&
       
   566         dpb->buffers[i]->longTermFrmIdx > maxLongTermFrmIdxPlus1-1)
       
   567     {
       
   568       dpb->buffers[i]->refType = FRM_NON_REF_PIC;
       
   569       dpb->numLongTermPics--;
       
   570     }
       
   571   }
       
   572 
       
   573   dpb->maxLongTermFrameIdx = maxLongTermFrmIdxPlus1 - 1;
       
   574 }