Void TEncGOP::compressGOP和Void TEncGOP::printOutSummary

Void TEncGOP::compressGOP( Int iPOCLast, Int iNumPicRcvd, TComList<TComPic*>& rcListPic,  
                           TComList<TComPicYuv*>& rcListPicYuvRecOut, std::list<AccessUnit>& accessUnitsInGOP,  
                           Bool isField, Bool isTff, const InputColourSpaceConversion snr_conversion, const Bool printFrameMSE )  
{  
  // TODO: Split this function up.  
  
  TComPic*        pcPic = NULL;  
  TComPicYuv*     pcPicYuvRecOut;  
  TComSlice*      pcSlice;  
  TComOutputBitstream  *pcBitstreamRedirect;  
  pcBitstreamRedirect = new TComOutputBitstream;  
  AccessUnit::iterator  itLocationToPushSliceHeaderNALU; // used to store location where NALU containing slice header is to be inserted  
  
  xInitGOP( iPOCLast, iNumPicRcvd, isField );  
  
  m_iNumPicCoded = 0;  
  SEIMessages leadingSeiMessages;  
  SEIMessages nestedSeiMessages;  
  SEIMessages duInfoSeiMessages;  
  SEIMessages trailingSeiMessages;  
  std::deque<DUData> duData;  
  SEIDecodingUnitInfo decodingUnitInfoSEI;  
  
  EfficientFieldIRAPMapping effFieldIRAPMap;  
  if (m_pcCfg->getEfficientFieldIRAPEnabled())  
  {  
    effFieldIRAPMap.initialize(isField, m_iGopSize, iPOCLast, iNumPicRcvd, m_iLastIDR, this, m_pcCfg);  
  }  
  
  //重设flag指明图片是否已被编码 reset flag indicating whether pictures have been encoded  
  for ( Int iGOPid=0; iGOPid < m_iGopSize; iGOPid++ )  
  {  
    m_pcCfg->setEncodedFlag(iGOPid, false);  
  }  
  
  for ( Int iGOPid=0; iGOPid < m_iGopSize; iGOPid++ )  
  {  
    if (m_pcCfg->getEfficientFieldIRAPEnabled())  
    {  
      iGOPid=effFieldIRAPMap.adjustGOPid(iGOPid);  
    }  
  
    //每一个slice的用时-- For time output for each slice  
    clock_t iBeforeTime = clock();  
  
    UInt uiColDir = calculateCollocatedFromL1Flag(m_pcCfg, iGOPid, m_iGopSize); //计算参考图像(参考图像在前和在后两种情况)的QP?
  
    /////////////////////////////////////////////////////////////////////////////////////////////////// 初始化开始编码Initial to start encoding  
    Int iTimeOffset;  
    Int pocCurr;  
  
    if(iPOCLast == 0) //第一帧或者顶场的情况case first frame or first top field  
    {  
      pocCurr=0;  
      iTimeOffset = 1;  
    }  
    else if(iPOCLast == 1 && isField) //底场的情况,和第一帧一样,poc计算不正确,我们自行设置正确的值case first bottom field, just like the first frame, the poc computation is not right anymore, we set the right value  
    {  
      pocCurr = 1;  
      iTimeOffset = 1;  
    }  
    else  
    {  
      pocCurr = iPOCLast - iNumPicRcvd + m_pcCfg->getGOPEntry(iGOPid).m_POC - ((isField && m_iGopSize>1) ? 1:0);  
      iTimeOffset = m_pcCfg->getGOPEntry(iGOPid).m_POC;  
    }  
  
    if(pocCurr>=m_pcCfg->getFramesToBeEncoded())//获取待编码帧  
    {  
      if (m_pcCfg->getEfficientFieldIRAPEnabled())  
      {  
        iGOPid=effFieldIRAPMap.restoreGOPid(iGOPid);  
      }  
      continue;  
    }  
  
    if( getNalUnitType(pocCurr, m_iLastIDR, isField) == NAL_UNIT_CODED_SLICE_IDR_W_RADL || getNalUnitType(pocCurr, m_iLastIDR, isField) == NAL_UNIT_CODED_SLICE_IDR_N_LP )  
    {  
      m_iLastIDR = pocCurr;  
    }  
    // start a new access unit: create an entry in the list of output access units  
    accessUnitsInGOP.push_back(AccessUnit());  
    AccessUnit& accessUnit = accessUnitsInGOP.back();  
    xGetBuffer( rcListPic, rcListPicYuvRecOut, iNumPicRcvd, iTimeOffset, pcPic, pcPicYuvRecOut, pocCurr, isField );  
  
    //片数据初始化  Slice data initialization  
    pcPic->clearSliceBuffer();  
    pcPic->allocateNewSlice();  
    m_pcSliceEncoder->setSliceIdx(0);  
    pcPic->setCurrSliceIdx(0);  
  
    m_pcSliceEncoder->initEncSlice ( pcPic, iPOCLast, pocCurr, iGOPid, pcSlice, isField );  
  
    //设置帧或场的编码Set Frame/Field coding  
    pcSlice->getPic()->setField(isField);  
  
    pcSlice->setLastIDR(m_iLastIDR);  
    pcSlice->setSliceIdx(0);  
    //设置默认的片层标志和序列参数集的层标志一样 set default slice level flag to the same as SPS level flag  
    pcSlice->setLFCrossSliceBoundaryFlag(  pcSlice->getPPS()->getLoopFilterAcrossSlicesEnabledFlag()  );  
  
    if(pcSlice->getSliceType()==B_SLICE&&m_pcCfg->getGOPEntry(iGOPid).m_sliceType=='P')  
    {  
      pcSlice->setSliceType(P_SLICE);  
    }  
    if(pcSlice->getSliceType()==B_SLICE&&m_pcCfg->getGOPEntry(iGOPid).m_sliceType=='I')  
    {  
      pcSlice->setSliceType(I_SLICE);  
    }  
      
    // 设置NAL单元的类型 Set the nal unit type  
    pcSlice->setNalUnitType(getNalUnitType(pocCurr, m_iLastIDR, isField));  
    if(pcSlice->getTemporalLayerNonReferenceFlag())  
    {  
      if (pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_TRAIL_R &&  
          !(m_iGopSize == 1 && pcSlice->getSliceType() == I_SLICE))  
        // Add this condition to avoid POC issues with encoder_intra_main.cfg configuration (see #1127 in bug tracker)  
      {  
        pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_TRAIL_N);  
      }  
      if(pcSlice->getNalUnitType()==NAL_UNIT_CODED_SLICE_RADL_R)  
      {  
        pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_RADL_N);  
      }  
      if(pcSlice->getNalUnitType()==NAL_UNIT_CODED_SLICE_RASL_R)  
      {  
        pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_RASL_N);  
      }  
    }  
  
    if (m_pcCfg->getEfficientFieldIRAPEnabled())  
    {  
      if ( pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_LP  
        || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_RADL  
        || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_N_LP  
        || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL  
        || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP  
        || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA )  /*(随机接入点Intra Random Access Point) IRAP picture, 
                                                                    一种IRAP(intra random access point)帧,称为BLA(broken link access picture)帧, 
                                                                    这种帧一般用做两段序列之间的连接。功能类似IDR帧,但可能之后会跟随RASL帧。*/  
      {  
        m_associatedIRAPType = pcSlice->getNalUnitType();  
        m_associatedIRAPPOC = pocCurr;  
      }  
      pcSlice->setAssociatedIRAPType(m_associatedIRAPType);  
      pcSlice->setAssociatedIRAPPOC(m_associatedIRAPPOC);  
    }  
    // Do decoding refresh marking if any  
    pcSlice->decodingRefreshMarking(m_pocCRA, m_bRefreshPending, rcListPic, m_pcCfg->getEfficientFieldIRAPEnabled());  
    m_pcEncTop->selectReferencePictureSet(pcSlice, pocCurr, iGOPid);  
    if (!m_pcCfg->getEfficientFieldIRAPEnabled())  
    {  
      if ( pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_LP  
        || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_RADL  
        || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_N_LP  
        || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL  
        || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP  
        || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA )  // IRAP picture  
      {  
        m_associatedIRAPType = pcSlice->getNalUnitType();  
        m_associatedIRAPPOC = pocCurr;  
      }  
      pcSlice->setAssociatedIRAPType(m_associatedIRAPType);  
      pcSlice->setAssociatedIRAPPOC(m_associatedIRAPPOC);  
    }  
  
    if ((pcSlice->checkThatAllRefPicsAreAvailable(rcListPic, pcSlice->getRPS(), false, m_iLastRecoveryPicPOC, m_pcCfg->getDecodingRefreshType() == 3) != 0) || (pcSlice->isIRAP())   
      || (m_pcCfg->getEfficientFieldIRAPEnabled() && isField && pcSlice->getAssociatedIRAPType() >= NAL_UNIT_CODED_SLICE_BLA_W_LP && pcSlice->getAssociatedIRAPType() <= NAL_UNIT_CODED_SLICE_CRA && pcSlice->getAssociatedIRAPPOC() == pcSlice->getPOC()+1)  
      )  
    {  
      pcSlice->createExplicitReferencePictureSetFromReference(rcListPic, pcSlice->getRPS(), pcSlice->isIRAP(), m_iLastRecoveryPicPOC, m_pcCfg->getDecodingRefreshType() == 3, m_pcCfg->getEfficientFieldIRAPEnabled());  
    }  
  
    pcSlice->applyReferencePictureSet(rcListPic, pcSlice->getRPS());  
  
    if(pcSlice->getTLayer() > 0   
      &&  !( pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_RADL_N     // Check if not a leading picture  
          || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_RADL_R  
          || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_RASL_N  
          || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_RASL_R )  
        )  
    {  
      if(pcSlice->isTemporalLayerSwitchingPoint(rcListPic) || pcSlice->getSPS()->getTemporalIdNestingFlag())  
      {  
        if(pcSlice->getTemporalLayerNonReferenceFlag())  
        {  
          pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_TSA_N);  
        }  
        else  
        {  
          pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_TSA_R);  
        }  
      }  
      else if(pcSlice->isStepwiseTemporalLayerSwitchingPointCandidate(rcListPic))  
      {  
        Bool isSTSA=true;  
        for(Int ii=iGOPid+1;(ii<m_pcCfg->getGOPSize() && isSTSA==true);ii++)  
        {  
          Int lTid= m_pcCfg->getGOPEntry(ii).m_temporalId;  
          if(lTid==pcSlice->getTLayer())  
          {  
            const TComReferencePictureSet* nRPS = pcSlice->getSPS()->getRPSList()->getReferencePictureSet(ii);  
            for(Int jj=0;jj<nRPS->getNumberOfPictures();jj++)  
            {  
              if(nRPS->getUsed(jj))  
              {  
                Int tPoc=m_pcCfg->getGOPEntry(ii).m_POC+nRPS->getDeltaPOC(jj);  
                Int kk=0;  
                for(kk=0;kk<m_pcCfg->getGOPSize();kk++)  
                {  
                  if(m_pcCfg->getGOPEntry(kk).m_POC==tPoc)  
                  {  
                    break;  
                  }  
                }  
                Int tTid=m_pcCfg->getGOPEntry(kk).m_temporalId;  
                if(tTid >= pcSlice->getTLayer())  
                {  
                  isSTSA=false;  
                  break;  
                }  
              }  
            }  
          }  
        }  
        if(isSTSA==true)  
        {  
          if(pcSlice->getTemporalLayerNonReferenceFlag())  
          {  
            pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_STSA_N);  
          }  
          else  
          {  
            pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_STSA_R);  
          }  
        }  
      }  
    }  
    arrangeLongtermPicturesInRPS(pcSlice, rcListPic);  
    TComRefPicListModification* refPicListModification = pcSlice->getRefPicListModification();  
    refPicListModification->setRefPicListModificationFlagL0(0);  
    refPicListModification->setRefPicListModificationFlagL1(0);  
    pcSlice->setNumRefIdx(REF_PIC_LIST_0,min(m_pcCfg->getGOPEntry(iGOPid).m_numRefPicsActive,pcSlice->getRPS()->getNumberOfPictures()));  
    pcSlice->setNumRefIdx(REF_PIC_LIST_1,min(m_pcCfg->getGOPEntry(iGOPid).m_numRefPicsActive,pcSlice->getRPS()->getNumberOfPictures()));  
  
    //设置参考图像列表  Set reference list  
    pcSlice->setRefPicList ( rcListPic );  
  
    //片信息细化  Slice info. refinement  
    if ( (pcSlice->getSliceType() == B_SLICE) && (pcSlice->getNumRefIdx(REF_PIC_LIST_1) == 0) )  
    {  
      pcSlice->setSliceType ( P_SLICE );  
    }  
    pcSlice->setEncCABACTableIdx(m_pcSliceEncoder->getEncCABACTableIdx());  
  
    if (pcSlice->getSliceType() == B_SLICE)  
    {  
      pcSlice->setColFromL0Flag(1-uiColDir);  
      Bool bLowDelay = true;  
      Int  iCurrPOC  = pcSlice->getPOC();  
      Int iRefIdx = 0;  
  
      for (iRefIdx = 0; iRefIdx < pcSlice->getNumRefIdx(REF_PIC_LIST_0) && bLowDelay; iRefIdx++)  
      {  
        if ( pcSlice->getRefPic(REF_PIC_LIST_0, iRefIdx)->getPOC() > iCurrPOC )  
        {  
          bLowDelay = false;  
        }  
      }  
      for (iRefIdx = 0; iRefIdx < pcSlice->getNumRefIdx(REF_PIC_LIST_1) && bLowDelay; iRefIdx++)  
      {  
        if ( pcSlice->getRefPic(REF_PIC_LIST_1, iRefIdx)->getPOC() > iCurrPOC )  
        {  
          bLowDelay = false;  
        }  
      }  
  
      pcSlice->setCheckLDC(bLowDelay);  
    }  
    else  
    {  
      pcSlice->setCheckLDC(true);  
    }  
  
    uiColDir = 1-uiColDir;  
  
    //-------------------------------------------------------------  
    pcSlice->setRefPOCList();  
  
    pcSlice->setList1IdxToList0Idx();  
  
    if (m_pcEncTop->getTMVPModeId() == 2)  
    {  
      if (iGOPid == 0) // first picture in SOP (i.e. forward B)  
      {  
        pcSlice->setEnableTMVPFlag(0);  
      }  
      else  
      {  
        // Note: pcSlice->getColFromL0Flag() is assumed to be always 0 and getcolRefIdx() is always 0.  
        pcSlice->setEnableTMVPFlag(1);  
      }  
    }  
    else if (m_pcEncTop->getTMVPModeId() == 1)  
    {  
      pcSlice->setEnableTMVPFlag(1);  
    }  
    else  
    {  
      pcSlice->setEnableTMVPFlag(0);  
    }  
    ///////////////////////////////////////////////////////////////////////////////////////////////////对于片的压缩 Compress a slice  
    //  Slice compression 片内的压缩  
    if (m_pcCfg->getUseASR())  
    {  
      m_pcSliceEncoder->setSearchRange(pcSlice);  
    }  
  
    Bool bGPBcheck=false;  
    if ( pcSlice->getSliceType() == B_SLICE)  
    {  
      if ( pcSlice->getNumRefIdx(RefPicList( 0 ) ) == pcSlice->getNumRefIdx(RefPicList( 1 ) ) )  
      {  
        bGPBcheck=true;  
        Int i;  
        for ( i=0; i < pcSlice->getNumRefIdx(RefPicList( 1 ) ); i++ )  
        {  
          if ( pcSlice->getRefPOC(RefPicList(1), i) != pcSlice->getRefPOC(RefPicList(0), i) )  
          {  
            bGPBcheck=false;  
            break;  
          }  
        }  
      }  
    }  
    if(bGPBcheck)  
    {  
      pcSlice->setMvdL1ZeroFlag(true);  
    }  
    else  
    {  
      pcSlice->setMvdL1ZeroFlag(false);  
    }  
    pcPic->getSlice(pcSlice->getSliceIdx())->setMvdL1ZeroFlag(pcSlice->getMvdL1ZeroFlag());  
  
  
    Double lambda            = 0.0;  
    Int actualHeadBits       = 0;  
    Int actualTotalBits      = 0;  
    Int estimatedBits        = 0;  
    Int tmpBitsBeforeWriting = 0;
*********************如果码率控制*******************************************
    if ( m_pcCfg->getUseRateCtrl() ) // TODO: does this work with multiple slices and slice-segments?  
    {  
      Int frameLevel = m_pcRateCtrl->getRCSeq()->getGOPID2Level( iGOPid );  
      if ( pcPic->getSlice(0)->getSliceType() == I_SLICE )  
      {  
        frameLevel = 0;  
      }  
      m_pcRateCtrl->initRCPic( frameLevel );  
      estimatedBits = m_pcRateCtrl->getRCPic()->getTargetBits();  
  
      Int sliceQP = m_pcCfg->getInitialQP();  
      if ( ( pcSlice->getPOC() == 0 && m_pcCfg->getInitialQP() > 0 ) || ( frameLevel == 0 && m_pcCfg->getForceIntraQP() ) ) //指明QP QP is specified  
      {  
        Int    NumberBFrames = ( m_pcCfg->getGOPSize() - 1 );  
        Double dLambda_scale = 1.0 - Clip3( 0.0, 0.5, 0.05*(Double)NumberBFrames );  
        Double dQPFactor     = 0.57*dLambda_scale;  
        Int    SHIFT_QP      = 12;  
        Int    bitdepth_luma_qp_scale = 0;  
        Double qp_temp = (Double) sliceQP + bitdepth_luma_qp_scale - SHIFT_QP;  
        lambda = dQPFactor*pow( 2.0, qp_temp/3.0 );  
      }  
      else if ( frameLevel == 0 )   //帧内编码的情况 intra case, but use the model  
      {  
        m_pcSliceEncoder->calCostSliceI(pcPic); // TODO: This only analyses the first slice segment - what about the others?  
  
        if ( m_pcCfg->getIntraPeriod() != 1 )   //并不是改善所有的帧内编码分配bit do not refine allocated bits for all intra case  
        {  
          Int bits = m_pcRateCtrl->getRCSeq()->getLeftAverageBits();  
          bits = m_pcRateCtrl->getRCPic()->getRefineBitsForIntra( bits );  
          if ( bits < 200 )  
          {  
            bits = 200;  
          }//比特数小于200的话就等于200  
          m_pcRateCtrl->getRCPic()->setTargetBits( bits );  
        }  
  
        list<TEncRCPic*> listPreviousPicture = m_pcRateCtrl->getPicList();  
        m_pcRateCtrl->getRCPic()->getLCUInitTargetBits();  
        lambda  = m_pcRateCtrl->getRCPic()->estimatePicLambda( listPreviousPicture, pcSlice->getSliceType());  
        sliceQP = m_pcRateCtrl->getRCPic()->estimatePicQP( lambda, listPreviousPicture );  
      }  
      else    //通常的情况 normal case  
      {  
        list<TEncRCPic*> listPreviousPicture = m_pcRateCtrl->getPicList();  
        lambda  = m_pcRateCtrl->getRCPic()->estimatePicLambda( listPreviousPicture, pcSlice->getSliceType());  
        sliceQP = m_pcRateCtrl->getRCPic()->estimatePicQP( lambda, listPreviousPicture );  
      }  
  
      sliceQP = Clip3( -pcSlice->getSPS()->getQpBDOffset(CHANNEL_TYPE_LUMA), MAX_QP, sliceQP );  
      m_pcRateCtrl->getRCPic()->setPicEstQP( sliceQP );  
  
      m_pcSliceEncoder->resetQP( pcPic, sliceQP, lambda );  
    }  
**********************if结束,即码率控制结束****************************************************  
    
    UInt uiNumSliceSegments = 1;  
  
    // 安排编码器,现在tile的数量已知  Allocate some coders, now the number of tiles are known.  
    const Int numSubstreamsColumns = (pcSlice->getPPS()->getNumTileColumnsMinus1() + 1);  
    const Int numSubstreamRows     = pcSlice->getPPS()->getEntropyCodingSyncEnabledFlag() ? pcPic->getFrameHeightInCtus() : (pcSlice->getPPS()->getNumTileRowsMinus1() + 1);  
    const Int numSubstreams        = numSubstreamRows * numSubstreamsColumns;  
    std::vector<TComOutputBitstream> substreamsOut(numSubstreams);  
  
    // now compress (trial encode) the various slice segments (slices, and dependent slices)  
    {  
      const UInt numberOfCtusInFrame=pcPic->getPicSym()->getNumberOfCtusInFrame(); //一帧里面CTU的个数 
      pcSlice->setSliceCurStartCtuTsAddr( 0 );  
      pcSlice->setSliceSegmentCurStartCtuTsAddr( 0 );  
****************************循环编码一帧里每个CTU**************************************************************************  
      for(UInt nextCtuTsAddr = 0; nextCtuTsAddr < numberOfCtusInFrame; )  
      {  
 
        m_pcSliceEncoder->precompressSlice( pcPic );////////////
        m_pcSliceEncoder->compressSlice   ( pcPic, false, false );/////////////
  
        const UInt curSliceSegmentEnd = pcSlice->getSliceSegmentCurEndCtuTsAddr();  
        if (curSliceSegmentEnd < numberOfCtusInFrame)  
        {  
          const Bool bNextSegmentIsDependentSlice=curSliceSegmentEnd<pcSlice->getSliceCurEndCtuTsAddr();  
          const UInt sliceBits=pcSlice->getSliceBits();  
          pcPic->allocateNewSlice();  
          //准备下一层 prepare for next slice  
          pcPic->setCurrSliceIdx                    ( uiNumSliceSegments );  
          m_pcSliceEncoder->setSliceIdx             ( uiNumSliceSegments   );  
          pcSlice = pcPic->getSlice                 ( uiNumSliceSegments   );  
          assert(pcSlice->getPPS()!=0);  
          pcSlice->copySliceInfo                    ( pcPic->getSlice(uiNumSliceSegments-1)  );  
          pcSlice->setSliceIdx                      ( uiNumSliceSegments   );  
          if (bNextSegmentIsDependentSlice)  
          {  
            pcSlice->setSliceBits(sliceBits);  
          }  
          else  
          {  
            pcSlice->setSliceCurStartCtuTsAddr      ( curSliceSegmentEnd );  
            pcSlice->setSliceBits(0);  
          }  
          pcSlice->setDependentSliceSegmentFlag(bNextSegmentIsDependentSlice);  
          pcSlice->setSliceSegmentCurStartCtuTsAddr ( curSliceSegmentEnd );  
          // TODO: optimise cabac_init during compress slice to improve multi-slice operation  
          // pcSlice->setEncCABACTableIdx(m_pcSliceEncoder->getEncCABACTableIdx());  
          uiNumSliceSegments ++;  
        }  
        nextCtuTsAddr = curSliceSegmentEnd;  
      }  
    }  
*******************************一帧所有的CTU都编码结束后开始SAO和loop filter***************************************************************  
    duData.clear();  
    pcSlice = pcPic->getSlice(0);  
  
    //自适应样点补偿参数估计利用的是 SAO parameter estimation using non-deblocked pixels for CTU bottom and right boundary areas  
    if( pcSlice->getSPS()->getUseSAO() && m_pcCfg->getSaoCtuBoundary() )//获取ctu边界  
    {  
      m_pcSAO->getPreDBFStatistics(pcPic);  
    }  
  
    //-- Loop filter环路滤波器  
    Bool bLFCrossTileBoundary = pcSlice->getPPS()->getLoopFilterAcrossTilesEnabledFlag();  
    m_pcLoopFilter->setCfg(bLFCrossTileBoundary);  
    if ( m_pcCfg->getDeblockingFilterMetric() )  
    {  
      applyDeblockingFilterMetric(pcPic, uiNumSliceSegments);  
    }  
    m_pcLoopFilter->loopFilterPic( pcPic );  
  
    /////////////////////////////////////////////////////////////////////////////////////////////////// File writing输出文件  
    // Set entropy coder设置熵编码器  
    m_pcEntropyCoder->setEntropyCoder   ( m_pcCavlcCoder );  
  
    if ( m_bSeqFirst )  
    {  
      // write various parameter sets写参数集  
      actualTotalBits += xWriteParameterSets(accessUnit, pcSlice);  
  
      // create prefix SEI messages at the beginning of the sequence  
      assert(leadingSeiMessages.empty());  
      xCreateIRAPLeadingSEIMessages(leadingSeiMessages, pcSlice->getSPS(), pcSlice->getPPS());  
  
      m_bSeqFirst = false;  
    }  
  
    // reset presence of BP SEI indication  
    m_bufferingPeriodSEIPresentInAU = false;  
    // create prefix SEI associated with a picture  
    xCreatePerPictureSEIMessages(iGOPid, leadingSeiMessages, nestedSeiMessages, pcSlice);  
  
    /* use the main bitstream buffer for storing the marshalled picture */  
    m_pcEntropyCoder->setBitstream(NULL);  
  
    pcSlice = pcPic->getSlice(0);  
  
    if (pcSlice->getSPS()->getUseSAO())  
    {  
      Bool sliceEnabled[MAX_NUM_COMPONENT];  
      TComBitCounter tempBitCounter;  
      tempBitCounter.resetBits();  
      m_pcEncTop->getRDGoOnSbacCoder()->setBitstream(&tempBitCounter);  
      m_pcSAO->initRDOCabacCoder(m_pcEncTop->getRDGoOnSbacCoder(), pcSlice);  
      m_pcSAO->SAOProcess(pcPic, sliceEnabled, pcPic->getSlice(0)->getLambdas(), m_pcCfg->getTestSAODisableAtPictureLevel(), m_pcCfg->getSaoEncodingRate(), m_pcCfg->getSaoEncodingRateChroma(), m_pcCfg->getSaoCtuBoundary());  
      m_pcSAO->PCMLFDisableProcess(pcPic);  
      m_pcEncTop->getRDGoOnSbacCoder()->setBitstream(NULL);  
  
      //assign SAO slice header  
      for(Int s=0; s< uiNumSliceSegments; s++)  
      {  
        pcPic->getSlice(s)->setSaoEnabledFlag(CHANNEL_TYPE_LUMA, sliceEnabled[COMPONENT_Y]);  
        assert(sliceEnabled[COMPONENT_Cb] == sliceEnabled[COMPONENT_Cr]);  
        pcPic->getSlice(s)->setSaoEnabledFlag(CHANNEL_TYPE_CHROMA, sliceEnabled[COMPONENT_Cb]);  
      }  
    }  
  
    // pcSlice is currently slice 0.  
    std::size_t binCountsInNalUnits   = 0; // For implementation of cabac_zero_word stuffing (section 7.4.3.10)  
    std::size_t numBytesInVclNalUnits = 0; // For implementation of cabac_zero_word stuffing (section 7.4.3.10)  
  
    for( UInt sliceSegmentStartCtuTsAddr = 0, sliceIdxCount=0; sliceSegmentStartCtuTsAddr < pcPic->getPicSym()->getNumberOfCtusInFrame(); sliceIdxCount++, sliceSegmentStartCtuTsAddr=pcSlice->getSliceSegmentCurEndCtuTsAddr() )  
    {  
      pcSlice = pcPic->getSlice(sliceIdxCount);  
      if(sliceIdxCount > 0 && pcSlice->getSliceType()!= I_SLICE)  
      {  
        pcSlice->checkColRefIdx(sliceIdxCount, pcPic);  
      }  
      pcPic->setCurrSliceIdx(sliceIdxCount);  
      m_pcSliceEncoder->setSliceIdx(sliceIdxCount);  
  
      pcSlice->setRPS(pcPic->getSlice(0)->getRPS());  
      pcSlice->setRPSidx(pcPic->getSlice(0)->getRPSidx());  
  
      for ( UInt ui = 0 ; ui < numSubstreams; ui++ )  
      {  
        substreamsOut[ui].clear();  
      }  
  
      m_pcEntropyCoder->setEntropyCoder   ( m_pcCavlcCoder );  
      m_pcEntropyCoder->resetEntropy      ( pcSlice );  
      /* start slice NALunit */  
      OutputNALUnit nalu( pcSlice->getNalUnitType(), pcSlice->getTLayer() );  
      m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream);  
  
      pcSlice->setNoRaslOutputFlag(false);  
      if (pcSlice->isIRAP())  
      {  
        if (pcSlice->getNalUnitType() >= NAL_UNIT_CODED_SLICE_BLA_W_LP && pcSlice->getNalUnitType() <= NAL_UNIT_CODED_SLICE_IDR_N_LP)  
        {  
          pcSlice->setNoRaslOutputFlag(true);  
        }  
        //the inference for NoOutputPriorPicsFlag  
        // KJS: This cannot happen at the encoder  
        if (!m_bFirst && pcSlice->isIRAP() && pcSlice->getNoRaslOutputFlag())  
        {  
          if (pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA)  
          {  
            pcSlice->setNoOutputPriorPicsFlag(true);  
          }  
        }  
      }  
  
      pcSlice->setEncCABACTableIdx(m_pcSliceEncoder->getEncCABACTableIdx());  
  
      tmpBitsBeforeWriting = m_pcEntropyCoder->getNumberOfWrittenBits();  
      m_pcEntropyCoder->encodeSliceHeader(pcSlice);  
      actualHeadBits += ( m_pcEntropyCoder->getNumberOfWrittenBits() - tmpBitsBeforeWriting );  
  
      pcSlice->setFinalized(true);  
  
      pcSlice->clearSubstreamSizes(  );  
      {  
        UInt numBinsCoded = 0;  
        m_pcSliceEncoder->encodeSlice(pcPic, &(substreamsOut[0]), numBinsCoded);  
        binCountsInNalUnits+=numBinsCoded;  
      }  
  
      {  
        // Construct the final bitstream by concatenating substreams.  
        // The final bitstream is either nalu.m_Bitstream or pcBitstreamRedirect;  
        // Complete the slice header info.  
        m_pcEntropyCoder->setEntropyCoder   ( m_pcCavlcCoder );  
        m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream);  
        m_pcEntropyCoder->encodeTilesWPPEntryPoint( pcSlice );  
  
        // Append substreams...  
        TComOutputBitstream *pcOut = pcBitstreamRedirect;  
        const Int numZeroSubstreamsAtStartOfSlice  = pcPic->getSubstreamForCtuAddr(pcSlice->getSliceSegmentCurStartCtuTsAddr(), false, pcSlice);  
        const Int numSubstreamsToCode  = pcSlice->getNumberOfSubstreamSizes()+1;  
        for ( UInt ui = 0 ; ui < numSubstreamsToCode; ui++ )  
        {  
          pcOut->addSubstream(&(substreamsOut[ui+numZeroSubstreamsAtStartOfSlice]));  
        }  
      }  
  
      // If current NALU is the first NALU of slice (containing slice header) and more NALUs exist (due to multiple dependent slices) then buffer it.  
      // If current NALU is the last NALU of slice and a NALU was buffered, then (a) Write current NALU (b) Update an write buffered NALU at approproate location in NALU list.  
      Bool bNALUAlignedWrittenToList    = false; // used to ensure current NALU is not written more than once to the NALU list.  
      xAttachSliceDataToNalUnit(nalu, pcBitstreamRedirect);  
      accessUnit.push_back(new NALUnitEBSP(nalu));  
      actualTotalBits += UInt(accessUnit.back()->m_nalUnitData.str().size()) * 8;  
      numBytesInVclNalUnits += (std::size_t)(accessUnit.back()->m_nalUnitData.str().size());  
      bNALUAlignedWrittenToList = true;  
  
      if (!bNALUAlignedWrittenToList)  
      {  
        nalu.m_Bitstream.writeAlignZero();  
        accessUnit.push_back(new NALUnitEBSP(nalu));  
      }  
  
      if( ( m_pcCfg->getPictureTimingSEIEnabled() || m_pcCfg->getDecodingUnitInfoSEIEnabled() ) &&  
          ( pcSlice->getSPS()->getVuiParametersPresentFlag() ) &&  
          ( ( pcSlice->getSPS()->getVuiParameters()->getHrdParameters()->getNalHrdParametersPresentFlag() )  
         || ( pcSlice->getSPS()->getVuiParameters()->getHrdParameters()->getVclHrdParametersPresentFlag() ) ) &&  
          ( pcSlice->getSPS()->getVuiParameters()->getHrdParameters()->getSubPicCpbParamsPresentFlag() ) )  
      {  
          UInt numNalus = 0;  
        UInt numRBSPBytes = 0;  
        for (AccessUnit::const_iterator it = accessUnit.begin(); it != accessUnit.end(); it++)  
        {  
          numRBSPBytes += UInt((*it)->m_nalUnitData.str().size());  
          numNalus ++;  
        }  
        duData.push_back(DUData());  
        duData.back().accumBitsDU = ( numRBSPBytes << 3 );  
        duData.back().accumNalsDU = numNalus;  
      }  
    } // end iteration over slices  
  
    // cabac_zero_words processing  
    cabac_zero_word_padding(pcSlice, pcPic, binCountsInNalUnits, numBytesInVclNalUnits, accessUnit.back()->m_nalUnitData, m_pcCfg->getCabacZeroWordPaddingEnabled());  
  
    pcPic->compressMotion();  
  
    //-- For time output for each slice  
    Double dEncTime = (Double)(clock()-iBeforeTime) / CLOCKS_PER_SEC;  
  
    std::string digestStr;  
    if (m_pcCfg->getDecodedPictureHashSEIEnabled())  
    {  
      SEIDecodedPictureHash *decodedPictureHashSei = new SEIDecodedPictureHash();  
      m_seiEncoder.initDecodedPictureHashSEI(decodedPictureHashSei, pcPic, digestStr, pcSlice->getSPS()->getBitDepths());  
      trailingSeiMessages.push_back(decodedPictureHashSei);  
    }  
    xWriteTrailingSEIMessages(trailingSeiMessages, accessUnit, pcSlice->getTLayer(), pcSlice->getSPS());  
  
    m_pcCfg->setEncodedFlag(iGOPid, true);  
  
    xCalculateAddPSNRs( isField, isTff, iGOPid, pcPic, accessUnit, rcListPic, dEncTime, snr_conversion, printFrameMSE );  
  
    if (!digestStr.empty())  
    {  
      if(m_pcCfg->getDecodedPictureHashSEIEnabled() == 1)  
      {  
        printf(" [MD5:%s]", digestStr.c_str());  
      }  
      else if(m_pcCfg->getDecodedPictureHashSEIEnabled() == 2)  
      {  
        printf(" [CRC:%s]", digestStr.c_str());  
      }  
      else if(m_pcCfg->getDecodedPictureHashSEIEnabled() == 3)  
      {  
        printf(" [Checksum:%s]", digestStr.c_str());  
      }  
    }  
**********************************************************************************************  
    if ( m_pcCfg->getUseRateCtrl() )  
    {  
      Double avgQP     = m_pcRateCtrl->getRCPic()->calAverageQP();  
      Double avgLambda = m_pcRateCtrl->getRCPic()->calAverageLambda();  
      if ( avgLambda < 0.0 )  
      {  
        avgLambda = lambda;  
      }  
  
      m_pcRateCtrl->getRCPic()->updateAfterPicture( actualHeadBits, actualTotalBits, avgQP, avgLambda, pcSlice->getSliceType());  
      m_pcRateCtrl->getRCPic()->addToPictureLsit( m_pcRateCtrl->getPicList() );  
  
      m_pcRateCtrl->getRCSeq()->updateAfterPic( actualTotalBits );  
      if ( pcSlice->getSliceType() != I_SLICE )  
      {  
        m_pcRateCtrl->getRCGOP()->updateAfterPicture( actualTotalBits );  
      }  
      else    // for intra picture, the estimated bits are used to update the current status in the GOP  
      {  
        m_pcRateCtrl->getRCGOP()->updateAfterPicture( estimatedBits );  
      }  
    }  
****************************************************************************************************  
    xCreatePictureTimingSEI(m_pcCfg->getEfficientFieldIRAPEnabled()?effFieldIRAPMap.GetIRAPGOPid():0, leadingSeiMessages, nestedSeiMessages, duInfoSeiMessages, pcSlice, isField, duData);  
    if (m_pcCfg->getScalableNestingSEIEnabled())  
    {  
      xCreateScalableNestingSEI (leadingSeiMessages, nestedSeiMessages);  
    }  
    xWriteLeadingSEIMessages(leadingSeiMessages, duInfoSeiMessages, accessUnit, pcSlice->getTLayer(), pcSlice->getSPS(), duData);  
    xWriteDuSEIMessages(duInfoSeiMessages, accessUnit, pcSlice->getTLayer(), pcSlice->getSPS(), duData);  
  
    pcPic->getPicYuvRec()->copyToPic(pcPicYuvRecOut);  //将重建的picture保存
  
    pcPic->setReconMark   ( true );  
    m_bFirst = false;  
    m_iNumPicCoded++;  //编码完一帧,已编码的帧数加一
    m_totalCoded ++;  
    /* logging: insert a newline at end of picture period */  
    printf("\n");  
    fflush(stdout);  
  
    if (m_pcCfg->getEfficientFieldIRAPEnabled())  
    {  
      iGOPid=effFieldIRAPMap.restoreGOPid(iGOPid);  
    }  
  } // iGOPid-loop  
  
  delete pcBitstreamRedirect;  
  
  assert ( (m_iNumPicCoded == iNumPicRcvd) );  
}  
  
Void TEncGOP::printOutSummary(UInt uiNumAllPicCoded, Bool isField, const Bool printMSEBasedSNR, const Bool printSequenceMSE, const BitDepths &bitDepths)  
{  
  assert (uiNumAllPicCoded == m_gcAnalyzeAll.getNumPic());  
  
  
  //--CFG_KDY  
  const Int rateMultiplier=(isField?2:1);  
  m_gcAnalyzeAll.setFrmRate( m_pcCfg->getFrameRate()*rateMultiplier );  
  m_gcAnalyzeI.setFrmRate( m_pcCfg->getFrameRate()*rateMultiplier );  
  m_gcAnalyzeP.setFrmRate( m_pcCfg->getFrameRate()*rateMultiplier );  
  m_gcAnalyzeB.setFrmRate( m_pcCfg->getFrameRate()*rateMultiplier );  
  const ChromaFormat chFmt = m_pcCfg->getChromaFormatIdc();  
  
  //-- all  
  printf( "\n\nSUMMARY --------------------------------------------------------\n" );  
  m_gcAnalyzeAll.printOut('a', chFmt, printMSEBasedSNR, printSequenceMSE, bitDepths);  
  
  printf( "\n\nI Slices--------------------------------------------------------\n" );  
  m_gcAnalyzeI.printOut('i', chFmt, printMSEBasedSNR, printSequenceMSE, bitDepths);  
  
  printf( "\n\nP Slices--------------------------------------------------------\n" );  
  m_gcAnalyzeP.printOut('p', chFmt, printMSEBasedSNR, printSequenceMSE, bitDepths);  
  
  printf( "\n\nB Slices--------------------------------------------------------\n" );  
  m_gcAnalyzeB.printOut('b', chFmt, printMSEBasedSNR, printSequenceMSE, bitDepths);  
  
  if (!m_pcCfg->getSummaryOutFilename().empty())  
  {  
    m_gcAnalyzeAll.printSummary(chFmt, printSequenceMSE, bitDepths, m_pcCfg->getSummaryOutFilename());  
  }  
  
  if (!m_pcCfg->getSummaryPicFilenameBase().empty())  
  {  
    m_gcAnalyzeI.printSummary(chFmt, printSequenceMSE, bitDepths, m_pcCfg->getSummaryPicFilenameBase()+"I.txt");  
    m_gcAnalyzeP.printSummary(chFmt, printSequenceMSE, bitDepths, m_pcCfg->getSummaryPicFilenameBase()+"P.txt");  
    m_gcAnalyzeB.printSummary(chFmt, printSequenceMSE, bitDepths, m_pcCfg->getSummaryPicFilenameBase()+"B.txt");  
  }  
  
  if(isField)  
  {  
    //-- interlaced summary  
    m_gcAnalyzeAll_in.setFrmRate( m_pcCfg->getFrameRate());  
    m_gcAnalyzeAll_in.setBits(m_gcAnalyzeAll.getBits());  
    // prior to the above statement, the interlace analyser does not contain the correct total number of bits.  
  
    printf( "\n\nSUMMARY INTERLACED ---------------------------------------------\n" );  
    m_gcAnalyzeAll_in.printOut('a', chFmt, printMSEBasedSNR, printSequenceMSE, bitDepths);  
  
    if (!m_pcCfg->getSummaryOutFilename().empty())  
    {  
      m_gcAnalyzeAll_in.printSummary(chFmt, printSequenceMSE, bitDepths, m_pcCfg->getSummaryOutFilename());  
    }  
  }  
  
  printf("\nRVM: %.3lf\n" , xCalculateRVM());  
}  
  

猜你喜欢

转载自blog.csdn.net/xhyan523/article/details/79617832