vp56dsp.c 3.12 KB
Newer Older
1 2 3 4
/*
 * Copyright (c) 2006 Aurelien Jacobs <aurel@gnuage.org>
 * Copyright (c) 2010 Mans Rullgard <mans@mansr.com>
 *
5
 * This file is part of Libav.
6
 *
7
 * Libav is free software; you can redistribute it and/or
8 9 10 11
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
12
 * Libav is distributed in the hope that it will be useful,
13 14 15 16 17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with Libav; if not, write to the Free Software
19 20 21 22
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include <stdint.h>
23 24

#include "libavutil/attributes.h"
25 26
#include "avcodec.h"
#include "vp56dsp.h"
27
#include "libavutil/common.h"
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79

/* Gives very similar result than the vp6 version except in a few cases */
static int vp5_adjust(int v, int t)
{
    int s2, s1 = v >> 31;
    v ^= s1;
    v -= s1;
    v *= v < 2*t;
    v -= t;
    s2 = v >> 31;
    v ^= s2;
    v -= s2;
    v = t - v;
    v += s1;
    v ^= s1;
    return v;
}

static int vp6_adjust(int v, int t)
{
    int V = v, s = v >> 31;
    V ^= s;
    V -= s;
    if (V-t-1 >= (unsigned)(t-1))
        return v;
    V = 2*t - V;
    V += s;
    V ^= s;
    return V;
}


#define VP56_EDGE_FILTER(pfx, suf, pix_inc, line_inc)                   \
static void pfx##_edge_filter_##suf(uint8_t *yuv, int stride, int t)    \
{                                                                       \
    int pix2_inc = 2 * pix_inc;                                         \
    int i, v;                                                           \
                                                                        \
    for (i=0; i<12; i++) {                                              \
        v = (yuv[-pix2_inc] + 3*(yuv[0]-yuv[-pix_inc]) - yuv[pix_inc] + 4)>>3;\
        v = pfx##_adjust(v, t);                                         \
        yuv[-pix_inc] = av_clip_uint8(yuv[-pix_inc] + v);               \
        yuv[0] = av_clip_uint8(yuv[0] - v);                             \
        yuv += line_inc;                                                \
    }                                                                   \
}

VP56_EDGE_FILTER(vp5, hor, 1, stride)
VP56_EDGE_FILTER(vp5, ver, stride, 1)
VP56_EDGE_FILTER(vp6, hor, 1, stride)
VP56_EDGE_FILTER(vp6, ver, stride, 1)

80
av_cold void ff_vp56dsp_init(VP56DSPContext *s, enum AVCodecID codec)
81
{
82
    if (codec == AV_CODEC_ID_VP5) {
83 84 85 86 87
        s->edge_filter_hor = vp5_edge_filter_hor;
        s->edge_filter_ver = vp5_edge_filter_ver;
    } else {
        s->edge_filter_hor = vp6_edge_filter_hor;
        s->edge_filter_ver = vp6_edge_filter_ver;
88 89

        if (CONFIG_VP6_DECODER) {
Aurelien Jacobs's avatar
Aurelien Jacobs committed
90
            s->vp6_filter_diag4 = ff_vp6_filter_diag4_c;
91 92 93 94 95

            if (ARCH_ARM)
                ff_vp6dsp_init_arm(s, codec);
            if (ARCH_X86)
                ff_vp6dsp_init_x86(s, codec);
96
        }
97 98
    }
}