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