1*09537850SAkhilesh Sanikop // Copyright 2019 The libgav1 Authors
2*09537850SAkhilesh Sanikop //
3*09537850SAkhilesh Sanikop // Licensed under the Apache License, Version 2.0 (the "License");
4*09537850SAkhilesh Sanikop // you may not use this file except in compliance with the License.
5*09537850SAkhilesh Sanikop // You may obtain a copy of the License at
6*09537850SAkhilesh Sanikop //
7*09537850SAkhilesh Sanikop // http://www.apache.org/licenses/LICENSE-2.0
8*09537850SAkhilesh Sanikop //
9*09537850SAkhilesh Sanikop // Unless required by applicable law or agreed to in writing, software
10*09537850SAkhilesh Sanikop // distributed under the License is distributed on an "AS IS" BASIS,
11*09537850SAkhilesh Sanikop // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*09537850SAkhilesh Sanikop // See the License for the specific language governing permissions and
13*09537850SAkhilesh Sanikop // limitations under the License.
14*09537850SAkhilesh Sanikop
15*09537850SAkhilesh Sanikop #include "src/prediction_mask.h"
16*09537850SAkhilesh Sanikop
17*09537850SAkhilesh Sanikop #include <algorithm>
18*09537850SAkhilesh Sanikop #include <array>
19*09537850SAkhilesh Sanikop #include <cassert>
20*09537850SAkhilesh Sanikop #include <cstddef>
21*09537850SAkhilesh Sanikop #include <cstdint>
22*09537850SAkhilesh Sanikop #include <cstdlib>
23*09537850SAkhilesh Sanikop #include <cstring>
24*09537850SAkhilesh Sanikop #include <memory>
25*09537850SAkhilesh Sanikop
26*09537850SAkhilesh Sanikop #include "src/utils/array_2d.h"
27*09537850SAkhilesh Sanikop #include "src/utils/bit_mask_set.h"
28*09537850SAkhilesh Sanikop #include "src/utils/common.h"
29*09537850SAkhilesh Sanikop #include "src/utils/constants.h"
30*09537850SAkhilesh Sanikop #include "src/utils/logging.h"
31*09537850SAkhilesh Sanikop #include "src/utils/memory.h"
32*09537850SAkhilesh Sanikop
33*09537850SAkhilesh Sanikop namespace libgav1 {
34*09537850SAkhilesh Sanikop namespace {
35*09537850SAkhilesh Sanikop
36*09537850SAkhilesh Sanikop constexpr int kWedgeDirectionTypes = 16;
37*09537850SAkhilesh Sanikop
38*09537850SAkhilesh Sanikop enum kWedgeDirection : uint8_t {
39*09537850SAkhilesh Sanikop kWedgeHorizontal,
40*09537850SAkhilesh Sanikop kWedgeVertical,
41*09537850SAkhilesh Sanikop kWedgeOblique27,
42*09537850SAkhilesh Sanikop kWedgeOblique63,
43*09537850SAkhilesh Sanikop kWedgeOblique117,
44*09537850SAkhilesh Sanikop kWedgeOblique153,
45*09537850SAkhilesh Sanikop };
46*09537850SAkhilesh Sanikop
47*09537850SAkhilesh Sanikop constexpr uint8_t kWedgeCodebook[3][16][3] = {{{kWedgeOblique27, 4, 4},
48*09537850SAkhilesh Sanikop {kWedgeOblique63, 4, 4},
49*09537850SAkhilesh Sanikop {kWedgeOblique117, 4, 4},
50*09537850SAkhilesh Sanikop {kWedgeOblique153, 4, 4},
51*09537850SAkhilesh Sanikop {kWedgeHorizontal, 4, 2},
52*09537850SAkhilesh Sanikop {kWedgeHorizontal, 4, 4},
53*09537850SAkhilesh Sanikop {kWedgeHorizontal, 4, 6},
54*09537850SAkhilesh Sanikop {kWedgeVertical, 4, 4},
55*09537850SAkhilesh Sanikop {kWedgeOblique27, 4, 2},
56*09537850SAkhilesh Sanikop {kWedgeOblique27, 4, 6},
57*09537850SAkhilesh Sanikop {kWedgeOblique153, 4, 2},
58*09537850SAkhilesh Sanikop {kWedgeOblique153, 4, 6},
59*09537850SAkhilesh Sanikop {kWedgeOblique63, 2, 4},
60*09537850SAkhilesh Sanikop {kWedgeOblique63, 6, 4},
61*09537850SAkhilesh Sanikop {kWedgeOblique117, 2, 4},
62*09537850SAkhilesh Sanikop {kWedgeOblique117, 6, 4}},
63*09537850SAkhilesh Sanikop {{kWedgeOblique27, 4, 4},
64*09537850SAkhilesh Sanikop {kWedgeOblique63, 4, 4},
65*09537850SAkhilesh Sanikop {kWedgeOblique117, 4, 4},
66*09537850SAkhilesh Sanikop {kWedgeOblique153, 4, 4},
67*09537850SAkhilesh Sanikop {kWedgeVertical, 2, 4},
68*09537850SAkhilesh Sanikop {kWedgeVertical, 4, 4},
69*09537850SAkhilesh Sanikop {kWedgeVertical, 6, 4},
70*09537850SAkhilesh Sanikop {kWedgeHorizontal, 4, 4},
71*09537850SAkhilesh Sanikop {kWedgeOblique27, 4, 2},
72*09537850SAkhilesh Sanikop {kWedgeOblique27, 4, 6},
73*09537850SAkhilesh Sanikop {kWedgeOblique153, 4, 2},
74*09537850SAkhilesh Sanikop {kWedgeOblique153, 4, 6},
75*09537850SAkhilesh Sanikop {kWedgeOblique63, 2, 4},
76*09537850SAkhilesh Sanikop {kWedgeOblique63, 6, 4},
77*09537850SAkhilesh Sanikop {kWedgeOblique117, 2, 4},
78*09537850SAkhilesh Sanikop {kWedgeOblique117, 6, 4}},
79*09537850SAkhilesh Sanikop {{kWedgeOblique27, 4, 4},
80*09537850SAkhilesh Sanikop {kWedgeOblique63, 4, 4},
81*09537850SAkhilesh Sanikop {kWedgeOblique117, 4, 4},
82*09537850SAkhilesh Sanikop {kWedgeOblique153, 4, 4},
83*09537850SAkhilesh Sanikop {kWedgeHorizontal, 4, 2},
84*09537850SAkhilesh Sanikop {kWedgeHorizontal, 4, 6},
85*09537850SAkhilesh Sanikop {kWedgeVertical, 2, 4},
86*09537850SAkhilesh Sanikop {kWedgeVertical, 6, 4},
87*09537850SAkhilesh Sanikop {kWedgeOblique27, 4, 2},
88*09537850SAkhilesh Sanikop {kWedgeOblique27, 4, 6},
89*09537850SAkhilesh Sanikop {kWedgeOblique153, 4, 2},
90*09537850SAkhilesh Sanikop {kWedgeOblique153, 4, 6},
91*09537850SAkhilesh Sanikop {kWedgeOblique63, 2, 4},
92*09537850SAkhilesh Sanikop {kWedgeOblique63, 6, 4},
93*09537850SAkhilesh Sanikop {kWedgeOblique117, 2, 4},
94*09537850SAkhilesh Sanikop {kWedgeOblique117, 6, 4}}};
95*09537850SAkhilesh Sanikop
96*09537850SAkhilesh Sanikop constexpr BitMaskSet kWedgeFlipSignMasks[9] = {
97*09537850SAkhilesh Sanikop BitMaskSet(0xBBFF), // kBlock8x8
98*09537850SAkhilesh Sanikop BitMaskSet(0xBBEF), // kBlock8x16
99*09537850SAkhilesh Sanikop BitMaskSet(0xBAEF), // kBlock8x32
100*09537850SAkhilesh Sanikop BitMaskSet(0xBBEF), // kBlock16x8
101*09537850SAkhilesh Sanikop BitMaskSet(0xBBFF), // kBlock16x16
102*09537850SAkhilesh Sanikop BitMaskSet(0xBBEF), // kBlock16x32
103*09537850SAkhilesh Sanikop BitMaskSet(0xABEF), // kBlock32x8
104*09537850SAkhilesh Sanikop BitMaskSet(0xBBEF), // kBlock32x16
105*09537850SAkhilesh Sanikop BitMaskSet(0xBBFF) // kBlock32x32
106*09537850SAkhilesh Sanikop };
107*09537850SAkhilesh Sanikop
108*09537850SAkhilesh Sanikop // This table (and the one below) contains a few leading zeros and trailing 64s
109*09537850SAkhilesh Sanikop // to avoid some additional memcpys where it is actually used.
110*09537850SAkhilesh Sanikop constexpr uint8_t kWedgeMasterObliqueOdd[kWedgeMaskMasterSize * 3 / 2] = {
111*09537850SAkhilesh Sanikop 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
112*09537850SAkhilesh Sanikop 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
113*09537850SAkhilesh Sanikop 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 6, 18, 37,
114*09537850SAkhilesh Sanikop 53, 60, 63, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
115*09537850SAkhilesh Sanikop 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
116*09537850SAkhilesh Sanikop 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64};
117*09537850SAkhilesh Sanikop
118*09537850SAkhilesh Sanikop constexpr uint8_t kWedgeMasterObliqueEven[kWedgeMaskMasterSize * 3 / 2] = {
119*09537850SAkhilesh Sanikop 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
120*09537850SAkhilesh Sanikop 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
121*09537850SAkhilesh Sanikop 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 11, 27,
122*09537850SAkhilesh Sanikop 46, 58, 62, 63, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
123*09537850SAkhilesh Sanikop 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
124*09537850SAkhilesh Sanikop 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64};
125*09537850SAkhilesh Sanikop
126*09537850SAkhilesh Sanikop constexpr uint8_t kWedgeMasterVertical[kWedgeMaskMasterSize] = {
127*09537850SAkhilesh Sanikop 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
128*09537850SAkhilesh Sanikop 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 7, 21,
129*09537850SAkhilesh Sanikop 43, 57, 62, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
130*09537850SAkhilesh Sanikop 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64};
131*09537850SAkhilesh Sanikop
BlockShape(BlockSize block_size)132*09537850SAkhilesh Sanikop int BlockShape(BlockSize block_size) {
133*09537850SAkhilesh Sanikop const int width = kNum4x4BlocksWide[block_size];
134*09537850SAkhilesh Sanikop const int height = kNum4x4BlocksHigh[block_size];
135*09537850SAkhilesh Sanikop if (height > width) return 0;
136*09537850SAkhilesh Sanikop if (height < width) return 1;
137*09537850SAkhilesh Sanikop return 2;
138*09537850SAkhilesh Sanikop }
139*09537850SAkhilesh Sanikop
GetWedgeDirection(BlockSize block_size,int index)140*09537850SAkhilesh Sanikop uint8_t GetWedgeDirection(BlockSize block_size, int index) {
141*09537850SAkhilesh Sanikop return kWedgeCodebook[BlockShape(block_size)][index][0];
142*09537850SAkhilesh Sanikop }
143*09537850SAkhilesh Sanikop
GetWedgeOffsetX(BlockSize block_size,int index)144*09537850SAkhilesh Sanikop uint8_t GetWedgeOffsetX(BlockSize block_size, int index) {
145*09537850SAkhilesh Sanikop return kWedgeCodebook[BlockShape(block_size)][index][1];
146*09537850SAkhilesh Sanikop }
147*09537850SAkhilesh Sanikop
GetWedgeOffsetY(BlockSize block_size,int index)148*09537850SAkhilesh Sanikop uint8_t GetWedgeOffsetY(BlockSize block_size, int index) {
149*09537850SAkhilesh Sanikop return kWedgeCodebook[BlockShape(block_size)][index][2];
150*09537850SAkhilesh Sanikop }
151*09537850SAkhilesh Sanikop
152*09537850SAkhilesh Sanikop } // namespace
153*09537850SAkhilesh Sanikop
GenerateWedgeMask(WedgeMaskArray * const wedge_masks)154*09537850SAkhilesh Sanikop bool GenerateWedgeMask(WedgeMaskArray* const wedge_masks) {
155*09537850SAkhilesh Sanikop // Generate master masks.
156*09537850SAkhilesh Sanikop uint8_t master_mask[6][kWedgeMaskMasterSize][kWedgeMaskMasterSize];
157*09537850SAkhilesh Sanikop for (int y = 0; y < kWedgeMaskMasterSize; ++y) {
158*09537850SAkhilesh Sanikop memcpy(master_mask[kWedgeVertical][y], kWedgeMasterVertical,
159*09537850SAkhilesh Sanikop kWedgeMaskMasterSize);
160*09537850SAkhilesh Sanikop }
161*09537850SAkhilesh Sanikop
162*09537850SAkhilesh Sanikop for (int y = 0, shift = 0; y < kWedgeMaskMasterSize; y += 2, ++shift) {
163*09537850SAkhilesh Sanikop memcpy(master_mask[kWedgeOblique63][y], kWedgeMasterObliqueEven + shift,
164*09537850SAkhilesh Sanikop kWedgeMaskMasterSize);
165*09537850SAkhilesh Sanikop memcpy(master_mask[kWedgeOblique63][y + 1], kWedgeMasterObliqueOdd + shift,
166*09537850SAkhilesh Sanikop kWedgeMaskMasterSize);
167*09537850SAkhilesh Sanikop }
168*09537850SAkhilesh Sanikop
169*09537850SAkhilesh Sanikop for (int y = 0; y < kWedgeMaskMasterSize; ++y) {
170*09537850SAkhilesh Sanikop for (int x = 0; x < kWedgeMaskMasterSize; ++x) {
171*09537850SAkhilesh Sanikop const uint8_t mask_value = master_mask[kWedgeOblique63][y][x];
172*09537850SAkhilesh Sanikop master_mask[kWedgeHorizontal][x][y] = master_mask[kWedgeVertical][y][x];
173*09537850SAkhilesh Sanikop master_mask[kWedgeOblique27][x][y] = mask_value;
174*09537850SAkhilesh Sanikop master_mask[kWedgeOblique117][y][kWedgeMaskMasterSize - 1 - x] =
175*09537850SAkhilesh Sanikop 64 - mask_value;
176*09537850SAkhilesh Sanikop master_mask[kWedgeOblique153][(kWedgeMaskMasterSize - 1 - x)][y] =
177*09537850SAkhilesh Sanikop 64 - mask_value;
178*09537850SAkhilesh Sanikop }
179*09537850SAkhilesh Sanikop }
180*09537850SAkhilesh Sanikop
181*09537850SAkhilesh Sanikop // Generate wedge masks.
182*09537850SAkhilesh Sanikop int block_size_index = 0;
183*09537850SAkhilesh Sanikop for (int size = kBlock8x8; size <= kBlock32x32; ++size) {
184*09537850SAkhilesh Sanikop if (!kIsWedgeCompoundModeAllowed.Contains(size)) continue;
185*09537850SAkhilesh Sanikop
186*09537850SAkhilesh Sanikop const int width = kBlockWidthPixels[size];
187*09537850SAkhilesh Sanikop const int height = kBlockHeightPixels[size];
188*09537850SAkhilesh Sanikop assert(width >= 8);
189*09537850SAkhilesh Sanikop assert(width <= 32);
190*09537850SAkhilesh Sanikop assert(height >= 8);
191*09537850SAkhilesh Sanikop assert(height <= 32);
192*09537850SAkhilesh Sanikop
193*09537850SAkhilesh Sanikop const auto block_size = static_cast<BlockSize>(size);
194*09537850SAkhilesh Sanikop for (int wedge_index = 0; wedge_index < kWedgeDirectionTypes;
195*09537850SAkhilesh Sanikop ++wedge_index) {
196*09537850SAkhilesh Sanikop const uint8_t direction = GetWedgeDirection(block_size, wedge_index);
197*09537850SAkhilesh Sanikop const uint8_t offset_x =
198*09537850SAkhilesh Sanikop DivideBy2(kWedgeMaskMasterSize) -
199*09537850SAkhilesh Sanikop ((GetWedgeOffsetX(block_size, wedge_index) * width) >> 3);
200*09537850SAkhilesh Sanikop const uint8_t offset_y =
201*09537850SAkhilesh Sanikop DivideBy2(kWedgeMaskMasterSize) -
202*09537850SAkhilesh Sanikop ((GetWedgeOffsetY(block_size, wedge_index) * height) >> 3);
203*09537850SAkhilesh Sanikop
204*09537850SAkhilesh Sanikop // Allocate the 2d array.
205*09537850SAkhilesh Sanikop for (int flip_sign = 0; flip_sign < 2; ++flip_sign) {
206*09537850SAkhilesh Sanikop if (!((*wedge_masks)[block_size_index][flip_sign][wedge_index].Reset(
207*09537850SAkhilesh Sanikop height, width, /*zero_initialize=*/false))) {
208*09537850SAkhilesh Sanikop LIBGAV1_DLOG(ERROR, "Failed to allocate memory for wedge masks.");
209*09537850SAkhilesh Sanikop return false;
210*09537850SAkhilesh Sanikop }
211*09537850SAkhilesh Sanikop }
212*09537850SAkhilesh Sanikop
213*09537850SAkhilesh Sanikop const auto flip_sign = static_cast<uint8_t>(
214*09537850SAkhilesh Sanikop kWedgeFlipSignMasks[block_size_index].Contains(wedge_index));
215*09537850SAkhilesh Sanikop uint8_t* wedge_masks_row =
216*09537850SAkhilesh Sanikop (*wedge_masks)[block_size_index][flip_sign][wedge_index][0];
217*09537850SAkhilesh Sanikop uint8_t* wedge_masks_row_flip =
218*09537850SAkhilesh Sanikop (*wedge_masks)[block_size_index][1 - flip_sign][wedge_index][0];
219*09537850SAkhilesh Sanikop uint8_t* master_mask_row = &master_mask[direction][offset_y][offset_x];
220*09537850SAkhilesh Sanikop for (int y = 0; y < height; ++y) {
221*09537850SAkhilesh Sanikop memcpy(wedge_masks_row, master_mask_row, width);
222*09537850SAkhilesh Sanikop for (int x = 0; x < width; ++x) {
223*09537850SAkhilesh Sanikop wedge_masks_row_flip[x] = 64 - wedge_masks_row[x];
224*09537850SAkhilesh Sanikop }
225*09537850SAkhilesh Sanikop wedge_masks_row += width;
226*09537850SAkhilesh Sanikop wedge_masks_row_flip += width;
227*09537850SAkhilesh Sanikop master_mask_row += kWedgeMaskMasterSize;
228*09537850SAkhilesh Sanikop }
229*09537850SAkhilesh Sanikop }
230*09537850SAkhilesh Sanikop
231*09537850SAkhilesh Sanikop block_size_index++;
232*09537850SAkhilesh Sanikop }
233*09537850SAkhilesh Sanikop return true;
234*09537850SAkhilesh Sanikop }
235*09537850SAkhilesh Sanikop
236*09537850SAkhilesh Sanikop } // namespace libgav1
237