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
535 535 { 536 536 printf( "\nMultiple QP optimization is not allowed when rate control is enabled." ); 537 537 assert(0); 538 return; 538 539 } 539 540 540 541 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 541 558 Double dPicRdCostBest = MAX_DOUBLE; 542 559 UInt uiQpIdxBest = 0; 543 560 … … 559 576 } 560 577 m_pcRdCost ->setFrameLambda(dFrameLambda); 561 578 562 const UInt initialSliceQp=pcSlice->getSliceQp();563 579 // for each QP candidate 564 580 for ( UInt uiQpIdx = 0; uiQpIdx < 2 * m_pcCfg->getDeltaQpRD() + 1; uiQpIdx++ ) 565 581 { … … 570 586 setUpLambda(pcSlice, m_pdRdPicLambda[uiQpIdx], m_piRdPicQp [uiQpIdx]); 571 587 572 588 // 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? 574 595 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 ); 581 598 582 599 // 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? 584 601 585 602 if ( dPicRdCost < dPicRdCostBest ) 586 603 { … … 589 606 } 590 607 } 591 608 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 }598 609 // set best values 599 610 pcSlice ->setSliceQp ( m_piRdPicQp [uiQpIdxBest] ); 600 611 #if ADAPTIVE_QP_SELECTION … … 603 614 setUpLambda(pcSlice, m_pdRdPicLambda[uiQpIdxBest], m_piRdPicQp [uiQpIdxBest]); 604 615 } 605 616 606 Void TEncSlice::calCostSliceI(TComPic* pcPic) 617 Void TEncSlice::calCostSliceI(TComPic* pcPic) // TODO: this only analyses the first slice segment. What about the others? 607 618 { 608 619 UInt ctuRsAddr; 609 620 UInt startCtuTsAddr; … … 637 648 638 649 /** \param rpcPic picture class 639 650 */ 640 Void TEncSlice::compressSlice( TComPic* pcPic )651 Void TEncSlice::compressSlice( TComPic* pcPic, const Bool bCompressEntireSlice ) 641 652 { 653 // if bCompressEntireSlice is true, then the entire slice (not slice segment) is compressed, 654 // effectively disabling the slice-segment-mode. 655 642 656 UInt startCtuTsAddr; 643 657 UInt boundingCtuTsAddr; 644 658 TComSlice* pcSlice = pcPic->getSlice(getSliceIdx()); 645 659 pcSlice->setSliceSegmentBits(0); 646 660 xDetermineStartAndBoundingCtuTsAddr ( startCtuTsAddr, boundingCtuTsAddr, pcPic, false ); 661 if (bCompressEntireSlice) 662 { 663 boundingCtuTsAddr = pcSlice->getSliceCurEndCtuTsAddr(); 664 pcSlice->setSliceSegmentCurEndCtuTsAddr(boundingCtuTsAddr); 665 } 647 666 648 667 // initialize cost values - these are used by precompressSlice (they should be parameters). 649 668 m_uiPicTotalBits = 0; … … 692 711 if( m_pcCfg->getUseAdaptQpSelect() && !(pcSlice->getDependentSliceSegmentFlag())) 693 712 { 694 713 // 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) 696 715 if(pcSlice->getSliceType()!=I_SLICE) 697 716 { 698 717 Int qpBase = pcSlice->getSliceQpBase(); … … 839 858 pcSlice->setSliceCurEndCtuTsAddr(validEndOfSliceCtuTsAddr); 840 859 boundingCtuTsAddr=validEndOfSliceCtuTsAddr; 841 860 } 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)) 843 862 { 844 863 pcSlice->setSliceSegmentCurEndCtuTsAddr(validEndOfSliceCtuTsAddr); 845 864 boundingCtuTsAddr=validEndOfSliceCtuTsAddr; … … 1076 1095 #if ADAPTIVE_QP_SELECTION 1077 1096 if( m_pcCfg->getUseAdaptQpSelect() ) 1078 1097 { 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. 1080 1099 } 1081 1100 #endif 1082 1101 -
source/Lib/TLibEncoder/TEncSlice.h
114 114 Int iGOPid, TComSlice*& rpcSlice, TComSPS* pSPS, TComPPS *pPPS, Bool isField ); 115 115 Void resetQP ( TComPic* pic, Int sliceQP, Double lambda ); 116 116 // compress and encode slice 117 Void precompressSlice ( TComPic* pcPic ); ///< precompress slice for multi-loop opt.118 Void compressSlice ( TComPic* pcPic 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 119 119 Void calCostSliceI ( TComPic* pcPic ); 120 120 Void encodeSlice ( TComPic* pcPic, TComOutputBitstream* pcSubstreams, UInt &numBinsCoded ); 121 121 -
source/Lib/TLibEncoder/TEncGOP.cpp
1065 1065 Int actualTotalBits = 0; 1066 1066 Int estimatedBits = 0; 1067 1067 Int tmpBitsBeforeWriting = 0; 1068 if ( m_pcCfg->getUseRateCtrl() ) 1068 if ( m_pcCfg->getUseRateCtrl() ) // TODO: does this work with multiple slices and slice-segments? 1069 1069 { 1070 1070 Int frameLevel = m_pcRateCtrl->getRCSeq()->getGOPID2Level( iGOPid ); 1071 1071 if ( pcPic->getSlice(0)->getSliceType() == I_SLICE ) … … 1088 1088 } 1089 1089 else if ( frameLevel == 0 ) // intra case, but use the model 1090 1090 { 1091 m_pcSliceEncoder->calCostSliceI(pcPic); 1091 m_pcSliceEncoder->calCostSliceI(pcPic); // TODO: This only analyses the first slice segment - what about the others? 1092 1092 1093 1093 if ( m_pcCfg->getIntraPeriod() != 1 ) // do not refine allocated bits for all intra case 1094 1094 { … … 1135 1135 for(UInt nextCtuTsAddr = 0; nextCtuTsAddr < numberOfCtusInFrame; ) 1136 1136 { 1137 1137 m_pcSliceEncoder->precompressSlice( pcPic ); 1138 m_pcSliceEncoder->compressSlice ( pcPic );1138 m_pcSliceEncoder->compressSlice ( pcPic, false ); 1139 1139 1140 1140 const UInt curSliceSegmentEnd = pcSlice->getSliceSegmentCurEndCtuTsAddr(); 1141 1141 if (curSliceSegmentEnd < numberOfCtusInFrame)