aboutsummaryrefslogtreecommitdiff
path: root/src/prediction_mask.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/prediction_mask.cc')
-rw-r--r--src/prediction_mask.cc236
1 files changed, 236 insertions, 0 deletions
diff --git a/src/prediction_mask.cc b/src/prediction_mask.cc
new file mode 100644
index 0000000..ab4d849
--- /dev/null
+++ b/src/prediction_mask.cc
@@ -0,0 +1,236 @@
+// Copyright 2019 The libgav1 Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/prediction_mask.h"
+
+#include <algorithm>
+#include <array>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <memory>
+
+#include "src/utils/array_2d.h"
+#include "src/utils/bit_mask_set.h"
+#include "src/utils/common.h"
+#include "src/utils/constants.h"
+#include "src/utils/logging.h"
+#include "src/utils/memory.h"
+
+namespace libgav1 {
+namespace {
+
+constexpr int kWedgeDirectionTypes = 16;
+
+enum kWedgeDirection : uint8_t {
+ kWedgeHorizontal,
+ kWedgeVertical,
+ kWedgeOblique27,
+ kWedgeOblique63,
+ kWedgeOblique117,
+ kWedgeOblique153,
+};
+
+constexpr uint8_t kWedgeCodebook[3][16][3] = {{{kWedgeOblique27, 4, 4},
+ {kWedgeOblique63, 4, 4},
+ {kWedgeOblique117, 4, 4},
+ {kWedgeOblique153, 4, 4},
+ {kWedgeHorizontal, 4, 2},
+ {kWedgeHorizontal, 4, 4},
+ {kWedgeHorizontal, 4, 6},
+ {kWedgeVertical, 4, 4},
+ {kWedgeOblique27, 4, 2},
+ {kWedgeOblique27, 4, 6},
+ {kWedgeOblique153, 4, 2},
+ {kWedgeOblique153, 4, 6},
+ {kWedgeOblique63, 2, 4},
+ {kWedgeOblique63, 6, 4},
+ {kWedgeOblique117, 2, 4},
+ {kWedgeOblique117, 6, 4}},
+ {{kWedgeOblique27, 4, 4},
+ {kWedgeOblique63, 4, 4},
+ {kWedgeOblique117, 4, 4},
+ {kWedgeOblique153, 4, 4},
+ {kWedgeVertical, 2, 4},
+ {kWedgeVertical, 4, 4},
+ {kWedgeVertical, 6, 4},
+ {kWedgeHorizontal, 4, 4},
+ {kWedgeOblique27, 4, 2},
+ {kWedgeOblique27, 4, 6},
+ {kWedgeOblique153, 4, 2},
+ {kWedgeOblique153, 4, 6},
+ {kWedgeOblique63, 2, 4},
+ {kWedgeOblique63, 6, 4},
+ {kWedgeOblique117, 2, 4},
+ {kWedgeOblique117, 6, 4}},
+ {{kWedgeOblique27, 4, 4},
+ {kWedgeOblique63, 4, 4},
+ {kWedgeOblique117, 4, 4},
+ {kWedgeOblique153, 4, 4},
+ {kWedgeHorizontal, 4, 2},
+ {kWedgeHorizontal, 4, 6},
+ {kWedgeVertical, 2, 4},
+ {kWedgeVertical, 6, 4},
+ {kWedgeOblique27, 4, 2},
+ {kWedgeOblique27, 4, 6},
+ {kWedgeOblique153, 4, 2},
+ {kWedgeOblique153, 4, 6},
+ {kWedgeOblique63, 2, 4},
+ {kWedgeOblique63, 6, 4},
+ {kWedgeOblique117, 2, 4},
+ {kWedgeOblique117, 6, 4}}};
+
+constexpr BitMaskSet kWedgeFlipSignMasks[9] = {
+ BitMaskSet(0xBBFF), // kBlock8x8
+ BitMaskSet(0xBBEF), // kBlock8x16
+ BitMaskSet(0xBAEF), // kBlock8x32
+ BitMaskSet(0xBBEF), // kBlock16x8
+ BitMaskSet(0xBBFF), // kBlock16x16
+ BitMaskSet(0xBBEF), // kBlock16x32
+ BitMaskSet(0xABEF), // kBlock32x8
+ BitMaskSet(0xBBEF), // kBlock32x16
+ BitMaskSet(0xBBFF) // kBlock32x32
+};
+
+// This table (and the one below) contains a few leading zeros and trailing 64s
+// to avoid some additional memcpys where it is actually used.
+constexpr uint8_t kWedgeMasterObliqueOdd[kWedgeMaskMasterSize * 3 / 2] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 6, 18, 37,
+ 53, 60, 63, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64};
+
+constexpr uint8_t kWedgeMasterObliqueEven[kWedgeMaskMasterSize * 3 / 2] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 11, 27,
+ 46, 58, 62, 63, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64};
+
+constexpr uint8_t kWedgeMasterVertical[kWedgeMaskMasterSize] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 7, 21,
+ 43, 57, 62, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64};
+
+int BlockShape(BlockSize block_size) {
+ const int width = kNum4x4BlocksWide[block_size];
+ const int height = kNum4x4BlocksHigh[block_size];
+ if (height > width) return 0;
+ if (height < width) return 1;
+ return 2;
+}
+
+uint8_t GetWedgeDirection(BlockSize block_size, int index) {
+ return kWedgeCodebook[BlockShape(block_size)][index][0];
+}
+
+uint8_t GetWedgeOffsetX(BlockSize block_size, int index) {
+ return kWedgeCodebook[BlockShape(block_size)][index][1];
+}
+
+uint8_t GetWedgeOffsetY(BlockSize block_size, int index) {
+ return kWedgeCodebook[BlockShape(block_size)][index][2];
+}
+
+} // namespace
+
+bool GenerateWedgeMask(WedgeMaskArray* const wedge_masks) {
+ // Generate master masks.
+ uint8_t master_mask[6][kWedgeMaskMasterSize][kWedgeMaskMasterSize];
+ for (int y = 0; y < kWedgeMaskMasterSize; ++y) {
+ memcpy(master_mask[kWedgeVertical][y], kWedgeMasterVertical,
+ kWedgeMaskMasterSize);
+ }
+
+ for (int y = 0, shift = 0; y < kWedgeMaskMasterSize; y += 2, ++shift) {
+ memcpy(master_mask[kWedgeOblique63][y], kWedgeMasterObliqueEven + shift,
+ kWedgeMaskMasterSize);
+ memcpy(master_mask[kWedgeOblique63][y + 1], kWedgeMasterObliqueOdd + shift,
+ kWedgeMaskMasterSize);
+ }
+
+ for (int y = 0; y < kWedgeMaskMasterSize; ++y) {
+ for (int x = 0; x < kWedgeMaskMasterSize; ++x) {
+ const uint8_t mask_value = master_mask[kWedgeOblique63][y][x];
+ master_mask[kWedgeHorizontal][x][y] = master_mask[kWedgeVertical][y][x];
+ master_mask[kWedgeOblique27][x][y] = mask_value;
+ master_mask[kWedgeOblique117][y][kWedgeMaskMasterSize - 1 - x] =
+ 64 - mask_value;
+ master_mask[kWedgeOblique153][(kWedgeMaskMasterSize - 1 - x)][y] =
+ 64 - mask_value;
+ }
+ }
+
+ // Generate wedge masks.
+ int block_size_index = 0;
+ for (int size = kBlock8x8; size <= kBlock32x32; ++size) {
+ if (!kIsWedgeCompoundModeAllowed.Contains(size)) continue;
+
+ const int width = kBlockWidthPixels[size];
+ const int height = kBlockHeightPixels[size];
+ assert(width >= 8);
+ assert(width <= 32);
+ assert(height >= 8);
+ assert(height <= 32);
+
+ const auto block_size = static_cast<BlockSize>(size);
+ for (int wedge_index = 0; wedge_index < kWedgeDirectionTypes;
+ ++wedge_index) {
+ const uint8_t direction = GetWedgeDirection(block_size, wedge_index);
+ const uint8_t offset_x =
+ DivideBy2(kWedgeMaskMasterSize) -
+ ((GetWedgeOffsetX(block_size, wedge_index) * width) >> 3);
+ const uint8_t offset_y =
+ DivideBy2(kWedgeMaskMasterSize) -
+ ((GetWedgeOffsetY(block_size, wedge_index) * height) >> 3);
+
+ // Allocate the 2d array.
+ for (int flip_sign = 0; flip_sign < 2; ++flip_sign) {
+ if (!((*wedge_masks)[block_size_index][flip_sign][wedge_index].Reset(
+ height, width, /*zero_initialize=*/false))) {
+ LIBGAV1_DLOG(ERROR, "Failed to allocate memory for wedge masks.");
+ return false;
+ }
+ }
+
+ const auto flip_sign = static_cast<uint8_t>(
+ kWedgeFlipSignMasks[block_size_index].Contains(wedge_index));
+ uint8_t* wedge_masks_row =
+ (*wedge_masks)[block_size_index][flip_sign][wedge_index][0];
+ uint8_t* wedge_masks_row_flip =
+ (*wedge_masks)[block_size_index][1 - flip_sign][wedge_index][0];
+ uint8_t* master_mask_row = &master_mask[direction][offset_y][offset_x];
+ for (int y = 0; y < height; ++y) {
+ memcpy(wedge_masks_row, master_mask_row, width);
+ for (int x = 0; x < width; ++x) {
+ wedge_masks_row_flip[x] = 64 - wedge_masks_row[x];
+ }
+ wedge_masks_row += width;
+ wedge_masks_row_flip += width;
+ master_mask_row += kWedgeMaskMasterSize;
+ }
+ }
+
+ block_size_index++;
+ }
+ return true;
+}
+
+} // namespace libgav1