Coverage Report

Created: 2026-05-30 06:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/vvenc/source/Lib/EncoderLib/EncLib.cpp
Line
Count
Source
1
/* -----------------------------------------------------------------------------
2
The copyright in this software is being made available under the Clear BSD
3
License, included below. No patent rights, trademark rights and/or 
4
other Intellectual Property Rights other than the copyrights concerning 
5
the Software are granted under this license.
6
7
The Clear BSD License
8
9
Copyright (c) 2019-2026, Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. & The VVenC Authors.
10
All rights reserved.
11
12
Redistribution and use in source and binary forms, with or without modification,
13
are permitted (subject to the limitations in the disclaimer below) provided that
14
the following conditions are met:
15
16
     * Redistributions of source code must retain the above copyright notice,
17
     this list of conditions and the following disclaimer.
18
19
     * Redistributions in binary form must reproduce the above copyright
20
     notice, this list of conditions and the following disclaimer in the
21
     documentation and/or other materials provided with the distribution.
22
23
     * Neither the name of the copyright holder nor the names of its
24
     contributors may be used to endorse or promote products derived from this
25
     software without specific prior written permission.
26
27
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
28
THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
29
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
31
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
32
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
33
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
34
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
35
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
36
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38
POSSIBILITY OF SUCH DAMAGE.
39
40
41
------------------------------------------------------------------------------------------- */
42
43
44
/** \file     EncLib.cpp
45
    \brief    encoder class
46
*/
47
48
#include "EncLib.h"
49
#include "CommonLib/Picture.h"
50
#include "CommonLib/CommonDef.h"
51
#include "CommonLib/TimeProfiler.h"
52
#include "CommonLib/Rom.h"
53
#include "CommonLib/MCTF.h"
54
#include "Utilities/NoMallocThreadPool.h"
55
#include "Utilities/MsgLog.h"
56
#include "EncStage.h"
57
#include "PreProcess.h"
58
#include "EncGOP.h"
59
#include "CommonLib/x86/CommonDefX86.h"
60
61
//! \ingroup EncoderLib
62
//! \{
63
64
namespace vvenc {
65
66
67
// ====================================================================================================================
68
// Constructor / destructor / create / destroy
69
// ====================================================================================================================
70
71
EncLib::EncLib( MsgLog& logger )
72
1.29k
  : msg             ( logger )
73
1.29k
  , m_recYuvBufFunc  ( nullptr )
74
1.29k
  , m_recYuvBufCtx   ( nullptr )
75
1.29k
  , m_encCfg         ()
76
1.29k
  , m_orgCfg         ()
77
1.29k
  , m_firstPassCfg   ()
78
1.29k
  , m_rateCtrl       ( nullptr )
79
1.29k
  , m_preProcess     ( nullptr )
80
1.29k
  , m_MCTF           ( nullptr )
81
1.29k
  , m_preEncoder     ( nullptr )
82
1.29k
  , m_gopEncoder     ( nullptr )
83
1.29k
  , m_threadPool     ( nullptr )
84
1.29k
  , m_picsRcvd       ( 0 )
85
1.29k
  , m_passInitialized( -1 )
86
1.29k
  , m_maxNumPicShared( MAX_INT )
87
1.29k
  , m_accessUnitOutputStarted( false )
88
1.29k
{
89
1.29k
}
90
91
EncLib::~EncLib()
92
1.29k
{
93
1.29k
  delete m_rateCtrl;
94
1.29k
  m_rateCtrl = nullptr;
95
1.29k
}
96
97
void EncLib::setRecYUVBufferCallback( void* ctx, vvencRecYUVBufferCallback func )
98
0
{
99
0
  m_recYuvBufCtx  = ctx;
100
0
  m_recYuvBufFunc = func;
101
0
  if( m_rateCtrl && m_rateCtrl->rcIsFinalPass && m_gopEncoder )
102
0
  {
103
0
    m_gopEncoder->setRecYUVBufferCallback( m_recYuvBufCtx, m_recYuvBufFunc );
104
0
  }
105
0
}
106
107
void EncLib::initEncoderLib( const vvenc_config& encCfg )
108
1.29k
{
109
  // copy config parameter
110
1.29k
  const_cast<VVEncCfg&>(m_encCfg) = encCfg;
111
112
#if defined( REAL_TARGET_X86 ) && defined( _MSC_VER ) && _MSC_VER >= 1938 && _MSC_VER < 1939
113
  if( read_x86_extension_flags() >= x86_simd::AVX2 )
114
  {
115
    msg.log( VVENC_WARNING, "WARNING: MSVC version 17.8 produces invalid AVX2 code, partially disabling AVX2!\n" );
116
  }
117
118
#endif
119
  // setup modified configs for rate control
120
1.29k
  if( m_encCfg.m_RCNumPasses > 1 || m_encCfg.m_LookAhead )
121
0
  {
122
0
    xInitRCCfg();
123
0
  }
124
125
  // initialize pass
126
1.29k
  initPass( 0, nullptr );
127
128
#if ENABLE_TRACING
129
  g_trace_ctx = tracing_init( m_encCfg.m_traceFile, m_encCfg.m_traceRule, msg );
130
  if( g_trace_ctx && m_encCfg.m_listTracingChannels )
131
  {
132
    std::string sChannelsList;
133
    g_trace_ctx->getChannelsList( sChannelsList );
134
    msg.log( VVENC_INFO, "\n Using tracing channels:\n\n%s\n", sChannelsList.c_str() );
135
  }
136
#endif
137
138
#if ENABLE_TIME_PROFILING
139
  if( g_timeProfiler )
140
  {
141
    delete g_timeProfiler;
142
  }
143
  g_timeProfiler = timeProfilerCreate( encCfg );
144
#endif
145
1.29k
}
146
147
void EncLib::uninitEncoderLib()
148
1.29k
{
149
#if ENABLE_TRACING
150
  if( g_trace_ctx )
151
  {
152
    tracing_uninit( g_trace_ctx );
153
  }
154
#endif
155
156
#if ENABLE_CU_MODE_COUNTERS
157
  std::cout << std::endl;
158
  std::cout << "CU Modes statistic across picture types and temporal levels (0:Intra, >0:Inter, luma only)" << std::endl;
159
  for( size_t j = 0; j < g_cuCounters1D.getNumCntTypes(); j++ )
160
  {
161
    for( size_t i = 0; i < g_cuCounters1D.getDimHor() - 1; i++ )
162
    {
163
      g_cuCounters1D[j][0][g_cuCounters1D.getDimHor() - 1] += g_cuCounters1D[j][0][i];
164
    }
165
  }
166
  StatCounters::report2D( std::cout, g_cuCounters1D, false, true, false, true, true, CU_MODES_TESTED );
167
168
  std::cout << std::endl;
169
  std::cout << "CU Modes statistic across block-shapes (Non-I-Slices, luma only)" << std::endl;
170
  StatCounters::report2D( std::cout, g_cuCounters2D, true, true, false, true, true, CU_MODES_TESTED );
171
#endif
172
173
#if ENABLE_TIME_PROFILING
174
#if ENABLE_TIME_PROFILING_MT_MODE
175
  if( m_threadPool )
176
  {
177
    for(auto& p : m_threadPool->getProfilers())
178
    {
179
      *g_timeProfiler += *p;
180
    }
181
  }
182
#endif
183
  timeProfilerResults( g_timeProfiler );
184
  delete g_timeProfiler;
185
  g_timeProfiler = nullptr;
186
#endif
187
1.29k
  xUninitLib();
188
1.29k
}
189
190
void EncLib::initPass( int pass, const char* statsFName )
191
1.29k
{
192
1.29k
  CHECK( m_passInitialized != pass && m_passInitialized + 1 != pass, "initialization of passes only in successive order possible" );
193
194
1.29k
  if( m_rateCtrl == nullptr )
195
1.29k
  {
196
1.29k
    m_rateCtrl = new RateCtrl(msg);
197
1.29k
  }
198
199
1.29k
  m_rateCtrl->setRCPass( m_encCfg, pass, statsFName );
200
201
1.29k
  if( m_passInitialized + 1 != pass )
202
0
  {
203
0
    return;
204
0
  }
205
206
  // reset
207
1.29k
  xUninitLib();
208
209
  // enable encoder config based on rate control pass
210
1.29k
  if( m_encCfg.m_RCNumPasses > 1 || ( m_encCfg.m_LookAhead && m_orgCfg.m_RCTargetBitrate > 0 ) )
211
0
  {
212
0
    if( !m_rateCtrl->rcIsFinalPass )
213
0
    {
214
      // set encoder config for 1st rate control pass
215
0
      const_cast<VVEncCfg&>(m_encCfg) = m_firstPassCfg;
216
0
    }
217
0
    else
218
0
    {
219
      // restore encoder config for final 2nd RC pass
220
0
      const_cast<VVEncCfg&>(m_encCfg) = m_orgCfg;
221
0
      m_rateCtrl->init( m_encCfg );
222
0
      const_cast<VVEncCfg&>(m_encCfg).m_QP = m_rateCtrl->getBaseQP();
223
0
    }
224
0
    if( m_encCfg.m_RCTargetBitrate > 0 && !m_encCfg.m_LookAhead )
225
0
    {
226
0
      m_rateCtrl->processFirstPassData( false );
227
0
    }
228
0
  }
229
1.29k
  else if( m_encCfg.m_usePerceptQPA && m_encCfg.m_LookAhead )
230
0
  {
231
0
    m_rateCtrl->init( m_encCfg );
232
0
  }
233
234
  // thread pool
235
1.29k
  if( m_encCfg.m_numThreads > 0 )
236
1.29k
  {
237
1.29k
    m_threadPool = new NoMallocThreadPool( m_encCfg.m_numThreads, "EncSliceThreadPool", &m_encCfg );
238
1.29k
  }
239
1.29k
  m_maxNumPicShared = 0;
240
241
  // pre processing
242
1.29k
  m_preProcess = new PreProcess( msg );
243
1.29k
  m_preProcess->initStage( m_encCfg, 1, -m_encCfg.m_leadFrames, true, true, false );
244
1.29k
  m_preProcess->init( m_encCfg, m_rateCtrl->rcIsFinalPass );
245
1.29k
  m_encStages.push_back( m_preProcess );
246
1.29k
  m_maxNumPicShared += 1;
247
248
  // MCTF
249
1.29k
  if( m_encCfg.m_vvencMCTF.MCTF || m_encCfg.m_usePerceptQPA )
250
1.29k
  {
251
1.29k
    m_MCTF = new MCTF();
252
1.29k
    const int leadFrames   = std::min( VVENC_MCTF_RANGE, m_encCfg.m_leadFrames );
253
1.29k
    const int minQueueSize = m_encCfg.m_vvencMCTF.MCTFFutureReference ? ( leadFrames + 1 + VVENC_MCTF_RANGE ) : ( leadFrames + 1 );
254
1.29k
    m_MCTF->initStage( m_encCfg, minQueueSize, -leadFrames, true, true, false );
255
1.29k
    m_MCTF->init( m_encCfg, m_rateCtrl->rcIsFinalPass, m_threadPool );
256
1.29k
    m_encStages.push_back( m_MCTF );
257
1.29k
    m_maxNumPicShared += minQueueSize - leadFrames;
258
1.29k
  }
259
260
  // pre analysis encoder
261
1.29k
  if( m_encCfg.m_LookAhead )
262
0
  {
263
0
    m_preEncoder = new EncGOP( msg );
264
0
    const int minQueueSize = m_firstPassCfg.m_GOPSize + 1;
265
0
    m_preEncoder->initStage( m_firstPassCfg, minQueueSize, 0, false, false, false );
266
0
    m_preEncoder->init( m_firstPassCfg, m_preProcess->getGOPCfg(), *m_rateCtrl, m_threadPool, true );
267
0
    m_encStages.push_back( m_preEncoder );
268
0
    m_maxNumPicShared += minQueueSize;
269
0
  }
270
271
  // gop encoder
272
1.29k
  m_gopEncoder = new EncGOP( msg );
273
1.29k
  const int minQueueSize = m_encCfg.m_GOPSize + 1;
274
1.29k
  m_gopEncoder->initStage( m_encCfg, minQueueSize, 0, false, false, m_encCfg.m_stageParallelProc );
275
1.29k
  m_gopEncoder->init( m_encCfg, m_preProcess->getGOPCfg(), *m_rateCtrl, m_threadPool, false );
276
1.29k
  m_encStages.push_back( m_gopEncoder );
277
1.29k
  m_maxNumPicShared += minQueueSize;
278
279
  // additional pictures due to structural delay
280
1.29k
  m_maxNumPicShared += m_preProcess->getGOPCfg()->getNumReorderPics()[ m_encCfg.m_maxTLayer ];
281
1.29k
  m_maxNumPicShared += 3;
282
  // increase number of picture buffers for GOP parallel processing
283
1.29k
  m_maxNumPicShared += m_encCfg.m_numParallelGOPs ? (m_encCfg.m_GOPSize + 1) * m_encCfg.m_numParallelGOPs: 0;
284
285
1.29k
  if( m_rateCtrl->rcIsFinalPass )
286
1.29k
  {
287
1.29k
    m_gopEncoder->setRecYUVBufferCallback( m_recYuvBufCtx, m_recYuvBufFunc );
288
1.29k
  }
289
290
  // link encoder stages
291
3.89k
  for( int i = 0; i < (int)m_encStages.size() - 1; i++ )
292
2.59k
  {
293
2.59k
    m_encStages[ i ]->linkNextStage( m_encStages[ i + 1 ] );
294
2.59k
  }
295
296
1.29k
  m_picsRcvd                = -m_encCfg.m_leadFrames;
297
1.29k
  m_accessUnitOutputStarted = false;
298
1.29k
  m_passInitialized         = pass;
299
1.29k
}
300
301
void EncLib::xUninitLib()
302
2.59k
{
303
  // make sure all processing threads are stopped before releasing data
304
2.59k
  if( m_threadPool )
305
1.29k
  {
306
1.29k
    m_threadPool->shutdown( true );
307
1.29k
  }
308
309
  // sub modules
310
2.59k
  if( m_rateCtrl != nullptr )
311
2.59k
  {
312
2.59k
    m_rateCtrl->destroy();
313
2.59k
  }
314
2.59k
  if( m_preProcess )
315
1.29k
  {
316
1.29k
    delete m_preProcess;
317
1.29k
    m_preProcess = nullptr;
318
1.29k
  }
319
2.59k
  if( m_MCTF )
320
1.29k
  {
321
1.29k
    delete m_MCTF;
322
1.29k
    m_MCTF = nullptr;
323
1.29k
  }
324
2.59k
  if( m_preEncoder )
325
0
  {
326
0
    delete m_preEncoder;
327
0
    m_preEncoder = nullptr;
328
0
  }
329
2.59k
  if( m_gopEncoder )
330
1.29k
  {
331
1.29k
    delete m_gopEncoder;
332
1.29k
    m_gopEncoder = nullptr;
333
1.29k
  }
334
2.59k
  m_encStages.clear();
335
336
2.59k
  for( auto picShared : m_picSharedList )
337
1.29k
  {
338
1.29k
    delete picShared;
339
1.29k
  }
340
2.59k
  m_picSharedList.clear();
341
342
  // thread pool
343
2.59k
  if( m_threadPool )
344
1.29k
  {
345
1.29k
    delete m_threadPool;
346
1.29k
    m_threadPool = nullptr;
347
1.29k
  }
348
2.59k
}
349
350
void EncLib::xInitRCCfg()
351
0
{
352
  // backup original configuration
353
0
  const_cast<VVEncCfg&>(m_orgCfg) = m_encCfg;
354
355
  // initialize first pass configuration
356
0
  m_firstPassCfg = m_encCfg;
357
0
  vvenc_init_preset( &m_firstPassCfg, vvencPresetMode::VVENC_FIRSTPASS );
358
359
  // fixed-QP encoding in first rate control pass
360
0
  m_firstPassCfg.m_RCTargetBitrate = 0;
361
0
  if( m_firstPassCfg.m_FirstPassMode > 2 )
362
0
  {
363
0
    m_firstPassCfg.m_SourceWidth  = ( m_encCfg.m_SourceWidth  >> 1 ) & ( ~7 );
364
0
    m_firstPassCfg.m_SourceHeight = ( m_encCfg.m_SourceHeight >> 1 ) & ( ~7 );
365
0
    m_firstPassCfg.m_PadSourceWidth  = m_firstPassCfg.m_SourceWidth;
366
0
    m_firstPassCfg.m_PadSourceHeight = m_firstPassCfg.m_SourceHeight;
367
0
#if TILES_IFP_2PRC_HOTFIX
368
0
    if( m_firstPassCfg.m_ifp && (m_firstPassCfg.m_numTileCols > 1 || m_firstPassCfg.m_numTileRows > 1) )
369
0
    {
370
      // due to sub-sampling, expected different tile configuration in cfg (m_tileRowHeight[], m_tileColumnWidth[])
371
      // currently, disable auto tiles for the first pass
372
0
      m_firstPassCfg.m_numTileCols = 1;
373
0
      m_firstPassCfg.m_numTileRows = 1;
374
0
      m_firstPassCfg.m_picPartitionFlag = false;
375
0
    }
376
0
#endif
377
0
  }
378
379
  // preserve some settings
380
0
  m_firstPassCfg.m_intraQPOffset   = m_encCfg.m_intraQPOffset;
381
0
  m_firstPassCfg.m_GOPQPA          = m_encCfg.m_GOPQPA;
382
0
  if( m_firstPassCfg.m_usePerceptQPA && ( m_firstPassCfg.m_QP <= MAX_QP_PERCEPT_QPA || m_firstPassCfg.m_framesToBeEncoded == 1 ) )
383
0
  {
384
0
    m_firstPassCfg.m_CTUSize       = m_encCfg.m_CTUSize;
385
0
  }
386
0
  m_firstPassCfg.m_vvencMCTF.MCTF  = m_encCfg.m_vvencMCTF.MCTF;
387
0
  m_firstPassCfg.m_IBCMode         = m_encCfg.m_IBCMode;
388
0
  m_firstPassCfg.m_bimCtuSize      = m_encCfg.m_CTUSize;
389
0
  m_firstPassCfg.m_log2MinCodingBlockSize = m_encCfg.m_log2MinCodingBlockSize;
390
391
  // set Inter block size
392
0
  if( m_firstPassCfg.m_FirstPassMode > 0 )
393
0
  {
394
0
    m_firstPassCfg.m_MinQT[ 1 ] = m_firstPassCfg.m_MaxQT[ 1 ] = ( std::min( m_firstPassCfg.m_SourceWidth, m_firstPassCfg.m_SourceHeight ) < 720 ? 32 : 64 );
395
0
  }
396
397
  // clear MaxCuDQPSubdiv
398
0
  if( m_firstPassCfg.m_CTUSize < 128 && std::min( m_firstPassCfg.m_SourceWidth, m_firstPassCfg.m_SourceHeight ) >= 720 )
399
0
  {
400
0
    m_firstPassCfg.m_cuQpDeltaSubdiv = 0;
401
0
  }
402
0
}
403
404
// ====================================================================================================================
405
// Public member functions
406
// ====================================================================================================================
407
408
// The current I/O work flow consists of three main parts:
409
//   1. At the beginning, the encoder can consume input YUV buffers without an output.
410
//   2. After the first encoded picture/access unit is output, on each next call: one yuv-buffer IN / one encoded access unit (AU) OUT.
411
//      Hence, in stage-parallel mode, we must wait until next encoded picture (AU) is going to be output
412
//   3. When no more input is available, the top level goes into flushing mode: nullptr IN / one encoded access unit (AU) OUT. 
413
//      The encoder flushes the encoded AUs until the queues are empty.
414
415
void EncLib::encodePicture( bool flush, const vvencYUVBuffer* yuvInBuf, AccessUnitList& au, bool& isQueueEmpty )
416
2.59k
{
417
2.59k
  PROFILER_ACCUM_AND_START_NEW_SET( 1, g_timeProfiler, P_TOP_LEVEL );
418
419
2.59k
  CHECK( yuvInBuf == nullptr && ! flush, "no input picture given" );
420
421
  // clear output access unit
422
2.59k
  au.clearAu();
423
424
  // NOTE regarding the stage parallel processing
425
  // The next input yuv-buffer must be passed to the encoding process (1.Stage).
426
  // The following should be considered:
427
  //   1. The final stage is non-blocking, so it doesn't wait until picture is reconstructed.
428
  //   2. Generally, the stages have different throughput; last stage is the slowest.
429
  //   3. The number of picture-units required for the input yuv-buffers is limited.
430
  //   4. Due to chunk-mode and non-blockiness, it's possible that we can run out of picture-units.
431
  //   5. Then we have to wait for the next available picture-unit, so the input frame can be passed to the 1.stage.
432
433
2.59k
  PicShared* picShared = nullptr;
434
2.59k
  bool inputPending    = ( yuvInBuf != nullptr );
435
3.89k
  while( true )
436
3.89k
  {
437
    // send new YUV input buffer to first encoder stage
438
3.89k
    if( inputPending )
439
1.29k
    {
440
1.29k
      picShared = xGetFreePicShared();
441
1.29k
      if( picShared )
442
1.29k
      {
443
1.29k
        picShared->reuse( m_picsRcvd, yuvInBuf );
444
1.29k
        m_encStages[ 0 ]->addPicSorted( picShared, flush );
445
1.29k
        m_picsRcvd  += 1;
446
1.29k
        inputPending = false;
447
1.29k
      }
448
1.29k
    }
449
450
3.89k
    PROFILER_EXT_UPDATE( g_timeProfiler, P_TOP_LEVEL, 0 );
451
452
    // trigger stages
453
3.89k
    isQueueEmpty = m_picsRcvd > 0 || ( m_picsRcvd <= 0 && flush );
454
3.89k
    for( auto encStage : m_encStages )
455
11.6k
    {
456
11.6k
      encStage->runStage( flush, au );
457
11.6k
      isQueueEmpty &= encStage->isStageDone();
458
11.6k
    }
459
460
3.89k
    if( !au.empty() )
461
1.29k
    {
462
1.29k
      m_AuList.push_back( au );
463
464
1.29k
      au.detachNalUnitList();
465
1.29k
      au.clearAu();
466
      // NOTE: delay AU output in stage parallel mode only
467
1.29k
      if( !m_accessUnitOutputStarted )
468
1.29k
        m_accessUnitOutputStarted = !m_encCfg.m_stageParallelProc || m_AuList.size() > 4 || flush;
469
1.29k
    }
470
471
    // wait if input picture hasn't been stored yet or if encoding is running and no new output access unit has been encoded
472
3.89k
    bool waitAndStay = inputPending || ( m_rateCtrl->rcIsFinalPass && m_AuList.empty() && ! isQueueEmpty && ( m_accessUnitOutputStarted || flush ) );
473
3.89k
    if( ! waitAndStay )
474
2.59k
    {
475
2.59k
      break;
476
2.59k
    }
477
478
1.29k
    if( m_encCfg.m_stageParallelProc )
479
1.29k
    {
480
1.29k
      for( auto encStage : m_encStages )
481
3.89k
      {
482
3.89k
        if( encStage->isNonBlocking() )
483
1.29k
          encStage->waitForFreeEncoders();
484
3.89k
      }
485
1.29k
    }
486
1.29k
  }
487
488
  // check if we have an AU to output
489
2.59k
  if( !m_AuList.empty() && m_accessUnitOutputStarted )
490
1.29k
  {
491
1.29k
    au = m_AuList.front();
492
1.29k
    m_AuList.front().detachNalUnitList();
493
1.29k
    m_AuList.pop_front();
494
1.29k
  }
495
496
  // reset output access unit, if not final pass
497
2.59k
  if( ! m_rateCtrl->rcIsFinalPass )
498
0
  {
499
0
    au.clearAu();
500
0
  }
501
502
  // finally, ensure that the whole queue is empty
503
2.59k
  isQueueEmpty &= m_AuList.empty();
504
2.59k
}
505
506
void EncLib::printSummary()
507
0
{
508
0
  if( m_gopEncoder )
509
0
  {
510
0
    m_gopEncoder->printOutSummary( m_encCfg.m_printMSEBasedSequencePSNR, m_encCfg.m_printSequenceMSE, m_encCfg.m_printHexPsnr );
511
0
  }
512
0
}
513
514
void EncLib::getParameterSets( AccessUnitList& au )
515
0
{
516
0
  if( m_gopEncoder )
517
0
  {
518
0
    m_gopEncoder->getParameterSets( au );
519
0
  }
520
0
}
521
522
int EncLib::getCurPass() const
523
0
{
524
0
  return m_passInitialized;
525
0
}
526
527
// ====================================================================================================================
528
// Protected member functions
529
// ====================================================================================================================
530
531
PicShared* EncLib::xGetFreePicShared()
532
1.29k
{
533
1.29k
  PicShared* picShared = nullptr;
534
1.29k
  for( auto itr : m_picSharedList )
535
0
  {
536
0
    if( ! itr->isUsed() )
537
0
    {
538
0
      picShared = itr;
539
0
      break;
540
0
    }
541
0
  }
542
543
1.29k
  if( ! picShared )
544
1.29k
  {
545
1.29k
    if( m_encCfg.m_stageParallelProc && ( m_picSharedList.size() >= m_maxNumPicShared ) )
546
0
      return nullptr;
547
548
1.29k
    picShared = new PicShared();
549
1.29k
    picShared->create( m_encCfg.m_framesToBeEncoded, m_encCfg.m_internChromaFormat, Size( m_encCfg.m_PadSourceWidth, m_encCfg.m_PadSourceHeight ), m_encCfg.m_vvencMCTF.MCTF || m_encCfg.m_usePerceptQPA );
550
1.29k
    m_picSharedList.push_back( picShared );
551
1.29k
  }
552
1.29k
  CHECK( picShared == nullptr, "out of memory" );
553
554
1.29k
  return picShared;
555
1.29k
}
556
557
} // namespace vvenc
558
559
//! \}