Coverage Report

Created: 2022-08-24 06:17

/src/x265/source/common/frame.cpp
Line
Count
Source (jump to first uncovered line)
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
698
{
34
698
    m_bChromaExtended = false;
35
698
    m_lowresInit = false;
36
698
    m_reconRowFlag = NULL;
37
698
    m_reconColCount = NULL;
38
698
    m_countRefEncoders = 0;
39
698
    m_encData = NULL;
40
698
    m_reconPic = NULL;
41
698
    m_quantOffsets = NULL;
42
698
    m_next = NULL;
43
698
    m_prev = NULL;
44
698
    m_param = NULL;
45
698
    m_userSEI.numPayloads = 0;
46
698
    m_userSEI.payloads = NULL;
47
698
    m_rpu.payloadSize = 0;
48
698
    m_rpu.payload = NULL;
49
698
    memset(&m_lowres, 0, sizeof(m_lowres));
50
698
    m_rcData = NULL;
51
698
    m_encodeStartTime = 0;
52
698
    m_reconfigureRc = false;
53
698
    m_ctuInfo = NULL;
54
698
    m_prevCtuInfoChange = NULL;
55
698
    m_addOnDepth = NULL;
56
698
    m_addOnCtuInfo = NULL;
57
698
    m_addOnPrevChange = NULL;
58
698
    m_classifyFrame = false;
59
698
    m_fieldNum = 0;
60
698
    m_picStruct = 0;
61
698
    m_edgePic = NULL;
62
698
    m_gaussianPic = NULL;
63
698
    m_thetaPic = NULL;
64
698
    m_edgeBitPlane = NULL;
65
698
    m_edgeBitPic = NULL;
66
698
}
67
68
bool Frame::create(x265_param *param, float* quantOffsets)
69
698
{
70
698
    m_fencPic = new PicYuv;
71
698
    m_param = param;
72
698
    CHECKED_MALLOC_ZERO(m_rcData, RcStats, 1);
73
74
698
    if (param->bCTUInfo)
75
0
    {
76
0
        uint32_t widthInCTU = (m_param->sourceWidth + param->maxCUSize - 1) >> m_param->maxLog2CUSize;
77
0
        uint32_t heightInCTU = (m_param->sourceHeight +  param->maxCUSize - 1) >> m_param->maxLog2CUSize;
78
0
        uint32_t numCTUsInFrame = widthInCTU * heightInCTU;
79
0
        CHECKED_MALLOC_ZERO(m_addOnDepth, uint8_t *, numCTUsInFrame);
80
0
        CHECKED_MALLOC_ZERO(m_addOnCtuInfo, uint8_t *, numCTUsInFrame);
81
0
        CHECKED_MALLOC_ZERO(m_addOnPrevChange, int *, numCTUsInFrame);
82
0
        for (uint32_t i = 0; i < numCTUsInFrame; i++)
83
0
        {
84
0
            CHECKED_MALLOC_ZERO(m_addOnDepth[i], uint8_t, uint32_t(param->num4x4Partitions));
85
0
            CHECKED_MALLOC_ZERO(m_addOnCtuInfo[i], uint8_t, uint32_t(param->num4x4Partitions));
86
0
            CHECKED_MALLOC_ZERO(m_addOnPrevChange[i], int, uint32_t(param->num4x4Partitions));
87
0
        }
88
0
    }
89
90
698
    if (param->bAnalysisType == AVC_INFO)
91
0
    {
92
0
        m_analysisData.wt = NULL;
93
0
        m_analysisData.intraData = NULL;
94
0
        m_analysisData.interData = NULL;
95
0
        m_analysisData.distortionData = NULL;
96
0
    }
97
98
698
    if (param->bDynamicRefine)
99
0
    {
100
0
        int size = m_param->maxCUDepth * X265_REFINE_INTER_LEVELS;
101
0
        CHECKED_MALLOC_ZERO(m_classifyRd, uint64_t, size);
102
0
        CHECKED_MALLOC_ZERO(m_classifyVariance, uint64_t, size);
103
0
        CHECKED_MALLOC_ZERO(m_classifyCount, uint32_t, size);
104
0
    }
105
106
698
    if (param->rc.aqMode == X265_AQ_EDGE || (param->rc.zonefileCount && param->rc.aqMode != 0))
107
0
    {
108
0
        uint32_t numCuInWidth = (param->sourceWidth + param->maxCUSize - 1) / param->maxCUSize;
109
0
        uint32_t numCuInHeight = (param->sourceHeight + param->maxCUSize - 1) / param->maxCUSize;
110
0
        uint32_t m_lumaMarginX = param->maxCUSize + 32; // search margin and 8-tap filter half-length, padded for 32-byte alignment
111
0
        uint32_t m_lumaMarginY = param->maxCUSize + 16; // margin for 8-tap filter and infinite padding
112
0
        intptr_t m_stride = (numCuInWidth * param->maxCUSize) + (m_lumaMarginX << 1);
113
0
        int maxHeight = numCuInHeight * param->maxCUSize;
114
115
0
        m_edgePic = X265_MALLOC(pixel, m_stride * (maxHeight + (m_lumaMarginY * 2)));
116
0
        m_gaussianPic = X265_MALLOC(pixel, m_stride * (maxHeight + (m_lumaMarginY * 2)));
117
0
        m_thetaPic = X265_MALLOC(pixel, m_stride * (maxHeight + (m_lumaMarginY * 2)));
118
0
    }
119
120
698
    if (param->recursionSkipMode == EDGE_BASED_RSKIP)
121
0
    {
122
0
        uint32_t numCuInWidth = (param->sourceWidth + param->maxCUSize - 1) / param->maxCUSize;
123
0
        uint32_t numCuInHeight = (param->sourceHeight + param->maxCUSize - 1) / param->maxCUSize;
124
0
        uint32_t lumaMarginX = param->maxCUSize + 32;
125
0
        uint32_t lumaMarginY = param->maxCUSize + 16;
126
0
        uint32_t stride = (numCuInWidth * param->maxCUSize) + (lumaMarginX << 1);
127
0
        uint32_t maxHeight = numCuInHeight * param->maxCUSize;
128
0
        uint32_t bitPlaneSize = stride * (maxHeight + (lumaMarginY * 2));
129
0
        CHECKED_MALLOC_ZERO(m_edgeBitPlane, pixel, bitPlaneSize);
130
0
        m_edgeBitPic = m_edgeBitPlane + lumaMarginY * stride + lumaMarginX;
131
0
    }
132
133
698
    if (m_fencPic->create(param, !!m_param->bCopyPicToFrame) && m_lowres.create(param, m_fencPic, param->rc.qgSize))
134
698
    {
135
698
        X265_CHECK((m_reconColCount == NULL), "m_reconColCount was initialized");
136
698
        m_numRows = (m_fencPic->m_picHeight + param->maxCUSize - 1)  / param->maxCUSize;
137
698
        m_reconRowFlag = new ThreadSafeInteger[m_numRows];
138
698
        m_reconColCount = new ThreadSafeInteger[m_numRows];
139
140
698
        if (quantOffsets)
141
0
        {
142
0
            int32_t cuCount = (param->rc.qgSize == 8) ? m_lowres.maxBlocksInRowFullRes * m_lowres.maxBlocksInColFullRes :
143
0
                                                        m_lowres.maxBlocksInRow * m_lowres.maxBlocksInCol;
144
0
            m_quantOffsets = new float[cuCount];
145
0
        }
146
698
        return true;
147
698
    }
148
0
    return false;
149
0
fail:
150
0
    return false;
151
698
}
152
153
bool Frame::allocEncodeData(x265_param *param, const SPS& sps)
154
698
{
155
698
    m_encData = new FrameData;
156
698
    m_reconPic = new PicYuv;
157
698
    m_param = param;
158
698
    m_encData->m_reconPic = m_reconPic;
159
698
    bool ok = m_encData->create(*param, sps, m_fencPic->m_picCsp) && m_reconPic->create(param);
160
698
    if (ok)
161
698
    {
162
        /* initialize right border of m_reconpicYuv as SAO may read beyond the
163
         * end of the picture accessing uninitialized pixels */
164
698
        int maxHeight = sps.numCuInHeight * param->maxCUSize;
165
698
        memset(m_reconPic->m_picOrg[0], 0, sizeof(pixel)* m_reconPic->m_stride * maxHeight);
166
167
        /* use pre-calculated cu/pu offsets cached in the SPS structure */
168
698
        m_reconPic->m_cuOffsetY = sps.cuOffsetY;
169
698
        m_reconPic->m_buOffsetY = sps.buOffsetY;
170
171
698
        if (param->internalCsp != X265_CSP_I400)
172
698
        {
173
698
            memset(m_reconPic->m_picOrg[1], 0, sizeof(pixel) * m_reconPic->m_strideC * (maxHeight >> m_reconPic->m_vChromaShift));
174
698
            memset(m_reconPic->m_picOrg[2], 0, sizeof(pixel) * m_reconPic->m_strideC * (maxHeight >> m_reconPic->m_vChromaShift));
175
176
            /* use pre-calculated cu/pu offsets cached in the SPS structure */
177
698
            m_reconPic->m_cuOffsetC = sps.cuOffsetC;
178
698
            m_reconPic->m_buOffsetC = sps.buOffsetC;
179
698
        }
180
698
    }
181
698
    return ok;
182
698
}
183
184
/* prepare to re-use a FrameData instance to encode a new picture */
185
void Frame::reinit(const SPS& sps)
186
0
{
187
0
    m_bChromaExtended = false;
188
0
    m_reconPic = m_encData->m_reconPic;
189
0
    m_encData->reinit(sps);
190
0
}
191
192
void Frame::destroy()
193
698
{
194
698
    if (m_encData)
195
698
    {
196
698
        m_encData->destroy();
197
698
        delete m_encData;
198
698
        m_encData = NULL;
199
698
    }
200
201
698
    if (m_fencPic)
202
698
    {
203
698
        if (m_param->bCopyPicToFrame)
204
698
            m_fencPic->destroy();
205
698
        delete m_fencPic;
206
698
        m_fencPic = NULL;
207
698
    }
208
209
698
    if (m_reconPic)
210
698
    {
211
698
        m_reconPic->destroy();
212
698
        delete m_reconPic;
213
698
        m_reconPic = NULL;
214
698
    }
215
216
698
    if (m_reconRowFlag)
217
698
    {
218
698
        delete[] m_reconRowFlag;
219
698
        m_reconRowFlag = NULL;
220
698
    }
221
222
698
    if (m_reconColCount)
223
698
    {
224
698
        delete[] m_reconColCount;
225
698
        m_reconColCount = NULL;
226
698
    }
227
228
698
    if (m_quantOffsets)
229
0
    {
230
0
        delete[] m_quantOffsets;
231
0
    }
232
233
698
    if (m_userSEI.numPayloads)
234
0
    {
235
0
        for (int i = 0; i < m_userSEI.numPayloads; i++)
236
0
            delete[] m_userSEI.payloads[i].payload;
237
0
        delete[] m_userSEI.payloads;
238
0
    }
239
240
698
    if (m_ctuInfo)
241
0
    {
242
0
        uint32_t widthInCU = (m_param->sourceWidth + m_param->maxCUSize - 1) >> m_param->maxLog2CUSize;
243
0
        uint32_t heightInCU = (m_param->sourceHeight + m_param->maxCUSize - 1) >> m_param->maxLog2CUSize;
244
0
        uint32_t numCUsInFrame = widthInCU * heightInCU;
245
0
        for (uint32_t i = 0; i < numCUsInFrame; i++)
246
0
        {
247
0
            X265_FREE((*m_ctuInfo + i)->ctuInfo);
248
0
            (*m_ctuInfo + i)->ctuInfo = NULL;
249
0
            X265_FREE(m_addOnDepth[i]);
250
0
            m_addOnDepth[i] = NULL;
251
0
            X265_FREE(m_addOnCtuInfo[i]);
252
0
            m_addOnCtuInfo[i] = NULL;
253
0
            X265_FREE(m_addOnPrevChange[i]);
254
0
            m_addOnPrevChange[i] = NULL;
255
0
        }
256
0
        X265_FREE(*m_ctuInfo);
257
0
        *m_ctuInfo = NULL;
258
0
        X265_FREE(m_ctuInfo);
259
0
        m_ctuInfo = NULL;
260
0
        X265_FREE(m_prevCtuInfoChange);
261
0
        m_prevCtuInfoChange = NULL;
262
0
        X265_FREE(m_addOnDepth);
263
0
        m_addOnDepth = NULL;
264
0
        X265_FREE(m_addOnCtuInfo);
265
0
        m_addOnCtuInfo = NULL;
266
0
        X265_FREE(m_addOnPrevChange);
267
0
        m_addOnPrevChange = NULL;
268
0
    }
269
698
    m_lowres.destroy();
270
698
    X265_FREE(m_rcData);
271
272
698
    if (m_param->bDynamicRefine)
273
0
    {
274
0
        X265_FREE_ZERO(m_classifyRd);
275
0
        X265_FREE_ZERO(m_classifyVariance);
276
0
        X265_FREE_ZERO(m_classifyCount);
277
0
    }
278
279
698
    if (m_param->rc.aqMode == X265_AQ_EDGE || (m_param->rc.zonefileCount && m_param->rc.aqMode != 0))
280
0
    {
281
0
        X265_FREE(m_edgePic);
282
0
        X265_FREE(m_gaussianPic);
283
0
        X265_FREE(m_thetaPic);
284
0
    }
285
286
698
    if (m_param->recursionSkipMode == EDGE_BASED_RSKIP)
287
0
    {
288
0
        X265_FREE_ZERO(m_edgeBitPlane);
289
0
        m_edgeBitPic = NULL;
290
0
    }
291
698
}