Ignore:
Timestamp:
11 Feb 2014, 23:53:38 (11 years ago)
Author:
qualcomm
Message:

JCTVC-P0192: Aligned bumping of sub-DPBs (MACRO: ALIGNED_BUMPING)

Added support to align the bumping process across layers in an access unit, and also clearly invoke the bumping process as given in Annex C. Support for NoOutputOfPriorPicsFlag will be added in a later patch.

From: Adarsh K. Ramasubramonian <aramasub@…>

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/SHM-5.1-dev/source/App/TAppDecoder/TAppDecTop.cpp

    r595 r612  
    4141#include <fcntl.h>
    4242#include <assert.h>
    43 
     43#include <iostream>
    4444#include "TAppDecTop.h"
    4545#include "TLibDecoder/AnnexBread.h"
    4646#include "TLibDecoder/NALread.h"
    47 
    4847//! \ingroup TAppDecoder
    4948//! \{
     
    255254        openedReconFile[curLayerId] = true;
    256255      }
     256#if ALIGNED_BUMPING
     257      Bool outputPicturesFlag = true; 
     258
     259      if (nalu.m_nalUnitType == NAL_UNIT_EOS) // End of sequence
     260      {
     261        flushAllPictures( nalu.m_layerId, outputPicturesFlag );       
     262      }
     263      if( bNewPicture ) // New picture, slice header parsed but picture not decoded
     264      {
     265        if ( bNewPOC &&
     266           (   nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_W_RADL
     267            || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_N_LP
     268            || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA_N_LP
     269            || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA_W_RADL
     270            || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA_W_LP ) )
     271        {
     272          flushAllPictures( nalu.m_layerId, outputPicturesFlag );
     273        }
     274        else
     275        {
     276          this->checkOutputBeforeDecoding( nalu.m_layerId );
     277        }
     278      }
     279
     280      /* The following code has to be executed when the last DU of the picture is decoded
     281         TODO: Need code to identify end of decoding a picture
     282      {
     283        this->checkOutputAfterDecoding( );
     284      } */
     285#else
    257286      if ( bNewPicture && bNewPOC &&
    258287           (   nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_W_RADL
     
    273302        xWriteOutput( pcListPic, curLayerId, nalu.m_temporalId );
    274303      }
    275     }
    276   }
     304#endif
     305    }
     306  }
     307#if ALIGNED_BUMPING
     308   flushAllPictures( true );   
     309#else
    277310  for(UInt layer = 0; layer <= m_tgtLayerId; layer++)
    278311  {
    279312    xFlushOutput( m_acTDecTop[layer].getListPic(), layer );
    280313  }
     314#endif
    281315  // delete buffers
    282316#if AVC_BASE
     
    9871021  return false;
    9881022}
    989 
     1023#if ALIGNED_BUMPING
     1024// Function outputs a picture, and marks it as not needed for output.
     1025Void TAppDecTop::xOutputAndMarkPic( TComPic *pic, const Char *reconFile, const Int layerIdx, Int &pocLastDisplay, DpbStatus &dpbStatus )
     1026{
     1027  if ( reconFile )
     1028  {
     1029    const Window &conf = pic->getConformanceWindow();
     1030    const Window &defDisp = m_respectDefDispWindow ? pic->getDefDisplayWindow() : Window();
     1031    Int xScal =  1, yScal = 1;
     1032  #if REPN_FORMAT_IN_VPS
     1033    UInt chromaFormatIdc = pic->getSlice(0)->getChromaFormatIdc();
     1034    xScal = TComSPS::getWinUnitX( chromaFormatIdc );
     1035    yScal = TComSPS::getWinUnitY( chromaFormatIdc );
     1036#endif
     1037    m_acTVideoIOYuvReconFile[layerIdx].write( pic->getPicYuvRec(),
     1038      conf.getWindowLeftOffset()  * xScal + defDisp.getWindowLeftOffset(),
     1039      conf.getWindowRightOffset() * xScal + defDisp.getWindowRightOffset(),
     1040      conf.getWindowTopOffset()   * yScal + defDisp.getWindowTopOffset(),
     1041      conf.getWindowBottomOffset()* yScal + defDisp.getWindowBottomOffset() );
     1042  }
     1043       
     1044  // update POC of display order
     1045  pocLastDisplay = pic->getPOC();
     1046
     1047  // Mark as not needed for output
     1048  pic->setOutputMark(false);
     1049
     1050  // "erase" non-referenced picture in the reference picture list after display
     1051  if ( !pic->getSlice(0)->isReferenced() && pic->getReconMark() == true )
     1052  {
     1053    pic->setReconMark(false);
     1054
     1055    // mark it should be extended later
     1056    pic->getPicYuvRec()->setBorderExtension( false );
     1057
     1058    dpbStatus.m_numPicsInLayer[layerIdx]--;
     1059  }
     1060}
     1061
     1062Void TAppDecTop::flushAllPictures(Int layerId, Bool outputPictures)
     1063{
     1064  // First "empty" all pictures that are not used for reference and not needed for output
     1065  emptyUnusedPicturesNotNeededForOutput();
     1066
     1067  if( outputPictures )  // All pictures in the DPB in that layer are to be output; this means other pictures would also be output
     1068  {
     1069    Int numReorderPics = -1;
     1070    std::vector<Int>  listOfPocs;
     1071    std::vector<Int>  listOfPocsInEachLayer[MAX_LAYERS];
     1072    std::vector<Int>  listOfPocsPositionInEachLayer[MAX_LAYERS];
     1073    DpbStatus dpbStatus;
     1074
     1075    // Find the status of the DPB
     1076    xFindDPBStatus(listOfPocs, listOfPocsInEachLayer, listOfPocsPositionInEachLayer, dpbStatus);
     1077
     1078    if( listOfPocs.size() )
     1079    {
     1080      while( listOfPocsInEachLayer[layerId].size() )    // As long as there picture in the layer to be output
     1081      {
     1082        bumpingProcess( listOfPocs, listOfPocsInEachLayer, listOfPocsPositionInEachLayer, dpbStatus );
     1083      }
     1084    }
     1085  }
     1086
     1087  // Now remove all pictures from the layer DPB?
     1088  markAllPicturesAsErased(layerId);
     1089}
     1090Void TAppDecTop::flushAllPictures(Bool outputPictures)
     1091{
     1092  // First "empty" all pictures that are not used for reference and not needed for output
     1093  emptyUnusedPicturesNotNeededForOutput();
     1094
     1095  if( outputPictures )  // All pictures in the DPB are to be output
     1096  {
     1097    Int numReorderPics = -1;
     1098    std::vector<Int>  listOfPocs;
     1099    std::vector<Int>  listOfPocsInEachLayer[MAX_LAYERS];
     1100    std::vector<Int>  listOfPocsPositionInEachLayer[MAX_LAYERS];
     1101    DpbStatus dpbStatus;
     1102
     1103    // Find the status of the DPB
     1104    xFindDPBStatus(listOfPocs, listOfPocsInEachLayer, listOfPocsPositionInEachLayer, dpbStatus);
     1105
     1106    while( dpbStatus.m_numAUsNotDisplayed )
     1107    {
     1108      bumpingProcess( listOfPocs, listOfPocsInEachLayer, listOfPocsPositionInEachLayer, dpbStatus );
     1109    }
     1110  }
     1111
     1112  // Now remove all pictures from the DPB?
     1113  markAllPicturesAsErased();
     1114}
     1115
     1116Void TAppDecTop::markAllPicturesAsErased()
     1117{
     1118  for(Int i = 0; i < MAX_LAYERS; i++)
     1119  {
     1120    m_acTDecTop[i].getListPic()->clear();
     1121  }
     1122}
     1123
     1124Void TAppDecTop::markAllPicturesAsErased(Int layerIdx)
     1125{
     1126  m_acTDecTop[layerIdx].getListPic()->clear();
     1127}
     1128
     1129Void TAppDecTop::checkOutputBeforeDecoding(Int layerIdx)
     1130{
     1131   
     1132  Int numReorderPics = -1;
     1133  std::vector<Int>  listOfPocs;
     1134  std::vector<Int>  listOfPocsInEachLayer[MAX_LAYERS];
     1135  std::vector<Int>  listOfPocsPositionInEachLayer[MAX_LAYERS];
     1136  DpbStatus dpbStatus;
     1137
     1138  // First "empty" all pictures that are not used for reference and not needed for output
     1139  emptyUnusedPicturesNotNeededForOutput();
     1140
     1141  // Find the status of the DPB
     1142  xFindDPBStatus(listOfPocs, listOfPocsInEachLayer, listOfPocsPositionInEachLayer, dpbStatus);
     1143
     1144  // If not picture to be output, return
     1145  if( listOfPocs.size() == 0 )
     1146  {
     1147    return;
     1148  }
     1149
     1150  // Find DPB-information from the VPS
     1151  DpbStatus maxDpbLimit;
     1152  TComVPS *vps = findDpbParametersFromVps(listOfPocs, listOfPocsInEachLayer, listOfPocsPositionInEachLayer, maxDpbLimit);
     1153  Int targetLsIdx = vps->getOutputLayerSetIdx( getCommonDecoderParams()->getTargetOutputLayerSetIdx() );
     1154  Int subDpbIdx   = vps->getSubDpbAssigned( targetLsIdx, layerIdx );
     1155  // Assume that listOfPocs is sorted in increasing order - if not have to sort it.
     1156  while( ifInvokeBumpingBeforeDecoding(dpbStatus, maxDpbLimit, layerIdx, subDpbIdx) )
     1157  {
     1158    bumpingProcess( listOfPocs, listOfPocsInEachLayer, listOfPocsPositionInEachLayer, dpbStatus );
     1159  } 
     1160}
     1161
     1162Void TAppDecTop::checkOutputAfterDecoding()
     1163{   
     1164  Int numReorderPics = -1;
     1165  std::vector<Int>  listOfPocs;
     1166  std::vector<Int>  listOfPocsInEachLayer[MAX_LAYERS];
     1167  std::vector<Int>  listOfPocsPositionInEachLayer[MAX_LAYERS];
     1168  DpbStatus dpbStatus;
     1169
     1170  // First "empty" all pictures that are not used for reference and not needed for output
     1171  emptyUnusedPicturesNotNeededForOutput();
     1172
     1173  // Find the status of the DPB
     1174  xFindDPBStatus(listOfPocs, listOfPocsInEachLayer, listOfPocsPositionInEachLayer, dpbStatus);
     1175
     1176  // If not picture to be output, return
     1177  if( listOfPocs.size() == 0 )
     1178  {
     1179    return;
     1180  }
     1181
     1182  // Find DPB-information from the VPS
     1183  DpbStatus maxDpbLimit;
     1184  findDpbParametersFromVps(listOfPocs, listOfPocsInEachLayer, listOfPocsPositionInEachLayer, maxDpbLimit);
     1185
     1186  // Assume that listOfPocs is sorted in increasing order - if not have to sort it.
     1187  while( ifInvokeBumpingAfterDecoding(dpbStatus, maxDpbLimit) )
     1188  {
     1189    bumpingProcess( listOfPocs, listOfPocsInEachLayer, listOfPocsPositionInEachLayer, dpbStatus );
     1190  } 
     1191}
     1192
     1193Void TAppDecTop::bumpingProcess(std::vector<Int> &listOfPocs, std::vector<Int> *listOfPocsInEachLayer, std::vector<Int> *listOfPocsPositionInEachLayer, DpbStatus &dpbStatus)
     1194{
     1195  // Choose the smallest POC value
     1196  Int pocValue = *(listOfPocs.begin());
     1197  std::vector<int>::iterator it;
     1198  TComList<TComPic*>::iterator iterPic;
     1199  for( Int layerIdx = 0; layerIdx < dpbStatus.m_numLayers; layerIdx++)
     1200  {
     1201    // Check if picture with pocValue is present.
     1202    it = find( listOfPocsInEachLayer[layerIdx].begin(), listOfPocsInEachLayer[layerIdx].end(), pocValue );
     1203    if( it != listOfPocsInEachLayer[layerIdx].end() )  // picture found.
     1204    {
     1205      Int picPosition = std::distance( listOfPocsInEachLayer[layerIdx].begin(), it );
     1206      Int j;
     1207      for(j = 0, iterPic = m_acTDecTop[layerIdx].getListPic()->begin(); j < listOfPocsPositionInEachLayer[layerIdx][picPosition]; j++) // Picture to be output
     1208      {
     1209        iterPic++;
     1210      }
     1211      TComPic *pic = *iterPic;
     1212
     1213      xOutputAndMarkPic( pic, m_pchReconFile[layerIdx], layerIdx, m_aiPOCLastDisplay[layerIdx], dpbStatus );
     1214
     1215      listOfPocsInEachLayer[layerIdx].erase( it );
     1216      listOfPocsPositionInEachLayer[layerIdx].erase( listOfPocsPositionInEachLayer[layerIdx].begin() + picPosition );
     1217    }
     1218  }
     1219  // Update sub-DPB status
     1220  for( Int subDpbIdx = 0; subDpbIdx < dpbStatus.m_numSubDpbs; subDpbIdx++)
     1221  {
     1222    dpbStatus.m_numPicsInSubDpb[subDpbIdx]--;
     1223  }
     1224  dpbStatus.m_numAUsNotDisplayed--;   
     1225
     1226  // Remove the picture from the listOfPocs
     1227  listOfPocs.erase( listOfPocs.begin() );
     1228}
     1229
     1230TComVPS *TAppDecTop::findDpbParametersFromVps(std::vector<Int> const &listOfPocs, std::vector<Int> const *listOfPocsInEachLayer, std::vector<Int> const *listOfPocsPositionInEachLayer, DpbStatus &maxDpbLimit)
     1231{
     1232  // -------------------------------------
     1233  // Find the VPS used for the pictures
     1234  // -------------------------------------
     1235  TComVPS *vps;
     1236  for(Int i = 0; i < MAX_LAYERS; i++)
     1237  {
     1238    if( m_acTDecTop[i].getListPic()->empty() )
     1239    {
     1240      assert( listOfPocsInEachLayer[i].size() == 0 );
     1241      continue;
     1242    }
     1243    std::vector<Int>::const_iterator it;
     1244    it = find( listOfPocsInEachLayer[i].begin(), listOfPocsInEachLayer[i].end(), listOfPocs[0] );
     1245    TComList<TComPic*>::iterator iterPic;
     1246    if( it != listOfPocsInEachLayer[i].end() )
     1247    {
     1248      Int picPosition = std::distance( listOfPocsInEachLayer[i].begin(), it );
     1249      Int j;
     1250      for(j = 0, iterPic = m_acTDecTop[i].getListPic()->begin(); j < listOfPocsPositionInEachLayer[i][picPosition]; j++) // Picture to be output
     1251      {
     1252        iterPic++;
     1253      }
     1254      TComPic *pic = *iterPic;
     1255      vps = pic->getSlice(0)->getVPS();
     1256      break;
     1257    }
     1258  }
     1259  Int targetOutputLsIdx = getCommonDecoderParams()->getTargetOutputLayerSetIdx();
     1260  Int targetLsIdx       = vps->getOutputLayerSetIdx( getCommonDecoderParams()->getTargetOutputLayerSetIdx() );
     1261  Int highestTId = getCommonDecoderParams()->getHighestTId();
     1262
     1263  maxDpbLimit.m_numAUsNotDisplayed = vps->getMaxVpsNumReorderPics( targetOutputLsIdx, highestTId ); // m_numAUsNotDisplayed is only variable name - stores reorderpics
     1264  maxDpbLimit.m_maxLatencyIncrease  = vps->getMaxVpsLatencyIncreasePlus1(targetOutputLsIdx, highestTId ) > 0;
     1265  if( maxDpbLimit.m_maxLatencyIncrease )
     1266  {
     1267    maxDpbLimit.m_maxLatencyPictures = vps->getMaxVpsNumReorderPics( targetOutputLsIdx, highestTId ) + vps->getMaxVpsLatencyIncreasePlus1(targetOutputLsIdx, highestTId ) - 1;
     1268  }
     1269  for(Int i = 0; i < vps->getNumLayersInIdList( targetLsIdx ); i++)
     1270  {
     1271    maxDpbLimit.m_numPicsInLayer[i] = vps->getMaxVpsLayerDecPicBuffMinus1( targetOutputLsIdx, i, highestTId ) + 1;
     1272    maxDpbLimit.m_numPicsInSubDpb[vps->getSubDpbAssigned( targetLsIdx, i )] = vps->getMaxVpsDecPicBufferingMinus1( targetOutputLsIdx, vps->getSubDpbAssigned( targetLsIdx, i ), highestTId) + 1;
     1273  }
     1274  return vps;
     1275  // -------------------------------------
     1276}
     1277Void TAppDecTop::emptyUnusedPicturesNotNeededForOutput()
     1278{
     1279  for(Int layerIdx = 0; layerIdx < MAX_LAYERS; layerIdx++)
     1280  {
     1281    TComList <TComPic*> *pcListPic = m_acTDecTop[layerIdx].getListPic();
     1282    TComList<TComPic*>::iterator iterPic = pcListPic->begin();
     1283    while ( iterPic != pcListPic->end() )
     1284    {
     1285      TComPic *pic = *iterPic;
     1286      if( !pic->getSlice(0)->isReferenced() && !pic->getOutputMark() )
     1287      {
     1288        // Emtpy the picture buffer
     1289        pic->setReconMark( false );
     1290      }
     1291      iterPic++;
     1292    }
     1293  }
     1294}
     1295
     1296Bool TAppDecTop::ifInvokeBumpingBeforeDecoding( const DpbStatus &dpbStatus, const DpbStatus &dpbLimit, const Int layerIdx, const Int subDpbIdx )
     1297{
     1298  Bool retVal = false;
     1299  // Number of reorder picutres
     1300  retVal |= ( dpbStatus.m_numAUsNotDisplayed > dpbLimit.m_numAUsNotDisplayed );
     1301
     1302  // Number of pictures in each sub-DPB
     1303  retVal |= ( dpbStatus.m_numPicsInSubDpb[subDpbIdx] >= dpbLimit.m_numPicsInSubDpb[subDpbIdx] );
     1304 
     1305  // Number of pictures in each layer
     1306  retVal |= ( dpbStatus.m_numPicsInLayer[layerIdx] >= dpbLimit.m_numPicsInLayer[layerIdx]);
     1307
     1308  return retVal;
     1309}
     1310
     1311Bool TAppDecTop::ifInvokeBumpingAfterDecoding( const DpbStatus &dpbStatus, const DpbStatus &dpbLimit )
     1312{
     1313  Bool retVal = false;
     1314
     1315  // Number of reorder picutres
     1316  retVal |= ( dpbStatus.m_numAUsNotDisplayed > dpbLimit.m_numAUsNotDisplayed );
     1317
     1318  return retVal;
     1319}
     1320
     1321Void TAppDecTop::xFindDPBStatus( std::vector<Int> &listOfPocs
     1322                            , std::vector<Int> *listOfPocsInEachLayer
     1323                            , std::vector<Int> *listOfPocsPositionInEachLayer
     1324                            , DpbStatus &dpbStatus
     1325                            )
     1326{
     1327  TComVPS *vps = NULL;
     1328  dpbStatus.init();
     1329  for( Int i = 0; i < MAX_LAYERS; i++ )
     1330  {
     1331    if( m_acTDecTop[i].getListPic()->empty() )
     1332    {
     1333      continue;
     1334    }
     1335   
     1336    // To check # AUs that have at least one picture not output,
     1337    // For each layer, populate listOfPOcs if not already present
     1338    TComList<TComPic*>::iterator iterPic = m_acTDecTop[i].getListPic()->begin();
     1339    Int picPositionInList = 0;
     1340    while (iterPic != m_acTDecTop[i].getListPic()->end())
     1341    {
     1342      TComPic* pic = *(iterPic);
     1343      if( pic->getReconMark() )
     1344      {
     1345        if( vps == NULL )
     1346        {
     1347          vps = pic->getSlice(0)->getVPS();
     1348        }
     1349
     1350        std::vector<Int>::iterator it;
     1351        if( pic->getOutputMark() ) // && pic->getPOC() > m_aiPOCLastDisplay[i])
     1352        {
     1353          it = find( listOfPocs.begin(), listOfPocs.end(), pic->getPOC() ); // Check if already included
     1354          if( it == listOfPocs.end() )  // New POC value - i.e. new AU - add to the list
     1355          {
     1356            listOfPocs.push_back( pic->getPOC() );
     1357          }
     1358          listOfPocsInEachLayer         [i].push_back( pic->getPOC()    );    // POC to be output in each layer
     1359          listOfPocsPositionInEachLayer [i].push_back( picPositionInList  );  // For ease of access
     1360        }
     1361        if( pic->getSlice(0)->isReferenced() || pic->getOutputMark() )
     1362        {
     1363          dpbStatus.m_numPicsInLayer[i]++;  // Count pictures that are "used for reference" or "needed for output"
     1364        }
     1365      }
     1366      iterPic++;
     1367      picPositionInList++;
     1368    }
     1369  }
     1370
     1371  assert( vps != NULL );    // No picture in any DPB?
     1372  std::sort( listOfPocs.begin(), listOfPocs.end() );    // Sort in increasing order of POC
     1373  Int targetLsIdx = vps->getOutputLayerSetIdx( getCommonDecoderParams()->getTargetOutputLayerSetIdx() );
     1374  // Update status
     1375  dpbStatus.m_numAUsNotDisplayed = listOfPocs.size();   // Number of AUs not displayed
     1376  dpbStatus.m_numLayers = vps->getMaxLayers();
     1377  dpbStatus.m_numSubDpbs = vps->getNumSubDpbs( vps->getOutputLayerSetIdx(
     1378                                                      this->getCommonDecoderParams()->getTargetOutputLayerSetIdx() ) );
     1379
     1380  for(Int i = 0; i < dpbStatus.m_numLayers; i++)
     1381  {
     1382    dpbStatus.m_numPicsNotDisplayedInLayer[i] = listOfPocsInEachLayer[i].size();
     1383    dpbStatus.m_numPicsInSubDpb[vps->getSubDpbAssigned(targetLsIdx,i)] += dpbStatus.m_numPicsInLayer[i];
     1384  }
     1385  assert( dpbStatus.m_numAUsNotDisplayed != -1 );
     1386
     1387
     1388
     1389#endif
    9901390//! \}
Note: See TracChangeset for help on using the changeset viewer.