Ticket #671: precompress_slice_r4392.patch

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

     
    537537  {
    538538    printf( "\nMultiple QP optimization is not allowed when rate control is enabled." );
    539539    assert(0);
     540    return;
    540541  }
    541542
    542543  TComSlice* pcSlice        = pcPic->getSlice(getSliceIdx());
     544
     545  if (pcSlice->getDependentSliceSegmentFlag())
     546  {
     547    // if this is a dependent slice segment, then it was optimised
     548    // when analysing the entire slice.
     549    return;
     550  }
     551
     552  if (pcSlice->getSliceMode()==FIXED_NUMBER_OF_BYTES)
     553  {
     554    // TODO: investigate use of average cost per CTU so that this Slice Mode can be used.
     555    printf( "\nUnable to optimise Slice-level QP if Slice Mode is set to FIXED_NUMBER_OF_BYTES\n" );
     556    assert(0);
     557    return;
     558  }
     559
    543560  Double     dPicRdCostBest = MAX_DOUBLE;
    544561  UInt       uiQpIdxBest = 0;
    545562
     
    561578  }
    562579  m_pcRdCost      ->setFrameLambda(dFrameLambda);
    563580
    564   const UInt initialSliceQp=pcSlice->getSliceQp();
    565581  // for each QP candidate
    566582  for ( UInt uiQpIdx = 0; uiQpIdx < 2 * m_pcCfg->getDeltaQpRD() + 1; uiQpIdx++ )
    567583  {
     
    572588    setUpLambda(pcSlice, m_pdRdPicLambda[uiQpIdx], m_piRdPicQp    [uiQpIdx]);
    573589
    574590    // try compress
    575     compressSlice   ( pcPic );
     591    compressSlice   ( pcPic, true );
     592
     593    UInt64 uiPicDist        = m_uiPicDist; // Distortion, as calculated by compressSlice.
     594    // NOTE: This distortion is the chroma-weighted SSE distortion for the slice.
     595    //       Previously a standard SSE distortion was calculated (for the entire frame).
     596    //       Which is correct?
    576597
    577     Double dPicRdCost;
    578     UInt64 uiPicDist        = m_uiPicDist;
    579     // TODO: will this work if multiple slices are being used? There may not be any reconstruction data yet.
    580     //       Will this also be ideal if a byte-restriction is placed on the slice?
    581     //         - what if the last CTU was sometimes included, sometimes not, and that had all the distortion?
    582     m_pcGOPEncoder->preLoopFilterPicAll( pcPic, uiPicDist );
     598    // TODO: Update loop filter, SAO and distortion calculation to work on one slice only.
     599    // m_pcGOPEncoder->preLoopFilterPicAll( pcPic, uiPicDist );
    583600
    584601    // compute RD cost and choose the best
    585     dPicRdCost = m_pcRdCost->calcRdCost64( m_uiPicTotalBits, uiPicDist, true, DF_SSE_FRAME);
     602    Double dPicRdCost = m_pcRdCost->calcRdCost64( m_uiPicTotalBits, uiPicDist, true, DF_SSE_FRAME); // NOTE: Is the 'true' parameter really necessary?
    586603
    587604    if ( dPicRdCost < dPicRdCostBest )
    588605    {
     
    591608    }
    592609  }
    593610
    594   if (pcSlice->getDependentSliceSegmentFlag() && initialSliceQp!=m_piRdPicQp[uiQpIdxBest] )
    595   {
    596     // TODO: this won't work with dependent slices: they do not have their own QP.
    597     fprintf(stderr,"ERROR - attempt to change QP for a dependent slice-segment, having already coded the slice\n");
    598     assert(pcSlice->getDependentSliceSegmentFlag()==false || initialSliceQp==m_piRdPicQp[uiQpIdxBest]);
    599   }
    600611  // set best values
    601612  pcSlice       ->setSliceQp             ( m_piRdPicQp    [uiQpIdxBest] );
    602613#if ADAPTIVE_QP_SELECTION
     
    605616  setUpLambda(pcSlice, m_pdRdPicLambda[uiQpIdxBest], m_piRdPicQp    [uiQpIdxBest]);
    606617}
    607618
    608 Void TEncSlice::calCostSliceI(TComPic* pcPic)
     619Void TEncSlice::calCostSliceI(TComPic* pcPic) // TODO: this only analyses the first slice segment. What about the others?
    609620{
    610621  Double            iSumHadSlice      = 0;
    611622  TComSlice * const pcSlice           = pcPic->getSlice(getSliceIdx());
     
    640651
    641652/** \param pcPic   picture class
    642653 */
    643 Void TEncSlice::compressSlice( TComPic* pcPic )
     654Void TEncSlice::compressSlice( TComPic* pcPic, const Bool bCompressEntireSlice )
    644655{
     656  // if bCompressEntireSlice is true, then the entire slice (not slice segment) is compressed,
     657  //   effectively disabling the slice-segment-mode.
     658
    645659  UInt   startCtuTsAddr;
    646660  UInt   boundingCtuTsAddr;
    647661  TComSlice* const pcSlice            = pcPic->getSlice(getSliceIdx());
    648662  pcSlice->setSliceSegmentBits(0);
    649663  xDetermineStartAndBoundingCtuTsAddr ( startCtuTsAddr, boundingCtuTsAddr, pcPic );
     664  if (bCompressEntireSlice)
     665  {
     666    boundingCtuTsAddr = pcSlice->getSliceCurEndCtuTsAddr();
     667    pcSlice->setSliceSegmentCurEndCtuTsAddr(boundingCtuTsAddr);
     668  }
    650669
    651670  // initialize cost values - these are used by precompressSlice (they should be parameters).
    652671  m_uiPicTotalBits  = 0;
     
    695714  if( m_pcCfg->getUseAdaptQpSelect() && !(pcSlice->getDependentSliceSegmentFlag()))
    696715  {
    697716    // TODO: this won't work with dependent slices: they do not have their own QP. Check fix to mask clause execution with && !(pcSlice->getDependentSliceSegmentFlag())
    698     m_pcTrQuant->clearSliceARLCnt();
     717    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)
    699718    if(pcSlice->getSliceType()!=I_SLICE)
    700719    {
    701720      Int qpBase = pcSlice->getSliceQpBase();
     
    842861      pcSlice->setSliceCurEndCtuTsAddr(validEndOfSliceCtuTsAddr);
    843862      boundingCtuTsAddr=validEndOfSliceCtuTsAddr;
    844863    }
    845     else if(pcSlice->getSliceSegmentMode()==FIXED_NUMBER_OF_BYTES && pcSlice->getSliceSegmentBits()+numberOfWrittenBits > (pcSlice->getSliceSegmentArgument()<<3))
     864    else if((!bCompressEntireSlice) && pcSlice->getSliceSegmentMode()==FIXED_NUMBER_OF_BYTES && pcSlice->getSliceSegmentBits()+numberOfWrittenBits > (pcSlice->getSliceSegmentArgument()<<3))
    846865    {
    847866      pcSlice->setSliceSegmentCurEndCtuTsAddr(validEndOfSliceCtuTsAddr);
    848867      boundingCtuTsAddr=validEndOfSliceCtuTsAddr;
     
    10891108#if ADAPTIVE_QP_SELECTION
    10901109  if( m_pcCfg->getUseAdaptQpSelect() )
    10911110  {
    1092     m_pcTrQuant->storeSliceQpNext(pcSlice);
     1111    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.
    10931112  }
    10941113#endif
    10951114
  • source/Lib/TLibEncoder/TEncSlice.h

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

     
    13551355    Int actualTotalBits      = 0;
    13561356    Int estimatedBits        = 0;
    13571357    Int tmpBitsBeforeWriting = 0;
    1358     if ( m_pcCfg->getUseRateCtrl() )
     1358    if ( m_pcCfg->getUseRateCtrl() ) // TODO: does this work with multiple slices and slice-segments?
    13591359    {
    13601360      Int frameLevel = m_pcRateCtrl->getRCSeq()->getGOPID2Level( iGOPid );
    13611361      if ( pcPic->getSlice(0)->getSliceType() == I_SLICE )
     
    13781378      }
    13791379      else if ( frameLevel == 0 )   // intra case, but use the model
    13801380      {
    1381         m_pcSliceEncoder->calCostSliceI(pcPic);
     1381        m_pcSliceEncoder->calCostSliceI(pcPic); // TODO: This only analyses the first slice segment - what about the others?
    13821382
    13831383        if ( m_pcCfg->getIntraPeriod() != 1 )   // do not refine allocated bits for all intra case
    13841384        {
     
    14261426      for(UInt nextCtuTsAddr = 0; nextCtuTsAddr < numberOfCtusInFrame; )
    14271427      {
    14281428        m_pcSliceEncoder->precompressSlice( pcPic );
    1429         m_pcSliceEncoder->compressSlice   ( pcPic );
     1429        m_pcSliceEncoder->compressSlice   ( pcPic, false );
    14301430
    14311431        const UInt curSliceSegmentEnd = pcSlice->getSliceSegmentCurEndCtuTsAddr();
    14321432        if (curSliceSegmentEnd < numberOfCtusInFrame)