Project

General

Profile

compressGOP.cpp

侯 震可, 09/10/2017 08:23 PM

Download (32.6 KB)

 
1

    
2
// ====================================================================================================================
3
// Public member functions
4
// ====================================================================================================================
5
Void TEncGOP::compressGOP( Int iPOCLast, Int iNumPicRcvd, TComList<TComPic*>& rcListPic,
6
                           TComList<TComPicYuv*>& rcListPicYuvRecOut, std::list<AccessUnit>& accessUnitsInGOP,
7
                           Bool isField, Bool isTff, const InputColourSpaceConversion snr_conversion, const Bool printFrameMSE )
8
{
9
  // TODO: Split this function up.
10

    
11
  TComPic*        pcPic = NULL;
12
  TComPicYuv*     pcPicYuvRecOut;
13
  TComSlice*      pcSlice;
14
  TComOutputBitstream  *pcBitstreamRedirect;
15
  pcBitstreamRedirect = new TComOutputBitstream;//基本的初始化
16
  AccessUnit::iterator  itLocationToPushSliceHeaderNALU; // used to store location where NALU containing slice header is to be inserted
17

    
18
  xInitGOP( iPOCLast, iNumPicRcvd, isField );//isField是否场编码,默认0
19

    
20
  m_iNumPicCoded = 0;//初始编码帧数
21
  SEIMessages leadingSeiMessages;
22
  SEIMessages nestedSeiMessages;
23
  SEIMessages duInfoSeiMessages;
24
  SEIMessages trailingSeiMessages;
25
  std::deque<DUData> duData;
26
  SEIDecodingUnitInfo decodingUnitInfoSEI;
27

    
28
  EfficientFieldIRAPMapping effFieldIRAPMap;
29
  if (m_pcCfg->getEfficientFieldIRAPEnabled())
30
  {
31
    effFieldIRAPMap.initialize(isField, m_iGopSize, iPOCLast, iNumPicRcvd, m_iLastIDR, this, m_pcCfg);
32
  }
33

    
34
  // reset flag indicating whether pictures have been encoded
35
  for ( Int iGOPid=0; iGOPid < m_iGopSize; iGOPid++ )
36
  {
37
    m_pcCfg->setEncodedFlag(iGOPid, false);
38
  }
39

    
40
  for ( Int iGOPid=0; iGOPid < m_iGopSize; iGOPid++ )
41
  {
42
    if (m_pcCfg->getEfficientFieldIRAPEnabled())
43
    {
44
      iGOPid=effFieldIRAPMap.adjustGOPid(iGOPid);
45
    }
46

    
47
    //-- For time output for each slice
48
    clock_t iBeforeTime = clock();
49

    
50
#if !X0038_LAMBDA_FROM_QP_CAPABILITY
51
    UInt uiColDir = calculateCollocatedFromL1Flag(m_pcCfg, iGOPid, m_iGopSize);
52
#endif
53

    
54
    /////////////////////////////////////////////////////////////////////////////////////////////////// Initial to start encoding
55
    Int iTimeOffset;
56
    Int pocCurr;//pocCurr帧的绝对poc
57

    
58
    if(iPOCLast == 0) //case first frame or first top field
59
    {
60
      pocCurr=0;
61
      iTimeOffset = 1;
62
    }
63
    else if(iPOCLast == 1 && isField) //case first bottom field, just like the first frame, the poc computation is not right anymore, we set the right value
64
    {
65
      pocCurr = 1;
66
      iTimeOffset = 1;
67
    }
68
    else
69
    {
70
      pocCurr = iPOCLast - iNumPicRcvd + m_pcCfg->getGOPEntry(iGOPid).m_POC - ((isField && m_iGopSize>1) ? 1:0);
71
      iTimeOffset = m_pcCfg->getGOPEntry(iGOPid).m_POC;
72
    }
73

    
74
    if(pocCurr>=m_pcCfg->getFramesToBeEncoded())
75
    {
76
      if (m_pcCfg->getEfficientFieldIRAPEnabled())
77
      {
78
        iGOPid=effFieldIRAPMap.restoreGOPid(iGOPid);
79
      }
80
      continue;//GOP编码结束跳出循环
81
    }
82

    
83
    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 )//该帧为idr帧
84
    {
85
      m_iLastIDR = pocCurr;//将上一个idr帧设为该帧的绝对poc
86
    }
87
    // start a new access unit: create an entry in the list of output access units
88
    accessUnitsInGOP.push_back(AccessUnit());
89
    AccessUnit& accessUnit = accessUnitsInGOP.back();
90
    xGetBuffer( rcListPic, rcListPicYuvRecOut, iNumPicRcvd, iTimeOffset, pcPic, pcPicYuvRecOut, pocCurr, isField );
91

    
92
#if REDUCED_ENCODER_MEMORY
93
    pcPic->prepareForReconstruction();
94

    
95
#endif
96
    //  Slice data initialization
97
    pcPic->clearSliceBuffer();
98
    pcPic->allocateNewSlice();
99
    m_pcSliceEncoder->setSliceIdx(0);
100
    pcPic->setCurrSliceIdx(0);
101

    
102
    m_pcSliceEncoder->initEncSlice ( pcPic, iPOCLast, pocCurr, iGOPid, pcSlice, isField );//初始化pcSlice
103

    
104
    pcSlice->setLastIDR(m_iLastIDR);
105
    pcSlice->setSliceIdx(0);
106
    //set default slice level flag to the same as SPS level flag
107
    pcSlice->setLFCrossSliceBoundaryFlag(  pcSlice->getPPS()->getLoopFilterAcrossSlicesEnabledFlag()  );
108

    
109
    if(pcSlice->getSliceType()==B_SLICE&&m_pcCfg->getGOPEntry(iGOPid).m_sliceType=='P')
110
    {
111
      pcSlice->setSliceType(P_SLICE);
112
    }
113
    if(pcSlice->getSliceType()==B_SLICE&&m_pcCfg->getGOPEntry(iGOPid).m_sliceType=='I')
114
    {
115
      pcSlice->setSliceType(I_SLICE);
116
    }
117
    
118
    // Set the nal unit type
119
    pcSlice->setNalUnitType(getNalUnitType(pocCurr, m_iLastIDR, isField));//根据当前帧poc与上个idr帧的绝对poc得到NAlUtype
120
    if(pcSlice->getTemporalLayerNonReferenceFlag())
121
    {
122
      if (pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_TRAIL_R &&
123
          !(m_iGopSize == 1 && pcSlice->getSliceType() == I_SLICE))
124
        // Add this condition to avoid POC issues with encoder_intra_main.cfg configuration (see #1127 in bug tracker)
125
      {
126
        pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_TRAIL_N);
127
      }
128
      if(pcSlice->getNalUnitType()==NAL_UNIT_CODED_SLICE_RADL_R)
129
      {
130
        pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_RADL_N);
131
      }
132
      if(pcSlice->getNalUnitType()==NAL_UNIT_CODED_SLICE_RASL_R)
133
      {
134
        pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_RASL_N);
135
      }
136
    }
137

    
138
    if (m_pcCfg->getEfficientFieldIRAPEnabled())
139
    {
140
      if ( pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_LP
141
        || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_RADL
142
        || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_N_LP
143
        || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL
144
        || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP
145
        || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA )  // IRAP picture
146
      {
147
        m_associatedIRAPType = pcSlice->getNalUnitType();
148
        m_associatedIRAPPOC = pocCurr;
149
      }
150
      pcSlice->setAssociatedIRAPType(m_associatedIRAPType);
151
      pcSlice->setAssociatedIRAPPOC(m_associatedIRAPPOC);
152
    }
153
    // Do decoding refresh marking if any
154
    pcSlice->decodingRefreshMarking(m_pocCRA, m_bRefreshPending, rcListPic, m_pcCfg->getEfficientFieldIRAPEnabled());
155
    m_pcEncTop->selectReferencePictureSet(pcSlice, pocCurr, iGOPid);
156
    if (!m_pcCfg->getEfficientFieldIRAPEnabled())
157
    {
158
      if ( pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_LP
159
        || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_RADL
160
        || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_N_LP
161
        || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL
162
        || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP
163
        || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA )  // IRAP picture
164
      {
165
        m_associatedIRAPType = pcSlice->getNalUnitType();
166
        m_associatedIRAPPOC = pocCurr;
167
      }
168
      pcSlice->setAssociatedIRAPType(m_associatedIRAPType);
169
      pcSlice->setAssociatedIRAPPOC(m_associatedIRAPPOC);
170
    }
171

    
172
    if ((pcSlice->checkThatAllRefPicsAreAvailable(rcListPic, pcSlice->getRPS(), false, m_iLastRecoveryPicPOC, m_pcCfg->getDecodingRefreshType() == 3) != 0) || (pcSlice->isIRAP()) 
173
      || (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)
174
      )
175
    {
176
      pcSlice->createExplicitReferencePictureSetFromReference(rcListPic, pcSlice->getRPS(), pcSlice->isIRAP(), m_iLastRecoveryPicPOC, m_pcCfg->getDecodingRefreshType() == 3, m_pcCfg->getEfficientFieldIRAPEnabled());
177
    }
178

    
179
    pcSlice->applyReferencePictureSet(rcListPic, pcSlice->getRPS());
180

    
181
    if(pcSlice->getTLayer() > 0 
182
      &&  !( pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_RADL_N     // Check if not a leading picture
183
          || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_RADL_R
184
          || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_RASL_N
185
          || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_RASL_R )
186
        )
187
    {
188
      if(pcSlice->isTemporalLayerSwitchingPoint(rcListPic) || pcSlice->getSPS()->getTemporalIdNestingFlag())
189
      {
190
        if(pcSlice->getTemporalLayerNonReferenceFlag())
191
        {
192
          pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_TSA_N);
193
        }
194
        else
195
        {
196
          pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_TSA_R);
197
        }
198
      }
199
      else if(pcSlice->isStepwiseTemporalLayerSwitchingPointCandidate(rcListPic))
200
      {
201
        Bool isSTSA=true;
202
        for(Int ii=iGOPid+1;(ii<m_pcCfg->getGOPSize() && isSTSA==true);ii++)
203
        {
204
          Int lTid= m_pcCfg->getGOPEntry(ii).m_temporalId;
205
          if(lTid==pcSlice->getTLayer())
206
          {
207
            const TComReferencePictureSet* nRPS = pcSlice->getSPS()->getRPSList()->getReferencePictureSet(ii);
208
            for(Int jj=0;jj<nRPS->getNumberOfPictures();jj++)
209
            {
210
              if(nRPS->getUsed(jj))
211
              {
212
                Int tPoc=m_pcCfg->getGOPEntry(ii).m_POC+nRPS->getDeltaPOC(jj);
213
                Int kk=0;
214
                for(kk=0;kk<m_pcCfg->getGOPSize();kk++)
215
                {
216
                  if(m_pcCfg->getGOPEntry(kk).m_POC==tPoc)
217
                  {
218
                    break;
219
                  }
220
                }
221
                Int tTid=m_pcCfg->getGOPEntry(kk).m_temporalId;
222
                if(tTid >= pcSlice->getTLayer())
223
                {
224
                  isSTSA=false;
225
                  break;
226
                }
227
              }
228
            }
229
          }
230
        }
231
        if(isSTSA==true)
232
        {
233
          if(pcSlice->getTemporalLayerNonReferenceFlag())
234
          {
235
            pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_STSA_N);
236
          }
237
          else
238
          {
239
            pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_STSA_R);
240
          }
241
        }
242
      }
243
    }
244
    arrangeLongtermPicturesInRPS(pcSlice, rcListPic);
245
    TComRefPicListModification* refPicListModification = pcSlice->getRefPicListModification();
246
    refPicListModification->setRefPicListModificationFlagL0(0);
247
    refPicListModification->setRefPicListModificationFlagL1(0);
248
    pcSlice->setNumRefIdx(REF_PIC_LIST_0,min(m_pcCfg->getGOPEntry(iGOPid).m_numRefPicsActive,pcSlice->getRPS()->getNumberOfPictures()));
249
    pcSlice->setNumRefIdx(REF_PIC_LIST_1,min(m_pcCfg->getGOPEntry(iGOPid).m_numRefPicsActive,pcSlice->getRPS()->getNumberOfPictures()));
250

    
251
    //  Set reference list
252
    pcSlice->setRefPicList ( rcListPic );
253

    
254
    //  Slice info. refinement
255
    if ( (pcSlice->getSliceType() == B_SLICE) && (pcSlice->getNumRefIdx(REF_PIC_LIST_1) == 0) )
256
    {
257
      pcSlice->setSliceType ( P_SLICE );
258
    }
259
    pcSlice->setEncCABACTableIdx(m_pcSliceEncoder->getEncCABACTableIdx());
260

    
261
    if (pcSlice->getSliceType() == B_SLICE)
262
    {
263
#if X0038_LAMBDA_FROM_QP_CAPABILITY
264
      const UInt uiColFromL0 = calculateCollocatedFromL0Flag(pcSlice);
265
      pcSlice->setColFromL0Flag(uiColFromL0);
266
#else
267
      pcSlice->setColFromL0Flag(1-uiColDir);
268
#endif
269
      Bool bLowDelay = true;
270
      Int  iCurrPOC  = pcSlice->getPOC();
271
      Int iRefIdx = 0;
272

    
273
      for (iRefIdx = 0; iRefIdx < pcSlice->getNumRefIdx(REF_PIC_LIST_0) && bLowDelay; iRefIdx++)
274
      {
275
        if ( pcSlice->getRefPic(REF_PIC_LIST_0, iRefIdx)->getPOC() > iCurrPOC )
276
        {
277
          bLowDelay = false;
278
        }
279
      }
280
      for (iRefIdx = 0; iRefIdx < pcSlice->getNumRefIdx(REF_PIC_LIST_1) && bLowDelay; iRefIdx++)
281
      {
282
        if ( pcSlice->getRefPic(REF_PIC_LIST_1, iRefIdx)->getPOC() > iCurrPOC )
283
        {
284
          bLowDelay = false;
285
        }
286
      }
287

    
288
      pcSlice->setCheckLDC(bLowDelay);
289
    }
290
    else
291
    {
292
      pcSlice->setCheckLDC(true);
293
    }
294

    
295
#if !X0038_LAMBDA_FROM_QP_CAPABILITY
296
    uiColDir = 1-uiColDir;
297
#endif
298

    
299
    //-------------------------------------------------------------
300
    pcSlice->setRefPOCList();
301

    
302
    pcSlice->setList1IdxToList0Idx();
303

    
304
    if (m_pcEncTop->getTMVPModeId() == 2)
305
    {
306
      if (iGOPid == 0) // first picture in SOP (i.e. forward B)
307
      {
308
        pcSlice->setEnableTMVPFlag(0);
309
      }
310
      else
311
      {
312
        // Note: pcSlice->getColFromL0Flag() is assumed to be always 0 and getcolRefIdx() is always 0.
313
        pcSlice->setEnableTMVPFlag(1);
314
      }
315
    }
316
    else if (m_pcEncTop->getTMVPModeId() == 1)
317
    {
318
      pcSlice->setEnableTMVPFlag(1);
319
    }
320
    else
321
    {
322
      pcSlice->setEnableTMVPFlag(0);
323
    }
324
    
325
    // set adaptive search range for non-intra-slices
326
    if (m_pcCfg->getUseASR() && pcSlice->getSliceType()!=I_SLICE)
327
    {
328
      m_pcSliceEncoder->setSearchRange(pcSlice);
329
    }
330

    
331
    Bool bGPBcheck=false;
332
    if ( pcSlice->getSliceType() == B_SLICE)
333
    {
334
      if ( pcSlice->getNumRefIdx(RefPicList( 0 ) ) == pcSlice->getNumRefIdx(RefPicList( 1 ) ) )
335
      {
336
        bGPBcheck=true;
337
        Int i;
338
        for ( i=0; i < pcSlice->getNumRefIdx(RefPicList( 1 ) ); i++ )
339
        {
340
          if ( pcSlice->getRefPOC(RefPicList(1), i) != pcSlice->getRefPOC(RefPicList(0), i) )
341
          {
342
            bGPBcheck=false;
343
            break;
344
          }
345
        }
346
      }
347
    }
348
    if(bGPBcheck)
349
    {
350
      pcSlice->setMvdL1ZeroFlag(true);
351
    }
352
    else
353
    {
354
      pcSlice->setMvdL1ZeroFlag(false);
355
    }
356

    
357

    
358
    Double lambda            = 0.0;
359
    Int actualHeadBits       = 0;
360
    Int actualTotalBits      = 0;
361
    Int estimatedBits        = 0;
362
    Int tmpBitsBeforeWriting = 0;
363
    if ( m_pcCfg->getUseRateCtrl() ) // TODO: does this work with multiple slices and slice-segments?
364
    {
365
      Int frameLevel = m_pcRateCtrl->getRCSeq()->getGOPID2Level( iGOPid );
366
      if ( pcPic->getSlice(0)->getSliceType() == I_SLICE )
367
      {
368
        frameLevel = 0;
369
      }
370
      m_pcRateCtrl->initRCPic( frameLevel );
371
      estimatedBits = m_pcRateCtrl->getRCPic()->getTargetBits();
372

    
373
      if (m_pcRateCtrl->getCpbSaturationEnabled() && frameLevel != 0)
374
      {
375
        Int estimatedCpbFullness = m_pcRateCtrl->getCpbState() + m_pcRateCtrl->getBufferingRate();
376

    
377
        // prevent overflow
378
        if (estimatedCpbFullness - estimatedBits > (Int)(m_pcRateCtrl->getCpbSize()*0.9f))
379
        {
380
          estimatedBits = estimatedCpbFullness - (Int)(m_pcRateCtrl->getCpbSize()*0.9f);
381
        }
382

    
383
        estimatedCpbFullness -= m_pcRateCtrl->getBufferingRate();
384
        // prevent underflow
385
        if (estimatedCpbFullness - estimatedBits < m_pcRateCtrl->getRCPic()->getLowerBound())
386
        {
387
          estimatedBits = max(200, estimatedCpbFullness - m_pcRateCtrl->getRCPic()->getLowerBound());
388
        }
389

    
390
        m_pcRateCtrl->getRCPic()->setTargetBits(estimatedBits);
391
      }
392

    
393
      Int sliceQP = m_pcCfg->getInitialQP();
394
      if ( ( pcSlice->getPOC() == 0 && m_pcCfg->getInitialQP() > 0 ) || ( frameLevel == 0 && m_pcCfg->getForceIntraQP() ) ) // QP is specified
395
      {
396
        Int    NumberBFrames = ( m_pcCfg->getGOPSize() - 1 );
397
        Double dLambda_scale = 1.0 - Clip3( 0.0, 0.5, 0.05*(Double)NumberBFrames );
398
        Double dQPFactor     = 0.57*dLambda_scale;
399
        Int    SHIFT_QP      = 12;
400
        Int    bitdepth_luma_qp_scale = 0;
401
        Double qp_temp = (Double) sliceQP + bitdepth_luma_qp_scale - SHIFT_QP;
402
        lambda = dQPFactor*pow( 2.0, qp_temp/3.0 );
403
      }
404
      else if ( frameLevel == 0 )   // intra case, but use the model
405
      {
406
        m_pcSliceEncoder->calCostSliceI(pcPic); // TODO: This only analyses the first slice segment - what about the others?
407

    
408
        if ( m_pcCfg->getIntraPeriod() != 1 )   // do not refine allocated bits for all intra case
409
        {
410
          Int bits = m_pcRateCtrl->getRCSeq()->getLeftAverageBits();
411
          bits = m_pcRateCtrl->getRCPic()->getRefineBitsForIntra( bits );
412

    
413
          if (m_pcRateCtrl->getCpbSaturationEnabled() )
414
          {
415
            Int estimatedCpbFullness = m_pcRateCtrl->getCpbState() + m_pcRateCtrl->getBufferingRate();
416

    
417
            // prevent overflow
418
            if (estimatedCpbFullness - bits > (Int)(m_pcRateCtrl->getCpbSize()*0.9f))
419
            {
420
              bits = estimatedCpbFullness - (Int)(m_pcRateCtrl->getCpbSize()*0.9f);
421
            }
422

    
423
            estimatedCpbFullness -= m_pcRateCtrl->getBufferingRate();
424
            // prevent underflow
425
            if (estimatedCpbFullness - bits < m_pcRateCtrl->getRCPic()->getLowerBound())
426
            {
427
              bits = estimatedCpbFullness - m_pcRateCtrl->getRCPic()->getLowerBound();
428
            }
429
          }
430

    
431
          if ( bits < 200 )
432
          {
433
            bits = 200;
434
          }
435
          m_pcRateCtrl->getRCPic()->setTargetBits( bits );
436
        }
437

    
438
        list<TEncRCPic*> listPreviousPicture = m_pcRateCtrl->getPicList();
439
        m_pcRateCtrl->getRCPic()->getLCUInitTargetBits();
440
        lambda  = m_pcRateCtrl->getRCPic()->estimatePicLambda( listPreviousPicture, pcSlice->getSliceType());
441
        sliceQP = m_pcRateCtrl->getRCPic()->estimatePicQP( lambda, listPreviousPicture );
442
      }
443
      else    // normal case
444
      {
445
        list<TEncRCPic*> listPreviousPicture = m_pcRateCtrl->getPicList();
446
        lambda  = m_pcRateCtrl->getRCPic()->estimatePicLambda( listPreviousPicture, pcSlice->getSliceType());
447
        sliceQP = m_pcRateCtrl->getRCPic()->estimatePicQP( lambda, listPreviousPicture );
448
      }
449

    
450
      sliceQP = Clip3( -pcSlice->getSPS()->getQpBDOffset(CHANNEL_TYPE_LUMA), MAX_QP, sliceQP );
451
      m_pcRateCtrl->getRCPic()->setPicEstQP( sliceQP );
452

    
453
      m_pcSliceEncoder->resetQP( pcPic, sliceQP, lambda );
454
    }
455

    
456
    UInt uiNumSliceSegments = 1;
457

    
458
    // Allocate some coders, now the number of tiles are known.
459
    const Int numSubstreamsColumns = (pcSlice->getPPS()->getNumTileColumnsMinus1() + 1);
460
    const Int numSubstreamRows     = pcSlice->getPPS()->getEntropyCodingSyncEnabledFlag() ? pcPic->getFrameHeightInCtus() : (pcSlice->getPPS()->getNumTileRowsMinus1() + 1);
461
    const Int numSubstreams        = numSubstreamRows * numSubstreamsColumns;
462
    std::vector<TComOutputBitstream> substreamsOut(numSubstreams);
463

    
464
    // now compress (trial encode) the various slice segments (slices, and dependent slices)
465
    {
466
      const UInt numberOfCtusInFrame=pcPic->getPicSym()->getNumberOfCtusInFrame();
467
      pcSlice->setSliceCurStartCtuTsAddr( 0 );
468
      pcSlice->setSliceSegmentCurStartCtuTsAddr( 0 );
469

    
470
      for(UInt nextCtuTsAddr = 0; nextCtuTsAddr < numberOfCtusInFrame; )
471
      {
472
        m_pcSliceEncoder->precompressSlice( pcPic );
473
        m_pcSliceEncoder->compressSlice   ( pcPic, false, false );
474

    
475
        const UInt curSliceSegmentEnd = pcSlice->getSliceSegmentCurEndCtuTsAddr();
476
        if (curSliceSegmentEnd < numberOfCtusInFrame)
477
        {
478
          const Bool bNextSegmentIsDependentSlice=curSliceSegmentEnd<pcSlice->getSliceCurEndCtuTsAddr();
479
          const UInt sliceBits=pcSlice->getSliceBits();
480
          pcPic->allocateNewSlice();
481
          // prepare for next slice
482
          pcPic->setCurrSliceIdx                    ( uiNumSliceSegments );
483
          m_pcSliceEncoder->setSliceIdx             ( uiNumSliceSegments   );
484
          pcSlice = pcPic->getSlice                 ( uiNumSliceSegments   );
485
          assert(pcSlice->getPPS()!=0);
486
          pcSlice->copySliceInfo                    ( pcPic->getSlice(uiNumSliceSegments-1)  );
487
          pcSlice->setSliceIdx                      ( uiNumSliceSegments   );
488
          if (bNextSegmentIsDependentSlice)
489
          {
490
            pcSlice->setSliceBits(sliceBits);
491
          }
492
          else
493
          {
494
            pcSlice->setSliceCurStartCtuTsAddr      ( curSliceSegmentEnd );
495
            pcSlice->setSliceBits(0);
496
          }
497
          pcSlice->setDependentSliceSegmentFlag(bNextSegmentIsDependentSlice);
498
          pcSlice->setSliceSegmentCurStartCtuTsAddr ( curSliceSegmentEnd );
499
          // TODO: optimise cabac_init during compress slice to improve multi-slice operation
500
          // pcSlice->setEncCABACTableIdx(m_pcSliceEncoder->getEncCABACTableIdx());
501
          uiNumSliceSegments ++;
502
        }
503
        nextCtuTsAddr = curSliceSegmentEnd;
504
      }
505
    }
506

    
507
    duData.clear();
508
    pcSlice = pcPic->getSlice(0);
509

    
510
    // SAO parameter estimation using non-deblocked pixels for CTU bottom and right boundary areas
511
    if( pcSlice->getSPS()->getUseSAO() && m_pcCfg->getSaoCtuBoundary() )
512
    {
513
      m_pcSAO->getPreDBFStatistics(pcPic);
514
    }
515

    
516
    //-- Loop filter
517
    Bool bLFCrossTileBoundary = pcSlice->getPPS()->getLoopFilterAcrossTilesEnabledFlag();
518
    m_pcLoopFilter->setCfg(bLFCrossTileBoundary);
519
    if ( m_pcCfg->getDeblockingFilterMetric() )
520
    {
521
      if ( m_pcCfg->getDeblockingFilterMetric()==2 )
522
      {
523
        applyDeblockingFilterParameterSelection(pcPic, uiNumSliceSegments, iGOPid);
524
      }
525
      else
526
      {
527
        applyDeblockingFilterMetric(pcPic, uiNumSliceSegments);
528
      }
529
    }
530
    m_pcLoopFilter->loopFilterPic( pcPic );
531

    
532
    /////////////////////////////////////////////////////////////////////////////////////////////////// File writing
533
    // Set entropy coder
534
    m_pcEntropyCoder->setEntropyCoder   ( m_pcCavlcCoder );
535

    
536
    // write various parameter sets
537
#if JCTVC_Y0038_PARAMS
538
    //bool writePS = m_bSeqFirst || (m_pcCfg->getReWriteParamSetsFlag() && (pcPic->getSlice(0)->getSliceType() == I_SLICE));
539
    bool writePS = m_bSeqFirst || (m_pcCfg->getReWriteParamSetsFlag() && (pcSlice->isIRAP()));
540
    if (writePS)
541
    {
542
      m_pcEncTop->setParamSetChanged(pcSlice->getSPS()->getSPSId(), pcSlice->getPPS()->getPPSId());
543
    }
544
    actualTotalBits += xWriteParameterSets(accessUnit, pcSlice, writePS);
545

    
546
    if (writePS)
547
#else
548
    actualTotalBits += xWriteParameterSets(accessUnit, pcSlice, m_bSeqFirst);
549

    
550
    if ( m_bSeqFirst )
551
#endif
552
    {
553
      // create prefix SEI messages at the beginning of the sequence
554
      assert(leadingSeiMessages.empty());
555
      xCreateIRAPLeadingSEIMessages(leadingSeiMessages, pcSlice->getSPS(), pcSlice->getPPS());
556

    
557
      m_bSeqFirst = false;
558
    }
559
    if (m_pcCfg->getAccessUnitDelimiter())
560
    {
561
      xWriteAccessUnitDelimiter(accessUnit, pcSlice);
562
    }
563

    
564
    // reset presence of BP SEI indication
565
    m_bufferingPeriodSEIPresentInAU = false;
566
    // create prefix SEI associated with a picture
567
    xCreatePerPictureSEIMessages(iGOPid, leadingSeiMessages, nestedSeiMessages, pcSlice);
568

    
569
    /* use the main bitstream buffer for storing the marshalled picture */
570
    m_pcEntropyCoder->setBitstream(NULL);
571

    
572
    pcSlice = pcPic->getSlice(0);
573

    
574
    if (pcSlice->getSPS()->getUseSAO())
575
    {
576
      Bool sliceEnabled[MAX_NUM_COMPONENT];
577
      TComBitCounter tempBitCounter;
578
      tempBitCounter.resetBits();
579
      m_pcEncTop->getRDGoOnSbacCoder()->setBitstream(&tempBitCounter);
580
      m_pcSAO->initRDOCabacCoder(m_pcEncTop->getRDGoOnSbacCoder(), pcSlice);
581
      m_pcSAO->SAOProcess(pcPic, sliceEnabled, pcPic->getSlice(0)->getLambdas(),
582
                          m_pcCfg->getTestSAODisableAtPictureLevel(),
583
                          m_pcCfg->getSaoEncodingRate(),
584
                          m_pcCfg->getSaoEncodingRateChroma(),
585
                          m_pcCfg->getSaoCtuBoundary(),
586
                          m_pcCfg->getSaoResetEncoderStateAfterIRAP());
587
      m_pcSAO->PCMLFDisableProcess(pcPic);
588
      m_pcEncTop->getRDGoOnSbacCoder()->setBitstream(NULL);
589

    
590
      //assign SAO slice header
591
      for(Int s=0; s< uiNumSliceSegments; s++)
592
      {
593
        pcPic->getSlice(s)->setSaoEnabledFlag(CHANNEL_TYPE_LUMA, sliceEnabled[COMPONENT_Y]);
594
        assert(sliceEnabled[COMPONENT_Cb] == sliceEnabled[COMPONENT_Cr]);
595
        pcPic->getSlice(s)->setSaoEnabledFlag(CHANNEL_TYPE_CHROMA, sliceEnabled[COMPONENT_Cb]);
596
      }
597
    }
598

    
599
    // pcSlice is currently slice 0.
600
    std::size_t binCountsInNalUnits   = 0; // For implementation of cabac_zero_word stuffing (section 7.4.3.10)
601
    std::size_t numBytesInVclNalUnits = 0; // For implementation of cabac_zero_word stuffing (section 7.4.3.10)
602

    
603
    for( UInt sliceSegmentStartCtuTsAddr = 0, sliceIdxCount=0; sliceSegmentStartCtuTsAddr < pcPic->getPicSym()->getNumberOfCtusInFrame(); sliceIdxCount++, sliceSegmentStartCtuTsAddr=pcSlice->getSliceSegmentCurEndCtuTsAddr() )
604
    {
605
      pcSlice = pcPic->getSlice(sliceIdxCount);
606
      if(sliceIdxCount > 0 && pcSlice->getSliceType()!= I_SLICE)
607
      {
608
        pcSlice->checkColRefIdx(sliceIdxCount, pcPic);
609
      }
610
      pcPic->setCurrSliceIdx(sliceIdxCount);
611
      m_pcSliceEncoder->setSliceIdx(sliceIdxCount);
612

    
613
      pcSlice->setRPS(pcPic->getSlice(0)->getRPS());
614
      pcSlice->setRPSidx(pcPic->getSlice(0)->getRPSidx());
615

    
616
      for ( UInt ui = 0 ; ui < numSubstreams; ui++ )
617
      {
618
        substreamsOut[ui].clear();
619
      }
620

    
621
      m_pcEntropyCoder->setEntropyCoder   ( m_pcCavlcCoder );
622
      m_pcEntropyCoder->resetEntropy      ( pcSlice );
623
      /* start slice NALunit */
624
      OutputNALUnit nalu( pcSlice->getNalUnitType(), pcSlice->getTLayer() );
625
      m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream);
626

    
627
      pcSlice->setNoRaslOutputFlag(false);
628
      if (pcSlice->isIRAP())
629
      {
630
        if (pcSlice->getNalUnitType() >= NAL_UNIT_CODED_SLICE_BLA_W_LP && pcSlice->getNalUnitType() <= NAL_UNIT_CODED_SLICE_IDR_N_LP)
631
        {
632
          pcSlice->setNoRaslOutputFlag(true);
633
        }
634
        //the inference for NoOutputPriorPicsFlag
635
        // KJS: This cannot happen at the encoder
636
        if (!m_bFirst && pcSlice->isIRAP() && pcSlice->getNoRaslOutputFlag())
637
        {
638
          if (pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA)
639
          {
640
            pcSlice->setNoOutputPriorPicsFlag(true);
641
          }
642
        }
643
      }
644

    
645
      pcSlice->setEncCABACTableIdx(m_pcSliceEncoder->getEncCABACTableIdx());
646

    
647
      tmpBitsBeforeWriting = m_pcEntropyCoder->getNumberOfWrittenBits();
648
      m_pcEntropyCoder->encodeSliceHeader(pcSlice);
649
      actualHeadBits += ( m_pcEntropyCoder->getNumberOfWrittenBits() - tmpBitsBeforeWriting );
650

    
651
      pcSlice->setFinalized(true);
652

    
653
      pcSlice->clearSubstreamSizes(  );
654
      {
655
        UInt numBinsCoded = 0;
656
        m_pcSliceEncoder->encodeSlice(pcPic, &(substreamsOut[0]), numBinsCoded);
657
        binCountsInNalUnits+=numBinsCoded;
658
      }
659

    
660
      {
661
        // Construct the final bitstream by concatenating substreams.
662
        // The final bitstream is either nalu.m_Bitstream or pcBitstreamRedirect;
663
        // Complete the slice header info.
664
        m_pcEntropyCoder->setEntropyCoder   ( m_pcCavlcCoder );
665
        m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream);
666
        m_pcEntropyCoder->encodeTilesWPPEntryPoint( pcSlice );
667

    
668
        // Append substreams...
669
        TComOutputBitstream *pcOut = pcBitstreamRedirect;
670
        const Int numZeroSubstreamsAtStartOfSlice  = pcPic->getSubstreamForCtuAddr(pcSlice->getSliceSegmentCurStartCtuTsAddr(), false, pcSlice);
671
        const Int numSubstreamsToCode  = pcSlice->getNumberOfSubstreamSizes()+1;
672
        for ( UInt ui = 0 ; ui < numSubstreamsToCode; ui++ )
673
        {
674
          pcOut->addSubstream(&(substreamsOut[ui+numZeroSubstreamsAtStartOfSlice]));
675
        }
676
      }
677

    
678
      // If current NALU is the first NALU of slice (containing slice header) and more NALUs exist (due to multiple dependent slices) then buffer it.
679
      // 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.
680
      Bool bNALUAlignedWrittenToList    = false; // used to ensure current NALU is not written more than once to the NALU list.
681
      xAttachSliceDataToNalUnit(nalu, pcBitstreamRedirect);
682
      accessUnit.push_back(new NALUnitEBSP(nalu));
683
      actualTotalBits += UInt(accessUnit.back()->m_nalUnitData.str().size()) * 8;
684
      numBytesInVclNalUnits += (std::size_t)(accessUnit.back()->m_nalUnitData.str().size());
685
      bNALUAlignedWrittenToList = true;
686

    
687
      if (!bNALUAlignedWrittenToList)
688
      {
689
        nalu.m_Bitstream.writeAlignZero();
690
        accessUnit.push_back(new NALUnitEBSP(nalu));
691
      }
692

    
693
      if( ( m_pcCfg->getPictureTimingSEIEnabled() || m_pcCfg->getDecodingUnitInfoSEIEnabled() ) &&
694
          ( pcSlice->getSPS()->getVuiParametersPresentFlag() ) &&
695
          ( ( pcSlice->getSPS()->getVuiParameters()->getHrdParameters()->getNalHrdParametersPresentFlag() )
696
         || ( pcSlice->getSPS()->getVuiParameters()->getHrdParameters()->getVclHrdParametersPresentFlag() ) ) &&
697
          ( pcSlice->getSPS()->getVuiParameters()->getHrdParameters()->getSubPicCpbParamsPresentFlag() ) )
698
      {
699
          UInt numNalus = 0;
700
        UInt numRBSPBytes = 0;
701
        for (AccessUnit::const_iterator it = accessUnit.begin(); it != accessUnit.end(); it++)
702
        {
703
          numRBSPBytes += UInt((*it)->m_nalUnitData.str().size());
704
          numNalus ++;
705
        }
706
        duData.push_back(DUData());
707
        duData.back().accumBitsDU = ( numRBSPBytes << 3 );
708
        duData.back().accumNalsDU = numNalus;
709
      }
710
    } // end iteration over slices
711

    
712
    // cabac_zero_words processing
713
    cabac_zero_word_padding(pcSlice, pcPic, binCountsInNalUnits, numBytesInVclNalUnits, accessUnit.back()->m_nalUnitData, m_pcCfg->getCabacZeroWordPaddingEnabled());
714

    
715
    pcPic->compressMotion();
716

    
717
    //-- For time output for each slice
718
    Double dEncTime = (Double)(clock()-iBeforeTime) / CLOCKS_PER_SEC;
719

    
720
    std::string digestStr;
721
    if (m_pcCfg->getDecodedPictureHashSEIType()!=HASHTYPE_NONE)
722
    {
723
      SEIDecodedPictureHash *decodedPictureHashSei = new SEIDecodedPictureHash();
724
      m_seiEncoder.initDecodedPictureHashSEI(decodedPictureHashSei, pcPic, digestStr, pcSlice->getSPS()->getBitDepths());
725
      trailingSeiMessages.push_back(decodedPictureHashSei);
726
    }
727

    
728
    m_pcCfg->setEncodedFlag(iGOPid, true);
729

    
730
    Double PSNR_Y;
731
    xCalculateAddPSNRs( isField, isTff, iGOPid, pcPic, accessUnit, rcListPic, dEncTime, snr_conversion, printFrameMSE, &PSNR_Y );
732
    
733
    // Only produce the Green Metadata SEI message with the last picture.
734
    if( m_pcCfg->getSEIGreenMetadataInfoSEIEnable() && pcSlice->getPOC() == ( m_pcCfg->getFramesToBeEncoded() - 1 )  )
735
    {
736
      SEIGreenMetadataInfo *seiGreenMetadataInfo = new SEIGreenMetadataInfo;
737
      m_seiEncoder.initSEIGreenMetadataInfo(seiGreenMetadataInfo, (UInt)(PSNR_Y * 100 + 0.5));
738
      trailingSeiMessages.push_back(seiGreenMetadataInfo);
739
    }
740
    
741
    xWriteTrailingSEIMessages(trailingSeiMessages, accessUnit, pcSlice->getTLayer(), pcSlice->getSPS());
742
    
743
    printHash(m_pcCfg->getDecodedPictureHashSEIType(), digestStr);
744

    
745
    if ( m_pcCfg->getUseRateCtrl() )
746
    {
747
      Double avgQP     = m_pcRateCtrl->getRCPic()->calAverageQP();
748
      Double avgLambda = m_pcRateCtrl->getRCPic()->calAverageLambda();
749
      if ( avgLambda < 0.0 )
750
      {
751
        avgLambda = lambda;
752
      }
753

    
754
      m_pcRateCtrl->getRCPic()->updateAfterPicture( actualHeadBits, actualTotalBits, avgQP, avgLambda, pcSlice->getSliceType());
755
      m_pcRateCtrl->getRCPic()->addToPictureLsit( m_pcRateCtrl->getPicList() );
756

    
757
      m_pcRateCtrl->getRCSeq()->updateAfterPic( actualTotalBits );
758
      if ( pcSlice->getSliceType() != I_SLICE )
759
      {
760
        m_pcRateCtrl->getRCGOP()->updateAfterPicture( actualTotalBits );
761
      }
762
      else    // for intra picture, the estimated bits are used to update the current status in the GOP
763
      {
764
        m_pcRateCtrl->getRCGOP()->updateAfterPicture( estimatedBits );
765
      }
766
      if (m_pcRateCtrl->getCpbSaturationEnabled())
767
      {
768
        m_pcRateCtrl->updateCpbState(actualTotalBits);
769
        printf(" [CPB %6d bits]", m_pcRateCtrl->getCpbState());
770
      }
771
    }
772

    
773
    xCreatePictureTimingSEI(m_pcCfg->getEfficientFieldIRAPEnabled()?effFieldIRAPMap.GetIRAPGOPid():0, leadingSeiMessages, nestedSeiMessages, duInfoSeiMessages, pcSlice, isField, duData);
774
    if (m_pcCfg->getScalableNestingSEIEnabled())
775
    {
776
      xCreateScalableNestingSEI (leadingSeiMessages, nestedSeiMessages);
777
    }
778
    xWriteLeadingSEIMessages(leadingSeiMessages, duInfoSeiMessages, accessUnit, pcSlice->getTLayer(), pcSlice->getSPS(), duData);
779
    xWriteDuSEIMessages(duInfoSeiMessages, accessUnit, pcSlice->getTLayer(), pcSlice->getSPS(), duData);
780

    
781
    pcPic->getPicYuvRec()->copyToPic(pcPicYuvRecOut);
782

    
783
    pcPic->setReconMark   ( true );
784
    m_bFirst = false;
785
    m_iNumPicCoded++;
786
    m_totalCoded ++;
787
    /* logging: insert a newline at end of picture period */
788
    printf("\n");
789
    fflush(stdout);
790

    
791
    if (m_pcCfg->getEfficientFieldIRAPEnabled())
792
    {
793
      iGOPid=effFieldIRAPMap.restoreGOPid(iGOPid);
794
    }
795
#if REDUCED_ENCODER_MEMORY
796

    
797
    pcPic->releaseReconstructionIntermediateData();
798
    if (!isField) // don't release the source data for field-coding because the fields are dealt with in pairs. // TODO: release source data for interlace simulations.
799
    {
800
      pcPic->releaseEncoderSourceImageData();
801
    }
802

    
803
#endif
804
  } // iGOPid-loop
805

    
806
  delete pcBitstreamRedirect;
807

    
808
  assert ( (m_iNumPicCoded == iNumPicRcvd) );
809
}