Coverage Report

Created: 2025-08-11 08:01

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