Coverage Report

Created: 2022-08-24 06:15

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