1 /*****************************************************************************
2  * Copyright (C) 2013-2020 MulticoreWare, Inc
3  *
4  * Authors: Steve Borho <steve@borho.org>
5  *          Min Chen <chenm003@163.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 "picyuv.h"
27 #include "slice.h"
28 #include "primitives.h"
29 
30 using namespace X265_NS;
31 
PicYuv()32 PicYuv::PicYuv()
33 {
34     m_picBuf[0] = NULL;
35     m_picBuf[1] = NULL;
36     m_picBuf[2] = NULL;
37 
38     m_picOrg[0] = NULL;
39     m_picOrg[1] = NULL;
40     m_picOrg[2] = NULL;
41 
42     m_cuOffsetY = NULL;
43     m_cuOffsetC = NULL;
44     m_buOffsetY = NULL;
45     m_buOffsetC = NULL;
46 
47     m_maxLumaLevel = 0;
48     m_avgLumaLevel = 0;
49 
50     m_maxChromaULevel = 0;
51     m_avgChromaULevel = 0;
52 
53     m_maxChromaVLevel = 0;
54     m_avgChromaVLevel = 0;
55 
56 #if (X265_DEPTH > 8)
57     m_minLumaLevel = 0xFFFF;
58     m_minChromaULevel = 0xFFFF;
59     m_minChromaVLevel = 0xFFFF;
60 #else
61     m_minLumaLevel = 0xFF;
62     m_minChromaULevel = 0xFF;
63     m_minChromaVLevel = 0xFF;
64 #endif
65 
66     m_stride = 0;
67     m_strideC = 0;
68     m_hChromaShift = 0;
69     m_vChromaShift = 0;
70 }
71 
create(x265_param * param,bool picAlloc,pixel * pixelbuf)72 bool PicYuv::create(x265_param* param, bool picAlloc, pixel *pixelbuf)
73 {
74     m_param = param;
75     uint32_t picWidth = m_param->sourceWidth;
76     uint32_t picHeight = m_param->sourceHeight;
77     uint32_t picCsp = m_param->internalCsp;
78     m_picWidth  = picWidth;
79     m_picHeight = picHeight;
80     m_hChromaShift = CHROMA_H_SHIFT(picCsp);
81     m_vChromaShift = CHROMA_V_SHIFT(picCsp);
82     m_picCsp = picCsp;
83 
84     uint32_t numCuInWidth = (m_picWidth + param->maxCUSize - 1)  / param->maxCUSize;
85     uint32_t numCuInHeight = (m_picHeight + param->maxCUSize - 1) / param->maxCUSize;
86 
87     m_lumaMarginX = param->maxCUSize + 32; // search margin and 8-tap filter half-length, padded for 32-byte alignment
88     m_lumaMarginY = param->maxCUSize + 16; // margin for 8-tap filter and infinite padding
89     m_stride = (numCuInWidth * param->maxCUSize) + (m_lumaMarginX << 1);
90 
91     int maxHeight = numCuInHeight * param->maxCUSize;
92     if (pixelbuf)
93         m_picOrg[0] = pixelbuf;
94     else
95     {
96         if (picAlloc)
97         {
98             CHECKED_MALLOC(m_picBuf[0], pixel, m_stride * (maxHeight + (m_lumaMarginY * 2)));
99             m_picOrg[0] = m_picBuf[0] + m_lumaMarginY * m_stride + m_lumaMarginX;
100         }
101     }
102 
103     if (picCsp != X265_CSP_I400)
104     {
105         m_chromaMarginX = m_lumaMarginX;  // keep 16-byte alignment for chroma CTUs
106         m_chromaMarginY = m_lumaMarginY >> m_vChromaShift;
107         m_strideC = ((numCuInWidth * m_param->maxCUSize) >> m_hChromaShift) + (m_chromaMarginX * 2);
108         if (picAlloc)
109         {
110             CHECKED_MALLOC(m_picBuf[1], pixel, m_strideC * ((maxHeight >> m_vChromaShift) + (m_chromaMarginY * 2)));
111             CHECKED_MALLOC(m_picBuf[2], pixel, m_strideC * ((maxHeight >> m_vChromaShift) + (m_chromaMarginY * 2)));
112 
113             m_picOrg[1] = m_picBuf[1] + m_chromaMarginY * m_strideC + m_chromaMarginX;
114             m_picOrg[2] = m_picBuf[2] + m_chromaMarginY * m_strideC + m_chromaMarginX;
115         }
116     }
117     else
118     {
119         m_picBuf[1] = m_picBuf[2] = NULL;
120         m_picOrg[1] = m_picOrg[2] = NULL;
121     }
122     return true;
123 
124 fail:
125     return false;
126 }
127 
getLumaBufLen(uint32_t picWidth,uint32_t picHeight,uint32_t picCsp)128 int PicYuv::getLumaBufLen(uint32_t picWidth, uint32_t picHeight, uint32_t picCsp)
129 {
130     m_picWidth = picWidth;
131     m_picHeight = picHeight;
132     m_hChromaShift = CHROMA_H_SHIFT(picCsp);
133     m_vChromaShift = CHROMA_V_SHIFT(picCsp);
134     m_picCsp = picCsp;
135 
136     uint32_t numCuInWidth = (m_picWidth + m_param->maxCUSize - 1) / m_param->maxCUSize;
137     uint32_t numCuInHeight = (m_picHeight + m_param->maxCUSize - 1) / m_param->maxCUSize;
138 
139     m_lumaMarginX = m_param->maxCUSize + 32; // search margin and 8-tap filter half-length, padded for 32-byte alignment
140     m_lumaMarginY = m_param->maxCUSize + 16; // margin for 8-tap filter and infinite padding
141     m_stride = (numCuInWidth * m_param->maxCUSize) + (m_lumaMarginX << 1);
142 
143     int maxHeight = numCuInHeight * m_param->maxCUSize;
144     int bufLen = (int)(m_stride * (maxHeight + (m_lumaMarginY * 2)));
145 
146     return bufLen;
147 }
148 
149 /* the first picture allocated by the encoder will be asked to generate these
150  * offset arrays. Once generated, they will be provided to all future PicYuv
151  * allocated by the same encoder. */
createOffsets(const SPS & sps)152 bool PicYuv::createOffsets(const SPS& sps)
153 {
154     uint32_t numPartitions = 1 << (m_param->unitSizeDepth * 2);
155 
156     if (m_picCsp != X265_CSP_I400)
157     {
158         CHECKED_MALLOC(m_cuOffsetY, intptr_t, sps.numCuInWidth * sps.numCuInHeight);
159         CHECKED_MALLOC(m_cuOffsetC, intptr_t, sps.numCuInWidth * sps.numCuInHeight);
160         for (uint32_t cuRow = 0; cuRow < sps.numCuInHeight; cuRow++)
161         {
162             for (uint32_t cuCol = 0; cuCol < sps.numCuInWidth; cuCol++)
163             {
164                 m_cuOffsetY[cuRow * sps.numCuInWidth + cuCol] = m_stride * cuRow * m_param->maxCUSize + cuCol * m_param->maxCUSize;
165                 m_cuOffsetC[cuRow * sps.numCuInWidth + cuCol] = m_strideC * cuRow * (m_param->maxCUSize >> m_vChromaShift) + cuCol * (m_param->maxCUSize >> m_hChromaShift);
166             }
167         }
168 
169         CHECKED_MALLOC(m_buOffsetY, intptr_t, (size_t)numPartitions);
170         CHECKED_MALLOC(m_buOffsetC, intptr_t, (size_t)numPartitions);
171         for (uint32_t idx = 0; idx < numPartitions; ++idx)
172         {
173             intptr_t x = g_zscanToPelX[idx];
174             intptr_t y = g_zscanToPelY[idx];
175             m_buOffsetY[idx] = m_stride * y + x;
176             m_buOffsetC[idx] = m_strideC * (y >> m_vChromaShift) + (x >> m_hChromaShift);
177         }
178     }
179     else
180     {
181         CHECKED_MALLOC(m_cuOffsetY, intptr_t, sps.numCuInWidth * sps.numCuInHeight);
182         for (uint32_t cuRow = 0; cuRow < sps.numCuInHeight; cuRow++)
183         for (uint32_t cuCol = 0; cuCol < sps.numCuInWidth; cuCol++)
184             m_cuOffsetY[cuRow * sps.numCuInWidth + cuCol] = m_stride * cuRow * m_param->maxCUSize + cuCol * m_param->maxCUSize;
185 
186         CHECKED_MALLOC(m_buOffsetY, intptr_t, (size_t)numPartitions);
187         for (uint32_t idx = 0; idx < numPartitions; ++idx)
188         {
189             intptr_t x = g_zscanToPelX[idx];
190             intptr_t y = g_zscanToPelY[idx];
191             m_buOffsetY[idx] = m_stride * y + x;
192         }
193     }
194     return true;
195 
196 fail:
197     return false;
198 }
199 
destroy()200 void PicYuv::destroy()
201 {
202     X265_FREE(m_picBuf[0]);
203     X265_FREE(m_picBuf[1]);
204     X265_FREE(m_picBuf[2]);
205 }
206 
207 /* Copy pixels from an x265_picture into internal PicYuv instance.
208  * Shift pixels as necessary, mask off bits above X265_DEPTH for safety. */
copyFromPicture(const x265_picture & pic,const x265_param & param,int padx,int pady)209 void PicYuv::copyFromPicture(const x265_picture& pic, const x265_param& param, int padx, int pady)
210 {
211     /* m_picWidth is the width that is being encoded, padx indicates how many
212      * of those pixels are padding to reach multiple of MinCU(4) size.
213      *
214      * Internally, we need to extend rows out to a multiple of 16 for lowres
215      * downscale and other operations. But those padding pixels are never
216      * encoded.
217      *
218      * The same applies to m_picHeight and pady */
219 
220     /* width and height - without padsize (input picture raw width and height) */
221     int width = m_picWidth - padx;
222     int height = m_picHeight - pady;
223 
224     /* internal pad to multiple of 16x16 blocks */
225     uint8_t rem = width & 15;
226 
227     padx = rem ? 16 - rem : padx;
228     rem = height & 15;
229     pady = rem ? 16 - rem : pady;
230 
231     /* add one more row and col of pad for downscale interpolation, fixes
232      * warnings from valgrind about using uninitialized pixels */
233     padx++;
234     pady++;
235     m_picCsp = pic.colorSpace;
236 
237     X265_CHECK(pic.bitDepth >= 8, "pic.bitDepth check failure");
238 
239     uint64_t lumaSum;
240     uint64_t cbSum;
241     uint64_t crSum;
242     lumaSum = cbSum = crSum = 0;
243 
244     if (m_param->bCopyPicToFrame)
245     {
246         if (pic.bitDepth == 8)
247         {
248 #if (X265_DEPTH > 8)
249         {
250             pixel *yPixel = m_picOrg[0];
251 
252             uint8_t *yChar = (uint8_t*)pic.planes[0];
253             int shift = (X265_DEPTH - 8);
254 
255             primitives.planecopy_cp(yChar, pic.stride[0] / sizeof(*yChar), yPixel, m_stride, width, height, shift);
256 
257             if (param.internalCsp != X265_CSP_I400)
258             {
259                 pixel *uPixel = m_picOrg[1];
260                 pixel *vPixel = m_picOrg[2];
261 
262                 uint8_t *uChar = (uint8_t*)pic.planes[1];
263                 uint8_t *vChar = (uint8_t*)pic.planes[2];
264 
265                 primitives.planecopy_cp(uChar, pic.stride[1] / sizeof(*uChar), uPixel, m_strideC, width >> m_hChromaShift, height >> m_vChromaShift, shift);
266                 primitives.planecopy_cp(vChar, pic.stride[2] / sizeof(*vChar), vPixel, m_strideC, width >> m_hChromaShift, height >> m_vChromaShift, shift);
267             }
268         }
269 #else /* Case for (X265_DEPTH == 8) */
270             // TODO: Does we need this path? may merge into above in future
271         {
272             pixel *yPixel = m_picOrg[0];
273             uint8_t *yChar = (uint8_t*)pic.planes[0];
274 
275             for (int r = 0; r < height; r++)
276             {
277                 memcpy(yPixel, yChar, width * sizeof(pixel));
278 
279                 yPixel += m_stride;
280                 yChar += pic.stride[0] / sizeof(*yChar);
281             }
282 
283             if (param.internalCsp != X265_CSP_I400)
284             {
285                 pixel *uPixel = m_picOrg[1];
286                 pixel *vPixel = m_picOrg[2];
287 
288                 uint8_t *uChar = (uint8_t*)pic.planes[1];
289                 uint8_t *vChar = (uint8_t*)pic.planes[2];
290 
291                 for (int r = 0; r < height >> m_vChromaShift; r++)
292                 {
293                     memcpy(uPixel, uChar, (width >> m_hChromaShift) * sizeof(pixel));
294                     memcpy(vPixel, vChar, (width >> m_hChromaShift) * sizeof(pixel));
295 
296                     uPixel += m_strideC;
297                     vPixel += m_strideC;
298                     uChar += pic.stride[1] / sizeof(*uChar);
299                     vChar += pic.stride[2] / sizeof(*vChar);
300                 }
301             }
302         }
303 #endif /* (X265_DEPTH > 8) */
304         }
305         else /* pic.bitDepth > 8 */
306         {
307             /* defensive programming, mask off bits that are supposed to be zero */
308             uint16_t mask = (1 << X265_DEPTH) - 1;
309             int shift = abs(pic.bitDepth - X265_DEPTH);
310             pixel *yPixel = m_picOrg[0];
311 
312             uint16_t *yShort = (uint16_t*)pic.planes[0];
313 
314             if (pic.bitDepth > X265_DEPTH)
315             {
316                 /* shift right and mask pixels to final size */
317                 primitives.planecopy_sp(yShort, pic.stride[0] / sizeof(*yShort), yPixel, m_stride, width, height, shift, mask);
318             }
319             else /* Case for (pic.bitDepth <= X265_DEPTH) */
320             {
321                 /* shift left and mask pixels to final size */
322                 primitives.planecopy_sp_shl(yShort, pic.stride[0] / sizeof(*yShort), yPixel, m_stride, width, height, shift, mask);
323             }
324 
325             if (param.internalCsp != X265_CSP_I400)
326             {
327                 pixel *uPixel = m_picOrg[1];
328                 pixel *vPixel = m_picOrg[2];
329 
330                 uint16_t *uShort = (uint16_t*)pic.planes[1];
331                 uint16_t *vShort = (uint16_t*)pic.planes[2];
332 
333                 if (pic.bitDepth > X265_DEPTH)
334                 {
335                     primitives.planecopy_sp(uShort, pic.stride[1] / sizeof(*uShort), uPixel, m_strideC, width >> m_hChromaShift, height >> m_vChromaShift, shift, mask);
336                     primitives.planecopy_sp(vShort, pic.stride[2] / sizeof(*vShort), vPixel, m_strideC, width >> m_hChromaShift, height >> m_vChromaShift, shift, mask);
337                 }
338                 else /* Case for (pic.bitDepth <= X265_DEPTH) */
339                 {
340                     primitives.planecopy_sp_shl(uShort, pic.stride[1] / sizeof(*uShort), uPixel, m_strideC, width >> m_hChromaShift, height >> m_vChromaShift, shift, mask);
341                     primitives.planecopy_sp_shl(vShort, pic.stride[2] / sizeof(*vShort), vPixel, m_strideC, width >> m_hChromaShift, height >> m_vChromaShift, shift, mask);
342                 }
343             }
344         }
345     }
346     else
347     {
348         m_picOrg[0] = (pixel*)pic.planes[0];
349         m_picOrg[1] = (pixel*)pic.planes[1];
350         m_picOrg[2] = (pixel*)pic.planes[2];
351     }
352 
353     pixel *Y = m_picOrg[0];
354     pixel *U = m_picOrg[1];
355     pixel *V = m_picOrg[2];
356 
357     pixel *yPic = m_picOrg[0];
358     pixel *uPic = m_picOrg[1];
359     pixel *vPic = m_picOrg[2];
360 
361     if(param.minLuma != 0 || param.maxLuma != PIXEL_MAX)
362     {
363         for (int r = 0; r < height; r++)
364         {
365             for (int c = 0; c < width; c++)
366             {
367                 yPic[c] = X265_MIN(yPic[c], (pixel)param.maxLuma);
368                 yPic[c] = X265_MAX(yPic[c], (pixel)param.minLuma);
369             }
370             yPic += m_stride;
371         }
372     }
373     yPic = m_picOrg[0];
374     if (param.csvLogLevel >= 2 || param.maxCLL || param.maxFALL)
375     {
376         for (int r = 0; r < height; r++)
377         {
378             for (int c = 0; c < width; c++)
379             {
380                 m_maxLumaLevel = X265_MAX(yPic[c], m_maxLumaLevel);
381                 m_minLumaLevel = X265_MIN(yPic[c], m_minLumaLevel);
382                 lumaSum += yPic[c];
383             }
384             yPic += m_stride;
385         }
386         m_avgLumaLevel = (double)lumaSum / (m_picHeight * m_picWidth);
387     }
388     if (param.csvLogLevel >= 2)
389     {
390         if (param.internalCsp != X265_CSP_I400)
391         {
392             for (int r = 0; r < height >> m_vChromaShift; r++)
393             {
394                 for (int c = 0; c < width >> m_hChromaShift; c++)
395                 {
396                     m_maxChromaULevel = X265_MAX(uPic[c], m_maxChromaULevel);
397                     m_minChromaULevel = X265_MIN(uPic[c], m_minChromaULevel);
398                     cbSum += uPic[c];
399 
400                     m_maxChromaVLevel = X265_MAX(vPic[c], m_maxChromaVLevel);
401                     m_minChromaVLevel = X265_MIN(vPic[c], m_minChromaVLevel);
402                     crSum += vPic[c];
403                 }
404 
405                 uPic += m_strideC;
406                 vPic += m_strideC;
407             }
408             m_avgChromaULevel = (double)cbSum / ((height >> m_vChromaShift) * (width >> m_hChromaShift));
409             m_avgChromaVLevel = (double)crSum / ((height >> m_vChromaShift) * (width >> m_hChromaShift));
410         }
411     }
412 
413 #if HIGH_BIT_DEPTH
414     bool calcHDRParams = !!param.minLuma || (param.maxLuma != PIXEL_MAX);
415     /* Apply min/max luma bounds for HDR pixel manipulations */
416     if (calcHDRParams)
417     {
418         X265_CHECK(pic.bitDepth == 10, "HDR stats can be applied/calculated only for 10bpp content");
419         uint64_t sumLuma;
420         m_maxLumaLevel = primitives.planeClipAndMax(Y, m_stride, width, height, &sumLuma, (pixel)param.minLuma, (pixel)param.maxLuma);
421         m_avgLumaLevel = (double) sumLuma / (m_picHeight * m_picWidth);
422     }
423 #else
424     (void) param;
425 #endif
426 
427     /* extend the right edge if width was not multiple of the minimum CU size */
428     for (int r = 0; r < height; r++)
429     {
430         for (int x = 0; x < padx; x++)
431             Y[width + x] = Y[width - 1];
432         Y += m_stride;
433     }
434 
435     /* extend the bottom if height was not multiple of the minimum CU size */
436     Y = m_picOrg[0] + (height - 1) * m_stride;
437     for (int i = 1; i <= pady; i++)
438         memcpy(Y + i * m_stride, Y, (width + padx) * sizeof(pixel));
439 
440     if (param.internalCsp != X265_CSP_I400)
441     {
442         for (int r = 0; r < height >> m_vChromaShift; r++)
443         {
444             for (int x = 0; x < padx >> m_hChromaShift; x++)
445             {
446                 U[(width >> m_hChromaShift) + x] = U[(width >> m_hChromaShift) - 1];
447                 V[(width >> m_hChromaShift) + x] = V[(width >> m_hChromaShift) - 1];
448             }
449 
450             U += m_strideC;
451             V += m_strideC;
452         }
453 
454         U = m_picOrg[1] + ((height >> m_vChromaShift) - 1) * m_strideC;
455         V = m_picOrg[2] + ((height >> m_vChromaShift) - 1) * m_strideC;
456 
457         for (int j = 1; j <= pady >> m_vChromaShift; j++)
458         {
459             memcpy(U + j * m_strideC, U, ((width + padx) >> m_hChromaShift) * sizeof(pixel));
460             memcpy(V + j * m_strideC, V, ((width + padx) >> m_hChromaShift) * sizeof(pixel));
461         }
462     }
463 }
464 
465 namespace X265_NS {
466 
467 template<uint32_t OUTPUT_BITDEPTH_DIV8>
md5_block(MD5Context & md5,const pixel * plane,uint32_t n)468 static void md5_block(MD5Context& md5, const pixel* plane, uint32_t n)
469 {
470     /* create a 64 byte buffer for packing pixel's into */
471     uint8_t buf[64 / OUTPUT_BITDEPTH_DIV8][OUTPUT_BITDEPTH_DIV8];
472 
473     for (uint32_t i = 0; i < n; i++)
474     {
475         pixel pel = plane[i];
476         /* perform bitdepth and endian conversion */
477         for (uint32_t d = 0; d < OUTPUT_BITDEPTH_DIV8; d++)
478             buf[i][d] = (uint8_t)(pel >> (d * 8));
479     }
480 
481     MD5Update(&md5, (uint8_t*)buf, n * OUTPUT_BITDEPTH_DIV8);
482 }
483 
484 /* Update md5 with all samples in plane in raster order, each sample
485  * is adjusted to OUTBIT_BITDEPTH_DIV8 */
486 template<uint32_t OUTPUT_BITDEPTH_DIV8>
md5_plane(MD5Context & md5,const pixel * plane,uint32_t width,uint32_t height,intptr_t stride)487 static void md5_plane(MD5Context& md5, const pixel* plane, uint32_t width, uint32_t height, intptr_t stride)
488 {
489     /* N is the number of samples to process per md5 update.
490      * All N samples must fit in buf */
491     uint32_t N = 32;
492     uint32_t width_modN = width % N;
493     uint32_t width_less_modN = width - width_modN;
494 
495     for (uint32_t y = 0; y < height; y++)
496     {
497         /* convert pel's into uint32_t chars in little endian byte order.
498          * NB, for 8bit data, data is truncated to 8bits. */
499         for (uint32_t x = 0; x < width_less_modN; x += N)
500             md5_block<OUTPUT_BITDEPTH_DIV8>(md5, &plane[y * stride + x], N);
501 
502         /* mop up any of the remaining line */
503         md5_block<OUTPUT_BITDEPTH_DIV8>(md5, &plane[y * stride + width_less_modN], width_modN);
504     }
505 }
506 
updateCRC(const pixel * plane,uint32_t & crcVal,uint32_t height,uint32_t width,intptr_t stride)507 void updateCRC(const pixel* plane, uint32_t& crcVal, uint32_t height, uint32_t width, intptr_t stride)
508 {
509     uint32_t crcMsb;
510     uint32_t bitVal;
511     uint32_t bitIdx;
512 
513     for (uint32_t y = 0; y < height; y++)
514     {
515         for (uint32_t x = 0; x < width; x++)
516         {
517             // take CRC of first pictureData byte
518             for (bitIdx = 0; bitIdx < 8; bitIdx++)
519             {
520                 crcMsb = (crcVal >> 15) & 1;
521                 bitVal = (plane[y * stride + x] >> (7 - bitIdx)) & 1;
522                 crcVal = (((crcVal << 1) + bitVal) & 0xffff) ^ (crcMsb * 0x1021);
523             }
524 
525 #if _MSC_VER
526 #pragma warning(disable: 4127) // conditional expression is constant
527 #endif
528             // take CRC of second pictureData byte if bit depth is greater than 8-bits
529             if (X265_DEPTH > 8)
530             {
531                 for (bitIdx = 0; bitIdx < 8; bitIdx++)
532                 {
533                     crcMsb = (crcVal >> 15) & 1;
534                     bitVal = (plane[y * stride + x] >> (15 - bitIdx)) & 1;
535                     crcVal = (((crcVal << 1) + bitVal) & 0xffff) ^ (crcMsb * 0x1021);
536                 }
537             }
538         }
539     }
540 }
541 
crcFinish(uint32_t & crcVal,uint8_t digest[16])542 void crcFinish(uint32_t& crcVal, uint8_t digest[16])
543 {
544     uint32_t crcMsb;
545 
546     for (int bitIdx = 0; bitIdx < 16; bitIdx++)
547     {
548         crcMsb = (crcVal >> 15) & 1;
549         crcVal = ((crcVal << 1) & 0xffff) ^ (crcMsb * 0x1021);
550     }
551 
552     digest[0] = (crcVal >> 8)  & 0xff;
553     digest[1] =  crcVal        & 0xff;
554 }
555 
updateChecksum(const pixel * plane,uint32_t & checksumVal,uint32_t height,uint32_t width,intptr_t stride,int row,uint32_t cuHeight)556 void updateChecksum(const pixel* plane, uint32_t& checksumVal, uint32_t height, uint32_t width, intptr_t stride, int row, uint32_t cuHeight)
557 {
558     uint8_t xor_mask;
559 
560     for (uint32_t y = row * cuHeight; y < ((row * cuHeight) + height); y++)
561     {
562         for (uint32_t x = 0; x < width; x++)
563         {
564             xor_mask = (uint8_t)((x & 0xff) ^ (y & 0xff) ^ (x >> 8) ^ (y >> 8));
565             checksumVal = (checksumVal + ((plane[y * stride + x] & 0xff) ^ xor_mask)) & 0xffffffff;
566 
567             if (X265_DEPTH > 8)
568                 checksumVal = (checksumVal + ((plane[y * stride + x] >> 7 >> 1) ^ xor_mask)) & 0xffffffff;
569         }
570     }
571 }
572 
checksumFinish(uint32_t checksum,uint8_t digest[16])573 void checksumFinish(uint32_t checksum, uint8_t digest[16])
574 {
575     digest[0] = (checksum >> 24) & 0xff;
576     digest[1] = (checksum >> 16) & 0xff;
577     digest[2] = (checksum >> 8)  & 0xff;
578     digest[3] =  checksum        & 0xff;
579 }
580 
updateMD5Plane(MD5Context & md5,const pixel * plane,uint32_t width,uint32_t height,intptr_t stride)581 void updateMD5Plane(MD5Context& md5, const pixel* plane, uint32_t width, uint32_t height, intptr_t stride)
582 {
583     /* choose an md5_plane packing function based on the system bitdepth */
584     typedef void(*MD5PlaneFunc)(MD5Context&, const pixel*, uint32_t, uint32_t, intptr_t);
585     MD5PlaneFunc md5_plane_func;
586     md5_plane_func = X265_DEPTH <= 8 ? (MD5PlaneFunc)md5_plane<1> : (MD5PlaneFunc)md5_plane<2>;
587 
588     md5_plane_func(md5, plane, width, height, stride);
589 }
590 }
591