tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 }