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