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
537 537 { 538 538 printf( "\nMultiple QP optimization is not allowed when rate control is enabled." ); 539 539 assert(0); 540 return; 540 541 } 541 542 542 543 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 543 560 Double dPicRdCostBest = MAX_DOUBLE; 544 561 UInt uiQpIdxBest = 0; 545 562 … … 561 578 } 562 579 m_pcRdCost ->setFrameLambda(dFrameLambda); 563 580 564 const UInt initialSliceQp=pcSlice->getSliceQp();565 581 // for each QP candidate 566 582 for ( UInt uiQpIdx = 0; uiQpIdx < 2 * m_pcCfg->getDeltaQpRD() + 1; uiQpIdx++ ) 567 583 { … … 572 588 setUpLambda(pcSlice, m_pdRdPicLambda[uiQpIdx], m_piRdPicQp [uiQpIdx]); 573 589 574 590 // 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? 576 597 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 ); 583 600 584 601 // 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? 586 603 587 604 if ( dPicRdCost < dPicRdCostBest ) 588 605 { … … 591 608 } 592 609 } 593 610 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 }600 611 // set best values 601 612 pcSlice ->setSliceQp ( m_piRdPicQp [uiQpIdxBest] ); 602 613 #if ADAPTIVE_QP_SELECTION … … 605 616 setUpLambda(pcSlice, m_pdRdPicLambda[uiQpIdxBest], m_piRdPicQp [uiQpIdxBest]); 606 617 } 607 618 608 Void TEncSlice::calCostSliceI(TComPic* pcPic) 619 Void TEncSlice::calCostSliceI(TComPic* pcPic) // TODO: this only analyses the first slice segment. What about the others? 609 620 { 610 621 Double iSumHadSlice = 0; 611 622 TComSlice * const pcSlice = pcPic->getSlice(getSliceIdx()); … … 640 651 641 652 /** \param pcPic picture class 642 653 */ 643 Void TEncSlice::compressSlice( TComPic* pcPic )654 Void TEncSlice::compressSlice( TComPic* pcPic, const Bool bCompressEntireSlice ) 644 655 { 656 // if bCompressEntireSlice is true, then the entire slice (not slice segment) is compressed, 657 // effectively disabling the slice-segment-mode. 658 645 659 UInt startCtuTsAddr; 646 660 UInt boundingCtuTsAddr; 647 661 TComSlice* const pcSlice = pcPic->getSlice(getSliceIdx()); 648 662 pcSlice->setSliceSegmentBits(0); 649 663 xDetermineStartAndBoundingCtuTsAddr ( startCtuTsAddr, boundingCtuTsAddr, pcPic ); 664 if (bCompressEntireSlice) 665 { 666 boundingCtuTsAddr = pcSlice->getSliceCurEndCtuTsAddr(); 667 pcSlice->setSliceSegmentCurEndCtuTsAddr(boundingCtuTsAddr); 668 } 650 669 651 670 // initialize cost values - these are used by precompressSlice (they should be parameters). 652 671 m_uiPicTotalBits = 0; … … 695 714 if( m_pcCfg->getUseAdaptQpSelect() && !(pcSlice->getDependentSliceSegmentFlag())) 696 715 { 697 716 // 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) 699 718 if(pcSlice->getSliceType()!=I_SLICE) 700 719 { 701 720 Int qpBase = pcSlice->getSliceQpBase(); … … 842 861 pcSlice->setSliceCurEndCtuTsAddr(validEndOfSliceCtuTsAddr); 843 862 boundingCtuTsAddr=validEndOfSliceCtuTsAddr; 844 863 } 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)) 846 865 { 847 866 pcSlice->setSliceSegmentCurEndCtuTsAddr(validEndOfSliceCtuTsAddr); 848 867 boundingCtuTsAddr=validEndOfSliceCtuTsAddr; … … 1089 1108 #if ADAPTIVE_QP_SELECTION 1090 1109 if( m_pcCfg->getUseAdaptQpSelect() ) 1091 1110 { 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. 1093 1112 } 1094 1113 #endif 1095 1114 -
source/Lib/TLibEncoder/TEncSlice.h
115 115 Int iGOPid, TComSlice*& rpcSlice, Bool isField ); 116 116 Void resetQP ( TComPic* pic, Int sliceQP, Double lambda ); 117 117 // compress and encode slice 118 Void precompressSlice ( TComPic* pcPic ); ///< precompress slice for multi-loop opt.119 Void compressSlice ( TComPic* pcPic 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 120 120 Void calCostSliceI ( TComPic* pcPic ); 121 121 Void encodeSlice ( TComPic* pcPic, TComOutputBitstream* pcSubstreams, UInt &numBinsCoded ); 122 122 -
source/Lib/TLibEncoder/TEncGOP.cpp
1355 1355 Int actualTotalBits = 0; 1356 1356 Int estimatedBits = 0; 1357 1357 Int tmpBitsBeforeWriting = 0; 1358 if ( m_pcCfg->getUseRateCtrl() ) 1358 if ( m_pcCfg->getUseRateCtrl() ) // TODO: does this work with multiple slices and slice-segments? 1359 1359 { 1360 1360 Int frameLevel = m_pcRateCtrl->getRCSeq()->getGOPID2Level( iGOPid ); 1361 1361 if ( pcPic->getSlice(0)->getSliceType() == I_SLICE ) … … 1378 1378 } 1379 1379 else if ( frameLevel == 0 ) // intra case, but use the model 1380 1380 { 1381 m_pcSliceEncoder->calCostSliceI(pcPic); 1381 m_pcSliceEncoder->calCostSliceI(pcPic); // TODO: This only analyses the first slice segment - what about the others? 1382 1382 1383 1383 if ( m_pcCfg->getIntraPeriod() != 1 ) // do not refine allocated bits for all intra case 1384 1384 { … … 1426 1426 for(UInt nextCtuTsAddr = 0; nextCtuTsAddr < numberOfCtusInFrame; ) 1427 1427 { 1428 1428 m_pcSliceEncoder->precompressSlice( pcPic ); 1429 m_pcSliceEncoder->compressSlice ( pcPic );1429 m_pcSliceEncoder->compressSlice ( pcPic, false ); 1430 1430 1431 1431 const UInt curSliceSegmentEnd = pcSlice->getSliceSegmentCurEndCtuTsAddr(); 1432 1432 if (curSliceSegmentEnd < numberOfCtusInFrame)