/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 | } |