Ticket #671: precompress_slice_r4154.patch

File precompress_slice_r4154.patch, 8.5 KB (added by karlsharman, 10 years ago)
  • source/Lib/TLibEncoder/TEncSlice.cpp

     
    535535  {
    536536    printf( "\nMultiple QP optimization is not allowed when rate control is enabled." );
    537537    assert(0);
     538    return;
    538539  }
    539540
    540541  TComSlice* pcSlice        = pcPic->getSlice(getSliceIdx());
     542
     543  if (pcSlice->getDependentSliceSegmentFlag())
     544  {
     545    // if this is a dependent slice segment, then it was optimised
     546    // when analysing the entire slice.
     547    return;
     548  }
     549
     550  if (pcSlice->getSliceMode()==FIXED_NUMBER_OF_BYTES)
     551  {
     552    // TODO: investigate use of average cost per CTU so that this Slice Mode can be used.
     553    printf( "\nUnable to optimise Slice-level QP if Slice Mode is set to FIXED_NUMBER_OF_BYTES\n" );
     554    assert(0);
     555    return;
     556  }
     557
    541558  Double     dPicRdCostBest = MAX_DOUBLE;
    542559  UInt       uiQpIdxBest = 0;
    543560
     
    559576  }
    560577  m_pcRdCost      ->setFrameLambda(dFrameLambda);
    561578
    562   const UInt initialSliceQp=pcSlice->getSliceQp();
    563579  // for each QP candidate
    564580  for ( UInt uiQpIdx = 0; uiQpIdx < 2 * m_pcCfg->getDeltaQpRD() + 1; uiQpIdx++ )
    565581  {
     
    570586    setUpLambda(pcSlice, m_pdRdPicLambda[uiQpIdx], m_piRdPicQp    [uiQpIdx]);
    571587
    572588    // try compress
    573     compressSlice   ( pcPic );
     589    compressSlice   ( pcPic, true );
     590
     591    UInt64 uiPicDist        = m_uiPicDist; // Distortion, as calculated by compressSlice.
     592    // NOTE: This distortion is the chroma-weighted SSE distortion for the slice.
     593    //       Previously a standard SSE distortion was calculated (for the entire frame).
     594    //       Which is correct?
    574595
    575     Double dPicRdCost;
    576     UInt64 uiPicDist        = m_uiPicDist;
    577     // TODO: will this work if multiple slices are being used? There may not be any reconstruction data yet.
    578     //       Will this also be ideal if a byte-restriction is placed on the slice?
    579     //         - what if the last CTU was sometimes included, sometimes not, and that had all the distortion?
    580     m_pcGOPEncoder->preLoopFilterPicAll( pcPic, uiPicDist );
     596    // TODO: Update loop filter, SAO and distortion calculation to work on one slice only.
     597    // m_pcGOPEncoder->preLoopFilterPicAll( pcPic, uiPicDist );
    581598
    582599    // compute RD cost and choose the best
    583     dPicRdCost = m_pcRdCost->calcRdCost64( m_uiPicTotalBits, uiPicDist, true, DF_SSE_FRAME);
     600    Double dPicRdCost = m_pcRdCost->calcRdCost64( m_uiPicTotalBits, uiPicDist, true, DF_SSE_FRAME); // NOTE: Is the 'true' parameter really necessary?
    584601
    585602    if ( dPicRdCost < dPicRdCostBest )
    586603    {
     
    589606    }
    590607  }
    591608
    592   if (pcSlice->getDependentSliceSegmentFlag() && initialSliceQp!=m_piRdPicQp[uiQpIdxBest] )
    593   {
    594     // TODO: this won't work with dependent slices: they do not have their own QP.
    595     fprintf(stderr,"ERROR - attempt to change QP for a dependent slice-segment, having already coded the slice\n");
    596     assert(pcSlice->getDependentSliceSegmentFlag()==false || initialSliceQp==m_piRdPicQp[uiQpIdxBest]);
    597   }
    598609  // set best values
    599610  pcSlice       ->setSliceQp             ( m_piRdPicQp    [uiQpIdxBest] );
    600611#if ADAPTIVE_QP_SELECTION
     
    603614  setUpLambda(pcSlice, m_pdRdPicLambda[uiQpIdxBest], m_piRdPicQp    [uiQpIdxBest]);
    604615}
    605616
    606 Void TEncSlice::calCostSliceI(TComPic* pcPic)
     617Void TEncSlice::calCostSliceI(TComPic* pcPic) // TODO: this only analyses the first slice segment. What about the others?
    607618{
    608619  UInt    ctuRsAddr;
    609620  UInt    startCtuTsAddr;
     
    637648
    638649/** \param rpcPic   picture class
    639650 */
    640 Void TEncSlice::compressSlice( TComPic* pcPic )
     651Void TEncSlice::compressSlice( TComPic* pcPic, const Bool bCompressEntireSlice )
    641652{
     653  // if bCompressEntireSlice is true, then the entire slice (not slice segment) is compressed,
     654  //   effectively disabling the slice-segment-mode.
     655 
    642656  UInt   startCtuTsAddr;
    643657  UInt   boundingCtuTsAddr;
    644658  TComSlice* pcSlice            = pcPic->getSlice(getSliceIdx());
    645659  pcSlice->setSliceSegmentBits(0);
    646660  xDetermineStartAndBoundingCtuTsAddr ( startCtuTsAddr, boundingCtuTsAddr, pcPic, false );
     661  if (bCompressEntireSlice)
     662  {
     663    boundingCtuTsAddr = pcSlice->getSliceCurEndCtuTsAddr();
     664    pcSlice->setSliceSegmentCurEndCtuTsAddr(boundingCtuTsAddr);
     665  }
    647666
    648667  // initialize cost values - these are used by precompressSlice (they should be parameters).
    649668  m_uiPicTotalBits  = 0;
     
    692711  if( m_pcCfg->getUseAdaptQpSelect() && !(pcSlice->getDependentSliceSegmentFlag()))
    693712  {
    694713    // TODO: this won't work with dependent slices: they do not have their own QP. Check fix to mask clause execution with && !(pcSlice->getDependentSliceSegmentFlag())
    695     m_pcTrQuant->clearSliceARLCnt();
     714    m_pcTrQuant->clearSliceARLCnt(); // TODO: this looks wrong for multiple slices - the results of all but the last slice will be cleared before they are used (all slices compressed, and then all slices encoded)
    696715    if(pcSlice->getSliceType()!=I_SLICE)
    697716    {
    698717      Int qpBase = pcSlice->getSliceQpBase();
     
    839858      pcSlice->setSliceCurEndCtuTsAddr(validEndOfSliceCtuTsAddr);
    840859      boundingCtuTsAddr=validEndOfSliceCtuTsAddr;
    841860    }
    842     else if(pcSlice->getSliceSegmentMode()==FIXED_NUMBER_OF_BYTES && pcSlice->getSliceSegmentBits()+numberOfWrittenBits > (pcSlice->getSliceSegmentArgument()<<3))
     861    else if((!bCompressEntireSlice) && pcSlice->getSliceSegmentMode()==FIXED_NUMBER_OF_BYTES && pcSlice->getSliceSegmentBits()+numberOfWrittenBits > (pcSlice->getSliceSegmentArgument()<<3))
    843862    {
    844863      pcSlice->setSliceSegmentCurEndCtuTsAddr(validEndOfSliceCtuTsAddr);
    845864      boundingCtuTsAddr=validEndOfSliceCtuTsAddr;
     
    10761095#if ADAPTIVE_QP_SELECTION
    10771096  if( m_pcCfg->getUseAdaptQpSelect() )
    10781097  {
    1079     m_pcTrQuant->storeSliceQpNext(pcSlice);
     1098    m_pcTrQuant->storeSliceQpNext(pcSlice); // TODO: this will only be storing the adaptive QP state of the very last slice-segment that is not dependent in the frame... Perhaps this should be moved to the compress slice loop.
    10801099  }
    10811100#endif
    10821101
  • source/Lib/TLibEncoder/TEncSlice.h

     
    114114                                Int iGOPid,   TComSlice*& rpcSlice, TComSPS* pSPS, TComPPS *pPPS, Bool isField );
    115115  Void    resetQP             ( TComPic* pic, Int sliceQP, Double lambda );
    116116  // compress and encode slice
    117   Void    precompressSlice    ( TComPic* pcPic                                     );      ///< precompress slice for multi-loop opt.
    118   Void    compressSlice       ( TComPic* pcPic                                     );      ///< analysis stage of slice
     117  Void    precompressSlice    ( TComPic* pcPic                                     );      ///< precompress slice for multi-loop slice-level QP opt.
     118  Void    compressSlice       ( TComPic* pcPic, const Bool bCompressEntireSlice    );      ///< analysis stage of slice
    119119  Void    calCostSliceI       ( TComPic* pcPic );
    120120  Void    encodeSlice         ( TComPic* pcPic, TComOutputBitstream* pcSubstreams, UInt &numBinsCoded );
    121121
  • source/Lib/TLibEncoder/TEncGOP.cpp

     
    10651065    Int actualTotalBits      = 0;
    10661066    Int estimatedBits        = 0;
    10671067    Int tmpBitsBeforeWriting = 0;
    1068     if ( m_pcCfg->getUseRateCtrl() )
     1068    if ( m_pcCfg->getUseRateCtrl() ) // TODO: does this work with multiple slices and slice-segments?
    10691069    {
    10701070      Int frameLevel = m_pcRateCtrl->getRCSeq()->getGOPID2Level( iGOPid );
    10711071      if ( pcPic->getSlice(0)->getSliceType() == I_SLICE )
     
    10881088      }
    10891089      else if ( frameLevel == 0 )   // intra case, but use the model
    10901090      {
    1091         m_pcSliceEncoder->calCostSliceI(pcPic);
     1091        m_pcSliceEncoder->calCostSliceI(pcPic); // TODO: This only analyses the first slice segment - what about the others?
    10921092
    10931093        if ( m_pcCfg->getIntraPeriod() != 1 )   // do not refine allocated bits for all intra case
    10941094        {
     
    11351135      for(UInt nextCtuTsAddr = 0; nextCtuTsAddr < numberOfCtusInFrame; )
    11361136      {
    11371137        m_pcSliceEncoder->precompressSlice( pcPic );
    1138         m_pcSliceEncoder->compressSlice   ( pcPic );
     1138        m_pcSliceEncoder->compressSlice   ( pcPic, false );
    11391139
    11401140        const UInt curSliceSegmentEnd = pcSlice->getSliceSegmentCurEndCtuTsAddr();
    11411141        if (curSliceSegmentEnd < numberOfCtusInFrame)