Coverage Report

Created: 2026-08-31 06:22

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