diff options
Diffstat (limited to 'third_party/dav1d/src/intra_edge.c')
-rw-r--r-- | third_party/dav1d/src/intra_edge.c | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/third_party/dav1d/src/intra_edge.c b/third_party/dav1d/src/intra_edge.c new file mode 100644 index 0000000000..684d113fa9 --- /dev/null +++ b/third_party/dav1d/src/intra_edge.c @@ -0,0 +1,165 @@ +/* + * Copyright © 2018, VideoLAN and dav1d authors + * Copyright © 2018, Two Orioles, LLC + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. 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. + * + * 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 OWNER 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. + */ + +#include "config.h" + +#include <stdlib.h> + +#include "common/attributes.h" + +#include "src/intra_edge.h" +#include "src/levels.h" + +struct ModeSelMem { + EdgeBranch *nwc[3 /* 64x64, 32x32, 16x16 */]; + EdgeTip *nt; +}; + +static void init_edges(EdgeNode *const node, + const enum BlockLevel bl, + const enum EdgeFlags edge_flags) +{ + node->o = edge_flags; + +#define ALL_FL(t) (EDGE_I444_##t | EDGE_I422_##t | EDGE_I420_##t) + if (bl == BL_8X8) { + EdgeTip *const nt = (EdgeTip *) node; + + node->h[0] = edge_flags | ALL_FL(LEFT_HAS_BOTTOM); + node->h[1] = edge_flags & (ALL_FL(LEFT_HAS_BOTTOM) | + EDGE_I420_TOP_HAS_RIGHT); + + node->v[0] = edge_flags | ALL_FL(TOP_HAS_RIGHT); + node->v[1] = edge_flags & (ALL_FL(TOP_HAS_RIGHT) | + EDGE_I420_LEFT_HAS_BOTTOM | + EDGE_I422_LEFT_HAS_BOTTOM); + + nt->split[0] = ALL_FL(TOP_HAS_RIGHT) | ALL_FL(LEFT_HAS_BOTTOM); + nt->split[1] = (edge_flags & ALL_FL(TOP_HAS_RIGHT)) | + EDGE_I422_LEFT_HAS_BOTTOM; + nt->split[2] = edge_flags | EDGE_I444_TOP_HAS_RIGHT; + nt->split[3] = edge_flags & (EDGE_I420_TOP_HAS_RIGHT | + EDGE_I420_LEFT_HAS_BOTTOM | + EDGE_I422_LEFT_HAS_BOTTOM); + } else { + EdgeBranch *const nwc = (EdgeBranch *) node; + + node->h[0] = edge_flags | ALL_FL(LEFT_HAS_BOTTOM); + node->h[1] = edge_flags & ALL_FL(LEFT_HAS_BOTTOM); + + node->v[0] = edge_flags | ALL_FL(TOP_HAS_RIGHT); + node->v[1] = edge_flags & ALL_FL(TOP_HAS_RIGHT); + + nwc->h4[0] = edge_flags | ALL_FL(LEFT_HAS_BOTTOM); + nwc->h4[1] = + nwc->h4[2] = ALL_FL(LEFT_HAS_BOTTOM); + nwc->h4[3] = edge_flags & ALL_FL(LEFT_HAS_BOTTOM); + if (bl == BL_16X16) + nwc->h4[1] |= edge_flags & EDGE_I420_TOP_HAS_RIGHT; + + nwc->v4[0] = edge_flags | ALL_FL(TOP_HAS_RIGHT); + nwc->v4[1] = + nwc->v4[2] = ALL_FL(TOP_HAS_RIGHT); + nwc->v4[3] = edge_flags & ALL_FL(TOP_HAS_RIGHT); + if (bl == BL_16X16) + nwc->v4[1] |= edge_flags & (EDGE_I420_LEFT_HAS_BOTTOM | + EDGE_I422_LEFT_HAS_BOTTOM); + + nwc->tls[0] = ALL_FL(TOP_HAS_RIGHT) | ALL_FL(LEFT_HAS_BOTTOM); + nwc->tls[1] = edge_flags & ALL_FL(LEFT_HAS_BOTTOM); + nwc->tls[2] = edge_flags & ALL_FL(TOP_HAS_RIGHT); + + nwc->trs[0] = edge_flags | ALL_FL(TOP_HAS_RIGHT); + nwc->trs[1] = edge_flags | ALL_FL(LEFT_HAS_BOTTOM); + nwc->trs[2] = 0; + + nwc->tts[0] = ALL_FL(TOP_HAS_RIGHT) | ALL_FL(LEFT_HAS_BOTTOM); + nwc->tts[1] = edge_flags & ALL_FL(TOP_HAS_RIGHT); + nwc->tts[2] = edge_flags & ALL_FL(LEFT_HAS_BOTTOM); + + nwc->tbs[0] = edge_flags | ALL_FL(LEFT_HAS_BOTTOM); + nwc->tbs[1] = edge_flags | ALL_FL(TOP_HAS_RIGHT); + nwc->tbs[2] = 0; + } +} + +static void init_mode_node(EdgeBranch *const nwc, + const enum BlockLevel bl, + struct ModeSelMem *const mem, + const int top_has_right, + const int left_has_bottom) +{ + init_edges(&nwc->node, bl, + (top_has_right ? ALL_FL(TOP_HAS_RIGHT) : 0) | + (left_has_bottom ? ALL_FL(LEFT_HAS_BOTTOM) : 0)); + if (bl == BL_16X16) { + for (int n = 0; n < 4; n++) { + EdgeTip *const nt = mem->nt++; + nwc->split[n] = &nt->node; + init_edges(&nt->node, bl + 1, + ((n == 3 || (n == 1 && !top_has_right)) ? 0 : + ALL_FL(TOP_HAS_RIGHT)) | + (!(n == 0 || (n == 2 && left_has_bottom)) ? 0 : + ALL_FL(LEFT_HAS_BOTTOM))); + } + } else { + for (int n = 0; n < 4; n++) { + EdgeBranch *const nwc_child = mem->nwc[bl]++; + nwc->split[n] = &nwc_child->node; + init_mode_node(nwc_child, bl + 1, mem, + !(n == 3 || (n == 1 && !top_has_right)), + n == 0 || (n == 2 && left_has_bottom)); + } + } +} + +void dav1d_init_mode_tree(EdgeNode *const root_node, EdgeTip *const nt, + const int allow_sb128) +{ + EdgeBranch *const root = (EdgeBranch *) root_node; + struct ModeSelMem mem; + mem.nt = nt; + + if (allow_sb128) { + mem.nwc[BL_128X128] = &root[1]; + mem.nwc[BL_64X64] = &root[1 + 4]; + mem.nwc[BL_32X32] = &root[1 + 4 + 16]; + init_mode_node(root, BL_128X128, &mem, 1, 0); + assert(mem.nwc[BL_128X128] == &root[1 + 4]); + assert(mem.nwc[BL_64X64] == &root[1 + 4 + 16]); + assert(mem.nwc[BL_32X32] == &root[1 + 4 + 16 + 64]); + assert(mem.nt == &nt[256]); + } else { + mem.nwc[BL_128X128] = NULL; + mem.nwc[BL_64X64] = &root[1]; + mem.nwc[BL_32X32] = &root[1 + 4]; + init_mode_node(root, BL_64X64, &mem, 1, 0); + assert(mem.nwc[BL_64X64] == &root[1 + 4]); + assert(mem.nwc[BL_32X32] == &root[1 + 4 + 16]); + assert(mem.nt == &nt[64]); + } +} |