1 /*****************************************************************************
2 * Copyright (C) 2013-2020 MulticoreWare, Inc
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
33 static int quantTSDefault4x4[16] =
34 {
35 16, 16, 16, 16,
36 16, 16, 16, 16,
37 16, 16, 16, 16,
38 16, 16, 16, 16
39 };
40
41 static int quantIntraDefault8x8[64] =
42 {
43 16, 16, 16, 16, 17, 18, 21, 24,
44 16, 16, 16, 16, 17, 19, 22, 25,
45 16, 16, 17, 18, 20, 22, 25, 29,
46 16, 16, 18, 21, 24, 27, 31, 36,
47 17, 17, 20, 24, 30, 35, 41, 47,
48 18, 19, 22, 27, 35, 44, 54, 65,
49 21, 22, 25, 31, 41, 54, 70, 88,
50 24, 25, 29, 36, 47, 65, 88, 115
51 };
52
53 static int quantInterDefault8x8[64] =
54 {
55 16, 16, 16, 16, 17, 18, 20, 24,
56 16, 16, 16, 17, 18, 20, 24, 25,
57 16, 16, 17, 18, 20, 24, 25, 28,
58 16, 17, 18, 20, 24, 25, 28, 33,
59 17, 18, 20, 24, 25, 28, 33, 41,
60 18, 20, 24, 25, 28, 33, 41, 54,
61 20, 24, 25, 28, 33, 41, 54, 71,
62 24, 25, 28, 33, 41, 54, 71, 91
63 };
64
65 }
66
67 namespace X265_NS {
68 // private namespace
69 const char ScalingList::MatrixType[4][6][20] =
70 {
71 {
72 "INTRA4X4_LUMA",
73 "INTRA4X4_CHROMAU",
74 "INTRA4X4_CHROMAV",
75 "INTER4X4_LUMA",
76 "INTER4X4_CHROMAU",
77 "INTER4X4_CHROMAV"
78 },
79 {
80 "INTRA8X8_LUMA",
81 "INTRA8X8_CHROMAU",
82 "INTRA8X8_CHROMAV",
83 "INTER8X8_LUMA",
84 "INTER8X8_CHROMAU",
85 "INTER8X8_CHROMAV"
86 },
87 {
88 "INTRA16X16_LUMA",
89 "INTRA16X16_CHROMAU",
90 "INTRA16X16_CHROMAV",
91 "INTER16X16_LUMA",
92 "INTER16X16_CHROMAU",
93 "INTER16X16_CHROMAV"
94 },
95 {
96 "INTRA32X32_LUMA",
97 "",
98 "",
99 "INTER32X32_LUMA",
100 "",
101 "",
102 },
103 };
104 const char ScalingList::MatrixType_DC[4][12][22] =
105 {
106 {
107 },
108 {
109 },
110 {
111 "INTRA16X16_LUMA_DC",
112 "INTRA16X16_CHROMAU_DC",
113 "INTRA16X16_CHROMAV_DC",
114 "INTER16X16_LUMA_DC",
115 "INTER16X16_CHROMAU_DC",
116 "INTER16X16_CHROMAV_DC"
117 },
118 {
119 "INTRA32X32_LUMA_DC",
120 "",
121 "",
122 "INTER32X32_LUMA_DC",
123 "",
124 "",
125 },
126 };
127
128 const int ScalingList::s_numCoefPerSize[NUM_SIZES] = { 16, 64, 256, 1024 };
129 const int32_t ScalingList::s_quantScales[NUM_REM] = { 26214, 23302, 20560, 18396, 16384, 14564 };
130 const int32_t ScalingList::s_invQuantScales[NUM_REM] = { 40, 45, 51, 57, 64, 72 };
131
ScalingList()132 ScalingList::ScalingList()
133 {
134 memset(m_quantCoef, 0, sizeof(m_quantCoef));
135 memset(m_dequantCoef, 0, sizeof(m_dequantCoef));
136 memset(m_scalingListCoef, 0, sizeof(m_scalingListCoef));
137 }
138
init()139 bool ScalingList::init()
140 {
141 bool ok = true;
142 for (int sizeId = 0; sizeId < NUM_SIZES; sizeId++)
143 {
144 for (int listId = 0; listId < NUM_LISTS; listId++)
145 {
146 m_scalingListCoef[sizeId][listId] = X265_MALLOC(int32_t, X265_MIN(MAX_MATRIX_COEF_NUM, s_numCoefPerSize[sizeId]));
147 ok &= !!m_scalingListCoef[sizeId][listId];
148 for (int rem = 0; rem < NUM_REM; rem++)
149 {
150 m_quantCoef[sizeId][listId][rem] = X265_MALLOC(int32_t, s_numCoefPerSize[sizeId]);
151 m_dequantCoef[sizeId][listId][rem] = X265_MALLOC(int32_t, s_numCoefPerSize[sizeId]);
152 ok &= m_quantCoef[sizeId][listId][rem] && m_dequantCoef[sizeId][listId][rem];
153 }
154 }
155 }
156 return ok;
157 }
158
~ScalingList()159 ScalingList::~ScalingList()
160 {
161 for (int sizeId = 0; sizeId < NUM_SIZES; sizeId++)
162 {
163 for (int listId = 0; listId < NUM_LISTS; listId++)
164 {
165 X265_FREE(m_scalingListCoef[sizeId][listId]);
166 for (int rem = 0; rem < NUM_REM; rem++)
167 {
168 X265_FREE(m_quantCoef[sizeId][listId][rem]);
169 X265_FREE(m_dequantCoef[sizeId][listId][rem]);
170 }
171 }
172 }
173 }
174
175 /* returns predicted list index if a match is found, else -1 */
checkPredMode(int size,int list) const176 int ScalingList::checkPredMode(int size, int list) const
177 {
178 for (int predList = list; predList >= 0; predList--)
179 {
180 // check DC value
181 if (size < BLOCK_16x16 && m_scalingListDC[size][list] != m_scalingListDC[size][predList])
182 continue;
183
184 // check value of matrix
185 if (!memcmp(m_scalingListCoef[size][list],
186 list == predList ? getScalingListDefaultAddress(size, predList) : m_scalingListCoef[size][predList],
187 sizeof(int32_t) * X265_MIN(MAX_MATRIX_COEF_NUM, s_numCoefPerSize[size])))
188 return predList;
189 }
190
191 return -1;
192 }
193
194 /* check if use default quantization matrix
195 * returns true if default quantization matrix is used in all sizes */
checkDefaultScalingList() const196 bool ScalingList::checkDefaultScalingList() const
197 {
198 int defaultCounter = 0;
199
200 for (int s = 0; s < NUM_SIZES; s++)
201 for (int l = 0; l < NUM_LISTS; l++)
202 if (!memcmp(m_scalingListCoef[s][l], getScalingListDefaultAddress(s, l),
203 sizeof(int32_t) * X265_MIN(MAX_MATRIX_COEF_NUM, s_numCoefPerSize[s])) &&
204 ((s < BLOCK_16x16) || (m_scalingListDC[s][l] == 16)))
205 defaultCounter++;
206
207 return defaultCounter != (NUM_LISTS * NUM_SIZES - 4); // -4 for 32x32
208 }
209
210 /* get address of default quantization matrix */
getScalingListDefaultAddress(int sizeId,int listId) const211 const int32_t* ScalingList::getScalingListDefaultAddress(int sizeId, int listId) const
212 {
213 switch (sizeId)
214 {
215 case BLOCK_4x4:
216 return quantTSDefault4x4;
217 case BLOCK_8x8:
218 return (listId < 3) ? quantIntraDefault8x8 : quantInterDefault8x8;
219 case BLOCK_16x16:
220 return (listId < 3) ? quantIntraDefault8x8 : quantInterDefault8x8;
221 case BLOCK_32x32:
222 return (listId < 1) ? quantIntraDefault8x8 : quantInterDefault8x8;
223 default:
224 break;
225 }
226
227 X265_CHECK(0, "invalid scaling list size\n");
228 return NULL;
229 }
230
processDefaultMarix(int sizeId,int listId)231 void ScalingList::processDefaultMarix(int sizeId, int listId)
232 {
233 memcpy(m_scalingListCoef[sizeId][listId], getScalingListDefaultAddress(sizeId, listId), sizeof(int) * X265_MIN(MAX_MATRIX_COEF_NUM, s_numCoefPerSize[sizeId]));
234 m_scalingListDC[sizeId][listId] = SCALING_LIST_DC;
235 }
236
setDefaultScalingList()237 void ScalingList::setDefaultScalingList()
238 {
239 for (int sizeId = 0; sizeId < NUM_SIZES; sizeId++)
240 for (int listId = 0; listId < NUM_LISTS; listId++)
241 processDefaultMarix(sizeId, listId);
242 m_bEnabled = true;
243 m_bDataPresent = false;
244 }
245
parseScalingList(const char * filename)246 bool ScalingList::parseScalingList(const char* filename)
247 {
248 FILE *fp = x265_fopen(filename, "r");
249 if (!fp)
250 {
251 x265_log_file(NULL, X265_LOG_ERROR, "can't open scaling list file %s\n", filename);
252 return true;
253 }
254
255 char line[1024];
256 int32_t *src = NULL;
257 fseek(fp, 0, 0);
258
259 for (int sizeIdc = 0; sizeIdc < NUM_SIZES; sizeIdc++)
260 {
261 int size = X265_MIN(MAX_MATRIX_COEF_NUM, s_numCoefPerSize[sizeIdc]);
262 for (int listIdc = 0; listIdc < NUM_LISTS; listIdc += (sizeIdc == 3) ? 3 : 1)
263 {
264 src = m_scalingListCoef[sizeIdc][listIdc];
265
266 do
267 {
268 char *ret = fgets(line, 1024, fp);
269 if (!ret || (!strstr(line, MatrixType[sizeIdc][listIdc]) && feof(fp)))
270 {
271 x265_log_file(NULL, X265_LOG_ERROR, "can't read matrix from %s\n", filename);
272 return true;
273 }
274 }
275 while (!strstr(line, MatrixType[sizeIdc][listIdc]));
276
277 for (int i = 0; i < size; i++)
278 {
279 int data;
280 if (fscanf(fp, "%d,", &data) != 1)
281 {
282 x265_log_file(NULL, X265_LOG_ERROR, "can't read matrix from %s\n", filename);
283 return true;
284 }
285 src[i] = data;
286 }
287
288 // set DC value for default matrix check
289 m_scalingListDC[sizeIdc][listIdc] = src[0];
290
291 if (sizeIdc > BLOCK_8x8)
292 {
293 do
294 {
295 char *ret = fgets(line, 1024, fp);
296 if (!ret || (!strstr(line, MatrixType_DC[sizeIdc][listIdc]) && feof(fp)))
297 {
298 x265_log_file(NULL, X265_LOG_ERROR, "can't read DC from %s\n", filename);
299 return true;
300 }
301 }
302 while (!strstr(line, MatrixType_DC[sizeIdc][listIdc]));
303
304 int data;
305 if (fscanf(fp, "%d,", &data) != 1)
306 {
307 x265_log_file(NULL, X265_LOG_ERROR, "can't read matrix from %s\n", filename);
308 return true;
309 }
310
311 // overwrite DC value when size of matrix is larger than 16x16
312 m_scalingListDC[sizeIdc][listIdc] = data;
313 }
314 }
315 if (sizeIdc == 3)
316 {
317 for (int listIdc = 1; listIdc < NUM_LISTS; listIdc++)
318 {
319 if (listIdc % 3 != 0)
320 {
321 src = m_scalingListCoef[sizeIdc][listIdc];
322 const int *srcNextSmallerSize = m_scalingListCoef[sizeIdc - 1][listIdc];
323 for (int i = 0; i < size; i++)
324 {
325 src[i] = srcNextSmallerSize[i];
326 }
327 m_scalingListDC[sizeIdc][listIdc] = m_scalingListDC[sizeIdc - 1][listIdc];
328 }
329 }
330 }
331 }
332
333 fclose(fp);
334
335 m_bEnabled = true;
336 m_bDataPresent = true;
337
338 return false;
339 }
340
341 /** set quantized matrix coefficient for encode */
setupQuantMatrices(int internalCsp)342 void ScalingList::setupQuantMatrices(int internalCsp)
343 {
344 for (int size = 0; size < NUM_SIZES; size++)
345 {
346 int width = 1 << (size + 2);
347 int ratio = width / X265_MIN(MAX_MATRIX_SIZE_NUM, width);
348 int stride = X265_MIN(MAX_MATRIX_SIZE_NUM, width);
349 int count = s_numCoefPerSize[size];
350
351 for (int list = 0; list < NUM_LISTS; list++)
352 {
353 int32_t *coeff = m_scalingListCoef[size][list];
354 int32_t dc = m_scalingListDC[size][list];
355
356 for (int rem = 0; rem < NUM_REM; rem++)
357 {
358 int32_t *quantCoeff = m_quantCoef[size][list][rem];
359 int32_t *dequantCoeff = m_dequantCoef[size][list][rem];
360
361 if (m_bEnabled)
362 {
363 if (internalCsp == X265_CSP_I444)
364 {
365 for (int i = 0; i < 64; i++)
366 {
367 m_scalingListCoef[BLOCK_32x32][1][i] = m_scalingListCoef[BLOCK_16x16][1][i];
368 m_scalingListCoef[BLOCK_32x32][2][i] = m_scalingListCoef[BLOCK_16x16][2][i];
369 m_scalingListCoef[BLOCK_32x32][4][i] = m_scalingListCoef[BLOCK_16x16][4][i];
370 m_scalingListCoef[BLOCK_32x32][5][i] = m_scalingListCoef[BLOCK_16x16][5][i];
371 }
372
373 m_scalingListDC[BLOCK_32x32][1] = m_scalingListDC[BLOCK_16x16][1];
374 m_scalingListDC[BLOCK_32x32][2] = m_scalingListDC[BLOCK_16x16][2];
375 m_scalingListDC[BLOCK_32x32][4] = m_scalingListDC[BLOCK_16x16][4];
376 m_scalingListDC[BLOCK_32x32][5] = m_scalingListDC[BLOCK_16x16][5];
377 }
378 processScalingListEnc(coeff, quantCoeff, s_quantScales[rem] << 4, width, width, ratio, stride, dc);
379 processScalingListDec(coeff, dequantCoeff, s_invQuantScales[rem], width, width, ratio, stride, dc);
380 }
381 else
382 {
383 /* flat quant and dequant coefficients */
384 for (int i = 0; i < count; i++)
385 {
386 quantCoeff[i] = s_quantScales[rem];
387 dequantCoeff[i] = s_invQuantScales[rem];
388 }
389 }
390 }
391 }
392 }
393 }
394
processScalingListEnc(int32_t * coeff,int32_t * quantcoeff,int32_t quantScales,int height,int width,int ratio,int stride,int32_t dc)395 void ScalingList::processScalingListEnc(int32_t *coeff, int32_t *quantcoeff, int32_t quantScales, int height, int width,
396 int ratio, int stride, int32_t dc)
397 {
398 for (int j = 0; j < height; j++)
399 for (int i = 0; i < width; i++)
400 quantcoeff[j * width + i] = quantScales / coeff[stride * (j / ratio) + i / ratio];
401
402 if (ratio > 1)
403 quantcoeff[0] = quantScales / dc;
404 }
405
processScalingListDec(int32_t * coeff,int32_t * dequantcoeff,int32_t invQuantScales,int height,int width,int ratio,int stride,int32_t dc)406 void ScalingList::processScalingListDec(int32_t *coeff, int32_t *dequantcoeff, int32_t invQuantScales, int height, int width,
407 int ratio, int stride, int32_t dc)
408 {
409 for (int j = 0; j < height; j++)
410 for (int i = 0; i < width; i++)
411 dequantcoeff[j * width + i] = invQuantScales * coeff[stride * (j / ratio) + i / ratio];
412
413 if (ratio > 1)
414 dequantcoeff[0] = invQuantScales * dc;
415 }
416
417 }
418