Imported Upstream version 1.4+222+hg5f9f7194267b
[deb_x265.git] / source / encoder / reference.cpp
1 /*****************************************************************************
2 * Copyright (C) 2013 x265 project
3 *
4 * Authors: Steve Borho <steve@borho.org>
5 * Deepthi Devaki <deepthidevaki@multicorewareinc.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 "primitives.h"
27 #include "slice.h"
28 #include "picyuv.h"
29
30 #include "reference.h"
31
32 using namespace x265;
33
34 MotionReference::MotionReference()
35 {
36 weightBuffer[0] = NULL;
37 weightBuffer[1] = NULL;
38 weightBuffer[2] = NULL;
39 }
40
41 MotionReference::~MotionReference()
42 {
43 X265_FREE(weightBuffer[0]);
44 X265_FREE(weightBuffer[1]);
45 X265_FREE(weightBuffer[2]);
46 }
47
48 int MotionReference::init(PicYuv* recPic, WeightParam *wp, const x265_param& p)
49 {
50 reconPic = recPic;
51 numWeightedRows = 0;
52 lumaStride = recPic->m_stride;
53 chromaStride = recPic->m_strideC;
54 numInterpPlanes = p.subpelRefine > 2 ? 3 : 1; /* is chroma satd possible? */
55
56 /* directly reference the extended integer pel planes */
57 fpelPlane[0] = recPic->m_picOrg[0];
58 fpelPlane[1] = recPic->m_picOrg[1];
59 fpelPlane[2] = recPic->m_picOrg[2];
60 isWeighted = false;
61
62 if (wp)
63 {
64 uint32_t numCUinHeight = (reconPic->m_picHeight + g_maxCUSize - 1) / g_maxCUSize;
65
66 int marginX = reconPic->m_lumaMarginX;
67 int marginY = reconPic->m_lumaMarginY;
68 intptr_t stride = reconPic->m_stride;
69 int cuHeight = g_maxCUSize;
70
71 for (int c = 0; c < numInterpPlanes; c++)
72 {
73 if (c == 1)
74 {
75 marginX = reconPic->m_chromaMarginX;
76 marginY = reconPic->m_chromaMarginY;
77 stride = reconPic->m_strideC;
78 cuHeight >>= reconPic->m_vChromaShift;
79 }
80
81 if (wp[c].bPresentFlag)
82 {
83 if (!weightBuffer[c])
84 {
85 size_t padheight = (numCUinHeight * cuHeight) + marginY * 2;
86 weightBuffer[c] = X265_MALLOC(pixel, stride * padheight);
87 if (!weightBuffer[c])
88 return -1;
89 }
90
91 /* use our buffer which will have weighted pixels written to it */
92 fpelPlane[c] = weightBuffer[c] + marginY * stride + marginX;
93 X265_CHECK(recPic->m_picOrg[c] - recPic->m_picBuf[c] == marginY * stride + marginX, "PicYuv pad calculation mismatch\n");
94
95 w[c].weight = wp[c].inputWeight;
96 w[c].offset = wp[c].inputOffset * (1 << (X265_DEPTH - 8));
97 w[c].shift = wp[c].log2WeightDenom;
98 w[c].round = w[c].shift ? 1 << (w[c].shift - 1) : 0;
99 }
100 }
101
102 isWeighted = true;
103 }
104
105 return 0;
106 }
107
108 void MotionReference::applyWeight(int finishedRows, int maxNumRows)
109 {
110 finishedRows = X265_MIN(finishedRows, maxNumRows);
111 if (numWeightedRows >= finishedRows)
112 return;
113
114 int marginX = reconPic->m_lumaMarginX;
115 int marginY = reconPic->m_lumaMarginY;
116 intptr_t stride = reconPic->m_stride;
117 int width = reconPic->m_picWidth;
118 int height = (finishedRows - numWeightedRows) * g_maxCUSize;
119 if (finishedRows == maxNumRows && (reconPic->m_picHeight % g_maxCUSize))
120 {
121 /* the last row may be partial height */
122 height -= g_maxCUSize;
123 height += reconPic->m_picHeight % g_maxCUSize;
124 }
125 int cuHeight = g_maxCUSize;
126
127 for (int c = 0; c < numInterpPlanes; c++)
128 {
129 if (c == 1)
130 {
131 marginX = reconPic->m_chromaMarginX;
132 marginY = reconPic->m_chromaMarginY;
133 stride = reconPic->m_strideC;
134 width >>= reconPic->m_hChromaShift;
135 height >>= reconPic->m_vChromaShift;
136 cuHeight >>= reconPic->m_vChromaShift;
137 }
138
139 /* Do not generate weighted predictions if using original picture */
140 if (fpelPlane[c] == reconPic->m_picOrg[c])
141 continue;
142
143 const pixel* src = reconPic->m_picOrg[c] + numWeightedRows * cuHeight * stride;
144 pixel* dst = fpelPlane[c] + numWeightedRows * cuHeight * stride;
145
146 // Computing weighted CU rows
147 int correction = IF_INTERNAL_PREC - X265_DEPTH; // intermediate interpolation depth
148 int padwidth = (width + 15) & ~15; // weightp assembly needs even 16 byte widths
149 primitives.weight_pp(src, dst, stride, padwidth, height, w[c].weight, w[c].round << correction, w[c].shift + correction, w[c].offset);
150
151 // Extending Left & Right
152 primitives.extendRowBorder(dst, stride, width, height, marginX);
153
154 // Extending Above
155 if (numWeightedRows == 0)
156 {
157 pixel *pixY = fpelPlane[c] - marginX;
158 for (int y = 0; y < marginY; y++)
159 memcpy(pixY - (y + 1) * stride, pixY, stride * sizeof(pixel));
160 }
161
162 // Extending Bottom
163 if (finishedRows == maxNumRows)
164 {
165 int picHeight = reconPic->m_picHeight;
166 if (c) picHeight >>= reconPic->m_vChromaShift;
167 pixel *pixY = fpelPlane[c] - marginX + (picHeight - 1) * stride;
168 for (int y = 0; y < marginY; y++)
169 memcpy(pixY + (y + 1) * stride, pixY, stride * sizeof(pixel));
170 }
171 }
172
173 numWeightedRows = finishedRows;
174 }