blob: fd151bae7414f129bfd4a26c554ea0258e0287f9 [file]
#!/usr/bin/env python3
## Copyright (c) 2026, Alliance for Open Media. All rights reserved.
##
## This source code is subject to the terms of the BSD 2 Clause License and
## the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
## was not distributed with this source code in the LICENSE file, you can
## obtain it at www.aomedia.org/license/software. If the Alliance for Open
## Media Patent License 1.0 was not distributed with this source code in the
## PATENTS file, you can obtain it at www.aomedia.org/license/patent.
##
# Precompute libaom AV1 wedge / inter-intra blending masks at codegen time
# so they can live in `.rdata` and be COW shared across processes instead
# of being computed at runtime into writable `.data` buffers.
#
# Output is a header fragment included by av1/common/reconinter.c that
# defines:
# - wedge_mask_obl (input to wedge_mask_buf generation)
# - wedge_mask_buf (compound prediction masks, indexed by offset)
# - smooth_interintra_mask_buf
# - wedge_masks (offsets into wedge_mask_buf)
#
# The algorithms in this file mirror init_wedge_master_masks(),
# init_wedge_masks() and init_smooth_interintra_masks() in
# av1/common/reconinter.c. They must stay in sync with that source. If those
# helpers, the master tables, the wedge codebooks, the block-size enum, or
# ii_weights1d ever change upstream, regenerate the .inc by running this
# script and committing the result.
#
# Regenerate:
# python3 source/libaom/tools/gen_wedge_masks_data.py
# --output source/libaom/av1/common/wedge_masks_data.inc
import argparse
import os
import sys
import textwrap
# -----------------------------------------------------------------------------
# Constants (must match reconinter.h / enums.h).
# -----------------------------------------------------------------------------
MAX_WEDGE_TYPES = 16
MAX_WEDGE_SIZE_LOG2 = 5
MAX_WEDGE_SIZE = 1 << MAX_WEDGE_SIZE_LOG2 # 32
MAX_WEDGE_SQUARE = MAX_WEDGE_SIZE * MAX_WEDGE_SIZE # 1024
MASK_MASTER_SIZE = MAX_WEDGE_SIZE << 1 # 64
MASK_MASTER_STRIDE = MASK_MASTER_SIZE
WEDGE_WEIGHT_BITS = 6
INTERINTRA_MODES = 4
MAX_SB_SIZE_LOG2 = 7
MAX_SB_SIZE = 1 << MAX_SB_SIZE_LOG2 # 128
# WedgeDirectionType.
WEDGE_HORIZONTAL = 0
WEDGE_VERTICAL = 1
WEDGE_OBLIQUE27 = 2
WEDGE_OBLIQUE63 = 3
WEDGE_OBLIQUE117 = 4
WEDGE_OBLIQUE153 = 5
WEDGE_DIRECTIONS = 6
# BLOCK_SIZE enum order (must match enums.h).
BLOCK_NAMES = [
"BLOCK_4X4", "BLOCK_4X8", "BLOCK_8X4", "BLOCK_8X8",
"BLOCK_8X16", "BLOCK_16X8", "BLOCK_16X16", "BLOCK_16X32",
"BLOCK_32X16", "BLOCK_32X32", "BLOCK_32X64", "BLOCK_64X32",
"BLOCK_64X64", "BLOCK_64X128", "BLOCK_128X64", "BLOCK_128X128",
"BLOCK_4X16", "BLOCK_16X4", "BLOCK_8X32", "BLOCK_32X8",
"BLOCK_16X64", "BLOCK_64X16",
]
BLOCK_SIZES_ALL = len(BLOCK_NAMES)
def _parse_block_dims(name):
# e.g. "BLOCK_8X16" -> (8, 16)
body = name.split("_", 1)[1]
w, h = body.split("X")
return int(w), int(h)
BLOCK_WIDTH = [_parse_block_dims(n)[0] for n in BLOCK_NAMES]
BLOCK_HEIGHT = [_parse_block_dims(n)[1] for n in BLOCK_NAMES]
def _bi(name):
return BLOCK_NAMES.index(name)
# Inter-intra modes (must match enums.h).
II_DC_PRED, II_V_PRED, II_H_PRED, II_SMOOTH_PRED = 0, 1, 2, 3
# -----------------------------------------------------------------------------
# Master mask tables (see wedge_master_oblique_odd / _even / _vertical in
# av1/common/reconinter.c).
# -----------------------------------------------------------------------------
WEDGE_MASTER_OBLIQUE_ODD = [
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,
]
WEDGE_MASTER_OBLIQUE_EVEN = [
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,
]
WEDGE_MASTER_VERTICAL = [
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,
]
# wedge_signflip_lookup (see av1/common/reconinter.c).
WEDGE_SIGNFLIP_LOOKUP = [
[0]*16, [0]*16, [0]*16,
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1], # BLOCK_8X8
[1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1], # BLOCK_8X16
[1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1], # BLOCK_16X8
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1], # BLOCK_16X16
[1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1], # BLOCK_16X32
[1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1], # BLOCK_32X16
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1], # BLOCK_32X32
[0]*16, [0]*16, [0]*16, [0]*16, [0]*16, [0]*16, [0]*16, [0]*16,
[1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1], # BLOCK_8X32
[1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1], # BLOCK_32X8
[0]*16, [0]*16,
]
assert len(WEDGE_SIGNFLIP_LOOKUP) == BLOCK_SIZES_ALL
# Wedge codebooks (see wedge_codebook_16_* in av1/common/reconinter.c).
# Each entry is
# (direction, x_offset, y_offset).
WEDGE_CODEBOOK_16_HGTW = [
(WEDGE_OBLIQUE27, 4, 4), (WEDGE_OBLIQUE63, 4, 4),
(WEDGE_OBLIQUE117, 4, 4), (WEDGE_OBLIQUE153, 4, 4),
(WEDGE_HORIZONTAL, 4, 2), (WEDGE_HORIZONTAL, 4, 4),
(WEDGE_HORIZONTAL, 4, 6), (WEDGE_VERTICAL, 4, 4),
(WEDGE_OBLIQUE27, 4, 2), (WEDGE_OBLIQUE27, 4, 6),
(WEDGE_OBLIQUE153, 4, 2), (WEDGE_OBLIQUE153, 4, 6),
(WEDGE_OBLIQUE63, 2, 4), (WEDGE_OBLIQUE63, 6, 4),
(WEDGE_OBLIQUE117, 2, 4), (WEDGE_OBLIQUE117, 6, 4),
]
WEDGE_CODEBOOK_16_HLTW = [
(WEDGE_OBLIQUE27, 4, 4), (WEDGE_OBLIQUE63, 4, 4),
(WEDGE_OBLIQUE117, 4, 4), (WEDGE_OBLIQUE153, 4, 4),
(WEDGE_VERTICAL, 2, 4), (WEDGE_VERTICAL, 4, 4),
(WEDGE_VERTICAL, 6, 4), (WEDGE_HORIZONTAL, 4, 4),
(WEDGE_OBLIQUE27, 4, 2), (WEDGE_OBLIQUE27, 4, 6),
(WEDGE_OBLIQUE153, 4, 2), (WEDGE_OBLIQUE153, 4, 6),
(WEDGE_OBLIQUE63, 2, 4), (WEDGE_OBLIQUE63, 6, 4),
(WEDGE_OBLIQUE117, 2, 4), (WEDGE_OBLIQUE117, 6, 4),
]
WEDGE_CODEBOOK_16_HEQW = [
(WEDGE_OBLIQUE27, 4, 4), (WEDGE_OBLIQUE63, 4, 4),
(WEDGE_OBLIQUE117, 4, 4), (WEDGE_OBLIQUE153, 4, 4),
(WEDGE_HORIZONTAL, 4, 2), (WEDGE_HORIZONTAL, 4, 6),
(WEDGE_VERTICAL, 2, 4), (WEDGE_VERTICAL, 6, 4),
(WEDGE_OBLIQUE27, 4, 2), (WEDGE_OBLIQUE27, 4, 6),
(WEDGE_OBLIQUE153, 4, 2), (WEDGE_OBLIQUE153, 4, 6),
(WEDGE_OBLIQUE63, 2, 4), (WEDGE_OBLIQUE63, 6, 4),
(WEDGE_OBLIQUE117, 2, 4), (WEDGE_OBLIQUE117, 6, 4),
]
# av1_wedge_params_lookup. Stored here as (wtypes, codebook). The masks/
# signflip pointers are reconstructed from BLOCK index. See
# av1_wedge_params_lookup in av1/common/reconinter.c.
WEDGE_PARAMS_LOOKUP = [
(0, None),
(0, None),
(0, None),
(MAX_WEDGE_TYPES, WEDGE_CODEBOOK_16_HEQW), # BLOCK_8X8
(MAX_WEDGE_TYPES, WEDGE_CODEBOOK_16_HGTW), # BLOCK_8X16
(MAX_WEDGE_TYPES, WEDGE_CODEBOOK_16_HLTW), # BLOCK_16X8
(MAX_WEDGE_TYPES, WEDGE_CODEBOOK_16_HEQW), # BLOCK_16X16
(MAX_WEDGE_TYPES, WEDGE_CODEBOOK_16_HGTW), # BLOCK_16X32
(MAX_WEDGE_TYPES, WEDGE_CODEBOOK_16_HLTW), # BLOCK_32X16
(MAX_WEDGE_TYPES, WEDGE_CODEBOOK_16_HEQW), # BLOCK_32X32
(0, None), (0, None), (0, None), (0, None),
(0, None), (0, None), (0, None), (0, None),
(MAX_WEDGE_TYPES, WEDGE_CODEBOOK_16_HGTW), # BLOCK_8X32
(MAX_WEDGE_TYPES, WEDGE_CODEBOOK_16_HLTW), # BLOCK_32X8
(0, None), (0, None),
]
assert len(WEDGE_PARAMS_LOOKUP) == BLOCK_SIZES_ALL
# ii_weights1d (see av1/common/reconinter.c).
II_WEIGHTS_1D = [
60, 58, 56, 54, 52, 50, 48, 47, 45, 44, 42, 41, 39, 38, 37, 35, 34, 33, 32,
31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 22, 21, 20, 19, 19, 18, 18, 17, 16,
16, 15, 15, 14, 14, 13, 13, 12, 12, 12, 11, 11, 10, 10, 10, 9, 9, 9, 8,
8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 4, 4,
4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
]
assert len(II_WEIGHTS_1D) == MAX_SB_SIZE
# ii_size_scales (see av1/common/reconinter.c).
II_SIZE_SCALES = [
32, 16, 16, 16, 8, 8, 8, 4,
4, 4, 2, 2, 2, 1, 1, 1,
8, 8, 4, 4, 2, 2,
]
assert len(II_SIZE_SCALES) == BLOCK_SIZES_ALL
# -----------------------------------------------------------------------------
# Algorithm: build wedge_mask_obl (init_wedge_master_masks in reconinter.c).
# -----------------------------------------------------------------------------
def shift_copy(src, dst, dst_off, shift, width):
"""Mirrors shift_copy() in reconinter.c."""
if shift >= 0:
for i in range(width - shift):
dst[dst_off + shift + i] = src[i]
for i in range(shift):
dst[dst_off + i] = src[0]
else:
n = -shift
for i in range(width - n):
dst[dst_off + i] = src[n + i]
for i in range(n):
dst[dst_off + width - n + i] = src[width - 1]
def build_wedge_mask_obl():
# [negative][direction] indexed flat per direction, MASK_MASTER_SIZE^2 bytes.
obl = [[[0] * (MASK_MASTER_SIZE * MASK_MASTER_SIZE)
for _ in range(WEDGE_DIRECTIONS)]
for _ in range(2)]
w = MASK_MASTER_SIZE
h = MASK_MASTER_SIZE
stride = MASK_MASTER_STRIDE
shift = h // 4
i = 0
while i < h:
shift_copy(WEDGE_MASTER_OBLIQUE_EVEN,
obl[0][WEDGE_OBLIQUE63], i * stride, shift, MASK_MASTER_SIZE)
shift -= 1
shift_copy(WEDGE_MASTER_OBLIQUE_ODD,
obl[0][WEDGE_OBLIQUE63], (i + 1) * stride, shift,
MASK_MASTER_SIZE)
# Vertical rows are just the vertical master copied each row.
for k in range(MASK_MASTER_SIZE):
obl[0][WEDGE_VERTICAL][i * stride + k] = WEDGE_MASTER_VERTICAL[k]
obl[0][WEDGE_VERTICAL][(i + 1) * stride + k] = (
WEDGE_MASTER_VERTICAL[k])
i += 2
max_val = 1 << WEDGE_WEIGHT_BITS # 64
for i in range(h):
for j in range(w):
msk = obl[0][WEDGE_OBLIQUE63][i * stride + j]
obl[0][WEDGE_OBLIQUE27][j * stride + i] = msk
obl[0][WEDGE_OBLIQUE117][i * stride + w - 1 - j] = max_val - msk
obl[0][WEDGE_OBLIQUE153][(w - 1 - j) * stride + i] = max_val - msk
obl[1][WEDGE_OBLIQUE63][i * stride + j] = max_val - msk
obl[1][WEDGE_OBLIQUE27][j * stride + i] = max_val - msk
obl[1][WEDGE_OBLIQUE117][i * stride + w - 1 - j] = msk
obl[1][WEDGE_OBLIQUE153][(w - 1 - j) * stride + i] = msk
mskx = obl[0][WEDGE_VERTICAL][i * stride + j]
obl[0][WEDGE_HORIZONTAL][j * stride + i] = mskx
obl[1][WEDGE_VERTICAL][i * stride + j] = max_val - mskx
obl[1][WEDGE_HORIZONTAL][j * stride + i] = max_val - mskx
return obl
# -----------------------------------------------------------------------------
# Algorithm: build wedge_mask_buf and wedge_masks offset table
# (init_wedge_masks + get_wedge_mask_inplace + aom_convolve_copy).
# -----------------------------------------------------------------------------
def get_wedge_mask_inplace_offset(wedge_obl, w_idx, neg, bsize):
"""Compute the starting (row, col) into wedge_mask_obl[neg^wsignflip][dir]
for a given wedge index/sign/block-size; mirrors get_wedge_mask_inplace().
Returns (which_neg, direction, row_off, col_off)."""
bw = BLOCK_WIDTH[bsize]
bh = BLOCK_HEIGHT[bsize]
wtypes, codebook = WEDGE_PARAMS_LOOKUP[bsize]
assert wtypes > 0
direction, x_off, y_off = codebook[w_idx]
woff = (x_off * bw) >> 3
hoff = (y_off * bh) >> 3
wsignflip = WEDGE_SIGNFLIP_LOOKUP[bsize][w_idx]
which = neg ^ wsignflip
row_off = MASK_MASTER_SIZE // 2 - hoff
col_off = MASK_MASTER_SIZE // 2 - woff
return which, direction, row_off, col_off
def build_wedge_mask_buf(obl):
buf_size = 2 * MAX_WEDGE_TYPES * 4 * MAX_WEDGE_SQUARE
buf = [0] * buf_size
# Offset table: wedge_masks[bsize][sign][wedge_index] -> uint32 offset.
offsets = [[[0] * MAX_WEDGE_TYPES for _ in range(2)]
for _ in range(BLOCK_SIZES_ALL)]
dst = 0
for bsize in range(BLOCK_SIZES_ALL):
wtypes, _ = WEDGE_PARAMS_LOOKUP[bsize]
if wtypes == 0:
continue
bw = BLOCK_WIDTH[bsize]
bh = BLOCK_HEIGHT[bsize]
for w_idx in range(wtypes):
# sign 0
which, direction, row_off, col_off = (
get_wedge_mask_inplace_offset(obl, w_idx, 0, bsize))
src = obl[which][direction]
for r in range(bh):
for c in range(bw):
buf[dst + r * bw + c] = src[
(row_off + r) * MASK_MASTER_STRIDE + (col_off + c)]
offsets[bsize][0][w_idx] = dst
dst += bw * bh
# sign 1
which, direction, row_off, col_off = (
get_wedge_mask_inplace_offset(obl, w_idx, 1, bsize))
src = obl[which][direction]
for r in range(bh):
for c in range(bw):
buf[dst + r * bw + c] = src[
(row_off + r) * MASK_MASTER_STRIDE + (col_off + c)]
offsets[bsize][1][w_idx] = dst
dst += bw * bh
assert dst <= buf_size, (dst, buf_size)
return buf, offsets
# -----------------------------------------------------------------------------
# Algorithm: build smooth_interintra_mask_buf
# (init_smooth_interintra_masks + build_smooth_interintra_mask).
# -----------------------------------------------------------------------------
def build_smooth_interintra(mask, mask_off, stride, plane_bsize, mode):
bw = BLOCK_WIDTH[plane_bsize]
bh = BLOCK_HEIGHT[plane_bsize]
size_scale = II_SIZE_SCALES[plane_bsize]
if mode == II_V_PRED:
for i in range(bh):
row = mask_off + i * stride
val = II_WEIGHTS_1D[i * size_scale]
for j in range(bw):
mask[row + j] = val
elif mode == II_H_PRED:
for i in range(bh):
row = mask_off + i * stride
for j in range(bw):
mask[row + j] = II_WEIGHTS_1D[j * size_scale]
elif mode == II_SMOOTH_PRED:
for i in range(bh):
row = mask_off + i * stride
for j in range(bw):
mask[row + j] = II_WEIGHTS_1D[min(i, j) * size_scale]
else: # II_DC_PRED or default
for i in range(bh):
row = mask_off + i * stride
for j in range(bw):
mask[row + j] = 32
def build_smooth_interintra_mask_buf():
# [INTERINTRA_MODES][BLOCK_SIZES_ALL][MAX_WEDGE_SQUARE]
buf = [[[0] * MAX_WEDGE_SQUARE for _ in range(BLOCK_SIZES_ALL)]
for _ in range(INTERINTRA_MODES)]
for m in range(INTERINTRA_MODES):
for bs in range(BLOCK_SIZES_ALL):
bw = BLOCK_WIDTH[bs]
bh = BLOCK_HEIGHT[bs]
if bw > MAX_WEDGE_SIZE or bh > MAX_WEDGE_SIZE:
continue
build_smooth_interintra(buf[m][bs], 0, bw, bs, m)
return buf
# -----------------------------------------------------------------------------
# C emission helpers.
# -----------------------------------------------------------------------------
def emit_bytes_block(values, indent=" ", per_line=16):
lines = []
for chunk_start in range(0, len(values), per_line):
chunk = values[chunk_start:chunk_start + per_line]
parts = ["{:>3d}".format(v) for v in chunk]
lines.append(indent + ", ".join(parts) + ",")
return "\n".join(lines)
def emit_wedge_mask_obl(out, obl):
out.append(
"DECLARE_ALIGNED(16, static const uint8_t,")
out.append(
" wedge_mask_obl[2][WEDGE_DIRECTIONS]")
out.append(
" [MASK_MASTER_SIZE * MASK_MASTER_SIZE]) = {")
for neg in range(2):
out.append(" {")
for direction in range(WEDGE_DIRECTIONS):
out.append(" {{ // [{}][dir={}]".format(neg, direction))
out.append(emit_bytes_block(obl[neg][direction], indent=" "))
out.append(" },")
out.append(" },")
out.append("};")
def emit_wedge_mask_buf(out, buf):
out.append(
"DECLARE_ALIGNED(16, static const uint8_t,")
out.append(
" wedge_mask_buf[2 * MAX_WEDGE_TYPES * 4 *"
" MAX_WEDGE_SQUARE]) = {")
out.append(emit_bytes_block(buf, indent=" "))
out.append("};")
def emit_smooth_interintra(out, buf):
out.append(
"DECLARE_ALIGNED(16, static const uint8_t,")
out.append(
" smooth_interintra_mask_buf[INTERINTRA_MODES]")
out.append(
" [BLOCK_SIZES_ALL]")
out.append(
" [MAX_WEDGE_SQUARE]) = {")
for m in range(INTERINTRA_MODES):
out.append(" {")
for bs in range(BLOCK_SIZES_ALL):
out.append(" {{ // mode={}, bsize={}".format(m, BLOCK_NAMES[bs]))
out.append(emit_bytes_block(buf[m][bs], indent=" "))
out.append(" },")
out.append(" },")
out.append("};")
def emit_wedge_offsets(out, offsets):
out.append(
"static const wedge_masks_type wedge_masks[BLOCK_SIZES_ALL][2] = {")
for bs in range(BLOCK_SIZES_ALL):
out.append(" { // " + BLOCK_NAMES[bs])
for sign in range(2):
row = offsets[bs][sign]
parts = ["{:>6d}u".format(v) for v in row]
out.append(" { " + ", ".join(parts) + " },")
out.append(" },")
out.append("};")
HEADER_BANNER = """\
/*
* Copyright (c) 2026, Alliance for Open Media. All rights reserved.
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
// This file is auto-generated by tools/gen_wedge_masks_data.py. DO NOT EDIT.
//
// It precomputes the libaom AV1 compound-prediction wedge masks and
// inter-intra smooth blending masks so they can live in `.rdata` and be
// COW-shared across processes, instead of being computed at runtime into
// writable `.data` buffers via av1_init_wedge_masks().
//
// `wedge_masks` stores byte offsets into `wedge_mask_buf` (not pointers) so
// no loader relocations are needed.
//
// To regenerate after upstream changes to reconinter.c (wedge codebooks,
// master tables, BLOCK_SIZE enum, ii_weights1d, etc.) run:
// python3 source/libaom/tools/gen_wedge_masks_data.py
// --output source/libaom/av1/common/wedge_masks_data.inc
"""
def write_output(path, obl, buf, smooth, offsets):
out = []
out.append(HEADER_BANNER)
# Disable clang-format on the generated data tables. The emitters below
# produce a deliberately column-aligned, 16-values-per-line layout so the
# ~14k lines of mask data are visually scannable (you can eyeball the
# wedge patterns and offset progressions). clang-format would otherwise
# reflow each table to fit the project column limit, jumbling rows
# together, destroying the alignment, and producing a several-thousand-
# line diff every time anyone re-ran it.
out.append("// The data tables below are emitted by")
out.append("// tools/gen_wedge_masks_data.py with a fixed 16-values-per-row")
out.append("// layout for visual readability. clang-format would reflow")
out.append("// them to fit the project column limit, destroying the")
out.append("// alignment and producing a many-thousand-line diff. Keep the")
out.append("// formatter off until the closing `// clang-format on` below.")
out.append("// clang-format off")
out.append("")
# `wedge_mask_obl` is intentionally not emitted: it was only used at
# runtime as an intermediate to populate `wedge_mask_buf`, which is now
# precomputed below. Dropping it saves ~48 KB of .rdata.
_ = obl # retained for verification harnesses; unused here.
emit_wedge_mask_buf(out, buf)
out.append("")
emit_smooth_interintra(out, smooth)
out.append("")
emit_wedge_offsets(out, offsets)
out.append("")
out.append("// clang-format on")
out.append("")
text = "\n".join(out)
with open(path, "w", encoding="utf-8", newline="\n") as f:
f.write(text)
def main():
parser = argparse.ArgumentParser(description=__doc__)
default_out = os.path.normpath(
os.path.join(os.path.dirname(__file__), "..", "av1", "common",
"wedge_masks_data.inc"))
parser.add_argument("--output", default=default_out,
help="Path to wedge_masks_data.inc (default: %(default)s)")
args = parser.parse_args()
obl = build_wedge_mask_obl()
buf, offsets = build_wedge_mask_buf(obl)
smooth = build_smooth_interintra_mask_buf()
write_output(args.output, obl, buf, smooth, offsets)
print("Wrote {}".format(args.output))
if __name__ == "__main__":
main()