gopdecoder.cpp

来自「SVC最新更新代码」· C++ 代码 · 共 1,768 行 · 第 1/5 页

CPP
1,768
字号
    m_pcCurrDPBUnit->getCtrlData().setMbDataCtrl0L1( pcMbDataCtrl0 );
  }
  return Err::m_nOK;
}

CurrDPBUnit*
DecodedPicBuffer::getILPredDPBUnit()
{
  ROTRS( m_pcCurrDPBUnitILPred->isCompleted(),  m_pcCurrDPBUnitILPred );
  ROTRS( m_pcCurrDPBUnit      ->isCompleted(),  m_pcCurrDPBUnit );
  return 0;
}

Bool
DecodedPicBuffer::xIs2ndFieldOfCompFieldPair( const SliceHeader& rcSliceHeader )
{
  ROFRS( m_pcLastDPBUnit,                                                                   false );
  ROFRS( m_pcLastDPBUnit->isExisting      (),                                               false );
  ROFRS( rcSliceHeader.getFieldPicFlag    (),                                               false );
  ROTRS( rcSliceHeader.getIdrFlag         (),                                               false );
  ROTRS( rcSliceHeader.getDecRefPicMarking().hasMMCO5(),                                    false );
  ROFRS( rcSliceHeader.getPicType         ()  + m_pcLastDPBUnit->getPicStatus () == FRAME,  false );
  ROFRS( rcSliceHeader.getFrameNum        () == m_pcLastDPBUnit->getFrameNum  (),           false );
  ROFRS( rcSliceHeader.isRefPic           () == m_pcLastDPBUnit->isRefPicUnit (),           false );
  return true;
}

Bool
DecodedPicBuffer::xIs2ndFieldOfCompFieldPair( Bool bRefBasePic )
{
  DPBUnit*  pcLastDPBUnit = ( bRefBasePic ? m_pcLastDPBUnitRefBasePic : m_pcLastDPBUnit );
  ROFRS( pcLastDPBUnit,                                                               false );
  ROFRS( pcLastDPBUnit->isExisting  (),                                               false );
  ROTRS( pcLastDPBUnit->getPicStatus() == FRAME,                                      false );
  ROFRS( pcLastDPBUnit->getPicStatus() +  m_pcCurrDPBUnit->getPicStatus () == FRAME,  false );
  ROFRS( pcLastDPBUnit->getFrameNum () == m_pcCurrDPBUnit->getFrameNum  (),           false );
  ROFRS( pcLastDPBUnit->isRefPicUnit() == m_pcCurrDPBUnit->isRefPicUnit (),           false );
  return true;
}

ErrVal
DecodedPicBuffer::xInsertNonExistingFrame( const SliceHeader* pcSliceHeader, UInt uiFrameNum )
{
  //===== determine POC =====
  Int iTopFieldPoc = ( pcSliceHeader ? pcSliceHeader->getPoc( TOP_FIELD ) : MSYS_INT_MIN );
  Int iBotFieldPoc = ( pcSliceHeader ? pcSliceHeader->getPoc( BOT_FIELD ) : MSYS_INT_MIN );
  //===== insert new non-existing frame unit =====
  ROT( m_cFreeDPBUnitList.empty() );
  DPBUnit* pcDPBUnit = m_cFreeDPBUnitList.popFront();
  RNOK(    pcDPBUnit->setNonExisting( uiFrameNum, iTopFieldPoc, iBotFieldPoc ) );
  m_cUsedDPBUnitList.push_back( pcDPBUnit );
  return Err::m_nOK;
}

ErrVal
DecodedPicBuffer::xInsertCurrentInNewBuffer( DPBUnit*& rpcStoredDPBUnit, Bool bRefBasePic )
{
  ROF ( m_uiMaxNumRefFrames > ( bRefBasePic ? 1U : 0U ) );
  ROF ( m_pcCurrDPBUnit->isCompleted() );
  ROT ( m_cFreeDPBUnitList.empty() );
  ROF(( rpcStoredDPBUnit = m_cFreeDPBUnitList.popFront() ));
  RNOK( m_pcCurrDPBUnit->store( *rpcStoredDPBUnit, bRefBasePic ) );
  m_cUsedDPBUnitList.push_back(  rpcStoredDPBUnit );
  if( ! bRefBasePic && m_pcCurrDPBUnit->isRefPicUnit() )
  {
    m_uiLastRefFrameNum = m_pcCurrDPBUnit->getFrameNum();
  }
  return Err::m_nOK;
}

ErrVal
DecodedPicBuffer::xCheckGapsInFrameNum( const SliceHeader& rcSliceHeader, PocCalculator& rcPocCalculator, PicBufferList& rcOutputList, PicBufferList& rcUnusedList )
{
  ROTRS( xIs2ndFieldOfCompFieldPair ( rcSliceHeader ),                                        Err::m_nOK );
  ROTRS( rcSliceHeader.getIdrFlag   (),                                                       Err::m_nOK );
  ROTRS( rcSliceHeader.getFrameNum  () == ( ( m_uiLastRefFrameNum + 1 ) % m_uiMaxFrameNum ),  Err::m_nOK );

  SliceHeader*  pcNonExSliceHeader  = 0; 
  UInt          uiCurrFrameNum      = rcSliceHeader.getFrameNum();
  UInt          uiMissingFrames     = uiCurrFrameNum - m_uiLastRefFrameNum - 1 + ( uiCurrFrameNum <= m_uiLastRefFrameNum ? m_uiMaxFrameNum : 0 );
  if( !rcSliceHeader.getSPS().getGapsInFrameNumValueAllowedFlag() )
  {
    fprintf( stderr, "\nLOST FRAMES = %d\n", uiMissingFrames );
    RERR();
  }
  if( rcSliceHeader.getSPS().getPicOrderCntType() )
  {
    ROF(( pcNonExSliceHeader = new SliceHeader( rcSliceHeader ) ));
    pcNonExSliceHeader->setNalRefIdc          ( NAL_REF_IDC_PRIORITY_HIGH );
    pcNonExSliceHeader->setNalUnitType        ( NAL_UNIT_CODED_SLICE );
    pcNonExSliceHeader->setIdrFlag            ( false );
    pcNonExSliceHeader->setFieldPicFlag       ( false );
    pcNonExSliceHeader->setBottomFieldFlag    ( false );
    pcNonExSliceHeader->setDeltaPicOrderCnt0  ( 0 );
    pcNonExSliceHeader->setDeltaPicOrderCnt1  ( 0 );
  }
  while( uiMissingFrames-- )
  {
    UInt  uiFrameNum    = ( m_uiLastRefFrameNum + 1 ) % m_uiMaxFrameNum;
    m_uiLastRefFrameNum = uiFrameNum;
    if( pcNonExSliceHeader )
    {
      pcNonExSliceHeader  ->setFrameNum ( uiFrameNum );
      RNOK( rcPocCalculator.calculatePoc( *pcNonExSliceHeader ) );
    }
    RNOK( xSlidingWindow          ( uiFrameNum ) );
    RNOK( xInsertNonExistingFrame ( pcNonExSliceHeader, uiFrameNum   ) );
    RNOK( xBumpingOutput          ( rcOutputList,       rcUnusedList ) );
    RNOK( xCheckBufferStatus      () );
  }
  m_pcLastDPBUnit           = 0;
  m_pcLastDPBUnitRefBasePic = 0;
  ROF( ( ( m_uiLastRefFrameNum + 1 ) % m_uiMaxFrameNum ) == uiCurrFrameNum );
  return Err::m_nOK;
}

ErrVal
DecodedPicBuffer::xUpdateAndStoreCurrentPic( PocCalculator& rcPocCalculator, PicBufferList& rcOutputList, PicBufferList& rcUnusedList )
{
  ROF( m_bInitDone && m_bInitBufferDone );
  ROF( m_pcCurrDPBUnit->isCompleted() );

  SliceHeader* pcSliceHeader = m_pcCurrDPBUnit->getSliceHeader();
  ROF( pcSliceHeader );
  ROF( pcSliceHeader->isRefPic      () == m_pcCurrDPBUnit->isRefPicUnit       () );
  ROF( pcSliceHeader->getOutputFlag () == m_pcCurrDPBUnit->isWaitingForOutput () );
  ROF( pcSliceHeader->getFrameNum   () == m_pcCurrDPBUnit->getFrameNum        () );

  UInt  uiCurrFrameNum    = pcSliceHeader->getFrameNum  ();
  Bool  bIsIDR            = pcSliceHeader->getIdrFlag   ();
  Bool  bIsRefPic         = pcSliceHeader->isRefPic     ();
  Bool  bIsOutput         = pcSliceHeader->getOutputFlag(); 
  Bool  bIs2ndFld         = xIs2ndFieldOfCompFieldPair  ();
  Bool  bIs2ndFldBase     = xIs2ndFieldOfCompFieldPair  ( true );
  Bool  bStoredAsLongTerm = false;

  //===== possible output of single non-reference field that might occupy an extra DPB unit (for output of complementary field pairs) =====
  if( ! bIs2ndFld )
  {
    RNOK  ( xBumpingOutput    ( rcOutputList, rcUnusedList ) ); 
    RNOK  ( xCheckBufferStatus() );
  }

  //===== non-reference/non-output picture =====
  if( ! bIsRefPic && ! bIsOutput )
  {
    RNOK  ( m_pcCurrDPBUnit->uninit () );
    RNOK  ( xCheckBufferStatus      () );
    RNOK  ( xDumpDPB                ( "after update (non-output and non-ref pic)" ) );
    m_pcLastDPBUnit           = 0;
    m_pcLastDPBUnitRefBasePic = 0;
    return Err::m_nOK;
  }

  //===== 2nd field of non-reference/output complementary field pair =====
  if( ! bIsRefPic && bIs2ndFld )
  {
    ROT   ( m_pcLastDPBUnitRefBasePic );
    RNOK  ( m_pcCurrDPBUnit->store  ( *m_pcLastDPBUnit ) );
    RNOK  ( m_pcCurrDPBUnit->uninit () );
    RNOK  ( xBumpingOutput          ( rcOutputList, rcUnusedList ) );
    RNOK  ( xCheckBufferStatus      () );
    RNOK  ( xDumpDPB                ( "after update (non-ref 2nd field)" ) );
    return Err::m_nOK;
  }
  
  //===== non-reference/output frame/field (not 2nd field of a complementary field pair) =====
  if( ! bIsRefPic )
  {
    RNOK  ( xInsertCurrentInNewBuffer     ( m_pcLastDPBUnit ) );
    RNOK  ( m_pcCurrDPBUnit->uninit       () );
    if( ! pcSliceHeader->getFieldPicFlag  () )
    {
      RNOK( xBumpingOutput                ( rcOutputList, rcUnusedList ) );
      RNOK( xCheckBufferStatus            () );
      RNOK( xDumpDPB                      ( "after update (non-ref frame)" ) );
    }
    else
    {
      RNOK( xDumpDPB                      ( "after update (non-ref 1st field)" ) );
    }
    m_pcLastDPBUnitRefBasePic = 0;
    return  Err::m_nOK;
  }

  //===== IDR picture =====
  if( bIsIDR )
  {
    ROF   ( m_cUsedDPBUnitList.empty() ); // has been cleaned in initCurrDPBUnit()
    ROT   ( m_pcLastDPBUnit );
    ROT   ( m_pcLastDPBUnitRefBasePic );
    if( pcSliceHeader->getLongTermReferenceFlag() )
    {
      m_iMaxLongTermFrameIdx = 0;
      RNOK( m_pcCurrDPBUnit->markLongTerm ( pcSliceHeader->getPicType(), m_iMaxLongTermFrameIdx ) );
    }
    RNOK  ( xInsertCurrentInNewBuffer     ( m_pcLastDPBUnit ) );
    if( pcSliceHeader->getStoreRefBasePicFlag() )
    {
      RNOK( xInsertCurrentInNewBuffer     ( m_pcLastDPBUnitRefBasePic, true ) );
    }
    RNOK  ( m_pcCurrDPBUnit->uninit       () );
    RNOK  ( xCheckBufferStatus            () );
    RNOK  ( xDumpDPB                      ( "after update (IDR pic)" ) );
    return  Err::m_nOK;
  }

  //===== non-IDR reference pictures =====
  //----- MMCO for reference base pictures -----
  if( pcSliceHeader->getDecRefBasePicMarking().getAdaptiveRefPicMarkingModeFlag() )
  {
    RNOK( xMMCO( rcPocCalculator, *pcSliceHeader, bStoredAsLongTerm, true ) );
    ROT ( bStoredAsLongTerm );
  }
  //----- memory management for decoded picture -----
  if( pcSliceHeader->getDecRefPicMarking().getAdaptiveRefPicMarkingModeFlag() )
  {
    RNOK( xMMCO( rcPocCalculator, *pcSliceHeader, bStoredAsLongTerm ) );
  }
  else if( ! bIs2ndFld )
  {
    RNOK( xSlidingWindow( uiCurrFrameNum ) );
  }
  //----- store pictures -----
  if( ! bStoredAsLongTerm )
  {
    if( bIs2ndFld )
    {
      RNOK( m_pcCurrDPBUnit->store    ( *m_pcLastDPBUnit ) );
    }
    else
    {
      RNOK( xInsertCurrentInNewBuffer (  m_pcLastDPBUnit ) );
    }
    if( pcSliceHeader->getStoreRefBasePicFlag() )
    {
      if( bIs2ndFldBase )
      {
        RNOK( m_pcCurrDPBUnit->store    ( *m_pcLastDPBUnitRefBasePic, true ) );
      }
      else
      {
        RNOK( xSlidingWindow            (  uiCurrFrameNum ) );
        RNOK( xInsertCurrentInNewBuffer (  m_pcLastDPBUnitRefBasePic, true ) );
      }
    }
    else
    {
      m_pcLastDPBUnitRefBasePic = 0;
    }
  }
  //----- uninit, output, check ----
  RNOK( m_pcCurrDPBUnit->uninit () );
  RNOK( xBumpingOutput          ( rcOutputList, rcUnusedList ) );
  RNOK( xCheckBufferStatus      () );
  RNOK( xDumpDPB                ( "after update (non-IDR ref pic)" ) );
  return Err::m_nOK;
}

ErrVal
DecodedPicBuffer::xCheckBufferStatus()
{
  ROF( m_bInitDone && m_bInitBufferDone );
  UInt                  uiNumNonRequired    = 0;
  UInt                  uiNumRequiredRef    = 0;
  UInt                  uiNumRequiredNonRef = 0;
  DPBUnitList::iterator iter                = m_cUsedDPBUnitList.begin();
  DPBUnitList::iterator end                 = m_cUsedDPBUnitList.end  ();
  for( ; iter != end; iter++ )
  {
    RNOK( (*iter)->checkStatus( m_iMaxLongTermFrameIdx ) );
    if( ! (*iter)->isRequired () )
    {
      uiNumNonRequired++;
    }
    else if( (*iter)->isUsedForRef() )
    {
      uiNumRequiredRef++;
    }
    else
    {
      uiNumRequiredNonRef++;
    }
  }
  ROT( uiNumNonRequired );
  ROF( uiNumRequiredRef                       <= m_uiMaxNumRefFrames );
  ROF( uiNumRequiredRef + uiNumRequiredNonRef <= m_uiDPBSizeInFrames );
  return Err::m_nOK;
}

ErrVal
DecodedPicBuffer::xBumpingOutput( PicBufferList& rcOutputList, PicBufferList& rcUnusedList, Bool bOutputAll )
{
  ROF( m_bInitDone && m_bInitBufferDone );
  //===== determine number of required and non-required picture and determine DPB unit with minimum POC =====
  DPBUnitList           cSortedByPocList;
  DPBUnitList           cNonRequiredList;
  UInt                  uiNumRequiredRef    = 0;
  UInt                  uiNumRequiredNonRef = 0;
  DPBUnitList::iterator iter                = m_cUsedDPBUnitList.begin();
  DPBUnitList::iterator end                 = m_cUsedDPBUnitList.end  ();
  for( ; iter != end; iter++ )
  {
    if( ! (*iter)->isRequired() )
    {
      cNonRequiredList.push_back( *iter );
    }
    else
    {
      if( (*iter)->isUsedForRef() )
      {
        uiNumRequiredRef++;
      }
      else
      {
        uiNumRequiredNonRef++;
      }
      if( (*iter)->isWaitingForOutput() )
      {
        //----- insert in POC sorted list -----
        DPBUnitList::iterator iterPocList = cSortedByPocList.begin();
        DPBUnitList::iterator endPocList  = cSortedByPocList.end  ();
        for( ; iterPocList != endPocList && (*iterPocList)->getPoc() < (*iter)->getPoc(); iterPocList++ );
        cSortedByPocList.insert( iterPocList, *iter );
      }
    }
  }
  ROT( uiNumRequiredRef  > m_uiDPBSizeInFrames );
  ROT( uiNumRequiredRef && bOutputAll );
  //===== output non-reference unit with minimum POC when required =====
  while( uiNumRequiredRef + uiNumRequiredNonRef > m_uiDPBSizeInFrames || ( bOutputAll && uiNumRequiredNonRef ) )
  {
    DPBUnit* pcDPBUnitToOutput = cSortedByPocList.popFront();
    ROF ( pcDPBUnitToOutput );
    RNOK( pcDPBUnitToOutput->output( m_cPicBufferList, rcOutputList, rcUnusedList ) );
    if( ! pcDPBUnitToOutput->isUsedForRef() )    
    {
      cNonRequiredList.push_back( pcDPBUnitToOutput );
      uiNumRequiredNonRef--;
    }
  }
  //===== clean-up used DPB unit list =====
  while( cNonRequiredList.size() )
  {
    DPBUnit* pcDPBUnit = cNonRequiredList.popFront();
    ROF ( pcDPBUnit );
    RNOK( pcDPBUnit->uninit() );
    m_cUsedDPBUnitList.remove   ( pcDPBUnit );
    m_cFreeDPBUnitList.push_back( pcDPBUnit );
  }
  ROF( ! bOutputAll || m_cUsedDPBUnitList.empty() );
  return Err::m_nOK;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?