Coverage Report

Created: 2026-02-26 06:25

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