Coverage Report

Created: 2026-03-08 06:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/x265/source/common/frame.cpp
Line
Count
Source
1
/*****************************************************************************
2
* Copyright (C) 2013-2020 MulticoreWare, Inc
3
*
4
* Author: Steve Borho <steve@borho.org>
5
*         Min Chen <chenm003@163.com>
6
*
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; either version 2 of the License, or
10
* (at your option) any later version.
11
*
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
* GNU General Public License for more details.
16
*
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
20
*
21
* This program is also available under a commercial proprietary license.
22
* For more information, contact us at license @ x265.com.
23
*****************************************************************************/
24
25
#include "common.h"
26
#include "frame.h"
27
#include "picyuv.h"
28
#include "framedata.h"
29
30
using namespace X265_NS;
31
32
Frame::Frame()
33
654
{
34
654
    m_bChromaExtended = false;
35
654
    m_lowresInit = false;
36
654
    m_reconRowFlag = NULL;
37
654
    m_reconColCount = NULL;
38
654
    m_countRefEncoders = 0;
39
654
    m_ctuMEFlags = NULL;
40
654
    m_encData = NULL;
41
1.30k
    for (int i = 0; i < NUM_RECON_VERSION; i++)
42
654
        m_reconPic[i] = NULL;
43
654
    m_quantOffsets = NULL;
44
654
    m_next = NULL;
45
654
    m_prev = NULL;
46
654
    m_param = NULL;
47
654
    m_userSEI.numPayloads = 0;
48
654
    m_userSEI.payloads = NULL;
49
654
    m_rpu.payloadSize = 0;
50
654
    m_rpu.payload = NULL;
51
654
    memset(&m_lowres, 0, sizeof(m_lowres));
52
654
    m_rcData = NULL;
53
654
    m_encodeStartTime = 0;
54
654
    m_reconfigureRc = false;
55
654
    m_ctuInfo = NULL;
56
654
    m_prevCtuInfoChange = NULL;
57
654
    m_addOnDepth = NULL;
58
654
    m_addOnCtuInfo = NULL;
59
654
    m_addOnPrevChange = NULL;
60
654
    m_classifyFrame = false;
61
654
    m_fieldNum = 0;
62
654
    m_picStruct = 0;
63
654
    m_edgePic = NULL;
64
654
    m_gaussianPic = NULL;
65
654
    m_thetaPic = NULL;
66
654
    m_edgeBitPlane = NULL;
67
654
    m_edgeBitPic = NULL;
68
654
    m_isInsideWindow = 0;
69
70
    // mcstf
71
654
    m_isSubSampled = NULL;
72
654
    m_mcstf = NULL;
73
654
    m_refPicCnt[0] = 0;
74
654
    m_refPicCnt[1] = 0;
75
654
    m_nextMCSTF = NULL;
76
654
    m_prevMCSTF = NULL;
77
78
654
    m_tempLayer = 0;
79
654
    m_sameLayerRefPic = false;
80
81
654
    m_viewId = 0;
82
654
    m_valid = 0;
83
654
    m_nextSubDPB = NULL;
84
654
    m_prevSubDPB = NULL;
85
86
654
    m_targetBitrate = 0;
87
654
    m_targetCrf = 0;
88
654
    m_targetQp = 0;
89
654
}
90
91
bool Frame::create(x265_param *param, float* quantOffsets)
92
654
{
93
654
    m_fencPic = new PicYuv;
94
654
    m_param = param;
95
96
654
    if (m_param->bEnableTemporalFilter)
97
0
    {
98
0
        m_mcstf = new TemporalFilter;
99
0
        m_mcstffencPic = new PicYuv;
100
0
        m_mcstf->m_range = param->mcstfFrameRange;
101
0
        m_mcstf->init(param);
102
103
0
        for (int i = 0; i < (m_mcstf->m_range << 1); i++)
104
0
            m_mcstf->createRefPicInfo(&m_mcstfRefList[i], m_param);
105
106
0
        m_fencPicSubsampled2 = new PicYuv;
107
0
        m_fencPicSubsampled4 = new PicYuv;
108
109
0
        if (!m_fencPicSubsampled2->createScaledPicYUV(param, 2))
110
0
            return false;
111
0
        if (!m_fencPicSubsampled4->createScaledPicYUV(param, 4))
112
0
            return false;
113
114
0
        m_mcstffencPic->create(param, !!m_param->bCopyPicToFrame);
115
0
        CHECKED_MALLOC_ZERO(m_isSubSampled, int, 1);
116
0
    }
117
118
654
    CHECKED_MALLOC_ZERO(m_rcData, RcStats, 1);
119
120
654
    if (param->bCTUInfo)
121
0
    {
122
0
        uint32_t widthInCTU = (m_param->sourceWidth + param->maxCUSize - 1) >> m_param->maxLog2CUSize;
123
0
        uint32_t heightInCTU = (m_param->sourceHeight +  param->maxCUSize - 1) >> m_param->maxLog2CUSize;
124
0
        uint32_t numCTUsInFrame = widthInCTU * heightInCTU;
125
0
        CHECKED_MALLOC_ZERO(m_addOnDepth, uint8_t *, numCTUsInFrame);
126
0
        CHECKED_MALLOC_ZERO(m_addOnCtuInfo, uint8_t *, numCTUsInFrame);
127
0
        CHECKED_MALLOC_ZERO(m_addOnPrevChange, int *, numCTUsInFrame);
128
0
        for (uint32_t i = 0; i < numCTUsInFrame; i++)
129
0
        {
130
0
            CHECKED_MALLOC_ZERO(m_addOnDepth[i], uint8_t, uint32_t(param->num4x4Partitions));
131
0
            CHECKED_MALLOC_ZERO(m_addOnCtuInfo[i], uint8_t, uint32_t(param->num4x4Partitions));
132
0
            CHECKED_MALLOC_ZERO(m_addOnPrevChange[i], int, uint32_t(param->num4x4Partitions));
133
0
        }
134
0
    }
135
136
    //if (param->bAnalysisType == AVC_INFO)
137
654
    {
138
654
        m_analysisData.wt = NULL;
139
654
        m_analysisData.intraData = NULL;
140
654
        m_analysisData.interData = NULL;
141
654
        m_analysisData.distortionData = NULL;
142
654
    }
143
144
654
    if (param->bDynamicRefine)
145
0
    {
146
0
        int size = m_param->maxCUDepth * X265_REFINE_INTER_LEVELS;
147
0
        CHECKED_MALLOC_ZERO(m_classifyRd, uint64_t, size);
148
0
        CHECKED_MALLOC_ZERO(m_classifyVariance, uint64_t, size);
149
0
        CHECKED_MALLOC_ZERO(m_classifyCount, uint32_t, size);
150
0
    }
151
152
654
    if (param->rc.aqMode == X265_AQ_EDGE || (param->rc.zonefileCount && param->rc.aqMode != 0))
153
0
    {
154
0
        uint32_t numCuInWidth = (param->sourceWidth + param->maxCUSize - 1) / param->maxCUSize;
155
0
        uint32_t numCuInHeight = (param->sourceHeight + param->maxCUSize - 1) / param->maxCUSize;
156
0
        uint32_t m_lumaMarginX = param->maxCUSize + 32; // search margin and 8-tap filter half-length, padded for 32-byte alignment
157
0
        uint32_t m_lumaMarginY = param->maxCUSize + 16; // margin for 8-tap filter and infinite padding
158
0
        intptr_t m_stride = (numCuInWidth * param->maxCUSize) + (m_lumaMarginX << 1);
159
0
        int maxHeight = numCuInHeight * param->maxCUSize;
160
161
0
        m_edgePic = X265_MALLOC(pixel, m_stride * (maxHeight + (m_lumaMarginY * 2)));
162
0
        m_gaussianPic = X265_MALLOC(pixel, m_stride * (maxHeight + (m_lumaMarginY * 2)));
163
0
        m_thetaPic = X265_MALLOC(pixel, m_stride * (maxHeight + (m_lumaMarginY * 2)));
164
0
    }
165
166
654
    if (param->recursionSkipMode == EDGE_BASED_RSKIP)
167
0
    {
168
0
        uint32_t numCuInWidth = (param->sourceWidth + param->maxCUSize - 1) / param->maxCUSize;
169
0
        uint32_t numCuInHeight = (param->sourceHeight + param->maxCUSize - 1) / param->maxCUSize;
170
0
        uint32_t lumaMarginX = param->maxCUSize + 32;
171
0
        uint32_t lumaMarginY = param->maxCUSize + 16;
172
0
        uint32_t stride = (numCuInWidth * param->maxCUSize) + (lumaMarginX << 1);
173
0
        uint32_t maxHeight = numCuInHeight * param->maxCUSize;
174
0
        uint32_t bitPlaneSize = stride * (maxHeight + (lumaMarginY * 2));
175
0
        CHECKED_MALLOC_ZERO(m_edgeBitPlane, pixel, bitPlaneSize);
176
0
        m_edgeBitPic = m_edgeBitPlane + lumaMarginY * stride + lumaMarginX;
177
0
    }
178
179
654
    if (m_fencPic->create(param, !!m_param->bCopyPicToFrame) && m_lowres.create(param, m_fencPic, param->rc.qgSize))
180
654
    {
181
654
        X265_CHECK((m_reconColCount == NULL), "m_reconColCount was initialized");
182
654
        m_numRows = (m_fencPic->m_picHeight + param->maxCUSize - 1)  / param->maxCUSize;
183
654
        int32_t m_numCols = (m_fencPic->m_picWidth + param->maxCUSize - 1)  / param->maxCUSize;
184
654
        m_reconRowFlag = new ThreadSafeInteger[m_numRows];
185
654
        m_reconColCount = new ThreadSafeInteger[m_numRows];
186
654
        m_ctuMEFlags = new ThreadSafeInteger[m_numRows * m_numCols];
187
654
        if (quantOffsets)
188
0
        {
189
0
            int32_t cuCount = (param->rc.qgSize == 8) ? m_lowres.maxBlocksInRowFullRes * m_lowres.maxBlocksInColFullRes :
190
0
                                                        m_lowres.maxBlocksInRow * m_lowres.maxBlocksInCol;
191
0
            m_quantOffsets = new float[cuCount];
192
0
        }
193
654
        return true;
194
654
    }
195
0
    return false;
196
0
fail:
197
0
    return false;
198
654
}
199
200
bool Frame::createSubSample()
201
0
{
202
203
0
    m_fencPicSubsampled2 = new PicYuv;
204
0
    m_fencPicSubsampled4 = new PicYuv;
205
206
0
    if (!m_fencPicSubsampled2->createScaledPicYUV(m_param, 2))
207
0
        return false;
208
0
    if (!m_fencPicSubsampled4->createScaledPicYUV(m_param, 4))
209
0
        return false;
210
0
    CHECKED_MALLOC_ZERO(m_isSubSampled, int, 1);
211
0
    return true;
212
0
fail:
213
0
    return false;
214
0
}
215
216
bool Frame::allocEncodeData(x265_param *param, const SPS& sps)
217
654
{
218
654
    m_encData = new FrameData;
219
654
    m_param = param;
220
1.30k
    for (int i = 0; i < !!m_param->bEnableSCC + 1; i++)
221
654
    {
222
654
        m_reconPic[i] = new PicYuv;
223
654
        m_encData->m_reconPic[i] = m_reconPic[i];
224
654
    }
225
654
    bool ok = m_encData->create(*param, sps, m_fencPic->m_picCsp) && m_reconPic[0]->create(param) && (param->bEnableSCC ? (param->bEnableSCC && m_reconPic[1]->create(param)) : 1);
226
654
    if (ok)
227
654
    {
228
        /* initialize right border of m_reconPicYuv as SAO may read beyond the
229
         * end of the picture accessing uninitialized pixels */
230
654
        int maxHeight = sps.numCuInHeight * param->maxCUSize;
231
654
        memset(m_reconPic[0]->m_picOrg[0], 0, sizeof(pixel)* m_reconPic[0]->m_stride * maxHeight);
232
233
1.30k
        for (int i = 0; i < !!m_param->bEnableSCC + 1; i++)
234
654
        {
235
            /* use pre-calculated cu/pu offsets cached in the SPS structure */
236
654
            m_reconPic[i]->m_cuOffsetY = sps.cuOffsetY;
237
654
            m_reconPic[i]->m_buOffsetY = sps.buOffsetY;
238
239
654
            if (param->internalCsp != X265_CSP_I400)
240
654
            {
241
654
                memset(m_reconPic[i]->m_picOrg[1], 0, sizeof(pixel) * m_reconPic[i]->m_strideC * (maxHeight >> m_reconPic[i]->m_vChromaShift));
242
654
                memset(m_reconPic[i]->m_picOrg[2], 0, sizeof(pixel) * m_reconPic[i]->m_strideC * (maxHeight >> m_reconPic[i]->m_vChromaShift));
243
244
                /* use pre-calculated cu/pu offsets cached in the SPS structure */
245
654
                m_reconPic[i]->m_cuOffsetC = sps.cuOffsetC;
246
654
                m_reconPic[i]->m_buOffsetC = sps.buOffsetC;
247
654
            }
248
654
        }
249
654
    }
250
654
    return ok;
251
654
}
252
253
/* prepare to re-use a FrameData instance to encode a new picture */
254
void Frame::reinit(const SPS& sps)
255
0
{
256
0
    m_bChromaExtended = false;
257
0
    for (int i = 0; i < !!m_param->bEnableSCC + 1; i++)
258
0
        m_reconPic[i] = m_encData->m_reconPic[i];
259
0
    m_encData->reinit(sps);
260
0
}
261
262
void Frame::destroy()
263
654
{
264
654
    if (m_encData)
265
654
    {
266
654
        m_encData->destroy();
267
654
        delete m_encData;
268
654
        m_encData = NULL;
269
654
    }
270
271
#if ENABLE_MULTIVIEW
272
    //Destroy interlayer References
273
    if (refPicSetInterLayer0.size())
274
    {
275
        Frame* iterFrame = refPicSetInterLayer0.first();
276
277
        while (iterFrame)
278
        {
279
            Frame* curFrame = iterFrame;
280
            iterFrame = iterFrame->m_nextSubDPB;
281
            refPicSetInterLayer0.removeSubDPB(*curFrame);
282
            iterFrame = refPicSetInterLayer0.first();
283
        }
284
    }
285
286
    if (refPicSetInterLayer1.size())
287
    {
288
        Frame* iterFrame = refPicSetInterLayer1.first();
289
290
        while (iterFrame)
291
        {
292
            Frame* curFrame = iterFrame;
293
            iterFrame = iterFrame->m_nextSubDPB;
294
            refPicSetInterLayer1.removeSubDPB(*curFrame);
295
            iterFrame = refPicSetInterLayer1.first();
296
        }
297
    }
298
#endif
299
300
654
    if (m_fencPic)
301
654
    {
302
654
        if (m_param->bCopyPicToFrame)
303
654
            m_fencPic->destroy();
304
654
        delete m_fencPic;
305
654
        m_fencPic = NULL;
306
654
    }
307
308
654
    if (m_param->bEnableTemporalFilter)
309
0
    {
310
311
0
        if (m_fencPicSubsampled2)
312
0
        {
313
0
            m_fencPicSubsampled2->destroy();
314
0
            delete m_fencPicSubsampled2;
315
0
            m_fencPicSubsampled2 = NULL;
316
0
        }
317
318
0
        if (m_fencPicSubsampled4)
319
0
        {
320
0
            m_fencPicSubsampled4->destroy();
321
0
            delete m_fencPicSubsampled4;
322
0
            m_fencPicSubsampled4 = NULL;
323
0
        }
324
325
0
        delete m_mcstf->m_metld;
326
0
        m_mcstf->m_metld = NULL;
327
0
        for (int i = 0; i < (m_mcstf->m_range << 1); i++)
328
0
            m_mcstf->destroyRefPicInfo(&m_mcstfRefList[i]);
329
330
0
        if (m_mcstffencPic)
331
0
        {
332
0
            m_mcstffencPic->destroy();
333
0
            delete m_mcstffencPic;
334
0
            m_mcstffencPic = NULL;
335
0
        }
336
337
0
        delete m_mcstf;
338
0
        X265_FREE(m_isSubSampled);
339
0
    }
340
341
1.30k
    for (int i = 0; i < !!m_param->bEnableSCC + 1; i++)
342
654
    {
343
654
        if (m_reconPic[i])
344
654
        {
345
654
            m_reconPic[i]->destroy();
346
654
            delete m_reconPic[i];
347
654
            m_reconPic[i] = NULL;
348
654
        }
349
654
    }
350
351
654
    if (m_reconRowFlag)
352
654
    {
353
654
        delete[] m_reconRowFlag;
354
654
        m_reconRowFlag = NULL;
355
654
    }
356
357
654
    if (m_reconColCount)
358
654
    {
359
654
        delete[] m_reconColCount;
360
654
        m_reconColCount = NULL;
361
654
    }
362
363
654
    if (m_ctuMEFlags)
364
654
    {
365
654
        delete[] m_ctuMEFlags;
366
654
        m_ctuMEFlags = NULL;
367
654
    }
368
369
654
    if (m_quantOffsets)
370
0
    {
371
0
        delete[] m_quantOffsets;
372
0
    }
373
374
654
    if (m_userSEI.numPayloads)
375
0
    {
376
0
        for (int i = 0; i < m_userSEI.numPayloads; i++)
377
0
            delete[] m_userSEI.payloads[i].payload;
378
0
        delete[] m_userSEI.payloads;
379
0
    }
380
381
654
    if (m_ctuInfo)
382
0
    {
383
0
        uint32_t widthInCU = (m_param->sourceWidth + m_param->maxCUSize - 1) >> m_param->maxLog2CUSize;
384
0
        uint32_t heightInCU = (m_param->sourceHeight + m_param->maxCUSize - 1) >> m_param->maxLog2CUSize;
385
0
        uint32_t numCUsInFrame = widthInCU * heightInCU;
386
0
        for (uint32_t i = 0; i < numCUsInFrame; i++)
387
0
        {
388
0
            X265_FREE((*m_ctuInfo + i)->ctuInfo);
389
0
            (*m_ctuInfo + i)->ctuInfo = NULL;
390
0
            X265_FREE(m_addOnDepth[i]);
391
0
            m_addOnDepth[i] = NULL;
392
0
            X265_FREE(m_addOnCtuInfo[i]);
393
0
            m_addOnCtuInfo[i] = NULL;
394
0
            X265_FREE(m_addOnPrevChange[i]);
395
0
            m_addOnPrevChange[i] = NULL;
396
0
        }
397
0
        X265_FREE(*m_ctuInfo);
398
0
        *m_ctuInfo = NULL;
399
0
        X265_FREE(m_ctuInfo);
400
0
        m_ctuInfo = NULL;
401
0
        X265_FREE(m_prevCtuInfoChange);
402
0
        m_prevCtuInfoChange = NULL;
403
0
        X265_FREE(m_addOnDepth);
404
0
        m_addOnDepth = NULL;
405
0
        X265_FREE(m_addOnCtuInfo);
406
0
        m_addOnCtuInfo = NULL;
407
0
        X265_FREE(m_addOnPrevChange);
408
0
        m_addOnPrevChange = NULL;
409
0
    }
410
411
654
    m_lowres.destroy(m_param);
412
654
    X265_FREE(m_rcData);
413
414
654
    if (m_param->bDynamicRefine)
415
0
    {
416
0
        X265_FREE_ZERO(m_classifyRd);
417
0
        X265_FREE_ZERO(m_classifyVariance);
418
0
        X265_FREE_ZERO(m_classifyCount);
419
0
    }
420
421
654
    if (m_param->rc.aqMode == X265_AQ_EDGE || (m_param->rc.zonefileCount && m_param->rc.aqMode != 0))
422
0
    {
423
0
        X265_FREE(m_edgePic);
424
0
        X265_FREE(m_gaussianPic);
425
0
        X265_FREE(m_thetaPic);
426
0
    }
427
428
654
    if (m_param->recursionSkipMode == EDGE_BASED_RSKIP)
429
0
    {
430
0
        X265_FREE_ZERO(m_edgeBitPlane);
431
        m_edgeBitPic = NULL;
432
0
    }
433
654
}