Coverage Report

Created: 2026-03-08 06:41

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