Coverage Report

Created: 2025-07-23 08:18

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