Coverage Report

Created: 2026-04-01 07:49

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