Mercurial > hg > forks > libbpg
comparison x265/source/common/scalinglist.cpp @ 0:772086c29cc7
Initial import.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Wed, 16 Nov 2016 11:16:33 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:772086c29cc7 |
---|---|
1 /***************************************************************************** | |
2 * Copyright (C) 2015 x265 project | |
3 * | |
4 * Authors: Steve Borho <steve@borho.org> | |
5 * | |
6 * This program is free software; you can redistribute it and/or modify | |
7 * it under the terms of the GNU General Public License as published by | |
8 * the Free Software Foundation; either version 2 of the License, or | |
9 * (at your option) any later version. | |
10 * | |
11 * This program is distributed in the hope that it will be useful, | |
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 * GNU General Public License for more details. | |
15 * | |
16 * You should have received a copy of the GNU General Public License | |
17 * along with this program; if not, write to the Free Software | |
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA. | |
19 * | |
20 * This program is also available under a commercial proprietary license. | |
21 * For more information, contact us at license @ x265.com. | |
22 *****************************************************************************/ | |
23 | |
24 #include "common.h" | |
25 #include "primitives.h" | |
26 #include "scalinglist.h" | |
27 | |
28 namespace { | |
29 // file-anonymous namespace | |
30 | |
31 /* Strings for scaling list file parsing */ | |
32 const char MatrixType[4][6][20] = | |
33 { | |
34 { | |
35 "INTRA4X4_LUMA", | |
36 "INTRA4X4_CHROMAU", | |
37 "INTRA4X4_CHROMAV", | |
38 "INTER4X4_LUMA", | |
39 "INTER4X4_CHROMAU", | |
40 "INTER4X4_CHROMAV" | |
41 }, | |
42 { | |
43 "INTRA8X8_LUMA", | |
44 "INTRA8X8_CHROMAU", | |
45 "INTRA8X8_CHROMAV", | |
46 "INTER8X8_LUMA", | |
47 "INTER8X8_CHROMAU", | |
48 "INTER8X8_CHROMAV" | |
49 }, | |
50 { | |
51 "INTRA16X16_LUMA", | |
52 "INTRA16X16_CHROMAU", | |
53 "INTRA16X16_CHROMAV", | |
54 "INTER16X16_LUMA", | |
55 "INTER16X16_CHROMAU", | |
56 "INTER16X16_CHROMAV" | |
57 }, | |
58 { | |
59 "INTRA32X32_LUMA", | |
60 "INTER32X32_LUMA", | |
61 }, | |
62 }; | |
63 const char MatrixType_DC[4][12][22] = | |
64 { | |
65 { | |
66 }, | |
67 { | |
68 }, | |
69 { | |
70 "INTRA16X16_LUMA_DC", | |
71 "INTRA16X16_CHROMAU_DC", | |
72 "INTRA16X16_CHROMAV_DC", | |
73 "INTER16X16_LUMA_DC", | |
74 "INTER16X16_CHROMAU_DC", | |
75 "INTER16X16_CHROMAV_DC" | |
76 }, | |
77 { | |
78 "INTRA32X32_LUMA_DC", | |
79 "INTER32X32_LUMA_DC", | |
80 }, | |
81 }; | |
82 | |
83 static int quantTSDefault4x4[16] = | |
84 { | |
85 16, 16, 16, 16, | |
86 16, 16, 16, 16, | |
87 16, 16, 16, 16, | |
88 16, 16, 16, 16 | |
89 }; | |
90 | |
91 static int quantIntraDefault8x8[64] = | |
92 { | |
93 16, 16, 16, 16, 17, 18, 21, 24, | |
94 16, 16, 16, 16, 17, 19, 22, 25, | |
95 16, 16, 17, 18, 20, 22, 25, 29, | |
96 16, 16, 18, 21, 24, 27, 31, 36, | |
97 17, 17, 20, 24, 30, 35, 41, 47, | |
98 18, 19, 22, 27, 35, 44, 54, 65, | |
99 21, 22, 25, 31, 41, 54, 70, 88, | |
100 24, 25, 29, 36, 47, 65, 88, 115 | |
101 }; | |
102 | |
103 static int quantInterDefault8x8[64] = | |
104 { | |
105 16, 16, 16, 16, 17, 18, 20, 24, | |
106 16, 16, 16, 17, 18, 20, 24, 25, | |
107 16, 16, 17, 18, 20, 24, 25, 28, | |
108 16, 17, 18, 20, 24, 25, 28, 33, | |
109 17, 18, 20, 24, 25, 28, 33, 41, | |
110 18, 20, 24, 25, 28, 33, 41, 54, | |
111 20, 24, 25, 28, 33, 41, 54, 71, | |
112 24, 25, 28, 33, 41, 54, 71, 91 | |
113 }; | |
114 | |
115 } | |
116 | |
117 namespace X265_NS { | |
118 // private namespace | |
119 | |
120 const int ScalingList::s_numCoefPerSize[NUM_SIZES] = { 16, 64, 256, 1024 }; | |
121 const int32_t ScalingList::s_quantScales[NUM_REM] = { 26214, 23302, 20560, 18396, 16384, 14564 }; | |
122 const int32_t ScalingList::s_invQuantScales[NUM_REM] = { 40, 45, 51, 57, 64, 72 }; | |
123 | |
124 ScalingList::ScalingList() | |
125 { | |
126 memset(m_quantCoef, 0, sizeof(m_quantCoef)); | |
127 memset(m_dequantCoef, 0, sizeof(m_dequantCoef)); | |
128 memset(m_scalingListCoef, 0, sizeof(m_scalingListCoef)); | |
129 } | |
130 | |
131 bool ScalingList::init() | |
132 { | |
133 bool ok = true; | |
134 for (int sizeId = 0; sizeId < NUM_SIZES; sizeId++) | |
135 { | |
136 for (int listId = 0; listId < NUM_LISTS; listId++) | |
137 { | |
138 m_scalingListCoef[sizeId][listId] = X265_MALLOC(int32_t, X265_MIN(MAX_MATRIX_COEF_NUM, s_numCoefPerSize[sizeId])); | |
139 ok &= !!m_scalingListCoef[sizeId][listId]; | |
140 for (int rem = 0; rem < NUM_REM; rem++) | |
141 { | |
142 m_quantCoef[sizeId][listId][rem] = X265_MALLOC(int32_t, s_numCoefPerSize[sizeId]); | |
143 m_dequantCoef[sizeId][listId][rem] = X265_MALLOC(int32_t, s_numCoefPerSize[sizeId]); | |
144 ok &= m_quantCoef[sizeId][listId][rem] && m_dequantCoef[sizeId][listId][rem]; | |
145 } | |
146 } | |
147 } | |
148 return ok; | |
149 } | |
150 | |
151 ScalingList::~ScalingList() | |
152 { | |
153 for (int sizeId = 0; sizeId < NUM_SIZES; sizeId++) | |
154 { | |
155 for (int listId = 0; listId < NUM_LISTS; listId++) | |
156 { | |
157 X265_FREE(m_scalingListCoef[sizeId][listId]); | |
158 for (int rem = 0; rem < NUM_REM; rem++) | |
159 { | |
160 X265_FREE(m_quantCoef[sizeId][listId][rem]); | |
161 X265_FREE(m_dequantCoef[sizeId][listId][rem]); | |
162 } | |
163 } | |
164 } | |
165 } | |
166 | |
167 /* returns predicted list index if a match is found, else -1 */ | |
168 int ScalingList::checkPredMode(int size, int list) const | |
169 { | |
170 for (int predList = list; predList >= 0; predList--) | |
171 { | |
172 // check DC value | |
173 if (size < BLOCK_16x16 && m_scalingListDC[size][list] != m_scalingListDC[size][predList]) | |
174 continue; | |
175 | |
176 // check value of matrix | |
177 if (!memcmp(m_scalingListCoef[size][list], | |
178 list == predList ? getScalingListDefaultAddress(size, predList) : m_scalingListCoef[size][predList], | |
179 sizeof(int32_t) * X265_MIN(MAX_MATRIX_COEF_NUM, s_numCoefPerSize[size]))) | |
180 return predList; | |
181 } | |
182 | |
183 return -1; | |
184 } | |
185 | |
186 /* check if use default quantization matrix | |
187 * returns true if default quantization matrix is used in all sizes */ | |
188 bool ScalingList::checkDefaultScalingList() const | |
189 { | |
190 int defaultCounter = 0; | |
191 | |
192 for (int s = 0; s < NUM_SIZES; s++) | |
193 for (int l = 0; l < NUM_LISTS; l++) | |
194 if (!memcmp(m_scalingListCoef[s][l], getScalingListDefaultAddress(s, l), | |
195 sizeof(int32_t) * X265_MIN(MAX_MATRIX_COEF_NUM, s_numCoefPerSize[s])) && | |
196 ((s < BLOCK_16x16) || (m_scalingListDC[s][l] == 16))) | |
197 defaultCounter++; | |
198 | |
199 return defaultCounter != (NUM_LISTS * NUM_SIZES - 4); // -4 for 32x32 | |
200 } | |
201 | |
202 /* get address of default quantization matrix */ | |
203 const int32_t* ScalingList::getScalingListDefaultAddress(int sizeId, int listId) const | |
204 { | |
205 switch (sizeId) | |
206 { | |
207 case BLOCK_4x4: | |
208 return quantTSDefault4x4; | |
209 case BLOCK_8x8: | |
210 return (listId < 3) ? quantIntraDefault8x8 : quantInterDefault8x8; | |
211 case BLOCK_16x16: | |
212 return (listId < 3) ? quantIntraDefault8x8 : quantInterDefault8x8; | |
213 case BLOCK_32x32: | |
214 return (listId < 1) ? quantIntraDefault8x8 : quantInterDefault8x8; | |
215 default: | |
216 break; | |
217 } | |
218 | |
219 X265_CHECK(0, "invalid scaling list size\n"); | |
220 return NULL; | |
221 } | |
222 | |
223 void ScalingList::processDefaultMarix(int sizeId, int listId) | |
224 { | |
225 memcpy(m_scalingListCoef[sizeId][listId], getScalingListDefaultAddress(sizeId, listId), sizeof(int) * X265_MIN(MAX_MATRIX_COEF_NUM, s_numCoefPerSize[sizeId])); | |
226 m_scalingListDC[sizeId][listId] = SCALING_LIST_DC; | |
227 } | |
228 | |
229 void ScalingList::setDefaultScalingList() | |
230 { | |
231 for (int sizeId = 0; sizeId < NUM_SIZES; sizeId++) | |
232 for (int listId = 0; listId < NUM_LISTS; listId++) | |
233 processDefaultMarix(sizeId, listId); | |
234 m_bEnabled = true; | |
235 m_bDataPresent = false; | |
236 } | |
237 | |
238 bool ScalingList::parseScalingList(const char* filename) | |
239 { | |
240 FILE *fp = fopen(filename, "r"); | |
241 if (!fp) | |
242 { | |
243 x265_log(NULL, X265_LOG_ERROR, "can't open scaling list file %s\n", filename); | |
244 return true; | |
245 } | |
246 | |
247 char line[1024]; | |
248 int32_t *src = NULL; | |
249 | |
250 for (int sizeIdc = 0; sizeIdc < NUM_SIZES; sizeIdc++) | |
251 { | |
252 int size = X265_MIN(MAX_MATRIX_COEF_NUM, s_numCoefPerSize[sizeIdc]); | |
253 for (int listIdc = 0; listIdc < NUM_LISTS; listIdc++) | |
254 { | |
255 src = m_scalingListCoef[sizeIdc][listIdc]; | |
256 | |
257 fseek(fp, 0, 0); | |
258 do | |
259 { | |
260 char *ret = fgets(line, 1024, fp); | |
261 if (!ret || (!strstr(line, MatrixType[sizeIdc][listIdc]) && feof(fp))) | |
262 { | |
263 x265_log(NULL, X265_LOG_ERROR, "can't read matrix from %s\n", filename); | |
264 return true; | |
265 } | |
266 } | |
267 while (!strstr(line, MatrixType[sizeIdc][listIdc])); | |
268 | |
269 for (int i = 0; i < size; i++) | |
270 { | |
271 int data; | |
272 if (fscanf(fp, "%d,", &data) != 1) | |
273 { | |
274 x265_log(NULL, X265_LOG_ERROR, "can't read matrix from %s\n", filename); | |
275 return true; | |
276 } | |
277 src[i] = data; | |
278 } | |
279 | |
280 // set DC value for default matrix check | |
281 m_scalingListDC[sizeIdc][listIdc] = src[0]; | |
282 | |
283 if (sizeIdc > BLOCK_8x8) | |
284 { | |
285 fseek(fp, 0, 0); | |
286 do | |
287 { | |
288 char *ret = fgets(line, 1024, fp); | |
289 if (!ret || (!strstr(line, MatrixType_DC[sizeIdc][listIdc]) && feof(fp))) | |
290 { | |
291 x265_log(NULL, X265_LOG_ERROR, "can't read DC from %s\n", filename); | |
292 return true; | |
293 } | |
294 } | |
295 while (!strstr(line, MatrixType_DC[sizeIdc][listIdc])); | |
296 | |
297 int data; | |
298 if (fscanf(fp, "%d,", &data) != 1) | |
299 { | |
300 x265_log(NULL, X265_LOG_ERROR, "can't read matrix from %s\n", filename); | |
301 return true; | |
302 } | |
303 | |
304 // overwrite DC value when size of matrix is larger than 16x16 | |
305 m_scalingListDC[sizeIdc][listIdc] = data; | |
306 } | |
307 } | |
308 } | |
309 | |
310 fclose(fp); | |
311 | |
312 m_bEnabled = true; | |
313 m_bDataPresent = !checkDefaultScalingList(); | |
314 | |
315 return false; | |
316 } | |
317 | |
318 /** set quantized matrix coefficient for encode */ | |
319 void ScalingList::setupQuantMatrices() | |
320 { | |
321 for (int size = 0; size < NUM_SIZES; size++) | |
322 { | |
323 int width = 1 << (size + 2); | |
324 int ratio = width / X265_MIN(MAX_MATRIX_SIZE_NUM, width); | |
325 int stride = X265_MIN(MAX_MATRIX_SIZE_NUM, width); | |
326 int count = s_numCoefPerSize[size]; | |
327 | |
328 for (int list = 0; list < NUM_LISTS; list++) | |
329 { | |
330 int32_t *coeff = m_scalingListCoef[size][list]; | |
331 int32_t dc = m_scalingListDC[size][list]; | |
332 | |
333 for (int rem = 0; rem < NUM_REM; rem++) | |
334 { | |
335 int32_t *quantCoeff = m_quantCoef[size][list][rem]; | |
336 int32_t *dequantCoeff = m_dequantCoef[size][list][rem]; | |
337 | |
338 if (m_bEnabled) | |
339 { | |
340 processScalingListEnc(coeff, quantCoeff, s_quantScales[rem] << 4, width, width, ratio, stride, dc); | |
341 processScalingListDec(coeff, dequantCoeff, s_invQuantScales[rem], width, width, ratio, stride, dc); | |
342 } | |
343 else | |
344 { | |
345 /* flat quant and dequant coefficients */ | |
346 for (int i = 0; i < count; i++) | |
347 { | |
348 quantCoeff[i] = s_quantScales[rem]; | |
349 dequantCoeff[i] = s_invQuantScales[rem]; | |
350 } | |
351 } | |
352 } | |
353 } | |
354 } | |
355 } | |
356 | |
357 void ScalingList::processScalingListEnc(int32_t *coeff, int32_t *quantcoeff, int32_t quantScales, int height, int width, | |
358 int ratio, int stride, int32_t dc) | |
359 { | |
360 for (int j = 0; j < height; j++) | |
361 for (int i = 0; i < width; i++) | |
362 quantcoeff[j * width + i] = quantScales / coeff[stride * (j / ratio) + i / ratio]; | |
363 | |
364 if (ratio > 1) | |
365 quantcoeff[0] = quantScales / dc; | |
366 } | |
367 | |
368 void ScalingList::processScalingListDec(int32_t *coeff, int32_t *dequantcoeff, int32_t invQuantScales, int height, int width, | |
369 int ratio, int stride, int32_t dc) | |
370 { | |
371 for (int j = 0; j < height; j++) | |
372 for (int i = 0; i < width; i++) | |
373 dequantcoeff[j * width + i] = invQuantScales * coeff[stride * (j / ratio) + i / ratio]; | |
374 | |
375 if (ratio > 1) | |
376 dequantcoeff[0] = invQuantScales * dc; | |
377 } | |
378 | |
379 } |