-
Karsten Suehring authoredKarsten Suehring authored
SEIFilmGrainSynthesizer.cpp 51.49 KiB
/* The copyright in this software is being made available under the BSD
* License, included below. This software may be subject to other third party
* and contributor rights, including patent rights, and no such rights are
* granted under this license.
*
* Copyright (c) 2010-2025, ITU/ISO/IEC
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
/** \file SEIFilmGrainSynthesizer.cpp
\brief SMPTE RDD5 based film grain synthesis functionality from SEI messages
*/
#include "SEIFilmGrainSynthesizer.h"
#include <stdio.h>
#include <cmath>
/* static look up table definitions */
static const int8_t gaussianLUT[2048] =
{
-11, 12, 103, -11, 42, -35, 12, 59, 77, 98, -87, 3, 65, -78, 45, 56,
-51, 21, 13, -11, -20, -19, 33, -127, 17, -6, -105, 18, 19, 71, 48, -10,
-38, 42, -2, 75, -67, 52, -90, 33, -47, 21, -3, -56, 49, 1, -57, -42,
-1, 120, -127, -108, -49, 9, 14, 127, 122, 109, 52, 127, 2, 7, 114, 19,
30, 12, 77, 112, 82, -61, -127, 111, -52, -29, 2, -49, -24, 58, -29, -73,
12, 112, 67, 79, -3, -114, -87, -6, -5, 40, 58, -81, 49, -27, -31, -34,
-105, 50, 16, -24, -35, -14, -15, -127, -55, -22, -55, -127, -112, 5, -26, -72,
127, 127, -2, 41, 87, -65, -16, 55, 19, 91, -81, -65, -64, 35, -7, -54,
99, -7, 88, 125, -26, 91, 0, 63, 60, -14, -23, 113, -33, 116, 14, 26,
51, -16, 107, -8, 53, 38, -34, 17, -7, 4, -91, 6, 63, 63, -15, 39,
-36, 19, 55, 17, -51, 40, 33, -37, 126, -39, -118, 17, -30, 0, 19, 98,
60, 101, -12, -73, -17, -52, 98, 3, 3, 60, 33, -3, -2, 10, -42, -106,
-38, 14, 127, 16, -127, -31, -86, -39, -56, 46, -41, 75, 23, -19, -22, -70,
74, -54, -2, 32, -45, 17, -92, 59, -64, -67, 56, -102, -29, -87, -34, -92,
68, 5, -74, -61, 93, -43, 14, -26, -38, -126, -17, 16, -127, 64, 34, 31,
93, 17, -51, -59, 71, 77, 81, 127, 127, 61, 33, -106, -93, 0, 0, 75,
-69, 71, 127, -19, -111, 30, 23, 15, 2, 39, 92, 5, 42, 2, -6, 38,
15, 114, -30, -37, 50, 44, 106, 27, 119, 7, -80, 25, -68, -21, 92, -11,
-1, 18, 41, -50, 79, -127, -43, 127, 18, 11, -21, 32, -52, 27, -88, -90,
-39, -19, -10, 24, -118, 72, -24, -44, 2, 12, 86, -107, 39, -33, -127, 47,
51, -24, -22, 46, 0, 15, -35, -69, -2, -74, 24, -6, 0, 29, -3, 45,
32, -32, 117, -45, 79, -24, -17, -109, -10, -70, 88, -48, 24, -91, 120, -37,
50, -127, 58, 32, -82, -10, -17, -7, 46, -127, -15, 89, 127, 17, 98, -39,
-33, 37, 42, -40, -32, -21, 105, -19, 19, 19, -59, -9, 30, 0, -127, 34,
127, -84, 75, 24, -40, -49, -127, -107, -14, 45, -75, 1, 30, -20, 41, -68,
-40, 12, 127, -3, 5, 20, -73, -59, -127, -3, -3, -53, -6, -119, 93, 120,
-80, -50, 0, 20, -46, 67, 78, -12, -22, -127, 36, -41, 56, 119, -5, -116,
-22, 68, -14, -90, 24, -82, -44, -127, 107, -25, -37, 40, -7, -7, -82, 5,
-87, 44, -34, 9, -127, 39, 70, 49, -63, 74, -49, 109, -27, -89, -47, -39,
44, 49, -4, 60, -42, 80, 9, -127, -9, -56, -49, 125, -66, 47, 36, 117,
15, -11, -96, 109, 94, -17, -56, 70, 8, -14, -5, 50, 37, -45, 120, -30,
-76, 40, -46, 6, 3, 69, 17, -78, 1, -79, 6, 127, 43, 26, 127, -127,
28, -55, -26, 55, 112, 48, 107, -1, -77, -1, 53, -9, -22, -43, 123, 108,
127, 102, 68, 46, 5, 1, 123, -13, -55, -34, -49, 89, 65, -105, -5, 94,
-53, 62, 45, 30, 46, 18, -35, 15, 41, 47, -98, -24, 94, -75, 127, -114,
127, -68, 1, -17, 51, -95, 47, 12, 34, -45, -75, 89, -107, -9, -58, -29,
-109, -24, 127, -61, -13, 77, -45, 17, 19, 83, -24, 9, 127, -66, 54, 4,
26, 13, 111, 43, -113, -22, 10, -24, 83, 67, -14, 75, -123, 59, 127, -12,
99, -19, 64, -38, 54, 9, 7, 61, -56, 3, -57, 113, -104, -59, 3, -9,
-47, 74, 85, -55, -34, 12, 118, 28, 93, -72, 13, -99, -72, -20, 30, 72,
-94, 19, -54, 64, -12, -63, -25, 65, 72, -10, 127, 0, -127, 103, -20, -73,
-112, -103, -6, 28, -42, -21, -59, -29, -26, 19, -4, -51, 94, -58, -95, -37,
35, 20, -69, 127, -19, -127, -22, -120, -53, 37, 74, -127, -1, -12, -119, -53,
-28, 38, 69, 17, 16, -114, 89, 62, 24, 37, -23, 49, -101, -32, -9, -95,
-53, 5, 93, -23, -49, -8, 51, 3, -75, -90, -10, -39, 127, -86, -22, 20,
20, 113, 75, 52, -31, 92, -63, 7, -12, 46, 36, 101, -43, -17, -53, -7,
-38, -76, -31, -21, 62, 31, 62, 20, -127, 31, 64, 36, 102, -85, -10, 77,
80, 58, -79, -8, 35, 8, 80, -24, -9, 3, -17, 72, 127, 83, -87, 55,
18, -119, -123, 36, 10, 127, 56, -55, 113, 13, 26, 32, -13, -48, 22, -13,
5, 58, 27, 24, 26, -11, -36, 37, -92, 78, 81, 9, 51, 14, 67, -13,
0, 32, 45, -76, 32, -39, -22, -49, -127, -27, 31, -9, 36, 14, 71, 13,
57, 12, -53, -86, 53, -44, -35, 2, 127, 12, -66, -44, 46, -115, 3, 10,
56, -35, 119, -19, -61, 52, -59, -127, -49, -23, 4, -5, 17, -82, -6, 127,
25, 79, 67, 64, -25, 14, -64, -37, -127, -28, 21, -63, 66, -53, -41, 109,
-62, 15, -22, 13, 29, -63, 20, 27, 95, -44, -59, -116, -10, 79, -49, 22,
-43, -16, 46, -47, -120, -36, -29, -52, -44, 29, 127, -13, 49, -9, -127, 75,
-28, -23, 88, 59, 11, -95, 81, -59, 58, 60, -26, 40, -92, -3, -22, -58,
-45, -59, -22, -53, 71, -29, 66, -32, -23, 14, -17, -66, -24, -28, -62, 47,
38, 17, 16, -37, -24, -11, 8, -27, -19, 59, 45, -49, -47, -4, -22, -81,
30, -67, -127, 74, 102, 5, -18, 98, 34, -66, 42, -52, 7, -59, 24, -58,
-19, -24, -118, -73, 91, 15, -16, 79, -32, -79, -127, -36, 41, 77, -83, 2,
56, 22, -75, 127, -16, -21, 12, 31, 56, -113, -127, 90, 55, 61, 12, 55,
-14, -113, -14, 32, 49, -67, -17, 91, -10, 1, 21, 69, -70, 99, -19, -112,
66, -90, -10, -9, -71, 127, 50, -81, -49, 24, 61, -61, -111, 7, -41, 127,
88, -66, 108, -127, -6, 36, -14, 41, -50, 14, 14, 73, -101, -28, 77, 127,
-8, -100, 88, 38, 121, 88, -125, -60, 13, -94, -115, 20, -67, -87, -94, -119,
44, -28, -30, 18, 5, -53, -61, 20, -43, 11, -77, -60, 13, 29, 3, 6,
-72, 38, -60, -11, 108, -53, 41, 66, -12, -127, -127, -49, 24, 29, 46, 36,
91, 34, -33, 116, -51, -34, -52, 91, 7, -83, 73, -26, -103, 24, -10, 76,
84, 5, 68, -80, -13, -17, -32, -48, 20, 50, 26, 10, 63, -104, -14, 37,
127, 114, 97, 35, 1, -33, -55, 127, -124, -33, 61, -7, 119, -32, -127, -53,
-42, 63, 3, -5, -26, 70, -58, -33, -44, -43, 34, -56, -127, 127, 25, -35,
-11, 16, -81, 29, -58, 40, -127, -127, 20, -47, -11, -36, -63, -52, -32, -82,
78, -76, -73, 8, 27, -72, -9, -74, -85, -86, -57, 25, 78, -10, -97, 35,
-65, 8, -59, 14, 1, -42, 32, -88, -44, 17, -3, -9, 59, 40, 12, -108,
-40, 24, 34, 18, -28, 2, 51, -110, -4, 100, 1, 65, 22, 0, 127, 61,
45, 25, -31, 6, 9, -7, -48, 99, 16, 44, -2, -40, 32, -39, -52, 10,
-110, -19, 56, -127, 69, 26, 51, 92, 40, 61, -52, 45, -38, 13, 85, 122,
27, 66, 45, -111, -83, -3, 31, 37, 19, -36, 58, 71, 39, -78, -47, 58,
-78, 8, -62, -36, -14, 61, 42, -127, 71, -4, 24, -54, 52, -127, 67, -4,
-42, 30, -63, 59, -3, -1, -18, -46, -92, -81, -96, -14, -53, -10, -11, -77,
13, 1, 8, -67, -127, 127, -28, 26, -14, 18, -13, -26, 2, 10, -46, -32,
-15, 27, -31, -59, 59, 77, -121, 28, 40, -54, -62, -31, -21, -37, -32, -6,
-127, -25, -60, 70, -127, 112, -127, 127, 88, -7, 116, 110, 53, 87, -127, 3,
16, 23, 74, -106, -51, 3, 74, -82, -112, -74, 65, 81, 25, 53, 127, -45,
-50, -103, -41, -65, -29, 79, -67, 64, -33, -30, -8, 127, 0, -13, -51, 67,
-14, 5, -92, 29, -35, -8, -90, -57, -3, 36, 43, 44, -31, -69, -7, 36,
39, -51, 43, -81, 58, 6, 127, 12, 57, 66, 46, 59, -43, -42, 41, -15,
-120, 24, 3, -11, 19, -13, 51, 28, 3, 55, -48, -12, -1, 2, 97, -19,
29, 42, 13, 43, 78, -44, 56, -108, -43, -19, 127, 15, -11, -18, -81, 83,
-37, 77, -109, 15, 65, -50, 43, 12, 13, 27, 28, 61, 57, 30, 26, 106,
-18, 56, 13, 97, 4, -8, -62, -103, 94, 108, -44, 52, 27, -47, -9, 105,
-53, 46, 89, 103, -33, 38, -34, 55, 51, 70, -94, -35, -87, -107, -19, -31,
9, -19, 79, -14, 77, 5, -19, -107, 85, 21, -45, -39, -42, 9, -29, 74,
47, -75, 60, -127, 120, -112, -57, -32, 41, 7, 79, 76, 66, 57, 41, -25,
31, 37, -47, -36, 43, -73, -37, 63, 127, -69, -52, 90, -33, -61, 60, -55,
44, 15, 4, -67, 13, -92, 64, 29, -39, -3, 83, -2, -38, -85, -86, 58,
35, -69, -61, 29, -37, -95, -78, 4, 30, -4, -32, -80, -22, -9, -77, 46,
7, -93, -71, 65, 9, -50, 127, -70, 26, -12, -39, -114, 63, -127, -100, 4,
-32, 111, 22, -60, 65, -101, 26, -42, 21, -59, -27, -74, 2, -94, 6, 126,
5, 76, -88, -9, -43, -101, 127, 1, 125, 92, -63, 52, 56, 4, 81, -127,
127, 80, 127, -29, 30, 116, -74, -17, -57, 105, 48, 45, 25, -72, 48, -38,
-108, 31, -34, 4, -11, 41, -127, 52, -104, -43, -37, 52, 2, 47, 87, -9,
77, 27, -41, -25, 90, 86, -56, 75, 10, 33, 78, 58, 127, 127, -7, -73,
49, -33, -106, -35, 38, 57, 53, -17, -4, 83, 52, -108, 54, -125, 28, 23,
56, -43, -88, -17, -6, 47, 23, -9, 0, -13, 111, 75, 27, -52, -38, -34,
39, 30, 66, 39, 38, -64, 38, 3, 21, -32, -51, -28, 54, -38, -87, 20,
52, 115, 18, -81, -70, 0, -14, -46, -46, -3, 125, 16, -14, 23, -82, -84,
-69, -20, -65, -127, 9, 81, -49, 61, 7, -36, -45, -42, 57, -26, 47, 20,
-85, 46, -13, 41, -37, -75, -60, 86, -78, -127, 12, 50, 2, -3, 13, 47,
5, 19, -78, -55, -27, 65, -71, 12, -108, 20, -16, 11, -31, 63, -55, 37,
75, -17, 127, -73, -33, -28, -120, 105, 68, 106, -103, -106, 71, 61, 2, 23,
-3, 33, -5, -15, -67, -15, -23, -54, 15, -63, 76, 58, -110, 1, 83, -27,
22, 75, -39, -17, -11, 64, -17, -127, -54, -66, 31, 96, 116, 3, -114, -7,
-108, -63, 97, 9, 50, 8, 75, -28, 72, 112, -36, -112, 95, -50, 23, -13,
-19, 55, 21, 23, 92, 91, 22, -49, 16, -75, 23, 9, -49, -97, -37, 49,
-36, 36, -127, -86, 43, 127, -24, -24, 84, 83, -35, -34, -12, 109, 102, -38,
51, -68, 34, 19, -22, 49, -32, 127, 40, 24, -93, -4, -3, 105, 3, -58,
-18, 8, 127, -18, 125, 68, 69, -62, 30, -36, 54, -57, -24, 17, 43, -36,
-27, -57, -67, -21, -10, -49, 68, 12, 65, 4, 48, 55, 127, -75, 44, 89,
-66, -13, -78, -82, -91, 22, 30, 33, -40, -87, -34, 96, -91, 39, 10, -64,
-3, -12, 127, -50, -37, -56, 23, -35, -36, -54, 90, -91, 2, 50, 77, -6,
-127, 16, 46, -5, -73, 0, -56, -18, -72, 28, 93, 60, 49, 20, 18, 111,
-111, 32, -83, 47, 47, -10, 35, -88, 43, 57, -98, 127, -17, 0, 1, -39,
-127, -2, 0, 63, 93, 0, 36, -66, -61, -19, 39, -127, 58, 50, -17, 127,
88, -43, -108, -51, -16, 7, -36, 68, 46, -14, 107, 40, 57, 7, 19, 8,
3, 88, -90, -92, -18, -21, -24, 13, 7, -4, -78, -91, -4, 8, -35, -5,
19, 2, -111, 4, -66, -81, 122, -20, -34, -37, -84, 127, 68, 46, 17, 47
};
static const uint32_t seedLUT[256] = {
747538460, 1088979410, 1744950180, 1767011913, 1403382928, 521866116, 1060417601, 2110622736,
1557184770, 105289385, 585624216, 1827676546, 1191843873, 1018104344, 1123590530, 663361569,
2023850500, 76561770, 1226763489, 80325252, 1992581442, 502705249, 740409860, 516219202,
557974537, 1883843076, 720112066, 1640137737, 1820967556, 40667586, 155354121, 1820967557,
1115949072, 1631803309, 98284748, 287433856, 2119719977, 988742797, 1827432592, 579378475,
1017745956, 1309377032, 1316535465, 2074315269, 1923385360, 209722667, 1546228260, 168102420,
135274561, 355958469, 248291472, 2127839491, 146920100, 585982612, 1611702337, 696506029,
1386498192, 1258072451, 1212240548, 1043171860, 1217404993, 1090770605, 1386498193, 169093201,
541098240, 1468005469, 456510673, 1578687785, 1838217424, 2010752065, 2089828354, 1362717428,
970073673, 854129835, 714793201, 1266069081, 1047060864, 1991471829, 1098097741, 913883585,
1669598224, 1337918685, 1219264706, 1799741108, 1834116681, 683417731, 1120274457, 1073098457,
1648396544, 176642749, 31171789, 718317889, 1266977808, 1400892508, 549749008, 1808010512,
67112961, 1005669825, 903663673, 1771104465, 1277749632, 1229754427, 950632997, 1979371465,
2074373264, 305357524, 1049387408, 1171033360, 1686114305, 2147468765, 1941195985, 117709841,
809550080, 991480851, 1816248997, 1561503561, 329575568, 780651196, 1659144592, 1910793616,
604016641, 1665084765, 1530186961, 1870928913, 809550081, 2079346113, 71307521, 876663040,
1073807360, 832356664, 1573927377, 204073344, 2026918147, 1702476788, 2043881033, 57949587,
2001393952, 1197426649, 1186508931, 332056865, 950043140, 890043474, 349099312, 148914948,
236204097, 2022643605, 1441981517, 498130129, 1443421481, 924216797, 1817491777, 1913146664,
1411989632, 929068432, 495735097, 1684636033, 1284520017, 432816184, 1344884865, 210843729,
676364544, 234449232, 12112337, 1350619139, 1753272996, 2037118872, 1408560528, 533334916,
1043640385, 357326099, 201376421, 110375493, 541106497, 416159637, 242512193, 777294080,
1614872576, 1535546636, 870600145, 910810409, 1821440209, 1605432464, 1145147393, 951695441,
1758494976, 1506656568, 1557150160, 608221521, 1073840384, 217672017, 684818688, 1750138880,
16777217, 677990609, 953274371, 1770050213, 1359128393, 1797602707, 1984616737, 1865815816,
2120835200, 2051677060, 1772234061, 1579794881, 1652821009, 1742099468, 1887260865, 46468113,
1011925248, 1134107920, 881643832, 1354774993, 472508800, 1892499769, 1752793472, 1962502272,
687898625, 883538000, 1354355153, 1761673473, 944820481, 2020102353, 22020353, 961597696,
1342242816, 964808962, 1355809701, 17016649, 1386540177, 647682692, 1849012289, 751668241,
1557184768, 127374604, 1927564752, 1045744913, 1614921984, 43588881, 1016185088, 1544617984,
1090519041, 136122424, 215038417, 1563027841, 2026918145, 1688778833, 701530369, 1372639488,
1342242817, 2036945104, 953274369, 1750192384, 16842753, 964808960, 1359020032, 1358954497
};
static const uint32_t deblockFactor[13] =
{ 64, 71, 77, 84, 90, 96, 103, 109, 116, 122, 128, 128, 128 };
SEIFilmGrainSynthesizer::SEIFilmGrainSynthesizer()
: m_width(0)
, m_height(0)
, m_chromaFormat(ChromaFormat::UNDEFINED)
, m_bitDepth(0)
, m_idrPicId(0)
, m_grainSynt(nullptr)
, m_fgsBlkSize(8)
, m_poc(0)
, m_errorCode(0)
, m_fgcParameters(nullptr)
{
}
void SEIFilmGrainSynthesizer::create(uint32_t width, uint32_t height, ChromaFormat fmt, uint8_t bitDepth, uint32_t idrPicId)
{
m_width = width;
m_height = height;
m_chromaFormat = fmt;
m_bitDepth = bitDepth;
m_idrPicId = idrPicId;
m_fgsBlkSize = 8;
m_errorCode = 0;
if (!m_grainSynt)
m_grainSynt = new GrainSynthesisStruct;
if (!m_fgcParameters)
m_fgcParameters = new SEIFilmGrainCharacteristics;
}
SEIFilmGrainSynthesizer::~SEIFilmGrainSynthesizer()
{
destroy();
}
void SEIFilmGrainSynthesizer::fgsInit()
{
deriveFGSBlkSize();
dataBaseGen();
}
void SEIFilmGrainSynthesizer::destroy()
{
if (m_fgcParameters)
delete m_fgcParameters;
if (m_grainSynt)
delete m_grainSynt;
}
void SEIFilmGrainSynthesizer::grainSynthesizeAndBlend(PelStorage* pGrainBuf, bool isIdrPic)
{
uint8_t compCtr; /* number of color components */
uint8_t color_offset[MAX_NUM_COMPONENT];
uint32_t widthComp[MAX_NUM_COMPONENT], heightComp[MAX_NUM_COMPONENT];
ptrdiff_t strideComp[MAX_NUM_COMPONENT];
uint32_t * offsetsArr[MAX_NUM_COMPONENT];
Pel * decComp[MAX_NUM_COMPONENT];
uint32_t pseudoRandValEc;
uint32_t picOffset;
/* from SMPTE RDD5 */
color_offset[0] = COLOUR_OFFSET_LUMA;
color_offset[1] = COLOUR_OFFSET_CR;
color_offset[2] = COLOUR_OFFSET_CB;
if (0 != m_fgcParameters->m_filmGrainCharacteristicsCancelFlag)
{
return;
}
const int numComp = getNumberValidComponents(m_chromaFormat);
widthComp[0] = m_width;
heightComp[0] = m_height;
if (ChromaFormat::_420 == m_chromaFormat)
{
widthComp[1] = (m_width >> 1);
widthComp[2] = (m_width >> 1);
heightComp[1] = (m_height >> 1);
heightComp[2] = (m_height >> 1);
}
else if (ChromaFormat::_422 == m_chromaFormat)
{
widthComp[1] = (m_width >> 1);
widthComp[2] = (m_width >> 1);
heightComp[1] = m_height;
heightComp[2] = m_height;
}
/*Allocate memory for offsets assuming 16x16 block size,
32x32 will need lesser than this*/
uint32_t maxNumBlocks = ((m_width >> 4) + 1) * ((m_height >> 4) + 1);
for (compCtr = 0; compCtr < numComp; compCtr++)
{
offsetsArr[compCtr] = new uint32_t[maxNumBlocks];
}
decComp[0] = pGrainBuf->bufs[0].buf;
decComp[1] = pGrainBuf->bufs[1].buf;
decComp[2] = pGrainBuf->bufs[2].buf;
/* component strides */
strideComp[0] = pGrainBuf->bufs[0].stride;
strideComp[1] = 0;
strideComp[2] = 0;
if (isChromaEnabled(m_chromaFormat))
{
strideComp[1] = pGrainBuf->bufs[1].stride;
strideComp[2] = pGrainBuf->bufs[2].stride;
}
int32_t numBlks_x[MAX_NUM_COMPONENT];
int32_t numBlks_y[MAX_NUM_COMPONENT];
picOffset = m_poc;
for (compCtr = 0; compCtr < numComp; compCtr++)
{
if (BLK_32 == m_fgsBlkSize)
{
numBlks_x[compCtr] = (widthComp[compCtr] >> 5) + ((widthComp[compCtr] & 0x1F) ? 1 : 0);
numBlks_y[compCtr] = (heightComp[compCtr] >> 5) + ((heightComp[compCtr] & 0x1F) ? 1 : 0);
}
else
{
numBlks_x[compCtr] = (widthComp[compCtr] >> 4) + ((widthComp[compCtr] & 0xF) ? 1 : 0);
numBlks_y[compCtr] = (heightComp[compCtr] >> 4) + ((heightComp[compCtr] & 0xF) ? 1 : 0);
}
}
for (compCtr = 0; compCtr < numComp; compCtr++)
{
if (1 == m_fgcParameters->m_compModel[compCtr].presentFlag)
{
uint32_t *tmp = offsetsArr[compCtr];
int i, j;
/* Seed initialization for current picture*/
pseudoRandValEc = seedLUT[((picOffset + color_offset[compCtr]) & 0xFF)];
for (i = 0; i < numBlks_y[compCtr]; i++)
{
for (j = 0; j < numBlks_x[compCtr]; j++)
{
*tmp = pseudoRandValEc;
pseudoRandValEc = prng(pseudoRandValEc);
tmp++;
}
}
}
}
m_fgsArgs.numComp = numComp;
for (compCtr = 0; compCtr < numComp; compCtr++)
{
if (1 == m_fgcParameters->m_compModel[compCtr].presentFlag)
{
m_fgsArgs.decComp[compCtr] = decComp[compCtr];
m_fgsArgs.widthComp[compCtr] = widthComp[compCtr];
m_fgsArgs.strideComp[compCtr] = strideComp[compCtr];
m_fgsArgs.fgsOffsets[compCtr] = offsetsArr[compCtr];
if (BLK_32 == m_fgsBlkSize)
{
m_fgsArgs.heightComp[compCtr] = numBlks_y[compCtr] * BLK_32;
}
else
{
m_fgsArgs.heightComp[compCtr] = numBlks_y[compCtr] * BLK_16;
}
}
}
m_fgsArgs.pFgcParameters = m_fgcParameters;
m_fgsArgs.blkSize = m_fgsBlkSize;
m_fgsArgs.bitDepth = m_bitDepth;
m_fgsArgs.pGrainSynt = m_grainSynt;
fgsProcess(m_fgsArgs);
for (compCtr = 0; compCtr < numComp; compCtr++)
{
delete offsetsArr[compCtr];
}
return;
}
/* Function validates film grain parameters and returns 0 for valid parameters of SMPTE-RDD5 else 1*/
/* Also down converts the chroma model values for 4:2:0 and 4:2:2 chroma_formats */
uint8_t SEIFilmGrainSynthesizer::grainValidateParams()
{
uint8_t compCtr, intensityCtr, multiGrainCheck[MAX_NUM_COMPONENT][MAX_NUM_INTENSITIES] = { { 0 } };
uint16_t multiGrainCtr;
uint8_t limitCompModelVal1[10] = { 0 }, limitCompModelVal2[10] = { 0 };
uint8_t num_comp_model_pairs = 0, limitCompModelCtr, compPairMatch;
memset(m_grainSynt->intensityInterval, INTENSITY_INTERVAL_MATCH_FAIL, sizeof(m_grainSynt->intensityInterval));
if ((m_width < MIN_WIDTH) || (m_width > MAX_WIDTH) || (m_width % 4))
{
return FGS_INVALID_WIDTH; /* Width not supported */
}
if ((m_height < MIN_HEIGHT) || (m_height > MAX_HEIGHT) || (m_height % 4))
{
return FGS_INVALID_HEIGHT; /* Height not supported */
}
if (m_chromaFormat == ChromaFormat::UNDEFINED)
{
return FGS_INVALID_CHROMA_FORMAT; /* Chroma format not supported */
}
const int numComp = getNumberValidComponents(m_chromaFormat);
if ((m_bitDepth < MIN_BIT_DEPTH) || (m_bitDepth > MAX_BIT_DEPTH))
{
return FGS_INVALID_BIT_DEPTH; /* Bit depth not supported */
}
if ((0 != m_fgcParameters->m_filmGrainCharacteristicsCancelFlag) &&
(1 != m_fgcParameters->m_filmGrainCharacteristicsCancelFlag))
{
return FGS_INVALID_FGC_CANCEL_FLAG; /* Film grain synthesis disabled */
}
if (FILM_GRAIN_MODEL_ID_VALUE != m_fgcParameters->m_filmGrainModelId)
{
return FGS_INVALID_GRAIN_MODEL_ID; /* Not supported */
}
if (0 != m_fgcParameters->m_separateColourDescriptionPresentFlag)
{
return FGS_INVALID_SEP_COL_DES_FLAG; /* Not supported */
}
if (BLENDING_MODE_VALUE != m_fgcParameters->m_blendingModeId)
{
return FGS_INVALID_BLEND_MODE; /* Not supported */
}
if (m_fgcParameters->m_compModel[0].presentFlag || m_fgcParameters->m_compModel[1].presentFlag || m_fgcParameters->m_compModel[2].presentFlag) {
if ((m_fgcParameters->m_log2ScaleFactor < MIN_LOG2SCALE_VALUE) ||
(m_fgcParameters->m_log2ScaleFactor > MAX_LOG2SCALE_VALUE))
{
return FGS_INVALID_LOG2_SCALE_FACTOR; /* Not supported */
}
}
/* validation of component model present flag */
for (compCtr = 0; compCtr < numComp; compCtr++)
{
if ((m_fgcParameters->m_compModel[compCtr].presentFlag != true) &&
(m_fgcParameters->m_compModel[compCtr].presentFlag != false))
{
return FGS_INVALID_COMP_MODEL_PRESENT_FLAG; /* Not supported */
}
if (m_fgcParameters->m_compModel[compCtr].presentFlag &&
(m_fgcParameters->m_compModel[compCtr].numModelValues > MAX_ALLOWED_MODEL_VALUES))
{
return FGS_INVALID_NUM_MODEL_VALUES; /* Not supported */
}
}
/* validation of intensity intervals and */
for (compCtr = 0; compCtr < numComp; compCtr++)
{
if (m_fgcParameters->m_compModel[compCtr].presentFlag)
{
for (intensityCtr = 0; intensityCtr < m_fgcParameters->m_compModel[compCtr].intensityValues.size(); intensityCtr++)
{
if (m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].intensityIntervalLowerBound >
m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].intensityIntervalUpperBound)
{
return FGS_INVALID_INTENSITY_BOUNDARY_VALUES; /* Not supported */
}
for (multiGrainCtr = m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].intensityIntervalLowerBound;
multiGrainCtr <= m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].intensityIntervalUpperBound; multiGrainCtr++)
{
m_grainSynt->intensityInterval[compCtr][multiGrainCtr] = intensityCtr;
if (multiGrainCheck[compCtr][multiGrainCtr]) /* Non over lap */
{
return FGS_INVALID_INTENSITY_BOUNDARY_VALUES; /* Not supported */
}
else
{
multiGrainCheck[compCtr][multiGrainCtr] = 1;
}
}
m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue.resize(MAX_NUM_MODEL_VALUES);
/* default initialization for cut off frequencies */
if (1 == m_fgcParameters->m_compModel[compCtr].numModelValues)
{
m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[1] = DEFAULT_HORZ_CUT_OFF_FREQUENCY;
m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[2] = m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[1];
}
else if (2 == m_fgcParameters->m_compModel[compCtr].numModelValues)
{
m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[2] = m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[1];
}
/* Error check on model component value */
if (m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[0] > (MAX_STANDARD_DEVIATION << (m_bitDepth - BIT_DEPTH_8)))
{
return FGS_INVALID_STANDARD_DEVIATION; /* Not supported */
}
else if ((m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[1] < MIN_CUT_OFF_FREQUENCY) ||
(m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[1] > MAX_CUT_OFF_FREQUENCY))
{
return FGS_INVALID_CUT_OFF_FREQUENCIES; /* Not supported */
}
else if ((m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[2] < MIN_CUT_OFF_FREQUENCY) ||
(m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[2] > MAX_CUT_OFF_FREQUENCY))
{
return FGS_INVALID_CUT_OFF_FREQUENCIES; /* Not supported */
}
/* conversion of component model values for 4:2:0 and 4:4:4 */
if (ChromaFormat::_444 != m_chromaFormat && (compCtr > 0))
{
if (ChromaFormat::_420 == m_chromaFormat) /* 4:2:0 */
{
m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[0] >>= 1;
m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[1] =
CLIP3(MIN_CUT_OFF_FREQUENCY, MAX_CUT_OFF_FREQUENCY,
(m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[1] << 1));
m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[2] =
CLIP3(MIN_CUT_OFF_FREQUENCY, MAX_CUT_OFF_FREQUENCY,
(m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[2] << 1));
}
else if (ChromaFormat::_422 == m_chromaFormat) /* 4:2:2 */
{
m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[0] =
(m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[0] * SCALE_DOWN_422) >> Q_FORMAT_SCALING;
m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[1] =
CLIP3(MIN_CUT_OFF_FREQUENCY, MAX_CUT_OFF_FREQUENCY,
(m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[1] << 1));
}
}
compPairMatch = 0;
for (limitCompModelCtr = 0; limitCompModelCtr <= num_comp_model_pairs; limitCompModelCtr++)
{
if ((limitCompModelVal1[limitCompModelCtr] ==
m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[1]) &&
(limitCompModelVal2[limitCompModelCtr] ==
m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[2]))
{
compPairMatch = 1;
}
}
if (0 == compPairMatch)
{
num_comp_model_pairs++;
/* max allowed pairs are 10 as per SMPTE -RDD5*/
if (num_comp_model_pairs > MAX_ALLOWED_COMP_MODEL_PAIRS)
{
return FGS_INVALID_NUM_CUT_OFF_FREQ_PAIRS; /* Not supported */
}
limitCompModelVal1[num_comp_model_pairs - 1] =
m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[1];
limitCompModelVal2[num_comp_model_pairs - 1] =
m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[2];
}
}
}
}
return FGS_SUCCESS; /* Success */
}
void SEIFilmGrainSynthesizer::deriveFGSBlkSize()
{
uint32_t picSizeInLumaSamples = m_height * m_width;
if (picSizeInLumaSamples <= (1920 * 1080))
{
m_fgsBlkSize = BLK_8;
}
else if (picSizeInLumaSamples <= (3840 * 2160))
{
m_fgsBlkSize = BLK_16;
}
else
{
m_fgsBlkSize = BLK_32;
}
}
void SEIFilmGrainSynthesizer::dataBaseGen()
{
uint32_t pseudoRandValEhv;
uint8_t h, v; /* Horizaontal and vertical cut off frequencies (+2)*/
uint32_t ScaleCutOffFh, ScaleCutOffFv, l, r, i, j, k;
int32_t B[DATA_BASE_SIZE][DATA_BASE_SIZE], IDCT[DATA_BASE_SIZE][DATA_BASE_SIZE];
int32_t Grain[DATA_BASE_SIZE][DATA_BASE_SIZE];
const TMatrixCoeff* Tmp = g_trCoreDCT2P64[TRANSFORM_FORWARD][0];
const int transform_scale = 9; // upscaling of original transform as specified in VVC (for 64x64 block)
const int add_1st = 1 << (transform_scale - 1);
TMatrixCoeff T[DATA_BASE_SIZE][DATA_BASE_SIZE]; // Original
TMatrixCoeff TT[DATA_BASE_SIZE][DATA_BASE_SIZE]; // Transpose
for (int x = 0; x < DATA_BASE_SIZE; x++)
{
for (int y = 0; y < DATA_BASE_SIZE; y++)
{
T[x][y] = Tmp[x * 64 + y]; /* Matrix Original */
TT[y][x] = Tmp[x * 64 + y]; /* Matrix Transpose */
}
}
for (h = 0; h < NUM_CUT_OFF_FREQ; h++)
{
for (v = 0; v < NUM_CUT_OFF_FREQ; v++)
{
memset(&B, 0, DATA_BASE_SIZE*DATA_BASE_SIZE * sizeof(int32_t));
memset(&IDCT, 0, DATA_BASE_SIZE*DATA_BASE_SIZE * sizeof(int32_t));
memset(&Grain, 0, DATA_BASE_SIZE*DATA_BASE_SIZE * sizeof(int32_t));
ScaleCutOffFh = ((h + 3) << 2) - 1;
ScaleCutOffFv = ((v + 3) << 2) - 1;
/* ehv : seed to be used for the psudo random generator for a given h and v */
pseudoRandValEhv = seedLUT[h + v * 13];
for (l = 0, r = 0; l <= ScaleCutOffFv; l++)
{
for (k = 0; k <= ScaleCutOffFh; k += 4)
{
B[k][l] = gaussianLUT[pseudoRandValEhv % 2048];
B[k + 1][l] = gaussianLUT[(pseudoRandValEhv + 1) % 2048];
B[k + 2][l] = gaussianLUT[(pseudoRandValEhv + 2) % 2048];
B[k + 3][l] = gaussianLUT[(pseudoRandValEhv + 3) % 2048];
r++;
pseudoRandValEhv = prng(pseudoRandValEhv);
}
}
B[0][0] = 0;
for (i = 0; i < DATA_BASE_SIZE; i++)
{
for (j = 0; j < DATA_BASE_SIZE; j++)
{
for (k = 0; k < DATA_BASE_SIZE; k++)
{
IDCT[i][j] += TT[i][k] * B[k][j];
}
IDCT[i][j] += add_1st;
IDCT[i][j] = IDCT[i][j] >> transform_scale;
}
}
for (i = 0; i < DATA_BASE_SIZE; i++)
{
for (j = 0; j < DATA_BASE_SIZE; j++)
{
for (k = 0; k < DATA_BASE_SIZE; k++)
{
Grain[i][j] += IDCT[i][k] * T[k][j];
}
Grain[i][j] += add_1st;
Grain[i][j] = Grain[i][j] >> transform_scale;
m_grainSynt->dataBase[h][v][j][i] = CLIP3(-127, 127, Grain[i][j]);
}
}
/* De-blocking at horizontal block edges */
for (l = 0; l < DATA_BASE_SIZE; l += m_fgsBlkSize)
{
for (k = 0; k < DATA_BASE_SIZE; k++)
{
m_grainSynt->dataBase[h][v][l][k] = ((m_grainSynt->dataBase[h][v][l][k]) * deblockFactor[v]) >> 7;
m_grainSynt->dataBase[h][v][l + m_fgsBlkSize - 1][k] = ((m_grainSynt->dataBase[h][v][l + m_fgsBlkSize - 1][k]) * deblockFactor[v]) >> 7;
}
}
}
}
return;
}
uint32_t SEIFilmGrainSynthesizer::prng(uint32_t x_r)
{
uint32_t addVal;
addVal = (1 + ((x_r & (POS_2)) > 0) + ((x_r & (POS_30)) > 0)) % 2;
x_r = (x_r << 1) + addVal;
return x_r;
}
uint32_t SEIFilmGrainSynthesizer::fgsProcess(fgsProcessArgs &inArgs)
{
uint32_t errorCode;
uint8_t blkSize = inArgs.blkSize;
if (blkSize == 8)
errorCode = fgsSimulationBlending_8x8(&inArgs);
else if (blkSize == 16)
errorCode = fgsSimulationBlending_16x16(&inArgs);
else if (blkSize == 32)
errorCode = fgsSimulationBlending_32x32(&inArgs);
else
errorCode = FGS_FAIL;
return errorCode;
}
void SEIFilmGrainSynthesizer::deblockGrainStripe(Pel *grainStripe, uint32_t widthComp, uint32_t heightComp,
uint32_t strideComp, uint32_t blkSize)
{
int32_t left1, left0, right0, right1;
uint32_t pos, vertCtr;
uint32_t widthCropped = (widthComp - blkSize);
for (vertCtr = 0; vertCtr < heightComp; vertCtr++)
{
for (pos = 0; pos < widthCropped; pos += blkSize)
{
left1 = *(grainStripe + blkSize - 2);
left0 = *(grainStripe + blkSize - 1);
right0 = *(grainStripe + blkSize + 0);
right1 = *(grainStripe + blkSize + 1);
*(grainStripe + blkSize + 0) = (left0 + (right0 << 1) + right1) >> 2;
*(grainStripe + blkSize - 1) = (left1 + (left0 << 1) + right0) >> 2;
grainStripe += blkSize;
}
grainStripe = grainStripe + (strideComp - pos);
}
return;
}
void SEIFilmGrainSynthesizer::blendStripe(Pel *decSampleHbdOffsetY, Pel *grainStripe, uint32_t widthComp,
ptrdiff_t strideSrc, ptrdiff_t strideGrain, uint32_t blockHeight,
uint8_t bitDepth)
{
uint32_t k, l;
uint16_t maxRange;
maxRange = (1 << bitDepth) - 1;
int32_t grainSample;
uint16_t decodeSampleHbd;
uint8_t bitDepthShift = (bitDepth - BIT_DEPTH_8);
ptrdiff_t bufInc = (strideSrc - widthComp);
ptrdiff_t grainBufInc = (strideGrain - widthComp);
for (l = 0; l < blockHeight; l++) /* y direction */
{
for (k = 0; k < widthComp; k++) /* x direction */
{
decodeSampleHbd = *decSampleHbdOffsetY;
grainSample = *grainStripe;
grainSample <<= bitDepthShift;
grainSample = CLIP3(0, maxRange, grainSample + decodeSampleHbd);
*decSampleHbdOffsetY = (Pel)grainSample;
decSampleHbdOffsetY++;
grainStripe++;
}
decSampleHbdOffsetY += bufInc;
grainStripe += grainBufInc;
}
return;
}
void SEIFilmGrainSynthesizer::blendStripe_32x32(Pel *decSampleHbdOffsetY, Pel *grainStripe, uint32_t widthComp,
ptrdiff_t strideSrc, ptrdiff_t strideGrain, uint32_t blockHeight,
uint8_t bitDepth)
{
uint32_t k, l;
uint16_t maxRange;
maxRange = (1 << bitDepth) - 1;
int32_t grainSample;
uint16_t decodeSampleHbd;
uint8_t bitDepthShift = (bitDepth - BIT_DEPTH_8);
ptrdiff_t bufInc = (strideSrc - widthComp);
ptrdiff_t grainBufInc = (strideGrain - widthComp);
for (l = 0; l < blockHeight; l++) /* y direction */
{
for (k = 0; k < widthComp; k++) /* x direction */
{
decodeSampleHbd = *decSampleHbdOffsetY;
grainSample = *grainStripe;
grainSample <<= bitDepthShift;
grainSample = CLIP3(0, maxRange, grainSample + decodeSampleHbd);
*decSampleHbdOffsetY = (Pel)grainSample;
decSampleHbdOffsetY++;
grainStripe++;
}
decSampleHbdOffsetY += bufInc;
grainStripe += grainBufInc;
}
return;
}
Pel SEIFilmGrainSynthesizer::blockAverage_8x8(Pel *decSampleBlk8, ptrdiff_t widthComp, uint16_t *pNumSamples,
uint8_t ySize, uint8_t xSize, uint8_t bitDepth)
{
uint32_t blockAvg = 0;
uint8_t k;
uint8_t l;
for (k = 0; k < ySize; k++)
{
for (l = 0; l < xSize; l++)
{
blockAvg += *decSampleBlk8;
decSampleBlk8++;
}
decSampleBlk8 += widthComp - xSize;
}
blockAvg = blockAvg >> (BLK_8_shift + (bitDepth - BIT_DEPTH_8));
*pNumSamples = BLK_AREA_8x8;
return blockAvg;
}
uint32_t SEIFilmGrainSynthesizer::blockAverage_16x16(Pel *decSampleBlk8, ptrdiff_t widthComp, uint16_t *pNumSamples,
uint8_t ySize, uint8_t xSize, uint8_t bitDepth)
{
uint32_t blockAvg = 0;
uint8_t k;
uint8_t l;
for (k = 0; k < ySize; k++)
{
for (l = 0; l < xSize; l++)
{
blockAvg += *decSampleBlk8;
decSampleBlk8++;
}
decSampleBlk8 += widthComp - xSize;
}
// blockAvg = blockAvg >> (BLK_16_shift + (bitDepth - BIT_DEPTH_8));
// If BLK_16 is not used or changed BLK_AREA_16x16 has to be changed
*pNumSamples = BLK_AREA_16x16;
return blockAvg;
}
uint32_t SEIFilmGrainSynthesizer::blockAverage_32x32(Pel *decSampleBlk32, ptrdiff_t strideComp, uint8_t bitDepth)
{
uint32_t blockAvg = 0;
uint8_t k;
uint8_t l;
ptrdiff_t bufInc = strideComp - BLK_32;
for (k = 0; k < BLK_32; k++)
{
for (l = 0; l < BLK_32; l++)
{
blockAvg += *decSampleBlk32++;
}
decSampleBlk32 += bufInc;
}
blockAvg = blockAvg >> (BLK_32_shift + (bitDepth - BIT_DEPTH_8));
return blockAvg;
}
void SEIFilmGrainSynthesizer::simulateGrainBlk8x8(Pel *grainStripe, uint32_t grainStripeOffsetBlk8,
GrainSynthesisStruct *grain_synt, uint32_t width,
uint8_t log2ScaleFactor, int16_t scaleFactor, uint32_t kOffset,
uint32_t lOffset, uint8_t h, uint8_t v, uint32_t xSize)
{
uint32_t l;
int8_t * database_h_v = &grain_synt->dataBase[h][v][lOffset][kOffset];
grainStripe += grainStripeOffsetBlk8;
uint32_t k;
for (l = 0; l < BLK_8; l++) /* y direction */
{
for (k = 0; k < xSize; k++) /* x direction */
{
*grainStripe = ((scaleFactor * (*database_h_v)) >> (log2ScaleFactor + GRAIN_SCALE));
grainStripe++;
database_h_v++;
}
grainStripe += width - xSize;
database_h_v += DATA_BASE_SIZE - xSize;
}
return;
}
void SEIFilmGrainSynthesizer::simulateGrainBlk16x16(Pel *grainStripe, uint32_t grainStripeOffsetBlk8,
GrainSynthesisStruct *grain_synt, uint32_t width,
uint8_t log2ScaleFactor, int16_t scaleFactor, uint32_t kOffset,
uint32_t lOffset, uint8_t h, uint8_t v, uint32_t xSize)
{
uint32_t l;
int8_t * database_h_v = &grain_synt->dataBase[h][v][lOffset][kOffset];
grainStripe += grainStripeOffsetBlk8;
uint32_t k;
for (l = 0; l < BLK_16; l++) /* y direction */
{
for (k = 0; k < xSize; k++) /* x direction */
{
*grainStripe = (int16_t)(((int32_t)scaleFactor * (*database_h_v)) >> (log2ScaleFactor + GRAIN_SCALE));
grainStripe++;
database_h_v++;
}
grainStripe += width - xSize;
database_h_v += DATA_BASE_SIZE - xSize;
}
return;
}
void SEIFilmGrainSynthesizer::simulateGrainBlk32x32(Pel *grainStripe, uint32_t grainStripeOffsetBlk32,
GrainSynthesisStruct *grain_synt, uint32_t width,
uint8_t log2ScaleFactor, int16_t scaleFactor, uint32_t kOffset,
uint32_t lOffset, uint8_t h, uint8_t v)
{
uint32_t l;
int8_t * database_h_v = &grain_synt->dataBase[h][v][lOffset][kOffset];
grainStripe += grainStripeOffsetBlk32;
uint32_t k;
uint8_t shiftVal = log2ScaleFactor + GRAIN_SCALE;
uint32_t grainbufInc = width - BLK_32;
for (l = 0; l < BLK_32; l++) /* y direction */
{
for (k = 0; k < BLK_32; k++) /* x direction */
{
*grainStripe = ((scaleFactor * (*database_h_v)) >> shiftVal);
grainStripe++;
database_h_v++;
}
grainStripe += grainbufInc;
database_h_v += DATA_BASE_SIZE - BLK_32;
}
return;
}
uint32_t SEIFilmGrainSynthesizer::fgsSimulationBlending_8x8(fgsProcessArgs *inArgs)
{
uint8_t numComp, compCtr, blkId; /* number of color components */
uint8_t log2ScaleFactor, h, v;
uint8_t bitDepth; /*grain bit depth and decoded bit depth are assumed to be same */
uint32_t widthComp[MAX_NUM_COMPONENT], heightComp[MAX_NUM_COMPONENT];
ptrdiff_t strideComp[MAX_NUM_COMPONENT];
Pel * decSampleHbdBlk16, *decSampleHbdBlk8, *decSampleHbdOffsetY;
Pel * decHbdComp[MAX_NUM_COMPONENT];
uint16_t numSamples;
int16_t scaleFactor;
uint32_t kOffset, lOffset, grainStripeOffset, grainStripeOffsetBlk8;
ptrdiff_t offsetBlk8x8;
uint32_t kOffset_const, lOffset_const;
int16_t scaleFactor_const;
Pel * grainStripe; /* worth a row of 16x16 : Max size : 16xw;*/
int32_t yOffset8x8, xOffset8x8;
uint32_t x, y;
uint32_t blockAvg, intensityInt; /* ec : seed to be used for the psudo random generator for a given color component */
uint32_t grainStripeWidth;
uint32_t wdPadded;
bitDepth = inArgs->bitDepth;
numComp = inArgs->numComp;
log2ScaleFactor = inArgs->pFgcParameters->m_log2ScaleFactor;
for (compCtr = 0; compCtr < numComp; compCtr++)
{
decHbdComp[compCtr] = inArgs->decComp[compCtr];
strideComp[compCtr] = inArgs->strideComp[compCtr];
widthComp[compCtr] = inArgs->widthComp[compCtr];
heightComp[compCtr] = inArgs->heightComp[compCtr];
}
wdPadded = ((inArgs->widthComp[0] - 1) | 0xF) + 1;
grainStripe = new Pel[wdPadded * BLK_16];
if (0 == inArgs->pFgcParameters->m_filmGrainCharacteristicsCancelFlag)
{
for (compCtr = 0; compCtr < numComp; compCtr++)
{
if (1 == inArgs->pFgcParameters->m_compModel[compCtr].presentFlag)
{
decSampleHbdOffsetY = decHbdComp[compCtr];
uint32_t *offset_tmp = inArgs->fgsOffsets[compCtr];
grainStripeWidth = ((widthComp[compCtr] - 1) | 0xF) + 1; // Make next muliptle of 16
/* Loop of 16x16 blocks */
for (y = 0; y < heightComp[compCtr]; y += BLK_16)
{
/* Initialization of grain stripe of 16xwidth size */
memset(grainStripe, 0, (grainStripeWidth * BLK_16 * sizeof(Pel)));
for (x = 0; x < widthComp[compCtr]; x += BLK_16)
{
/* start position offset of decoded sample in x direction */
grainStripeOffset = x;
decSampleHbdBlk16 = decSampleHbdOffsetY + x;
kOffset_const = (MSB16(*offset_tmp) % 52);
kOffset_const &= 0xFFFC;
lOffset_const = (LSB16(*offset_tmp) % 56);
lOffset_const &= 0xFFF8;
scaleFactor_const = 1 - 2 * BIT0(*offset_tmp);
for (blkId = 0; blkId < NUM_8x8_BLKS_16x16; blkId++)
{
yOffset8x8 = (blkId >> 1) * BLK_8;
xOffset8x8 = (blkId & 0x1) * BLK_8;
offsetBlk8x8 = xOffset8x8 + (yOffset8x8 * strideComp[compCtr]);
grainStripeOffsetBlk8 = grainStripeOffset + (xOffset8x8 + (yOffset8x8 * grainStripeWidth));
decSampleHbdBlk8 = decSampleHbdBlk16 + offsetBlk8x8;
blockAvg = blockAverage_8x8(decSampleHbdBlk8, strideComp[compCtr], &numSamples, BLK_8, BLK_8, bitDepth);
/* Selection of the component model */
intensityInt = inArgs->pGrainSynt->intensityInterval[compCtr][blockAvg];
if (INTENSITY_INTERVAL_MATCH_FAIL != intensityInt)
{
/* 8x8 grain block offset using co-ordinates of decoded 8x8 block in the frame */
// kOffset = kOffset_const;
kOffset = kOffset_const + xOffset8x8;
lOffset = lOffset_const + yOffset8x8;
scaleFactor =
scaleFactor_const
* inArgs->pFgcParameters->m_compModel[compCtr].intensityValues[intensityInt].compModelValue[0];
h = inArgs->pFgcParameters->m_compModel[compCtr].intensityValues[intensityInt].compModelValue[1] - 2;
v = inArgs->pFgcParameters->m_compModel[compCtr].intensityValues[intensityInt].compModelValue[2] - 2;
/* 8x8 block grain simulation */
simulateGrainBlk8x8(grainStripe, grainStripeOffsetBlk8, inArgs->pGrainSynt, grainStripeWidth,
log2ScaleFactor, scaleFactor, kOffset, lOffset, h, v, BLK_8);
} /* only if average falls in any interval */
// }/* includes corner case handling */
} /* 8x8 level block processing */
/* uppdate the PRNG once per 16x16 block of samples */
offset_tmp++;
} /* End of 16xwidth grain simulation */
/* deblocking at the vertical edges of 8x8 at 16xwidth*/
deblockGrainStripe(grainStripe, widthComp[compCtr], BLK_16, grainStripeWidth, BLK_8);
/* Blending of size 16xwidth*/
blendStripe(decSampleHbdOffsetY, grainStripe, widthComp[compCtr], strideComp[compCtr], grainStripeWidth,
BLK_16, bitDepth);
decSampleHbdOffsetY += BLK_16 * strideComp[compCtr];
} /* end of component loop */
}
}
}
delete [] grainStripe;
return FGS_SUCCESS;
}
uint32_t SEIFilmGrainSynthesizer::fgsSimulationBlending_16x16(fgsProcessArgs *inArgs)
{
uint8_t numComp, compCtr; /* number of color components */
uint8_t log2ScaleFactor, h, v;
uint8_t bitDepth; /*grain bit depth and decoded bit depth are assumed to be same */
uint32_t widthComp[MAX_NUM_COMPONENT], heightComp[MAX_NUM_COMPONENT];
ptrdiff_t strideComp[MAX_NUM_COMPONENT];
Pel * decSampleHbdBlk16, *decSampleHbdOffsetY;
Pel * decHbdComp[MAX_NUM_COMPONENT];
uint16_t numSamples;
int16_t scaleFactor;
uint32_t kOffset, lOffset, grainStripeOffset;
Pel * grainStripe; /* worth a row of 16x16 : Max size : 16xw;*/
uint32_t x, y;
uint32_t blockAvg, intensityInt; /* ec : seed to be used for the psudo random generator for a given color component */
uint32_t grainStripeWidth;
uint32_t wdPadded;
bitDepth = inArgs->bitDepth;
numComp = inArgs->numComp;
log2ScaleFactor = inArgs->pFgcParameters->m_log2ScaleFactor;
for (compCtr = 0; compCtr < numComp; compCtr++)
{
decHbdComp[compCtr] = inArgs->decComp[compCtr];
strideComp[compCtr] = inArgs->strideComp[compCtr];
widthComp[compCtr] = inArgs->widthComp[compCtr];
heightComp[compCtr] = inArgs->heightComp[compCtr];
}
wdPadded = ((inArgs->widthComp[0] - 1) | 0xF) + 1;
grainStripe = new Pel[wdPadded * BLK_16];
if (0 == inArgs->pFgcParameters->m_filmGrainCharacteristicsCancelFlag)
{
for (compCtr = 0; compCtr < numComp; compCtr++)
{
if (1 == inArgs->pFgcParameters->m_compModel[compCtr].presentFlag)
{
decSampleHbdOffsetY = decHbdComp[compCtr];
uint32_t *offset_tmp = inArgs->fgsOffsets[compCtr];
grainStripeWidth = ((widthComp[compCtr] - 1) | 0xF) + 1; // Make next muliptle of 16
/* Loop of 16x16 blocks */
for (y = 0; y < heightComp[compCtr]; y += BLK_16)
{
/* Initialization of grain stripe of 16xwidth size */
memset(grainStripe, 0, (grainStripeWidth * BLK_16 * sizeof(Pel)));
for (x = 0; x < widthComp[compCtr]; x += BLK_16)
{
/* start position offset of decoded sample in x direction */
grainStripeOffset = x;
decSampleHbdBlk16 = decSampleHbdOffsetY + x;
blockAvg =
blockAverage_16x16(decSampleHbdBlk16, strideComp[compCtr], &numSamples, BLK_16, BLK_16, bitDepth);
blockAvg = blockAvg >> (BLK_16_shift + (bitDepth - BIT_DEPTH_8));
/* Selection of the component model */
intensityInt = inArgs->pGrainSynt->intensityInterval[compCtr][blockAvg];
if (INTENSITY_INTERVAL_MATCH_FAIL != intensityInt)
{
kOffset = (MSB16(*offset_tmp) % 52);
kOffset &= 0xFFFC;
lOffset = (LSB16(*offset_tmp) % 56);
lOffset &= 0xFFF8;
scaleFactor = 1 - 2 * BIT0(*offset_tmp);
scaleFactor *=
inArgs->pFgcParameters->m_compModel[compCtr].intensityValues[intensityInt].compModelValue[0];
h = inArgs->pFgcParameters->m_compModel[compCtr].intensityValues[intensityInt].compModelValue[1] - 2;
v = inArgs->pFgcParameters->m_compModel[compCtr].intensityValues[intensityInt].compModelValue[2] - 2;
/* 16x16 block grain simulation */
simulateGrainBlk16x16(grainStripe, grainStripeOffset, inArgs->pGrainSynt, grainStripeWidth,
log2ScaleFactor, scaleFactor, kOffset, lOffset, h, v, BLK_16);
} /* only if average falls in any interval */
// }/* includes corner case handling */
/* uppdate the PRNG once per 16x16 block of samples */
offset_tmp++;
} /* End of 16xwidth grain simulation */
/* deblocking at the vertical edges of 16x16 at 16xwidth*/
deblockGrainStripe(grainStripe, widthComp[compCtr], BLK_16, grainStripeWidth, BLK_16);
/* Blending of size 16xwidth*/
blendStripe(decSampleHbdOffsetY, grainStripe, widthComp[compCtr], strideComp[compCtr], grainStripeWidth,
BLK_16, bitDepth);
decSampleHbdOffsetY += BLK_16 * strideComp[compCtr];
} /* end of component loop */
}
}
}
delete [] grainStripe;
return FGS_SUCCESS;
}
uint32_t SEIFilmGrainSynthesizer::fgsSimulationBlending_32x32(fgsProcessArgs *inArgs)
{
uint8_t numComp, compCtr; /* number of color components */
uint8_t log2ScaleFactor, h, v;
uint8_t bitDepth; /*grain bit depth and decoded bit depth are assumed to be same */
uint32_t widthComp[MAX_NUM_COMPONENT], heightComp[MAX_NUM_COMPONENT];
ptrdiff_t strideComp[MAX_NUM_COMPONENT];
Pel * decSampleBlk32, *decSampleOffsetY;
Pel * decComp[MAX_NUM_COMPONENT];
int16_t scaleFactor;
uint32_t kOffset, lOffset, grainStripeOffset;
Pel * grainStripe;
uint32_t x, y;
uint32_t blockAvg, intensityInt; /* ec : seed to be used for the psudo random generator for a given color component */
uint32_t grainStripeWidth;
uint32_t wdPadded;
bitDepth = inArgs->bitDepth;
numComp = inArgs->numComp;
log2ScaleFactor = inArgs->pFgcParameters->m_log2ScaleFactor;
for (compCtr = 0; compCtr < numComp; compCtr++)
{
decComp[compCtr] = inArgs->decComp[compCtr];
strideComp[compCtr] = inArgs->strideComp[compCtr];
heightComp[compCtr] = inArgs->heightComp[compCtr];
widthComp[compCtr] = inArgs->widthComp[compCtr];
}
wdPadded = ((inArgs->widthComp[0] - 1) | 0x1F) + 1;
grainStripe = new Pel[wdPadded * BLK_32];
if (0 == inArgs->pFgcParameters->m_filmGrainCharacteristicsCancelFlag)
{
for (compCtr = 0; compCtr < numComp; compCtr++)
{
if (1 == inArgs->pFgcParameters->m_compModel[compCtr].presentFlag)
{
uint32_t *offset_tmp = inArgs->fgsOffsets[compCtr];
decSampleOffsetY = decComp[compCtr];
grainStripeWidth = ((widthComp[compCtr] - 1) | 0x1F) + 1; // Make next muliptle of 32
/* Loop of 32x32 blocks */
for (y = 0; y < heightComp[compCtr]; y += BLK_32)
{
/* Initialization of grain stripe of 32xwidth size */
memset(grainStripe, 0, (grainStripeWidth * BLK_32 * sizeof(Pel)));
for (x = 0; x < widthComp[compCtr]; x += BLK_32)
{
/* start position offset of decoded sample in x direction */
grainStripeOffset = x;
decSampleBlk32 = decSampleOffsetY + x;
blockAvg = blockAverage_32x32(decSampleBlk32, strideComp[compCtr], bitDepth);
/* Selection of the component model */
intensityInt = inArgs->pGrainSynt->intensityInterval[compCtr][blockAvg];
if (INTENSITY_INTERVAL_MATCH_FAIL != intensityInt)
{
kOffset = (MSB16(*offset_tmp) % 36);
kOffset &= 0xFFFC;
lOffset = (LSB16(*offset_tmp) % 40);
lOffset &= 0xFFF8;
scaleFactor = 1 - 2 * BIT0(*offset_tmp);
scaleFactor *= inArgs->pFgcParameters->m_compModel[compCtr].intensityValues[intensityInt].compModelValue[0];
h = inArgs->pFgcParameters->m_compModel[compCtr].intensityValues[intensityInt].compModelValue[1] - 2;
v = inArgs->pFgcParameters->m_compModel[compCtr].intensityValues[intensityInt].compModelValue[2] - 2;
/* 32x32 block grain simulation */
simulateGrainBlk32x32(grainStripe, grainStripeOffset, inArgs->pGrainSynt, grainStripeWidth,
log2ScaleFactor, scaleFactor, kOffset, lOffset, h, v);
} /* only if average falls in any interval */
/* uppdate the PRNG once per 16x16 block of samples */
offset_tmp++;
} /* End of 32xwidth grain simulation */
/* deblocking at the vertical edges of 8x8 at 16xwidth*/
deblockGrainStripe(grainStripe, widthComp[compCtr], BLK_32, grainStripeWidth, BLK_32);
blendStripe_32x32(decSampleOffsetY, grainStripe, widthComp[compCtr], strideComp[compCtr], grainStripeWidth, BLK_32, bitDepth);
decSampleOffsetY += BLK_32 * strideComp[compCtr];
} /* end of component loop */
}
}
}
delete [] grainStripe;
return FGS_SUCCESS;
}