1 /*****************************************************************************
2 * Copyright (C) 2013-2020 MulticoreWare, Inc
3 *
4 * Authors: Steve Borho <steve@borho.org>
5 * Deepthi Devaki <deepthidevaki@multicorewareinc.com>
6 * Min Chen <chenm003@163.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
21 *
22 * This program is also available under a commercial proprietary license.
23 * For more information, contact us at license @ x265.com.
24 *****************************************************************************/
25
26 #include "common.h"
27 #include "primitives.h"
28 #include "slice.h"
29 #include "picyuv.h"
30
31 #include "reference.h"
32
33 using namespace X265_NS;
34
MotionReference()35 MotionReference::MotionReference()
36 {
37 weightBuffer[0] = NULL;
38 weightBuffer[1] = NULL;
39 weightBuffer[2] = NULL;
40 numSliceWeightedRows = NULL;
41 }
42
~MotionReference()43 MotionReference::~MotionReference()
44 {
45 X265_FREE(numSliceWeightedRows);
46 X265_FREE(weightBuffer[0]);
47 X265_FREE(weightBuffer[1]);
48 X265_FREE(weightBuffer[2]);
49 }
50
init(PicYuv * recPic,WeightParam * wp,const x265_param & p)51 int MotionReference::init(PicYuv* recPic, WeightParam *wp, const x265_param& p)
52 {
53 reconPic = recPic;
54 lumaStride = recPic->m_stride;
55 chromaStride = recPic->m_strideC;
56 numInterpPlanes = p.subpelRefine > 2 ? 3 : 1; /* is chroma satd possible? */
57
58 if (numSliceWeightedRows)
59 {
60 // Unnecessary, but avoid risk on parameters dynamic modify in future.
61 X265_FREE(numSliceWeightedRows);
62 numSliceWeightedRows = NULL;
63 }
64 numSliceWeightedRows = X265_MALLOC(uint32_t, p.maxSlices);
65 memset(numSliceWeightedRows, 0, p.maxSlices * sizeof(uint32_t));
66
67 /* directly reference the extended integer pel planes */
68 fpelPlane[0] = recPic->m_picOrg[0];
69 fpelPlane[1] = recPic->m_picOrg[1];
70 fpelPlane[2] = recPic->m_picOrg[2];
71 isWeighted = false;
72
73 if (wp)
74 {
75 uint32_t numCUinHeight = (reconPic->m_picHeight + p.maxCUSize - 1) / p.maxCUSize;
76
77 int marginX = reconPic->m_lumaMarginX;
78 int marginY = reconPic->m_lumaMarginY;
79 intptr_t stride = reconPic->m_stride;
80 int cuHeight = p.maxCUSize;
81
82 for (int c = 0; c < (p.internalCsp != X265_CSP_I400 && recPic->m_picCsp != X265_CSP_I400 ? numInterpPlanes : 1); c++)
83 {
84 if (c == 1)
85 {
86 marginX = reconPic->m_chromaMarginX;
87 marginY = reconPic->m_chromaMarginY;
88 stride = reconPic->m_strideC;
89 cuHeight >>= reconPic->m_vChromaShift;
90 }
91
92 if (wp[c].wtPresent)
93 {
94 if (!weightBuffer[c])
95 {
96 size_t padheight = (numCUinHeight * cuHeight) + marginY * 2;
97 weightBuffer[c] = X265_MALLOC(pixel, stride * padheight);
98 if (!weightBuffer[c])
99 return -1;
100 }
101
102 /* use our buffer which will have weighted pixels written to it */
103 fpelPlane[c] = weightBuffer[c] + marginY * stride + marginX;
104 X265_CHECK(recPic->m_picOrg[c] - recPic->m_picBuf[c] == marginY * stride + marginX, "PicYuv pad calculation mismatch\n");
105
106 w[c].weight = wp[c].inputWeight;
107 w[c].offset = wp[c].inputOffset * (1 << (X265_DEPTH - 8));
108 w[c].shift = wp[c].log2WeightDenom;
109 w[c].round = w[c].shift ? 1 << (w[c].shift - 1) : 0;
110 }
111 }
112
113 isWeighted = true;
114 }
115
116 return 0;
117 }
118
applyWeight(uint32_t finishedRows,uint32_t maxNumRows,uint32_t maxNumRowsInSlice,uint32_t sliceId)119 void MotionReference::applyWeight(uint32_t finishedRows, uint32_t maxNumRows, uint32_t maxNumRowsInSlice, uint32_t sliceId)
120 {
121 const uint32_t numWeightedRows = numSliceWeightedRows[sliceId];
122 finishedRows = X265_MIN(finishedRows, maxNumRowsInSlice);
123 if (numWeightedRows >= finishedRows)
124 return;
125
126 int marginX = reconPic->m_lumaMarginX;
127 int marginY = reconPic->m_lumaMarginY;
128 intptr_t stride = reconPic->m_stride;
129 int width = reconPic->m_picWidth;
130 int height = (finishedRows - numWeightedRows) * reconPic->m_param->maxCUSize;
131 /* the last row may be partial height */
132 if (finishedRows == maxNumRows - 1)
133 {
134 const int leftRows = (reconPic->m_picHeight & (reconPic->m_param->maxCUSize - 1));
135
136 height += leftRows ? leftRows : reconPic->m_param->maxCUSize;
137 }
138 int cuHeight = reconPic->m_param->maxCUSize;
139
140 for (int c = 0; c < numInterpPlanes; c++)
141 {
142 if (c == 1)
143 {
144 marginX = reconPic->m_chromaMarginX;
145 marginY = reconPic->m_chromaMarginY;
146 stride = reconPic->m_strideC;
147 width >>= reconPic->m_hChromaShift;
148 height >>= reconPic->m_vChromaShift;
149 cuHeight >>= reconPic->m_vChromaShift;
150 }
151
152 /* Do not generate weighted predictions if using original picture */
153 if (fpelPlane[c] == reconPic->m_picOrg[c])
154 continue;
155
156 const pixel* src = reconPic->m_picOrg[c] + numWeightedRows * cuHeight * stride;
157 pixel* dst = fpelPlane[c] + numWeightedRows * cuHeight * stride;
158 // Computing weighted CU rows
159 int correction = IF_INTERNAL_PREC - X265_DEPTH; // intermediate interpolation depth
160 int padwidth = (width + 31) & ~31; // weightp assembly needs even 32 byte widths
161 primitives.weight_pp(src, dst, stride, padwidth, height, w[c].weight, w[c].round << correction, w[c].shift + correction, w[c].offset);
162 // Extending Left & Right
163 primitives.extendRowBorder(dst, stride, width, height, marginX);
164
165 // Extending Above
166 if (numWeightedRows == 0)
167 {
168 pixel *pixY = fpelPlane[c] - marginX;
169 for (int y = 0; y < marginY; y++)
170 memcpy(pixY - (y + 1) * stride, pixY, stride * sizeof(pixel));
171 }
172
173 // Extending Bottom
174 if (finishedRows == maxNumRows - 1)
175 {
176 int picHeight = reconPic->m_picHeight;
177 if (c) picHeight >>= reconPic->m_vChromaShift;
178 pixel *pixY = fpelPlane[c] - marginX + (picHeight - 1) * stride;
179 for (int y = 0; y < marginY; y++)
180 memcpy(pixY + (y + 1) * stride, pixY, stride * sizeof(pixel));
181 }
182 }
183
184 numSliceWeightedRows[sliceId] = finishedRows;
185 }
186