Coverage Report

Created: 2026-02-26 06:24

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
0
{
124
0
    m_aborted = false;
125
0
    m_reconfigure = false;
126
0
    m_reconfigureRc = false;
127
0
    m_encodedFrameNum = 0;
128
0
    m_pocLast = -1;
129
0
    m_curEncoder = 0;
130
0
    m_numLumaWPFrames = 0;
131
0
    m_numChromaWPFrames = 0;
132
0
    m_numLumaWPBiFrames = 0;
133
0
    m_numChromaWPBiFrames = 0;
134
0
    m_lookahead = NULL;
135
0
    m_rateControl = NULL;
136
0
    m_dpb = NULL;
137
0
    m_numDelayedPic = 0;
138
0
    m_outputCount = 0;
139
0
    m_param = NULL;
140
0
    m_latestParam = NULL;
141
0
    m_threadPool = NULL;
142
0
    m_analysisFileIn = NULL;
143
0
    m_analysisFileOut = NULL;
144
0
    m_filmGrainIn = NULL;
145
0
    m_aomFilmGrainIn = NULL;
146
0
    m_naluFile = NULL;
147
0
    m_offsetEmergency = NULL;
148
0
    m_iFrameNum = 0;
149
0
    m_iPPSQpMinus26 = 0;
150
0
    m_rpsInSpsCount = 0;
151
0
    m_cB = 1.0;
152
0
    m_cR = 1.0;
153
0
    for (int i = 0; i < MAX_LAYERS; i++)
154
0
        m_exportedPic[i] = NULL;
155
0
    for (int i = 0; i < X265_MAX_FRAME_THREADS; i++)
156
0
        m_frameEncoder[i] = NULL;
157
0
    for (uint32_t i = 0; i < DUP_BUFFER; i++)
158
0
        m_dupBuffer[i] = NULL;
159
0
    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
0
    m_prevTonemapPayload.payload = NULL;
171
0
    m_startPoint = 0;
172
0
    m_saveCTUSize = 0;
173
0
    m_zoneIndex = 0;
174
0
}
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
0
{
191
0
    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
0
    x265_param* p = m_param;
199
200
0
    int rows = (p->sourceHeight + p->maxCUSize - 1) >> g_log2Size[p->maxCUSize];
201
0
    int cols = (p->sourceWidth  + p->maxCUSize - 1) >> g_log2Size[p->maxCUSize];
202
203
0
    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
0
    if (rows == 1 || cols < 3)
252
0
    {
253
0
        x265_log(p, X265_LOG_WARNING, "Too few rows/columns, --wpp disabled\n");
254
0
        p->bEnableWavefront = 0;
255
0
    }
256
257
    // For zero-latency tune, frameNumThreads must be set to 1
258
0
    if (p->tune && (!strcmp(p->tune, "zerolatency") || !strcmp(p->tune, "zero-latency")))
259
0
    {
260
0
        p->frameNumThreads = 1;
261
0
    }
262
263
0
    bool allowPools = !strlen(p->numaPools) || strcmp(p->numaPools, "none");
264
265
    // Trim the thread pool if --wpp, --pme, and --pmode are disabled
266
0
    if (!p->bEnableWavefront && !p->bDistributeModeAnalysis && !p->bDistributeMotionEstimation && !p->lookaheadSlices)
267
0
        allowPools = false;
268
269
0
    m_numPools = 0;
270
0
    if (allowPools)
271
0
        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
0
    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
0
    x265_log(p, X265_LOG_INFO, "Slices                              : %d\n", p->maxSlices);
299
300
0
    char buf[128];
301
0
    int len = 0;
302
0
    if (p->bEnableWavefront)
303
0
        len += snprintf(buf + len, sizeof(buf) - len, "wpp(%d rows)", rows);
304
0
    if (p->bDistributeModeAnalysis)
305
0
        len += snprintf(buf + len,  sizeof(buf) - len, "%spmode", len ? "+" : "");
306
0
    if (p->bDistributeMotionEstimation)
307
0
        len += snprintf(buf + len, sizeof(buf) - len, "%spme ", len ? "+" : "");
308
0
    if (!len)
309
0
        strcpy(buf, "none");
310
311
0
    x265_log(p, X265_LOG_INFO, "frame threads / pool features       : %d / %s\n", p->frameNumThreads, buf);
312
313
0
    for (int i = 0; i < m_param->frameNumThreads; i++)
314
0
    {
315
0
        m_frameEncoder[i] = new FrameEncoder;
316
0
        m_frameEncoder[i]->m_nalList.m_annexB = !!m_param->bAnnexB;
317
0
    }
318
319
0
    if (m_numPools)
320
0
    {
321
0
        for (int i = 0; i < m_param->frameNumThreads; i++)
322
0
        {
323
0
            int pool = i % m_numPools;
324
0
            m_frameEncoder[i]->m_pool = &m_threadPool[pool];
325
0
            m_frameEncoder[i]->m_jpId = m_threadPool[pool].m_numProviders++;
326
0
            m_threadPool[pool].m_jpTable[m_frameEncoder[i]->m_jpId] = m_frameEncoder[i];
327
0
        }
328
0
        for (int i = 0; i < m_numPools; i++)
329
0
            m_threadPool[i].start();
330
0
    }
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
0
    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
0
    else if (!strlen(m_param->scalingLists) || !strcmp(m_param->scalingLists, "off"))
345
0
        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
0
    int pools = m_numPools;
351
0
    ThreadPool* lookAheadThreadPool = 0;
352
0
    if (m_param->lookaheadThreads > 0)
353
0
    {
354
0
        lookAheadThreadPool = ThreadPool::allocThreadPools(p, pools, 1);
355
0
    }
356
0
    else
357
0
        lookAheadThreadPool = m_threadPool;
358
0
    m_lookahead = new Lookahead(m_param, lookAheadThreadPool);
359
0
    if (pools)
360
0
    {
361
0
        m_lookahead->m_jpId = lookAheadThreadPool[0].m_numProviders++;
362
0
        lookAheadThreadPool[0].m_jpTable[m_lookahead->m_jpId] = m_lookahead;
363
0
    }
364
0
    if (m_param->lookaheadThreads > 0)
365
0
        for (int i = 0; i < pools; i++)
366
0
            lookAheadThreadPool[i].start();
367
0
    m_lookahead->m_numPools = pools;
368
0
    m_dpb = new DPB(m_param);
369
370
0
    m_rateControl = new RateControl(*m_param, this);
371
0
    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
0
    initVPS(&m_vps);
378
0
    initSPS(&m_sps);
379
0
    initPPS(&m_pps);
380
   
381
0
    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
0
    else
455
0
        m_scalingList.setupQuantMatrices(m_sps.chromaFormatIdc);
456
457
0
    int numRows = (m_param->sourceHeight + m_param->maxCUSize - 1) / m_param->maxCUSize;
458
0
    int numCols = (m_param->sourceWidth  + m_param->maxCUSize - 1) / m_param->maxCUSize;
459
0
    for (int i = 0; i < m_param->frameNumThreads; i++)
460
0
    {
461
0
        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
0
    }
467
468
0
    for (int i = 0; i < m_param->frameNumThreads; i++)
469
0
    {
470
0
        m_frameEncoder[i]->start();
471
0
        m_frameEncoder[i]->m_done.wait(); /* wait for thread to initialize */
472
0
    }
473
474
0
    if (m_param->bEmitHRDSEI)
475
0
        m_rateControl->initHRD(m_sps);
476
477
0
    if (!m_rateControl->init(m_sps))
478
0
        m_aborted = true;
479
0
    if (!m_lookahead->create())
480
0
        m_aborted = true;
481
482
0
    initRefIdx();
483
0
    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
0
    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
0
    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
0
    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
0
    m_bZeroLatency = !m_param->bframes && !m_param->lookaheadDepth && m_param->frameNumThreads == 1 && m_param->maxSlices == 1;
549
0
    m_aborted |= parseLambdaFile(m_param);
550
551
0
    m_encodeStartTime = x265_mdate();
552
553
0
    m_nalList.m_annexB = !!m_param->bAnnexB;
554
555
0
    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
0
    else
567
0
         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
0
    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
0
}
585
586
void Encoder::stopJobs()
587
0
{
588
0
    if (m_rateControl)
589
0
        m_rateControl->terminate(); // unblock all blocked RC calls
590
591
0
    if (m_lookahead)
592
0
        m_lookahead->stopJobs();
593
    
594
0
    for (int i = 0; i < m_param->frameNumThreads; i++)
595
0
    {
596
0
        if (m_frameEncoder[i])
597
0
        {
598
0
            m_frameEncoder[i]->getEncodedPicture(m_nalList);
599
0
            m_frameEncoder[i]->m_threadActive = false;
600
0
            m_frameEncoder[i]->m_enable.trigger();
601
0
            m_frameEncoder[i]->stop();
602
0
        }
603
0
    }
604
605
0
    if (m_threadPool)
606
0
    {
607
0
        for (int i = 0; i < m_numPools; i++)
608
0
            m_threadPool[i].stopWorkers();
609
0
    }
610
0
}
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
0
{
870
#if ENABLE_HDR10_PLUS
871
    if (m_bToneMap)
872
        m_hdr10plus_api->hdr10plus_clear_movie(m_cim, m_numCimInfo);
873
#endif
874
875
0
    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
0
    for (int layer = 0; layer < m_param->numLayers; layer++)
882
0
    {
883
0
        if (m_exportedPic[layer])
884
0
        {
885
0
            ATOMIC_DEC(&m_exportedPic[layer]->m_countRefEncoders);
886
0
            m_exportedPic[layer] = NULL;
887
0
        }
888
0
    }
889
890
0
    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
0
    for (int i = 0; i < m_param->frameNumThreads; i++)
918
0
    {
919
0
        if (m_frameEncoder[i])
920
0
        {
921
0
            m_frameEncoder[i]->destroy();
922
0
            delete m_frameEncoder[i];
923
0
        }
924
0
    }
925
926
    // thread pools can be cleaned up now that all the JobProviders are
927
    // known to be shutdown
928
0
    delete [] m_threadPool;
929
930
0
    if (m_lookahead)
931
0
    {
932
0
        m_lookahead->destroy();
933
0
        delete m_lookahead;
934
0
    }
935
936
0
    delete m_dpb;
937
0
    if (!m_param->bResetZoneConfig && m_param->rc.zonefileCount)
938
0
    {
939
0
        delete[] zoneReadCount;
940
0
        delete[] zoneWriteCount;
941
0
    }
942
943
0
    if (m_rateControl)
944
0
    {
945
0
        m_rateControl->destroy();
946
0
        delete m_rateControl;
947
0
    }
948
949
0
    X265_FREE(m_offsetEmergency);
950
951
0
    if (m_analysisFileIn)
952
0
        fclose(m_analysisFileIn);
953
954
0
    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
0
    if (m_naluFile)
974
0
        fclose(m_naluFile);
975
0
    if (m_filmGrainIn)
976
0
        x265_fclose(m_filmGrainIn);
977
0
    if (m_aomFilmGrainIn)
978
0
        x265_fclose(m_aomFilmGrainIn);
979
980
#ifdef SVT_HEVC
981
    X265_FREE(m_svtAppData);
982
#endif
983
984
0
    if (m_param)
985
0
    {
986
0
        if (m_param->csvfpt)
987
0
            fclose(m_param->csvfpt);
988
0
    }
989
990
    // Need not check anymore since all pointer is alias to base[]
991
0
    PARAM_NS::x265_param_free(m_paramBase[0]);
992
0
    PARAM_NS::x265_param_free(m_paramBase[1]);
993
0
    PARAM_NS::x265_param_free(m_paramBase[2]);
994
0
}
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
0
{
1055
0
    x265_sei_payload toneMap;
1056
0
    toneMap.payload = NULL;
1057
0
    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
0
    x265_sei_payload seiMsg;
1081
0
    seiMsg.payload = NULL;
1082
0
    int userPayload = 0;
1083
0
    if (m_enableNal)
1084
0
    {
1085
0
        readUserSeiFile(seiMsg, m_pocLast);
1086
0
        if (seiMsg.payload)
1087
0
            userPayload = 1;;
1088
0
    }
1089
1090
0
    int numPayloads = pic_in->userSEI.numPayloads + toneMapPayload + userPayload;
1091
1092
    // TODO: we may reuse buffer if become smaller than exist buffer
1093
0
    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
0
    frame->m_userSEI.numPayloads = numPayloads;
1102
1103
0
    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
0
}
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
0
{
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
0
    if (m_aborted)
1429
0
        return -1;
1430
1431
0
    const x265_picture* inputPic[MAX_VIEWS] = { NULL };
1432
0
    static int written = 0, read = 0;
1433
0
    bool dontRead = false;
1434
0
    bool dropflag = false;
1435
1436
0
    if (*m_exportedPic)
1437
0
    {
1438
0
        if (!m_param->bUseAnalysisFile && strlen(m_param->analysisSave))
1439
0
            x265_free_analysis_data(m_param, &m_exportedPic[0]->m_analysisData);
1440
1441
0
        for (int i = 0; i < m_param->numLayers; i++)
1442
0
        {
1443
0
            ATOMIC_DEC(&m_exportedPic[i]->m_countRefEncoders);
1444
0
            m_exportedPic[i] = NULL;
1445
0
        }
1446
0
        m_dpb->recycleUnreferenced();
1447
1448
0
        if (m_param->bEnableTemporalFilter)
1449
0
            m_lookahead->m_origPicBuf->recycleOrigPicList();
1450
0
    }
1451
1452
0
    if ((pic_in && (!m_param->chunkEnd || (m_encodedFrameNum < m_param->chunkEnd))) || (m_param->bEnableFrameDuplication && !pic_in && (read < written)))
1453
0
    {
1454
0
        if ((m_param->bEnableFrameDuplication && !pic_in && (read < written)))
1455
0
            dontRead = true;
1456
0
        else
1457
0
        {
1458
0
            if (m_latestParam->forceFlush == 1)
1459
0
            {
1460
0
                m_lookahead->setLookaheadQueue();
1461
0
                m_latestParam->forceFlush = 0;
1462
0
            }
1463
0
            if (m_latestParam->forceFlush == 2)
1464
0
            {
1465
0
                m_lookahead->m_filled = false;
1466
0
                m_latestParam->forceFlush = 0;
1467
0
            }
1468
1469
0
            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
0
        }
1476
1477
0
        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
0
        else
1534
0
        {
1535
0
            for (int view = 0; view < m_param->numViews; view++)
1536
0
                inputPic[view] = pic_in + view;
1537
0
        }
1538
1539
0
        x265_param* p = (m_reconfigure || m_reconfigureRc || m_param->bConfigRCFrame) ? m_latestParam : m_param;
1540
0
        Frame* inFrame[MAX_LAYERS];
1541
0
        for (int layer = 0; layer < m_param->numLayers; layer++)
1542
0
        {
1543
0
            if (m_dpb->m_freeList.empty())
1544
0
            {
1545
0
                inFrame[layer] = new Frame;
1546
0
                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
0
                inFrame[layer]->m_valid = false;
1554
0
                if (inFrame[layer]->create(p, inputPic[!m_param->format ? (m_param->numScalableLayers > 1) ? 0 : layer : 0]->quantOffsets))
1555
0
                {
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
0
                    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
0
                    else
1580
0
                    {
1581
0
                        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
0
                        else
1590
0
                        {
1591
0
                            m_sps.cuOffsetY = inFrame[layer]->m_fencPic->m_cuOffsetY;
1592
0
                            m_sps.buOffsetY = inFrame[layer]->m_fencPic->m_buOffsetY;
1593
0
                            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
0
                            if (m_param->internalCsp != X265_CSP_I400)
1599
0
                            {
1600
0
                                m_sps.cuOffsetC = inFrame[layer]->m_fencPic->m_cuOffsetC;
1601
0
                                m_sps.buOffsetC = inFrame[layer]->m_fencPic->m_buOffsetC;
1602
0
                                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
0
                            }
1608
0
                        }
1609
0
                    }
1610
0
                }
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
0
            }
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
0
            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
0
            inFrame[layer]->m_poc = (!layer) ? (++m_pocLast) : m_pocLast;
1675
0
            inFrame[layer]->m_userData = inputPic[0]->userData;
1676
0
            inFrame[layer]->m_pts = inputPic[0]->pts;
1677
0
            inFrame[layer]-> vbvEndFlag = inputPic[0]->vbvEndFlag;
1678
1679
0
            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
0
            inFrame[layer]->m_forceqp = inputPic[0]->forceqp;
1697
0
            inFrame[layer]->m_param = (m_reconfigure || m_reconfigureRc || m_param->bConfigRCFrame) ? m_latestParam : m_param;
1698
0
            inFrame[layer]->m_picStruct = inputPic[0]->picStruct;
1699
1700
            /*Copy reconfigured RC parameters to frame*/
1701
0
            if (m_param->rc.rateControlMode == X265_RC_ABR)
1702
0
                inFrame[layer]->m_targetBitrate = inFrame[layer]->m_param->rc.bitrate;
1703
0
            else if (m_param->rc.rateControlMode == X265_RC_CRF)
1704
0
                inFrame[layer]->m_targetCrf = inFrame[layer]->m_param->rc.rfConstant;
1705
0
            else if (m_param->rc.rateControlMode == X265_RC_CQP)
1706
0
                inFrame[layer]->m_targetQp = inFrame[layer]->m_param->rc.qp;
1707
1708
0
            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
0
            ATOMIC_INC(&inFrame[layer]->m_countRefEncoders);
1713
0
        }
1714
0
        copyUserSEIMessages(inFrame[0], inputPic[0]);
1715
1716
        /*Copy Dolby Vision RPU from inputPic to frame*/
1717
0
        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
0
        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
0
        if (m_pocLast == 0)
1735
0
            m_firstPts = inFrame[0]->m_pts;
1736
0
        if (m_bframeDelay && m_pocLast == m_bframeDelay)
1737
0
            m_bframeDelayTime = inFrame[0]->m_pts - m_firstPts;
1738
1739
0
        if ((m_param->rc.aqMode || m_param->bEnableWeightedPred || m_param->bEnableWeightedBiPred) &&
1740
0
            (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
0
        int sliceType = (m_param->rc.bStatRead) ? m_rateControl->rateControlSliceType(inFrame[0]->m_poc) : X265_TYPE_AUTO;
1751
0
        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
0
        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
0
        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
0
        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
0
        if (m_reconfigureRc || m_param->bConfigRCFrame)
1845
0
            inFrame[0]->m_reconfigureRc = true;
1846
1847
0
        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
0
        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
0
        m_numDelayedPic++;
1914
0
    }
1915
0
    else if (m_latestParam->forceFlush == 2)
1916
0
        m_lookahead->m_filled = true;
1917
0
    else
1918
0
        m_lookahead->flush();
1919
1920
0
    FrameEncoder *curEncoder = m_frameEncoder[m_curEncoder];
1921
0
    m_curEncoder = (m_curEncoder + 1) % m_param->frameNumThreads;
1922
0
    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
0
    Frame** outFrames = { NULL };
1929
0
    Frame* frameEnc[MAX_LAYERS] = { NULL };
1930
0
    int pass = 0;
1931
0
    do
1932
0
    {
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
0
        if (!m_bZeroLatency || pass)
1937
0
            outFrames = curEncoder->getEncodedPicture(m_nalList);
1938
0
        if (outFrames)
1939
0
        {
1940
0
            for (int sLayer = 0; sLayer < m_param->numLayers; sLayer++)
1941
0
            {
1942
0
                Frame* outFrame = *(outFrames + sLayer);
1943
0
                Slice* slice = outFrame->m_encData->m_slice;
1944
0
                x265_frame_stats* frameData = NULL;
1945
1946
                /* Free up inputPic->analysisData since it has already been used */
1947
0
                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
0
                if (pic_out)
1950
0
                {
1951
0
                    PicYuv* recpic = outFrame->m_reconPic[0];
1952
0
                    pic_out[sLayer].poc = slice->m_poc;
1953
0
                    pic_out[sLayer].bitDepth = X265_DEPTH;
1954
0
                    pic_out[sLayer].userData = outFrame->m_userData;
1955
0
                    pic_out[sLayer].colorSpace = m_param->internalCsp;
1956
0
                    pic_out[sLayer].frameData.tLayer = outFrame->m_tempLayer;
1957
0
                    pic_out[sLayer].layerID = sLayer;
1958
0
                    frameData = &(pic_out[sLayer].frameData);
1959
1960
0
                    pic_out[sLayer].pts = outFrame->m_pts;
1961
0
                    pic_out[sLayer].dts = outFrame->m_dts;
1962
0
                    pic_out[sLayer].reorderedPts = outFrame->m_reorderedPts;
1963
0
                    pic_out[sLayer].sliceType = outFrame->m_lowres.sliceType;
1964
0
                    pic_out[sLayer].planes[0] = recpic->m_picOrg[0];
1965
0
                    pic_out[sLayer].stride[0] = (int)(recpic->m_stride * sizeof(pixel));
1966
0
                    if (m_param->internalCsp != X265_CSP_I400)
1967
0
                    {
1968
0
                        pic_out[sLayer].planes[1] = recpic->m_picOrg[1];
1969
0
                        pic_out[sLayer].stride[1] = (int)(recpic->m_strideC * sizeof(pixel));
1970
0
                        pic_out[sLayer].planes[2] = recpic->m_picOrg[2];
1971
0
                        pic_out[sLayer].stride[2] = (int)(recpic->m_strideC * sizeof(pixel));
1972
0
                    }
1973
1974
                    /* Dump analysis data from pic_out to file in save mode and free */
1975
0
                    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
0
                }
2030
0
                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
0
                if (m_param->analysisMultiPassRefine || m_param->analysisMultiPassDistortion)
2042
0
                    x265_free_analysis_data(m_param, &outFrame->m_analysisData);
2043
0
                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
0
                else
2063
0
                {
2064
0
                    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
0
                    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
0
                }
2090
0
                if (m_aborted)
2091
0
                    return -1;
2092
2093
0
                if ((m_outputCount + 1) >= m_param->chunkStart)
2094
0
                    finishFrameStats(outFrame, curEncoder, frameData, m_pocLast, sLayer);
2095
0
                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
0
                if (m_param->rc.bStatWrite)
2124
0
                    if (m_rateControl->writeRateControlFrameStats(outFrame, &curEncoder->m_rce))
2125
0
                        m_aborted = true;
2126
0
                if (pic_out)
2127
0
                {
2128
                    /* m_rcData is allocated for every frame */
2129
0
                    pic_out[sLayer].rcData = outFrame->m_rcData;
2130
0
                    outFrame->m_rcData->qpaRc = outFrame->m_encData->m_avgQpRc;
2131
0
                    outFrame->m_rcData->qRceq = curEncoder->m_rce.qRceq;
2132
0
                    outFrame->m_rcData->qpNoVbv = curEncoder->m_rce.qpNoVbv;
2133
0
                    outFrame->m_rcData->coeffBits = outFrame->m_encData->m_frameStats.coeffBits;
2134
0
                    outFrame->m_rcData->miscBits = outFrame->m_encData->m_frameStats.miscBits;
2135
0
                    outFrame->m_rcData->mvBits = outFrame->m_encData->m_frameStats.mvBits;
2136
0
                    outFrame->m_rcData->qScale = outFrame->m_rcData->newQScale = x265_qp2qScale(outFrame->m_encData->m_avgQpRc);
2137
0
                    outFrame->m_rcData->poc = curEncoder->m_rce.poc;
2138
0
                    outFrame->m_rcData->encodeOrder = curEncoder->m_rce.encodeOrder;
2139
0
                    outFrame->m_rcData->sliceType = curEncoder->m_rce.sliceType;
2140
0
                    outFrame->m_rcData->keptAsRef = curEncoder->m_rce.sliceType == B_SLICE && !IS_REFERENCED(outFrame) ? 0 : 1;
2141
0
                    outFrame->m_rcData->qpAq = outFrame->m_encData->m_avgQpAq;
2142
0
                    outFrame->m_rcData->iCuCount = outFrame->m_encData->m_frameStats.percent8x8Intra * m_rateControl->m_ncu;
2143
0
                    outFrame->m_rcData->pCuCount = outFrame->m_encData->m_frameStats.percent8x8Inter * m_rateControl->m_ncu;
2144
0
                    outFrame->m_rcData->skipCuCount = outFrame->m_encData->m_frameStats.percent8x8Skip * m_rateControl->m_ncu;
2145
0
                    outFrame->m_rcData->currentSatd = curEncoder->m_rce.coeffBits;
2146
0
                }
2147
2148
0
                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
0
                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
0
                else
2168
0
                    m_exportedPic[sLayer] = outFrame;
2169
2170
0
                m_outputCount++;
2171
0
                if (m_param->chunkEnd == m_outputCount)
2172
0
                    m_numDelayedPic = 0;
2173
0
                else if (sLayer == m_param->numLayers -1)
2174
0
                    m_numDelayedPic--;
2175
2176
0
                ret = 1;
2177
0
            }
2178
0
        }
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
0
        if (!pass)
2183
0
            frameEnc[0] = m_lookahead->getDecidedPicture();
2184
0
        if (frameEnc[0] && !pass && (!m_param->chunkEnd || (m_encodedFrameNum < m_param->chunkEnd)))
2185
0
        {
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
0
            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
0
            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
0
            if (m_param->bResetZoneConfig)
2234
0
            {
2235
0
                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
0
            }
2241
2242
0
            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
0
            if (frameEnc[0]->m_reconfigureRc && !m_reconfigureRc)
2269
0
                frameEnc[0]->m_reconfigureRc = false;
2270
0
            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
0
            curEncoder->m_param = m_reconfigure ? m_latestParam : m_param;
2282
0
            curEncoder->m_reconfigure = m_reconfigure;
2283
2284
            /* give this frame a FrameData instance before encoding */
2285
0
            for (int layer = 0; layer < m_param->numLayers; layer++)
2286
0
            {
2287
0
                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
0
                else
2296
0
                {
2297
0
                    frameEnc[layer]->allocEncodeData(m_reconfigure ? m_latestParam : m_param, m_sps);
2298
0
                    Slice* slice = frameEnc[layer]->m_encData->m_slice;
2299
0
                    slice->m_sps = &m_sps;
2300
0
                    slice->m_pps = &m_pps;
2301
0
                    slice->m_param = m_param;
2302
0
                    slice->m_maxNumMergeCand = m_param->maxNumMergeCand;
2303
0
                    slice->m_endCUAddr = slice->realEndAddress(m_sps.numCUsInFrame * m_param->num4x4Partitions);
2304
0
                }
2305
0
                frameEnc[layer]->m_valid = true;
2306
0
                int baseViewType = frameEnc[0]->m_lowres.sliceType;
2307
0
                frameEnc[layer]->m_encData->m_slice->m_origSliceType = IS_X265_TYPE_B(baseViewType) ? B_SLICE : (baseViewType == X265_TYPE_P) ? P_SLICE : I_SLICE;
2308
0
            }
2309
0
            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
0
            for (int layer = 0; layer < m_param->numLayers; layer++)
2329
0
            {
2330
0
                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
0
            }
2349
2350
0
            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
0
            frameEnc[0]->m_encData->m_slice->m_iPPSQpMinus26 = m_iPPSQpMinus26;
2378
0
            frameEnc[0]->m_encData->m_slice->numRefIdxDefault[0] = m_pps.numRefIdxDefault[0];
2379
0
            frameEnc[0]->m_encData->m_slice->numRefIdxDefault[1] = m_pps.numRefIdxDefault[1];
2380
0
            frameEnc[0]->m_encData->m_slice->m_iNumRPSInSPS = m_sps.spsrpsNum;
2381
2382
0
            curEncoder->m_rce.encodeOrder = frameEnc[0]->m_encodeOrder = m_encodedFrameNum++;
2383
2384
0
            if (!strlen(m_param->analysisLoad) || !m_param->bDisableLookahead)
2385
0
            {
2386
0
                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
0
                else
2395
0
                    frameEnc[0]->m_dts = frameEnc[0]->m_reorderedPts;
2396
0
            }
2397
2398
            /* Allocate analysis data before encode in save mode. This is allocated in frameEnc[0] */
2399
0
            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
0
            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
0
            for (int layer = 0; layer < m_param->numLayers; layer++)
2427
0
                m_dpb->prepareEncode(frameEnc[layer]);
2428
2429
0
            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
0
            for (int layer = 0; layer < m_param->numLayers; layer++)
2450
0
            {
2451
0
                if (!!m_param->selectiveSAO)
2452
0
                {
2453
0
                    Slice* slice = frameEnc[layer]->m_encData->m_slice;
2454
0
                    slice->m_bUseSao = curEncoder->m_frameFilter.m_useSao = 1;
2455
0
                    switch (m_param->selectiveSAO)
2456
0
                    {
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
0
                    }
2467
0
                }
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
0
            }
2474
0
            if (m_param->rc.rateControlMode != X265_RC_CQP)
2475
0
                m_lookahead->getEstimatedPictureCost(frameEnc[0]);
2476
2477
0
            if (m_param->bIntraRefresh)
2478
0
                 calcRefreshInterval(frameEnc[0]);
2479
2480
            // Generate MCSTF References and perform HME
2481
0
            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
0
            if (!curEncoder->startCompressFrame(frameEnc))
2507
0
                m_aborted = true;
2508
0
        }
2509
0
        else if (m_encodedFrameNum)
2510
0
            m_rateControl->setFinalFrameCount(m_encodedFrameNum);
2511
0
    }
2512
0
    while (m_bZeroLatency && ++pass < 2);
2513
2514
0
    return ret;
2515
0
}
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
0
{
2730
0
    m_accBits += bits;
2731
0
    m_numPics++;
2732
0
}
2733
2734
void EncStats::addSsim(double ssim)
2735
0
{
2736
0
    m_globalSsim += ssim;
2737
0
}
2738
2739
void EncStats::addQP(double aveQp)
2740
0
{
2741
0
    m_totalQp += aveQp;
2742
0
}
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
0
{
2772
0
    if (m_param->logLevel < X265_LOG_INFO)
2773
0
        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
0
{
3053
0
    PicYuv* reconPic = curFrame->m_reconPic[0];
3054
0
    uint64_t bits = curEncoder->m_accessUnitBits[layer];
3055
3056
    //===== calculate PSNR =====
3057
0
    int width  = reconPic->m_picWidth - m_sps.conformanceWindow.rightOffset;
3058
0
    int height = reconPic->m_picHeight - m_sps.conformanceWindow.bottomOffset;
3059
0
    int size = width * height;
3060
3061
0
    int maxvalY = 255 << (X265_DEPTH - 8);
3062
0
    int maxvalC = 255 << (X265_DEPTH - 8);
3063
0
    double refValueY = (double)maxvalY * maxvalY * size;
3064
0
    double refValueC = (double)maxvalC * maxvalC * size / 4.0;
3065
0
    uint64_t ssdY, ssdU, ssdV;
3066
3067
0
    ssdY = curEncoder->m_SSDY[layer];
3068
0
    ssdU = curEncoder->m_SSDU[layer];
3069
0
    ssdV = curEncoder->m_SSDV[layer];
3070
0
    double psnrY = (ssdY ? 10.0 * log10(refValueY / (double)ssdY) : 99.99);
3071
0
    double psnrU = (ssdU ? 10.0 * log10(refValueC / (double)ssdU) : 99.99);
3072
0
    double psnrV = (ssdV ? 10.0 * log10(refValueC / (double)ssdV) : 99.99);
3073
3074
0
    FrameData& curEncData = *curFrame->m_encData;
3075
0
    Slice* slice = curEncData.m_slice;
3076
3077
    //===== add bits, psnr and ssim =====
3078
0
    m_analyzeAll[layer].addBits(bits);
3079
0
    m_analyzeAll[layer].addQP(curEncData.m_avgQpAq);
3080
3081
0
    if (m_param->bEnablePsnr)
3082
0
        m_analyzeAll[layer].addPsnr(psnrY, psnrU, psnrV);
3083
3084
0
    double ssim = 0.0;
3085
0
    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
0
    if (slice->isIntra())
3091
0
    {
3092
0
        m_analyzeI[layer].addBits(bits);
3093
0
        m_analyzeI[layer].addQP(curEncData.m_avgQpAq);
3094
0
        if (m_param->bEnablePsnr)
3095
0
            m_analyzeI[layer].addPsnr(psnrY, psnrU, psnrV);
3096
0
        if (m_param->bEnableSsim)
3097
0
            m_analyzeI[layer].addSsim(ssim);
3098
0
    }
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
0
    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
0
    char c = (slice->isIntra() ? (curFrame->m_lowres.sliceType == X265_TYPE_IDR ? 'I' : 'i') : slice->isInterP() ? 'P' : 'B');
3123
0
    int poc = slice->m_poc;
3124
0
    if (!IS_REFERENCED(curFrame))
3125
0
        c += 32; // lower case if unreferenced
3126
3127
0
    if (frameStats)
3128
0
    {
3129
0
        const int picOrderCntLSB = slice->m_poc - slice->m_lastIDR;
3130
3131
0
        frameStats->encoderOrder = m_outputCount;
3132
0
        frameStats->sliceType = c;
3133
0
        frameStats->poc = picOrderCntLSB;
3134
0
        frameStats->qp = curEncData.m_avgQpAq;
3135
0
        frameStats->bits = bits;
3136
0
        frameStats->bScenecut = curFrame->m_lowres.bScenecut;
3137
0
        if (m_param->csvLogLevel >= 2)
3138
0
            frameStats->ipCostRatio = curFrame->m_lowres.ipCostRatio;
3139
0
        frameStats->bufferFill = m_rateControl->m_bufferFillActual;
3140
0
        frameStats->bufferFillFinal = m_rateControl->m_bufferFillFinal;
3141
0
        if (m_param->csvLogLevel >= 2)
3142
0
            frameStats->unclippedBufferFillFinal = m_rateControl->m_unclippedBufferFillFinal;
3143
0
        frameStats->frameLatency = inPoc - poc;
3144
0
        if (m_param->rc.rateControlMode == X265_RC_CRF)
3145
0
            frameStats->rateFactor = curEncData.m_rateFactor;
3146
0
        frameStats->psnrY = psnrY;
3147
0
        frameStats->psnrU = psnrU;
3148
0
        frameStats->psnrV = psnrV;
3149
0
        double psnr = (psnrY * 6 + psnrU + psnrV) / 8;
3150
0
        frameStats->psnr = psnr;
3151
0
        frameStats->ssim = ssim;
3152
0
        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
0
#define ELAPSED_MSEC(start, end) (((double)(end) - (start)) / 1000)
3164
0
        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
0
        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
0
    }
3248
0
}
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
0
{
3257
0
    int j = 0;
3258
3259
0
    for (j = 0; j < MAX_NUM_REF_IDX; j++)
3260
0
    {
3261
0
        m_refIdxLastGOP.numRefIdxl0[j] = 0;
3262
0
        m_refIdxLastGOP.numRefIdxl1[j] = 0;
3263
0
    }
3264
3265
0
    return;
3266
0
}
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
0
{
3317
0
    sbacCoder.setBitstream(&bs);
3318
3319
0
    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
0
    bs.resetBits();
3328
#if ENABLE_ALPHA || ENABLE_MULTIVIEW
3329
    sbacCoder.codeVPS(m_vps, m_sps);
3330
#else
3331
0
    sbacCoder.codeVPS(m_vps);
3332
0
#endif
3333
0
    bs.writeByteAlignment();
3334
0
    list.serialize(NAL_UNIT_VPS, bs);
3335
3336
0
    for (int layer = 0; layer < m_param->numLayers; layer++)
3337
0
    {
3338
0
        bs.resetBits();
3339
0
        sbacCoder.codeSPS(m_sps, m_scalingList, m_vps.ptl, layer);
3340
0
        bs.writeByteAlignment();
3341
0
        list.serialize(NAL_UNIT_SPS, bs, layer);
3342
0
    }
3343
3344
0
    for (int layer = 0; layer < m_param->numLayers; layer++)
3345
0
    {
3346
0
        bs.resetBits();
3347
0
        sbacCoder.codePPS(m_pps, (m_param->maxSlices <= 1), m_iPPSQpMinus26, layer);
3348
0
        bs.writeByteAlignment();
3349
0
        list.serialize(NAL_UNIT_PPS, bs, layer);
3350
0
    }
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
0
    if (m_param->bSingleSeiNal)
3380
0
        bs.resetBits();
3381
3382
0
    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
0
    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
0
    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
0
}
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
0
{
3454
    /* Note that much of the VPS is initialized by determineLevel() */
3455
0
    vps->ptl.progressiveSourceFlag = !m_param->interlaceMode;
3456
0
    vps->ptl.interlacedSourceFlag = !!m_param->interlaceMode;
3457
0
    vps->ptl.nonPackedConstraintFlag = false;
3458
0
    vps->ptl.frameOnlyConstraintFlag = !m_param->interlaceMode;
3459
0
    vps->m_numLayers = m_param->numScalableLayers;
3460
0
    vps->m_numViews = m_param->numViews;
3461
0
    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
0
}
3556
3557
void Encoder::initSPS(SPS *sps)
3558
0
{
3559
0
    sps->conformanceWindow = m_conformanceWindow;
3560
0
    sps->chromaFormatIdc = m_param->internalCsp;
3561
0
    sps->picWidthInLumaSamples = m_param->sourceWidth;
3562
0
    sps->picHeightInLumaSamples = m_param->sourceHeight;
3563
0
    sps->numCuInWidth = (m_param->sourceWidth + m_param->maxCUSize - 1) / m_param->maxCUSize;
3564
0
    sps->numCuInHeight = (m_param->sourceHeight + m_param->maxCUSize - 1) / m_param->maxCUSize;
3565
0
    sps->numCUsInFrame = sps->numCuInWidth * sps->numCuInHeight;
3566
0
    sps->numPartitions = m_param->num4x4Partitions;
3567
0
    sps->numPartInCUSize = 1 << m_param->unitSizeDepth;
3568
3569
0
    sps->log2MinCodingBlockSize = m_param->maxLog2CUSize - m_param->maxCUDepth;
3570
0
    sps->log2DiffMaxMinCodingBlockSize = m_param->maxCUDepth;
3571
0
    uint32_t maxLog2TUSize = (uint32_t)g_log2Size[m_param->maxTUSize];
3572
0
    sps->quadtreeTULog2MaxSize = X265_MIN((uint32_t)m_param->maxLog2CUSize, maxLog2TUSize);
3573
0
    sps->quadtreeTULog2MinSize = 2;
3574
0
    sps->quadtreeTUMaxDepthInter = m_param->tuQTMaxInterDepth;
3575
0
    sps->quadtreeTUMaxDepthIntra = m_param->tuQTMaxIntraDepth;
3576
3577
0
    sps->bUseSAO = m_param->bEnableSAO;
3578
3579
0
    sps->bUseAMP = m_param->bEnableAMP;
3580
0
    sps->maxAMPDepth = m_param->bEnableAMP ? m_param->maxCUDepth : 0;
3581
3582
0
    sps->maxTempSubLayers = m_vps.maxTempSubLayers;// Getting the value from the user
3583
3584
0
    for(uint8_t i = 0; i < sps->maxTempSubLayers; i++)
3585
0
    {
3586
0
        sps->maxDecPicBuffering[i] = m_vps.maxDecPicBuffering[i];
3587
0
        sps->numReorderPics[i] = m_vps.numReorderPics[i];
3588
0
        sps->maxLatencyIncrease[i] = m_vps.maxLatencyIncrease[i] = m_param->bframes;
3589
0
    }
3590
3591
0
    sps->bUseStrongIntraSmoothing = m_param->bEnableStrongIntraSmoothing;
3592
0
    sps->bTemporalMVPEnabled = m_param->bEnableTemporalMvp;
3593
0
    sps->bEmitVUITimingInfo = m_param->bEmitVUITimingInfo;
3594
0
    sps->bEmitVUIHRDInfo = m_param->bEmitVUIHRDInfo;
3595
0
    sps->log2MaxPocLsb = m_param->log2MaxPocLsb;
3596
0
    int maxDeltaPOC = (m_param->bframes + 2) * (!!m_param->bBPyramid + 1) * 2;
3597
0
    while ((1 << sps->log2MaxPocLsb) <= maxDeltaPOC * 2)
3598
0
        sps->log2MaxPocLsb++;
3599
3600
0
    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
0
    VUI& vui = sps->vuiParameters;
3604
0
    vui.aspectRatioInfoPresentFlag = !!m_param->vui.aspectRatioIdc;
3605
0
    vui.aspectRatioIdc = m_param->vui.aspectRatioIdc;
3606
0
    vui.sarWidth = m_param->vui.sarWidth;
3607
0
    vui.sarHeight = m_param->vui.sarHeight;
3608
3609
0
    vui.overscanInfoPresentFlag = m_param->vui.bEnableOverscanInfoPresentFlag;
3610
0
    vui.overscanAppropriateFlag = m_param->vui.bEnableOverscanAppropriateFlag;
3611
3612
0
    vui.videoSignalTypePresentFlag = m_param->vui.bEnableVideoSignalTypePresentFlag;
3613
0
    vui.videoFormat = m_param->vui.videoFormat;
3614
0
    vui.videoFullRangeFlag = m_param->vui.bEnableVideoFullRangeFlag;
3615
3616
0
    vui.colourDescriptionPresentFlag = m_param->vui.bEnableColorDescriptionPresentFlag;
3617
0
    vui.colourPrimaries = m_param->vui.colorPrimaries;
3618
0
    vui.transferCharacteristics = m_param->vui.transferCharacteristics;
3619
0
    vui.matrixCoefficients = m_param->vui.matrixCoeffs;
3620
3621
0
    vui.chromaLocInfoPresentFlag = m_param->vui.bEnableChromaLocInfoPresentFlag;
3622
0
    vui.chromaSampleLocTypeTopField = m_param->vui.chromaSampleLocTypeTopField;
3623
0
    vui.chromaSampleLocTypeBottomField = m_param->vui.chromaSampleLocTypeBottomField;
3624
3625
0
    vui.defaultDisplayWindow.bEnabled = m_param->vui.bEnableDefaultDisplayWindowFlag;
3626
0
    vui.defaultDisplayWindow.rightOffset = m_param->vui.defDispWinRightOffset;
3627
0
    vui.defaultDisplayWindow.topOffset = m_param->vui.defDispWinTopOffset;
3628
0
    vui.defaultDisplayWindow.bottomOffset = m_param->vui.defDispWinBottomOffset;
3629
0
    vui.defaultDisplayWindow.leftOffset = m_param->vui.defDispWinLeftOffset;
3630
3631
0
    vui.frameFieldInfoPresentFlag = !!m_param->interlaceMode || (m_param->pictureStructure >= 0);
3632
0
    vui.fieldSeqFlag = !!m_param->interlaceMode;
3633
3634
0
    vui.hrdParametersPresentFlag = m_param->bEmitHRDSEI;
3635
3636
0
    vui.timingInfo.numUnitsInTick = m_param->fpsDenom;
3637
0
    vui.timingInfo.timeScale = m_param->fpsNum;
3638
0
    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
0
}
3657
3658
void Encoder::initPPS(PPS *pps)
3659
0
{
3660
0
    bool bIsVbv = m_param->rc.vbvBufferSize > 0 && m_param->rc.vbvMaxBitrate > 0;
3661
0
    bool bEnableDistOffset = m_param->analysisMultiPassDistortion && m_param->rc.bStatRead;
3662
3663
0
    if (!m_param->bLossless && (m_param->rc.aqMode || bIsVbv || m_param->bAQMotion))
3664
0
    {
3665
0
        pps->bUseDQP = true;
3666
0
        pps->maxCuDQPDepth = g_log2Size[m_param->maxCUSize] - g_log2Size[m_param->rc.qgSize];
3667
0
        X265_CHECK(pps->maxCuDQPDepth <= 3, "max CU DQP depth cannot be greater than 3\n");
3668
0
    }
3669
0
    else if (!m_param->bLossless && bEnableDistOffset)
3670
0
    {
3671
0
        pps->bUseDQP = true;
3672
0
        pps->maxCuDQPDepth = 0;
3673
0
    }
3674
0
    else
3675
0
    {
3676
0
        pps->bUseDQP = false;
3677
0
        pps->maxCuDQPDepth = 0;
3678
0
    }
3679
3680
0
    pps->chromaQpOffset[0] = m_param->cbQpOffset;
3681
0
    pps->chromaQpOffset[1] = m_param->crQpOffset;
3682
0
    pps->pps_slice_chroma_qp_offsets_present_flag = m_param->bHDR10Opt;
3683
3684
0
    pps->bConstrainedIntraPred = m_param->bEnableConstrainedIntra;
3685
0
    pps->bUseWeightPred = m_param->bEnableWeightedPred;
3686
0
    pps->bUseWeightedBiPred = m_param->bEnableWeightedBiPred;
3687
0
    pps->bTransquantBypassEnabled = m_param->bCULossless || m_param->bLossless;
3688
0
    pps->bTransformSkipEnabled = m_param->bEnableTransformSkip;
3689
0
    pps->bSignHideEnabled = m_param->bEnableSignHiding;
3690
3691
0
    pps->bDeblockingFilterControlPresent = !m_param->bEnableLoopFilter || m_param->deblockingFilterBetaOffset || m_param->deblockingFilterTCOffset;
3692
0
    pps->bPicDisableDeblockingFilter = !m_param->bEnableLoopFilter;
3693
0
    pps->deblockingFilterBetaOffsetDiv2 = m_param->deblockingFilterBetaOffset;
3694
0
    pps->deblockingFilterTcOffsetDiv2 = m_param->deblockingFilterTCOffset;
3695
3696
0
    pps->bEntropyCodingSyncEnabled = m_param->bEnableWavefront;
3697
3698
0
    pps->numRefIdxDefault[0] = 1 + !!m_param->bEnableSCC;;
3699
0
    pps->numRefIdxDefault[1] = 1;
3700
0
    pps->pps_extension_flag = false;
3701
0
    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
0
}
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
0
{
3861
0
    this->m_param = p;
3862
0
    if (p->bAnalysisType == AVC_INFO)
3863
0
        this->m_externalFlush = true;
3864
0
    else 
3865
0
        this->m_externalFlush = false;
3866
3867
0
    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
0
    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
0
    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
0
    else if (p->keyframeMax <= 1)
3888
0
    {
3889
0
        p->keyframeMax = 1;
3890
3891
        // disable lookahead for all-intra encodes
3892
0
        p->bFrameAdaptive = 0;
3893
0
        p->bframes = 0;
3894
0
        p->bOpenGOP = 0;
3895
0
        p->bRepeatHeaders = 1;
3896
0
        p->lookaheadDepth = 0;
3897
0
        p->bframes = 0;
3898
0
        p->scenecutThreshold = 0;
3899
0
        p->bHistBasedSceneCut = 0;
3900
0
        p->bFrameAdaptive = 0;
3901
0
        p->rc.cuTree = 0;
3902
0
        p->bEnableWeightedPred = 0;
3903
0
        p->bEnableWeightedBiPred = 0;
3904
0
        p->bIntraRefresh = 0;
3905
3906
        /* SPSs shall have sps_max_dec_pic_buffering_minus1[ sps_max_sub_layers_minus1 ] equal to 0 only */
3907
0
        p->maxNumReferences = 1;
3908
0
    }
3909
0
    if (!p->keyframeMin)
3910
0
    {
3911
0
        double fps = (double)p->fpsNum / p->fpsDenom;
3912
0
        p->keyframeMin = X265_MIN((int)fps, p->keyframeMax / 10);
3913
0
    }
3914
0
    p->keyframeMin = X265_MAX(1, p->keyframeMin);
3915
3916
0
    if (!p->bframes)
3917
0
        p->bBPyramid = 0;
3918
0
    if (!p->rdoqLevel)
3919
0
        p->psyRdoq = 0;
3920
3921
0
    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
0
    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
0
    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
0
    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
0
    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
0
    if (p->bLossless)
3965
0
    {
3966
0
        p->rc.rateControlMode = X265_RC_CQP;
3967
0
        p->rc.qp = 4; // An oddity, QP=4 is more lossless than QP=0 and gives better lambdas
3968
0
        p->bEnableSsim = 0;
3969
0
        p->bEnablePsnr = 0;
3970
0
    }
3971
3972
0
    if (p->rc.rateControlMode == X265_RC_CQP)
3973
0
    {
3974
0
        p->rc.aqMode = X265_AQ_NONE;
3975
0
        p->rc.hevcAq = 0;
3976
0
        p->rc.bitrate = 0;
3977
0
        p->rc.cuTree = 0;
3978
0
        p->rc.aqStrength = 0;
3979
0
    }
3980
3981
0
    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
0
    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
0
    if (p->maxTUSize > p->maxCUSize)
3994
0
    {
3995
0
        x265_log(p, X265_LOG_WARNING, "Max TU size should be less than or equal to max CU size, setting max TU size = %d\n", p->maxCUSize);
3996
0
        p->maxTUSize = p->maxCUSize;
3997
0
    }
3998
0
    if (p->rc.aqStrength == 0 && p->rc.cuTree == 0)
3999
0
    {
4000
0
        p->rc.aqMode = X265_AQ_NONE;
4001
0
        p->rc.hevcAq = 0;
4002
0
    }
4003
0
    if (p->rc.aqMode == X265_AQ_NONE && p->rc.cuTree == 0)
4004
0
        p->rc.aqStrength = 0;
4005
0
    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
0
    if (p->totalFrames && p->totalFrames <= 2 * ((float)p->fpsNum) / p->fpsDenom && p->rc.bStrictCbr)
4011
0
        p->lookaheadDepth = p->totalFrames;
4012
0
    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
0
    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
0
    if (!p->selectiveSAO && p->bEnableSAO)
4047
0
        p->selectiveSAO = 4;
4048
4049
0
    if (p->interlaceMode)
4050
0
        x265_log(p, X265_LOG_WARNING, "Support for interlaced video is experimental\n");
4051
4052
0
    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
0
    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
0
    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
0
    if (strlen(p->analysisSave) && !p->analysisSaveReuseLevel)
4073
0
        p->analysisSaveReuseLevel = 5;
4074
4075
0
    if (strlen(p->analysisLoad) && !p->analysisLoadReuseLevel)
4076
0
        p->analysisLoadReuseLevel = 5;
4077
4078
0
    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
0
    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
0
    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
0
    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
0
    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
0
    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
0
    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
0
    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
0
    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
0
    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
0
    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
0
    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
0
    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
0
    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
0
    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
0
    if (p->bEnableTemporalSubLayers > 2)
4189
0
            p->bframes = x265_temporal_layer_bframes[p->bEnableTemporalSubLayers - 1];
4190
4191
0
    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
0
    m_bframeDelay = p->bframes ? (p->bBPyramid ? 2 : 1) : 0;
4201
4202
0
    p->bFrameBias = X265_MIN(X265_MAX(-90, p->bFrameBias), 100);
4203
0
    p->scenecutBias = (double)(p->scenecutBias / 100);
4204
4205
0
    if (p->logLevel < X265_LOG_INFO)
4206
0
    {
4207
        /* don't measure these metrics if they will not be reported */
4208
0
        p->bEnablePsnr = 0;
4209
0
        p->bEnableSsim = 0;
4210
0
    }
4211
    /* Warn users trying to measure PSNR/SSIM with psy opts on. */
4212
0
    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
0
    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
0
    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
0
    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
0
    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
0
    if (!p->rc.bStatRead || p->rc.rateControlMode != X265_RC_CRF)
4259
0
    {
4260
0
        p->rc.bEncFocusedFramesOnly = 0;
4261
0
    }
4262
4263
    /* some options make no sense if others are disabled */
4264
0
    p->bSaoNonDeblocked &= p->bEnableSAO;
4265
0
    p->bEnableTSkipFast &= p->bEnableTransformSkip;
4266
0
    p->bLimitSAO &= p->bEnableSAO;
4267
4268
0
    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
0
                                      " Offsets are shared in the analysis file already.\n");
4271
    /* initialize the conformance window */
4272
0
    m_conformanceWindow.bEnabled = false;
4273
0
    m_conformanceWindow.rightOffset = 0;
4274
0
    m_conformanceWindow.topOffset = 0;
4275
0
    m_conformanceWindow.bottomOffset = 0;
4276
0
    m_conformanceWindow.leftOffset = 0;
4277
4278
0
    uint32_t padsize = 0;
4279
0
    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
0
    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
0
    else if (p->sourceWidth & (p->minCUSize - 1))
4337
0
    {
4338
0
        uint32_t rem = p->sourceWidth & (p->minCUSize - 1);
4339
0
        padsize = p->minCUSize - rem;
4340
0
        p->sourceWidth += padsize;
4341
4342
0
        m_conformanceWindow.bEnabled = true;
4343
0
        m_conformanceWindow.rightOffset = padsize;
4344
0
    }
4345
4346
0
    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
0
    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
0
    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
0
    bool bIsVbv = m_param->rc.vbvBufferSize > 0 && m_param->rc.vbvMaxBitrate > 0;
4364
0
    if (!m_param->bLossless && (m_param->rc.aqMode || bIsVbv || m_param->bAQMotion))
4365
0
    {
4366
0
        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
0
        if (p->rc.qgSize > p->maxCUSize)
4372
0
        {
4373
0
            p->rc.qgSize = p->maxCUSize;
4374
0
            x265_log(p, X265_LOG_WARNING, "QGSize should be less than or equal to maxCUSize, setting QGSize = %d\n", p->rc.qgSize);
4375
0
        }
4376
0
    }
4377
0
    else
4378
0
        m_param->rc.qgSize = p->maxCUSize;
4379
4380
0
    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
0
    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
0
    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
0
    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
0
    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
0
    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
0
    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
0
#endif
4443
4444
0
    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
0
    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
0
    else if(p->sourceHeight & (p->minCUSize - 1))
4556
0
    {
4557
0
        uint32_t rem = p->sourceHeight & (p->minCUSize - 1);
4558
0
        padsize = p->minCUSize - rem;
4559
0
        p->sourceHeight += padsize;
4560
0
        m_conformanceWindow.bEnabled = true;
4561
0
        m_conformanceWindow.bottomOffset = padsize;
4562
0
    }
4563
4564
0
    if (p->bLogCuStats)
4565
0
        x265_log(p, X265_LOG_WARNING, "--cu-stats option is now deprecated\n");
4566
4567
0
    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
0
    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
0
    const uint32_t numRows = (p->sourceHeight + p->maxCUSize - 1) / p->maxCUSize;
4579
0
    const uint32_t slicesLimit = X265_MIN(numRows, NALList::MAX_NAL_UNITS - 1);
4580
0
    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
0
    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
0
    if (strlen(p->videoSignalTypePreset))     // Default disabled.
4600
0
        configureVideoSignalTypePreset(p);
4601
4602
0
    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
0
    p->maxLog2CUSize = g_log2Size[p->maxCUSize];
4612
0
    p->maxCUDepth    = p->maxLog2CUSize - g_log2Size[p->minCUSize];
4613
0
    p->unitSizeDepth = p->maxLog2CUSize - LOG2_UNIT_SIZE;
4614
0
    p->num4x4Partitions = (1U << (p->unitSizeDepth << 1));
4615
4616
0
    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
0
    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
0
    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
0
    if (p->dolbyProfile)     // Default disabled.
4635
0
        configureDolbyVisionParams(p);
4636
4637
0
    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
0
    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
0
    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
0
    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
0
    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
0
    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
0
    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
0
    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
0
}
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