ipred_prepare_tmpl.c (7751B)
1 /* 2 * Copyright © 2018, VideoLAN and dav1d authors 3 * Copyright © 2018, Two Orioles, LLC 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright notice, this 10 * list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions and the following disclaimer in the documentation 14 * and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include "config.h" 29 30 #include <stdint.h> 31 #include <string.h> 32 33 #include "common/intops.h" 34 35 #include "src/ipred_prepare.h" 36 37 static const uint8_t av1_mode_conv[N_INTRA_PRED_MODES] 38 [2 /* have_left */][2 /* have_top */] = 39 { 40 [DC_PRED] = { { DC_128_PRED, TOP_DC_PRED }, 41 { LEFT_DC_PRED, DC_PRED } }, 42 [PAETH_PRED] = { { DC_128_PRED, VERT_PRED }, 43 { HOR_PRED, PAETH_PRED } }, 44 }; 45 46 static const uint8_t av1_mode_to_angle_map[8] = { 47 90, 180, 45, 135, 113, 157, 203, 67 48 }; 49 50 static const struct { 51 uint8_t needs_left:1; 52 uint8_t needs_top:1; 53 uint8_t needs_topleft:1; 54 uint8_t needs_topright:1; 55 uint8_t needs_bottomleft:1; 56 } av1_intra_prediction_edges[N_IMPL_INTRA_PRED_MODES] = { 57 [DC_PRED] = { .needs_top = 1, .needs_left = 1 }, 58 [VERT_PRED] = { .needs_top = 1 }, 59 [HOR_PRED] = { .needs_left = 1 }, 60 [LEFT_DC_PRED] = { .needs_left = 1 }, 61 [TOP_DC_PRED] = { .needs_top = 1 }, 62 [DC_128_PRED] = { 0 }, 63 [Z1_PRED] = { .needs_top = 1, .needs_topright = 1, 64 .needs_topleft = 1 }, 65 [Z2_PRED] = { .needs_left = 1, .needs_top = 1, .needs_topleft = 1 }, 66 [Z3_PRED] = { .needs_left = 1, .needs_bottomleft = 1, 67 .needs_topleft = 1 }, 68 [SMOOTH_PRED] = { .needs_left = 1, .needs_top = 1 }, 69 [SMOOTH_V_PRED] = { .needs_left = 1, .needs_top = 1 }, 70 [SMOOTH_H_PRED] = { .needs_left = 1, .needs_top = 1 }, 71 [PAETH_PRED] = { .needs_left = 1, .needs_top = 1, .needs_topleft = 1 }, 72 [FILTER_PRED] = { .needs_left = 1, .needs_top = 1, .needs_topleft = 1 }, 73 }; 74 75 enum IntraPredMode 76 bytefn(dav1d_prepare_intra_edges)(const int x, const int have_left, 77 const int y, const int have_top, 78 const int w, const int h, 79 const enum EdgeFlags edge_flags, 80 const pixel *const dst, 81 const ptrdiff_t stride, 82 const pixel *prefilter_toplevel_sb_edge, 83 enum IntraPredMode mode, int *const angle, 84 const int tw, const int th, const int filter_edge, 85 pixel *const topleft_out HIGHBD_DECL_SUFFIX) 86 { 87 const int bitdepth = bitdepth_from_max(bitdepth_max); 88 assert(y < h && x < w); 89 90 switch (mode) { 91 case VERT_PRED: 92 case HOR_PRED: 93 case DIAG_DOWN_LEFT_PRED: 94 case DIAG_DOWN_RIGHT_PRED: 95 case VERT_RIGHT_PRED: 96 case HOR_DOWN_PRED: 97 case HOR_UP_PRED: 98 case VERT_LEFT_PRED: { 99 *angle = av1_mode_to_angle_map[mode - VERT_PRED] + 3 * *angle; 100 101 if (*angle <= 90) 102 mode = *angle < 90 && have_top ? Z1_PRED : VERT_PRED; 103 else if (*angle < 180) 104 mode = Z2_PRED; 105 else 106 mode = *angle > 180 && have_left ? Z3_PRED : HOR_PRED; 107 break; 108 } 109 case DC_PRED: 110 case PAETH_PRED: 111 mode = av1_mode_conv[mode][have_left][have_top]; 112 break; 113 default: 114 break; 115 } 116 117 const pixel *dst_top; 118 if (have_top && 119 (av1_intra_prediction_edges[mode].needs_top || 120 av1_intra_prediction_edges[mode].needs_topleft || 121 (av1_intra_prediction_edges[mode].needs_left && !have_left))) 122 { 123 if (prefilter_toplevel_sb_edge) { 124 dst_top = &prefilter_toplevel_sb_edge[x * 4]; 125 } else { 126 dst_top = &dst[-PXSTRIDE(stride)]; 127 } 128 } 129 130 if (av1_intra_prediction_edges[mode].needs_left) { 131 const int sz = th << 2; 132 pixel *const left = &topleft_out[-sz]; 133 134 if (have_left) { 135 const int px_have = imin(sz, (h - y) << 2); 136 137 for (int i = 0; i < px_have; i++) 138 left[sz - 1 - i] = dst[PXSTRIDE(stride) * i - 1]; 139 if (px_have < sz) 140 pixel_set(left, left[sz - px_have], sz - px_have); 141 } else { 142 pixel_set(left, have_top ? *dst_top : ((1 << bitdepth) >> 1) + 1, sz); 143 } 144 145 if (av1_intra_prediction_edges[mode].needs_bottomleft) { 146 const int have_bottomleft = (!have_left || y + th >= h) ? 0 : 147 (edge_flags & EDGE_I444_LEFT_HAS_BOTTOM); 148 149 if (have_bottomleft) { 150 const int px_have = imin(sz, (h - y - th) << 2); 151 152 for (int i = 0; i < px_have; i++) 153 left[-(i + 1)] = dst[(sz + i) * PXSTRIDE(stride) - 1]; 154 if (px_have < sz) 155 pixel_set(left - sz, left[-px_have], sz - px_have); 156 } else { 157 pixel_set(left - sz, left[0], sz); 158 } 159 } 160 } 161 162 if (av1_intra_prediction_edges[mode].needs_top) { 163 const int sz = tw << 2; 164 pixel *const top = &topleft_out[1]; 165 166 if (have_top) { 167 const int px_have = imin(sz, (w - x) << 2); 168 pixel_copy(top, dst_top, px_have); 169 if (px_have < sz) 170 pixel_set(top + px_have, top[px_have - 1], sz - px_have); 171 } else { 172 pixel_set(top, have_left ? dst[-1] : ((1 << bitdepth) >> 1) - 1, sz); 173 } 174 175 if (av1_intra_prediction_edges[mode].needs_topright) { 176 const int have_topright = (!have_top || x + tw >= w) ? 0 : 177 (edge_flags & EDGE_I444_TOP_HAS_RIGHT); 178 179 if (have_topright) { 180 const int px_have = imin(sz, (w - x - tw) << 2); 181 182 pixel_copy(top + sz, &dst_top[sz], px_have); 183 if (px_have < sz) 184 pixel_set(top + sz + px_have, top[sz + px_have - 1], 185 sz - px_have); 186 } else { 187 pixel_set(top + sz, top[sz - 1], sz); 188 } 189 } 190 } 191 192 if (av1_intra_prediction_edges[mode].needs_topleft) { 193 if (have_left) 194 *topleft_out = have_top ? dst_top[-1] : dst[-1]; 195 else 196 *topleft_out = have_top ? *dst_top : (1 << bitdepth) >> 1; 197 198 if (mode == Z2_PRED && tw + th >= 6 && filter_edge) 199 *topleft_out = ((topleft_out[-1] + topleft_out[1]) * 5 + 200 topleft_out[0] * 6 + 8) >> 4; 201 } 202 203 return mode; 204 }