Coverage Report

Created: 2022-08-24 06:17

/src/x265/source/encoder/encoder.cpp
Line
Count
Source (jump to first uncovered line)
1
/*****************************************************************************
2
 * Copyright (C) 2013-2020 MulticoreWare, Inc
3
 *
4
 * Authors: Steve Borho <steve@borho.org>
5
 *          Min Chen <chenm003@163.com>
6
 *          Praveen Kumar Tiwari <praveen@multicorewareinc.com>
7
 *          Aruna Matheswaran <aruna@multicorewareinc.com>
8
 *
9
 * This program is free software; you can redistribute it and/or modify
10
 * it under the terms of the GNU General Public License as published by
11
 * the Free Software Foundation; either version 2 of the License, or
12
 * (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU General Public License
20
 * along with this program; if not, write to the Free Software
21
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
22
 *
23
 * This program is also available under a commercial proprietary license.
24
 * For more information, contact us at license @ x265.com.
25
 *****************************************************************************/
26
27
#include "common.h"
28
#include "primitives.h"
29
#include "threadpool.h"
30
#include "param.h"
31
#include "frame.h"
32
#include "framedata.h"
33
#include "picyuv.h"
34
35
#include "bitcost.h"
36
#include "encoder.h"
37
#include "slicetype.h"
38
#include "frameencoder.h"
39
#include "ratecontrol.h"
40
#include "dpb.h"
41
#include "nal.h"
42
43
#include "x265.h"
44
45
#if _MSC_VER
46
#pragma warning(disable: 4996) // POSIX functions are just fine, thanks
47
#endif
48
49
namespace X265_NS {
50
const char g_sliceTypeToChar[] = {'B', 'P', 'I'};
51
52
/* Dolby Vision profile specific settings */
53
typedef struct
54
{
55
    int bEmitHRDSEI;
56
    int bEnableVideoSignalTypePresentFlag;
57
    int bEnableColorDescriptionPresentFlag;
58
    int bEnableAccessUnitDelimiters;
59
    int bAnnexB;
60
61
    /* VUI parameters specific to Dolby Vision Profile */
62
    int videoFormat;
63
    int bEnableVideoFullRangeFlag;
64
    int transferCharacteristics;
65
    int colorPrimaries;
66
    int matrixCoeffs;
67
68
    int doviProfileId;
69
}DolbyVisionProfileSpec;
70
71
DolbyVisionProfileSpec dovi[] =
72
{
73
    { 1, 1, 1, 1, 1, 5, 1,  2, 2, 2, 50 },
74
    { 1, 1, 1, 1, 1, 5, 0, 16, 9, 9, 81 },
75
    { 1, 1, 1, 1, 1, 5, 0,  1, 1, 1, 82 }
76
};
77
}
78
79
/* Threshold for motion vection, based on expermental result.
80
 * TODO: come up an algorithm for adoptive threshold */
81
0
#define MVTHRESHOLD (10*10)
82
0
#define PU_2Nx2N 1
83
0
#define MAX_CHROMA_QP_OFFSET 12
84
0
#define CONF_OFFSET_BYTES (2 * sizeof(int))
85
static const char* defaultAnalysisFileName = "x265_analysis.dat";
86
87
using namespace X265_NS;
88
89
Encoder::Encoder()
90
0
{
91
0
    m_aborted = false;
92
0
    m_reconfigure = false;
93
0
    m_reconfigureRc = false;
94
0
    m_encodedFrameNum = 0;
95
0
    m_pocLast = -1;
96
0
    m_curEncoder = 0;
97
0
    m_numLumaWPFrames = 0;
98
0
    m_numChromaWPFrames = 0;
99
0
    m_numLumaWPBiFrames = 0;
100
0
    m_numChromaWPBiFrames = 0;
101
0
    m_lookahead = NULL;
102
0
    m_rateControl = NULL;
103
0
    m_dpb = NULL;
104
0
    m_exportedPic = NULL;
105
0
    m_numDelayedPic = 0;
106
0
    m_outputCount = 0;
107
0
    m_param = NULL;
108
0
    m_latestParam = NULL;
109
0
    m_threadPool = NULL;
110
0
    m_analysisFileIn = NULL;
111
0
    m_analysisFileOut = NULL;
112
0
    m_naluFile = NULL;
113
0
    m_offsetEmergency = NULL;
114
0
    m_iFrameNum = 0;
115
0
    m_iPPSQpMinus26 = 0;
116
0
    m_rpsInSpsCount = 0;
117
0
    m_cB = 1.0;
118
0
    m_cR = 1.0;
119
0
    for (int i = 0; i < X265_MAX_FRAME_THREADS; i++)
120
0
        m_frameEncoder[i] = NULL;
121
0
    for (uint32_t i = 0; i < DUP_BUFFER; i++)
122
0
        m_dupBuffer[i] = NULL;
123
0
    MotionEstimate::initScales();
124
125
#if ENABLE_HDR10_PLUS
126
    m_hdr10plus_api = hdr10plus_api_get();
127
    m_numCimInfo = 0;
128
    m_cim = NULL;
129
#endif
130
131
#if SVT_HEVC
132
    m_svtAppData = NULL;
133
#endif
134
0
    m_prevTonemapPayload.payload = NULL;
135
0
    m_startPoint = 0;
136
0
    m_saveCTUSize = 0;
137
0
    m_edgePic = NULL;
138
0
    m_edgeHistThreshold = 0;
139
0
    m_chromaHistThreshold = 0.0;
140
0
    m_scaledEdgeThreshold = 0.0;
141
0
    m_scaledChromaThreshold = 0.0;
142
0
    m_zoneIndex = 0;
143
0
}
144
145
inline char *strcatFilename(const char *input, const char *suffix)
146
0
{
147
0
    char *output = X265_MALLOC(char, strlen(input) + strlen(suffix) + 1);
148
0
    if (!output)
149
0
    {
150
0
        x265_log(NULL, X265_LOG_ERROR, "unable to allocate memory for filename\n");
151
0
        return NULL;
152
0
    }
153
0
    strcpy(output, input);
154
0
    strcat(output, suffix);
155
0
    return output;
156
0
}
157
158
void Encoder::create()
159
0
{
160
0
    if (!primitives.pu[0].sad)
161
0
    {
162
        // this should be an impossible condition when using our public API, and indicates a serious bug.
163
0
        x265_log(m_param, X265_LOG_ERROR, "Primitives must be initialized before encoder is created\n");
164
0
        abort();
165
0
    }
166
167
0
    x265_param* p = m_param;
168
169
0
    int rows = (p->sourceHeight + p->maxCUSize - 1) >> g_log2Size[p->maxCUSize];
170
0
    int cols = (p->sourceWidth  + p->maxCUSize - 1) >> g_log2Size[p->maxCUSize];
171
172
0
    if (m_param->bEnableFrameDuplication)
173
0
    {
174
0
        size_t framesize = 0;
175
0
        int pixelbytes = p->sourceBitDepth > 8 ? 2 : 1;
176
0
        for (int i = 0; i < x265_cli_csps[p->internalCsp].planes; i++)
177
0
        {
178
0
            int stride = (p->sourceWidth >> x265_cli_csps[p->internalCsp].width[i]) * pixelbytes;
179
0
            framesize += (stride * (p->sourceHeight >> x265_cli_csps[p->internalCsp].height[i]));
180
0
        }
181
182
        //Sets the picture structure and emits it in the picture timing SEI message
183
0
        m_param->pictureStructure = 0; 
184
185
0
        for (uint32_t i = 0; i < DUP_BUFFER; i++)
186
0
        {
187
0
            m_dupBuffer[i] = (AdaptiveFrameDuplication*)x265_malloc(sizeof(AdaptiveFrameDuplication));
188
0
            m_dupBuffer[i]->dupPic = NULL;
189
0
            m_dupBuffer[i]->dupPic = x265_picture_alloc();
190
0
            x265_picture_init(p, m_dupBuffer[i]->dupPic);
191
0
            m_dupBuffer[i]->dupPlane = NULL;
192
0
            m_dupBuffer[i]->dupPlane = X265_MALLOC(char, framesize);
193
0
            m_dupBuffer[i]->dupPic->planes[0] = m_dupBuffer[i]->dupPlane;
194
0
            m_dupBuffer[i]->bOccupied = false;
195
0
            m_dupBuffer[i]->bDup = false;
196
0
        }
197
198
0
        if (!(p->sourceBitDepth == 8 && p->internalBitDepth == 8))
199
0
        {
200
0
            int size = p->sourceWidth * p->sourceHeight;
201
0
            int hshift = CHROMA_H_SHIFT(p->internalCsp);
202
0
            int vshift = CHROMA_V_SHIFT(p->internalCsp);
203
0
            int widthC = p->sourceWidth >> hshift;
204
0
            int heightC = p->sourceHeight >> vshift;
205
206
0
            m_dupPicOne[0] = X265_MALLOC(pixel, size);
207
0
            m_dupPicTwo[0] = X265_MALLOC(pixel, size);
208
0
            if (p->internalCsp != X265_CSP_I400)
209
0
            {
210
0
                for (int k = 1; k < 3; k++)
211
0
                {
212
0
                    m_dupPicOne[k] = X265_MALLOC(pixel, widthC * heightC);
213
0
                    m_dupPicTwo[k] = X265_MALLOC(pixel, widthC * heightC);
214
0
                }
215
0
            }
216
0
        }
217
0
    }
218
219
0
    if (m_param->bHistBasedSceneCut)
220
0
    {
221
0
        m_planeSizes[0] = (m_param->sourceWidth >> x265_cli_csps[p->internalCsp].width[0]) * (m_param->sourceHeight >> x265_cli_csps[m_param->internalCsp].height[0]);
222
0
        uint32_t pixelbytes = m_param->internalBitDepth > 8 ? 2 : 1;
223
0
        m_edgePic = X265_MALLOC(pixel, m_planeSizes[0] * pixelbytes);
224
0
        m_edgeHistThreshold = m_param->edgeTransitionThreshold;
225
0
        m_chromaHistThreshold = m_edgeHistThreshold * 10.0;
226
0
        m_chromaHistThreshold = x265_min(m_chromaHistThreshold, MAX_SCENECUT_THRESHOLD);
227
0
        m_scaledEdgeThreshold = m_edgeHistThreshold * SCENECUT_STRENGTH_FACTOR;
228
0
        m_scaledEdgeThreshold = x265_min(m_scaledEdgeThreshold, MAX_SCENECUT_THRESHOLD);
229
0
        m_scaledChromaThreshold = m_chromaHistThreshold * SCENECUT_STRENGTH_FACTOR;
230
0
        m_scaledChromaThreshold = x265_min(m_scaledChromaThreshold, MAX_SCENECUT_THRESHOLD);
231
0
        if (m_param->sourceBitDepth != m_param->internalBitDepth)
232
0
        {
233
0
            int size = m_param->sourceWidth * m_param->sourceHeight;
234
0
            int hshift = CHROMA_H_SHIFT(m_param->internalCsp);
235
0
            int vshift = CHROMA_V_SHIFT(m_param->internalCsp);
236
0
            int widthC = m_param->sourceWidth >> hshift;
237
0
            int heightC = m_param->sourceHeight >> vshift;
238
239
0
            m_inputPic[0] = X265_MALLOC(pixel, size);
240
0
            if (m_param->internalCsp != X265_CSP_I400)
241
0
            {
242
0
                for (int j = 1; j < 3; j++)
243
0
                {
244
0
                    m_inputPic[j] = X265_MALLOC(pixel, widthC * heightC);
245
0
                }
246
0
            }
247
0
        }
248
0
    }
249
250
    // Do not allow WPP if only one row or fewer than 3 columns, it is pointless and unstable
251
0
    if (rows == 1 || cols < 3)
252
0
    {
253
0
        x265_log(p, X265_LOG_WARNING, "Too few rows/columns, --wpp disabled\n");
254
0
        p->bEnableWavefront = 0;
255
0
    }
256
257
0
    bool allowPools = !p->numaPools || strcmp(p->numaPools, "none");
258
259
    // Trim the thread pool if --wpp, --pme, and --pmode are disabled
260
0
    if (!p->bEnableWavefront && !p->bDistributeModeAnalysis && !p->bDistributeMotionEstimation && !p->lookaheadSlices)
261
0
        allowPools = false;
262
263
0
    m_numPools = 0;
264
0
    if (allowPools)
265
0
        m_threadPool = ThreadPool::allocThreadPools(p, m_numPools, 0);
266
0
    else
267
0
    {
268
0
        if (!p->frameNumThreads)
269
0
        {
270
            // auto-detect frame threads
271
0
            int cpuCount = ThreadPool::getCpuCount();
272
0
            ThreadPool::getFrameThreadsCount(p, cpuCount);
273
0
        }
274
0
    }
275
276
0
    if (!m_numPools)
277
0
    {
278
        // issue warnings if any of these features were requested
279
0
        if (p->bEnableWavefront)
280
0
            x265_log(p, X265_LOG_WARNING, "No thread pool allocated, --wpp disabled\n");
281
0
        if (p->bDistributeMotionEstimation)
282
0
            x265_log(p, X265_LOG_WARNING, "No thread pool allocated, --pme disabled\n");
283
0
        if (p->bDistributeModeAnalysis)
284
0
            x265_log(p, X265_LOG_WARNING, "No thread pool allocated, --pmode disabled\n");
285
0
        if (p->lookaheadSlices)
286
0
            x265_log(p, X265_LOG_WARNING, "No thread pool allocated, --lookahead-slices disabled\n");
287
288
        // disable all pool features if the thread pool is disabled or unusable.
289
0
        p->bEnableWavefront = p->bDistributeModeAnalysis = p->bDistributeMotionEstimation = p->lookaheadSlices = 0;
290
0
    }
291
292
0
    x265_log(p, X265_LOG_INFO, "Slices                              : %d\n", p->maxSlices);
293
294
0
    char buf[128];
295
0
    int len = 0;
296
0
    if (p->bEnableWavefront)
297
0
        len += sprintf(buf + len, "wpp(%d rows)", rows);
298
0
    if (p->bDistributeModeAnalysis)
299
0
        len += sprintf(buf + len, "%spmode", len ? "+" : "");
300
0
    if (p->bDistributeMotionEstimation)
301
0
        len += sprintf(buf + len, "%spme ", len ? "+" : "");
302
0
    if (!len)
303
0
        strcpy(buf, "none");
304
305
0
    x265_log(p, X265_LOG_INFO, "frame threads / pool features       : %d / %s\n", p->frameNumThreads, buf);
306
307
0
    for (int i = 0; i < m_param->frameNumThreads; i++)
308
0
    {
309
0
        m_frameEncoder[i] = new FrameEncoder;
310
0
        m_frameEncoder[i]->m_nalList.m_annexB = !!m_param->bAnnexB;
311
0
    }
312
313
0
    if (m_numPools)
314
0
    {
315
0
        for (int i = 0; i < m_param->frameNumThreads; i++)
316
0
        {
317
0
            int pool = i % m_numPools;
318
0
            m_frameEncoder[i]->m_pool = &m_threadPool[pool];
319
0
            m_frameEncoder[i]->m_jpId = m_threadPool[pool].m_numProviders++;
320
0
            m_threadPool[pool].m_jpTable[m_frameEncoder[i]->m_jpId] = m_frameEncoder[i];
321
0
        }
322
0
        for (int i = 0; i < m_numPools; i++)
323
0
            m_threadPool[i].start();
324
0
    }
325
0
    else
326
0
    {
327
        /* CU stats and noise-reduction buffers are indexed by jpId, so it cannot be left as -1 */
328
0
        for (int i = 0; i < m_param->frameNumThreads; i++)
329
0
            m_frameEncoder[i]->m_jpId = 0;
330
0
    }
331
332
0
    if (!m_scalingList.init())
333
0
    {
334
0
        x265_log(m_param, X265_LOG_ERROR, "Unable to allocate scaling list arrays\n");
335
0
        m_aborted = true;
336
0
        return;
337
0
    }
338
0
    else if (!m_param->scalingLists || !strcmp(m_param->scalingLists, "off"))
339
0
        m_scalingList.m_bEnabled = false;
340
0
    else if (!strcmp(m_param->scalingLists, "default"))
341
0
        m_scalingList.setDefaultScalingList();
342
0
    else if (m_scalingList.parseScalingList(m_param->scalingLists))
343
0
        m_aborted = true;
344
0
    int pools = m_numPools;
345
0
    ThreadPool* lookAheadThreadPool = 0;
346
0
    if (m_param->lookaheadThreads > 0)
347
0
    {
348
0
        lookAheadThreadPool = ThreadPool::allocThreadPools(p, pools, 1);
349
0
    }
350
0
    else
351
0
        lookAheadThreadPool = m_threadPool;
352
0
    m_lookahead = new Lookahead(m_param, lookAheadThreadPool);
353
0
    if (pools)
354
0
    {
355
0
        m_lookahead->m_jpId = lookAheadThreadPool[0].m_numProviders++;
356
0
        lookAheadThreadPool[0].m_jpTable[m_lookahead->m_jpId] = m_lookahead;
357
0
    }
358
0
    if (m_param->lookaheadThreads > 0)
359
0
        for (int i = 0; i < pools; i++)
360
0
            lookAheadThreadPool[i].start();
361
0
    m_lookahead->m_numPools = pools;
362
0
    m_dpb = new DPB(m_param);
363
0
    m_rateControl = new RateControl(*m_param, this);
364
0
    if (!m_param->bResetZoneConfig)
365
0
    {
366
0
        zoneReadCount = new ThreadSafeInteger[m_param->rc.zonefileCount];
367
0
        zoneWriteCount = new ThreadSafeInteger[m_param->rc.zonefileCount];
368
0
    }
369
370
0
    initVPS(&m_vps);
371
0
    initSPS(&m_sps);
372
0
    initPPS(&m_pps);
373
   
374
0
    if (m_param->rc.vbvBufferSize)
375
0
    {
376
0
        m_offsetEmergency = (uint16_t(*)[MAX_NUM_TR_CATEGORIES][MAX_NUM_TR_COEFFS])X265_MALLOC(uint16_t, MAX_NUM_TR_CATEGORIES * MAX_NUM_TR_COEFFS * (QP_MAX_MAX - QP_MAX_SPEC));
377
0
        if (!m_offsetEmergency)
378
0
        {
379
0
            x265_log(m_param, X265_LOG_ERROR, "Unable to allocate memory\n");
380
0
            m_aborted = true;
381
0
            return;
382
0
        }
383
384
0
        bool scalingEnabled = m_scalingList.m_bEnabled;
385
0
        if (!scalingEnabled)
386
0
        {
387
0
            m_scalingList.setDefaultScalingList();
388
0
            m_scalingList.setupQuantMatrices(m_sps.chromaFormatIdc);
389
0
        }
390
0
        else
391
0
            m_scalingList.setupQuantMatrices(m_sps.chromaFormatIdc);
392
393
0
        for (int q = 0; q < QP_MAX_MAX - QP_MAX_SPEC; q++)
394
0
        {
395
0
            for (int cat = 0; cat < MAX_NUM_TR_CATEGORIES; cat++)
396
0
            {
397
0
                uint16_t *nrOffset = m_offsetEmergency[q][cat];
398
399
0
                int trSize = cat & 3;
400
401
0
                int coefCount = 1 << ((trSize + 2) * 2);
402
403
                /* Denoise chroma first then luma, then DC. */
404
0
                int dcThreshold = (QP_MAX_MAX - QP_MAX_SPEC) * 2 / 3;
405
0
                int lumaThreshold = (QP_MAX_MAX - QP_MAX_SPEC) * 2 / 3;
406
0
                int chromaThreshold = 0;
407
408
0
                int thresh = (cat < 4 || (cat >= 8 && cat < 12)) ? lumaThreshold : chromaThreshold;
409
410
0
                double quantF = (double)(1ULL << (q / 6 + 16 + 8));
411
412
0
                for (int i = 0; i < coefCount; i++)
413
0
                {
414
                    /* True "emergency mode": remove all DCT coefficients */
415
0
                    if (q == QP_MAX_MAX - QP_MAX_SPEC - 1)
416
0
                    {
417
0
                        nrOffset[i] = INT16_MAX;
418
0
                        continue;
419
0
                    }
420
421
0
                    int iThresh = i == 0 ? dcThreshold : thresh;
422
0
                    if (q < iThresh)
423
0
                    {
424
0
                        nrOffset[i] = 0;
425
0
                        continue;
426
0
                    }
427
428
0
                    int numList = (cat >= 8) * 3 + ((int)!iThresh);
429
430
0
                    double pos = (double)(q - iThresh + 1) / (QP_MAX_MAX - QP_MAX_SPEC - iThresh);
431
0
                    double start = quantF / (m_scalingList.m_quantCoef[trSize][numList][QP_MAX_SPEC % 6][i]);
432
433
                    // Formula chosen as an exponential scale to vaguely mimic the effects of a higher quantizer.
434
0
                    double bias = (pow(2, pos * (QP_MAX_MAX - QP_MAX_SPEC)) * 0.003 - 0.003) * start;
435
0
                    nrOffset[i] = (uint16_t)X265_MIN(bias + 0.5, INT16_MAX);
436
0
                }
437
0
            }
438
0
        }
439
440
0
        if (!scalingEnabled)
441
0
        {
442
0
            m_scalingList.m_bEnabled = false;
443
0
            m_scalingList.m_bDataPresent = false;
444
0
            m_scalingList.setupQuantMatrices(m_sps.chromaFormatIdc);
445
0
        }
446
0
    }
447
0
    else
448
0
        m_scalingList.setupQuantMatrices(m_sps.chromaFormatIdc);
449
450
0
    int numRows = (m_param->sourceHeight + m_param->maxCUSize - 1) / m_param->maxCUSize;
451
0
    int numCols = (m_param->sourceWidth  + m_param->maxCUSize - 1) / m_param->maxCUSize;
452
0
    for (int i = 0; i < m_param->frameNumThreads; i++)
453
0
    {
454
0
        if (!m_frameEncoder[i]->init(this, numRows, numCols))
455
0
        {
456
0
            x265_log(m_param, X265_LOG_ERROR, "Unable to initialize frame encoder, aborting\n");
457
0
            m_aborted = true;
458
0
        }
459
0
    }
460
461
0
    for (int i = 0; i < m_param->frameNumThreads; i++)
462
0
    {
463
0
        m_frameEncoder[i]->start();
464
0
        m_frameEncoder[i]->m_done.wait(); /* wait for thread to initialize */
465
0
    }
466
467
0
    if (m_param->bEmitHRDSEI)
468
0
        m_rateControl->initHRD(m_sps);
469
470
0
    if (!m_rateControl->init(m_sps))
471
0
        m_aborted = true;
472
0
    if (!m_lookahead->create())
473
0
        m_aborted = true;
474
475
0
    initRefIdx();
476
0
    if (m_param->analysisSave && m_param->bUseAnalysisFile)
477
0
    {
478
0
        char* temp = strcatFilename(m_param->analysisSave, ".temp");
479
0
        if (!temp)
480
0
            m_aborted = true;
481
0
        else
482
0
        {
483
0
            m_analysisFileOut = x265_fopen(temp, "wb");
484
0
            X265_FREE(temp);
485
0
        }
486
0
        if (!m_analysisFileOut)
487
0
        {
488
0
            x265_log_file(NULL, X265_LOG_ERROR, "Analysis save: failed to open file %s.temp\n", m_param->analysisSave);
489
0
            m_aborted = true;
490
0
        }
491
0
    }
492
493
0
    if (m_param->analysisMultiPassRefine || m_param->analysisMultiPassDistortion)
494
0
    {
495
0
        const char* name = m_param->analysisReuseFileName;
496
0
        if (!name)
497
0
            name = defaultAnalysisFileName;
498
0
        if (m_param->rc.bStatWrite)
499
0
        {
500
0
            char* temp = strcatFilename(name, ".temp");
501
0
            if (!temp)
502
0
                m_aborted = true;
503
0
            else
504
0
            {
505
0
                m_analysisFileOut = x265_fopen(temp, "wb");
506
0
                X265_FREE(temp);
507
0
            }
508
0
            if (!m_analysisFileOut)
509
0
            {
510
0
                x265_log_file(NULL, X265_LOG_ERROR, "Analysis 2 pass: failed to open file %s.temp\n", name);
511
0
                m_aborted = true;
512
0
            }
513
0
        }
514
0
        if (m_param->rc.bStatRead)
515
0
        {
516
0
            m_analysisFileIn = x265_fopen(name, "rb");
517
0
            if (!m_analysisFileIn)
518
0
            {
519
0
                x265_log_file(NULL, X265_LOG_ERROR, "Analysis 2 pass: failed to open file %s\n", name);
520
0
                m_aborted = true;
521
0
            }
522
0
        }
523
0
    }
524
0
    m_bZeroLatency = !m_param->bframes && !m_param->lookaheadDepth && m_param->frameNumThreads == 1 && m_param->maxSlices == 1;
525
0
    m_aborted |= parseLambdaFile(m_param);
526
527
0
    m_encodeStartTime = x265_mdate();
528
529
0
    m_nalList.m_annexB = !!m_param->bAnnexB;
530
531
0
    if (m_param->naluFile)
532
0
    {
533
0
        m_naluFile = x265_fopen(m_param->naluFile, "r");
534
0
        if (!m_naluFile)
535
0
        {
536
0
            x265_log_file(NULL, X265_LOG_ERROR, "%s file not found or Failed to open\n", m_param->naluFile);
537
0
            m_aborted = true;
538
0
        }
539
0
        else
540
0
             m_enableNal = 1;
541
0
    }
542
0
    else
543
0
         m_enableNal = 0;
544
545
#if ENABLE_HDR10_PLUS
546
    if (m_bToneMap)
547
        m_numCimInfo = m_hdr10plus_api->hdr10plus_json_to_movie_cim(m_param->toneMapFile, m_cim);
548
#endif
549
0
    if (m_param->bDynamicRefine)
550
0
    {
551
        /* Allocate memory for 1 GOP and reuse it for the subsequent GOPs */
552
0
        int size = (m_param->keyframeMax + m_param->lookaheadDepth) * m_param->maxCUDepth * X265_REFINE_INTER_LEVELS;
553
0
        CHECKED_MALLOC_ZERO(m_variance, uint64_t, size);
554
0
        CHECKED_MALLOC_ZERO(m_rdCost, uint64_t, size);
555
0
        CHECKED_MALLOC_ZERO(m_trainingCount, uint32_t, size);
556
0
        return;
557
0
    fail:
558
0
        m_aborted = true;
559
0
    }
560
0
}
561
562
void Encoder::stopJobs()
563
0
{
564
0
    if (m_rateControl)
565
0
        m_rateControl->terminate(); // unblock all blocked RC calls
566
567
0
    if (m_lookahead)
568
0
        m_lookahead->stopJobs();
569
    
570
0
    for (int i = 0; i < m_param->frameNumThreads; i++)
571
0
    {
572
0
        if (m_frameEncoder[i])
573
0
        {
574
0
            m_frameEncoder[i]->getEncodedPicture(m_nalList);
575
0
            m_frameEncoder[i]->m_threadActive = false;
576
0
            m_frameEncoder[i]->m_enable.trigger();
577
0
            m_frameEncoder[i]->stop();
578
0
        }
579
0
    }
580
581
0
    if (m_threadPool)
582
0
    {
583
0
        for (int i = 0; i < m_numPools; i++)
584
0
            m_threadPool[i].stopWorkers();
585
0
    }
586
0
}
587
588
int Encoder::copySlicetypePocAndSceneCut(int *slicetype, int *poc, int *sceneCut)
589
0
{
590
0
    Frame *FramePtr = m_dpb->m_picList.getCurFrame();
591
0
    if (FramePtr != NULL)
592
0
    {
593
0
        *slicetype = FramePtr->m_lowres.sliceType;
594
0
        *poc = FramePtr->m_encData->m_slice->m_poc;
595
0
        *sceneCut = FramePtr->m_lowres.bScenecut;
596
0
    }
597
0
    else
598
0
    {
599
0
        x265_log(NULL, X265_LOG_WARNING, "Frame is still in lookahead pipeline, this API must be called after (poc >= lookaheadDepth + bframes + 2) condition check\n");
600
0
        return -1;
601
0
    }
602
0
    return 0;
603
0
}
604
605
int Encoder::getRefFrameList(PicYuv** l0, PicYuv** l1, int sliceType, int poc, int* pocL0, int* pocL1)
606
0
{
607
0
    if (!(IS_X265_TYPE_I(sliceType)))
608
0
    {
609
0
        Frame *framePtr = m_dpb->m_picList.getPOC(poc);
610
0
        if (framePtr != NULL)
611
0
        {
612
0
            for (int j = 0; j < framePtr->m_encData->m_slice->m_numRefIdx[0]; j++)    // check only for --ref=n number of frames.
613
0
            {
614
0
                if (framePtr->m_encData->m_slice->m_refFrameList[0][j] && framePtr->m_encData->m_slice->m_refFrameList[0][j]->m_reconPic != NULL)
615
0
                {
616
0
                    int l0POC = framePtr->m_encData->m_slice->m_refFrameList[0][j]->m_poc;
617
0
                    pocL0[j] = l0POC;
618
0
                    Frame* l0Fp = m_dpb->m_picList.getPOC(l0POC);
619
0
                    while (l0Fp->m_reconRowFlag[l0Fp->m_numRows - 1].get() == 0)
620
0
                        l0Fp->m_reconRowFlag[l0Fp->m_numRows - 1].waitForChange(0); /* If recon is not ready, current frame encoder has to wait. */
621
0
                    l0[j] = l0Fp->m_reconPic;
622
0
                }
623
0
            }
624
0
            for (int j = 0; j < framePtr->m_encData->m_slice->m_numRefIdx[1]; j++)    // check only for --ref=n number of frames.
625
0
            {
626
0
                if (framePtr->m_encData->m_slice->m_refFrameList[1][j] && framePtr->m_encData->m_slice->m_refFrameList[1][j]->m_reconPic != NULL)
627
0
                {
628
0
                    int l1POC = framePtr->m_encData->m_slice->m_refFrameList[1][j]->m_poc;
629
0
                    pocL1[j] = l1POC;
630
0
                    Frame* l1Fp = m_dpb->m_picList.getPOC(l1POC);
631
0
                    while (l1Fp->m_reconRowFlag[l1Fp->m_numRows - 1].get() == 0)
632
0
                        l1Fp->m_reconRowFlag[l1Fp->m_numRows - 1].waitForChange(0); /* If recon is not ready, current frame encoder has to wait. */
633
0
                    l1[j] = l1Fp->m_reconPic;
634
0
                }
635
0
            }
636
0
        }
637
0
        else
638
0
        {
639
0
            x265_log(NULL, X265_LOG_WARNING, "Current frame is not in DPB piclist.\n");
640
0
            return 1;
641
0
        }
642
0
    }
643
0
    else
644
0
    {
645
0
        x265_log(NULL, X265_LOG_ERROR, "I frames does not have a refrence List\n");
646
0
        return -1;
647
0
    }
648
0
    return 0;
649
0
}
650
651
int Encoder::setAnalysisDataAfterZScan(x265_analysis_data *analysis_data, Frame* curFrame)
652
0
{
653
0
    int mbImageWidth, mbImageHeight;
654
0
    mbImageWidth = (curFrame->m_fencPic->m_picWidth + 16 - 1) >> 4; //AVC block sizes
655
0
    mbImageHeight = (curFrame->m_fencPic->m_picHeight + 16 - 1) >> 4;
656
0
    if (analysis_data->sliceType == X265_TYPE_IDR || analysis_data->sliceType == X265_TYPE_I)
657
0
    {
658
0
        curFrame->m_analysisData.sliceType = X265_TYPE_I;
659
0
        if (m_param->analysisLoadReuseLevel < 7)
660
0
            return -1;
661
0
        curFrame->m_analysisData.numPartitions = m_param->num4x4Partitions;
662
0
        int num16x16inCUWidth = m_param->maxCUSize >> 4;
663
0
        uint32_t ctuAddr, offset, cuPos;
664
0
        x265_analysis_intra_data * intraData = curFrame->m_analysisData.intraData;
665
0
        x265_analysis_intra_data * srcIntraData = analysis_data->intraData;
666
0
        for (int i = 0; i < mbImageHeight; i++)
667
0
        {
668
0
            for (int j = 0; j < mbImageWidth; j++)
669
0
            {
670
0
                int mbIndex = j + i * mbImageWidth;
671
0
                ctuAddr = (j / num16x16inCUWidth + ((i / num16x16inCUWidth) * (mbImageWidth / num16x16inCUWidth)));
672
0
                offset = ((i % num16x16inCUWidth) << 5) + ((j % num16x16inCUWidth) << 4);
673
0
                if ((j % 4 >= 2) && m_param->maxCUSize == 64)
674
0
                    offset += (2 * 16);
675
0
                if ((i % 4 >= 2) && m_param->maxCUSize == 64)
676
0
                    offset += (2 * 32);
677
0
                cuPos = ctuAddr  * curFrame->m_analysisData.numPartitions + offset;
678
0
                memcpy(&(intraData)->depth[cuPos], &(srcIntraData)->depth[mbIndex * 16], 16);
679
0
                memcpy(&(intraData)->chromaModes[cuPos], &(srcIntraData)->chromaModes[mbIndex * 16], 16);
680
0
                memcpy(&(intraData)->partSizes[cuPos], &(srcIntraData)->partSizes[mbIndex * 16], 16);
681
0
                memcpy(&(intraData)->partSizes[cuPos], &(srcIntraData)->partSizes[mbIndex * 16], 16);
682
0
            }
683
0
        }
684
0
        memcpy(&(intraData)->modes, (srcIntraData)->modes, curFrame->m_analysisData.numPartitions * analysis_data->numCUsInFrame);
685
0
    }
686
0
    else
687
0
    {
688
0
        uint32_t numDir = analysis_data->sliceType == X265_TYPE_P ? 1 : 2;
689
0
        if (m_param->analysisLoadReuseLevel < 7)
690
0
            return -1;
691
0
        curFrame->m_analysisData.numPartitions = m_param->num4x4Partitions;
692
0
        int num16x16inCUWidth = m_param->maxCUSize >> 4;
693
0
        uint32_t ctuAddr, offset, cuPos;
694
0
        x265_analysis_inter_data * interData = curFrame->m_analysisData.interData;
695
0
        x265_analysis_inter_data * srcInterData = analysis_data->interData;
696
0
        for (int i = 0; i < mbImageHeight; i++)
697
0
        {
698
0
            for (int j = 0; j < mbImageWidth; j++)
699
0
            {
700
0
                int mbIndex = j + i * mbImageWidth;
701
0
                ctuAddr = (j / num16x16inCUWidth + ((i / num16x16inCUWidth) * (mbImageWidth / num16x16inCUWidth)));
702
0
                offset = ((i % num16x16inCUWidth) << 5) + ((j % num16x16inCUWidth) << 4);
703
0
                if ((j % 4 >= 2) && m_param->maxCUSize == 64)
704
0
                    offset += (2 * 16);
705
0
                if ((i % 4 >= 2) && m_param->maxCUSize == 64)
706
0
                    offset += (2 * 32);
707
0
                cuPos = ctuAddr  * curFrame->m_analysisData.numPartitions + offset;
708
0
                memcpy(&(interData)->depth[cuPos], &(srcInterData)->depth[mbIndex * 16], 16);
709
0
                memcpy(&(interData)->modes[cuPos], &(srcInterData)->modes[mbIndex * 16], 16);
710
711
0
                memcpy(&(interData)->partSize[cuPos], &(srcInterData)->partSize[mbIndex * 16], 16);
712
713
0
                int bytes = curFrame->m_analysisData.numPartitions >> ((srcInterData)->depth[mbIndex * 16] * 2);
714
0
                int cuCount = 1;
715
0
                if (bytes < 16)
716
0
                    cuCount = 4;
717
0
                for (int cuI = 0; cuI < cuCount; cuI++)
718
0
                {
719
0
                    int numPU = nbPartsTable[(srcInterData)->partSize[mbIndex * 16 + cuI * bytes]];
720
0
                    for (int pu = 0; pu < numPU; pu++)
721
0
                    {
722
0
                        int cuOffset = cuI * bytes + pu;
723
0
                        (interData)->mergeFlag[cuPos + cuOffset] = (srcInterData)->mergeFlag[(mbIndex * 16) + cuOffset];
724
0
                        (interData)->sadCost[cuPos + cuOffset] = (srcInterData)->sadCost[(mbIndex * 16) + cuOffset];
725
0
                        (interData)->interDir[cuPos + cuOffset] = (srcInterData)->interDir[(mbIndex * 16) + cuOffset];
726
0
                        for (uint32_t k = 0; k < numDir; k++)
727
0
                        {
728
0
                            (interData)->mvpIdx[k][cuPos + cuOffset] = (srcInterData)->mvpIdx[k][(mbIndex * 16) + cuOffset];
729
0
                            (interData)->refIdx[k][cuPos + cuOffset] = (srcInterData)->refIdx[k][(mbIndex * 16) + cuOffset];
730
0
                            memcpy(&(interData)->mv[k][cuPos + cuOffset], &(srcInterData)->mv[k][(mbIndex * 16) + cuOffset], sizeof(MV));
731
0
                            if (m_param->analysisLoadReuseLevel == 7 && numPU == PU_2Nx2N &&
732
0
                                ((interData)->depth[cuPos + cuOffset] == (m_param->maxCUSize >> 5)))
733
0
                            {
734
0
                                int mv_x = (interData)->mv[k][cuPos + cuOffset].x;
735
0
                                int mv_y = (interData)->mv[k][cuPos + cuOffset].y;
736
0
                                if ((mv_x*mv_x + mv_y*mv_y) <= MVTHRESHOLD)
737
0
                                    memset(&curFrame->m_analysisData.modeFlag[k][cuPos + cuOffset], 1, bytes);
738
0
                            }
739
0
                        }
740
0
                    }
741
0
                }
742
0
            }
743
0
        }
744
0
    }
745
0
    return 0;
746
0
}
747
748
int Encoder::setAnalysisData(x265_analysis_data *analysis_data, int poc, uint32_t cuBytes)
749
0
{
750
0
    uint32_t widthInCU = (m_param->sourceWidth + m_param->maxCUSize - 1) >> m_param->maxLog2CUSize;
751
0
    uint32_t heightInCU = (m_param->sourceHeight + m_param->maxCUSize - 1) >> m_param->maxLog2CUSize;
752
753
0
    Frame* curFrame = m_dpb->m_picList.getPOC(poc);
754
0
    if (curFrame != NULL)
755
0
    {
756
0
        curFrame->m_analysisData = (*analysis_data);
757
0
        curFrame->m_analysisData.numCUsInFrame = widthInCU * heightInCU;
758
0
        curFrame->m_analysisData.numPartitions = m_param->num4x4Partitions;
759
0
        x265_alloc_analysis_data(m_param, &curFrame->m_analysisData);
760
0
        if (m_param->maxCUSize == 16)
761
0
        {
762
0
            if (analysis_data->sliceType == X265_TYPE_IDR || analysis_data->sliceType == X265_TYPE_I)
763
0
            {
764
0
                curFrame->m_analysisData.sliceType = X265_TYPE_I;
765
0
                if (m_param->analysisLoadReuseLevel < 2)
766
0
                    return -1;
767
768
0
                curFrame->m_analysisData.numPartitions = m_param->num4x4Partitions;
769
0
                size_t count = 0;
770
0
                x265_analysis_intra_data * currIntraData = curFrame->m_analysisData.intraData;
771
0
                x265_analysis_intra_data * intraData = analysis_data->intraData;
772
0
                for (uint32_t d = 0; d < cuBytes; d++)
773
0
                {
774
0
                    int bytes = curFrame->m_analysisData.numPartitions >> ((intraData)->depth[d] * 2);
775
0
                    memset(&(currIntraData)->depth[count], (intraData)->depth[d], bytes);
776
0
                    memset(&(currIntraData)->chromaModes[count], (intraData)->chromaModes[d], bytes);
777
0
                    memset(&(currIntraData)->partSizes[count], (intraData)->partSizes[d], bytes);
778
0
                    memset(&(currIntraData)->partSizes[count], (intraData)->partSizes[d], bytes);
779
0
                    count += bytes;
780
0
                }
781
0
                memcpy(&(currIntraData)->modes, (intraData)->modes, curFrame->m_analysisData.numPartitions * analysis_data->numCUsInFrame);
782
0
            }
783
0
            else
784
0
            {
785
0
                uint32_t numDir = analysis_data->sliceType == X265_TYPE_P ? 1 : 2;
786
0
                if (m_param->analysisLoadReuseLevel < 2)
787
0
                    return -1;
788
789
0
                curFrame->m_analysisData.numPartitions = m_param->num4x4Partitions;
790
0
                size_t count = 0;
791
0
                x265_analysis_inter_data * currInterData = curFrame->m_analysisData.interData;
792
0
                x265_analysis_inter_data * interData = analysis_data->interData;
793
0
                for (uint32_t d = 0; d < cuBytes; d++)
794
0
                {
795
0
                    int bytes = curFrame->m_analysisData.numPartitions >> ((interData)->depth[d] * 2);
796
0
                    memset(&(currInterData)->depth[count], (interData)->depth[d], bytes);
797
0
                    memset(&(currInterData)->modes[count], (interData)->modes[d], bytes);
798
0
                    memcpy(&(currInterData)->sadCost[count], &(analysis_data->interData)->sadCost[d], bytes);
799
0
                    if (m_param->analysisLoadReuseLevel > 4)
800
0
                    {
801
0
                        memset(&(currInterData)->partSize[count], (interData)->partSize[d], bytes);
802
0
                        int numPU = nbPartsTable[(interData)->partSize[d]];
803
0
                        for (int pu = 0; pu < numPU; pu++)
804
0
                        {
805
0
                            if (pu) d++;
806
0
                            (currInterData)->mergeFlag[count + pu] = (interData)->mergeFlag[d];
807
0
                            if (m_param->analysisLoadReuseLevel >= 7)
808
0
                            {
809
0
                                (currInterData)->interDir[count + pu] = (interData)->interDir[d];
810
0
                                for (uint32_t i = 0; i < numDir; i++)
811
0
                                {
812
0
                                    (currInterData)->mvpIdx[i][count + pu] = (interData)->mvpIdx[i][d];
813
0
                                    (currInterData)->refIdx[i][count + pu] = (interData)->refIdx[i][d];
814
0
                                    memcpy(&(currInterData)->mv[i][count + pu], &(interData)->mv[i][d], sizeof(MV));
815
0
                                    if (m_param->analysisLoadReuseLevel == 7 && numPU == PU_2Nx2N && m_param->num4x4Partitions <= 16)
816
0
                                    {
817
0
                                        int mv_x = (currInterData)->mv[i][count + pu].x;
818
0
                                        int mv_y = (currInterData)->mv[i][count + pu].y;
819
0
                                        if ((mv_x*mv_x + mv_y*mv_y) <= MVTHRESHOLD)
820
0
                                            memset(&curFrame->m_analysisData.modeFlag[i][count + pu], 1, bytes);
821
0
                                    }
822
0
                                }
823
0
                            }
824
0
                        }
825
0
                    }
826
0
                    count += bytes;
827
0
                }
828
0
            }
829
0
        }
830
0
        else
831
0
            setAnalysisDataAfterZScan(analysis_data, curFrame);
832
833
0
        curFrame->m_copyMVType.trigger();
834
0
        return 0;
835
0
    }
836
0
    return -1;
837
0
}
838
839
void Encoder::destroy()
840
0
{
841
#if ENABLE_HDR10_PLUS
842
    if (m_bToneMap)
843
        m_hdr10plus_api->hdr10plus_clear_movie(m_cim, m_numCimInfo);
844
#endif
845
846
0
    if (m_param->bDynamicRefine)
847
0
    {
848
0
        X265_FREE(m_variance);
849
0
        X265_FREE(m_rdCost);
850
0
        X265_FREE(m_trainingCount);
851
0
    }
852
0
    if (m_exportedPic)
853
0
    {
854
0
        ATOMIC_DEC(&m_exportedPic->m_countRefEncoders);
855
0
        m_exportedPic = NULL;
856
0
    }
857
858
0
    if (m_param->bEnableFrameDuplication)
859
0
    {
860
0
        for (uint32_t i = 0; i < DUP_BUFFER; i++)
861
0
        {
862
0
            X265_FREE(m_dupBuffer[i]->dupPlane);
863
0
            x265_picture_free(m_dupBuffer[i]->dupPic);
864
0
            X265_FREE(m_dupBuffer[i]);
865
0
        }
866
867
0
        if (!(m_param->sourceBitDepth == 8 && m_param->internalBitDepth == 8))
868
0
        {
869
0
            for (int k = 0; k < 3; k++)
870
0
            {
871
0
                if (k == 0)
872
0
                {
873
0
                    X265_FREE(m_dupPicOne[k]);
874
0
                    X265_FREE(m_dupPicTwo[k]);
875
0
                }
876
0
                else if(k >= 1 && m_param->internalCsp != X265_CSP_I400)
877
0
                {
878
0
                    X265_FREE(m_dupPicOne[k]);
879
0
                    X265_FREE(m_dupPicTwo[k]);
880
0
                }
881
0
            }
882
0
        }
883
0
    }
884
885
0
    if (m_param->bHistBasedSceneCut)
886
0
    {
887
0
        if (m_edgePic != NULL)
888
0
        {
889
0
            X265_FREE_ZERO(m_edgePic);
890
0
        }
891
892
0
        if (m_param->sourceBitDepth != m_param->internalBitDepth)
893
0
        {
894
0
            X265_FREE_ZERO(m_inputPic[0]);
895
0
            if (m_param->internalCsp != X265_CSP_I400)
896
0
            {
897
0
                for (int i = 1; i < 3; i++)
898
0
                {
899
0
                    X265_FREE_ZERO(m_inputPic[i]);
900
0
                }
901
0
            }
902
0
        }
903
0
    }
904
905
0
    for (int i = 0; i < m_param->frameNumThreads; i++)
906
0
    {
907
0
        if (m_frameEncoder[i])
908
0
        {
909
0
            m_frameEncoder[i]->destroy();
910
0
            delete m_frameEncoder[i];
911
0
        }
912
0
    }
913
914
    // thread pools can be cleaned up now that all the JobProviders are
915
    // known to be shutdown
916
0
    delete [] m_threadPool;
917
918
0
    if (m_lookahead)
919
0
    {
920
0
        m_lookahead->destroy();
921
0
        delete m_lookahead;
922
0
    }
923
924
0
    delete m_dpb;
925
0
    if (!m_param->bResetZoneConfig && m_param->rc.zonefileCount)
926
0
    {
927
0
        delete[] zoneReadCount;
928
0
        delete[] zoneWriteCount;
929
0
    }
930
0
    if (m_rateControl)
931
0
    {
932
0
        m_rateControl->destroy();
933
0
        delete m_rateControl;
934
0
    }
935
936
0
    X265_FREE(m_offsetEmergency);
937
938
0
    if (m_latestParam != NULL && m_latestParam != m_param)
939
0
    {
940
0
        if (m_latestParam->scalingLists != m_param->scalingLists)
941
0
            free((char*)m_latestParam->scalingLists);
942
943
0
        PARAM_NS::x265_param_free(m_latestParam);
944
0
    }
945
0
    if (m_analysisFileIn)
946
0
        fclose(m_analysisFileIn);
947
948
0
    if (m_analysisFileOut)
949
0
    {
950
0
        int bError = 1;
951
0
        fclose(m_analysisFileOut);
952
0
        const char* name = m_param->analysisSave ? m_param->analysisSave : m_param->analysisReuseFileName;
953
0
        if (!name)
954
0
            name = defaultAnalysisFileName;
955
0
        char* temp = strcatFilename(name, ".temp");
956
0
        if (temp)
957
0
        {
958
0
            x265_unlink(name);
959
0
            bError = x265_rename(temp, name);
960
0
        }
961
0
        if (bError)
962
0
        {
963
0
            x265_log_file(m_param, X265_LOG_ERROR, "failed to rename analysis stats file to \"%s\"\n", name);
964
0
        }
965
0
        X265_FREE(temp);
966
0
     }
967
0
    if (m_naluFile)
968
0
        fclose(m_naluFile);
969
970
#ifdef SVT_HEVC
971
    X265_FREE(m_svtAppData);
972
#endif
973
0
    if (m_param)
974
0
    {
975
0
        if (m_param->csvfpt)
976
0
            fclose(m_param->csvfpt);
977
        /* release string arguments that were strdup'd */
978
0
        free((char*)m_param->rc.lambdaFileName);
979
0
        free((char*)m_param->rc.statFileName);
980
0
        free((char*)m_param->analysisReuseFileName);
981
0
        free((char*)m_param->scalingLists);
982
0
        free((char*)m_param->csvfn);
983
0
        free((char*)m_param->numaPools);
984
0
        free((char*)m_param->masteringDisplayColorVolume);
985
0
        free((char*)m_param->toneMapFile);
986
0
        free((char*)m_param->analysisSave);
987
0
        free((char*)m_param->analysisLoad);
988
0
        PARAM_NS::x265_param_free(m_param);
989
0
    }
990
0
}
991
992
void Encoder::updateVbvPlan(RateControl* rc)
993
0
{
994
0
    for (int i = 0; i < m_param->frameNumThreads; i++)
995
0
    {
996
0
        FrameEncoder *encoder = m_frameEncoder[i];
997
0
        if (encoder->m_rce.isActive && encoder->m_rce.poc != rc->m_curSlice->m_poc)
998
0
        {
999
0
            int64_t bits = m_param->rc.bEnableConstVbv ? (int64_t)encoder->m_rce.frameSizePlanned : (int64_t)X265_MAX(encoder->m_rce.frameSizeEstimated, encoder->m_rce.frameSizePlanned);
1000
0
            rc->m_bufferFill -= bits;
1001
0
            rc->m_bufferFill = X265_MAX(rc->m_bufferFill, 0);
1002
0
            rc->m_bufferFill += encoder->m_rce.bufferRate;
1003
0
            rc->m_bufferFill = X265_MIN(rc->m_bufferFill, rc->m_bufferSize);
1004
0
            if (rc->m_2pass)
1005
0
                rc->m_predictedBits += bits;
1006
0
        }
1007
0
    }
1008
0
}
1009
1010
void Encoder::calcRefreshInterval(Frame* frameEnc)
1011
0
{
1012
0
    Slice* slice = frameEnc->m_encData->m_slice;
1013
0
    uint32_t numBlocksInRow = slice->m_sps->numCuInWidth;
1014
0
    FrameData::PeriodicIR* pir = &frameEnc->m_encData->m_pir;
1015
0
    if (slice->m_sliceType == I_SLICE)
1016
0
    {
1017
0
        pir->framesSinceLastPir = 0;
1018
0
        m_bQueuedIntraRefresh = 0;
1019
        /* PIR is currently only supported with ref == 1, so any intra frame effectively refreshes
1020
         * the whole frame and counts as an intra refresh. */
1021
0
        pir->pirEndCol = numBlocksInRow;
1022
0
    }
1023
0
    else if (slice->m_sliceType == P_SLICE)
1024
0
    {
1025
0
        Frame* ref = frameEnc->m_encData->m_slice->m_refFrameList[0][0];
1026
0
        int pocdiff = frameEnc->m_poc - ref->m_poc;
1027
0
        int numPFramesInGOP = m_param->keyframeMax / pocdiff;
1028
0
        int increment = (numBlocksInRow + numPFramesInGOP - 1) / numPFramesInGOP;
1029
0
        pir->pirEndCol = ref->m_encData->m_pir.pirEndCol;
1030
0
        pir->framesSinceLastPir = ref->m_encData->m_pir.framesSinceLastPir + pocdiff;
1031
0
        if (pir->framesSinceLastPir >= m_param->keyframeMax ||
1032
0
            (m_bQueuedIntraRefresh && pir->pirEndCol >= numBlocksInRow))
1033
0
        {
1034
0
            pir->pirEndCol = 0;
1035
0
            pir->framesSinceLastPir = 0;
1036
0
            m_bQueuedIntraRefresh = 0;
1037
0
            frameEnc->m_lowres.bKeyframe = 1;
1038
0
        }
1039
0
        pir->pirStartCol = pir->pirEndCol;
1040
0
        pir->pirEndCol += increment;
1041
        /* If our intra refresh has reached the right side of the frame, we're done. */
1042
0
        if (pir->pirEndCol >= numBlocksInRow)
1043
0
        {
1044
0
            pir->pirEndCol = numBlocksInRow;
1045
0
        }
1046
0
    }
1047
0
}
1048
1049
void Encoder::copyUserSEIMessages(Frame *frame, const x265_picture* pic_in)
1050
0
{
1051
0
    x265_sei_payload toneMap;
1052
0
    toneMap.payload = NULL;
1053
0
    int toneMapPayload = 0;
1054
1055
#if ENABLE_HDR10_PLUS
1056
    if (m_bToneMap)
1057
    {
1058
        int currentPOC = m_pocLast;
1059
        if (currentPOC < m_numCimInfo)
1060
        {
1061
            int32_t i = 0;
1062
            toneMap.payloadSize = 0;
1063
            while (m_cim[currentPOC][i] == 0xFF)
1064
                toneMap.payloadSize += m_cim[currentPOC][i++];
1065
            toneMap.payloadSize += m_cim[currentPOC][i];
1066
1067
            toneMap.payload = (uint8_t*)x265_malloc(sizeof(uint8_t) * toneMap.payloadSize);
1068
            toneMap.payloadType = USER_DATA_REGISTERED_ITU_T_T35;
1069
            memcpy(toneMap.payload, &m_cim[currentPOC][i + 1], toneMap.payloadSize);
1070
            toneMapPayload = 1;
1071
        }
1072
    }
1073
#endif
1074
    /* seiMsg will contain SEI messages specified in a fixed file format in POC order.
1075
    * Format of the file : <POC><space><PREFIX><space><NAL UNIT TYPE>/<SEI TYPE><space><SEI Payload> */
1076
0
    x265_sei_payload seiMsg;
1077
0
    seiMsg.payload = NULL;
1078
0
    int userPayload = 0;
1079
0
    if (m_enableNal)
1080
0
    {
1081
0
        readUserSeiFile(seiMsg, m_pocLast);
1082
0
        if (seiMsg.payload)
1083
0
            userPayload = 1;;
1084
0
    }
1085
1086
0
    int numPayloads = pic_in->userSEI.numPayloads + toneMapPayload + userPayload;
1087
0
    frame->m_userSEI.numPayloads = numPayloads;
1088
1089
0
    if (frame->m_userSEI.numPayloads)
1090
0
    {
1091
0
        if (!frame->m_userSEI.payloads)
1092
0
        {
1093
0
            frame->m_userSEI.payloads = new x265_sei_payload[numPayloads];
1094
0
            for (int i = 0; i < numPayloads; i++)
1095
0
                frame->m_userSEI.payloads[i].payload = NULL;
1096
0
        }
1097
0
        for (int i = 0; i < numPayloads; i++)
1098
0
        {
1099
0
            x265_sei_payload input;
1100
0
            if ((i == (numPayloads - 1)) && toneMapPayload)
1101
0
                input = toneMap;
1102
0
            else if (m_enableNal)
1103
0
                input = seiMsg;
1104
0
            else
1105
0
                input = pic_in->userSEI.payloads[i];
1106
1107
0
            if (!frame->m_userSEI.payloads[i].payload)
1108
0
                frame->m_userSEI.payloads[i].payload = new uint8_t[input.payloadSize];
1109
0
            memcpy(frame->m_userSEI.payloads[i].payload, input.payload, input.payloadSize);
1110
0
            frame->m_userSEI.payloads[i].payloadSize = input.payloadSize;
1111
0
            frame->m_userSEI.payloads[i].payloadType = input.payloadType;
1112
0
        }
1113
0
        if (toneMap.payload)
1114
0
            x265_free(toneMap.payload);
1115
0
        if (seiMsg.payload)
1116
0
            x265_free(seiMsg.payload);
1117
0
    }
1118
0
}
1119
1120
//Find Sum of Squared Difference (SSD) between two pictures
1121
uint64_t Encoder::computeSSD(pixel *fenc, pixel *rec, intptr_t stride, uint32_t width, uint32_t height, x265_param *param)
1122
0
{
1123
0
    uint64_t ssd = 0;
1124
1125
0
    if (!param->bEnableFrameDuplication || (width & 3))
1126
0
    {
1127
0
        if ((width | height) & 3)
1128
0
        {
1129
            /* Slow Path */
1130
0
            for (uint32_t y = 0; y < height; y++)
1131
0
            {
1132
0
                for (uint32_t x = 0; x < width; x++)
1133
0
                {
1134
0
                    int diff = (int)(fenc[x] - rec[x]);
1135
0
                    ssd += diff * diff;
1136
0
                }
1137
1138
0
                fenc += stride;
1139
0
                rec += stride;
1140
0
            }
1141
1142
0
            return ssd;
1143
0
        }
1144
0
    }
1145
1146
0
    uint32_t y = 0;
1147
1148
    /* Consume rows in ever narrower chunks of height */
1149
0
    for (int size = BLOCK_64x64; size >= BLOCK_4x4 && y < height; size--)
1150
0
    {
1151
0
        uint32_t rowHeight = 1 << (size + 2);
1152
1153
0
        for (; y + rowHeight <= height; y += rowHeight)
1154
0
        {
1155
0
            uint32_t y1, x = 0;
1156
1157
            /* Consume each row using the largest square blocks possible */
1158
0
            if (size == BLOCK_64x64 && !(stride & 31))
1159
0
                for (; x + 64 <= width; x += 64)
1160
0
                    ssd += primitives.cu[BLOCK_64x64].sse_pp(fenc + x, stride, rec + x, stride);
1161
1162
0
            if (size >= BLOCK_32x32 && !(stride & 15))
1163
0
                for (; x + 32 <= width; x += 32)
1164
0
                    for (y1 = 0; y1 + 32 <= rowHeight; y1 += 32)
1165
0
                        ssd += primitives.cu[BLOCK_32x32].sse_pp(fenc + y1 * stride + x, stride, rec + y1 * stride + x, stride);
1166
1167
0
            if (size >= BLOCK_16x16)
1168
0
                for (; x + 16 <= width; x += 16)
1169
0
                    for (y1 = 0; y1 + 16 <= rowHeight; y1 += 16)
1170
0
                        ssd += primitives.cu[BLOCK_16x16].sse_pp(fenc + y1 * stride + x, stride, rec + y1 * stride + x, stride);
1171
1172
0
            if (size >= BLOCK_8x8)
1173
0
                for (; x + 8 <= width; x += 8)
1174
0
                    for (y1 = 0; y1 + 8 <= rowHeight; y1 += 8)
1175
0
                        ssd += primitives.cu[BLOCK_8x8].sse_pp(fenc + y1 * stride + x, stride, rec + y1 * stride + x, stride);
1176
1177
0
            for (; x + 4 <= width; x += 4)
1178
0
                for (y1 = 0; y1 + 4 <= rowHeight; y1 += 4)
1179
0
                    ssd += primitives.cu[BLOCK_4x4].sse_pp(fenc + y1 * stride + x, stride, rec + y1 * stride + x, stride);
1180
1181
0
            fenc += stride * rowHeight;
1182
0
            rec += stride * rowHeight;
1183
0
        }
1184
0
    }
1185
1186
    /* Handle last few rows of frames for videos 
1187
    with height not divisble by 4 */
1188
0
    uint32_t h = height % y;
1189
0
    if (param->bEnableFrameDuplication && h)
1190
0
    {
1191
0
        for (uint32_t i = 0; i < h; i++)
1192
0
        {
1193
0
            for (uint32_t j = 0; j < width; j++)
1194
0
            {
1195
0
                int diff = (int)(fenc[j] - rec[j]);
1196
0
                ssd += diff * diff;
1197
0
            }
1198
1199
0
            fenc += stride;
1200
0
            rec += stride;
1201
0
        }
1202
0
    }
1203
1204
0
    return ssd;
1205
0
}
1206
1207
//Compute the PSNR weightage between two pictures
1208
double Encoder::ComputePSNR(x265_picture *firstPic, x265_picture *secPic, x265_param *param)
1209
0
{
1210
0
    uint64_t ssdY = 0, ssdU = 0, ssdV = 0;
1211
0
    intptr_t strideL, strideC;
1212
0
    uint32_t widthL, heightL, widthC, heightC;
1213
0
    double psnrY = 0, psnrU = 0, psnrV = 0, psnrWeight = 0;
1214
0
    int width = firstPic->width;
1215
0
    int height = firstPic->height;
1216
0
    int hshift = CHROMA_H_SHIFT(firstPic->colorSpace);
1217
0
    int vshift = CHROMA_V_SHIFT(firstPic->colorSpace);
1218
0
    pixel *yFirstPic = NULL, *ySecPic = NULL;
1219
0
    pixel *uFirstPic = NULL, *uSecPic = NULL;
1220
0
    pixel *vFirstPic = NULL, *vSecPic = NULL;
1221
1222
0
    strideL = widthL = width;
1223
0
    heightL = height;
1224
1225
0
    strideC = widthC = widthL >> hshift;
1226
0
    heightC = heightL >> vshift;
1227
1228
0
    int size = width * height;
1229
0
    int maxvalY = 255 << (X265_DEPTH - 8);
1230
0
    int maxvalC = 255 << (X265_DEPTH - 8);
1231
0
    double refValueY = (double)maxvalY * maxvalY * size;
1232
0
    double refValueC = (double)maxvalC * maxvalC * size / 4.0;
1233
1234
0
    if (firstPic->bitDepth == 8 && X265_DEPTH == 8)
1235
0
    {
1236
0
        yFirstPic = (pixel*)firstPic->planes[0];
1237
0
        ySecPic = (pixel*)secPic->planes[0];
1238
0
        if (param->internalCsp != X265_CSP_I400)
1239
0
        {
1240
0
            uFirstPic = (pixel*)firstPic->planes[1];
1241
0
            uSecPic = (pixel*)secPic->planes[1];
1242
0
            vFirstPic = (pixel*)firstPic->planes[2];
1243
0
            vSecPic = (pixel*)secPic->planes[2];
1244
0
        }
1245
0
    }
1246
0
    else if (firstPic->bitDepth == 8 && X265_DEPTH > 8)
1247
0
    {
1248
0
        int shift = (X265_DEPTH - 8);
1249
0
        uint8_t *yChar1, *yChar2, *uChar1, *uChar2, *vChar1, *vChar2;
1250
1251
0
        yChar1 = (uint8_t*)firstPic->planes[0];
1252
0
        yChar2 = (uint8_t*)secPic->planes[0];
1253
1254
0
        primitives.planecopy_cp(yChar1, firstPic->stride[0] / sizeof(*yChar1), m_dupPicOne[0], firstPic->stride[0] / sizeof(*yChar1), width, height, shift);
1255
0
        primitives.planecopy_cp(yChar2, secPic->stride[0] / sizeof(*yChar2), m_dupPicTwo[0], secPic->stride[0] / sizeof(*yChar2), width, height, shift);
1256
1257
0
        if (param->internalCsp != X265_CSP_I400)
1258
0
        {
1259
0
            uChar1 = (uint8_t*)firstPic->planes[1];
1260
0
            uChar2 = (uint8_t*)secPic->planes[1];
1261
0
            vChar1 = (uint8_t*)firstPic->planes[2];
1262
0
            vChar2 = (uint8_t*)secPic->planes[2];
1263
1264
0
            primitives.planecopy_cp(uChar1, firstPic->stride[1] / sizeof(*uChar1), m_dupPicOne[1], firstPic->stride[1] / sizeof(*uChar1), widthC, heightC, shift);
1265
0
            primitives.planecopy_cp(uChar2, secPic->stride[1] / sizeof(*uChar2), m_dupPicTwo[1], secPic->stride[1] / sizeof(*uChar2), widthC, heightC, shift);
1266
1267
0
            primitives.planecopy_cp(vChar1, firstPic->stride[2] / sizeof(*vChar1), m_dupPicOne[2], firstPic->stride[2] / sizeof(*vChar1), widthC, heightC, shift);
1268
0
            primitives.planecopy_cp(vChar2, secPic->stride[2] / sizeof(*vChar2), m_dupPicTwo[2], secPic->stride[2] / sizeof(*vChar2), widthC, heightC, shift);
1269
0
        }
1270
0
    }
1271
0
    else
1272
0
    {
1273
0
        uint16_t *yShort1, *yShort2, *uShort1, *uShort2, *vShort1, *vShort2;
1274
        /* defensive programming, mask off bits that are supposed to be zero */
1275
0
        uint16_t mask = (1 << X265_DEPTH) - 1;
1276
0
        int shift = abs(firstPic->bitDepth - X265_DEPTH);
1277
1278
0
        yShort1 = (uint16_t*)firstPic->planes[0];
1279
0
        yShort2 = (uint16_t*)secPic->planes[0];
1280
1281
0
        if (firstPic->bitDepth > X265_DEPTH)
1282
0
        {
1283
            /* shift right and mask pixels to final size */
1284
0
            primitives.planecopy_sp(yShort1, firstPic->stride[0] / sizeof(*yShort1), m_dupPicOne[0], firstPic->stride[0] / sizeof(*yShort1), width, height, shift, mask);
1285
0
            primitives.planecopy_sp(yShort2, secPic->stride[0] / sizeof(*yShort2), m_dupPicTwo[0], secPic->stride[0] / sizeof(*yShort2), width, height, shift, mask);
1286
0
        }
1287
0
        else /* Case for (pic.bitDepth <= X265_DEPTH) */
1288
0
        {
1289
            /* shift left and mask pixels to final size */
1290
0
            primitives.planecopy_sp_shl(yShort1, firstPic->stride[0] / sizeof(*yShort1), m_dupPicOne[0], firstPic->stride[0] / sizeof(*yShort1), width, height, shift, mask);
1291
0
            primitives.planecopy_sp_shl(yShort2, secPic->stride[0] / sizeof(*yShort2), m_dupPicTwo[0], secPic->stride[0] / sizeof(*yShort2), width, height, shift, mask);
1292
0
        }
1293
1294
0
        if (param->internalCsp != X265_CSP_I400)
1295
0
        {
1296
0
            uShort1 = (uint16_t*)firstPic->planes[1];
1297
0
            uShort2 = (uint16_t*)secPic->planes[1];
1298
0
            vShort1 = (uint16_t*)firstPic->planes[2];
1299
0
            vShort2 = (uint16_t*)secPic->planes[2];
1300
1301
0
            if (firstPic->bitDepth > X265_DEPTH)
1302
0
            {
1303
0
                primitives.planecopy_sp(uShort1, firstPic->stride[1] / sizeof(*uShort1), m_dupPicOne[1], firstPic->stride[1] / sizeof(*uShort1), widthC, heightC, shift, mask);
1304
0
                primitives.planecopy_sp(uShort2, secPic->stride[1] / sizeof(*uShort2), m_dupPicTwo[1], secPic->stride[1] / sizeof(*uShort2), widthC, heightC, shift, mask);
1305
1306
0
                primitives.planecopy_sp(vShort1, firstPic->stride[2] / sizeof(*vShort1), m_dupPicOne[2], firstPic->stride[2] / sizeof(*vShort1), widthC, heightC, shift, mask);
1307
0
                primitives.planecopy_sp(vShort2, secPic->stride[2] / sizeof(*vShort2), m_dupPicTwo[2], secPic->stride[2] / sizeof(*vShort2), widthC, heightC, shift, mask);
1308
0
            }
1309
0
            else /* Case for (pic.bitDepth <= X265_DEPTH) */
1310
0
            {
1311
0
                primitives.planecopy_sp_shl(uShort1, firstPic->stride[1] / sizeof(*uShort1), m_dupPicOne[1], firstPic->stride[1] / sizeof(*uShort1), widthC, heightC, shift, mask);
1312
0
                primitives.planecopy_sp_shl(uShort2, secPic->stride[1] / sizeof(*uShort2), m_dupPicTwo[1], secPic->stride[1] / sizeof(*uShort2), widthC, heightC, shift, mask);
1313
1314
0
                primitives.planecopy_sp_shl(vShort1, firstPic->stride[2] / sizeof(*vShort1), m_dupPicOne[2], firstPic->stride[2] / sizeof(*vShort1), widthC, heightC, shift, mask);
1315
0
                primitives.planecopy_sp_shl(vShort2, secPic->stride[2] / sizeof(*vShort2), m_dupPicTwo[2], secPic->stride[2] / sizeof(*vShort2), widthC, heightC, shift, mask);
1316
0
            }
1317
0
        }
1318
0
    }
1319
1320
0
    if (!(firstPic->bitDepth == 8 && X265_DEPTH == 8))
1321
0
    {
1322
0
        yFirstPic = m_dupPicOne[0]; ySecPic = m_dupPicTwo[0];
1323
0
        uFirstPic = m_dupPicOne[1]; uSecPic = m_dupPicTwo[1];
1324
0
        vFirstPic = m_dupPicOne[2]; vSecPic = m_dupPicTwo[2];
1325
0
    }
1326
1327
    //Compute SSD
1328
0
    ssdY = computeSSD(yFirstPic, ySecPic, strideL, widthL, heightL, param);
1329
0
    psnrY = (ssdY ? 10.0 * log10(refValueY / (double)ssdY) : 99.99);
1330
1331
0
    if (param->internalCsp != X265_CSP_I400)
1332
0
    {
1333
0
        ssdU = computeSSD(uFirstPic, uSecPic, strideC, widthC, heightC, param);
1334
0
        ssdV = computeSSD(vFirstPic, vSecPic, strideC, widthC, heightC, param);
1335
0
        psnrU = (ssdU ? 10.0 * log10(refValueC / (double)ssdU) : 99.99);
1336
0
        psnrV = (ssdV ? 10.0 * log10(refValueC / (double)ssdV) : 99.99);
1337
0
    }
1338
1339
    //Compute PSNR(picN,pic(N+1))
1340
0
    return psnrWeight = (psnrY * 6 + psnrU + psnrV) / 8;
1341
0
}
1342
1343
void Encoder::copyPicture(x265_picture *dest, const x265_picture *src)
1344
0
{
1345
0
    dest->poc = src->poc;
1346
0
    dest->pts = src->pts;
1347
0
    dest->userSEI = src->userSEI;
1348
0
    dest->bitDepth = src->bitDepth;
1349
0
    dest->framesize = src->framesize;
1350
0
    dest->height = src->height;
1351
0
    dest->width = src->width;
1352
0
    dest->colorSpace = src->colorSpace;
1353
0
    dest->userSEI = src->userSEI;
1354
0
    dest->rpu.payload = src->rpu.payload;
1355
0
    dest->picStruct = src->picStruct;
1356
0
    dest->stride[0] = src->stride[0];
1357
0
    dest->stride[1] = src->stride[1];
1358
0
    dest->stride[2] = src->stride[2];
1359
0
    memcpy(dest->planes[0], src->planes[0], src->framesize * sizeof(char));
1360
0
    dest->planes[1] = (char*)dest->planes[0] + src->stride[0] * src->height;
1361
0
    dest->planes[2] = (char*)dest->planes[1] + src->stride[1] * (src->height >> x265_cli_csps[src->colorSpace].height[1]);
1362
0
}
1363
1364
bool Encoder::computeHistograms(x265_picture *pic)
1365
0
{
1366
0
    pixel *src = NULL, *planeV = NULL, *planeU = NULL;
1367
0
    uint32_t widthC, heightC;
1368
0
    int hshift, vshift;
1369
1370
0
    hshift = CHROMA_H_SHIFT(pic->colorSpace);
1371
0
    vshift = CHROMA_V_SHIFT(pic->colorSpace);
1372
0
    widthC = pic->width >> hshift;
1373
0
    heightC = pic->height >> vshift;
1374
1375
0
    if (pic->bitDepth == X265_DEPTH)
1376
0
    {
1377
0
        src = (pixel*)pic->planes[0];
1378
0
        if (m_param->internalCsp != X265_CSP_I400)
1379
0
        {
1380
0
            planeU = (pixel*)pic->planes[1];
1381
0
            planeV = (pixel*)pic->planes[2];
1382
0
        }
1383
0
    }
1384
0
    else if (pic->bitDepth == 8 && X265_DEPTH > 8)
1385
0
    {
1386
0
        int shift = (X265_DEPTH - 8);
1387
0
        uint8_t *yChar, *uChar, *vChar;
1388
1389
0
        yChar = (uint8_t*)pic->planes[0];
1390
0
        primitives.planecopy_cp(yChar, pic->stride[0] / sizeof(*yChar), m_inputPic[0], pic->stride[0] / sizeof(*yChar), pic->width, pic->height, shift);
1391
0
        src = m_inputPic[0];
1392
0
        if (m_param->internalCsp != X265_CSP_I400)
1393
0
        {
1394
0
            uChar = (uint8_t*)pic->planes[1];
1395
0
            vChar = (uint8_t*)pic->planes[2];
1396
0
            primitives.planecopy_cp(uChar, pic->stride[1] / sizeof(*uChar), m_inputPic[1], pic->stride[1] / sizeof(*uChar), widthC, heightC, shift);
1397
0
            primitives.planecopy_cp(vChar, pic->stride[2] / sizeof(*vChar), m_inputPic[2], pic->stride[2] / sizeof(*vChar), widthC, heightC, shift);
1398
0
            planeU = m_inputPic[1];
1399
0
            planeV = m_inputPic[2];
1400
0
        }
1401
0
    }
1402
0
    else
1403
0
    {
1404
0
        uint16_t *yShort, *uShort, *vShort;
1405
        /* mask off bits that are supposed to be zero */
1406
0
        uint16_t mask = (1 << X265_DEPTH) - 1;
1407
0
        int shift = abs(pic->bitDepth - X265_DEPTH);
1408
1409
0
        yShort = (uint16_t*)pic->planes[0];
1410
0
        uShort = (uint16_t*)pic->planes[1];
1411
0
        vShort = (uint16_t*)pic->planes[2];
1412
1413
0
        if (pic->bitDepth > X265_DEPTH)
1414
0
        {
1415
            /* shift right and mask pixels to final size */
1416
0
            primitives.planecopy_sp(yShort, pic->stride[0] / sizeof(*yShort), m_inputPic[0], pic->stride[0] / sizeof(*yShort), pic->width, pic->height, shift, mask);
1417
0
            if (m_param->internalCsp != X265_CSP_I400)
1418
0
            {
1419
0
                primitives.planecopy_sp(uShort, pic->stride[1] / sizeof(*uShort), m_inputPic[1], pic->stride[1] / sizeof(*uShort), widthC, heightC, shift, mask);
1420
0
                primitives.planecopy_sp(vShort, pic->stride[2] / sizeof(*vShort), m_inputPic[2], pic->stride[2] / sizeof(*vShort), widthC, heightC, shift, mask);
1421
0
            }
1422
0
        }
1423
0
        else /* Case for (pic.bitDepth < X265_DEPTH) */
1424
0
        {
1425
            /* shift left and mask pixels to final size */
1426
0
            primitives.planecopy_sp_shl(yShort, pic->stride[0] / sizeof(*yShort), m_inputPic[0], pic->stride[0] / sizeof(*yShort), pic->width, pic->height, shift, mask);
1427
0
            if (m_param->internalCsp != X265_CSP_I400)
1428
0
            {
1429
0
                primitives.planecopy_sp_shl(uShort, pic->stride[1] / sizeof(*uShort), m_inputPic[1], pic->stride[1] / sizeof(*uShort), widthC, heightC, shift, mask);
1430
0
                primitives.planecopy_sp_shl(vShort, pic->stride[2] / sizeof(*vShort), m_inputPic[2], pic->stride[2] / sizeof(*vShort), widthC, heightC, shift, mask);
1431
0
            }
1432
0
        }
1433
1434
0
        src = m_inputPic[0];
1435
0
        planeU = m_inputPic[1];
1436
0
        planeV = m_inputPic[2];
1437
0
    }
1438
1439
0
    size_t bufSize = sizeof(pixel) * m_planeSizes[0];
1440
0
    int32_t planeCount = x265_cli_csps[m_param->internalCsp].planes;
1441
0
    memset(m_edgePic, 0, bufSize);
1442
1443
0
    if (!computeEdge(m_edgePic, src, NULL, pic->width, pic->height, pic->width, false, 1))
1444
0
    {
1445
0
        x265_log(m_param, X265_LOG_ERROR, "Failed to compute edge!");
1446
0
        return false;
1447
0
    }
1448
1449
0
    pixel pixelVal;
1450
0
    int32_t *edgeHist = m_curEdgeHist;
1451
0
    memset(edgeHist, 0, 2 * sizeof(int32_t));
1452
0
    for (int64_t i = 0; i < m_planeSizes[0]; i++)
1453
0
    {
1454
0
        if (!m_edgePic[i])
1455
0
           edgeHist[0]++;
1456
0
        else
1457
0
           edgeHist[1]++;
1458
0
    }
1459
1460
0
    if (pic->colorSpace != X265_CSP_I400)
1461
0
    {
1462
        /* U Histogram Calculation */
1463
0
        int32_t *uHist = m_curUVHist[0];
1464
0
        memset(uHist, 0, HISTOGRAM_BINS * sizeof(int32_t));
1465
1466
0
        for (int64_t i = 0; i < m_planeSizes[1]; i++)
1467
0
        {
1468
0
            pixelVal = planeU[i];
1469
0
            uHist[pixelVal]++;
1470
0
        }
1471
1472
        /* V Histogram Calculation */
1473
0
        if (planeCount == 3)
1474
0
        {
1475
0
            pixelVal = 0;
1476
0
            int32_t *vHist = m_curUVHist[1];
1477
0
            memset(vHist, 0, HISTOGRAM_BINS * sizeof(int32_t));
1478
1479
0
            for (int64_t i = 0; i < m_planeSizes[2]; i++)
1480
0
            {
1481
0
                pixelVal = planeV[i];
1482
0
                vHist[pixelVal]++;
1483
0
            }
1484
0
            for (int i = 0; i < HISTOGRAM_BINS; i++)
1485
0
            {
1486
0
                m_curMaxUVHist[i] = x265_max(uHist[i], vHist[i]);
1487
0
            }
1488
0
        }
1489
0
        else
1490
0
        {   /* in case of bi planar color space */
1491
0
            memcpy(m_curMaxUVHist, m_curUVHist[0], HISTOGRAM_BINS * sizeof(int32_t));
1492
0
        }
1493
0
    }
1494
0
    return true;
1495
0
}
1496
1497
void Encoder::computeHistogramSAD(double *maxUVNormalizedSad, double *edgeNormalizedSad, int curPoc)
1498
0
{
1499
1500
0
    if (curPoc == 0)
1501
0
    {   /* first frame is scenecut by default no sad computation for the same. */
1502
0
        *maxUVNormalizedSad = 0.0;
1503
0
        *edgeNormalizedSad  = 0.0;
1504
0
    }
1505
0
    else
1506
0
    {
1507
        /* compute sum of absolute difference of normalized histogram bins for maxUV and edge histograms. */
1508
0
        int32_t edgefreqDiff = 0;
1509
0
        int32_t maxUVfreqDiff = 0;
1510
0
        double  edgeProbabilityDiff = 0;
1511
1512
0
        for (int j = 0; j < HISTOGRAM_BINS; j++)
1513
0
        {
1514
0
            if (j < 2)
1515
0
            {
1516
0
                edgefreqDiff = abs(m_curEdgeHist[j] - m_prevEdgeHist[j]);
1517
0
                edgeProbabilityDiff = (double) edgefreqDiff / m_planeSizes[0];
1518
0
                *edgeNormalizedSad += edgeProbabilityDiff;
1519
0
            }
1520
0
            maxUVfreqDiff = abs(m_curMaxUVHist[j] - m_prevMaxUVHist[j]);
1521
0
            *maxUVNormalizedSad += (double)maxUVfreqDiff / m_planeSizes[2];
1522
0
        }
1523
0
    }
1524
1525
    /* store histograms of previous frame for reference */
1526
0
    size_t bufsize = HISTOGRAM_BINS * sizeof(int32_t);
1527
0
    memcpy(m_prevMaxUVHist, m_curMaxUVHist, bufsize);
1528
0
    memcpy(m_prevEdgeHist, m_curEdgeHist, 2 * sizeof(int32_t));
1529
0
}
1530
1531
void Encoder::findSceneCuts(x265_picture *pic, bool& bDup, double maxUVSad, double edgeSad)
1532
0
{
1533
0
    pic->frameData.bScenecut = false;
1534
1535
0
    if (pic->poc == 0)
1536
0
    {
1537
        /* for first frame */
1538
0
        pic->frameData.bScenecut = false;
1539
0
        bDup = false;
1540
0
    }
1541
0
    else
1542
0
    {
1543
0
        if (edgeSad == 0.0 && maxUVSad == 0.0)
1544
0
        {
1545
0
            bDup = true;
1546
0
        }
1547
0
        else if (edgeSad > m_edgeHistThreshold && maxUVSad >= m_chromaHistThreshold)
1548
0
        {
1549
0
            pic->frameData.bScenecut = true;
1550
0
            bDup = false;
1551
0
        }
1552
0
        else if (edgeSad > m_scaledEdgeThreshold || maxUVSad >= m_scaledChromaThreshold)
1553
0
        {
1554
0
            pic->frameData.bScenecut = true;
1555
0
            bDup = false;
1556
0
        }
1557
0
    }
1558
1559
0
    if (pic->frameData.bScenecut)
1560
0
       x265_log(m_param, X265_LOG_DEBUG, "scene cut at %d \n", pic->poc);
1561
0
}
1562
1563
/**
1564
 * Feed one new input frame into the encoder, get one frame out. If pic_in is
1565
 * NULL, a flush condition is implied and pic_in must be NULL for all subsequent
1566
 * calls for this encoder instance.
1567
 *
1568
 * pic_in  input original YUV picture or NULL
1569
 * pic_out pointer to reconstructed picture struct
1570
 *
1571
 * returns 0 if no frames are currently available for output
1572
 *         1 if frame was output, m_nalList contains access unit
1573
 *         negative on malloc error or abort */
1574
int Encoder::encode(const x265_picture* pic_in, x265_picture* pic_out)
1575
0
{
1576
#if CHECKED_BUILD || _DEBUG
1577
    if (g_checkFailures)
1578
    {
1579
        x265_log(m_param, X265_LOG_ERROR, "encoder aborting because of internal error\n");
1580
        return -1;
1581
    }
1582
#endif
1583
0
    if (m_aborted)
1584
0
        return -1;
1585
1586
0
    const x265_picture* inputPic = NULL;
1587
0
    static int written = 0, read = 0;
1588
0
    bool dontRead = false;
1589
0
    bool bdropFrame = false;
1590
0
    bool dropflag = false;
1591
1592
0
    if (m_exportedPic)
1593
0
    {
1594
0
        if (!m_param->bUseAnalysisFile && m_param->analysisSave)
1595
0
            x265_free_analysis_data(m_param, &m_exportedPic->m_analysisData);
1596
0
        ATOMIC_DEC(&m_exportedPic->m_countRefEncoders);
1597
0
        m_exportedPic = NULL;
1598
0
        m_dpb->recycleUnreferenced();
1599
0
    }
1600
0
    if ((pic_in && (!m_param->chunkEnd || (m_encodedFrameNum < m_param->chunkEnd))) || (m_param->bEnableFrameDuplication && !pic_in && (read < written)))
1601
0
    {
1602
0
        if (m_param->bHistBasedSceneCut && pic_in)
1603
0
        {
1604
0
            x265_picture *pic = (x265_picture *) pic_in;
1605
1606
0
            if (pic->poc == 0)
1607
0
            {
1608
                /* for entire encode compute the chroma plane sizes only once */
1609
0
                for (int i = 1; i < x265_cli_csps[m_param->internalCsp].planes; i++)
1610
0
                    m_planeSizes[i] = (pic->width >> x265_cli_csps[m_param->internalCsp].width[i]) * (pic->height >> x265_cli_csps[m_param->internalCsp].height[i]);
1611
0
            }
1612
1613
0
            if (computeHistograms(pic))
1614
0
            {
1615
0
                double maxUVSad = 0.0, edgeSad = 0.0;
1616
0
                computeHistogramSAD(&maxUVSad, &edgeSad, pic_in->poc);
1617
0
                findSceneCuts(pic, bdropFrame, maxUVSad, edgeSad);
1618
0
            }
1619
0
        }
1620
1621
0
        if ((m_param->bEnableFrameDuplication && !pic_in && (read < written)))
1622
0
            dontRead = true;
1623
0
        else
1624
0
        {
1625
0
            if (m_latestParam->forceFlush == 1)
1626
0
            {
1627
0
                m_lookahead->setLookaheadQueue();
1628
0
                m_latestParam->forceFlush = 0;
1629
0
            }
1630
0
            if (m_latestParam->forceFlush == 2)
1631
0
            {
1632
0
                m_lookahead->m_filled = false;
1633
0
                m_latestParam->forceFlush = 0;
1634
0
            }
1635
1636
0
            if (pic_in->bitDepth < 8 || pic_in->bitDepth > 16)
1637
0
            {
1638
0
                x265_log(m_param, X265_LOG_ERROR, "Input bit depth (%d) must be between 8 and 16\n",
1639
0
                         pic_in->bitDepth);
1640
0
                return -1;
1641
0
            }
1642
0
        }
1643
1644
0
        if (m_param->bEnableFrameDuplication)
1645
0
        {
1646
0
            double psnrWeight = 0;
1647
1648
0
            if (!dontRead)
1649
0
            {
1650
0
                if (!m_dupBuffer[0]->bOccupied)
1651
0
                {
1652
0
                    copyPicture(m_dupBuffer[0]->dupPic, pic_in);
1653
0
                    m_dupBuffer[0]->bOccupied = true;
1654
0
                    written++;
1655
0
                    return 0;
1656
0
                }
1657
0
                else if (!m_dupBuffer[1]->bOccupied)
1658
0
                {
1659
0
                    copyPicture(m_dupBuffer[1]->dupPic, pic_in);
1660
0
                    m_dupBuffer[1]->bOccupied = true;
1661
0
                    written++;
1662
0
                }
1663
1664
0
                if (m_param->bEnableFrameDuplication && m_param->bHistBasedSceneCut)
1665
0
                {
1666
0
                    if (!bdropFrame && m_dupBuffer[1]->dupPic->frameData.bScenecut == false)
1667
0
                    {
1668
0
                        psnrWeight = ComputePSNR(m_dupBuffer[0]->dupPic, m_dupBuffer[1]->dupPic, m_param);
1669
0
                        if (psnrWeight >= m_param->dupThreshold)
1670
0
                            dropflag = true;
1671
0
                    }
1672
0
                    else
1673
0
                    {
1674
0
                        dropflag = true;
1675
0
                    }
1676
0
                }
1677
0
                else if (m_param->bEnableFrameDuplication)
1678
0
                {
1679
0
                    psnrWeight = ComputePSNR(m_dupBuffer[0]->dupPic, m_dupBuffer[1]->dupPic, m_param);
1680
0
                    if (psnrWeight >= m_param->dupThreshold)
1681
0
                        dropflag = true;
1682
0
                }
1683
1684
0
                if (dropflag)
1685
0
                {
1686
0
                    if (m_dupBuffer[0]->bDup)
1687
0
                    {
1688
0
                        m_dupBuffer[0]->dupPic->picStruct = tripling;
1689
0
                        m_dupBuffer[0]->bDup = false;
1690
0
                        read++;
1691
0
                    }
1692
0
                    else
1693
0
                    {
1694
0
                        m_dupBuffer[0]->dupPic->picStruct = doubling;
1695
0
                        m_dupBuffer[0]->bDup = true;
1696
0
                        m_dupBuffer[1]->bOccupied = false;
1697
0
                        read++;
1698
0
                        return 0;
1699
0
                    }
1700
0
                }
1701
0
                else if (m_dupBuffer[0]->bDup)
1702
0
                    m_dupBuffer[0]->bDup = false;
1703
0
                else
1704
0
                    m_dupBuffer[0]->dupPic->picStruct = 0;
1705
0
            }
1706
1707
0
            if (read < written)
1708
0
            {
1709
0
                inputPic = m_dupBuffer[0]->dupPic;
1710
0
                read++;
1711
0
            }
1712
0
        }
1713
0
        else
1714
0
            inputPic = pic_in;
1715
1716
0
        Frame *inFrame;
1717
0
        x265_param *p = (m_reconfigure || m_reconfigureRc) ? m_latestParam : m_param;
1718
0
        if (m_dpb->m_freeList.empty())
1719
0
        {
1720
0
            inFrame = new Frame;
1721
0
            inFrame->m_encodeStartTime = x265_mdate();
1722
0
            if (inFrame->create(p, inputPic->quantOffsets))
1723
0
            {
1724
                /* the first PicYuv created is asked to generate the CU and block unit offset
1725
                 * arrays which are then shared with all subsequent PicYuv (orig and recon) 
1726
                 * allocated by this top level encoder */
1727
0
                if (m_sps.cuOffsetY)
1728
0
                {
1729
0
                    inFrame->m_fencPic->m_cuOffsetY = m_sps.cuOffsetY;
1730
0
                    inFrame->m_fencPic->m_buOffsetY = m_sps.buOffsetY;
1731
0
                    if (m_param->internalCsp != X265_CSP_I400)
1732
0
                    {
1733
0
                        inFrame->m_fencPic->m_cuOffsetC = m_sps.cuOffsetC;
1734
0
                        inFrame->m_fencPic->m_buOffsetC = m_sps.buOffsetC;
1735
0
                    }
1736
0
                }
1737
0
                else
1738
0
                {
1739
0
                    if (!inFrame->m_fencPic->createOffsets(m_sps))
1740
0
                    {
1741
0
                        m_aborted = true;
1742
0
                        x265_log(m_param, X265_LOG_ERROR, "memory allocation failure, aborting encode\n");
1743
0
                        inFrame->destroy();
1744
0
                        delete inFrame;
1745
0
                        return -1;
1746
0
                    }
1747
0
                    else
1748
0
                    {
1749
0
                        m_sps.cuOffsetY = inFrame->m_fencPic->m_cuOffsetY;
1750
0
                        m_sps.buOffsetY = inFrame->m_fencPic->m_buOffsetY;
1751
0
                        if (m_param->internalCsp != X265_CSP_I400)
1752
0
                        {
1753
0
                            m_sps.cuOffsetC = inFrame->m_fencPic->m_cuOffsetC;
1754
0
                            m_sps.cuOffsetY = inFrame->m_fencPic->m_cuOffsetY;
1755
0
                            m_sps.buOffsetC = inFrame->m_fencPic->m_buOffsetC;
1756
0
                            m_sps.buOffsetY = inFrame->m_fencPic->m_buOffsetY;
1757
0
                        }
1758
0
                    }
1759
0
                }
1760
0
                if (m_param->recursionSkipMode == EDGE_BASED_RSKIP && m_param->bHistBasedSceneCut)
1761
0
                {
1762
0
                    pixel* src = m_edgePic;
1763
0
                    primitives.planecopy_pp_shr(src, inFrame->m_fencPic->m_picWidth, inFrame->m_edgeBitPic, inFrame->m_fencPic->m_stride,
1764
0
                        inFrame->m_fencPic->m_picWidth, inFrame->m_fencPic->m_picHeight, 0);
1765
0
                }
1766
0
            }
1767
0
            else
1768
0
            {
1769
0
                m_aborted = true;
1770
0
                x265_log(m_param, X265_LOG_ERROR, "memory allocation failure, aborting encode\n");
1771
0
                inFrame->destroy();
1772
0
                delete inFrame;
1773
0
                return -1;
1774
0
            }
1775
0
        }
1776
0
        else
1777
0
        {
1778
0
            inFrame = m_dpb->m_freeList.popBack();
1779
0
            inFrame->m_encodeStartTime = x265_mdate();
1780
            /* Set lowres scencut and satdCost here to aovid overwriting ANALYSIS_READ
1781
               decision by lowres init*/
1782
0
            inFrame->m_lowres.bScenecut = false;
1783
0
            inFrame->m_lowres.satdCost = (int64_t)-1;
1784
0
            inFrame->m_lowresInit = false;
1785
0
        }
1786
1787
        /* Copy input picture into a Frame and PicYuv, send to lookahead */
1788
0
        inFrame->m_fencPic->copyFromPicture(*inputPic, *m_param, m_sps.conformanceWindow.rightOffset, m_sps.conformanceWindow.bottomOffset);
1789
1790
0
        inFrame->m_poc       = ++m_pocLast;
1791
0
        inFrame->m_userData  = inputPic->userData;
1792
0
        inFrame->m_pts       = inputPic->pts;
1793
0
        if (m_param->bHistBasedSceneCut)
1794
0
        {
1795
0
            inFrame->m_lowres.bScenecut = (inputPic->frameData.bScenecut == 1) ? true : false;
1796
0
        }
1797
0
        inFrame->m_forceqp   = inputPic->forceqp;
1798
0
        inFrame->m_param     = (m_reconfigure || m_reconfigureRc) ? m_latestParam : m_param;
1799
0
        inFrame->m_picStruct = inputPic->picStruct;
1800
0
        if (m_param->bField && m_param->interlaceMode)
1801
0
            inFrame->m_fieldNum = inputPic->fieldNum;
1802
1803
0
        copyUserSEIMessages(inFrame, inputPic);
1804
1805
        /*Copy Dolby Vision RPU from inputPic to frame*/
1806
0
        if (inputPic->rpu.payloadSize)
1807
0
        {
1808
0
            inFrame->m_rpu.payloadSize = inputPic->rpu.payloadSize;
1809
0
            inFrame->m_rpu.payload = new uint8_t[inputPic->rpu.payloadSize];
1810
0
            memcpy(inFrame->m_rpu.payload, inputPic->rpu.payload, inputPic->rpu.payloadSize);
1811
0
        }
1812
1813
0
        if (inputPic->quantOffsets != NULL)
1814
0
        {
1815
0
            int cuCount;
1816
0
            if (m_param->rc.qgSize == 8)
1817
0
                cuCount = inFrame->m_lowres.maxBlocksInRowFullRes * inFrame->m_lowres.maxBlocksInColFullRes;
1818
0
            else
1819
0
                cuCount = inFrame->m_lowres.maxBlocksInRow * inFrame->m_lowres.maxBlocksInCol;
1820
0
            memcpy(inFrame->m_quantOffsets, inputPic->quantOffsets, cuCount * sizeof(float));
1821
0
        }
1822
1823
0
        if (m_pocLast == 0)
1824
0
            m_firstPts = inFrame->m_pts;
1825
0
        if (m_bframeDelay && m_pocLast == m_bframeDelay)
1826
0
            m_bframeDelayTime = inFrame->m_pts - m_firstPts;
1827
1828
        /* Encoder holds a reference count until stats collection is finished */
1829
0
        ATOMIC_INC(&inFrame->m_countRefEncoders);
1830
1831
0
        if ((m_param->rc.aqMode || m_param->bEnableWeightedPred || m_param->bEnableWeightedBiPred) &&
1832
0
            (m_param->rc.cuTree && m_param->rc.bStatRead))
1833
0
        {
1834
0
            if (!m_rateControl->cuTreeReadFor2Pass(inFrame))
1835
0
            {
1836
0
                m_aborted = 1;
1837
0
                return -1;
1838
0
            }
1839
0
        }
1840
1841
        /* Use the frame types from the first pass, if available */
1842
0
        int sliceType = (m_param->rc.bStatRead) ? m_rateControl->rateControlSliceType(inFrame->m_poc) : inputPic->sliceType;
1843
1844
        /* In analysisSave mode, x265_analysis_data is allocated in inputPic and inFrame points to this */
1845
        /* Load analysis data before lookahead->addPicture, since sliceType has been decided */
1846
0
        if (m_param->analysisLoad)
1847
0
        {
1848
            /* reads analysis data for the frame and allocates memory based on slicetype */
1849
0
            static int paramBytes = CONF_OFFSET_BYTES;
1850
0
            if (!inFrame->m_poc && m_param->bAnalysisType != HEVC_INFO)
1851
0
            {
1852
0
                x265_analysis_validate saveParam = inputPic->analysisData.saveParam;
1853
0
                paramBytes += validateAnalysisData(&saveParam, 0);
1854
0
                if (paramBytes == -1)
1855
0
                {
1856
0
                    m_aborted = true;
1857
0
                    return -1;
1858
0
                }
1859
0
            }
1860
0
            if (m_saveCTUSize)
1861
0
            {
1862
0
                cuLocation cuLocInFrame;
1863
0
                cuLocInFrame.init(m_param);
1864
                /* Set skipWidth/skipHeight flags when the out of bound pixels in lowRes is greater than half of maxCUSize */
1865
0
                int extendedWidth = ((m_param->sourceWidth / 2 + m_param->maxCUSize - 1) >> m_param->maxLog2CUSize) * m_param->maxCUSize;
1866
0
                int extendedHeight = ((m_param->sourceHeight / 2 + m_param->maxCUSize - 1) >> m_param->maxLog2CUSize) * m_param->maxCUSize;
1867
0
                uint32_t outOfBoundaryLowres = extendedWidth - m_param->sourceWidth / 2;
1868
0
                if (outOfBoundaryLowres * 2 >= m_param->maxCUSize)
1869
0
                    cuLocInFrame.skipWidth = true;
1870
0
                uint32_t outOfBoundaryLowresH = extendedHeight - m_param->sourceHeight / 2;
1871
0
                if (outOfBoundaryLowresH * 2 >= m_param->maxCUSize)
1872
0
                    cuLocInFrame.skipHeight = true;
1873
0
                readAnalysisFile(&inFrame->m_analysisData, inFrame->m_poc, inputPic, paramBytes, cuLocInFrame);
1874
0
            }
1875
0
            else
1876
0
                readAnalysisFile(&inFrame->m_analysisData, inFrame->m_poc, inputPic, paramBytes);
1877
0
            inFrame->m_poc = inFrame->m_analysisData.poc;
1878
0
            sliceType = inFrame->m_analysisData.sliceType;
1879
0
            inFrame->m_lowres.bScenecut = !!inFrame->m_analysisData.bScenecut;
1880
0
            inFrame->m_lowres.satdCost = inFrame->m_analysisData.satdCost;
1881
0
            if (m_param->bDisableLookahead)
1882
0
            {
1883
0
                inFrame->m_lowres.sliceType = sliceType;
1884
0
                inFrame->m_lowres.bKeyframe = !!inFrame->m_analysisData.lookahead.keyframe;
1885
0
                inFrame->m_lowres.bLastMiniGopBFrame = !!inFrame->m_analysisData.lookahead.lastMiniGopBFrame;
1886
0
                if (m_rateControl->m_isVbv)
1887
0
                {
1888
0
                    int vbvCount = m_param->lookaheadDepth + m_param->bframes + 2;
1889
0
                    for (int index = 0; index < vbvCount; index++)
1890
0
                    {
1891
0
                        inFrame->m_lowres.plannedSatd[index] = inFrame->m_analysisData.lookahead.plannedSatd[index];
1892
0
                        inFrame->m_lowres.plannedType[index] = inFrame->m_analysisData.lookahead.plannedType[index];
1893
0
                    }
1894
0
                }
1895
0
            }
1896
0
        }
1897
0
        if (m_param->bUseRcStats && inputPic->rcData)
1898
0
        {
1899
0
            RcStats* rc = (RcStats*)inputPic->rcData;
1900
0
            m_rateControl->m_accumPQp = rc->cumulativePQp;
1901
0
            m_rateControl->m_accumPNorm = rc->cumulativePNorm;
1902
0
            m_rateControl->m_isNextGop = true;
1903
0
            for (int j = 0; j < 3; j++)
1904
0
                m_rateControl->m_lastQScaleFor[j] = rc->lastQScaleFor[j];
1905
0
            m_rateControl->m_wantedBitsWindow = rc->wantedBitsWindow;
1906
0
            m_rateControl->m_cplxrSum = rc->cplxrSum;
1907
0
            m_rateControl->m_totalBits = rc->totalBits;
1908
0
            m_rateControl->m_encodedBits = rc->encodedBits;
1909
0
            m_rateControl->m_shortTermCplxSum = rc->shortTermCplxSum;
1910
0
            m_rateControl->m_shortTermCplxCount = rc->shortTermCplxCount;
1911
0
            if (m_rateControl->m_isVbv)
1912
0
            {
1913
0
                m_rateControl->m_bufferFillFinal = rc->bufferFillFinal;
1914
0
                for (int i = 0; i < 4; i++)
1915
0
                {
1916
0
                    m_rateControl->m_pred[i].coeff = rc->coeff[i];
1917
0
                    m_rateControl->m_pred[i].count = rc->count[i];
1918
0
                    m_rateControl->m_pred[i].offset = rc->offset[i];
1919
0
                }
1920
0
            }
1921
0
            m_param->bUseRcStats = 0;
1922
0
        }
1923
1924
0
        if (m_param->bEnableFrameDuplication && ((read < written) || (m_dupBuffer[0]->dupPic->picStruct == tripling && (read <= written))))
1925
0
        {
1926
0
            if (m_dupBuffer[0]->dupPic->picStruct == tripling)
1927
0
                m_dupBuffer[0]->bOccupied = m_dupBuffer[1]->bOccupied = false;
1928
0
            else
1929
0
            {
1930
0
                copyPicture(m_dupBuffer[0]->dupPic, m_dupBuffer[1]->dupPic);
1931
0
                m_dupBuffer[1]->bOccupied = false;
1932
0
            }
1933
0
        }
1934
1935
0
        if (m_reconfigureRc)
1936
0
            inFrame->m_reconfigureRc = true;
1937
1938
0
        m_lookahead->addPicture(*inFrame, sliceType);
1939
0
        m_numDelayedPic++;
1940
0
    }
1941
0
    else if (m_latestParam->forceFlush == 2)
1942
0
        m_lookahead->m_filled = true;
1943
0
    else
1944
0
        m_lookahead->flush();
1945
1946
0
    FrameEncoder *curEncoder = m_frameEncoder[m_curEncoder];
1947
0
    m_curEncoder = (m_curEncoder + 1) % m_param->frameNumThreads;
1948
0
    int ret = 0;
1949
1950
    /* Normal operation is to wait for the current frame encoder to complete its current frame
1951
     * and then to give it a new frame to work on.  In zero-latency mode, we must encode this
1952
     * input picture before returning so the order must be reversed. This do/while() loop allows
1953
     * us to alternate the order of the calls without ugly code replication */
1954
0
    Frame* outFrame = NULL;
1955
0
    Frame* frameEnc = NULL;
1956
0
    int pass = 0;
1957
0
    do
1958
0
    {
1959
        /* getEncodedPicture() should block until the FrameEncoder has completed
1960
         * encoding the frame.  This is how back-pressure through the API is
1961
         * accomplished when the encoder is full */
1962
0
        if (!m_bZeroLatency || pass)
1963
0
            outFrame = curEncoder->getEncodedPicture(m_nalList);
1964
0
        if (outFrame)
1965
0
        {
1966
0
            Slice *slice = outFrame->m_encData->m_slice;
1967
0
            x265_frame_stats* frameData = NULL;
1968
1969
            /* Free up inputPic->analysisData since it has already been used */
1970
0
            if ((m_param->analysisLoad && !m_param->analysisSave) || ((m_param->bAnalysisType == AVC_INFO) && slice->m_sliceType != I_SLICE))
1971
0
                x265_free_analysis_data(m_param, &outFrame->m_analysisData);
1972
1973
0
            if (pic_out)
1974
0
            {
1975
0
                PicYuv *recpic = outFrame->m_reconPic;
1976
0
                pic_out->poc = slice->m_poc;
1977
0
                pic_out->bitDepth = X265_DEPTH;
1978
0
                pic_out->userData = outFrame->m_userData;
1979
0
                pic_out->colorSpace = m_param->internalCsp;
1980
0
                frameData = &(pic_out->frameData);
1981
1982
0
                pic_out->pts = outFrame->m_pts;
1983
0
                pic_out->dts = outFrame->m_dts;
1984
0
                pic_out->reorderedPts = outFrame->m_reorderedPts;
1985
0
                pic_out->sliceType = outFrame->m_lowres.sliceType;
1986
0
                pic_out->planes[0] = recpic->m_picOrg[0];
1987
0
                pic_out->stride[0] = (int)(recpic->m_stride * sizeof(pixel));
1988
0
                if (m_param->internalCsp != X265_CSP_I400)
1989
0
                {
1990
0
                    pic_out->planes[1] = recpic->m_picOrg[1];
1991
0
                    pic_out->stride[1] = (int)(recpic->m_strideC * sizeof(pixel));
1992
0
                    pic_out->planes[2] = recpic->m_picOrg[2];
1993
0
                    pic_out->stride[2] = (int)(recpic->m_strideC * sizeof(pixel));
1994
0
                }
1995
1996
                /* Dump analysis data from pic_out to file in save mode and free */
1997
0
                if (m_param->analysisSave)
1998
0
                {
1999
0
                    pic_out->analysisData.poc = pic_out->poc;
2000
0
                    pic_out->analysisData.sliceType = pic_out->sliceType;
2001
0
                    pic_out->analysisData.bScenecut = outFrame->m_lowres.bScenecut;
2002
0
                    pic_out->analysisData.satdCost  = outFrame->m_lowres.satdCost;
2003
0
                    pic_out->analysisData.numCUsInFrame = outFrame->m_analysisData.numCUsInFrame;
2004
0
                    pic_out->analysisData.numPartitions = outFrame->m_analysisData.numPartitions;
2005
0
                    pic_out->analysisData.wt = outFrame->m_analysisData.wt;
2006
0
                    pic_out->analysisData.interData = outFrame->m_analysisData.interData;
2007
0
                    pic_out->analysisData.intraData = outFrame->m_analysisData.intraData;
2008
0
                    pic_out->analysisData.distortionData = outFrame->m_analysisData.distortionData;
2009
0
                    pic_out->analysisData.modeFlag[0] = outFrame->m_analysisData.modeFlag[0];
2010
0
                    pic_out->analysisData.modeFlag[1] = outFrame->m_analysisData.modeFlag[1];
2011
0
                    if (m_param->bDisableLookahead)
2012
0
                    {
2013
0
                        int factor = 1;
2014
0
                        if (m_param->scaleFactor)
2015
0
                            factor = m_param->scaleFactor * 2;
2016
0
                        pic_out->analysisData.numCuInHeight = outFrame->m_analysisData.numCuInHeight;
2017
0
                        pic_out->analysisData.lookahead.dts = outFrame->m_dts;
2018
0
                        pic_out->analysisData.lookahead.reorderedPts = outFrame->m_reorderedPts;
2019
0
                        pic_out->analysisData.satdCost *= factor;
2020
0
                        pic_out->analysisData.lookahead.keyframe = outFrame->m_lowres.bKeyframe;
2021
0
                        pic_out->analysisData.lookahead.lastMiniGopBFrame = outFrame->m_lowres.bLastMiniGopBFrame;
2022
0
                        if (m_rateControl->m_isVbv)
2023
0
                        {
2024
0
                            int vbvCount = m_param->lookaheadDepth + m_param->bframes + 2;
2025
0
                            for (int index = 0; index < vbvCount; index++)
2026
0
                            {
2027
0
                                pic_out->analysisData.lookahead.plannedSatd[index] = outFrame->m_lowres.plannedSatd[index];
2028
0
                                pic_out->analysisData.lookahead.plannedType[index] = outFrame->m_lowres.plannedType[index];
2029
0
                            }
2030
0
                            for (uint32_t index = 0; index < pic_out->analysisData.numCuInHeight; index++)
2031
0
                            {
2032
0
                                outFrame->m_analysisData.lookahead.intraSatdForVbv[index] = outFrame->m_encData->m_rowStat[index].intraSatdForVbv;
2033
0
                                outFrame->m_analysisData.lookahead.satdForVbv[index] = outFrame->m_encData->m_rowStat[index].satdForVbv;
2034
0
                            }
2035
0
                            pic_out->analysisData.lookahead.intraSatdForVbv = outFrame->m_analysisData.lookahead.intraSatdForVbv;
2036
0
                            pic_out->analysisData.lookahead.satdForVbv = outFrame->m_analysisData.lookahead.satdForVbv;
2037
0
                            for (uint32_t index = 0; index < pic_out->analysisData.numCUsInFrame; index++)
2038
0
                            {
2039
0
                                outFrame->m_analysisData.lookahead.intraVbvCost[index] = outFrame->m_encData->m_cuStat[index].intraVbvCost;
2040
0
                                outFrame->m_analysisData.lookahead.vbvCost[index] = outFrame->m_encData->m_cuStat[index].vbvCost;
2041
0
                            }
2042
0
                            pic_out->analysisData.lookahead.intraVbvCost = outFrame->m_analysisData.lookahead.intraVbvCost;
2043
0
                            pic_out->analysisData.lookahead.vbvCost = outFrame->m_analysisData.lookahead.vbvCost;
2044
0
                        }
2045
0
                    }
2046
0
                    writeAnalysisFile(&pic_out->analysisData, *outFrame->m_encData);
2047
0
                    pic_out->analysisData.saveParam = pic_out->analysisData.saveParam;
2048
0
                    if (m_param->bUseAnalysisFile)
2049
0
                        x265_free_analysis_data(m_param, &pic_out->analysisData);
2050
0
                }
2051
0
            }
2052
0
            if (m_param->rc.bStatWrite && (m_param->analysisMultiPassRefine || m_param->analysisMultiPassDistortion))
2053
0
            {
2054
0
                if (pic_out)
2055
0
                {
2056
0
                    pic_out->analysisData.poc = pic_out->poc;
2057
0
                    pic_out->analysisData.interData = outFrame->m_analysisData.interData;
2058
0
                    pic_out->analysisData.intraData = outFrame->m_analysisData.intraData;
2059
0
                    pic_out->analysisData.distortionData = outFrame->m_analysisData.distortionData;
2060
0
                }
2061
0
                writeAnalysisFileRefine(&outFrame->m_analysisData, *outFrame->m_encData);
2062
0
            }
2063
0
            if (m_param->analysisMultiPassRefine || m_param->analysisMultiPassDistortion)
2064
0
                x265_free_analysis_data(m_param, &outFrame->m_analysisData);
2065
0
            if (m_param->internalCsp == X265_CSP_I400)
2066
0
            {
2067
0
                if (slice->m_sliceType == P_SLICE)
2068
0
                {
2069
0
                    if (slice->m_weightPredTable[0][0][0].wtPresent)
2070
0
                        m_numLumaWPFrames++;
2071
0
                }
2072
0
                else if (slice->m_sliceType == B_SLICE)
2073
0
                {
2074
0
                    bool bLuma = false;
2075
0
                    for (int l = 0; l < 2; l++)
2076
0
                    {
2077
0
                        if (slice->m_weightPredTable[l][0][0].wtPresent)
2078
0
                            bLuma = true;
2079
0
                    }
2080
0
                    if (bLuma)
2081
0
                        m_numLumaWPBiFrames++;
2082
0
                }
2083
0
            }
2084
0
            else
2085
0
            {
2086
0
                if (slice->m_sliceType == P_SLICE)
2087
0
                {
2088
0
                    if (slice->m_weightPredTable[0][0][0].wtPresent)
2089
0
                        m_numLumaWPFrames++;
2090
0
                    if (slice->m_weightPredTable[0][0][1].wtPresent ||
2091
0
                        slice->m_weightPredTable[0][0][2].wtPresent)
2092
0
                        m_numChromaWPFrames++;
2093
0
                }
2094
0
                else if (slice->m_sliceType == B_SLICE)
2095
0
                {
2096
0
                    bool bLuma = false, bChroma = false;
2097
0
                    for (int l = 0; l < 2; l++)
2098
0
                    {
2099
0
                        if (slice->m_weightPredTable[l][0][0].wtPresent)
2100
0
                            bLuma = true;
2101
0
                        if (slice->m_weightPredTable[l][0][1].wtPresent ||
2102
0
                            slice->m_weightPredTable[l][0][2].wtPresent)
2103
0
                            bChroma = true;
2104
0
                    }
2105
2106
0
                    if (bLuma)
2107
0
                        m_numLumaWPBiFrames++;
2108
0
                    if (bChroma)
2109
0
                        m_numChromaWPBiFrames++;
2110
0
                }
2111
0
            }
2112
0
            if (m_aborted)
2113
0
                return -1;
2114
2115
0
            if ((m_outputCount + 1)  >= m_param->chunkStart)
2116
0
                finishFrameStats(outFrame, curEncoder, frameData, m_pocLast);
2117
0
            if (m_param->analysisSave)
2118
0
            {
2119
0
                pic_out->analysisData.frameBits = frameData->bits;
2120
0
                if (!slice->isIntra())
2121
0
                {
2122
0
                    for (int ref = 0; ref < MAX_NUM_REF; ref++)
2123
0
                        pic_out->analysisData.list0POC[ref] = frameData->list0POC[ref];
2124
2125
0
                    double totalIntraPercent = 0;
2126
2127
0
                    for (uint32_t depth = 0; depth < m_param->maxCUDepth; depth++)
2128
0
                        for (uint32_t intramode = 0; intramode < 3; intramode++)
2129
0
                            totalIntraPercent += frameData->cuStats.percentIntraDistribution[depth][intramode];
2130
0
                    totalIntraPercent += frameData->cuStats.percentIntraNxN;
2131
2132
0
                    for (uint32_t depth = 0; depth < m_param->maxCUDepth; depth++)
2133
0
                        totalIntraPercent += frameData->puStats.percentIntraPu[depth];
2134
0
                    pic_out->analysisData.totalIntraPercent = totalIntraPercent;
2135
2136
0
                    if (!slice->isInterP())
2137
0
                    {
2138
0
                        for (int ref = 0; ref < MAX_NUM_REF; ref++)
2139
0
                            pic_out->analysisData.list1POC[ref] = frameData->list1POC[ref];
2140
0
                    }
2141
0
                }
2142
0
            }
2143
2144
            /* Write RateControl Frame level stats in multipass encodes */
2145
0
            if (m_param->rc.bStatWrite)
2146
0
                if (m_rateControl->writeRateControlFrameStats(outFrame, &curEncoder->m_rce))
2147
0
                    m_aborted = true;
2148
0
            if (pic_out)
2149
0
            { 
2150
                /* m_rcData is allocated for every frame */
2151
0
                pic_out->rcData = outFrame->m_rcData;
2152
0
                outFrame->m_rcData->qpaRc = outFrame->m_encData->m_avgQpRc;
2153
0
                outFrame->m_rcData->qRceq = curEncoder->m_rce.qRceq;
2154
0
                outFrame->m_rcData->qpNoVbv = curEncoder->m_rce.qpNoVbv;
2155
0
                outFrame->m_rcData->coeffBits = outFrame->m_encData->m_frameStats.coeffBits;
2156
0
                outFrame->m_rcData->miscBits = outFrame->m_encData->m_frameStats.miscBits;
2157
0
                outFrame->m_rcData->mvBits = outFrame->m_encData->m_frameStats.mvBits;
2158
0
                outFrame->m_rcData->qScale = outFrame->m_rcData->newQScale = x265_qp2qScale(outFrame->m_encData->m_avgQpRc);
2159
0
                outFrame->m_rcData->poc = curEncoder->m_rce.poc;
2160
0
                outFrame->m_rcData->encodeOrder = curEncoder->m_rce.encodeOrder;
2161
0
                outFrame->m_rcData->sliceType = curEncoder->m_rce.sliceType;
2162
0
                outFrame->m_rcData->keptAsRef = curEncoder->m_rce.sliceType == B_SLICE && !IS_REFERENCED(outFrame) ? 0 : 1;
2163
0
                outFrame->m_rcData->qpAq = outFrame->m_encData->m_avgQpAq;
2164
0
                outFrame->m_rcData->iCuCount = outFrame->m_encData->m_frameStats.percent8x8Intra * m_rateControl->m_ncu;
2165
0
                outFrame->m_rcData->pCuCount = outFrame->m_encData->m_frameStats.percent8x8Inter * m_rateControl->m_ncu;
2166
0
                outFrame->m_rcData->skipCuCount = outFrame->m_encData->m_frameStats.percent8x8Skip  * m_rateControl->m_ncu;
2167
0
            }
2168
2169
            /* Allow this frame to be recycled if no frame encoders are using it for reference */
2170
0
            if (!pic_out)
2171
0
            {
2172
0
                ATOMIC_DEC(&outFrame->m_countRefEncoders);
2173
0
                m_dpb->recycleUnreferenced();
2174
0
            }
2175
0
            else
2176
0
                m_exportedPic = outFrame;
2177
            
2178
0
            m_outputCount++;
2179
0
            if (m_param->chunkEnd == m_outputCount)
2180
0
                m_numDelayedPic = 0;
2181
0
            else 
2182
0
                m_numDelayedPic--;
2183
2184
0
            ret = 1;
2185
0
        }
2186
2187
        /* pop a single frame from decided list, then provide to frame encoder
2188
         * curEncoder is guaranteed to be idle at this point */
2189
0
        if (!pass)
2190
0
            frameEnc = m_lookahead->getDecidedPicture();
2191
0
        if (frameEnc && !pass && (!m_param->chunkEnd || (m_encodedFrameNum < m_param->chunkEnd)))
2192
0
        {
2193
0
            if (m_param->bEnableSceneCutAwareQp && frameEnc->m_lowres.bScenecut)
2194
0
                m_rateControl->m_lastScenecut = frameEnc->m_poc;
2195
2196
0
            if (m_param->analysisMultiPassRefine || m_param->analysisMultiPassDistortion)
2197
0
            {
2198
0
                uint32_t widthInCU = (m_param->sourceWidth + m_param->maxCUSize - 1) >> m_param->maxLog2CUSize;
2199
0
                uint32_t heightInCU = (m_param->sourceHeight + m_param->maxCUSize - 1) >> m_param->maxLog2CUSize;
2200
0
                frameEnc->m_analysisData.numCUsInFrame = widthInCU * heightInCU;
2201
0
                frameEnc->m_analysisData.numPartitions = m_param->num4x4Partitions;
2202
0
                x265_alloc_analysis_data(m_param, &frameEnc->m_analysisData);
2203
0
                frameEnc->m_analysisData.poc = frameEnc->m_poc;
2204
0
                if (m_param->rc.bStatRead)
2205
0
                    readAnalysisFile(&frameEnc->m_analysisData, frameEnc->m_poc, frameEnc->m_lowres.sliceType);
2206
0
            }
2207
2208
0
            if (m_param->bResetZoneConfig)
2209
0
            {
2210
0
                for (int i = 0; i < m_param->rc.zonefileCount; i++)
2211
0
                {
2212
0
                    if (m_param->rc.zones[i].startFrame == frameEnc->m_poc)
2213
0
                        x265_encoder_reconfig(this, m_param->rc.zones[i].zoneParam);
2214
0
                }
2215
0
            }
2216
2217
0
            if (frameEnc->m_reconfigureRc && m_reconfigureRc)
2218
0
            {
2219
0
                x265_copy_params(m_param, m_latestParam);
2220
0
                m_rateControl->reconfigureRC();
2221
0
                m_reconfigureRc = false;
2222
0
            }
2223
0
            if (frameEnc->m_reconfigureRc && !m_reconfigureRc)
2224
0
                frameEnc->m_reconfigureRc = false;
2225
0
            if (curEncoder->m_reconfigure)
2226
0
            {
2227
                /* One round robin cycle of FE reconfigure is complete */
2228
                /* Safe to copy m_latestParam to Encoder::m_param, encoder reconfigure complete */
2229
0
                for (int frameEncId = 0; frameEncId < m_param->frameNumThreads; frameEncId++)
2230
0
                    m_frameEncoder[frameEncId]->m_reconfigure = false;
2231
0
                x265_copy_params(m_param, m_latestParam);
2232
0
                m_reconfigure = false;
2233
0
            }
2234
2235
            /* Initiate reconfigure for this FE if necessary */
2236
0
            curEncoder->m_param = m_reconfigure ? m_latestParam : m_param;
2237
0
            curEncoder->m_reconfigure = m_reconfigure;
2238
2239
            /* give this frame a FrameData instance before encoding */
2240
0
            if (m_dpb->m_frameDataFreeList)
2241
0
            {
2242
0
                frameEnc->m_encData = m_dpb->m_frameDataFreeList;
2243
0
                m_dpb->m_frameDataFreeList = m_dpb->m_frameDataFreeList->m_freeListNext;
2244
0
                frameEnc->reinit(m_sps);
2245
0
                frameEnc->m_param = m_reconfigure ? m_latestParam : m_param;
2246
0
                frameEnc->m_encData->m_param = m_reconfigure ? m_latestParam : m_param;
2247
0
            }
2248
0
            else
2249
0
            {
2250
0
                frameEnc->allocEncodeData(m_reconfigure ? m_latestParam : m_param, m_sps);
2251
0
                Slice* slice = frameEnc->m_encData->m_slice;
2252
0
                slice->m_sps = &m_sps;
2253
0
                slice->m_pps = &m_pps;
2254
0
                slice->m_param = m_param;
2255
0
                slice->m_maxNumMergeCand = m_param->maxNumMergeCand;
2256
0
                slice->m_endCUAddr = slice->realEndAddress(m_sps.numCUsInFrame * m_param->num4x4Partitions);
2257
0
            }
2258
0
            if (m_param->analysisLoad && m_param->bDisableLookahead)
2259
0
            {
2260
0
                frameEnc->m_dts = frameEnc->m_analysisData.lookahead.dts;
2261
0
                frameEnc->m_reorderedPts = frameEnc->m_analysisData.lookahead.reorderedPts;
2262
0
                if (m_rateControl->m_isVbv)
2263
0
                {
2264
0
                    for (uint32_t index = 0; index < frameEnc->m_analysisData.numCuInHeight; index++)
2265
0
                    {
2266
0
                        frameEnc->m_encData->m_rowStat[index].intraSatdForVbv = frameEnc->m_analysisData.lookahead.intraSatdForVbv[index];
2267
0
                        frameEnc->m_encData->m_rowStat[index].satdForVbv = frameEnc->m_analysisData.lookahead.satdForVbv[index];
2268
0
                    }
2269
0
                    for (uint32_t index = 0; index < frameEnc->m_analysisData.numCUsInFrame; index++)
2270
0
                    {
2271
0
                        frameEnc->m_encData->m_cuStat[index].intraVbvCost = frameEnc->m_analysisData.lookahead.intraVbvCost[index];
2272
0
                        frameEnc->m_encData->m_cuStat[index].vbvCost = frameEnc->m_analysisData.lookahead.vbvCost[index];
2273
0
                    }
2274
0
                }
2275
0
            }
2276
0
            if (m_param->searchMethod == X265_SEA && frameEnc->m_lowres.sliceType != X265_TYPE_B)
2277
0
            {
2278
0
                int padX = m_param->maxCUSize + 32;
2279
0
                int padY = m_param->maxCUSize + 16;
2280
0
                uint32_t numCuInHeight = (frameEnc->m_encData->m_reconPic->m_picHeight + m_param->maxCUSize - 1) / m_param->maxCUSize;
2281
0
                int maxHeight = numCuInHeight * m_param->maxCUSize;
2282
0
                for (int i = 0; i < INTEGRAL_PLANE_NUM; i++)
2283
0
                {
2284
0
                    frameEnc->m_encData->m_meBuffer[i] = X265_MALLOC(uint32_t, frameEnc->m_reconPic->m_stride * (maxHeight + (2 * padY)));
2285
0
                    if (frameEnc->m_encData->m_meBuffer[i])
2286
0
                    {
2287
0
                        memset(frameEnc->m_encData->m_meBuffer[i], 0, sizeof(uint32_t)* frameEnc->m_reconPic->m_stride * (maxHeight + (2 * padY)));
2288
0
                        frameEnc->m_encData->m_meIntegral[i] = frameEnc->m_encData->m_meBuffer[i] + frameEnc->m_encData->m_reconPic->m_stride * padY + padX;
2289
0
                    }
2290
0
                    else
2291
0
                        x265_log(m_param, X265_LOG_ERROR, "SEA motion search: POC %d Integral buffer[%d] unallocated\n", frameEnc->m_poc, i);
2292
0
                }
2293
0
            }
2294
2295
0
            if (m_param->bOptQpPPS && frameEnc->m_lowres.bKeyframe && m_param->bRepeatHeaders)
2296
0
            {
2297
0
                ScopedLock qpLock(m_sliceQpLock);
2298
0
                if (m_iFrameNum > 0)
2299
0
                {
2300
                    //Search the least cost
2301
0
                    int64_t iLeastCost = m_iBitsCostSum[0];
2302
0
                    int iLeastId = 0;
2303
0
                    for (int i = 1; i < QP_MAX_MAX + 1; i++)
2304
0
                    {
2305
0
                        if (iLeastCost > m_iBitsCostSum[i])
2306
0
                        {
2307
0
                            iLeastId = i;
2308
0
                            iLeastCost = m_iBitsCostSum[i];
2309
0
                        }
2310
0
                    }
2311
                    /* If last slice Qp is close to (26 + m_iPPSQpMinus26) or outputs is all I-frame video,
2312
                       we don't need to change m_iPPSQpMinus26. */
2313
0
                    if (m_iFrameNum > 1)
2314
0
                        m_iPPSQpMinus26 = (iLeastId + 1) - 26;
2315
0
                    m_iFrameNum = 0;
2316
0
                }
2317
2318
0
                for (int i = 0; i < QP_MAX_MAX + 1; i++)
2319
0
                    m_iBitsCostSum[i] = 0;
2320
0
            }
2321
2322
0
            frameEnc->m_encData->m_slice->m_iPPSQpMinus26 = m_iPPSQpMinus26;
2323
0
            frameEnc->m_encData->m_slice->numRefIdxDefault[0] = m_pps.numRefIdxDefault[0];
2324
0
            frameEnc->m_encData->m_slice->numRefIdxDefault[1] = m_pps.numRefIdxDefault[1];
2325
0
            frameEnc->m_encData->m_slice->m_iNumRPSInSPS = m_sps.spsrpsNum;
2326
2327
0
            curEncoder->m_rce.encodeOrder = frameEnc->m_encodeOrder = m_encodedFrameNum++;
2328
2329
0
            if (!m_param->analysisLoad || !m_param->bDisableLookahead)
2330
0
            {
2331
0
                if (m_bframeDelay)
2332
0
                {
2333
0
                    int64_t *prevReorderedPts = m_prevReorderedPts;
2334
0
                    frameEnc->m_dts = m_encodedFrameNum > m_bframeDelay
2335
0
                        ? prevReorderedPts[(m_encodedFrameNum - m_bframeDelay) % m_bframeDelay]
2336
0
                        : frameEnc->m_reorderedPts - m_bframeDelayTime;
2337
0
                    prevReorderedPts[m_encodedFrameNum % m_bframeDelay] = frameEnc->m_reorderedPts;
2338
0
                }
2339
0
                else
2340
0
                    frameEnc->m_dts = frameEnc->m_reorderedPts;
2341
0
            }
2342
2343
            /* Allocate analysis data before encode in save mode. This is allocated in frameEnc */
2344
0
            if (m_param->analysisSave && !m_param->analysisLoad)
2345
0
            {
2346
0
                x265_analysis_data* analysis = &frameEnc->m_analysisData;
2347
0
                analysis->poc = frameEnc->m_poc;
2348
0
                analysis->sliceType = frameEnc->m_lowres.sliceType;
2349
0
                uint32_t widthInCU       = (m_param->sourceWidth  + m_param->maxCUSize - 1) >> m_param->maxLog2CUSize;
2350
0
                uint32_t heightInCU      = (m_param->sourceHeight + m_param->maxCUSize - 1) >> m_param->maxLog2CUSize;
2351
2352
0
                uint32_t numCUsInFrame   = widthInCU * heightInCU;
2353
0
                analysis->numCUsInFrame  = numCUsInFrame;
2354
0
                analysis->numCuInHeight = heightInCU;
2355
0
                analysis->numPartitions  = m_param->num4x4Partitions;
2356
0
                x265_alloc_analysis_data(m_param, analysis);
2357
0
            }
2358
            /* determine references, setup RPS, etc */
2359
0
            m_dpb->prepareEncode(frameEnc);
2360
0
            if (!!m_param->selectiveSAO)
2361
0
            {
2362
0
                Slice* slice = frameEnc->m_encData->m_slice;
2363
0
                slice->m_bUseSao = curEncoder->m_frameFilter.m_useSao = 1;
2364
0
                switch (m_param->selectiveSAO)
2365
0
                {
2366
0
                case 3: if (!IS_REFERENCED(frameEnc))
2367
0
                            slice->m_bUseSao = curEncoder->m_frameFilter.m_useSao = 0;
2368
0
                        break;
2369
0
                case 2: if (!!m_param->bframes && slice->m_sliceType == B_SLICE)
2370
0
                            slice->m_bUseSao = curEncoder->m_frameFilter.m_useSao = 0;
2371
0
                        break;
2372
0
                case 1: if (slice->m_sliceType != I_SLICE)
2373
0
                            slice->m_bUseSao = curEncoder->m_frameFilter.m_useSao = 0;
2374
0
                        break;
2375
0
                }
2376
0
            }
2377
0
            else
2378
0
            {
2379
0
                Slice* slice = frameEnc->m_encData->m_slice;
2380
0
                slice->m_bUseSao = curEncoder->m_frameFilter.m_useSao = 0;
2381
0
            }
2382
2383
0
            if (m_param->rc.rateControlMode != X265_RC_CQP)
2384
0
                m_lookahead->getEstimatedPictureCost(frameEnc);
2385
0
            if (m_param->bIntraRefresh)
2386
0
                 calcRefreshInterval(frameEnc);
2387
2388
            /* Allow FrameEncoder::compressFrame() to start in the frame encoder thread */
2389
0
            if (!curEncoder->startCompressFrame(frameEnc))
2390
0
                m_aborted = true;
2391
0
        }
2392
0
        else if (m_encodedFrameNum)
2393
0
            m_rateControl->setFinalFrameCount(m_encodedFrameNum);
2394
0
    }
2395
0
    while (m_bZeroLatency && ++pass < 2);
2396
2397
0
    return ret;
2398
0
}
2399
2400
int Encoder::reconfigureParam(x265_param* encParam, x265_param* param)
2401
0
{
2402
0
    if (isReconfigureRc(encParam, param) && !param->rc.zonefileCount)
2403
0
    {
2404
        /* VBV can't be turned ON if it wasn't ON to begin with and can't be turned OFF if it was ON to begin with*/
2405
0
        if (param->rc.vbvMaxBitrate > 0 && param->rc.vbvBufferSize > 0 &&
2406
0
            encParam->rc.vbvMaxBitrate > 0 && encParam->rc.vbvBufferSize > 0)
2407
0
        {
2408
0
            m_reconfigureRc |= encParam->rc.vbvMaxBitrate != param->rc.vbvMaxBitrate;
2409
0
            m_reconfigureRc |= encParam->rc.vbvBufferSize != param->rc.vbvBufferSize;
2410
0
            if (m_reconfigureRc && m_param->bEmitHRDSEI)
2411
0
                x265_log(m_param, X265_LOG_WARNING, "VBV parameters cannot be changed when HRD is in use.\n");
2412
0
            else
2413
0
            {
2414
0
                encParam->rc.vbvMaxBitrate = param->rc.vbvMaxBitrate;
2415
0
                encParam->rc.vbvBufferSize = param->rc.vbvBufferSize;
2416
0
            }
2417
0
        }
2418
0
        m_reconfigureRc |= encParam->rc.bitrate != param->rc.bitrate;
2419
0
        encParam->rc.bitrate = param->rc.bitrate;
2420
0
        m_reconfigureRc |= encParam->rc.rfConstant != param->rc.rfConstant;
2421
0
        encParam->rc.rfConstant = param->rc.rfConstant;
2422
0
    }
2423
0
    else
2424
0
    {
2425
0
        encParam->maxNumReferences = param->maxNumReferences; // never uses more refs than specified in stream headers
2426
0
        encParam->bEnableFastIntra = param->bEnableFastIntra;
2427
0
        encParam->bEnableEarlySkip = param->bEnableEarlySkip;
2428
0
        encParam->recursionSkipMode = param->recursionSkipMode;
2429
0
        encParam->searchMethod = param->searchMethod;
2430
        /* Scratch buffer prevents me_range from being increased for esa/tesa */
2431
0
        if (param->searchRange < encParam->searchRange)
2432
0
            encParam->searchRange = param->searchRange;
2433
        /* We can't switch out of subme=0 during encoding. */
2434
0
        if (encParam->subpelRefine)
2435
0
            encParam->subpelRefine = param->subpelRefine;
2436
0
        encParam->rdoqLevel = param->rdoqLevel;
2437
0
        encParam->rdLevel = param->rdLevel;
2438
0
        encParam->bEnableRectInter = param->bEnableRectInter;
2439
0
        encParam->maxNumMergeCand = param->maxNumMergeCand;
2440
0
        encParam->bIntraInBFrames = param->bIntraInBFrames;
2441
0
        if (param->scalingLists && !encParam->scalingLists)
2442
0
            encParam->scalingLists = strdup(param->scalingLists);
2443
2444
0
        encParam->rc.aqMode = param->rc.aqMode;
2445
0
        encParam->rc.aqStrength = param->rc.aqStrength;
2446
0
        encParam->noiseReductionInter = param->noiseReductionInter;
2447
0
        encParam->noiseReductionIntra = param->noiseReductionIntra;
2448
2449
0
        encParam->limitModes = param->limitModes;
2450
0
        encParam->bEnableSplitRdSkip = param->bEnableSplitRdSkip;
2451
0
        encParam->bCULossless = param->bCULossless;
2452
0
        encParam->bEnableRdRefine = param->bEnableRdRefine;
2453
0
        encParam->limitTU = param->limitTU;
2454
0
        encParam->bEnableTSkipFast = param->bEnableTSkipFast;
2455
0
        encParam->rdPenalty = param->rdPenalty;
2456
0
        encParam->dynamicRd = param->dynamicRd;
2457
0
        encParam->bEnableTransformSkip = param->bEnableTransformSkip;
2458
0
        encParam->bEnableAMP = param->bEnableAMP;
2459
2460
        /* Resignal changes in params in Parameter Sets */
2461
0
        m_sps.maxAMPDepth = (m_sps.bUseAMP = param->bEnableAMP && param->bEnableAMP) ? param->maxCUDepth : 0;
2462
0
        m_pps.bTransformSkipEnabled = param->bEnableTransformSkip ? 1 : 0;
2463
2464
0
    }
2465
0
    encParam->forceFlush = param->forceFlush;
2466
    /* To add: Loop Filter/deblocking controls, transform skip, signhide require PPS to be resent */
2467
    /* To add: SAO, temporal MVP, AMP, TU depths require SPS to be resent, at every CVS boundary */
2468
0
    return x265_check_params(encParam);
2469
0
}
2470
2471
bool Encoder::isReconfigureRc(x265_param* latestParam, x265_param* param_in)
2472
0
{
2473
0
    return (latestParam->rc.vbvMaxBitrate != param_in->rc.vbvMaxBitrate
2474
0
        || latestParam->rc.vbvBufferSize != param_in->rc.vbvBufferSize
2475
0
        || latestParam->rc.bitrate != param_in->rc.bitrate
2476
0
        || latestParam->rc.rfConstant != param_in->rc.rfConstant);
2477
0
}
2478
2479
void Encoder::copyCtuInfo(x265_ctu_info_t** frameCtuInfo, int poc)
2480
0
{
2481
0
    uint32_t widthInCU = (m_param->sourceWidth + m_param->maxCUSize - 1) >> m_param->maxLog2CUSize;
2482
0
    uint32_t heightInCU = (m_param->sourceHeight + m_param->maxCUSize - 1) >> m_param->maxLog2CUSize;
2483
0
    Frame* curFrame;
2484
0
    Frame* prevFrame = NULL;
2485
0
    int32_t* frameCTU;
2486
0
    uint32_t numCUsInFrame = widthInCU * heightInCU;
2487
0
    uint32_t maxNum8x8Partitions = 64;
2488
0
    bool copied = false;
2489
0
    do
2490
0
    {
2491
0
        curFrame = m_lookahead->m_inputQueue.getPOC(poc);
2492
0
        if (!curFrame)
2493
0
            curFrame = m_lookahead->m_outputQueue.getPOC(poc);
2494
2495
0
        if (poc > 0)
2496
0
        {
2497
0
            prevFrame = m_lookahead->m_inputQueue.getPOC(poc - 1);
2498
0
            if (!prevFrame)
2499
0
                prevFrame = m_lookahead->m_outputQueue.getPOC(poc - 1);
2500
0
            if (!prevFrame)
2501
0
            {
2502
0
                FrameEncoder* prevEncoder;
2503
0
                for (int i = 0; i < m_param->frameNumThreads; i++)
2504
0
                {
2505
0
                    prevEncoder = m_frameEncoder[i];
2506
0
                    prevFrame = prevEncoder->m_frame;
2507
0
                    if (prevFrame && (prevEncoder->m_frame->m_poc == poc - 1))
2508
0
                    {
2509
0
                        prevFrame = prevEncoder->m_frame;
2510
0
                        break;
2511
0
                    }
2512
0
                }
2513
0
            }
2514
0
        }
2515
0
        x265_ctu_info_t* ctuTemp, *prevCtuTemp;
2516
0
        if (curFrame)
2517
0
        {
2518
0
            if (!curFrame->m_ctuInfo)
2519
0
                CHECKED_MALLOC(curFrame->m_ctuInfo, x265_ctu_info_t*, 1);
2520
0
            CHECKED_MALLOC(*curFrame->m_ctuInfo, x265_ctu_info_t, numCUsInFrame);
2521
0
            CHECKED_MALLOC_ZERO(curFrame->m_prevCtuInfoChange, int, numCUsInFrame * maxNum8x8Partitions);
2522
0
            for (uint32_t i = 0; i < numCUsInFrame; i++)
2523
0
            {
2524
0
                ctuTemp = *curFrame->m_ctuInfo + i;
2525
0
                CHECKED_MALLOC(frameCTU, int32_t, maxNum8x8Partitions);
2526
0
                ctuTemp->ctuInfo = (int32_t*)frameCTU;
2527
0
                ctuTemp->ctuAddress = frameCtuInfo[i]->ctuAddress;
2528
0
                memcpy(ctuTemp->ctuPartitions, frameCtuInfo[i]->ctuPartitions, sizeof(int32_t) * maxNum8x8Partitions);
2529
0
                memcpy(ctuTemp->ctuInfo, frameCtuInfo[i]->ctuInfo, sizeof(int32_t) * maxNum8x8Partitions);
2530
0
                if (prevFrame && curFrame->m_poc > 1)
2531
0
                {
2532
0
                    prevCtuTemp = *prevFrame->m_ctuInfo + i;
2533
0
                    for (uint32_t j = 0; j < maxNum8x8Partitions; j++)
2534
0
                        curFrame->m_prevCtuInfoChange[i * maxNum8x8Partitions + j] = (*((int32_t *)prevCtuTemp->ctuInfo + j) == 2) ? (poc - 1) : prevFrame->m_prevCtuInfoChange[i * maxNum8x8Partitions + j];
2535
0
                }
2536
0
            }
2537
0
            copied = true;
2538
0
            curFrame->m_copied.trigger();
2539
0
        }
2540
0
        else
2541
0
        {
2542
0
            FrameEncoder* curEncoder;
2543
0
            for (int i = 0; i < m_param->frameNumThreads; i++)
2544
0
            {
2545
0
                curEncoder = m_frameEncoder[i];
2546
0
                curFrame = curEncoder->m_frame;
2547
0
                if (curFrame)
2548
0
                {
2549
0
                    if (poc == curFrame->m_poc)
2550
0
                    {
2551
0
                        if (!curFrame->m_ctuInfo)
2552
0
                            CHECKED_MALLOC(curFrame->m_ctuInfo, x265_ctu_info_t*, 1);
2553
0
                        CHECKED_MALLOC(*curFrame->m_ctuInfo, x265_ctu_info_t, numCUsInFrame);
2554
0
                        CHECKED_MALLOC_ZERO(curFrame->m_prevCtuInfoChange, int, numCUsInFrame * maxNum8x8Partitions);
2555
0
                        for (uint32_t l = 0; l < numCUsInFrame; l++)
2556
0
                        {
2557
0
                            ctuTemp = *curFrame->m_ctuInfo + l;
2558
0
                            CHECKED_MALLOC(frameCTU, int32_t, maxNum8x8Partitions);
2559
0
                            ctuTemp->ctuInfo = (int32_t*)frameCTU;
2560
0
                            ctuTemp->ctuAddress = frameCtuInfo[l]->ctuAddress;
2561
0
                            memcpy(ctuTemp->ctuPartitions, frameCtuInfo[l]->ctuPartitions, sizeof(int32_t) * maxNum8x8Partitions);
2562
0
                            memcpy(ctuTemp->ctuInfo, frameCtuInfo[l]->ctuInfo, sizeof(int32_t) * maxNum8x8Partitions);
2563
0
                            if (prevFrame && curFrame->m_poc > 1)
2564
0
                            {
2565
0
                                prevCtuTemp = *prevFrame->m_ctuInfo + l;
2566
0
                                for (uint32_t j = 0; j < maxNum8x8Partitions; j++)
2567
0
                                    curFrame->m_prevCtuInfoChange[l * maxNum8x8Partitions + j] = (*((int32_t *)prevCtuTemp->ctuInfo + j) == CTU_INFO_CHANGE) ? (poc - 1) : prevFrame->m_prevCtuInfoChange[l * maxNum8x8Partitions + j];
2568
0
                            }
2569
0
                        }
2570
0
                        copied = true;
2571
0
                        curFrame->m_copied.trigger();
2572
0
                        break;
2573
0
                    }
2574
0
                }
2575
0
            }
2576
0
        }
2577
0
    } while (!copied);
2578
0
    return;
2579
0
fail:
2580
0
    for (uint32_t i = 0; i < numCUsInFrame; i++)
2581
0
    {
2582
0
        X265_FREE((*curFrame->m_ctuInfo + i)->ctuInfo);
2583
0
        (*curFrame->m_ctuInfo + i)->ctuInfo = NULL;
2584
0
    }
2585
0
    X265_FREE(*curFrame->m_ctuInfo);
2586
0
    *(curFrame->m_ctuInfo) = NULL;
2587
0
    X265_FREE(curFrame->m_ctuInfo);
2588
0
    curFrame->m_ctuInfo = NULL;
2589
0
    X265_FREE(curFrame->m_prevCtuInfoChange);
2590
0
    curFrame->m_prevCtuInfoChange = NULL;
2591
0
}
2592
2593
void EncStats::addPsnr(double psnrY, double psnrU, double psnrV)
2594
0
{
2595
0
    m_psnrSumY += psnrY;
2596
0
    m_psnrSumU += psnrU;
2597
0
    m_psnrSumV += psnrV;
2598
0
}
2599
2600
void EncStats::addBits(uint64_t bits)
2601
0
{
2602
0
    m_accBits += bits;
2603
0
    m_numPics++;
2604
0
}
2605
2606
void EncStats::addSsim(double ssim)
2607
0
{
2608
0
    m_globalSsim += ssim;
2609
0
}
2610
2611
void EncStats::addQP(double aveQp)
2612
0
{
2613
0
    m_totalQp += aveQp;
2614
0
}
2615
2616
char* Encoder::statsString(EncStats& stat, char* buffer)
2617
0
{
2618
0
    double fps = (double)m_param->fpsNum / m_param->fpsDenom;
2619
0
    double scale = fps / 1000 / (double)stat.m_numPics;
2620
2621
0
    int len = sprintf(buffer, "%6u, ", stat.m_numPics);
2622
2623
0
    len += sprintf(buffer + len, "Avg QP:%2.2lf", stat.m_totalQp / (double)stat.m_numPics);
2624
0
    len += sprintf(buffer + len, "  kb/s: %-8.2lf", stat.m_accBits * scale);
2625
0
    if (m_param->bEnablePsnr)
2626
0
    {
2627
0
        len += sprintf(buffer + len, "  PSNR Mean: Y:%.3lf U:%.3lf V:%.3lf",
2628
0
                       stat.m_psnrSumY / (double)stat.m_numPics,
2629
0
                       stat.m_psnrSumU / (double)stat.m_numPics,
2630
0
                       stat.m_psnrSumV / (double)stat.m_numPics);
2631
0
    }
2632
0
    if (m_param->bEnableSsim)
2633
0
    {
2634
0
        sprintf(buffer + len, "  SSIM Mean: %.6lf (%.3lfdB)",
2635
0
                stat.m_globalSsim / (double)stat.m_numPics,
2636
0
                x265_ssim2dB(stat.m_globalSsim / (double)stat.m_numPics));
2637
0
    }
2638
0
    return buffer;
2639
0
}
2640
2641
void Encoder::printSummary()
2642
0
{
2643
0
    if (m_param->logLevel < X265_LOG_INFO)
2644
0
        return;
2645
2646
0
    char buffer[200];
2647
0
    if (m_analyzeI.m_numPics)
2648
0
        x265_log(m_param, X265_LOG_INFO, "frame I: %s\n", statsString(m_analyzeI, buffer));
2649
0
    if (m_analyzeP.m_numPics)
2650
0
        x265_log(m_param, X265_LOG_INFO, "frame P: %s\n", statsString(m_analyzeP, buffer));
2651
0
    if (m_analyzeB.m_numPics)
2652
0
        x265_log(m_param, X265_LOG_INFO, "frame B: %s\n", statsString(m_analyzeB, buffer));
2653
0
    if (m_param->bEnableWeightedPred && m_analyzeP.m_numPics)
2654
0
    {
2655
0
        x265_log(m_param, X265_LOG_INFO, "Weighted P-Frames: Y:%.1f%% UV:%.1f%%\n",
2656
0
            (float)100.0 * m_numLumaWPFrames / m_analyzeP.m_numPics,
2657
0
            (float)100.0 * m_numChromaWPFrames / m_analyzeP.m_numPics);
2658
0
    }
2659
0
    if (m_param->bEnableWeightedBiPred && m_analyzeB.m_numPics)
2660
0
    {
2661
0
        x265_log(m_param, X265_LOG_INFO, "Weighted B-Frames: Y:%.1f%% UV:%.1f%%\n",
2662
0
            (float)100.0 * m_numLumaWPBiFrames / m_analyzeB.m_numPics,
2663
0
            (float)100.0 * m_numChromaWPBiFrames / m_analyzeB.m_numPics);
2664
0
    }
2665
0
    int pWithB = 0;
2666
0
    for (int i = 0; i <= m_param->bframes; i++)
2667
0
        pWithB += m_lookahead->m_histogram[i];
2668
2669
0
    if (pWithB)
2670
0
    {
2671
0
        int p = 0;
2672
0
        for (int i = 0; i <= m_param->bframes; i++)
2673
0
            p += sprintf(buffer + p, "%.1f%% ", 100. * m_lookahead->m_histogram[i] / pWithB);
2674
2675
0
        x265_log(m_param, X265_LOG_INFO, "consecutive B-frames: %s\n", buffer);
2676
0
    }
2677
0
    if (m_param->bLossless)
2678
0
    {
2679
0
        float frameSize = (float)(m_param->sourceWidth - m_sps.conformanceWindow.rightOffset) *
2680
0
                                 (m_param->sourceHeight - m_sps.conformanceWindow.bottomOffset);
2681
0
        float uncompressed = frameSize * X265_DEPTH * m_analyzeAll.m_numPics;
2682
2683
0
        x265_log(m_param, X265_LOG_INFO, "lossless compression ratio %.2f::1\n", uncompressed / m_analyzeAll.m_accBits);
2684
0
    }
2685
0
    if (m_param->bMultiPassOptRPS && m_param->rc.bStatRead)
2686
0
    {
2687
0
        x265_log(m_param, X265_LOG_INFO, "RPS in SPS: %d frames (%.2f%%), RPS not in SPS: %d frames (%.2f%%)\n", 
2688
0
            m_rpsInSpsCount, (float)100.0 * m_rpsInSpsCount / m_rateControl->m_numEntries, 
2689
0
            m_rateControl->m_numEntries - m_rpsInSpsCount, 
2690
0
            (float)100.0 * (m_rateControl->m_numEntries - m_rpsInSpsCount) / m_rateControl->m_numEntries);
2691
0
    }
2692
2693
0
    if (m_analyzeAll.m_numPics)
2694
0
    {
2695
0
        int p = 0;
2696
0
        double elapsedEncodeTime = (double)(x265_mdate() - m_encodeStartTime) / 1000000;
2697
0
        double elapsedVideoTime = (double)m_analyzeAll.m_numPics * m_param->fpsDenom / m_param->fpsNum;
2698
0
        double bitrate = (0.001f * m_analyzeAll.m_accBits) / elapsedVideoTime;
2699
2700
0
        p += sprintf(buffer + p, "\nencoded %d frames in %.2fs (%.2f fps), %.2f kb/s, Avg QP:%2.2lf", m_analyzeAll.m_numPics,
2701
0
                     elapsedEncodeTime, m_analyzeAll.m_numPics / elapsedEncodeTime, bitrate, m_analyzeAll.m_totalQp / (double)m_analyzeAll.m_numPics);
2702
2703
0
        if (m_param->bEnablePsnr)
2704
0
        {
2705
0
            double globalPsnr = (m_analyzeAll.m_psnrSumY * 6 + m_analyzeAll.m_psnrSumU + m_analyzeAll.m_psnrSumV) / (8 * m_analyzeAll.m_numPics);
2706
0
            p += sprintf(buffer + p, ", Global PSNR: %.3f", globalPsnr);
2707
0
        }
2708
2709
0
        if (m_param->bEnableSsim)
2710
0
            p += sprintf(buffer + p, ", SSIM Mean Y: %.7f (%6.3f dB)", m_analyzeAll.m_globalSsim / m_analyzeAll.m_numPics, x265_ssim2dB(m_analyzeAll.m_globalSsim / m_analyzeAll.m_numPics));
2711
2712
0
        sprintf(buffer + p, "\n");
2713
0
        general_log(m_param, NULL, X265_LOG_INFO, buffer);
2714
0
    }
2715
0
    else
2716
0
        general_log(m_param, NULL, X265_LOG_INFO, "\nencoded 0 frames\n");
2717
2718
#if DETAILED_CU_STATS
2719
    /* Summarize stats from all frame encoders */
2720
    CUStats cuStats;
2721
    for (int i = 0; i < m_param->frameNumThreads; i++)
2722
        cuStats.accumulate(m_frameEncoder[i]->m_cuStats, *m_param);
2723
2724
    if (!cuStats.totalCTUTime)
2725
        return;
2726
2727
    int totalWorkerCount = 0;
2728
    for (int i = 0; i < m_numPools; i++)
2729
        totalWorkerCount += m_threadPool[i].m_numWorkers;
2730
2731
    int64_t  batchElapsedTime, coopSliceElapsedTime;
2732
    uint64_t batchCount, coopSliceCount;
2733
    m_lookahead->getWorkerStats(batchElapsedTime, batchCount, coopSliceElapsedTime, coopSliceCount);
2734
    int64_t lookaheadWorkerTime = m_lookahead->m_slicetypeDecideElapsedTime + m_lookahead->m_preLookaheadElapsedTime +
2735
                                  batchElapsedTime + coopSliceElapsedTime;
2736
2737
    int64_t totalWorkerTime = cuStats.totalCTUTime + cuStats.loopFilterElapsedTime + cuStats.pmodeTime +
2738
                              cuStats.pmeTime + lookaheadWorkerTime + cuStats.weightAnalyzeTime;
2739
    int64_t elapsedEncodeTime = x265_mdate() - m_encodeStartTime;
2740
2741
    int64_t interRDOTotalTime = 0, intraRDOTotalTime = 0;
2742
    uint64_t interRDOTotalCount = 0, intraRDOTotalCount = 0;
2743
    for (uint32_t i = 0; i <= m_param->maxCUDepth; i++)
2744
    {
2745
        interRDOTotalTime += cuStats.interRDOElapsedTime[i];
2746
        intraRDOTotalTime += cuStats.intraRDOElapsedTime[i];
2747
        interRDOTotalCount += cuStats.countInterRDO[i];
2748
        intraRDOTotalCount += cuStats.countIntraRDO[i];
2749
    }
2750
2751
    /* Time within compressCTU() and pmode tasks not captured by ME, Intra mode selection, or RDO (2Nx2N merge, 2Nx2N bidir, etc) */
2752
    int64_t unaccounted = (cuStats.totalCTUTime + cuStats.pmodeTime) -
2753
                          (cuStats.intraAnalysisElapsedTime + cuStats.motionEstimationElapsedTime + interRDOTotalTime + intraRDOTotalTime);
2754
2755
#define ELAPSED_SEC(val)  ((double)(val) / 1000000)
2756
#define ELAPSED_MSEC(val) ((double)(val) / 1000)
2757
2758
    if (m_param->bDistributeMotionEstimation && cuStats.countPMEMasters)
2759
    {
2760
        x265_log(m_param, X265_LOG_INFO, "CU: %%%05.2lf time spent in motion estimation, averaging %.3lf CU inter modes per CTU\n",
2761
                 100.0 * (cuStats.motionEstimationElapsedTime + cuStats.pmeTime) / totalWorkerTime,
2762
                 (double)cuStats.countMotionEstimate / cuStats.totalCTUs);
2763
        x265_log(m_param, X265_LOG_INFO, "CU: %.3lf PME masters per inter CU, each blocked an average of %.3lf ns\n",
2764
                 (double)cuStats.countPMEMasters / cuStats.countMotionEstimate,
2765
                 (double)cuStats.pmeBlockTime / cuStats.countPMEMasters);
2766
        x265_log(m_param, X265_LOG_INFO, "CU:       %.3lf slaves per PME master, each took an average of %.3lf ms\n",
2767
                 (double)cuStats.countPMETasks / cuStats.countPMEMasters,
2768
                 ELAPSED_MSEC(cuStats.pmeTime) / cuStats.countPMETasks);
2769
    }
2770
    else
2771
    {
2772
        x265_log(m_param, X265_LOG_INFO, "CU: %%%05.2lf time spent in motion estimation, averaging %.3lf CU inter modes per CTU\n",
2773
                 100.0 * cuStats.motionEstimationElapsedTime / totalWorkerTime,
2774
                 (double)cuStats.countMotionEstimate / cuStats.totalCTUs);
2775
2776
        if (cuStats.skippedMotionReferences[0] || cuStats.skippedMotionReferences[1] || cuStats.skippedMotionReferences[2])
2777
            x265_log(m_param, X265_LOG_INFO, "CU: Skipped motion searches per depth %%%.2lf %%%.2lf %%%.2lf %%%.2lf\n",
2778
                     100.0 * cuStats.skippedMotionReferences[0] / cuStats.totalMotionReferences[0],
2779
                     100.0 * cuStats.skippedMotionReferences[1] / cuStats.totalMotionReferences[1],
2780
                     100.0 * cuStats.skippedMotionReferences[2] / cuStats.totalMotionReferences[2],
2781
                     100.0 * cuStats.skippedMotionReferences[3] / cuStats.totalMotionReferences[3]);
2782
    }
2783
    x265_log(m_param, X265_LOG_INFO, "CU: %%%05.2lf time spent in intra analysis, averaging %.3lf Intra PUs per CTU\n",
2784
             100.0 * cuStats.intraAnalysisElapsedTime / totalWorkerTime,
2785
             (double)cuStats.countIntraAnalysis / cuStats.totalCTUs);
2786
    if (cuStats.skippedIntraCU[0] || cuStats.skippedIntraCU[1] || cuStats.skippedIntraCU[2])
2787
        x265_log(m_param, X265_LOG_INFO, "CU: Skipped intra CUs at depth %%%.2lf %%%.2lf %%%.2lf\n",
2788
                 100.0 * cuStats.skippedIntraCU[0] / cuStats.totalIntraCU[0],
2789
                 100.0 * cuStats.skippedIntraCU[1] / cuStats.totalIntraCU[1],
2790
                 100.0 * cuStats.skippedIntraCU[2] / cuStats.totalIntraCU[2]);
2791
    x265_log(m_param, X265_LOG_INFO, "CU: %%%05.2lf time spent in inter RDO, measuring %.3lf inter/merge predictions per CTU\n",
2792
             100.0 * interRDOTotalTime / totalWorkerTime,
2793
             (double)interRDOTotalCount / cuStats.totalCTUs);
2794
    x265_log(m_param, X265_LOG_INFO, "CU: %%%05.2lf time spent in intra RDO, measuring %.3lf intra predictions per CTU\n",
2795
             100.0 * intraRDOTotalTime / totalWorkerTime,
2796
             (double)intraRDOTotalCount / cuStats.totalCTUs);
2797
    x265_log(m_param, X265_LOG_INFO, "CU: %%%05.2lf time spent in loop filters, average %.3lf ms per call\n",
2798
             100.0 * cuStats.loopFilterElapsedTime / totalWorkerTime,
2799
             ELAPSED_MSEC(cuStats.loopFilterElapsedTime) / cuStats.countLoopFilter);
2800
    if (cuStats.countWeightAnalyze && cuStats.weightAnalyzeTime)
2801
    {
2802
        x265_log(m_param, X265_LOG_INFO, "CU: %%%05.2lf time spent in weight analysis, average %.3lf ms per call\n",
2803
                 100.0 * cuStats.weightAnalyzeTime / totalWorkerTime,
2804
                 ELAPSED_MSEC(cuStats.weightAnalyzeTime) / cuStats.countWeightAnalyze);
2805
    }
2806
    if (m_param->bDistributeModeAnalysis && cuStats.countPModeMasters)
2807
    {
2808
        x265_log(m_param, X265_LOG_INFO, "CU: %.3lf PMODE masters per CTU, each blocked an average of %.3lf ns\n",
2809
                 (double)cuStats.countPModeMasters / cuStats.totalCTUs,
2810
                 (double)cuStats.pmodeBlockTime / cuStats.countPModeMasters);
2811
        x265_log(m_param, X265_LOG_INFO, "CU:       %.3lf slaves per PMODE master, each took average of %.3lf ms\n",
2812
                 (double)cuStats.countPModeTasks / cuStats.countPModeMasters,
2813
                 ELAPSED_MSEC(cuStats.pmodeTime) / cuStats.countPModeTasks);
2814
    }
2815
2816
    x265_log(m_param, X265_LOG_INFO, "CU: %%%05.2lf time spent in slicetypeDecide (avg %.3lfms) and prelookahead (avg %.3lfms)\n",
2817
             100.0 * lookaheadWorkerTime / totalWorkerTime,
2818
             ELAPSED_MSEC(m_lookahead->m_slicetypeDecideElapsedTime) / m_lookahead->m_countSlicetypeDecide,
2819
             ELAPSED_MSEC(m_lookahead->m_preLookaheadElapsedTime) / m_lookahead->m_countPreLookahead);
2820
2821
    x265_log(m_param, X265_LOG_INFO, "CU: %%%05.2lf time spent in other tasks\n",
2822
             100.0 * unaccounted / totalWorkerTime);
2823
2824
    if (intraRDOTotalTime && intraRDOTotalCount)
2825
    {
2826
        x265_log(m_param, X265_LOG_INFO, "CU: Intra RDO time  per depth %%%05.2lf %%%05.2lf %%%05.2lf %%%05.2lf\n",
2827
                 100.0 * cuStats.intraRDOElapsedTime[0] / intraRDOTotalTime,  // 64
2828
                 100.0 * cuStats.intraRDOElapsedTime[1] / intraRDOTotalTime,  // 32
2829
                 100.0 * cuStats.intraRDOElapsedTime[2] / intraRDOTotalTime,  // 16
2830
                 100.0 * cuStats.intraRDOElapsedTime[3] / intraRDOTotalTime); // 8
2831
        x265_log(m_param, X265_LOG_INFO, "CU: Intra RDO calls per depth %%%05.2lf %%%05.2lf %%%05.2lf %%%05.2lf\n",
2832
                 100.0 * cuStats.countIntraRDO[0] / intraRDOTotalCount,  // 64
2833
                 100.0 * cuStats.countIntraRDO[1] / intraRDOTotalCount,  // 32
2834
                 100.0 * cuStats.countIntraRDO[2] / intraRDOTotalCount,  // 16
2835
                 100.0 * cuStats.countIntraRDO[3] / intraRDOTotalCount); // 8
2836
    }
2837
2838
    if (interRDOTotalTime && interRDOTotalCount)
2839
    {
2840
        x265_log(m_param, X265_LOG_INFO, "CU: Inter RDO time  per depth %%%05.2lf %%%05.2lf %%%05.2lf %%%05.2lf\n",
2841
                 100.0 * cuStats.interRDOElapsedTime[0] / interRDOTotalTime,  // 64
2842
                 100.0 * cuStats.interRDOElapsedTime[1] / interRDOTotalTime,  // 32
2843
                 100.0 * cuStats.interRDOElapsedTime[2] / interRDOTotalTime,  // 16
2844
                 100.0 * cuStats.interRDOElapsedTime[3] / interRDOTotalTime); // 8
2845
        x265_log(m_param, X265_LOG_INFO, "CU: Inter RDO calls per depth %%%05.2lf %%%05.2lf %%%05.2lf %%%05.2lf\n",
2846
                 100.0 * cuStats.countInterRDO[0] / interRDOTotalCount,  // 64
2847
                 100.0 * cuStats.countInterRDO[1] / interRDOTotalCount,  // 32
2848
                 100.0 * cuStats.countInterRDO[2] / interRDOTotalCount,  // 16
2849
                 100.0 * cuStats.countInterRDO[3] / interRDOTotalCount); // 8
2850
    }
2851
2852
    x265_log(m_param, X265_LOG_INFO, "CU: " X265_LL " %dX%d CTUs compressed in %.3lf seconds, %.3lf CTUs per worker-second\n",
2853
             cuStats.totalCTUs, m_param->maxCUSize, m_param->maxCUSize,
2854
             ELAPSED_SEC(totalWorkerTime),
2855
             cuStats.totalCTUs / ELAPSED_SEC(totalWorkerTime));
2856
2857
    if (m_threadPool)
2858
        x265_log(m_param, X265_LOG_INFO, "CU: %.3lf average worker utilization, %%%05.2lf of theoretical maximum utilization\n",
2859
                 (double)totalWorkerTime / elapsedEncodeTime,
2860
                 100.0 * totalWorkerTime / (elapsedEncodeTime * totalWorkerCount));
2861
2862
#undef ELAPSED_SEC
2863
#undef ELAPSED_MSEC
2864
#endif
2865
0
}
2866
2867
void Encoder::fetchStats(x265_stats *stats, size_t statsSizeBytes)
2868
0
{
2869
0
    if (statsSizeBytes >= sizeof(stats))
2870
0
    {
2871
0
        stats->globalPsnrY = m_analyzeAll.m_psnrSumY;
2872
0
        stats->globalPsnrU = m_analyzeAll.m_psnrSumU;
2873
0
        stats->globalPsnrV = m_analyzeAll.m_psnrSumV;
2874
0
        stats->encodedPictureCount = m_analyzeAll.m_numPics;
2875
0
        stats->totalWPFrames = m_numLumaWPFrames;
2876
0
        stats->accBits = m_analyzeAll.m_accBits;
2877
0
        stats->elapsedEncodeTime = (double)(x265_mdate() - m_encodeStartTime) / 1000000;
2878
0
        if (stats->encodedPictureCount > 0)
2879
0
        {
2880
0
            stats->globalSsim = m_analyzeAll.m_globalSsim / stats->encodedPictureCount;
2881
0
            stats->globalPsnr = (stats->globalPsnrY * 6 + stats->globalPsnrU + stats->globalPsnrV) / (8 * stats->encodedPictureCount);
2882
0
            stats->elapsedVideoTime = (double)stats->encodedPictureCount * m_param->fpsDenom / m_param->fpsNum;
2883
0
            stats->bitrate = (0.001f * stats->accBits) / stats->elapsedVideoTime;
2884
0
        }
2885
0
        else
2886
0
        {
2887
0
            stats->globalSsim = 0;
2888
0
            stats->globalPsnr = 0;
2889
0
            stats->bitrate = 0;
2890
0
            stats->elapsedVideoTime = 0;
2891
0
        }
2892
2893
0
        double fps = (double)m_param->fpsNum / m_param->fpsDenom;
2894
0
        double scale = fps / 1000;
2895
2896
0
        stats->statsI.numPics = m_analyzeI.m_numPics;
2897
0
        stats->statsI.avgQp   = m_analyzeI.m_totalQp / (double)m_analyzeI.m_numPics;
2898
0
        stats->statsI.bitrate = m_analyzeI.m_accBits * scale / (double)m_analyzeI.m_numPics;
2899
0
        stats->statsI.psnrY   = m_analyzeI.m_psnrSumY / (double)m_analyzeI.m_numPics;
2900
0
        stats->statsI.psnrU   = m_analyzeI.m_psnrSumU / (double)m_analyzeI.m_numPics;
2901
0
        stats->statsI.psnrV   = m_analyzeI.m_psnrSumV / (double)m_analyzeI.m_numPics;
2902
0
        stats->statsI.ssim    = x265_ssim2dB(m_analyzeI.m_globalSsim / (double)m_analyzeI.m_numPics);
2903
2904
0
        stats->statsP.numPics = m_analyzeP.m_numPics;
2905
0
        stats->statsP.avgQp   = m_analyzeP.m_totalQp / (double)m_analyzeP.m_numPics;
2906
0
        stats->statsP.bitrate = m_analyzeP.m_accBits * scale / (double)m_analyzeP.m_numPics;
2907
0
        stats->statsP.psnrY   = m_analyzeP.m_psnrSumY / (double)m_analyzeP.m_numPics;
2908
0
        stats->statsP.psnrU   = m_analyzeP.m_psnrSumU / (double)m_analyzeP.m_numPics;
2909
0
        stats->statsP.psnrV   = m_analyzeP.m_psnrSumV / (double)m_analyzeP.m_numPics;
2910
0
        stats->statsP.ssim    = x265_ssim2dB(m_analyzeP.m_globalSsim / (double)m_analyzeP.m_numPics);
2911
2912
0
        stats->statsB.numPics = m_analyzeB.m_numPics;
2913
0
        stats->statsB.avgQp   = m_analyzeB.m_totalQp / (double)m_analyzeB.m_numPics;
2914
0
        stats->statsB.bitrate = m_analyzeB.m_accBits * scale / (double)m_analyzeB.m_numPics;
2915
0
        stats->statsB.psnrY   = m_analyzeB.m_psnrSumY / (double)m_analyzeB.m_numPics;
2916
0
        stats->statsB.psnrU   = m_analyzeB.m_psnrSumU / (double)m_analyzeB.m_numPics;
2917
0
        stats->statsB.psnrV   = m_analyzeB.m_psnrSumV / (double)m_analyzeB.m_numPics;
2918
0
        stats->statsB.ssim    = x265_ssim2dB(m_analyzeB.m_globalSsim / (double)m_analyzeB.m_numPics);
2919
0
        if (m_param->csvLogLevel >= 2 || m_param->maxCLL || m_param->maxFALL)
2920
0
        {
2921
0
            stats->maxCLL = m_analyzeAll.m_maxCLL;
2922
0
            stats->maxFALL = (uint16_t)(m_analyzeAll.m_maxFALL / m_analyzeAll.m_numPics);
2923
0
        }
2924
0
    }
2925
    /* If new statistics are added to x265_stats, we must check here whether the
2926
     * structure provided by the user is the new structure or an older one (for
2927
     * future safety) */
2928
0
}
2929
2930
void Encoder::finishFrameStats(Frame* curFrame, FrameEncoder *curEncoder, x265_frame_stats* frameStats, int inPoc)
2931
0
{
2932
0
    PicYuv* reconPic = curFrame->m_reconPic;
2933
0
    uint64_t bits = curEncoder->m_accessUnitBits;
2934
2935
    //===== calculate PSNR =====
2936
0
    int width  = reconPic->m_picWidth - m_sps.conformanceWindow.rightOffset;
2937
0
    int height = reconPic->m_picHeight - m_sps.conformanceWindow.bottomOffset;
2938
0
    int size = width * height;
2939
2940
0
    int maxvalY = 255 << (X265_DEPTH - 8);
2941
0
    int maxvalC = 255 << (X265_DEPTH - 8);
2942
0
    double refValueY = (double)maxvalY * maxvalY * size;
2943
0
    double refValueC = (double)maxvalC * maxvalC * size / 4.0;
2944
0
    uint64_t ssdY, ssdU, ssdV;
2945
2946
0
    ssdY = curEncoder->m_SSDY;
2947
0
    ssdU = curEncoder->m_SSDU;
2948
0
    ssdV = curEncoder->m_SSDV;
2949
0
    double psnrY = (ssdY ? 10.0 * log10(refValueY / (double)ssdY) : 99.99);
2950
0
    double psnrU = (ssdU ? 10.0 * log10(refValueC / (double)ssdU) : 99.99);
2951
0
    double psnrV = (ssdV ? 10.0 * log10(refValueC / (double)ssdV) : 99.99);
2952
2953
0
    FrameData& curEncData = *curFrame->m_encData;
2954
0
    Slice* slice = curEncData.m_slice;
2955
2956
    //===== add bits, psnr and ssim =====
2957
0
    m_analyzeAll.addBits(bits);
2958
0
    m_analyzeAll.addQP(curEncData.m_avgQpAq);
2959
2960
0
    if (m_param->bEnablePsnr)
2961
0
        m_analyzeAll.addPsnr(psnrY, psnrU, psnrV);
2962
2963
0
    double ssim = 0.0;
2964
0
    if (m_param->bEnableSsim && curEncoder->m_ssimCnt)
2965
0
    {
2966
0
        ssim = curEncoder->m_ssim / curEncoder->m_ssimCnt;
2967
0
        m_analyzeAll.addSsim(ssim);
2968
0
    }
2969
0
    if (slice->isIntra())
2970
0
    {
2971
0
        m_analyzeI.addBits(bits);
2972
0
        m_analyzeI.addQP(curEncData.m_avgQpAq);
2973
0
        if (m_param->bEnablePsnr)
2974
0
            m_analyzeI.addPsnr(psnrY, psnrU, psnrV);
2975
0
        if (m_param->bEnableSsim)
2976
0
            m_analyzeI.addSsim(ssim);
2977
0
    }
2978
0
    else if (slice->isInterP())
2979
0
    {
2980
0
        m_analyzeP.addBits(bits);
2981
0
        m_analyzeP.addQP(curEncData.m_avgQpAq);
2982
0
        if (m_param->bEnablePsnr)
2983
0
            m_analyzeP.addPsnr(psnrY, psnrU, psnrV);
2984
0
        if (m_param->bEnableSsim)
2985
0
            m_analyzeP.addSsim(ssim);
2986
0
    }
2987
0
    else if (slice->isInterB())
2988
0
    {
2989
0
        m_analyzeB.addBits(bits);
2990
0
        m_analyzeB.addQP(curEncData.m_avgQpAq);
2991
0
        if (m_param->bEnablePsnr)
2992
0
            m_analyzeB.addPsnr(psnrY, psnrU, psnrV);
2993
0
        if (m_param->bEnableSsim)
2994
0
            m_analyzeB.addSsim(ssim);
2995
0
    }
2996
0
    if (m_param->csvLogLevel >= 2 || m_param->maxCLL || m_param->maxFALL)
2997
0
    {
2998
0
        m_analyzeAll.m_maxFALL += curFrame->m_fencPic->m_avgLumaLevel;
2999
0
        m_analyzeAll.m_maxCLL = X265_MAX(m_analyzeAll.m_maxCLL, curFrame->m_fencPic->m_maxLumaLevel);
3000
0
    }
3001
0
    char c = (slice->isIntra() ? (curFrame->m_lowres.sliceType == X265_TYPE_IDR ? 'I' : 'i') : slice->isInterP() ? 'P' : 'B');
3002
0
    int poc = slice->m_poc;
3003
0
    if (!IS_REFERENCED(curFrame))
3004
0
        c += 32; // lower case if unreferenced
3005
3006
0
    if (frameStats)
3007
0
    {
3008
0
        const int picOrderCntLSB = slice->m_poc - slice->m_lastIDR;
3009
3010
0
        frameStats->encoderOrder = m_outputCount;
3011
0
        frameStats->sliceType = c;
3012
0
        frameStats->poc = picOrderCntLSB;
3013
0
        frameStats->qp = curEncData.m_avgQpAq;
3014
0
        frameStats->bits = bits;
3015
0
        frameStats->bScenecut = curFrame->m_lowres.bScenecut;
3016
0
        if (m_param->csvLogLevel >= 2)
3017
0
            frameStats->ipCostRatio = curFrame->m_lowres.ipCostRatio;
3018
0
        frameStats->bufferFill = m_rateControl->m_bufferFillActual;
3019
0
        frameStats->bufferFillFinal = m_rateControl->m_bufferFillFinal;
3020
0
        if (m_param->csvLogLevel >= 2)
3021
0
            frameStats->unclippedBufferFillFinal = m_rateControl->m_unclippedBufferFillFinal;
3022
0
        frameStats->frameLatency = inPoc - poc;
3023
0
        if (m_param->rc.rateControlMode == X265_RC_CRF)
3024
0
            frameStats->rateFactor = curEncData.m_rateFactor;
3025
0
        frameStats->psnrY = psnrY;
3026
0
        frameStats->psnrU = psnrU;
3027
0
        frameStats->psnrV = psnrV;
3028
0
        double psnr = (psnrY * 6 + psnrU + psnrV) / 8;
3029
0
        frameStats->psnr = psnr;
3030
0
        frameStats->ssim = ssim;
3031
0
        if (!slice->isIntra())
3032
0
        {
3033
0
            for (int ref = 0; ref < MAX_NUM_REF; ref++)
3034
0
                frameStats->list0POC[ref] = ref < slice->m_numRefIdx[0] ? slice->m_refPOCList[0][ref] - slice->m_lastIDR : -1;
3035
3036
0
            if (!slice->isInterP())
3037
0
            {
3038
0
                for (int ref = 0; ref < MAX_NUM_REF; ref++)
3039
0
                    frameStats->list1POC[ref] = ref < slice->m_numRefIdx[1] ? slice->m_refPOCList[1][ref] - slice->m_lastIDR : -1;
3040
0
            }
3041
0
        }
3042
0
#define ELAPSED_MSEC(start, end) (((double)(end) - (start)) / 1000)
3043
0
        if (m_param->csvLogLevel >= 2)
3044
0
        {
3045
#if ENABLE_LIBVMAF
3046
            frameStats->vmafFrameScore = curFrame->m_fencPic->m_vmafScore;
3047
#endif
3048
0
            frameStats->decideWaitTime = ELAPSED_MSEC(0, curEncoder->m_slicetypeWaitTime);
3049
0
            frameStats->row0WaitTime = ELAPSED_MSEC(curEncoder->m_startCompressTime, curEncoder->m_row0WaitTime);
3050
0
            frameStats->wallTime = ELAPSED_MSEC(curEncoder->m_row0WaitTime, curEncoder->m_endCompressTime);
3051
0
            frameStats->refWaitWallTime = ELAPSED_MSEC(curEncoder->m_row0WaitTime, curEncoder->m_allRowsAvailableTime);
3052
0
            frameStats->totalCTUTime = ELAPSED_MSEC(0, curEncoder->m_totalWorkerElapsedTime);
3053
0
            frameStats->stallTime = ELAPSED_MSEC(0, curEncoder->m_totalNoWorkerTime);
3054
0
            frameStats->totalFrameTime = ELAPSED_MSEC(curFrame->m_encodeStartTime, x265_mdate());
3055
0
            if (curEncoder->m_totalActiveWorkerCount)
3056
0
                frameStats->avgWPP = (double)curEncoder->m_totalActiveWorkerCount / curEncoder->m_activeWorkerCountSamples;
3057
0
            else
3058
0
                frameStats->avgWPP = 1;
3059
0
            frameStats->countRowBlocks = curEncoder->m_countRowBlocks;
3060
3061
0
            frameStats->avgChromaDistortion = curFrame->m_encData->m_frameStats.avgChromaDistortion;
3062
0
            frameStats->avgLumaDistortion = curFrame->m_encData->m_frameStats.avgLumaDistortion;
3063
0
            frameStats->avgPsyEnergy = curFrame->m_encData->m_frameStats.avgPsyEnergy;
3064
0
            frameStats->avgResEnergy = curFrame->m_encData->m_frameStats.avgResEnergy;
3065
0
            frameStats->maxLumaLevel = curFrame->m_fencPic->m_maxLumaLevel;
3066
0
            frameStats->minLumaLevel = curFrame->m_fencPic->m_minLumaLevel;
3067
0
            frameStats->avgLumaLevel = curFrame->m_fencPic->m_avgLumaLevel;
3068
3069
0
            frameStats->maxChromaULevel = curFrame->m_fencPic->m_maxChromaULevel;
3070
0
            frameStats->minChromaULevel = curFrame->m_fencPic->m_minChromaULevel;
3071
0
            frameStats->avgChromaULevel = curFrame->m_fencPic->m_avgChromaULevel;
3072
3073
0
            frameStats->maxChromaVLevel = curFrame->m_fencPic->m_maxChromaVLevel;
3074
0
            frameStats->minChromaVLevel = curFrame->m_fencPic->m_minChromaVLevel;
3075
0
            frameStats->avgChromaVLevel = curFrame->m_fencPic->m_avgChromaVLevel;
3076
3077
0
            if (curFrame->m_encData->m_frameStats.totalPu[4] == 0)
3078
0
                frameStats->puStats.percentNxN = 0;
3079
0
            else
3080
0
                frameStats->puStats.percentNxN = (double)(curFrame->m_encData->m_frameStats.cnt4x4 / (double)curFrame->m_encData->m_frameStats.totalPu[4]) * 100;
3081
0
            for (uint32_t depth = 0; depth <= m_param->maxCUDepth; depth++)
3082
0
            {
3083
0
                if (curFrame->m_encData->m_frameStats.totalPu[depth] == 0)
3084
0
                {
3085
0
                    frameStats->puStats.percentSkipPu[depth] = 0;
3086
0
                    frameStats->puStats.percentIntraPu[depth] = 0;
3087
0
                    frameStats->puStats.percentAmpPu[depth] = 0;
3088
0
                    for (int i = 0; i < INTER_MODES - 1; i++)
3089
0
                    {
3090
0
                        frameStats->puStats.percentInterPu[depth][i] = 0;
3091
0
                        frameStats->puStats.percentMergePu[depth][i] = 0;
3092
0
                    }
3093
0
                }
3094
0
                else
3095
0
                {
3096
0
                    frameStats->puStats.percentSkipPu[depth] = (double)(curFrame->m_encData->m_frameStats.cntSkipPu[depth] / (double)curFrame->m_encData->m_frameStats.totalPu[depth]) * 100;
3097
0
                    frameStats->puStats.percentIntraPu[depth] = (double)(curFrame->m_encData->m_frameStats.cntIntraPu[depth] / (double)curFrame->m_encData->m_frameStats.totalPu[depth]) * 100;
3098
0
                    frameStats->puStats.percentAmpPu[depth] = (double)(curFrame->m_encData->m_frameStats.cntAmp[depth] / (double)curFrame->m_encData->m_frameStats.totalPu[depth]) * 100;
3099
0
                    for (int i = 0; i < INTER_MODES - 1; i++)
3100
0
                    {
3101
0
                        frameStats->puStats.percentInterPu[depth][i] = (double)(curFrame->m_encData->m_frameStats.cntInterPu[depth][i] / (double)curFrame->m_encData->m_frameStats.totalPu[depth]) * 100;
3102
0
                        frameStats->puStats.percentMergePu[depth][i] = (double)(curFrame->m_encData->m_frameStats.cntMergePu[depth][i] / (double)curFrame->m_encData->m_frameStats.totalPu[depth]) * 100;
3103
0
                    }
3104
0
                }
3105
0
            }
3106
0
        }
3107
3108
0
        if (m_param->csvLogLevel >= 1)
3109
0
        {
3110
0
            frameStats->cuStats.percentIntraNxN = curFrame->m_encData->m_frameStats.percentIntraNxN;
3111
3112
0
            for (uint32_t depth = 0; depth <= m_param->maxCUDepth; depth++)
3113
0
            {
3114
0
                frameStats->cuStats.percentSkipCu[depth] = curFrame->m_encData->m_frameStats.percentSkipCu[depth];
3115
0
                frameStats->cuStats.percentMergeCu[depth] = curFrame->m_encData->m_frameStats.percentMergeCu[depth];
3116
0
                frameStats->cuStats.percentInterDistribution[depth][0] = curFrame->m_encData->m_frameStats.percentInterDistribution[depth][0];
3117
0
                frameStats->cuStats.percentInterDistribution[depth][1] = curFrame->m_encData->m_frameStats.percentInterDistribution[depth][1];
3118
0
                frameStats->cuStats.percentInterDistribution[depth][2] = curFrame->m_encData->m_frameStats.percentInterDistribution[depth][2];
3119
0
                for (int n = 0; n < INTRA_MODES; n++)
3120
0
                    frameStats->cuStats.percentIntraDistribution[depth][n] = curFrame->m_encData->m_frameStats.percentIntraDistribution[depth][n];
3121
0
            }
3122
0
        }
3123
0
    }
3124
0
}
3125
3126
#if defined(_MSC_VER)
3127
#pragma warning(disable: 4800) // forcing int to bool
3128
#pragma warning(disable: 4127) // conditional expression is constant
3129
#endif
3130
3131
void Encoder::initRefIdx()
3132
0
{
3133
0
    int j = 0;
3134
3135
0
    for (j = 0; j < MAX_NUM_REF_IDX; j++)
3136
0
    {
3137
0
        m_refIdxLastGOP.numRefIdxl0[j] = 0;
3138
0
        m_refIdxLastGOP.numRefIdxl1[j] = 0;
3139
0
    }
3140
3141
0
    return;
3142
0
}
3143
3144
void Encoder::analyseRefIdx(int *numRefIdx)
3145
0
{
3146
0
    int i_l0 = 0;
3147
0
    int i_l1 = 0;
3148
3149
0
    i_l0 = numRefIdx[0];
3150
0
    i_l1 = numRefIdx[1];
3151
3152
0
    if ((0 < i_l0) && (MAX_NUM_REF_IDX > i_l0))
3153
0
        m_refIdxLastGOP.numRefIdxl0[i_l0]++;
3154
0
    if ((0 < i_l1) && (MAX_NUM_REF_IDX > i_l1))
3155
0
        m_refIdxLastGOP.numRefIdxl1[i_l1]++;
3156
3157
0
    return;
3158
0
}
3159
3160
void Encoder::updateRefIdx()
3161
0
{
3162
0
    int i_max_l0 = 0;
3163
0
    int i_max_l1 = 0;
3164
0
    int j = 0;
3165
3166
0
    i_max_l0 = 0;
3167
0
    i_max_l1 = 0;
3168
0
    m_refIdxLastGOP.numRefIdxDefault[0] = 1;
3169
0
    m_refIdxLastGOP.numRefIdxDefault[1] = 1;
3170
0
    for (j = 0; j < MAX_NUM_REF_IDX; j++)
3171
0
    {
3172
0
        if (i_max_l0 < m_refIdxLastGOP.numRefIdxl0[j])
3173
0
        {
3174
0
            i_max_l0 = m_refIdxLastGOP.numRefIdxl0[j];
3175
0
            m_refIdxLastGOP.numRefIdxDefault[0] = j;
3176
0
        }
3177
0
        if (i_max_l1 < m_refIdxLastGOP.numRefIdxl1[j])
3178
0
        {
3179
0
            i_max_l1 = m_refIdxLastGOP.numRefIdxl1[j];
3180
0
            m_refIdxLastGOP.numRefIdxDefault[1] = j;
3181
0
        }
3182
0
    }
3183
3184
0
    m_pps.numRefIdxDefault[0] = m_refIdxLastGOP.numRefIdxDefault[0];
3185
0
    m_pps.numRefIdxDefault[1] = m_refIdxLastGOP.numRefIdxDefault[1];
3186
0
    initRefIdx();
3187
3188
0
    return;
3189
0
}
3190
3191
void Encoder::getStreamHeaders(NALList& list, Entropy& sbacCoder, Bitstream& bs)
3192
0
{
3193
0
    sbacCoder.setBitstream(&bs);
3194
3195
0
    if (m_param->dolbyProfile && !m_param->bRepeatHeaders)
3196
0
    {
3197
0
        bs.resetBits();
3198
0
        bs.write(0x10, 8);
3199
0
        list.serialize(NAL_UNIT_ACCESS_UNIT_DELIMITER, bs);
3200
0
    }
3201
    
3202
    /* headers for start of bitstream */
3203
0
    bs.resetBits();
3204
0
    sbacCoder.codeVPS(m_vps);
3205
0
    bs.writeByteAlignment();
3206
0
    list.serialize(NAL_UNIT_VPS, bs);
3207
3208
0
    bs.resetBits();
3209
0
    sbacCoder.codeSPS(m_sps, m_scalingList, m_vps.ptl);
3210
0
    bs.writeByteAlignment();
3211
0
    list.serialize(NAL_UNIT_SPS, bs);
3212
3213
0
    bs.resetBits();
3214
0
    sbacCoder.codePPS(m_pps, (m_param->maxSlices <= 1), m_iPPSQpMinus26);
3215
0
    bs.writeByteAlignment();
3216
0
    list.serialize(NAL_UNIT_PPS, bs);
3217
3218
0
    if (m_param->bSingleSeiNal)
3219
0
        bs.resetBits();
3220
3221
0
    if (m_param->bEmitHDR10SEI)
3222
0
    {
3223
0
        if (m_param->bEmitCLL)
3224
0
        {
3225
0
            SEIContentLightLevel cllsei;
3226
0
            cllsei.max_content_light_level = m_param->maxCLL;
3227
0
            cllsei.max_pic_average_light_level = m_param->maxFALL;
3228
0
            cllsei.writeSEImessages(bs, m_sps, NAL_UNIT_PREFIX_SEI, list, m_param->bSingleSeiNal);
3229
0
        }
3230
3231
0
        if (m_param->masteringDisplayColorVolume)
3232
0
        {
3233
0
            SEIMasteringDisplayColorVolume mdsei;
3234
0
            if (mdsei.parse(m_param->masteringDisplayColorVolume))
3235
0
                mdsei.writeSEImessages(bs, m_sps, NAL_UNIT_PREFIX_SEI, list, m_param->bSingleSeiNal);
3236
0
            else
3237
0
                x265_log(m_param, X265_LOG_WARNING, "unable to parse mastering display color volume info\n");
3238
0
        }
3239
0
    }
3240
3241
0
    if (m_param->bEmitInfoSEI)
3242
0
    {
3243
0
        char *opts = x265_param2string(m_param, m_sps.conformanceWindow.rightOffset, m_sps.conformanceWindow.bottomOffset);
3244
0
        if (opts)
3245
0
        {
3246
0
            char *buffer = X265_MALLOC(char, strlen(opts) + strlen(PFX(version_str)) +
3247
0
                strlen(PFX(build_info_str)) + 200);
3248
0
            if (buffer)
3249
0
            {
3250
0
                sprintf(buffer, "x265 (build %d) - %s:%s - H.265/HEVC codec - "
3251
0
                    "Copyright 2013-2018 (c) Multicoreware, Inc - "
3252
0
                    "http://x265.org - options: %s",
3253
0
                    X265_BUILD, PFX(version_str), PFX(build_info_str), opts);
3254
3255
0
                SEIuserDataUnregistered idsei;
3256
0
                idsei.m_userData = (uint8_t*)buffer;
3257
0
                idsei.setSize((uint32_t)strlen(buffer));
3258
0
                idsei.writeSEImessages(bs, m_sps, NAL_UNIT_PREFIX_SEI, list, m_param->bSingleSeiNal);
3259
3260
0
                X265_FREE(buffer);
3261
0
            }
3262
3263
0
            X265_FREE(opts);
3264
0
        }
3265
0
    }
3266
3267
0
    if ((m_param->bEmitHRDSEI || !!m_param->interlaceMode))
3268
0
    {
3269
        /* Picture Timing and Buffering Period SEI require the SPS to be "activated" */
3270
0
        SEIActiveParameterSets sei;
3271
0
        sei.m_selfContainedCvsFlag = true;
3272
0
        sei.m_noParamSetUpdateFlag = true;
3273
0
        sei.writeSEImessages(bs, m_sps, NAL_UNIT_PREFIX_SEI, list, m_param->bSingleSeiNal);
3274
0
    }
3275
0
}
3276
3277
void Encoder::initVPS(VPS *vps)
3278
0
{
3279
    /* Note that much of the VPS is initialized by determineLevel() */
3280
0
    vps->ptl.progressiveSourceFlag = !m_param->interlaceMode;
3281
0
    vps->ptl.interlacedSourceFlag = !!m_param->interlaceMode;
3282
0
    vps->ptl.nonPackedConstraintFlag = false;
3283
0
    vps->ptl.frameOnlyConstraintFlag = !m_param->interlaceMode;
3284
0
}
3285
3286
void Encoder::initSPS(SPS *sps)
3287
0
{
3288
0
    sps->conformanceWindow = m_conformanceWindow;
3289
0
    sps->chromaFormatIdc = m_param->internalCsp;
3290
0
    sps->picWidthInLumaSamples = m_param->sourceWidth;
3291
0
    sps->picHeightInLumaSamples = m_param->sourceHeight;
3292
0
    sps->numCuInWidth = (m_param->sourceWidth + m_param->maxCUSize - 1) / m_param->maxCUSize;
3293
0
    sps->numCuInHeight = (m_param->sourceHeight + m_param->maxCUSize - 1) / m_param->maxCUSize;
3294
0
    sps->numCUsInFrame = sps->numCuInWidth * sps->numCuInHeight;
3295
0
    sps->numPartitions = m_param->num4x4Partitions;
3296
0
    sps->numPartInCUSize = 1 << m_param->unitSizeDepth;
3297
3298
0
    sps->log2MinCodingBlockSize = m_param->maxLog2CUSize - m_param->maxCUDepth;
3299
0
    sps->log2DiffMaxMinCodingBlockSize = m_param->maxCUDepth;
3300
0
    uint32_t maxLog2TUSize = (uint32_t)g_log2Size[m_param->maxTUSize];
3301
0
    sps->quadtreeTULog2MaxSize = X265_MIN((uint32_t)m_param->maxLog2CUSize, maxLog2TUSize);
3302
0
    sps->quadtreeTULog2MinSize = 2;
3303
0
    sps->quadtreeTUMaxDepthInter = m_param->tuQTMaxInterDepth;
3304
0
    sps->quadtreeTUMaxDepthIntra = m_param->tuQTMaxIntraDepth;
3305
3306
0
    sps->bUseSAO = m_param->bEnableSAO;
3307
3308
0
    sps->bUseAMP = m_param->bEnableAMP;
3309
0
    sps->maxAMPDepth = m_param->bEnableAMP ? m_param->maxCUDepth : 0;
3310
3311
0
    sps->maxTempSubLayers = m_param->bEnableTemporalSubLayers ? 2 : 1;
3312
0
    sps->maxDecPicBuffering = m_vps.maxDecPicBuffering;
3313
0
    sps->numReorderPics = m_vps.numReorderPics;
3314
0
    sps->maxLatencyIncrease = m_vps.maxLatencyIncrease = m_param->bframes;
3315
3316
0
    sps->bUseStrongIntraSmoothing = m_param->bEnableStrongIntraSmoothing;
3317
0
    sps->bTemporalMVPEnabled = m_param->bEnableTemporalMvp;
3318
0
    sps->bEmitVUITimingInfo = m_param->bEmitVUITimingInfo;
3319
0
    sps->bEmitVUIHRDInfo = m_param->bEmitVUIHRDInfo;
3320
0
    sps->log2MaxPocLsb = m_param->log2MaxPocLsb;
3321
0
    int maxDeltaPOC = (m_param->bframes + 2) * (!!m_param->bBPyramid + 1) * 2;
3322
0
    while ((1 << sps->log2MaxPocLsb) <= maxDeltaPOC * 2)
3323
0
        sps->log2MaxPocLsb++;
3324
3325
0
    if (sps->log2MaxPocLsb != m_param->log2MaxPocLsb)
3326
0
        x265_log(m_param, X265_LOG_WARNING, "Reset log2MaxPocLsb to %d to account for all POC values\n", sps->log2MaxPocLsb);
3327
3328
0
    VUI& vui = sps->vuiParameters;
3329
0
    vui.aspectRatioInfoPresentFlag = !!m_param->vui.aspectRatioIdc;
3330
0
    vui.aspectRatioIdc = m_param->vui.aspectRatioIdc;
3331
0
    vui.sarWidth = m_param->vui.sarWidth;
3332
0
    vui.sarHeight = m_param->vui.sarHeight;
3333
3334
0
    vui.overscanInfoPresentFlag = m_param->vui.bEnableOverscanInfoPresentFlag;
3335
0
    vui.overscanAppropriateFlag = m_param->vui.bEnableOverscanAppropriateFlag;
3336
3337
0
    vui.videoSignalTypePresentFlag = m_param->vui.bEnableVideoSignalTypePresentFlag;
3338
0
    vui.videoFormat = m_param->vui.videoFormat;
3339
0
    vui.videoFullRangeFlag = m_param->vui.bEnableVideoFullRangeFlag;
3340
3341
0
    vui.colourDescriptionPresentFlag = m_param->vui.bEnableColorDescriptionPresentFlag;
3342
0
    vui.colourPrimaries = m_param->vui.colorPrimaries;
3343
0
    vui.transferCharacteristics = m_param->vui.transferCharacteristics;
3344
0
    vui.matrixCoefficients = m_param->vui.matrixCoeffs;
3345
3346
0
    vui.chromaLocInfoPresentFlag = m_param->vui.bEnableChromaLocInfoPresentFlag;
3347
0
    vui.chromaSampleLocTypeTopField = m_param->vui.chromaSampleLocTypeTopField;
3348
0
    vui.chromaSampleLocTypeBottomField = m_param->vui.chromaSampleLocTypeBottomField;
3349
3350
0
    vui.defaultDisplayWindow.bEnabled = m_param->vui.bEnableDefaultDisplayWindowFlag;
3351
0
    vui.defaultDisplayWindow.rightOffset = m_param->vui.defDispWinRightOffset;
3352
0
    vui.defaultDisplayWindow.topOffset = m_param->vui.defDispWinTopOffset;
3353
0
    vui.defaultDisplayWindow.bottomOffset = m_param->vui.defDispWinBottomOffset;
3354
0
    vui.defaultDisplayWindow.leftOffset = m_param->vui.defDispWinLeftOffset;
3355
3356
0
    vui.frameFieldInfoPresentFlag = !!m_param->interlaceMode || (m_param->pictureStructure >= 0);
3357
0
    vui.fieldSeqFlag = !!m_param->interlaceMode;
3358
3359
0
    vui.hrdParametersPresentFlag = m_param->bEmitHRDSEI;
3360
3361
0
    vui.timingInfo.numUnitsInTick = m_param->fpsDenom;
3362
0
    vui.timingInfo.timeScale = m_param->fpsNum;
3363
0
}
3364
3365
void Encoder::initPPS(PPS *pps)
3366
0
{
3367
0
    bool bIsVbv = m_param->rc.vbvBufferSize > 0 && m_param->rc.vbvMaxBitrate > 0;
3368
0
    bool bEnableDistOffset = m_param->analysisMultiPassDistortion && m_param->rc.bStatRead;
3369
3370
0
    if (!m_param->bLossless && (m_param->rc.aqMode || bIsVbv || m_param->bAQMotion))
3371
0
    {
3372
0
        pps->bUseDQP = true;
3373
0
        pps->maxCuDQPDepth = g_log2Size[m_param->maxCUSize] - g_log2Size[m_param->rc.qgSize];
3374
0
        X265_CHECK(pps->maxCuDQPDepth <= 3, "max CU DQP depth cannot be greater than 3\n");
3375
0
    }
3376
0
    else if (!m_param->bLossless && bEnableDistOffset)
3377
0
    {
3378
0
        pps->bUseDQP = true;
3379
0
        pps->maxCuDQPDepth = 0;
3380
0
    }
3381
0
    else
3382
0
    {
3383
0
        pps->bUseDQP = false;
3384
0
        pps->maxCuDQPDepth = 0;
3385
0
    }
3386
3387
0
    pps->chromaQpOffset[0] = m_param->cbQpOffset;
3388
0
    pps->chromaQpOffset[1] = m_param->crQpOffset;
3389
0
    pps->pps_slice_chroma_qp_offsets_present_flag = m_param->bHDR10Opt;
3390
3391
0
    pps->bConstrainedIntraPred = m_param->bEnableConstrainedIntra;
3392
0
    pps->bUseWeightPred = m_param->bEnableWeightedPred;
3393
0
    pps->bUseWeightedBiPred = m_param->bEnableWeightedBiPred;
3394
0
    pps->bTransquantBypassEnabled = m_param->bCULossless || m_param->bLossless;
3395
0
    pps->bTransformSkipEnabled = m_param->bEnableTransformSkip;
3396
0
    pps->bSignHideEnabled = m_param->bEnableSignHiding;
3397
3398
0
    pps->bDeblockingFilterControlPresent = !m_param->bEnableLoopFilter || m_param->deblockingFilterBetaOffset || m_param->deblockingFilterTCOffset;
3399
0
    pps->bPicDisableDeblockingFilter = !m_param->bEnableLoopFilter;
3400
0
    pps->deblockingFilterBetaOffsetDiv2 = m_param->deblockingFilterBetaOffset;
3401
0
    pps->deblockingFilterTcOffsetDiv2 = m_param->deblockingFilterTCOffset;
3402
3403
0
    pps->bEntropyCodingSyncEnabled = m_param->bEnableWavefront;
3404
3405
0
    pps->numRefIdxDefault[0] = 1;
3406
0
    pps->numRefIdxDefault[1] = 1;
3407
0
}
3408
3409
void Encoder::configureZone(x265_param *p, x265_param *zone)
3410
0
{
3411
0
    if (m_param->bResetZoneConfig)
3412
0
    {
3413
0
        p->maxNumReferences = zone->maxNumReferences;
3414
0
        p->bEnableFastIntra = zone->bEnableFastIntra;
3415
0
        p->bEnableEarlySkip = zone->bEnableEarlySkip;
3416
0
        p->recursionSkipMode = zone->recursionSkipMode;
3417
0
        p->searchMethod = zone->searchMethod;
3418
0
        p->searchRange = zone->searchRange;
3419
0
        p->subpelRefine = zone->subpelRefine;
3420
0
        p->rdoqLevel = zone->rdoqLevel;
3421
0
        p->rdLevel = zone->rdLevel;
3422
0
        p->bEnableRectInter = zone->bEnableRectInter;
3423
0
        p->maxNumMergeCand = zone->maxNumMergeCand;
3424
0
        p->bIntraInBFrames = zone->bIntraInBFrames;
3425
0
        if (zone->scalingLists)
3426
0
            p->scalingLists = strdup(zone->scalingLists);
3427
3428
0
        p->rc.aqMode = zone->rc.aqMode;
3429
0
        p->rc.aqStrength = zone->rc.aqStrength;
3430
0
        p->noiseReductionInter = zone->noiseReductionInter;
3431
0
        p->noiseReductionIntra = zone->noiseReductionIntra;
3432
3433
0
        p->limitModes = zone->limitModes;
3434
0
        p->bEnableSplitRdSkip = zone->bEnableSplitRdSkip;
3435
0
        p->bCULossless = zone->bCULossless;
3436
0
        p->bEnableRdRefine = zone->bEnableRdRefine;
3437
0
        p->limitTU = zone->limitTU;
3438
0
        p->bEnableTSkipFast = zone->bEnableTSkipFast;
3439
0
        p->rdPenalty = zone->rdPenalty;
3440
0
        p->dynamicRd = zone->dynamicRd;
3441
0
        p->bEnableTransformSkip = zone->bEnableTransformSkip;
3442
0
        p->bEnableAMP = zone->bEnableAMP;
3443
3444
0
        if (m_param->rc.rateControlMode == X265_RC_ABR)
3445
0
            p->rc.bitrate = zone->rc.bitrate;
3446
0
        if (m_param->rc.rateControlMode == X265_RC_CRF)
3447
0
            p->rc.rfConstant = zone->rc.rfConstant;
3448
0
        if (m_param->rc.rateControlMode == X265_RC_CQP)
3449
0
        {
3450
0
            p->rc.qp = zone->rc.qp;
3451
0
            p->rc.aqMode = X265_AQ_NONE;
3452
0
            p->rc.hevcAq = 0;
3453
0
        }
3454
0
        p->radl = zone->radl;
3455
0
    }
3456
0
    memcpy(zone, p, sizeof(x265_param));
3457
0
}
3458
3459
void Encoder::configureDolbyVisionParams(x265_param* p)
3460
0
{
3461
0
    uint32_t doviProfile = 0;
3462
3463
0
    while (dovi[doviProfile].doviProfileId != p->dolbyProfile && doviProfile + 1 < sizeof(dovi) / sizeof(dovi[0]))
3464
0
        doviProfile++;
3465
3466
0
    p->bEmitHRDSEI = dovi[doviProfile].bEmitHRDSEI;
3467
0
    p->vui.bEnableVideoSignalTypePresentFlag = dovi[doviProfile].bEnableVideoSignalTypePresentFlag;
3468
0
    p->vui.bEnableColorDescriptionPresentFlag = dovi[doviProfile].bEnableColorDescriptionPresentFlag;
3469
0
    p->bEnableAccessUnitDelimiters = dovi[doviProfile].bEnableAccessUnitDelimiters;
3470
0
    p->bAnnexB = dovi[doviProfile].bAnnexB;
3471
0
    p->vui.videoFormat = dovi[doviProfile].videoFormat;
3472
0
    p->vui.bEnableVideoFullRangeFlag = dovi[doviProfile].bEnableVideoFullRangeFlag;
3473
0
    p->vui.transferCharacteristics = dovi[doviProfile].transferCharacteristics;
3474
0
    p->vui.colorPrimaries = dovi[doviProfile].colorPrimaries;
3475
0
    p->vui.matrixCoeffs = dovi[doviProfile].matrixCoeffs;
3476
3477
0
    if (dovi[doviProfile].doviProfileId == 81)
3478
0
        p->bEmitHDR10SEI = p->bEmitCLL = 1;
3479
3480
0
    if (dovi[doviProfile].doviProfileId == 50)
3481
0
        p->crQpOffset = 3;
3482
0
}
3483
3484
void Encoder::configure(x265_param *p)
3485
0
{
3486
0
    this->m_param = p;
3487
0
    if (p->bAnalysisType == AVC_INFO)
3488
0
        this->m_externalFlush = true;
3489
0
    else 
3490
0
        this->m_externalFlush = false;
3491
3492
0
    if (p->bAnalysisType == AVC_INFO && (p->limitTU == 3 || p->limitTU == 4))
3493
0
    {
3494
0
        x265_log(p, X265_LOG_WARNING, "limit TU = 3 or 4 with MVType AVCINFO produces inconsistent output\n");
3495
0
    }
3496
3497
0
    if (p->bAnalysisType == AVC_INFO && p->minCUSize != 8)
3498
0
    {
3499
0
        p->minCUSize = 8;
3500
0
        x265_log(p, X265_LOG_WARNING, "Setting minCuSize = 8, AVCINFO expects 8x8 blocks\n");
3501
0
    }
3502
3503
0
    if (p->keyframeMax < 0)
3504
0
    {
3505
        /* A negative max GOP size indicates the user wants only one I frame at
3506
         * the start of the stream. Set an infinite GOP distance and disable
3507
         * adaptive I frame placement */
3508
0
        p->keyframeMax = INT_MAX;
3509
0
        p->scenecutThreshold = 0;
3510
0
        p->bHistBasedSceneCut = 0;
3511
0
    }
3512
0
    else if (p->keyframeMax <= 1)
3513
0
    {
3514
0
        p->keyframeMax = 1;
3515
3516
        // disable lookahead for all-intra encodes
3517
0
        p->bFrameAdaptive = 0;
3518
0
        p->bframes = 0;
3519
0
        p->bOpenGOP = 0;
3520
0
        p->bRepeatHeaders = 1;
3521
0
        p->lookaheadDepth = 0;
3522
0
        p->bframes = 0;
3523
0
        p->scenecutThreshold = 0;
3524
0
        p->bHistBasedSceneCut = 0;
3525
0
        p->bFrameAdaptive = 0;
3526
0
        p->rc.cuTree = 0;
3527
0
        p->bEnableWeightedPred = 0;
3528
0
        p->bEnableWeightedBiPred = 0;
3529
0
        p->bIntraRefresh = 0;
3530
3531
        /* SPSs shall have sps_max_dec_pic_buffering_minus1[ sps_max_sub_layers_minus1 ] equal to 0 only */
3532
0
        p->maxNumReferences = 1;
3533
0
    }
3534
0
    if (!p->keyframeMin)
3535
0
    {
3536
0
        double fps = (double)p->fpsNum / p->fpsDenom;
3537
0
        p->keyframeMin = X265_MIN((int)fps, p->keyframeMax / 10);
3538
0
    }
3539
0
    p->keyframeMin = X265_MAX(1, p->keyframeMin);
3540
3541
0
    if (!p->bframes)
3542
0
        p->bBPyramid = 0;
3543
0
    if (!p->rdoqLevel)
3544
0
        p->psyRdoq = 0;
3545
3546
    /* Disable features which are not supported by the current RD level */
3547
0
    if (p->rdLevel < 3)
3548
0
    {
3549
0
        if (p->bCULossless)             /* impossible */
3550
0
            x265_log(p, X265_LOG_WARNING, "--cu-lossless disabled, requires --rdlevel 3 or higher\n");
3551
0
        if (p->bEnableTransformSkip)    /* impossible */
3552
0
            x265_log(p, X265_LOG_WARNING, "--tskip disabled, requires --rdlevel 3 or higher\n");
3553
0
        p->bCULossless = p->bEnableTransformSkip = 0;
3554
0
    }
3555
0
    if (p->rdLevel < 2)
3556
0
    {
3557
0
        if (p->bDistributeModeAnalysis) /* not useful */
3558
0
            x265_log(p, X265_LOG_WARNING, "--pmode disabled, requires --rdlevel 2 or higher\n");
3559
0
        p->bDistributeModeAnalysis = 0;
3560
3561
0
        p->psyRd = 0;                   /* impossible */
3562
3563
0
        if (p->bEnableRectInter)        /* broken, not very useful */
3564
0
            x265_log(p, X265_LOG_WARNING, "--rect disabled, requires --rdlevel 2 or higher\n");
3565
0
        p->bEnableRectInter = 0;
3566
0
    }
3567
3568
0
    if (!p->bEnableRectInter)          /* not useful */
3569
0
        p->bEnableAMP = false;
3570
3571
    /* In 444, chroma gets twice as much resolution, so halve quality when psy-rd is enabled */
3572
0
    if (p->internalCsp == X265_CSP_I444 && p->psyRd)
3573
0
    {
3574
0
        if (!p->cbQpOffset && !p->crQpOffset)
3575
0
        {
3576
0
            p->cbQpOffset = MAX_CHROMA_QP_OFFSET / 2;
3577
0
            p->crQpOffset = MAX_CHROMA_QP_OFFSET / 2;
3578
0
            x265_log(p, X265_LOG_WARNING, "halving the quality when psy-rd is enabled for 444 input."
3579
0
                     " Setting cbQpOffset = %d and crQpOffset = %d\n", p->cbQpOffset, p->crQpOffset);
3580
0
        }
3581
0
    }
3582
3583
0
    if (p->bLossless)
3584
0
    {
3585
0
        p->rc.rateControlMode = X265_RC_CQP;
3586
0
        p->rc.qp = 4; // An oddity, QP=4 is more lossless than QP=0 and gives better lambdas
3587
0
        p->bEnableSsim = 0;
3588
0
        p->bEnablePsnr = 0;
3589
0
    }
3590
3591
0
    if (p->rc.rateControlMode == X265_RC_CQP)
3592
0
    {
3593
0
        p->rc.aqMode = X265_AQ_NONE;
3594
0
        p->rc.hevcAq = 0;
3595
0
        p->rc.bitrate = 0;
3596
0
        p->rc.cuTree = 0;
3597
0
        p->rc.aqStrength = 0;
3598
0
    }
3599
3600
0
    if (p->rc.aqMode == 0 && p->rc.cuTree)
3601
0
    {
3602
0
        p->rc.aqMode = X265_AQ_VARIANCE;
3603
0
        p->rc.aqStrength = 0.0;
3604
0
    }
3605
3606
0
    if (p->lookaheadDepth == 0 && p->rc.cuTree && !p->rc.bStatRead)
3607
0
    {
3608
0
        x265_log(p, X265_LOG_WARNING, "cuTree disabled, requires lookahead to be enabled\n");
3609
0
        p->rc.cuTree = 0;
3610
0
    }
3611
3612
0
    if (p->maxTUSize > p->maxCUSize)
3613
0
    {
3614
0
        x265_log(p, X265_LOG_WARNING, "Max TU size should be less than or equal to max CU size, setting max TU size = %d\n", p->maxCUSize);
3615
0
        p->maxTUSize = p->maxCUSize;
3616
0
    }
3617
0
    if (p->rc.aqStrength == 0 && p->rc.cuTree == 0)
3618
0
    {
3619
0
        p->rc.aqMode = X265_AQ_NONE;
3620
0
        p->rc.hevcAq = 0;
3621
0
    }
3622
0
    if (p->rc.aqMode == X265_AQ_NONE && p->rc.cuTree == 0)
3623
0
        p->rc.aqStrength = 0;
3624
0
    if (p->rc.hevcAq && p->rc.aqMode)
3625
0
    {
3626
0
        x265_log(p, X265_LOG_WARNING, "hevc-aq enabled, disabling other aq-modes\n");
3627
0
    }
3628
3629
0
    if (p->totalFrames && p->totalFrames <= 2 * ((float)p->fpsNum) / p->fpsDenom && p->rc.bStrictCbr)
3630
0
        p->lookaheadDepth = p->totalFrames;
3631
0
    if (p->bIntraRefresh)
3632
0
    {
3633
0
        int numCuInWidth = (m_param->sourceWidth + m_param->maxCUSize - 1) / m_param->maxCUSize;
3634
0
        if (p->maxNumReferences > 1)
3635
0
        {
3636
0
            x265_log(p,  X265_LOG_WARNING, "Max References > 1 + intra-refresh is not supported , setting max num references = 1\n");
3637
0
            p->maxNumReferences = 1;
3638
0
        }
3639
3640
0
        if (p->bBPyramid && p->bframes)
3641
0
            x265_log(p,  X265_LOG_WARNING, "B pyramid cannot be enabled when max references is 1, Disabling B pyramid\n");
3642
0
        p->bBPyramid = 0;
3643
3644
3645
0
        if (p->bOpenGOP)
3646
0
        {
3647
0
            x265_log(p,  X265_LOG_WARNING, "Open Gop disabled, Intra Refresh is not compatible with openGop\n");
3648
0
            p->bOpenGOP = 0;
3649
0
        }
3650
3651
0
        x265_log(p,  X265_LOG_WARNING, "Scenecut is disabled when Intra Refresh is enabled\n");
3652
3653
0
        if (((float)numCuInWidth - 1) / m_param->keyframeMax > 1)
3654
0
            x265_log(p,  X265_LOG_WARNING, "Keyint value is very low.It leads to frequent intra refreshes, can be almost every frame."
3655
0
                     "Prefered use case would be high keyint value or an API call to refresh when necessary\n");
3656
3657
0
    }
3658
3659
0
    if (p->selectiveSAO && !p->bEnableSAO)
3660
0
    {
3661
0
        p->bEnableSAO = 1;
3662
0
        x265_log(p, X265_LOG_WARNING, "SAO turned ON when selective-sao is ON\n");
3663
0
    }
3664
3665
0
    if (!p->selectiveSAO && p->bEnableSAO)
3666
0
        p->selectiveSAO = 4;
3667
3668
0
    if (p->interlaceMode)
3669
0
        x265_log(p, X265_LOG_WARNING, "Support for interlaced video is experimental\n");
3670
3671
0
    if (p->rc.rfConstantMin > p->rc.rfConstant)
3672
0
    {
3673
0
        x265_log(m_param, X265_LOG_WARNING, "CRF min must be less than CRF\n");
3674
0
        p->rc.rfConstantMin = 0;
3675
0
    }
3676
3677
0
    if (p->analysisSaveReuseLevel && !p->analysisSave)
3678
0
    {
3679
0
        x265_log(p, X265_LOG_WARNING, "analysis-save-reuse-level can be set only when analysis-save is enabled."
3680
0
            " Resetting analysis-save-reuse-level to 0.\n");
3681
0
        p->analysisSaveReuseLevel = 0;
3682
0
    }
3683
3684
0
    if (p->analysisLoadReuseLevel && !p->analysisLoad)
3685
0
    {
3686
0
        x265_log(p, X265_LOG_WARNING, "analysis-load-reuse-level can be set only when analysis-load is enabled."
3687
0
            " Resetting analysis-load-reuse-level to 0.\n");
3688
0
        p->analysisLoadReuseLevel = 0;
3689
0
    }
3690
3691
0
    if (p->analysisSave && !p->analysisSaveReuseLevel)
3692
0
        p->analysisSaveReuseLevel = 5;
3693
3694
0
    if (p->analysisLoad && !p->analysisLoadReuseLevel)
3695
0
        p->analysisLoadReuseLevel = 5;
3696
3697
0
    if ((p->analysisLoad || p->analysisSave) && (p->bDistributeModeAnalysis || p->bDistributeMotionEstimation))
3698
0
    {
3699
0
        x265_log(p, X265_LOG_WARNING, "Analysis load/save options incompatible with pmode/pme, Disabling pmode/pme\n");
3700
0
        p->bDistributeMotionEstimation = p->bDistributeModeAnalysis = 0;
3701
0
    }
3702
3703
0
    if ((p->analysisLoad || p->analysisSave) && (p->analysisMultiPassRefine || p->analysisMultiPassDistortion))
3704
0
    {
3705
0
        x265_log(p, X265_LOG_WARNING, "Cannot use Analysis load/save option and multi-pass-opt-analysis/multi-pass-opt-distortion together,"
3706
0
            "Disabling Analysis load/save and multi-pass-opt-analysis/multi-pass-opt-distortion\n");
3707
0
        p->analysisSave = p->analysisLoad = NULL;
3708
0
        p->analysisMultiPassRefine = p->analysisMultiPassDistortion = 0;
3709
0
    }
3710
0
    if (p->scaleFactor)
3711
0
    {
3712
0
        if (p->scaleFactor == 1)
3713
0
        {
3714
0
            p->scaleFactor = 0;
3715
0
        }
3716
0
        else if ((p->analysisSaveReuseLevel > 6 && p->analysisSaveReuseLevel != 10) || (p->analysisLoadReuseLevel > 6 && p->analysisLoadReuseLevel != 10))
3717
0
        {
3718
0
            x265_log(p, X265_LOG_WARNING, "Input scaling works with analysis-save/load and analysis-save/load-reuse-level 1-6 and 10. Disabling scale-factor.\n");
3719
0
            p->scaleFactor = 0;
3720
0
        }
3721
0
    }
3722
3723
0
    if (p->intraRefine && p->analysisLoadReuseLevel && p->analysisLoadReuseLevel < 10)
3724
0
    {
3725
0
        x265_log(p, X265_LOG_WARNING, "Intra refinement requires analysis load, analysis-load-reuse-level 10. Disabling intra refine.\n");
3726
0
        p->intraRefine = 0;
3727
0
    }
3728
3729
0
    if (p->interRefine && p->analysisLoadReuseLevel && p->analysisLoadReuseLevel < 10)
3730
0
    {
3731
0
        x265_log(p, X265_LOG_WARNING, "Inter refinement requires analysis load, analysis-load-reuse-level 10. Disabling inter refine.\n");
3732
0
        p->interRefine = 0;
3733
0
    }
3734
3735
0
    if (p->bDynamicRefine && p->analysisLoadReuseLevel && p->analysisLoadReuseLevel < 10)
3736
0
    {
3737
0
        x265_log(p, X265_LOG_WARNING, "Dynamic refinement requires analysis load, analysis-load-reuse-level 10. Disabling dynamic refine.\n");
3738
0
        p->bDynamicRefine = 0;
3739
3740
0
        if (p->interRefine)
3741
0
        {
3742
0
            x265_log(p, X265_LOG_WARNING, "Inter refine cannot be used with dynamic refine. Disabling refine-inter.\n");
3743
0
            p->interRefine = 0;
3744
0
        }
3745
0
    }
3746
0
    if (p->scaleFactor && !p->interRefine && !p->bDynamicRefine && p->analysisLoadReuseLevel == 10)
3747
0
    {
3748
0
        x265_log(p, X265_LOG_WARNING, "Inter refinement 0 is not supported with scaling and analysis-reuse-level=10. Enabling refine-inter 1.\n");
3749
0
        p->interRefine = 1;
3750
0
    }
3751
3752
0
    if (!(p->bAnalysisType == HEVC_INFO) && p->limitTU && (p->interRefine || p->bDynamicRefine))
3753
0
    {
3754
0
        x265_log(p, X265_LOG_WARNING, "Inter refinement does not support limitTU. Disabling limitTU.\n");
3755
0
        p->limitTU = 0;
3756
0
    }
3757
3758
0
    if (p->ctuDistortionRefine == CTU_DISTORTION_INTERNAL)
3759
0
    {
3760
0
        if (!p->analysisLoad && !p->analysisSave)
3761
0
        {
3762
0
            x265_log(p, X265_LOG_WARNING, "refine-ctu-distortion 1 requires analysis save/load. Disabling refine-ctu-distortion\n");
3763
0
            p->ctuDistortionRefine = 0;
3764
0
        }
3765
0
        if (p->scaleFactor && p->analysisLoad)
3766
0
        {
3767
0
            x265_log(p, X265_LOG_WARNING, "refine-ctu-distortion 1 cannot be enabled along with multi resolution analysis refinement. Disabling refine-ctu-distortion\n");
3768
0
            p->ctuDistortionRefine = 0;
3769
0
        }
3770
0
    }
3771
3772
0
    if ((p->analysisMultiPassRefine || p->analysisMultiPassDistortion) && (p->bDistributeModeAnalysis || p->bDistributeMotionEstimation))
3773
0
    {
3774
0
        x265_log(p, X265_LOG_WARNING, "multi-pass-opt-analysis/multi-pass-opt-distortion incompatible with pmode/pme, Disabling pmode/pme\n");
3775
0
        p->bDistributeMotionEstimation = p->bDistributeModeAnalysis = 0;
3776
0
    }
3777
3778
0
    if (p->bDistributeModeAnalysis && (p->limitReferences >> 1) && 1)
3779
0
    {
3780
0
        x265_log(p, X265_LOG_WARNING, "Limit reference options 2 and 3 are not supported with pmode. Disabling limit reference\n");
3781
0
        p->limitReferences = 0;
3782
0
    }
3783
3784
0
    if (p->bEnableTemporalSubLayers && !p->bframes)
3785
0
    {
3786
0
        x265_log(p, X265_LOG_WARNING, "B frames not enabled, temporal sublayer disabled\n");
3787
0
        p->bEnableTemporalSubLayers = 0;
3788
0
    }
3789
3790
0
    m_bframeDelay = p->bframes ? (p->bBPyramid ? 2 : 1) : 0;
3791
3792
0
    p->bFrameBias = X265_MIN(X265_MAX(-90, p->bFrameBias), 100);
3793
0
    p->scenecutBias = (double)(p->scenecutBias / 100);
3794
3795
0
    if (p->logLevel < X265_LOG_INFO)
3796
0
    {
3797
        /* don't measure these metrics if they will not be reported */
3798
0
        p->bEnablePsnr = 0;
3799
0
        p->bEnableSsim = 0;
3800
0
    }
3801
    /* Warn users trying to measure PSNR/SSIM with psy opts on. */
3802
0
    if (p->bEnablePsnr || p->bEnableSsim)
3803
0
    {
3804
0
        const char *s = NULL;
3805
3806
0
        if (p->psyRd || p->psyRdoq)
3807
0
        {
3808
0
            s = p->bEnablePsnr ? "psnr" : "ssim";
3809
0
            x265_log(p, X265_LOG_WARNING, "--%s used with psy on: results will be invalid!\n", s);
3810
0
        }
3811
0
        else if (!p->rc.aqMode && p->bEnableSsim)
3812
0
        {
3813
0
            x265_log(p, X265_LOG_WARNING, "--ssim used with AQ off: results will be invalid!\n");
3814
0
            s = "ssim";
3815
0
        }
3816
0
        else if (p->rc.aqStrength > 0 && p->bEnablePsnr)
3817
0
        {
3818
0
            x265_log(p, X265_LOG_WARNING, "--psnr used with AQ on: results will be invalid!\n");
3819
0
            s = "psnr";
3820
0
        }
3821
0
        if (s)
3822
0
            x265_log(p, X265_LOG_WARNING, "--tune %s should be used if attempting to benchmark %s!\n", s, s);
3823
0
    }
3824
0
    if (p->searchMethod == X265_SEA && (p->bDistributeMotionEstimation || p->bDistributeModeAnalysis))
3825
0
    {
3826
0
        x265_log(p, X265_LOG_WARNING, "Disabling pme and pmode: --pme and --pmode cannot be used with SEA motion search!\n");
3827
0
        p->bDistributeMotionEstimation = 0;
3828
0
        p->bDistributeModeAnalysis = 0;
3829
0
    }
3830
3831
0
    if (!p->rc.bStatWrite && !p->rc.bStatRead && (p->analysisMultiPassRefine || p->analysisMultiPassDistortion))
3832
0
    {
3833
0
        x265_log(p, X265_LOG_WARNING, "analysis-multi-pass/distortion is enabled only when rc multi pass is enabled. Disabling multi-pass-opt-analysis and multi-pass-opt-distortion\n");
3834
0
        p->analysisMultiPassRefine = 0;
3835
0
        p->analysisMultiPassDistortion = 0;
3836
0
    }
3837
0
    if (p->analysisMultiPassRefine && p->rc.bStatWrite && p->rc.bStatRead)
3838
0
    {
3839
0
        x265_log(p, X265_LOG_WARNING, "--multi-pass-opt-analysis doesn't support refining analysis through multiple-passes; it only reuses analysis from the second-to-last pass to the last pass.Disabling reading\n");
3840
0
        p->rc.bStatRead = 0;
3841
0
    }
3842
3843
    /* some options make no sense if others are disabled */
3844
0
    p->bSaoNonDeblocked &= p->bEnableSAO;
3845
0
    p->bEnableTSkipFast &= p->bEnableTransformSkip;
3846
0
    p->bLimitSAO &= p->bEnableSAO;
3847
3848
0
    if (m_param->bUseAnalysisFile && m_param->analysisLoad && (p->confWinRightOffset || p->confWinBottomOffset))
3849
0
        x265_log(p, X265_LOG_WARNING, "It is recommended not to set conformance window offset in file based analysis-load."
3850
0
                                      " Offsets are shared in the analysis file already.\n");
3851
    /* initialize the conformance window */
3852
0
    m_conformanceWindow.bEnabled = false;
3853
0
    m_conformanceWindow.rightOffset = 0;
3854
0
    m_conformanceWindow.topOffset = 0;
3855
0
    m_conformanceWindow.bottomOffset = 0;
3856
0
    m_conformanceWindow.leftOffset = 0;
3857
3858
0
    uint32_t padsize = 0;
3859
0
    if (m_param->analysisLoad && m_param->bUseAnalysisFile)
3860
0
    {
3861
0
        m_analysisFileIn = x265_fopen(m_param->analysisLoad, "rb");
3862
0
        if (!m_analysisFileIn)
3863
0
        {
3864
0
            x265_log_file(NULL, X265_LOG_ERROR, "Analysis load: failed to open file %s\n", m_param->analysisLoad);
3865
0
            m_aborted = true;
3866
0
        }
3867
0
        else
3868
0
        {
3869
0
            int rightOffset, bottomOffset;
3870
0
            if (fread(&rightOffset, sizeof(int), 1, m_analysisFileIn) != 1)
3871
0
            {
3872
0
                x265_log(NULL, X265_LOG_ERROR, "Error reading analysis data. Conformance window right offset missing\n");
3873
0
                m_aborted = true;
3874
0
            }
3875
0
            else if (rightOffset && p->analysisLoadReuseLevel > 1)
3876
0
            {
3877
0
                int scaleFactor = p->scaleFactor < 2 ? 1 : p->scaleFactor;
3878
0
                padsize = rightOffset * scaleFactor;
3879
0
                p->sourceWidth += padsize;
3880
0
                m_conformanceWindow.bEnabled = true;
3881
0
                m_conformanceWindow.rightOffset = padsize;
3882
0
            }
3883
3884
0
            if (fread(&bottomOffset, sizeof(int), 1, m_analysisFileIn) != 1)
3885
0
            {
3886
0
                x265_log(NULL, X265_LOG_ERROR, "Error reading analysis data. Conformance window bottom offset missing\n");
3887
0
                m_aborted = true;
3888
0
            }
3889
0
            else if (bottomOffset && p->analysisLoadReuseLevel > 1)
3890
0
            {
3891
0
                int scaleFactor = p->scaleFactor < 2 ? 1 : p->scaleFactor;
3892
0
                padsize = bottomOffset * scaleFactor;
3893
0
                p->sourceHeight += padsize;
3894
0
                m_conformanceWindow.bEnabled = true;
3895
0
                m_conformanceWindow.bottomOffset = padsize;
3896
0
            }
3897
0
        }
3898
0
    }
3899
3900
    /* set pad size if width is not multiple of the minimum CU size */
3901
0
    if (p->confWinRightOffset)
3902
0
    {
3903
0
        if ((p->sourceWidth + p->confWinRightOffset) & (p->minCUSize - 1))
3904
0
        {
3905
0
            x265_log(p, X265_LOG_ERROR, "Incompatible conformance window right offset."
3906
0
                                          " This when added to the source width should be a multiple of minCUSize\n");
3907
0
            m_aborted = true;
3908
0
        }
3909
0
        else
3910
0
        {
3911
0
            p->sourceWidth += p->confWinRightOffset;
3912
0
            m_conformanceWindow.bEnabled = true;
3913
0
            m_conformanceWindow.rightOffset = p->confWinRightOffset;
3914
0
        }
3915
0
    }
3916
0
    else if (p->sourceWidth & (p->minCUSize - 1))
3917
0
    {
3918
0
        uint32_t rem = p->sourceWidth & (p->minCUSize - 1);
3919
0
        padsize = p->minCUSize - rem;
3920
0
        p->sourceWidth += padsize;
3921
3922
0
        m_conformanceWindow.bEnabled = true;
3923
0
        m_conformanceWindow.rightOffset = padsize;
3924
0
    }
3925
3926
0
    if (p->bEnableRdRefine && (p->rdLevel < 5 || !p->rc.aqMode))
3927
0
    {
3928
0
        p->bEnableRdRefine = false;
3929
0
        x265_log(p, X265_LOG_WARNING, "--rd-refine disabled, requires RD level > 4 and adaptive quant\n");
3930
0
    }
3931
3932
0
    if (p->bOptCUDeltaQP && p->rdLevel < 5)
3933
0
    {
3934
0
        p->bOptCUDeltaQP = false;
3935
0
        x265_log(p, X265_LOG_WARNING, "--opt-cu-delta-qp disabled, requires RD level > 4\n");
3936
0
    }
3937
3938
0
    if (p->limitTU && p->tuQTMaxInterDepth < 2)
3939
0
    {
3940
0
        p->limitTU = 0;
3941
0
        x265_log(p, X265_LOG_WARNING, "limit-tu disabled, requires tu-inter-depth > 1\n");
3942
0
    }
3943
0
    bool bIsVbv = m_param->rc.vbvBufferSize > 0 && m_param->rc.vbvMaxBitrate > 0;
3944
0
    if (!m_param->bLossless && (m_param->rc.aqMode || bIsVbv || m_param->bAQMotion))
3945
0
    {
3946
0
        if (p->rc.qgSize < X265_MAX(8, p->minCUSize))
3947
0
        {
3948
0
            p->rc.qgSize = X265_MAX(8, p->minCUSize);
3949
0
            x265_log(p, X265_LOG_WARNING, "QGSize should be greater than or equal to 8 and minCUSize, setting QGSize = %d\n", p->rc.qgSize);
3950
0
        }
3951
0
        if (p->rc.qgSize > p->maxCUSize)
3952
0
        {
3953
0
            p->rc.qgSize = p->maxCUSize;
3954
0
            x265_log(p, X265_LOG_WARNING, "QGSize should be less than or equal to maxCUSize, setting QGSize = %d\n", p->rc.qgSize);
3955
0
        }
3956
0
    }
3957
0
    else
3958
0
        m_param->rc.qgSize = p->maxCUSize;
3959
3960
0
    if (m_param->dynamicRd && (!bIsVbv || !p->rc.aqMode || p->rdLevel > 4))
3961
0
    {
3962
0
        p->dynamicRd = 0;
3963
0
        x265_log(p, X265_LOG_WARNING, "Dynamic-rd disabled, requires RD <= 4, VBV and aq-mode enabled\n");
3964
0
    }
3965
3966
0
    if (!p->bEnableFrameDuplication && p->dupThreshold && p->dupThreshold != 70)
3967
0
    {
3968
0
        x265_log(p, X265_LOG_WARNING, "Frame-duplication threshold works only with frame-duplication enabled. Enabling frame-duplication.\n");
3969
0
        p->bEnableFrameDuplication = 1;
3970
0
    }
3971
3972
0
    if (p->bEnableFrameDuplication && p->interlaceMode)
3973
0
    {
3974
0
        x265_log(p, X265_LOG_WARNING, "Frame-duplication does not support interlace mode. Disabling Frame Duplication.\n");
3975
0
        p->bEnableFrameDuplication = 0;
3976
0
    }
3977
3978
0
    if (p->bEnableFrameDuplication && p->pictureStructure != 0 && p->pictureStructure != -1)
3979
0
    {
3980
0
        x265_log(p, X265_LOG_WARNING, "Frame-duplication works only with pic_struct = 0. Setting pic-struct = 0.\n");
3981
0
        p->pictureStructure = 0;
3982
0
    }
3983
3984
0
    if (m_param->bEnableFrameDuplication && (!bIsVbv || !m_param->bEmitHRDSEI))
3985
0
    {
3986
0
        x265_log(m_param, X265_LOG_WARNING, "Frame-duplication require NAL HRD and VBV parameters. Disabling frame duplication\n");
3987
0
        m_param->bEnableFrameDuplication = 0;
3988
0
    }
3989
#ifdef ENABLE_HDR10_PLUS
3990
    if (m_param->bDhdr10opt && m_param->toneMapFile == NULL)
3991
    {
3992
        x265_log(p, X265_LOG_WARNING, "Disabling dhdr10-opt. dhdr10-info must be enabled.\n");
3993
        m_param->bDhdr10opt = 0;
3994
    }
3995
3996
    if (m_param->toneMapFile)
3997
    {
3998
        if (!x265_fopen(p->toneMapFile, "r"))
3999
        {
4000
            x265_log(p, X265_LOG_ERROR, "Unable to open tone-map file.\n");
4001
            m_bToneMap = 0;
4002
            m_param->toneMapFile = NULL;
4003
            m_aborted = true;
4004
        }
4005
        else
4006
            m_bToneMap = 1;
4007
    }
4008
    else
4009
        m_bToneMap = 0;
4010
#else
4011
0
    if (m_param->toneMapFile)
4012
0
    {
4013
0
        x265_log(p, X265_LOG_WARNING, "--dhdr10-info disabled. Enable HDR10_PLUS in cmake.\n");
4014
0
        m_bToneMap = 0;
4015
0
        m_param->toneMapFile = NULL;
4016
0
    }
4017
0
    else if (m_param->bDhdr10opt)
4018
0
    {
4019
0
        x265_log(p, X265_LOG_WARNING, "Disabling dhdr10-opt. dhdr10-info must be enabled.\n");
4020
0
        m_param->bDhdr10opt = 0;
4021
0
    }
4022
0
#endif
4023
4024
0
    if (p->uhdBluray)
4025
0
    {
4026
0
        p->bEnableAccessUnitDelimiters = 1;
4027
0
        p->vui.aspectRatioIdc = 1;
4028
0
        p->bEmitHRDSEI = 1;
4029
0
        int disableUhdBd = 0;
4030
4031
0
        if (p->levelIdc && p->levelIdc != 51)
4032
0
        {
4033
0
            x265_log(p, X265_LOG_WARNING, "uhd-bd: Wrong level specified, UHD Bluray mandates Level 5.1\n");
4034
0
        }
4035
0
        p->levelIdc = 51;
4036
4037
0
        if (!p->bHighTier)
4038
0
        {
4039
0
            x265_log(p, X265_LOG_WARNING, "uhd-bd: Turning on high tier\n");
4040
0
            p->bHighTier = 1;
4041
0
        }
4042
4043
0
        if (!p->bRepeatHeaders)
4044
0
        {
4045
0
            x265_log(p, X265_LOG_WARNING, "uhd-bd: Turning on repeat-headers\n");
4046
0
            p->bRepeatHeaders = 1;
4047
0
        }
4048
4049
0
        if (p->bOpenGOP)
4050
0
        {
4051
0
            x265_log(p, X265_LOG_WARNING, "uhd-bd: Turning off open GOP\n");
4052
0
            p->bOpenGOP = false;
4053
0
        }
4054
4055
0
        if (p->bIntraRefresh)
4056
0
        {
4057
0
            x265_log(p, X265_LOG_WARNING, "uhd-bd: turning off intra-refresh\n");
4058
0
            p->bIntraRefresh = 0;
4059
0
        }
4060
4061
0
        if (p->keyframeMin != 1)
4062
0
        {
4063
0
            x265_log(p, X265_LOG_WARNING, "uhd-bd: keyframeMin is always 1\n");
4064
0
            p->keyframeMin = 1;
4065
0
        }
4066
4067
0
        int fps = (p->fpsNum + p->fpsDenom - 1) / p->fpsDenom;
4068
0
        if (p->keyframeMax > fps)
4069
0
        {
4070
0
            x265_log(p, X265_LOG_WARNING, "uhd-bd: reducing keyframeMax to %d\n", fps);
4071
0
            p->keyframeMax = fps;
4072
0
        }
4073
4074
0
        if (p->maxNumReferences > 6)
4075
0
        {
4076
0
            x265_log(p, X265_LOG_WARNING, "uhd-bd: reducing references to 6\n");
4077
0
            p->maxNumReferences = 6;
4078
0
        }
4079
4080
0
        if (p->bEnableTemporalSubLayers)
4081
0
        {
4082
0
            x265_log(p, X265_LOG_WARNING, "uhd-bd: Turning off temporal layering\n");
4083
0
            p->bEnableTemporalSubLayers = 0;
4084
0
        }
4085
4086
0
        if (p->vui.colorPrimaries != 1 && p->vui.colorPrimaries != 9)
4087
0
        {
4088
0
            x265_log(p, X265_LOG_ERROR, "uhd-bd: colour primaries should be either BT.709 or BT.2020\n");
4089
0
            disableUhdBd = 1;
4090
0
        }
4091
0
        else if (p->vui.colorPrimaries == 9)
4092
0
        {
4093
0
            p->vui.bEnableChromaLocInfoPresentFlag = 1;
4094
0
            p->vui.chromaSampleLocTypeTopField = 2;
4095
0
            p->vui.chromaSampleLocTypeBottomField = 2;
4096
0
        }
4097
4098
0
        if (p->vui.transferCharacteristics != 1 && p->vui.transferCharacteristics != 14 && p->vui.transferCharacteristics != 16)
4099
0
        {
4100
0
            x265_log(p, X265_LOG_ERROR, "uhd-bd: transfer characteristics supported are BT.709, BT.2020-10 or SMPTE ST.2084\n");
4101
0
            disableUhdBd = 1;
4102
0
        }
4103
0
        if (p->vui.matrixCoeffs != 1 && p->vui.matrixCoeffs != 9)
4104
0
        {
4105
0
            x265_log(p, X265_LOG_ERROR, "uhd-bd: matrix coeffs supported are either BT.709 or BT.2020\n");
4106
0
            disableUhdBd = 1;
4107
0
        }
4108
0
        if ((p->sourceWidth != 1920 && p->sourceWidth != 3840) || (p->sourceHeight != 1080 && p->sourceHeight != 2160))
4109
0
        {
4110
0
            x265_log(p, X265_LOG_ERROR, "uhd-bd: Supported resolutions are 1920x1080 and 3840x2160\n");
4111
0
            disableUhdBd = 1;
4112
0
        }
4113
0
        if (disableUhdBd)
4114
0
        {
4115
0
            p->uhdBluray = 0;
4116
0
            x265_log(p, X265_LOG_ERROR, "uhd-bd: Disabled\n");
4117
0
        }
4118
0
    }
4119
    /* set pad size if height is not multiple of the minimum CU size */
4120
0
    if (p->confWinBottomOffset)
4121
0
    {
4122
0
        if ((p->sourceHeight + p->confWinBottomOffset) & (p->minCUSize - 1))
4123
0
        {
4124
0
            x265_log(p, X265_LOG_ERROR, "Incompatible conformance window bottom offset."
4125
0
                " This when added to the source height should be a multiple of minCUSize\n");
4126
0
            m_aborted = true;
4127
0
        }
4128
0
        else
4129
0
        {
4130
0
            p->sourceHeight += p->confWinBottomOffset;
4131
0
            m_conformanceWindow.bEnabled = true;
4132
0
            m_conformanceWindow.bottomOffset = p->confWinBottomOffset;
4133
0
        }
4134
0
    }
4135
0
    else if(p->sourceHeight & (p->minCUSize - 1))
4136
0
    {
4137
0
        uint32_t rem = p->sourceHeight & (p->minCUSize - 1);
4138
0
        padsize = p->minCUSize - rem;
4139
0
        p->sourceHeight += padsize;
4140
0
        m_conformanceWindow.bEnabled = true;
4141
0
        m_conformanceWindow.bottomOffset = padsize;
4142
0
    }
4143
4144
0
    if (p->bLogCuStats)
4145
0
        x265_log(p, X265_LOG_WARNING, "--cu-stats option is now deprecated\n");
4146
4147
0
    if (p->log2MaxPocLsb < 4)
4148
0
    {
4149
0
        x265_log(p, X265_LOG_WARNING, "maximum of the picture order count can not be less than 4\n");
4150
0
        p->log2MaxPocLsb = 4;
4151
0
    }
4152
4153
0
    if (p->maxSlices < 1)
4154
0
    {
4155
0
        x265_log(p, X265_LOG_WARNING, "maxSlices can not be less than 1, force set to 1\n");
4156
0
        p->maxSlices = 1;
4157
0
    }
4158
0
    const uint32_t numRows = (p->sourceHeight + p->maxCUSize - 1) / p->maxCUSize;
4159
0
    const uint32_t slicesLimit = X265_MIN(numRows, NALList::MAX_NAL_UNITS - 1);
4160
0
    if (p->maxSlices > slicesLimit)
4161
0
    {
4162
0
        x265_log(p, X265_LOG_WARNING, "maxSlices can not be more than min(rows, MAX_NAL_UNITS-1), force set to %d\n", slicesLimit);
4163
0
        p->maxSlices = slicesLimit;
4164
0
    }
4165
0
    if (p->bHDR10Opt)
4166
0
    {
4167
0
        if (p->internalCsp != X265_CSP_I420 || p->internalBitDepth != 10 || p->vui.colorPrimaries != 9 ||
4168
0
            p->vui.transferCharacteristics != 16 || p->vui.matrixCoeffs != 9)
4169
0
        {
4170
0
            x265_log(p, X265_LOG_ERROR, "Recommended Settings for HDR10-opt: colour primaries should be BT.2020,\n"
4171
0
                                        "                                            transfer characteristics should be SMPTE ST.2084,\n"
4172
0
                                        "                                            matrix coeffs should be BT.2020,\n"
4173
0
                                        "                                            the input video should be 10 bit 4:2:0\n"
4174
0
                                        "                                            Disabling hdr10-opt.\n");
4175
0
            p->bHDR10Opt = 0;
4176
0
        }
4177
0
    }
4178
4179
0
    if (m_param->toneMapFile || p->bHDR10Opt || p->bEmitHDR10SEI)
4180
0
    {
4181
0
        if (!p->bRepeatHeaders)
4182
0
        {
4183
0
            p->bRepeatHeaders = 1;
4184
0
            x265_log(p, X265_LOG_WARNING, "Turning on repeat-headers for HDR compatibility\n");
4185
0
        }
4186
0
    }
4187
4188
0
    p->maxLog2CUSize = g_log2Size[p->maxCUSize];
4189
0
    p->maxCUDepth    = p->maxLog2CUSize - g_log2Size[p->minCUSize];
4190
0
    p->unitSizeDepth = p->maxLog2CUSize - LOG2_UNIT_SIZE;
4191
0
    p->num4x4Partitions = (1U << (p->unitSizeDepth << 1));
4192
4193
0
    if (p->radl && (p->keyframeMax != p->keyframeMin))
4194
0
    {
4195
0
        p->radl = 0;
4196
0
        x265_log(p, X265_LOG_WARNING, "Radl requires fixed gop-length (keyint == min-keyint). Disabling radl.\n");
4197
0
    }
4198
4199
0
    if ((p->chunkStart || p->chunkEnd) && p->bOpenGOP && m_param->bResetZoneConfig)
4200
0
    {
4201
0
        p->chunkStart = p->chunkEnd = 0;
4202
0
        x265_log(p, X265_LOG_WARNING, "Chunking requires closed gop structure. Disabling chunking.\n");
4203
0
    }
4204
4205
0
    if (p->chunkEnd < p->chunkStart)
4206
0
    {
4207
0
        p->chunkStart = p->chunkEnd = 0;
4208
0
        x265_log(p, X265_LOG_WARNING, "chunk-end cannot be less than chunk-start. Disabling chunking.\n");
4209
0
    }
4210
4211
0
    if (p->dolbyProfile)     // Default disabled.
4212
0
        configureDolbyVisionParams(p);
4213
4214
0
    if (p->rc.zonefileCount && p->rc.zoneCount)
4215
0
    {
4216
0
        p->rc.zoneCount = 0;
4217
0
        x265_log(p, X265_LOG_WARNING, "Only zone or zonefile can be used. Enabling only zonefile\n");
4218
0
    }
4219
4220
0
    if (m_param->rc.zonefileCount && p->bOpenGOP)
4221
0
    {
4222
0
        p->bOpenGOP = 0;
4223
0
        x265_log(p, X265_LOG_WARNING, "Zone encoding requires closed gop structure. Enabling closed GOP.\n");
4224
0
    }
4225
4226
0
    if (m_param->rc.zonefileCount && !p->bRepeatHeaders)
4227
0
    {
4228
0
        p->bRepeatHeaders = 1;
4229
0
        x265_log(p, X265_LOG_WARNING, "Turning on repeat - headers for zone encoding\n");
4230
0
    }
4231
4232
0
    if (m_param->bEnableHME)
4233
0
    {
4234
0
        if (m_param->sourceHeight < 540)
4235
0
        {
4236
0
            x265_log(p, X265_LOG_WARNING, "Source height < 540p is too low for HME. Disabling HME.\n");
4237
0
            p->bEnableHME = 0;
4238
0
        }
4239
0
    }
4240
4241
0
    if (m_param->bEnableHME)
4242
0
    {
4243
0
        if (m_param->searchMethod != m_param->hmeSearchMethod[2])
4244
0
            m_param->searchMethod = m_param->hmeSearchMethod[2];
4245
0
        if (m_param->searchRange != m_param->hmeRange[2])
4246
0
            m_param->searchRange = m_param->hmeRange[2];
4247
0
    }
4248
4249
0
   if (p->bHistBasedSceneCut && !p->edgeTransitionThreshold)
4250
0
   {
4251
0
       p->edgeTransitionThreshold = 0.01;
4252
0
       x265_log(p, X265_LOG_WARNING, "using  default threshold %.2lf for scene cut detection\n", p->edgeTransitionThreshold);
4253
0
   }
4254
4255
0
}
4256
4257
void Encoder::readAnalysisFile(x265_analysis_data* analysis, int curPoc, const x265_picture* picIn, int paramBytes)
4258
0
{
4259
0
#define X265_FREAD(val, size, readSize, fileOffset, src)\
4260
0
    if (!m_param->bUseAnalysisFile)\
4261
0
        {\
4262
0
        memcpy(val, src, (size * readSize));\
4263
0
        }\
4264
0
        else if (fread(val, size, readSize, fileOffset) != readSize)\
4265
0
    {\
4266
0
        x265_log(NULL, X265_LOG_ERROR, "Error reading analysis data\n");\
4267
0
        x265_free_analysis_data(m_param, analysis);\
4268
0
        m_aborted = true;\
4269
0
        return;\
4270
0
    }\
4271
0
4272
0
    static uint64_t consumedBytes = 0;
4273
0
    static uint64_t totalConsumedBytes = 0;
4274
0
    uint32_t depthBytes = 0;
4275
0
    if (m_param->bUseAnalysisFile)
4276
0
        fseeko(m_analysisFileIn, totalConsumedBytes + paramBytes, SEEK_SET);
4277
0
    const x265_analysis_data *picData = &(picIn->analysisData);
4278
0
    x265_analysis_intra_data *intraPic = picData->intraData;
4279
0
    x265_analysis_inter_data *interPic = picData->interData;
4280
0
    x265_analysis_distortion_data *picDistortion = picData->distortionData;
4281
4282
0
    int poc; uint32_t frameRecordSize;
4283
0
    X265_FREAD(&frameRecordSize, sizeof(uint32_t), 1, m_analysisFileIn, &(picData->frameRecordSize));
4284
0
    X265_FREAD(&depthBytes, sizeof(uint32_t), 1, m_analysisFileIn, &(picData->depthBytes));
4285
0
    X265_FREAD(&poc, sizeof(int), 1, m_analysisFileIn, &(picData->poc));
4286
4287
0
    if (m_param->bUseAnalysisFile)
4288
0
    {
4289
0
        uint64_t currentOffset = totalConsumedBytes;
4290
4291
        /* Seeking to the right frame Record */
4292
0
        while (poc != curPoc && !feof(m_analysisFileIn))
4293
0
        {
4294
0
            currentOffset += frameRecordSize;
4295
0
            fseeko(m_analysisFileIn, currentOffset + paramBytes, SEEK_SET);
4296
0
            X265_FREAD(&frameRecordSize, sizeof(uint32_t), 1, m_analysisFileIn, &(picData->frameRecordSize));
4297
0
            X265_FREAD(&depthBytes, sizeof(uint32_t), 1, m_analysisFileIn, &(picData->depthBytes));
4298
0
            X265_FREAD(&poc, sizeof(int), 1, m_analysisFileIn, &(picData->poc));
4299
0
        }
4300
0
        if (poc != curPoc || feof(m_analysisFileIn))
4301
0
        {
4302
0
            x265_log(NULL, X265_LOG_WARNING, "Error reading analysis data: Cannot find POC %d\n", curPoc);
4303
0
            x265_free_analysis_data(m_param, analysis);
4304
0
            return;
4305
0
        }
4306
0
    }
4307
4308
0
    uint32_t numCUsLoad, numCUsInHeightLoad;
4309
4310
    /* Now arrived at the right frame, read the record */
4311
0
    analysis->poc = poc;
4312
0
    analysis->frameRecordSize = frameRecordSize;
4313
0
    X265_FREAD(&analysis->sliceType, sizeof(int), 1, m_analysisFileIn, &(picData->sliceType));
4314
0
    X265_FREAD(&analysis->bScenecut, sizeof(int), 1, m_analysisFileIn, &(picData->bScenecut));
4315
0
    X265_FREAD(&analysis->satdCost, sizeof(int64_t), 1, m_analysisFileIn, &(picData->satdCost));
4316
0
    X265_FREAD(&numCUsLoad, sizeof(int), 1, m_analysisFileIn, &(picData->numCUsInFrame));
4317
0
    X265_FREAD(&analysis->numPartitions, sizeof(int), 1, m_analysisFileIn, &(picData->numPartitions));
4318
4319
    /* Update analysis info to save current settings */
4320
0
    uint32_t widthInCU = (m_param->sourceWidth + m_param->maxCUSize - 1) >> m_param->maxLog2CUSize;
4321
0
    uint32_t heightInCU = (m_param->sourceHeight + m_param->maxCUSize - 1) >> m_param->maxLog2CUSize;
4322
0
    uint32_t numCUsInFrame = widthInCU * heightInCU;
4323
0
    analysis->numCUsInFrame = numCUsInFrame;
4324
0
    analysis->numCuInHeight = heightInCU;
4325
4326
0
    if (m_param->bDisableLookahead)
4327
0
    {
4328
0
        X265_FREAD(&numCUsInHeightLoad, sizeof(uint32_t), 1, m_analysisFileIn, &(picData->numCuInHeight));
4329
0
        X265_FREAD(&analysis->lookahead, sizeof(x265_lookahead_data), 1, m_analysisFileIn, &(picData->lookahead));
4330
0
    }
4331
0
    int scaledNumPartition = analysis->numPartitions;
4332
0
    int factor = 1 << m_param->scaleFactor;
4333
4334
0
    if (m_param->scaleFactor)
4335
0
        analysis->numPartitions *= factor;
4336
    /* Memory is allocated for inter and intra analysis data based on the slicetype */
4337
0
    x265_alloc_analysis_data(m_param, analysis);
4338
4339
0
    if (m_param->ctuDistortionRefine == CTU_DISTORTION_INTERNAL)
4340
0
    {
4341
0
        X265_FREAD((analysis->distortionData)->ctuDistortion, sizeof(sse_t), numCUsLoad, m_analysisFileIn, picDistortion);
4342
0
        computeDistortionOffset(analysis);
4343
0
    }
4344
0
    if (m_param->bDisableLookahead && m_rateControl->m_isVbv)
4345
0
    {
4346
0
        size_t vbvCount = m_param->lookaheadDepth + m_param->bframes + 2;
4347
0
        X265_FREAD(analysis->lookahead.intraVbvCost, sizeof(uint32_t), numCUsLoad, m_analysisFileIn, picData->lookahead.intraVbvCost);
4348
0
        X265_FREAD(analysis->lookahead.vbvCost, sizeof(uint32_t), numCUsLoad, m_analysisFileIn, picData->lookahead.vbvCost);
4349
0
        X265_FREAD(analysis->lookahead.satdForVbv, sizeof(uint32_t), numCUsInHeightLoad, m_analysisFileIn, picData->lookahead.satdForVbv);
4350
0
        X265_FREAD(analysis->lookahead.intraSatdForVbv, sizeof(uint32_t), numCUsInHeightLoad, m_analysisFileIn, picData->lookahead.intraSatdForVbv);
4351
0
        X265_FREAD(analysis->lookahead.plannedSatd, sizeof(int64_t), vbvCount, m_analysisFileIn, picData->lookahead.plannedSatd);
4352
4353
0
        if (m_param->scaleFactor)
4354
0
        {
4355
0
            for (uint64_t index = 0; index < vbvCount; index++)
4356
0
                analysis->lookahead.plannedSatd[index] *= factor;
4357
4358
0
            for (uint32_t i = 0; i < numCUsInHeightLoad; i++)
4359
0
            {
4360
0
                analysis->lookahead.satdForVbv[i] *= factor;
4361
0
                analysis->lookahead.intraSatdForVbv[i] *= factor;
4362
0
            }
4363
0
            for (uint32_t i = 0; i < numCUsLoad; i++)
4364
0
            {
4365
0
                analysis->lookahead.vbvCost[i] *= factor;
4366
0
                analysis->lookahead.intraVbvCost[i] *= factor;
4367
0
            }
4368
0
        }
4369
0
    }
4370
0
    if (analysis->sliceType == X265_TYPE_IDR || analysis->sliceType == X265_TYPE_I)
4371
0
    {
4372
0
        if (m_param->bAnalysisType == HEVC_INFO)
4373
0
            return;
4374
0
        if (m_param->analysisLoadReuseLevel < 2)
4375
0
            return;
4376
4377
0
        uint8_t *tempBuf = NULL, *depthBuf = NULL, *modeBuf = NULL, *partSizes = NULL;
4378
0
        int8_t *cuQPBuf = NULL;
4379
4380
0
        tempBuf = X265_MALLOC(uint8_t, depthBytes * 3);
4381
0
        depthBuf = tempBuf;
4382
0
        modeBuf = tempBuf + depthBytes;
4383
0
        partSizes = tempBuf + 2 * depthBytes;
4384
0
        if (m_param->rc.cuTree)
4385
0
            cuQPBuf = X265_MALLOC(int8_t, depthBytes);
4386
4387
0
        X265_FREAD(depthBuf, sizeof(uint8_t), depthBytes, m_analysisFileIn, intraPic->depth);
4388
0
        X265_FREAD(modeBuf, sizeof(uint8_t), depthBytes, m_analysisFileIn, intraPic->chromaModes);
4389
0
        X265_FREAD(partSizes, sizeof(uint8_t), depthBytes, m_analysisFileIn, intraPic->partSizes);
4390
0
        if (m_param->rc.cuTree) { X265_FREAD(cuQPBuf, sizeof(int8_t), depthBytes, m_analysisFileIn, intraPic->cuQPOff); }
4391
4392
0
        size_t count = 0;
4393
0
        for (uint32_t d = 0; d < depthBytes; d++)
4394
0
        {
4395
0
            int bytes = analysis->numPartitions >> (depthBuf[d] * 2);
4396
0
            if (m_param->scaleFactor)
4397
0
            {
4398
0
                if (depthBuf[d] == 0)
4399
0
                    depthBuf[d] = 1;
4400
0
                if (partSizes[d] == SIZE_NxN)
4401
0
                    partSizes[d] = SIZE_2Nx2N;
4402
0
            }
4403
0
            memset(&(analysis->intraData)->depth[count], depthBuf[d], bytes);
4404
0
            memset(&(analysis->intraData)->chromaModes[count], modeBuf[d], bytes);
4405
0
            memset(&(analysis->intraData)->partSizes[count], partSizes[d], bytes);
4406
0
            if (m_param->rc.cuTree)
4407
0
                memset(&(analysis->intraData)->cuQPOff[count], cuQPBuf[d], bytes);
4408
0
            count += bytes;
4409
0
        }
4410
4411
0
        if (!m_param->scaleFactor)
4412
0
        {
4413
0
            X265_FREAD((analysis->intraData)->modes, sizeof(uint8_t), numCUsLoad * analysis->numPartitions, m_analysisFileIn, intraPic->modes);
4414
0
        }
4415
0
        else
4416
0
        {
4417
0
            uint8_t *tempLumaBuf = X265_MALLOC(uint8_t, numCUsLoad * scaledNumPartition);
4418
0
            X265_FREAD(tempLumaBuf, sizeof(uint8_t), numCUsLoad * scaledNumPartition, m_analysisFileIn, intraPic->modes);
4419
0
            for (uint32_t ctu32Idx = 0, cnt = 0; ctu32Idx < numCUsLoad * scaledNumPartition; ctu32Idx++, cnt += factor)
4420
0
                memset(&(analysis->intraData)->modes[cnt], tempLumaBuf[ctu32Idx], factor);
4421
0
            X265_FREE(tempLumaBuf);
4422
0
        }
4423
0
        if (m_param->rc.cuTree)
4424
0
            X265_FREE(cuQPBuf);
4425
0
        X265_FREE(tempBuf);
4426
0
        consumedBytes += frameRecordSize;
4427
0
    }
4428
4429
0
    else
4430
0
    {
4431
0
        uint32_t numDir = analysis->sliceType == X265_TYPE_P ? 1 : 2;
4432
0
        uint32_t numPlanes = m_param->internalCsp == X265_CSP_I400 ? 1 : 3;
4433
0
        X265_FREAD((WeightParam*)analysis->wt, sizeof(WeightParam), numPlanes * numDir, m_analysisFileIn, (picIn->analysisData.wt));
4434
0
        if (m_param->analysisLoadReuseLevel < 2)
4435
0
            return;
4436
4437
0
        uint8_t *tempBuf = NULL, *depthBuf = NULL, *modeBuf = NULL, *partSize = NULL, *mergeFlag = NULL;
4438
0
        uint8_t *interDir = NULL, *chromaDir = NULL, *mvpIdx[2];
4439
0
        MV* mv[2];
4440
0
        int8_t* refIdx[2];
4441
0
        int8_t* cuQPBuf = NULL;
4442
4443
0
        int numBuf = m_param->analysisLoadReuseLevel > 4 ? 4 : 2;
4444
0
        bool bIntraInInter = false;
4445
0
        if (m_param->analysisLoadReuseLevel == 10)
4446
0
        {
4447
0
            numBuf++;
4448
0
            bIntraInInter = (analysis->sliceType == X265_TYPE_P || m_param->bIntraInBFrames);
4449
0
            if (bIntraInInter) numBuf++;
4450
0
        }
4451
0
        if (m_param->bAnalysisType == HEVC_INFO)
4452
0
        {
4453
0
            depthBytes = numCUsLoad * analysis->numPartitions;
4454
0
            memcpy(((x265_analysis_inter_data *)analysis->interData)->depth, interPic->depth, depthBytes);
4455
0
        }
4456
0
        else
4457
0
        {
4458
0
            tempBuf = X265_MALLOC(uint8_t, depthBytes * numBuf);
4459
0
            depthBuf = tempBuf;
4460
0
            modeBuf = tempBuf + depthBytes;
4461
0
            if (m_param->rc.cuTree)
4462
0
                cuQPBuf = X265_MALLOC(int8_t, depthBytes);
4463
4464
0
            X265_FREAD(depthBuf, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->depth);
4465
0
            X265_FREAD(modeBuf, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->modes);
4466
0
            if (m_param->rc.cuTree) { X265_FREAD(cuQPBuf, sizeof(int8_t), depthBytes, m_analysisFileIn, interPic->cuQPOff); }
4467
4468
0
            if (m_param->analysisLoadReuseLevel > 4)
4469
0
            {
4470
0
                partSize = modeBuf + depthBytes;
4471
0
                mergeFlag = partSize + depthBytes;
4472
0
                X265_FREAD(partSize, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->partSize);
4473
0
                X265_FREAD(mergeFlag, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->mergeFlag);
4474
4475
0
                if (m_param->analysisLoadReuseLevel == 10)
4476
0
                {
4477
0
                    interDir = mergeFlag + depthBytes;
4478
0
                    X265_FREAD(interDir, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->interDir);
4479
0
                    if (bIntraInInter)
4480
0
                    {
4481
0
                        chromaDir = interDir + depthBytes;
4482
0
                        X265_FREAD(chromaDir, sizeof(uint8_t), depthBytes, m_analysisFileIn, intraPic->chromaModes);
4483
0
                    }
4484
0
                    for (uint32_t i = 0; i < numDir; i++)
4485
0
                    {
4486
0
                        mvpIdx[i] = X265_MALLOC(uint8_t, depthBytes);
4487
0
                        refIdx[i] = X265_MALLOC(int8_t, depthBytes);
4488
0
                        mv[i] = X265_MALLOC(MV, depthBytes);
4489
0
                        X265_FREAD(mvpIdx[i], sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->mvpIdx[i]);
4490
0
                        X265_FREAD(refIdx[i], sizeof(int8_t), depthBytes, m_analysisFileIn, interPic->refIdx[i]);
4491
0
                        X265_FREAD(mv[i], sizeof(MV), depthBytes, m_analysisFileIn, interPic->mv[i]);
4492
0
                    }
4493
0
                }
4494
0
            }
4495
4496
0
            size_t count = 0;
4497
0
            for (uint32_t d = 0; d < depthBytes; d++)
4498
0
            {
4499
0
                int bytes = analysis->numPartitions >> (depthBuf[d] * 2);
4500
0
                if (m_param->scaleFactor && modeBuf[d] == MODE_INTRA && depthBuf[d] == 0)
4501
0
                    depthBuf[d] = 1;
4502
0
                memset(&(analysis->interData)->depth[count], depthBuf[d], bytes);
4503
0
                memset(&(analysis->interData)->modes[count], modeBuf[d], bytes);
4504
0
                if (m_param->rc.cuTree)
4505
0
                    memset(&(analysis->interData)->cuQPOff[count], cuQPBuf[d], bytes);
4506
0
                if (m_param->analysisLoadReuseLevel > 4)
4507
0
                {
4508
0
                    if (m_param->scaleFactor && modeBuf[d] == MODE_INTRA && partSize[d] == SIZE_NxN)
4509
0
                        partSize[d] = SIZE_2Nx2N;
4510
0
                    memset(&(analysis->interData)->partSize[count], partSize[d], bytes);
4511
0
                    int numPU = (modeBuf[d] == MODE_INTRA) ? 1 : nbPartsTable[(int)partSize[d]];
4512
0
                    for (int pu = 0; pu < numPU; pu++)
4513
0
                    {
4514
0
                        if (pu) d++;
4515
0
                        (analysis->interData)->mergeFlag[count + pu] = mergeFlag[d];
4516
0
                        if (m_param->analysisLoadReuseLevel == 10)
4517
0
                        {
4518
0
                            (analysis->interData)->interDir[count + pu] = interDir[d];
4519
0
                            for (uint32_t i = 0; i < numDir; i++)
4520
0
                            {
4521
0
                                (analysis->interData)->mvpIdx[i][count + pu] = mvpIdx[i][d];
4522
0
                                (analysis->interData)->refIdx[i][count + pu] = refIdx[i][d];
4523
0
                                if (m_param->scaleFactor)
4524
0
                                {
4525
0
                                    mv[i][d].x *= (int32_t)m_param->scaleFactor;
4526
0
                                    mv[i][d].y *= (int32_t)m_param->scaleFactor;
4527
0
                                }
4528
0
                                memcpy(&(analysis->interData)->mv[i][count + pu], &mv[i][d], sizeof(MV));
4529
0
                            }
4530
0
                        }
4531
0
                    }
4532
0
                    if (m_param->analysisLoadReuseLevel == 10 && bIntraInInter)
4533
0
                        memset(&(analysis->intraData)->chromaModes[count], chromaDir[d], bytes);
4534
0
                }
4535
0
                count += bytes;
4536
0
            }
4537
4538
0
            if (m_param->rc.cuTree)
4539
0
                X265_FREE(cuQPBuf);
4540
0
            X265_FREE(tempBuf);
4541
0
        }
4542
0
        if (m_param->analysisLoadReuseLevel == 10)
4543
0
        {
4544
0
            if (m_param->bAnalysisType != HEVC_INFO)
4545
0
            {
4546
0
                for (uint32_t i = 0; i < numDir; i++)
4547
0
                {
4548
0
                    X265_FREE(mvpIdx[i]);
4549
0
                    X265_FREE(refIdx[i]);
4550
0
                    X265_FREE(mv[i]);
4551
0
                }
4552
0
            }
4553
0
            if (bIntraInInter)
4554
0
            {
4555
0
                if (!m_param->scaleFactor)
4556
0
                {
4557
0
                    X265_FREAD((analysis->intraData)->modes, sizeof(uint8_t), numCUsLoad * analysis->numPartitions, m_analysisFileIn, intraPic->modes);
4558
0
                }
4559
0
                else
4560
0
                {
4561
0
                    uint8_t *tempLumaBuf = X265_MALLOC(uint8_t, numCUsLoad * scaledNumPartition);
4562
0
                    X265_FREAD(tempLumaBuf, sizeof(uint8_t), numCUsLoad * scaledNumPartition, m_analysisFileIn, intraPic->modes);
4563
0
                    for (uint32_t ctu32Idx = 0, cnt = 0; ctu32Idx < numCUsLoad * scaledNumPartition; ctu32Idx++, cnt += factor)
4564
0
                        memset(&(analysis->intraData)->modes[cnt], tempLumaBuf[ctu32Idx], factor);
4565
0
                    X265_FREE(tempLumaBuf);
4566
0
                }
4567
0
            }
4568
0
        }
4569
0
        else
4570
0
            X265_FREAD((analysis->interData)->ref, sizeof(int32_t), numCUsLoad * X265_MAX_PRED_MODE_PER_CTU * numDir, m_analysisFileIn, interPic->ref);
4571
4572
0
        consumedBytes += frameRecordSize;
4573
0
        if (numDir == 1)
4574
0
            totalConsumedBytes = consumedBytes;
4575
0
    }
4576
4577
0
#undef X265_FREAD
4578
0
}
4579
4580
void Encoder::readAnalysisFile(x265_analysis_data* analysis, int curPoc, const x265_picture* picIn, int paramBytes, cuLocation cuLoc)
4581
0
{
4582
0
#define X265_FREAD(val, size, readSize, fileOffset, src)\
4583
0
    if (!m_param->bUseAnalysisFile)\
4584
0
    {\
4585
0
        memcpy(val, src, (size * readSize));\
4586
0
    }\
4587
0
    else if (fread(val, size, readSize, fileOffset) != readSize)\
4588
0
    {\
4589
0
        x265_log(NULL, X265_LOG_ERROR, "Error reading analysis data\n");\
4590
0
        x265_free_analysis_data(m_param, analysis);\
4591
0
        m_aborted = true;\
4592
0
        return;\
4593
0
    }\
4594
0
4595
0
    static uint64_t consumedBytes = 0;
4596
0
    static uint64_t totalConsumedBytes = 0;
4597
0
    uint32_t depthBytes = 0;
4598
0
    if (m_param->bUseAnalysisFile)
4599
0
        fseeko(m_analysisFileIn, totalConsumedBytes + paramBytes, SEEK_SET);
4600
4601
0
    const x265_analysis_data *picData = &(picIn->analysisData);
4602
0
    x265_analysis_intra_data *intraPic = picData->intraData;
4603
0
    x265_analysis_inter_data *interPic = picData->interData;
4604
0
    x265_analysis_distortion_data *picDistortion = picData->distortionData;
4605
4606
0
    int poc; uint32_t frameRecordSize;
4607
0
    X265_FREAD(&frameRecordSize, sizeof(uint32_t), 1, m_analysisFileIn, &(picData->frameRecordSize));
4608
0
    X265_FREAD(&depthBytes, sizeof(uint32_t), 1, m_analysisFileIn, &(picData->depthBytes));
4609
0
    X265_FREAD(&poc, sizeof(int), 1, m_analysisFileIn, &(picData->poc));
4610
4611
0
    if (m_param->bUseAnalysisFile)
4612
0
    {
4613
0
        uint64_t currentOffset = totalConsumedBytes;
4614
4615
        /* Seeking to the right frame Record */
4616
0
        while (poc != curPoc && !feof(m_analysisFileIn))
4617
0
        {
4618
0
            currentOffset += frameRecordSize;
4619
0
            fseeko(m_analysisFileIn, currentOffset + paramBytes, SEEK_SET);
4620
0
            X265_FREAD(&frameRecordSize, sizeof(uint32_t), 1, m_analysisFileIn, &(picData->frameRecordSize));
4621
0
            X265_FREAD(&depthBytes, sizeof(uint32_t), 1, m_analysisFileIn, &(picData->depthBytes));
4622
0
            X265_FREAD(&poc, sizeof(int), 1, m_analysisFileIn, &(picData->poc));
4623
0
        }
4624
0
        if (poc != curPoc || feof(m_analysisFileIn))
4625
0
        {
4626
0
            x265_log(NULL, X265_LOG_WARNING, "Error reading analysis data: Cannot find POC %d\n", curPoc);
4627
0
            x265_free_analysis_data(m_param, analysis);
4628
0
            return;
4629
0
        }
4630
0
    }
4631
4632
    /* Now arrived at the right frame, read the record */
4633
0
    analysis->poc = poc;
4634
0
    analysis->frameRecordSize = frameRecordSize;
4635
0
    X265_FREAD(&analysis->sliceType, sizeof(int), 1, m_analysisFileIn, &(picData->sliceType));
4636
0
    X265_FREAD(&analysis->bScenecut, sizeof(int), 1, m_analysisFileIn, &(picData->bScenecut));
4637
0
    X265_FREAD(&analysis->satdCost, sizeof(int64_t), 1, m_analysisFileIn, &(picData->satdCost));
4638
0
    X265_FREAD(&analysis->numCUsInFrame, sizeof(int), 1, m_analysisFileIn, &(picData->numCUsInFrame));
4639
0
    X265_FREAD(&analysis->numPartitions, sizeof(int), 1, m_analysisFileIn, &(picData->numPartitions));
4640
    
4641
0
    if (m_param->bDisableLookahead)
4642
0
    {
4643
0
        X265_FREAD(&analysis->numCuInHeight, sizeof(uint32_t), 1, m_analysisFileIn, &(picData->numCuInHeight));
4644
0
        X265_FREAD(&analysis->lookahead, sizeof(x265_lookahead_data), 1, m_analysisFileIn, &(picData->lookahead));
4645
0
    }
4646
0
    int scaledNumPartition = analysis->numPartitions;
4647
0
    int factor = 1 << m_param->scaleFactor;
4648
4649
0
    int numPartitions = analysis->numPartitions;
4650
0
    int numCUsInFrame = analysis->numCUsInFrame;
4651
0
    int numCuInHeight = analysis->numCuInHeight;
4652
    /* Allocate memory for scaled resoultion's numPartitions and numCUsInFrame*/
4653
0
    analysis->numPartitions = m_param->num4x4Partitions;
4654
0
    analysis->numCUsInFrame = cuLoc.heightInCU * cuLoc.widthInCU;
4655
0
    analysis->numCuInHeight = cuLoc.heightInCU;
4656
4657
    /* Memory is allocated for inter and intra analysis data based on the slicetype */
4658
0
    x265_alloc_analysis_data(m_param, analysis);
4659
4660
0
    if (m_param->ctuDistortionRefine == CTU_DISTORTION_INTERNAL)
4661
0
    {
4662
0
        X265_FREAD((analysis->distortionData)->ctuDistortion, sizeof(sse_t), analysis->numCUsInFrame, m_analysisFileIn, picDistortion);
4663
0
        computeDistortionOffset(analysis);
4664
0
    }
4665
4666
0
    analysis->numPartitions = numPartitions * factor;
4667
0
    analysis->numCUsInFrame = numCUsInFrame;
4668
0
    analysis->numCuInHeight = numCuInHeight;
4669
0
    if (m_param->bDisableLookahead && m_rateControl->m_isVbv)
4670
0
    {
4671
0
        uint32_t width = analysis->numCUsInFrame / analysis->numCuInHeight;
4672
0
        bool skipLastRow = (analysis->numCuInHeight * 2) > cuLoc.heightInCU;
4673
0
        bool skipLastCol = (width * 2) > cuLoc.widthInCU;
4674
0
        uint32_t *intraVbvCostBuf = NULL, *vbvCostBuf = NULL, *satdForVbvBuf = NULL, *intraSatdForVbvBuf = NULL;
4675
0
        intraVbvCostBuf = X265_MALLOC(uint32_t, analysis->numCUsInFrame);
4676
0
        vbvCostBuf = X265_MALLOC(uint32_t, analysis->numCUsInFrame);
4677
0
        satdForVbvBuf = X265_MALLOC(uint32_t, analysis->numCuInHeight);
4678
0
        intraSatdForVbvBuf = X265_MALLOC(uint32_t, analysis->numCuInHeight);
4679
4680
0
        X265_FREAD(intraVbvCostBuf, sizeof(uint32_t), analysis->numCUsInFrame, m_analysisFileIn, picData->lookahead.intraVbvCost);
4681
0
        X265_FREAD(vbvCostBuf, sizeof(uint32_t), analysis->numCUsInFrame, m_analysisFileIn, picData->lookahead.vbvCost);
4682
0
        X265_FREAD(satdForVbvBuf, sizeof(uint32_t), analysis->numCuInHeight, m_analysisFileIn, picData->lookahead.satdForVbv);
4683
0
        X265_FREAD(intraSatdForVbvBuf, sizeof(uint32_t), analysis->numCuInHeight, m_analysisFileIn, picData->lookahead.intraSatdForVbv);
4684
4685
0
        int k = 0;
4686
0
        for (uint32_t i = 0; i < analysis->numCuInHeight; i++)
4687
0
        {
4688
0
            analysis->lookahead.satdForVbv[m_param->scaleFactor * i] = satdForVbvBuf[i] * m_param->scaleFactor;
4689
0
            analysis->lookahead.intraSatdForVbv[m_param->scaleFactor * i] = intraSatdForVbvBuf[i] * m_param->scaleFactor;
4690
0
            if (!(i == (analysis->numCuInHeight - 1) && skipLastRow))
4691
0
            {
4692
0
                analysis->lookahead.satdForVbv[(m_param->scaleFactor * i) + 1] = satdForVbvBuf[i] * m_param->scaleFactor;
4693
0
                analysis->lookahead.intraSatdForVbv[(m_param->scaleFactor * i) + 1] = intraSatdForVbvBuf[i] * m_param->scaleFactor;
4694
0
            }
4695
4696
0
            for (uint32_t j = 0; j < width; j++, k++)
4697
0
            {
4698
0
                analysis->lookahead.vbvCost[(i * m_param->scaleFactor * cuLoc.widthInCU) + (j * m_param->scaleFactor)] = vbvCostBuf[k];
4699
0
                analysis->lookahead.intraVbvCost[(i * m_param->scaleFactor * cuLoc.widthInCU) + (j * m_param->scaleFactor)] = intraVbvCostBuf[k];
4700
4701
0
                if (!(j == (width - 1) && skipLastCol))
4702
0
                {
4703
0
                    analysis->lookahead.vbvCost[(i * m_param->scaleFactor * cuLoc.widthInCU) + (j * m_param->scaleFactor) + 1] = vbvCostBuf[k];
4704
0
                    analysis->lookahead.intraVbvCost[(i * m_param->scaleFactor * cuLoc.widthInCU) + (j * m_param->scaleFactor) + 1] = intraVbvCostBuf[k];
4705
0
                }
4706
0
                if (!(i == (analysis->numCuInHeight - 1) && skipLastRow))
4707
0
                {
4708
0
                    analysis->lookahead.vbvCost[(i * m_param->scaleFactor * cuLoc.widthInCU) + cuLoc.widthInCU + (j * m_param->scaleFactor)] = vbvCostBuf[k];
4709
0
                    analysis->lookahead.intraVbvCost[(i * m_param->scaleFactor * cuLoc.widthInCU) + cuLoc.widthInCU + (j * m_param->scaleFactor)] = intraVbvCostBuf[k];
4710
0
                    if (!(j == (width - 1) && skipLastCol))
4711
0
                    {
4712
0
                        analysis->lookahead.vbvCost[(i * m_param->scaleFactor * cuLoc.widthInCU) + cuLoc.widthInCU + (j * m_param->scaleFactor) + 1] = vbvCostBuf[k];
4713
0
                        analysis->lookahead.intraVbvCost[(i * m_param->scaleFactor * cuLoc.widthInCU) + cuLoc.widthInCU + (j * m_param->scaleFactor) + 1] = intraVbvCostBuf[k];
4714
0
                    }
4715
0
                }
4716
0
            }
4717
0
        }
4718
0
        X265_FREE(satdForVbvBuf);
4719
0
        X265_FREE(intraSatdForVbvBuf);
4720
0
        X265_FREE(intraVbvCostBuf);
4721
0
        X265_FREE(vbvCostBuf);
4722
0
    }
4723
4724
0
    if (analysis->sliceType == X265_TYPE_IDR || analysis->sliceType == X265_TYPE_I)
4725
0
    {
4726
0
        if (m_param->analysisLoadReuseLevel < 2)
4727
0
            return;
4728
4729
0
        uint8_t *tempBuf = NULL, *depthBuf = NULL, *modeBuf = NULL, *partSizes = NULL;
4730
0
        int8_t *cuQPBuf = NULL;
4731
4732
0
        tempBuf = X265_MALLOC(uint8_t, depthBytes * 3);
4733
0
        depthBuf = tempBuf;
4734
0
        modeBuf = tempBuf + depthBytes;
4735
0
        partSizes = tempBuf + 2 * depthBytes;
4736
0
        if (m_param->rc.cuTree)
4737
0
            cuQPBuf = X265_MALLOC(int8_t, depthBytes);
4738
4739
0
        X265_FREAD(depthBuf, sizeof(uint8_t), depthBytes, m_analysisFileIn, intraPic->depth);
4740
0
        X265_FREAD(modeBuf, sizeof(uint8_t), depthBytes, m_analysisFileIn, intraPic->chromaModes);
4741
0
        X265_FREAD(partSizes, sizeof(uint8_t), depthBytes, m_analysisFileIn, intraPic->partSizes);
4742
0
        if (m_param->rc.cuTree) { X265_FREAD(cuQPBuf, sizeof(int8_t), depthBytes, m_analysisFileIn, intraPic->cuQPOff); }
4743
4744
0
        uint32_t count = 0;
4745
0
        for (uint32_t d = 0; d < depthBytes; d++)
4746
0
        {
4747
0
            int bytes = analysis->numPartitions >> (depthBuf[d] * 2);
4748
0
            int numCTUCopied = 1;
4749
0
            if (!depthBuf[d]) //copy data of one 64x64 to four scaled 64x64 CTUs.
4750
0
            {
4751
0
                bytes /= 4;
4752
0
                numCTUCopied = 4;
4753
0
            }
4754
0
            if (partSizes[d] == SIZE_NxN)
4755
0
                partSizes[d] = SIZE_2Nx2N;
4756
0
            if ((depthBuf[d] > 1 && m_param->maxCUSize == 64) || (depthBuf[d] && m_param->maxCUSize != 64))
4757
0
                depthBuf[d]--;
4758
4759
0
            for (int numCTU = 0; numCTU < numCTUCopied; numCTU++)
4760
0
            {
4761
0
                memset(&(analysis->intraData)->depth[count], depthBuf[d], bytes);
4762
0
                memset(&(analysis->intraData)->chromaModes[count], modeBuf[d], bytes);
4763
0
                memset(&(analysis->intraData)->partSizes[count], partSizes[d], bytes);
4764
0
                if (m_param->rc.cuTree)
4765
0
                    memset(&(analysis->intraData)->cuQPOff[count], cuQPBuf[d], bytes);
4766
0
                count += bytes;
4767
0
                d += getCUIndex(&cuLoc, &count, bytes, 1);
4768
0
            }
4769
0
        }
4770
4771
0
        cuLoc.evenRowIndex = 0;
4772
0
        cuLoc.oddRowIndex = m_param->num4x4Partitions * cuLoc.widthInCU;
4773
0
        cuLoc.switchCondition = 0;
4774
0
        uint8_t *tempLumaBuf = X265_MALLOC(uint8_t, analysis->numCUsInFrame * scaledNumPartition);
4775
0
        X265_FREAD(tempLumaBuf, sizeof(uint8_t), analysis->numCUsInFrame * scaledNumPartition, m_analysisFileIn, intraPic->modes);
4776
0
        uint32_t cnt = 0;
4777
0
        for (uint32_t ctu32Idx = 0; ctu32Idx < analysis->numCUsInFrame * scaledNumPartition; ctu32Idx++)
4778
0
        {
4779
0
            memset(&(analysis->intraData)->modes[cnt], tempLumaBuf[ctu32Idx], factor);
4780
0
            cnt += factor;
4781
0
            ctu32Idx += getCUIndex(&cuLoc, &cnt, factor, 0);
4782
0
        }
4783
0
        X265_FREE(tempLumaBuf);
4784
0
        if (m_param->rc.cuTree)
4785
0
            X265_FREE(cuQPBuf);
4786
0
        X265_FREE(tempBuf);
4787
0
        consumedBytes += frameRecordSize;
4788
0
    }
4789
4790
0
    else
4791
0
    {
4792
0
        uint32_t numDir = analysis->sliceType == X265_TYPE_P ? 1 : 2;
4793
0
        uint32_t numPlanes = m_param->internalCsp == X265_CSP_I400 ? 1 : 3;
4794
0
        X265_FREAD((WeightParam*)analysis->wt, sizeof(WeightParam), numPlanes * numDir, m_analysisFileIn, (picIn->analysisData.wt));
4795
0
        if (m_param->analysisLoadReuseLevel < 2)
4796
0
            return;
4797
4798
0
        uint8_t *tempBuf = NULL, *depthBuf = NULL, *modeBuf = NULL, *partSize = NULL, *mergeFlag = NULL;
4799
0
        uint8_t *interDir = NULL, *chromaDir = NULL, *mvpIdx[2];
4800
0
        MV* mv[2];
4801
0
        int8_t* refIdx[2];
4802
0
        int8_t* cuQPBuf = NULL;
4803
4804
0
        int numBuf = m_param->analysisLoadReuseLevel > 4 ? 4 : 2;
4805
0
        bool bIntraInInter = false;
4806
0
        if (m_param->analysisLoadReuseLevel == 10)
4807
0
        {
4808
0
            numBuf++;
4809
0
            bIntraInInter = (analysis->sliceType == X265_TYPE_P || m_param->bIntraInBFrames);
4810
0
            if (bIntraInInter) numBuf++;
4811
0
        }
4812
4813
0
        tempBuf = X265_MALLOC(uint8_t, depthBytes * numBuf);
4814
0
        depthBuf = tempBuf;
4815
0
        modeBuf = tempBuf + depthBytes;
4816
0
        if (m_param->rc.cuTree)
4817
0
            cuQPBuf = X265_MALLOC(int8_t, depthBytes);
4818
4819
0
        X265_FREAD(depthBuf, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->depth);
4820
0
        X265_FREAD(modeBuf, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->modes);
4821
0
        if (m_param->rc.cuTree) { X265_FREAD(cuQPBuf, sizeof(int8_t), depthBytes, m_analysisFileIn, interPic->cuQPOff); }
4822
0
        if (m_param->analysisLoadReuseLevel > 4)
4823
0
        {
4824
0
            partSize = modeBuf + depthBytes;
4825
0
            mergeFlag = partSize + depthBytes;
4826
0
            X265_FREAD(partSize, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->partSize);
4827
0
            X265_FREAD(mergeFlag, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->mergeFlag);
4828
0
            if (m_param->analysisLoadReuseLevel == 10)
4829
0
            {
4830
0
                interDir = mergeFlag + depthBytes;
4831
0
                X265_FREAD(interDir, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->interDir);
4832
0
                if (bIntraInInter)
4833
0
                {
4834
0
                    chromaDir = interDir + depthBytes;
4835
0
                    X265_FREAD(chromaDir, sizeof(uint8_t), depthBytes, m_analysisFileIn, intraPic->chromaModes);
4836
0
                }
4837
0
                for (uint32_t i = 0; i < numDir; i++)
4838
0
                {
4839
0
                    mvpIdx[i] = X265_MALLOC(uint8_t, depthBytes);
4840
0
                    refIdx[i] = X265_MALLOC(int8_t, depthBytes);
4841
0
                    mv[i] = X265_MALLOC(MV, depthBytes);
4842
0
                    X265_FREAD(mvpIdx[i], sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->mvpIdx[i]);
4843
0
                    X265_FREAD(refIdx[i], sizeof(int8_t), depthBytes, m_analysisFileIn, interPic->refIdx[i]);
4844
0
                    X265_FREAD(mv[i], sizeof(MV), depthBytes, m_analysisFileIn, interPic->mv[i]);
4845
0
                }
4846
0
            }
4847
0
        }
4848
4849
0
        uint32_t count = 0;
4850
0
        cuLoc.switchCondition = 0;
4851
0
        for (uint32_t d = 0; d < depthBytes; d++)
4852
0
        {
4853
0
            int bytes = analysis->numPartitions >> (depthBuf[d] * 2);
4854
0
            bool isScaledMaxCUSize = false;
4855
0
            int numCTUCopied = 1;
4856
0
            int writeDepth = depthBuf[d];
4857
0
            if (!depthBuf[d]) //copy data of one 64x64 to four scaled 64x64 CTUs.
4858
0
            {
4859
0
                isScaledMaxCUSize = true;
4860
0
                bytes /= 4;
4861
0
                numCTUCopied = 4;
4862
0
            }
4863
0
            if ((modeBuf[d] != MODE_INTRA && depthBuf[d] != 0) || (modeBuf[d] == MODE_INTRA && depthBuf[d] > 1))
4864
0
                writeDepth--;
4865
4866
0
            for (int numCTU = 0; numCTU < numCTUCopied; numCTU++)
4867
0
            {
4868
0
                memset(&(analysis->interData)->depth[count], writeDepth, bytes);
4869
0
                memset(&(analysis->interData)->modes[count], modeBuf[d], bytes);
4870
0
                if (m_param->rc.cuTree)
4871
0
                    memset(&(analysis->interData)->cuQPOff[count], cuQPBuf[d], bytes);
4872
0
                if (m_param->analysisLoadReuseLevel == 10 && bIntraInInter)
4873
0
                    memset(&(analysis->intraData)->chromaModes[count], chromaDir[d], bytes);
4874
4875
0
                if (m_param->analysisLoadReuseLevel > 4)
4876
0
                {
4877
0
                    puOrientation puOrient;
4878
0
                    puOrient.init();
4879
0
                    if (modeBuf[d] == MODE_INTRA && partSize[d] == SIZE_NxN)
4880
0
                        partSize[d] = SIZE_2Nx2N;
4881
0
                    int partitionSize = partSize[d];
4882
0
                    if (isScaledMaxCUSize && partSize[d] != SIZE_2Nx2N)
4883
0
                        partitionSize = getPuShape(&puOrient, partSize[d], numCTU);
4884
0
                    memset(&(analysis->interData)->partSize[count], partitionSize, bytes);
4885
0
                    int numPU = (modeBuf[d] == MODE_INTRA) ? 1 : nbPartsTable[(int)partSize[d]];
4886
0
                    for (int pu = 0; pu < numPU; pu++)
4887
0
                    {
4888
0
                        if (!isScaledMaxCUSize && pu)
4889
0
                            d++;
4890
0
                        int restoreD = d;
4891
                        /* Adjust d value when the current CTU takes data from 2nd PU */
4892
0
                        if (puOrient.isRect || (puOrient.isAmp && partitionSize == SIZE_2Nx2N))
4893
0
                        {
4894
0
                            if ((numCTU > 1 && !puOrient.isVert) || ((numCTU % 2 == 1) && puOrient.isVert))
4895
0
                                d++;
4896
0
                        }
4897
0
                        if (puOrient.isAmp && pu)
4898
0
                            d++;
4899
4900
0
                        (analysis->interData)->mergeFlag[count + pu] = mergeFlag[d];
4901
0
                        if (m_param->analysisLoadReuseLevel == 10)
4902
0
                        {
4903
0
                            (analysis->interData)->interDir[count + pu] = interDir[d];
4904
0
                            MV mvCopy[2];
4905
0
                            for (uint32_t i = 0; i < numDir; i++)
4906
0
                            {
4907
0
                                (analysis->interData)->mvpIdx[i][count + pu] = mvpIdx[i][d];
4908
0
                                (analysis->interData)->refIdx[i][count + pu] = refIdx[i][d];
4909
0
                                mvCopy[i].x = mv[i][d].x * (int32_t)m_param->scaleFactor;
4910
0
                                mvCopy[i].y = mv[i][d].y * (int32_t)m_param->scaleFactor;
4911
0
                                memcpy(&(analysis->interData)->mv[i][count + pu], &mvCopy[i], sizeof(MV));
4912
0
                            }
4913
0
                        }
4914
0
                        d = restoreD; // Restore d value after copying each of the 4 64x64 CTUs
4915
4916
0
                        if (isScaledMaxCUSize && (puOrient.isRect || puOrient.isAmp))
4917
0
                        {
4918
                            /* Skip PU index when current CTU is a 2Nx2N */
4919
0
                            if (partitionSize == SIZE_2Nx2N)
4920
0
                                pu++;
4921
                            /* Adjust d after completion of all 4 CTU copies */
4922
0
                            if (numCTU == 3 && (pu == (numPU - 1)))
4923
0
                                d++;
4924
0
                        }
4925
0
                    }
4926
0
                }
4927
0
                count += bytes;
4928
0
                d += getCUIndex(&cuLoc, &count, bytes, 1);
4929
0
            }
4930
0
        }
4931
4932
0
        if (m_param->rc.cuTree)
4933
0
            X265_FREE(cuQPBuf);
4934
0
        X265_FREE(tempBuf);
4935
4936
0
        if (m_param->analysisLoadReuseLevel == 10)
4937
0
        {
4938
0
            for (uint32_t i = 0; i < numDir; i++)
4939
0
            {
4940
0
                X265_FREE(mvpIdx[i]);
4941
0
                X265_FREE(refIdx[i]);
4942
0
                X265_FREE(mv[i]);
4943
0
            }
4944
0
            if (bIntraInInter)
4945
0
            {
4946
0
                cuLoc.evenRowIndex = 0;
4947
0
                cuLoc.oddRowIndex = m_param->num4x4Partitions * cuLoc.widthInCU;
4948
0
                cuLoc.switchCondition = 0;
4949
0
                uint8_t *tempLumaBuf = X265_MALLOC(uint8_t, analysis->numCUsInFrame * scaledNumPartition);
4950
0
                X265_FREAD(tempLumaBuf, sizeof(uint8_t), analysis->numCUsInFrame * scaledNumPartition, m_analysisFileIn, intraPic->modes);
4951
0
                uint32_t cnt = 0;
4952
0
                for (uint32_t ctu32Idx = 0; ctu32Idx < analysis->numCUsInFrame * scaledNumPartition; ctu32Idx++)
4953
0
                {
4954
0
                    memset(&(analysis->intraData)->modes[cnt], tempLumaBuf[ctu32Idx], factor);
4955
0
                    cnt += factor;
4956
0
                    ctu32Idx += getCUIndex(&cuLoc, &cnt, factor, 0);
4957
0
                }
4958
0
                X265_FREE(tempLumaBuf);
4959
0
            }
4960
0
        }
4961
0
        else
4962
0
            X265_FREAD((analysis->interData)->ref, sizeof(int32_t), analysis->numCUsInFrame * X265_MAX_PRED_MODE_PER_CTU * numDir, m_analysisFileIn, interPic->ref);
4963
4964
0
        consumedBytes += frameRecordSize;
4965
0
        if (numDir == 1)
4966
0
            totalConsumedBytes = consumedBytes;
4967
0
    }
4968
4969
    /* Restore to the current encode's numPartitions and numCUsInFrame */
4970
0
    analysis->numPartitions = m_param->num4x4Partitions;
4971
0
    analysis->numCUsInFrame = cuLoc.heightInCU * cuLoc.widthInCU;
4972
0
    analysis->numCuInHeight = cuLoc.heightInCU;
4973
0
#undef X265_FREAD
4974
0
}
4975
4976
4977
int Encoder::validateAnalysisData(x265_analysis_validate* saveParam, int writeFlag)
4978
0
{
4979
0
#define X265_PARAM_VALIDATE(analysisParam, size, bytes, param, errorMsg)\
4980
0
    if(!writeFlag)\
4981
0
    {\
4982
0
        fileOffset = m_analysisFileIn;\
4983
0
        if ((!m_param->bUseAnalysisFile && analysisParam != (int)*param) || \
4984
0
            (m_param->bUseAnalysisFile && (fread(&readValue, size, bytes, fileOffset) != bytes || (readValue != (int)*param))))\
4985
0
        {\
4986
0
            x265_log(NULL, X265_LOG_ERROR, "Error reading analysis data. Incompatible option : <%s> \n", #errorMsg);\
4987
0
            m_aborted = true;\
4988
0
            return -1;\
4989
0
        }\
4990
0
    }\
4991
0
    if(writeFlag)\
4992
0
    {\
4993
0
        fileOffset = m_analysisFileOut;\
4994
0
        if(!m_param->bUseAnalysisFile)\
4995
0
            analysisParam = *param;\
4996
0
        else if(fwrite(param, size, bytes, fileOffset) < bytes)\
4997
0
        {\
4998
0
            x265_log(NULL, X265_LOG_ERROR, "Error writing analysis data\n"); \
4999
0
            m_aborted = true;\
5000
0
            return -1; \
5001
0
        }\
5002
0
    }\
5003
0
    count++;
5004
5005
0
#define X265_FREAD(val, size, readSize, fileOffset, src)\
5006
0
    if (!m_param->bUseAnalysisFile)\
5007
0
    {\
5008
0
        memcpy(val, src, (size * readSize));\
5009
0
    }\
5010
0
    else if (fread(val, size, readSize, fileOffset) != readSize)\
5011
0
    {\
5012
0
        x265_log(NULL, X265_LOG_ERROR, "Error reading analysis data\n");\
5013
0
        m_aborted = true;\
5014
0
        return -1;\
5015
0
    }\
5016
0
    count++;
5017
5018
0
    FILE*     fileOffset = NULL;
5019
0
    int       readValue = 0;
5020
0
    int       count = 0;
5021
5022
0
    if (m_param->bUseAnalysisFile && writeFlag)
5023
0
    {
5024
0
        X265_PARAM_VALIDATE(saveParam->rightOffset, sizeof(int), 1, &m_conformanceWindow.rightOffset, right-offset);
5025
0
        X265_PARAM_VALIDATE(saveParam->bottomOffset, sizeof(int), 1, &m_conformanceWindow.bottomOffset, bottom-offset);
5026
0
    }
5027
5028
0
    X265_PARAM_VALIDATE(saveParam->intraRefresh, sizeof(int), 1, &m_param->bIntraRefresh, intra-refresh);
5029
0
    X265_PARAM_VALIDATE(saveParam->maxNumReferences, sizeof(int), 1, &m_param->maxNumReferences, ref);
5030
0
    X265_PARAM_VALIDATE(saveParam->keyframeMax, sizeof(int), 1, &m_param->keyframeMax, keyint);
5031
0
    X265_PARAM_VALIDATE(saveParam->keyframeMin, sizeof(int), 1, &m_param->keyframeMin, min-keyint);
5032
0
    X265_PARAM_VALIDATE(saveParam->openGOP, sizeof(int), 1, &m_param->bOpenGOP, open-gop);
5033
0
    X265_PARAM_VALIDATE(saveParam->bframes, sizeof(int), 1, &m_param->bframes, bframes);
5034
0
    X265_PARAM_VALIDATE(saveParam->bPyramid, sizeof(int), 1, &m_param->bBPyramid, bPyramid);
5035
0
    X265_PARAM_VALIDATE(saveParam->minCUSize, sizeof(int), 1, &m_param->minCUSize, min - cu - size);
5036
0
    X265_PARAM_VALIDATE(saveParam->lookaheadDepth, sizeof(int), 1, &m_param->lookaheadDepth, rc - lookahead);
5037
0
    X265_PARAM_VALIDATE(saveParam->chunkStart, sizeof(int), 1, &m_param->chunkStart, chunk-start);
5038
0
    X265_PARAM_VALIDATE(saveParam->chunkEnd, sizeof(int), 1, &m_param->chunkEnd, chunk-end);
5039
0
    X265_PARAM_VALIDATE(saveParam->ctuDistortionRefine, sizeof(int), 1, &m_param->ctuDistortionRefine, ctu - distortion);
5040
0
    X265_PARAM_VALIDATE(saveParam->frameDuplication, sizeof(int), 1, &m_param->bEnableFrameDuplication, frame - dup);
5041
5042
0
    int sourceHeight, sourceWidth;
5043
0
    if (writeFlag)
5044
0
    {
5045
0
        X265_PARAM_VALIDATE(saveParam->analysisReuseLevel, sizeof(int), 1, &m_param->analysisSaveReuseLevel, analysis - save - reuse - level);
5046
0
        X265_PARAM_VALIDATE(saveParam->cuTree, sizeof(int), 1, &m_param->rc.cuTree, cutree-offset);
5047
0
        sourceHeight = m_param->sourceHeight - m_conformanceWindow.bottomOffset;
5048
0
        sourceWidth = m_param->sourceWidth - m_conformanceWindow.rightOffset;
5049
0
        X265_PARAM_VALIDATE(saveParam->sourceWidth, sizeof(int), 1, &sourceWidth, res-width);
5050
0
        X265_PARAM_VALIDATE(saveParam->sourceHeight, sizeof(int), 1, &sourceHeight, res-height);
5051
0
        X265_PARAM_VALIDATE(saveParam->maxCUSize, sizeof(int), 1, &m_param->maxCUSize, ctu);
5052
0
    }
5053
0
    else
5054
0
    {
5055
0
        fileOffset = m_analysisFileIn;
5056
5057
0
        int saveLevel = 0;
5058
0
        bool isIncompatibleReuseLevel = false;
5059
0
        int loadLevel = m_param->analysisLoadReuseLevel;
5060
5061
0
        X265_FREAD(&saveLevel, sizeof(int), 1, m_analysisFileIn, &(saveParam->analysisReuseLevel));
5062
        
5063
0
        if (loadLevel == 10 && saveLevel != 10)
5064
0
            isIncompatibleReuseLevel = true;
5065
0
        else if (((loadLevel >= 7) && (loadLevel <= 9)) && ((saveLevel < 7) || (saveLevel > 9)))
5066
0
            isIncompatibleReuseLevel = true;
5067
0
        else if ((loadLevel == 5 || loadLevel == 6) && ((saveLevel != 5) && (saveLevel != 6)))
5068
0
            isIncompatibleReuseLevel = true;
5069
0
        else if ((loadLevel >= 2 && loadLevel <= 4) && (saveLevel < 2 || saveLevel > 6))
5070
0
            isIncompatibleReuseLevel = true;
5071
0
        else if (!saveLevel)
5072
0
            isIncompatibleReuseLevel = true;
5073
5074
0
        if (isIncompatibleReuseLevel)
5075
0
        {
5076
0
            x265_log(NULL, X265_LOG_ERROR, "Error reading analysis data. Incompatible reuse-levels.\n");
5077
0
            m_aborted = true;
5078
0
            return -1;
5079
0
        }
5080
5081
0
        int bcutree;
5082
0
        X265_FREAD(&bcutree, sizeof(int), 1, m_analysisFileIn, &(saveParam->cuTree));
5083
0
        if (loadLevel == 10 && m_param->rc.cuTree && (!bcutree || saveLevel < 2))
5084
0
        {
5085
0
            x265_log(NULL, X265_LOG_ERROR, "Error reading cu-tree info. Disabling cutree offsets. \n");
5086
0
            m_param->rc.cuTree = 0;
5087
0
            return -1;
5088
0
        }
5089
5090
0
        bool error = false;
5091
0
        int curSourceHeight = m_param->sourceHeight - m_conformanceWindow.bottomOffset;
5092
0
        int curSourceWidth = m_param->sourceWidth - m_conformanceWindow.rightOffset;
5093
      
5094
0
        X265_FREAD(&sourceWidth, sizeof(int), 1, m_analysisFileIn, &(saveParam->sourceWidth));
5095
0
        X265_FREAD(&sourceHeight, sizeof(int), 1, m_analysisFileIn, &(saveParam->sourceHeight));
5096
0
        X265_FREAD(&readValue, sizeof(int), 1, m_analysisFileIn, &(saveParam->maxCUSize));
5097
5098
0
        bool isScaledRes = (2 * sourceHeight == curSourceHeight) && (2 * sourceWidth == curSourceWidth);
5099
0
        if (!isScaledRes && (m_param->analysisLoadReuseLevel > 1) && (sourceHeight != curSourceHeight
5100
0
            || sourceWidth != curSourceWidth || readValue != (int)m_param->maxCUSize || m_param->scaleFactor))
5101
0
            error = true;
5102
0
        else if (isScaledRes && !m_param->scaleFactor)
5103
0
            error = true;
5104
0
        else if (isScaledRes && (int)m_param->maxCUSize == readValue)
5105
0
            m_saveCTUSize = 1;
5106
0
        else if (isScaledRes && (g_log2Size[m_param->maxCUSize] - g_log2Size[readValue]) != 1)
5107
0
            error = true;
5108
5109
0
        if (error)
5110
0
        {
5111
0
            x265_log(NULL, X265_LOG_ERROR, "Error reading analysis data. Incompatible option : <input-res / scale-factor / ctu> \n");
5112
0
            m_aborted = true;
5113
0
            return -1;
5114
0
        }
5115
0
    }
5116
0
    return (count * sizeof(int));
5117
5118
0
#undef X265_FREAD
5119
0
#undef X265_PARAM_VALIDATE
5120
0
}
5121
5122
/* Toggle between two consecutive CTU rows. The save's CTU is copied
5123
twice consecutively in the first and second CTU row of load*/
5124
5125
int Encoder::getCUIndex(cuLocation* cuLoc, uint32_t* count, int bytes, int flag)
5126
0
{
5127
0
    int index = 0;
5128
0
    cuLoc->switchCondition += bytes;
5129
0
    int isBoundaryW = (*count % (m_param->num4x4Partitions * cuLoc->widthInCU) == 0);
5130
5131
    /* Width boundary case :
5132
    Skip to appropriate index when out of boundary cases occur
5133
    Out of boundary may occur when the out of bound pixels along
5134
    the width in low resoultion is greater than half of the maxCUSize */
5135
0
    if (cuLoc->skipWidth && isBoundaryW)
5136
0
    {
5137
0
        if (flag)
5138
0
            index++;
5139
0
        else
5140
0
        {
5141
            /* Number of 4x4 blocks in out of bound region */
5142
0
            int outOfBound = m_param->maxCUSize / 2;
5143
0
            uint32_t sum = (uint32_t)pow((outOfBound >> 2), 2);
5144
0
            index += sum;
5145
0
        }
5146
0
        cuLoc->switchCondition += m_param->num4x4Partitions;
5147
0
    }
5148
5149
    /* Completed writing 2 CTUs - move to the last remembered index of the next CTU row*/
5150
0
    if (cuLoc->switchCondition == 2 * m_param->num4x4Partitions)
5151
0
    {
5152
0
        if (isBoundaryW)
5153
0
            cuLoc->evenRowIndex = *count + (m_param->num4x4Partitions * cuLoc->widthInCU); // end of row - skip to the next even row
5154
0
        else
5155
0
            cuLoc->evenRowIndex = *count;
5156
0
        *count = cuLoc->oddRowIndex;
5157
5158
        /* Height boundary case :
5159
        Skip to appropriate index when out of boundary cases occur
5160
        Out of boundary may occur when the out of bound pixels along
5161
        the height in low resoultion is greater than half of the maxCUSize */
5162
0
        int isBoundaryH = (*count >= (m_param->num4x4Partitions * cuLoc->heightInCU * cuLoc->widthInCU));
5163
0
        if (cuLoc->skipHeight && isBoundaryH)
5164
0
        {
5165
0
            if (flag)
5166
0
                index += 2;
5167
0
            else
5168
0
            {
5169
0
                int outOfBound = m_param->maxCUSize / 2;
5170
0
                uint32_t sum = (uint32_t)(2 * pow((abs(outOfBound) >> 2), 2));
5171
0
                index += sum;
5172
0
            }
5173
0
            *count = cuLoc->evenRowIndex;
5174
0
            cuLoc->switchCondition = 0;
5175
0
        }
5176
0
    }
5177
    /* Completed writing 4 CTUs - move to the last remembered index of
5178
    the previous CTU row to copy the next save CTU's data*/
5179
0
    else if (cuLoc->switchCondition == 4 * m_param->num4x4Partitions)
5180
0
    {
5181
0
        if (isBoundaryW)
5182
0
            cuLoc->oddRowIndex = *count + (m_param->num4x4Partitions * cuLoc->widthInCU); // end of row - skip to the next odd row
5183
0
        else
5184
0
            cuLoc->oddRowIndex = *count;
5185
0
        *count = cuLoc->evenRowIndex;
5186
0
        cuLoc->switchCondition = 0;
5187
0
    }
5188
0
    return index;
5189
0
}
5190
5191
/*      save                        load
5192
                       CTU0    CTU1    CTU2    CTU3
5193
        2NxN          2Nx2N   2Nx2N   2Nx2N   2Nx2N
5194
        NX2N          2Nx2N   2Nx2N   2Nx2N   2Nx2N
5195
        2NxnU          2NxN    2NxN   2Nx2N   2Nx2N
5196
        2NxnD         2Nx2N   2Nx2N    2NxN    2NxN
5197
        nLx2N          Nx2N   2Nx2N    Nx2N   2Nx2N
5198
        nRx2N         2Nx2N    Nx2N    2Nx2N   Nx2N
5199
*/
5200
int Encoder::getPuShape(puOrientation* puOrient, int partSize, int numCTU)
5201
0
{
5202
0
    puOrient->isRect = true;
5203
0
    if (partSize == SIZE_Nx2N)
5204
0
        puOrient->isVert = true;
5205
0
    if (partSize >= SIZE_2NxnU) // All AMP modes
5206
0
    {
5207
0
        puOrient->isAmp = true;
5208
0
        puOrient->isRect = false;
5209
0
        if (partSize == SIZE_2NxnD && numCTU > 1)
5210
0
            return SIZE_2NxN;
5211
0
        else if (partSize == SIZE_2NxnU && numCTU < 2)
5212
0
            return SIZE_2NxN;
5213
0
        else if (partSize == SIZE_nLx2N)
5214
0
        {
5215
0
            puOrient->isVert = true;
5216
0
            if (!(numCTU % 2))
5217
0
                return SIZE_Nx2N;
5218
0
        }
5219
0
        else if (partSize == SIZE_nRx2N)
5220
0
        {
5221
0
            puOrient->isVert = true;
5222
0
            if (numCTU % 2)
5223
0
                return SIZE_Nx2N;
5224
0
        }
5225
0
    }
5226
0
    return SIZE_2Nx2N;
5227
0
}
5228
void Encoder::computeDistortionOffset(x265_analysis_data* analysis)
5229
0
{
5230
0
    x265_analysis_distortion_data *distortionData = analysis->distortionData;
5231
5232
0
    double sum = 0.0, sqrSum = 0.0;
5233
0
    for (uint32_t i = 0; i < analysis->numCUsInFrame; ++i)
5234
0
    {
5235
0
        distortionData->scaledDistortion[i] = X265_LOG2(X265_MAX(distortionData->ctuDistortion[i], 1));
5236
0
        sum += distortionData->scaledDistortion[i];
5237
0
        sqrSum += distortionData->scaledDistortion[i] * distortionData->scaledDistortion[i];
5238
0
    }
5239
0
    double avg = sum / analysis->numCUsInFrame;
5240
0
    distortionData->sdDistortion = pow(((sqrSum / analysis->numCUsInFrame) - (avg * avg)), 0.5);
5241
0
    distortionData->averageDistortion = avg;
5242
0
    distortionData->highDistortionCtuCount = distortionData->lowDistortionCtuCount = 0;
5243
0
    for (uint32_t i = 0; i < analysis->numCUsInFrame; ++i)
5244
0
    {
5245
0
        distortionData->threshold[i] = distortionData->scaledDistortion[i] / distortionData->averageDistortion;
5246
0
        distortionData->offset[i] = (distortionData->averageDistortion - distortionData->scaledDistortion[i]) / distortionData->sdDistortion;
5247
0
        if (distortionData->threshold[i] < 0.9 && distortionData->offset[i] >= 1)
5248
0
            distortionData->lowDistortionCtuCount++;
5249
0
        else if (distortionData->threshold[i] > 1.1 && distortionData->offset[i] <= -1)
5250
0
            distortionData->highDistortionCtuCount++;
5251
0
    }
5252
0
}
5253
void Encoder::readAnalysisFile(x265_analysis_data* analysis, int curPoc, int sliceType)
5254
0
{
5255
5256
0
#define X265_FREAD(val, size, readSize, fileOffset)\
5257
0
    if (fread(val, size, readSize, fileOffset) != readSize)\
5258
0
    {\
5259
0
    x265_log(NULL, X265_LOG_ERROR, "Error reading analysis 2 pass data\n"); \
5260
0
    x265_alloc_analysis_data(m_param, analysis); \
5261
0
    m_aborted = true; \
5262
0
    return; \
5263
0
}\
5264
0
5265
0
    uint32_t depthBytes = 0;
5266
0
    int poc; uint32_t frameRecordSize;
5267
0
    X265_FREAD(&frameRecordSize, sizeof(uint32_t), 1, m_analysisFileIn);
5268
0
    X265_FREAD(&depthBytes, sizeof(uint32_t), 1, m_analysisFileIn);
5269
0
    X265_FREAD(&poc, sizeof(int), 1, m_analysisFileIn);
5270
5271
0
    if (poc != curPoc || feof(m_analysisFileIn))
5272
0
    {
5273
0
        x265_log(NULL, X265_LOG_WARNING, "Error reading analysis 2 pass data: Cannot find POC %d\n", curPoc);
5274
0
        x265_free_analysis_data(m_param, analysis);
5275
0
        return;
5276
0
    }
5277
    /* Now arrived at the right frame, read the record */
5278
0
    analysis->frameRecordSize = frameRecordSize;
5279
0
    uint8_t* tempBuf = NULL, *depthBuf = NULL;
5280
0
    X265_FREAD((analysis->distortionData)->ctuDistortion, sizeof(sse_t), analysis->numCUsInFrame, m_analysisFileIn);
5281
0
    tempBuf = X265_MALLOC(uint8_t, depthBytes);
5282
0
    X265_FREAD(tempBuf, sizeof(uint8_t), depthBytes, m_analysisFileIn);
5283
0
    depthBuf = tempBuf;
5284
0
    x265_analysis_data *analysisData = (x265_analysis_data*)analysis;
5285
0
    x265_analysis_intra_data *intraData = analysisData->intraData;
5286
0
    x265_analysis_inter_data *interData = analysisData->interData;
5287
5288
0
    computeDistortionOffset(analysis);
5289
0
    size_t count = 0;
5290
0
    for (uint32_t d = 0; d < depthBytes; d++)
5291
0
    {
5292
0
        int bytes = analysis->numPartitions >> (depthBuf[d] * 2);
5293
0
        if (IS_X265_TYPE_I(sliceType))
5294
0
            memset(&intraData->depth[count], depthBuf[d], bytes);
5295
0
        else
5296
0
            memset(&interData->depth[count], depthBuf[d], bytes);
5297
0
        count += bytes;
5298
0
    }
5299
5300
5301
0
    if (!IS_X265_TYPE_I(sliceType))
5302
0
    {
5303
0
        MV *tempMVBuf[2], *MVBuf[2];
5304
0
        int32_t *tempRefBuf, *refBuf;
5305
0
        uint8_t *tempMvpBuf[2], *mvpBuf[2];
5306
0
        uint8_t* tempModeBuf = NULL, *modeBuf = NULL;
5307
0
        int numDir = sliceType == X265_TYPE_P ? 1 : 2;
5308
0
        tempRefBuf = X265_MALLOC(int32_t, numDir * depthBytes);
5309
5310
0
        for (int i = 0; i < numDir; i++)
5311
0
        {
5312
0
            tempMVBuf[i] = X265_MALLOC(MV, depthBytes);
5313
0
            X265_FREAD(tempMVBuf[i], sizeof(MV), depthBytes, m_analysisFileIn);
5314
0
            MVBuf[i] = tempMVBuf[i];
5315
0
            tempMvpBuf[i] = X265_MALLOC(uint8_t, depthBytes);
5316
0
            X265_FREAD(tempMvpBuf[i], sizeof(uint8_t), depthBytes, m_analysisFileIn);
5317
0
            mvpBuf[i] = tempMvpBuf[i];
5318
0
            X265_FREAD(&tempRefBuf[i*depthBytes], sizeof(int32_t), depthBytes, m_analysisFileIn);
5319
0
        }
5320
0
        refBuf = tempRefBuf;
5321
0
        tempModeBuf = X265_MALLOC(uint8_t, depthBytes);
5322
0
        X265_FREAD(tempModeBuf, sizeof(uint8_t), depthBytes, m_analysisFileIn);
5323
0
        modeBuf = tempModeBuf;
5324
        
5325
0
        count = 0;
5326
5327
0
        for (uint32_t d = 0; d < depthBytes; d++)
5328
0
        {
5329
0
            size_t bytes = analysis->numPartitions >> (depthBuf[d] * 2);
5330
0
            for (int i = 0; i < numDir; i++)
5331
0
            {
5332
0
                int32_t* ref = &(analysis->interData)->ref[i * analysis->numPartitions * analysis->numCUsInFrame];
5333
0
                for (size_t j = count, k = 0; k < bytes; j++, k++)
5334
0
                {
5335
0
                    memcpy(&(analysis->interData)->mv[i][j], MVBuf[i] + d, sizeof(MV));
5336
0
                    memcpy(&(analysis->interData)->mvpIdx[i][j], mvpBuf[i] + d, sizeof(uint8_t));
5337
0
                    memcpy(&ref[j], refBuf + (i * depthBytes) + d, sizeof(int32_t));
5338
0
                }
5339
0
            }
5340
0
            memset(&(analysis->interData)->modes[count], modeBuf[d], bytes);
5341
0
            count += bytes;
5342
0
        }
5343
5344
0
        for (int i = 0; i < numDir; i++)
5345
0
        {
5346
0
            X265_FREE(tempMVBuf[i]);
5347
0
            X265_FREE(tempMvpBuf[i]);
5348
0
        }
5349
0
        X265_FREE(tempRefBuf);
5350
0
        X265_FREE(tempModeBuf);
5351
0
    }
5352
0
    X265_FREE(tempBuf);
5353
5354
0
#undef X265_FREAD
5355
0
}
5356
5357
void Encoder::copyDistortionData(x265_analysis_data* analysis, FrameData &curEncData)
5358
0
{
5359
0
    for (uint32_t cuAddr = 0; cuAddr < analysis->numCUsInFrame; cuAddr++)
5360
0
    {
5361
0
        uint8_t depth = 0;
5362
0
        CUData* ctu = curEncData.getPicCTU(cuAddr);
5363
0
        x265_analysis_distortion_data *distortionData = (x265_analysis_distortion_data *)analysis->distortionData;
5364
0
        distortionData->ctuDistortion[cuAddr] = 0;
5365
0
        for (uint32_t absPartIdx = 0; absPartIdx < ctu->m_numPartitions;)
5366
0
        {
5367
0
            depth = ctu->m_cuDepth[absPartIdx];
5368
0
            distortionData->ctuDistortion[cuAddr] += ctu->m_distortion[absPartIdx];
5369
0
            absPartIdx += ctu->m_numPartitions >> (depth * 2);
5370
0
        }
5371
0
    }
5372
0
}
5373
5374
void Encoder::writeAnalysisFile(x265_analysis_data* analysis, FrameData &curEncData)
5375
0
{
5376
5377
0
#define X265_FWRITE(val, size, writeSize, fileOffset)\
5378
0
    if (fwrite(val, size, writeSize, fileOffset) < writeSize)\
5379
0
    {\
5380
0
        x265_log(NULL, X265_LOG_ERROR, "Error writing analysis data\n");\
5381
0
        x265_free_analysis_data(m_param, analysis);\
5382
0
        m_aborted = true;\
5383
0
        return;\
5384
0
    }\
5385
0
5386
0
    uint32_t depthBytes = 0;
5387
0
    uint32_t numDir, numPlanes;
5388
0
    bool bIntraInInter = false;
5389
5390
0
    if (!analysis->poc)
5391
0
    {
5392
0
        if (validateAnalysisData(&analysis->saveParam, 1) == -1)
5393
0
        {
5394
0
            m_aborted = true;
5395
0
            return;
5396
0
        }
5397
0
    }
5398
5399
    /* calculate frameRecordSize */
5400
0
    analysis->frameRecordSize = sizeof(analysis->frameRecordSize) + sizeof(depthBytes) + sizeof(analysis->poc) + sizeof(analysis->sliceType) +
5401
0
                      sizeof(analysis->numCUsInFrame) + sizeof(analysis->numPartitions) + sizeof(analysis->bScenecut) + sizeof(analysis->satdCost);
5402
0
    if (analysis->sliceType > X265_TYPE_I)
5403
0
    {
5404
0
        numDir = (analysis->sliceType == X265_TYPE_P) ? 1 : 2;
5405
0
        numPlanes = m_param->internalCsp == X265_CSP_I400 ? 1 : 3;
5406
0
        analysis->frameRecordSize += sizeof(WeightParam) * numPlanes * numDir;
5407
0
    }
5408
5409
0
    if (m_param->ctuDistortionRefine == CTU_DISTORTION_INTERNAL)
5410
0
    {
5411
0
        copyDistortionData(analysis, curEncData);
5412
0
        analysis->frameRecordSize += analysis->numCUsInFrame * sizeof(sse_t);
5413
0
    }
5414
5415
0
    if (m_param->analysisSaveReuseLevel > 1)
5416
0
    {
5417
5418
0
        if (analysis->sliceType == X265_TYPE_IDR || analysis->sliceType == X265_TYPE_I)
5419
0
        {
5420
0
            for (uint32_t cuAddr = 0; cuAddr < analysis->numCUsInFrame; cuAddr++)
5421
0
            {
5422
0
                uint8_t depth = 0;
5423
0
                uint8_t mode = 0;
5424
0
                uint8_t partSize = 0;
5425
5426
0
                CUData* ctu = curEncData.getPicCTU(cuAddr);
5427
0
                x265_analysis_intra_data* intraDataCTU = analysis->intraData;
5428
0
                int baseQP = (int)(ctu->m_encData->m_cuStat[cuAddr].baseQp + 0.5);
5429
5430
0
                for (uint32_t absPartIdx = 0; absPartIdx < ctu->m_numPartitions; depthBytes++)
5431
0
                {
5432
0
                    depth = ctu->m_cuDepth[absPartIdx];
5433
0
                    intraDataCTU->depth[depthBytes] = depth;
5434
5435
0
                    mode = ctu->m_chromaIntraDir[absPartIdx];
5436
0
                    intraDataCTU->chromaModes[depthBytes] = mode;
5437
5438
0
                    partSize = ctu->m_partSize[absPartIdx];
5439
0
                    intraDataCTU->partSizes[depthBytes] = partSize;
5440
5441
0
                    if (m_param->rc.cuTree)
5442
0
                        intraDataCTU->cuQPOff[depthBytes] = (int8_t)(ctu->m_qpAnalysis[absPartIdx] - baseQP);
5443
0
                    absPartIdx += ctu->m_numPartitions >> (depth * 2);
5444
0
                }
5445
0
                memcpy(&intraDataCTU->modes[ctu->m_cuAddr * ctu->m_numPartitions], ctu->m_lumaIntraDir, sizeof(uint8_t)* ctu->m_numPartitions);
5446
0
            }
5447
0
        }
5448
0
        else
5449
0
        {
5450
0
            bIntraInInter = (analysis->sliceType == X265_TYPE_P || m_param->bIntraInBFrames);
5451
0
            for (uint32_t cuAddr = 0; cuAddr < analysis->numCUsInFrame; cuAddr++)
5452
0
            {
5453
0
                uint8_t depth = 0;
5454
0
                uint8_t predMode = 0;
5455
0
                uint8_t partSize = 0;
5456
5457
0
                CUData* ctu = curEncData.getPicCTU(cuAddr);
5458
0
                x265_analysis_inter_data* interDataCTU = analysis->interData;
5459
0
                x265_analysis_intra_data* intraDataCTU = analysis->intraData;
5460
0
                int baseQP = (int)(ctu->m_encData->m_cuStat[cuAddr].baseQp + 0.5);
5461
5462
0
                for (uint32_t absPartIdx = 0; absPartIdx < ctu->m_numPartitions; depthBytes++)
5463
0
                {
5464
0
                    depth = ctu->m_cuDepth[absPartIdx];
5465
0
                    interDataCTU->depth[depthBytes] = depth;
5466
5467
0
                    predMode = ctu->m_predMode[absPartIdx];
5468
0
                    if (m_param->analysisSaveReuseLevel != 10 && ctu->m_refIdx[1][absPartIdx] != -1)
5469
0
                        predMode = 4; // used as indicator if the block is coded as bidir
5470
5471
0
                    interDataCTU->modes[depthBytes] = predMode;
5472
0
                    if (m_param->rc.cuTree)
5473
0
                        interDataCTU->cuQPOff[depthBytes] = (int8_t)(ctu->m_qpAnalysis[absPartIdx] - baseQP);
5474
5475
0
                    if (m_param->analysisSaveReuseLevel > 4)
5476
0
                    {
5477
0
                        partSize = ctu->m_partSize[absPartIdx];
5478
0
                        interDataCTU->partSize[depthBytes] = partSize;
5479
5480
                        /* Store per PU data */
5481
0
                        uint32_t numPU = (predMode == MODE_INTRA) ? 1 : nbPartsTable[(int)partSize];
5482
0
                        for (uint32_t puIdx = 0; puIdx < numPU; puIdx++)
5483
0
                        {
5484
0
                            uint32_t puabsPartIdx = ctu->getPUOffset(puIdx, absPartIdx) + absPartIdx;
5485
0
                            if (puIdx) depthBytes++;
5486
0
                            interDataCTU->mergeFlag[depthBytes] = ctu->m_mergeFlag[puabsPartIdx];
5487
5488
0
                            if (m_param->analysisSaveReuseLevel == 10)
5489
0
                            {
5490
0
                                interDataCTU->interDir[depthBytes] = ctu->m_interDir[puabsPartIdx];
5491
0
                                for (uint32_t dir = 0; dir < numDir; dir++)
5492
0
                                {
5493
0
                                    interDataCTU->mvpIdx[dir][depthBytes] = ctu->m_mvpIdx[dir][puabsPartIdx];
5494
0
                                    interDataCTU->refIdx[dir][depthBytes] = ctu->m_refIdx[dir][puabsPartIdx];
5495
0
                                    interDataCTU->mv[dir][depthBytes].word = ctu->m_mv[dir][puabsPartIdx].word;
5496
0
                                }
5497
0
                            }
5498
0
                        }
5499
0
                        if (m_param->analysisSaveReuseLevel == 10 && bIntraInInter)
5500
0
                            intraDataCTU->chromaModes[depthBytes] = ctu->m_chromaIntraDir[absPartIdx];
5501
0
                    }
5502
0
                    absPartIdx += ctu->m_numPartitions >> (depth * 2);
5503
0
                }
5504
0
                if (m_param->analysisSaveReuseLevel == 10 && bIntraInInter)
5505
0
                    memcpy(&intraDataCTU->modes[ctu->m_cuAddr * ctu->m_numPartitions], ctu->m_lumaIntraDir, sizeof(uint8_t)* ctu->m_numPartitions);
5506
0
            }
5507
0
        }
5508
5509
0
        if ((analysis->sliceType == X265_TYPE_IDR || analysis->sliceType == X265_TYPE_I) && m_param->rc.cuTree)
5510
0
            analysis->frameRecordSize += sizeof(uint8_t)* analysis->numCUsInFrame * analysis->numPartitions + depthBytes * 3 + (sizeof(int8_t) * depthBytes);
5511
0
        else if (analysis->sliceType == X265_TYPE_IDR || analysis->sliceType == X265_TYPE_I)
5512
0
            analysis->frameRecordSize += sizeof(uint8_t)* analysis->numCUsInFrame * analysis->numPartitions + depthBytes * 3;
5513
0
        else
5514
0
        {
5515
            /* Add sizeof depth, modes, partSize, cuQPOffset, mergeFlag */
5516
0
            analysis->frameRecordSize += depthBytes * 2;
5517
0
            if (m_param->rc.cuTree)
5518
0
            analysis->frameRecordSize += (sizeof(int8_t) * depthBytes);
5519
0
            if (m_param->analysisSaveReuseLevel > 4)
5520
0
                analysis->frameRecordSize += (depthBytes * 2);
5521
5522
0
            if (m_param->analysisSaveReuseLevel == 10)
5523
0
            {
5524
                /* Add Size of interDir, mvpIdx, refIdx, mv, luma and chroma modes */
5525
0
                analysis->frameRecordSize += depthBytes;
5526
0
                analysis->frameRecordSize += sizeof(uint8_t)* depthBytes * numDir;
5527
0
                analysis->frameRecordSize += sizeof(int8_t)* depthBytes * numDir;
5528
0
                analysis->frameRecordSize += sizeof(MV)* depthBytes * numDir;
5529
0
                if (bIntraInInter)
5530
0
                    analysis->frameRecordSize += sizeof(uint8_t)* analysis->numCUsInFrame * analysis->numPartitions + depthBytes;
5531
0
            }
5532
0
            else
5533
0
                analysis->frameRecordSize += sizeof(int32_t)* analysis->numCUsInFrame * X265_MAX_PRED_MODE_PER_CTU * numDir;
5534
0
        }
5535
0
        analysis->depthBytes = depthBytes;
5536
0
    }
5537
5538
0
    if (!m_param->bUseAnalysisFile)
5539
0
        return;
5540
5541
0
    X265_FWRITE(&analysis->frameRecordSize, sizeof(uint32_t), 1, m_analysisFileOut);
5542
0
    X265_FWRITE(&depthBytes, sizeof(uint32_t), 1, m_analysisFileOut);
5543
0
    X265_FWRITE(&analysis->poc, sizeof(int), 1, m_analysisFileOut);
5544
0
    X265_FWRITE(&analysis->sliceType, sizeof(int), 1, m_analysisFileOut);
5545
0
    X265_FWRITE(&analysis->bScenecut, sizeof(int), 1, m_analysisFileOut);
5546
0
    X265_FWRITE(&analysis->satdCost, sizeof(int64_t), 1, m_analysisFileOut);
5547
0
    X265_FWRITE(&analysis->numCUsInFrame, sizeof(int), 1, m_analysisFileOut);
5548
0
    X265_FWRITE(&analysis->numPartitions, sizeof(int), 1, m_analysisFileOut);
5549
0
    if (m_param->ctuDistortionRefine == CTU_DISTORTION_INTERNAL)
5550
0
        X265_FWRITE((analysis->distortionData)->ctuDistortion, sizeof(sse_t), analysis->numCUsInFrame, m_analysisFileOut);
5551
0
    if (analysis->sliceType > X265_TYPE_I)
5552
0
        X265_FWRITE((WeightParam*)analysis->wt, sizeof(WeightParam), numPlanes * numDir, m_analysisFileOut);
5553
5554
0
    if (m_param->analysisSaveReuseLevel < 2)
5555
0
        return;
5556
5557
0
    if (analysis->sliceType == X265_TYPE_IDR || analysis->sliceType == X265_TYPE_I)
5558
0
    {
5559
0
        X265_FWRITE((analysis->intraData)->depth, sizeof(uint8_t), depthBytes, m_analysisFileOut);
5560
0
        X265_FWRITE((analysis->intraData)->chromaModes, sizeof(uint8_t), depthBytes, m_analysisFileOut);
5561
0
        X265_FWRITE((analysis->intraData)->partSizes, sizeof(char), depthBytes, m_analysisFileOut);
5562
0
        if (m_param->rc.cuTree)
5563
0
            X265_FWRITE((analysis->intraData)->cuQPOff, sizeof(int8_t), depthBytes, m_analysisFileOut);
5564
0
        X265_FWRITE((analysis->intraData)->modes, sizeof(uint8_t), analysis->numCUsInFrame * analysis->numPartitions, m_analysisFileOut);
5565
0
    }
5566
0
    else
5567
0
    {
5568
0
        X265_FWRITE((analysis->interData)->depth, sizeof(uint8_t), depthBytes, m_analysisFileOut);
5569
0
        X265_FWRITE((analysis->interData)->modes, sizeof(uint8_t), depthBytes, m_analysisFileOut);
5570
0
        if (m_param->rc.cuTree)
5571
0
            X265_FWRITE((analysis->interData)->cuQPOff, sizeof(int8_t), depthBytes, m_analysisFileOut);
5572
0
        if (m_param->analysisSaveReuseLevel > 4)
5573
0
        {
5574
0
            X265_FWRITE((analysis->interData)->partSize, sizeof(uint8_t), depthBytes, m_analysisFileOut);
5575
0
            X265_FWRITE((analysis->interData)->mergeFlag, sizeof(uint8_t), depthBytes, m_analysisFileOut);
5576
0
            if (m_param->analysisSaveReuseLevel == 10)
5577
0
            {
5578
0
                X265_FWRITE((analysis->interData)->interDir, sizeof(uint8_t), depthBytes, m_analysisFileOut);
5579
0
                if (bIntraInInter) X265_FWRITE((analysis->intraData)->chromaModes, sizeof(uint8_t), depthBytes, m_analysisFileOut);
5580
0
                for (uint32_t dir = 0; dir < numDir; dir++)
5581
0
                {
5582
0
                    X265_FWRITE((analysis->interData)->mvpIdx[dir], sizeof(uint8_t), depthBytes, m_analysisFileOut);
5583
0
                    X265_FWRITE((analysis->interData)->refIdx[dir], sizeof(int8_t), depthBytes, m_analysisFileOut);
5584
0
                    X265_FWRITE((analysis->interData)->mv[dir], sizeof(MV), depthBytes, m_analysisFileOut);
5585
0
                }
5586
0
                if (bIntraInInter)
5587
0
                    X265_FWRITE((analysis->intraData)->modes, sizeof(uint8_t), analysis->numCUsInFrame * analysis->numPartitions, m_analysisFileOut);
5588
0
            }
5589
0
        }
5590
0
        if (m_param->analysisSaveReuseLevel != 10)
5591
0
            X265_FWRITE((analysis->interData)->ref, sizeof(int32_t), analysis->numCUsInFrame * X265_MAX_PRED_MODE_PER_CTU * numDir, m_analysisFileOut);
5592
5593
0
    }
5594
0
#undef X265_FWRITE
5595
0
}
5596
5597
void Encoder::writeAnalysisFileRefine(x265_analysis_data* analysis, FrameData &curEncData)
5598
0
{
5599
0
#define X265_FWRITE(val, size, writeSize, fileOffset)\
5600
0
    if (fwrite(val, size, writeSize, fileOffset) < writeSize)\
5601
0
    {\
5602
0
    x265_log(NULL, X265_LOG_ERROR, "Error writing analysis 2 pass data\n"); \
5603
0
    x265_free_analysis_data(m_param, analysis); \
5604
0
    m_aborted = true; \
5605
0
    return; \
5606
0
}\
5607
0
5608
0
    uint32_t depthBytes = 0;
5609
0
    x265_analysis_data *analysisData = (x265_analysis_data*)analysis;
5610
0
    x265_analysis_intra_data *intraData = analysisData->intraData;
5611
0
    x265_analysis_inter_data *interData = analysisData->interData;
5612
0
    x265_analysis_distortion_data *distortionData = analysisData->distortionData;
5613
5614
0
    copyDistortionData(analysis, curEncData);
5615
5616
0
    if (curEncData.m_slice->m_sliceType == I_SLICE)
5617
0
    {
5618
0
        for (uint32_t cuAddr = 0; cuAddr < analysis->numCUsInFrame; cuAddr++)
5619
0
        {
5620
0
            uint8_t depth = 0;
5621
0
            CUData* ctu = curEncData.getPicCTU(cuAddr);
5622
0
            for (uint32_t absPartIdx = 0; absPartIdx < ctu->m_numPartitions; depthBytes++)
5623
0
            {
5624
0
                depth = ctu->m_cuDepth[absPartIdx];
5625
0
                intraData->depth[depthBytes] = depth;
5626
0
                absPartIdx += ctu->m_numPartitions >> (depth * 2);
5627
0
            }
5628
0
        }
5629
0
    }
5630
5631
0
    else
5632
0
    {
5633
0
        int32_t* ref[2];
5634
0
        ref[0] = (analysis->interData)->ref;
5635
0
        ref[1] = &(analysis->interData)->ref[analysis->numPartitions * analysis->numCUsInFrame];
5636
0
        depthBytes = 0;
5637
0
        for (uint32_t cuAddr = 0; cuAddr < analysis->numCUsInFrame; cuAddr++)
5638
0
        {
5639
0
            uint8_t depth = 0;
5640
0
            uint8_t predMode = 0;
5641
5642
0
            CUData* ctu = curEncData.getPicCTU(cuAddr);
5643
0
            for (uint32_t absPartIdx = 0; absPartIdx < ctu->m_numPartitions; depthBytes++)
5644
0
            {
5645
0
                depth = ctu->m_cuDepth[absPartIdx];
5646
0
                interData->depth[depthBytes] = depth;
5647
0
                interData->mv[0][depthBytes].word = ctu->m_mv[0][absPartIdx].word;
5648
0
                interData->mvpIdx[0][depthBytes] = ctu->m_mvpIdx[0][absPartIdx];
5649
0
                ref[0][depthBytes] = ctu->m_refIdx[0][absPartIdx];
5650
0
                predMode = ctu->m_predMode[absPartIdx];
5651
0
                if (ctu->m_refIdx[1][absPartIdx] != -1)
5652
0
                {
5653
0
                    interData->mv[1][depthBytes].word = ctu->m_mv[1][absPartIdx].word;
5654
0
                    interData->mvpIdx[1][depthBytes] = ctu->m_mvpIdx[1][absPartIdx];
5655
0
                    ref[1][depthBytes] = ctu->m_refIdx[1][absPartIdx];
5656
0
                    predMode = 4; // used as indiacator if the block is coded as bidir
5657
0
                }
5658
0
                interData->modes[depthBytes] = predMode;
5659
5660
0
                absPartIdx += ctu->m_numPartitions >> (depth * 2);
5661
0
            }
5662
0
        }
5663
0
    }
5664
5665
    /* calculate frameRecordSize */
5666
0
    analysis->frameRecordSize = sizeof(analysis->frameRecordSize) + sizeof(depthBytes) + sizeof(analysis->poc);
5667
0
    analysis->frameRecordSize += depthBytes * sizeof(uint8_t);
5668
0
    analysis->frameRecordSize += analysis->numCUsInFrame * sizeof(sse_t);
5669
0
    if (curEncData.m_slice->m_sliceType != I_SLICE)
5670
0
    {
5671
0
        int numDir = (curEncData.m_slice->m_sliceType == P_SLICE) ? 1 : 2;
5672
0
        analysis->frameRecordSize += depthBytes * sizeof(MV) * numDir;
5673
0
        analysis->frameRecordSize += depthBytes * sizeof(int32_t) * numDir;
5674
0
        analysis->frameRecordSize += depthBytes * sizeof(uint8_t) * numDir;
5675
0
        analysis->frameRecordSize += depthBytes * sizeof(uint8_t);
5676
0
    }
5677
0
    X265_FWRITE(&analysis->frameRecordSize, sizeof(uint32_t), 1, m_analysisFileOut);
5678
0
    X265_FWRITE(&depthBytes, sizeof(uint32_t), 1, m_analysisFileOut);
5679
0
    X265_FWRITE(&analysis->poc, sizeof(uint32_t), 1, m_analysisFileOut);
5680
0
    X265_FWRITE(distortionData->ctuDistortion, sizeof(sse_t), analysis->numCUsInFrame, m_analysisFileOut);
5681
0
    if (curEncData.m_slice->m_sliceType == I_SLICE)
5682
0
    {
5683
0
        X265_FWRITE((analysis->intraData)->depth, sizeof(uint8_t), depthBytes, m_analysisFileOut);
5684
0
    }
5685
0
    else
5686
0
    {
5687
0
        X265_FWRITE((analysis->interData)->depth, sizeof(uint8_t), depthBytes, m_analysisFileOut);
5688
0
    }
5689
0
    if (curEncData.m_slice->m_sliceType != I_SLICE)
5690
0
    {
5691
0
        int numDir = curEncData.m_slice->m_sliceType == P_SLICE ? 1 : 2;
5692
0
        for (int i = 0; i < numDir; i++)
5693
0
        {
5694
0
            int32_t* ref = &(analysis->interData)->ref[i * analysis->numPartitions * analysis->numCUsInFrame];
5695
0
            X265_FWRITE(interData->mv[i], sizeof(MV), depthBytes, m_analysisFileOut);
5696
0
            X265_FWRITE(interData->mvpIdx[i], sizeof(uint8_t), depthBytes, m_analysisFileOut);
5697
0
            X265_FWRITE(ref, sizeof(int32_t), depthBytes, m_analysisFileOut);
5698
0
        }
5699
0
        X265_FWRITE((analysis->interData)->modes, sizeof(uint8_t), depthBytes, m_analysisFileOut);
5700
0
    }
5701
0
#undef X265_FWRITE
5702
0
}
5703
5704
void Encoder::printReconfigureParams()
5705
0
{
5706
0
    if (!(m_reconfigure || m_reconfigureRc))
5707
0
        return;
5708
0
    x265_param* oldParam = m_param;
5709
0
    x265_param* newParam = m_latestParam;
5710
    
5711
0
    x265_log(newParam, X265_LOG_DEBUG, "Reconfigured param options, input Frame: %d\n", m_pocLast + 1);
5712
5713
0
    char tmp[60];
5714
0
#define TOOLCMP(COND1, COND2, STR)  if (COND1 != COND2) { sprintf(tmp, STR, COND1, COND2); x265_log(newParam, X265_LOG_DEBUG, tmp); }
5715
0
    TOOLCMP(oldParam->maxNumReferences, newParam->maxNumReferences, "ref=%d to %d\n");
5716
0
    TOOLCMP(oldParam->bEnableFastIntra, newParam->bEnableFastIntra, "fast-intra=%d to %d\n");
5717
0
    TOOLCMP(oldParam->bEnableEarlySkip, newParam->bEnableEarlySkip, "early-skip=%d to %d\n");
5718
0
    TOOLCMP(oldParam->recursionSkipMode, newParam->recursionSkipMode, "rskip=%d to %d\n");
5719
0
    TOOLCMP(oldParam->searchMethod, newParam->searchMethod, "me=%d to %d\n");
5720
0
    TOOLCMP(oldParam->searchRange, newParam->searchRange, "merange=%d to %d\n");
5721
0
    TOOLCMP(oldParam->subpelRefine, newParam->subpelRefine, "subme= %d to %d\n");
5722
0
    TOOLCMP(oldParam->rdLevel, newParam->rdLevel, "rd=%d to %d\n");
5723
0
    TOOLCMP(oldParam->rdoqLevel, newParam->rdoqLevel, "rdoq=%d to %d\n" );
5724
0
    TOOLCMP(oldParam->bEnableRectInter, newParam->bEnableRectInter, "rect=%d to %d\n");
5725
0
    TOOLCMP(oldParam->maxNumMergeCand, newParam->maxNumMergeCand, "max-merge=%d to %d\n");
5726
0
    TOOLCMP(oldParam->bIntraInBFrames, newParam->bIntraInBFrames, "b-intra=%d to %d\n");
5727
0
    TOOLCMP(oldParam->scalingLists, newParam->scalingLists, "scalinglists=%s to %s\n");
5728
0
    TOOLCMP(oldParam->rc.vbvMaxBitrate, newParam->rc.vbvMaxBitrate, "vbv-maxrate=%d to %d\n");
5729
0
    TOOLCMP(oldParam->rc.vbvBufferSize, newParam->rc.vbvBufferSize, "vbv-bufsize=%d to %d\n");
5730
0
    TOOLCMP(oldParam->rc.bitrate, newParam->rc.bitrate, "bitrate=%d to %d\n");
5731
0
    TOOLCMP(oldParam->rc.rfConstant, newParam->rc.rfConstant, "crf=%f to %f\n");
5732
0
}
5733
5734
void Encoder::readUserSeiFile(x265_sei_payload& seiMsg, int curPoc)
5735
0
{
5736
0
    char line[1024];
5737
0
    while (fgets(line, sizeof(line), m_naluFile))
5738
0
    {
5739
0
        int poc = atoi(strtok(line, " "));
5740
0
        char *prefix = strtok(NULL, " ");
5741
0
        int nalType = atoi(strtok(NULL, "/"));
5742
0
        int payloadType = atoi(strtok(NULL, " "));
5743
0
        char *base64Encode = strtok(NULL, "\n");
5744
0
        int base64EncodeLength = (int)strlen(base64Encode);
5745
0
        char *base64Decode = SEI::base64Decode(base64Encode, base64EncodeLength);
5746
0
        if (nalType == NAL_UNIT_PREFIX_SEI && (!strcmp(prefix, "PREFIX")))
5747
0
        {
5748
0
            int currentPOC = curPoc;
5749
0
            if (currentPOC == poc)
5750
0
            {
5751
0
                seiMsg.payloadSize = (base64EncodeLength / 4) * 3;
5752
0
                seiMsg.payload = (uint8_t*)x265_malloc(sizeof(uint8_t) * seiMsg.payloadSize);
5753
0
                if (!seiMsg.payload)
5754
0
                {
5755
0
                    x265_log(m_param, X265_LOG_ERROR, "Unable to allocate memory for SEI payload\n");
5756
0
                    break;
5757
0
                }
5758
0
                if (payloadType == 4)
5759
0
                    seiMsg.payloadType = USER_DATA_REGISTERED_ITU_T_T35;
5760
0
                else if (payloadType == 5)
5761
0
                    seiMsg.payloadType = USER_DATA_UNREGISTERED;
5762
0
                else
5763
0
                {
5764
0
                    x265_log(m_param, X265_LOG_WARNING, "Unsupported SEI payload Type for frame %d\n", poc);
5765
0
                    break;
5766
0
                }
5767
0
                memcpy(seiMsg.payload, base64Decode, seiMsg.payloadSize);
5768
0
                break;
5769
0
            }
5770
0
        }
5771
0
        else
5772
0
        {
5773
0
            x265_log(m_param, X265_LOG_WARNING, "SEI message for frame %d is not inserted. Will support only PREFIX SEI messages.\n", poc);
5774
0
            break;
5775
0
        }
5776
0
    }
5777
0
}
5778
5779
bool Encoder::computeSPSRPSIndex()
5780
0
{
5781
0
    RPS* rpsInSPS = m_sps.spsrps;
5782
0
    int* rpsNumInPSP = &m_sps.spsrpsNum;
5783
0
    int  beginNum = m_sps.numGOPBegin;
5784
0
    int  endNum;
5785
0
    RPS* rpsInRec;
5786
0
    RPS* rpsInIdxList;
5787
0
    RPS* thisRpsInSPS;
5788
0
    RPS* thisRpsInList;
5789
0
    RPSListNode* headRpsIdxList = NULL;
5790
0
    RPSListNode* tailRpsIdxList = NULL;
5791
0
    RPSListNode* rpsIdxListIter = NULL;
5792
0
    RateControlEntry *rce2Pass = m_rateControl->m_rce2Pass;
5793
0
    int numEntries = m_rateControl->m_numEntries;
5794
0
    RateControlEntry *rce;
5795
0
    int idx = 0;
5796
0
    int pos = 0;
5797
0
    int resultIdx[64];
5798
0
    memset(rpsInSPS, 0, sizeof(RPS) * MAX_NUM_SHORT_TERM_RPS);
5799
5800
    // find out all RPS date in current GOP
5801
0
    beginNum++;
5802
0
    endNum = beginNum;
5803
0
    if (!m_param->bRepeatHeaders)
5804
0
    {
5805
0
        endNum = numEntries;
5806
0
    }
5807
0
    else
5808
0
    {
5809
0
        while (endNum < numEntries)
5810
0
        {
5811
0
            rce = &rce2Pass[endNum];
5812
0
            if (rce->sliceType == I_SLICE)
5813
0
            {
5814
0
                if (m_param->keyframeMin && (endNum - beginNum + 1 < m_param->keyframeMin))
5815
0
                {
5816
0
                    endNum++;
5817
0
                    continue;
5818
0
                }
5819
0
                break;
5820
0
            }
5821
0
            endNum++;
5822
0
        }
5823
0
    }
5824
0
    m_sps.numGOPBegin = endNum;
5825
5826
    // find out all kinds of RPS
5827
0
    for (int i = beginNum; i < endNum; i++)
5828
0
    {
5829
0
        rce = &rce2Pass[i];
5830
0
        rpsInRec = &rce->rpsData;
5831
0
        rpsIdxListIter = headRpsIdxList;
5832
        // i frame don't recode RPS info
5833
0
        if (rce->sliceType != I_SLICE)
5834
0
        {
5835
0
            while (rpsIdxListIter)
5836
0
            {
5837
0
                rpsInIdxList = rpsIdxListIter->rps;
5838
0
                if (rpsInRec->numberOfPictures == rpsInIdxList->numberOfPictures
5839
0
                    && rpsInRec->numberOfNegativePictures == rpsInIdxList->numberOfNegativePictures
5840
0
                    && rpsInRec->numberOfPositivePictures == rpsInIdxList->numberOfPositivePictures)
5841
0
                {
5842
0
                    for (pos = 0; pos < rpsInRec->numberOfPictures; pos++)
5843
0
                    {
5844
0
                        if (rpsInRec->deltaPOC[pos] != rpsInIdxList->deltaPOC[pos]
5845
0
                            || rpsInRec->bUsed[pos] != rpsInIdxList->bUsed[pos])
5846
0
                            break;
5847
0
                    }
5848
0
                    if (pos == rpsInRec->numberOfPictures)    // if this type of RPS has exist
5849
0
                    {
5850
0
                        rce->rpsIdx = rpsIdxListIter->idx;
5851
0
                        rpsIdxListIter->count++;
5852
                        // sort RPS type link after reset RPS type count.
5853
0
                        RPSListNode* next = rpsIdxListIter->next;
5854
0
                        RPSListNode* prior = rpsIdxListIter->prior;
5855
0
                        RPSListNode* iter = prior;
5856
0
                        if (iter)
5857
0
                        {
5858
0
                            while (iter)
5859
0
                            {
5860
0
                                if (iter->count > rpsIdxListIter->count)
5861
0
                                    break;
5862
0
                                iter = iter->prior;
5863
0
                            }
5864
0
                            if (iter)
5865
0
                            {
5866
0
                                prior->next = next;
5867
0
                                if (next)
5868
0
                                    next->prior = prior;
5869
0
                                else
5870
0
                                    tailRpsIdxList = prior;
5871
0
                                rpsIdxListIter->next = iter->next;
5872
0
                                rpsIdxListIter->prior = iter;
5873
0
                                iter->next->prior = rpsIdxListIter;
5874
0
                                iter->next = rpsIdxListIter;
5875
0
                            }
5876
0
                            else
5877
0
                            {
5878
0
                                prior->next = next;
5879
0
                                if (next)
5880
0
                                    next->prior = prior;
5881
0
                                else
5882
0
                                    tailRpsIdxList = prior;
5883
0
                                headRpsIdxList->prior = rpsIdxListIter;
5884
0
                                rpsIdxListIter->next = headRpsIdxList;
5885
0
                                rpsIdxListIter->prior = NULL;
5886
0
                                headRpsIdxList = rpsIdxListIter;
5887
0
                            }
5888
0
                        }
5889
0
                        break;
5890
0
                    }
5891
0
                }
5892
0
                rpsIdxListIter = rpsIdxListIter->next;
5893
0
            }
5894
0
            if (!rpsIdxListIter)  // add new type of RPS
5895
0
            {
5896
0
                RPSListNode* newIdxNode = new RPSListNode();
5897
0
                if (newIdxNode == NULL)
5898
0
                    goto fail;
5899
0
                newIdxNode->rps = rpsInRec;
5900
0
                newIdxNode->idx = idx++;
5901
0
                newIdxNode->count = 1;
5902
0
                newIdxNode->next = NULL;
5903
0
                newIdxNode->prior = NULL;
5904
0
                if (!tailRpsIdxList)
5905
0
                    tailRpsIdxList = headRpsIdxList = newIdxNode;
5906
0
                else
5907
0
                {
5908
0
                    tailRpsIdxList->next = newIdxNode;
5909
0
                    newIdxNode->prior = tailRpsIdxList;
5910
0
                    tailRpsIdxList = newIdxNode;
5911
0
                }
5912
0
                rce->rpsIdx = newIdxNode->idx;
5913
0
            }
5914
0
        }
5915
0
        else
5916
0
        {
5917
0
            rce->rpsIdx = -1;
5918
0
        }
5919
0
    }
5920
5921
    // get commonly RPS set
5922
0
    memset(resultIdx, 0, sizeof(resultIdx));
5923
0
    if (idx > MAX_NUM_SHORT_TERM_RPS)
5924
0
        idx = MAX_NUM_SHORT_TERM_RPS;
5925
5926
0
    *rpsNumInPSP = idx;
5927
0
    rpsIdxListIter = headRpsIdxList;
5928
0
    for (int i = 0; i < idx; i++)
5929
0
    {
5930
0
        resultIdx[i] = rpsIdxListIter->idx;
5931
0
        m_rpsInSpsCount += rpsIdxListIter->count;
5932
0
        thisRpsInSPS = rpsInSPS + i;
5933
0
        thisRpsInList = rpsIdxListIter->rps;
5934
0
        thisRpsInSPS->numberOfPictures = thisRpsInList->numberOfPictures;
5935
0
        thisRpsInSPS->numberOfNegativePictures = thisRpsInList->numberOfNegativePictures;
5936
0
        thisRpsInSPS->numberOfPositivePictures = thisRpsInList->numberOfPositivePictures;
5937
0
        for (pos = 0; pos < thisRpsInList->numberOfPictures; pos++)
5938
0
        {
5939
0
            thisRpsInSPS->deltaPOC[pos] = thisRpsInList->deltaPOC[pos];
5940
0
            thisRpsInSPS->bUsed[pos] = thisRpsInList->bUsed[pos];
5941
0
        }
5942
0
        rpsIdxListIter = rpsIdxListIter->next;
5943
0
    }
5944
5945
    //reset every frame's RPS index
5946
0
    for (int i = beginNum; i < endNum; i++)
5947
0
    {
5948
0
        int j;
5949
0
        rce = &rce2Pass[i];
5950
0
        for (j = 0; j < idx; j++)
5951
0
        {
5952
0
            if (rce->rpsIdx == resultIdx[j])
5953
0
            {
5954
0
                rce->rpsIdx = j;
5955
0
                break;
5956
0
            }
5957
0
        }
5958
5959
0
        if (j == idx)
5960
0
            rce->rpsIdx = -1;
5961
0
    }
5962
5963
0
    rpsIdxListIter = headRpsIdxList;
5964
0
    while (rpsIdxListIter)
5965
0
    {
5966
0
        RPSListNode* freeIndex = rpsIdxListIter;
5967
0
        rpsIdxListIter = rpsIdxListIter->next;
5968
0
        delete freeIndex;
5969
0
    }
5970
0
    return true;
5971
5972
0
fail:
5973
0
    rpsIdxListIter = headRpsIdxList;
5974
0
    while (rpsIdxListIter)
5975
0
    {
5976
0
        RPSListNode* freeIndex = rpsIdxListIter;
5977
0
        rpsIdxListIter = rpsIdxListIter->next;
5978
0
        delete freeIndex;
5979
0
    }
5980
0
    return false;
5981
0
}
5982