Coverage Report

Created: 2026-03-08 06:41

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