1 /*
2 * Copyright (C) 2006 Michael Niedermayer <michaelni@gmx.at>
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with FFmpeg; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21 #ifdef HAVE_CONFIG_H
22 # include "config.h"
23 #endif
24
25 #include <stdalign.h>
26
27 #if defined(__GNUC__)
28 # define ATTR_USED __attribute__((used))
29 #else
30 # define ATTR_USED
31 #endif
32
33 typedef intptr_t x86_reg;
34 typedef struct { uint64_t a, b; } xmm_reg;
35
36 const ATTR_USED alignas (16) xmm_reg pb_1 = {
37 0x0101010101010101ULL, 0x0101010101010101ULL
38 };
39 const ATTR_USED alignas (16) xmm_reg pw_1 = {
40 0x0001000100010001ULL, 0x0001000100010001ULL
41 };
42
43 #ifdef CAN_COMPILE_SSSE3
44 #if defined(__SSE__) || defined(__GNUC__) || defined(__clang__)
45 // ================ SSSE3 =================
46 #define HAVE_YADIF_SSSE3
47 #define COMPILE_TEMPLATE_SSE 1
48 #define COMPILE_TEMPLATE_SSSE3 1
49 #define VLC_TARGET VLC_SSE
50 #define RENAME(a) a ## _ssse3
51 #include "yadif_template.h"
52 #undef COMPILE_TEMPLATE_SSE
53 #undef COMPILE_TEMPLATE_SSSE3
54 #undef VLC_TARGET
55 #undef RENAME
56 #endif
57 #endif
58
59 #ifdef CAN_COMPILE_SSE2
60 #if defined(__SSE__) || defined(__GNUC__) || defined(__clang__)
61 // ================= SSE2 =================
62 #define HAVE_YADIF_SSE2
63 #define COMPILE_TEMPLATE_SSE 1
64 #define VLC_TARGET VLC_SSE
65 #define RENAME(a) a ## _sse2
66 #include "yadif_template.h"
67 #undef COMPILE_TEMPLATE_SSE
68 #undef VLC_TARGET
69 #undef RENAME
70 #endif
71 #endif
72
73 #ifdef CAN_COMPILE_MMX
74 #if defined(__MMX__) || defined(__GNUC__) || defined(__clang__)
75 // ================ MMX =================
76 #define HAVE_YADIF_MMX
77 #define VLC_TARGET VLC_MMX
78 #define RENAME(a) a ## _mmx
79 #include "yadif_template.h"
80 #undef VLC_TARGET
81 #undef RENAME
82 #endif
83 #endif
84
85 #define FFABS abs
86
87 #define CHECK(j)\
88 { int score = FFABS(cur[mrefs-1+(j)] - cur[prefs-1-(j)])\
89 + FFABS(cur[mrefs +(j)] - cur[prefs -(j)])\
90 + FFABS(cur[mrefs+1+(j)] - cur[prefs+1-(j)]);\
91 if (score < spatial_score) {\
92 spatial_score= score;\
93 spatial_pred= (cur[mrefs +(j)] + cur[prefs -(j)])>>1;\
94
95 #define FILTER \
96 for (x = 0; x < w; x++) { \
97 int c = cur[mrefs]; \
98 int d = (prev2[0] + next2[0])>>1; \
99 int e = cur[prefs]; \
100 int temporal_diff0 = FFABS(prev2[0] - next2[0]); \
101 int temporal_diff1 =(FFABS(prev[mrefs] - c) + FFABS(prev[prefs] - e) )>>1; \
102 int temporal_diff2 =(FFABS(next[mrefs] - c) + FFABS(next[prefs] - e) )>>1; \
103 int diff = FFMAX3(temporal_diff0>>1, temporal_diff1, temporal_diff2); \
104 int spatial_pred = (c+e)>>1; \
105 int spatial_score = FFABS(cur[mrefs-1] - cur[prefs-1]) + FFABS(c-e) \
106 + FFABS(cur[mrefs+1] - cur[prefs+1]) - 1; \
107 \
108 CHECK(-1) CHECK(-2) }} }} \
109 CHECK( 1) CHECK( 2) }} }} \
110 \
111 if (mode < 2) { \
112 int b = (prev2[2*mrefs] + next2[2*mrefs])>>1; \
113 int f = (prev2[2*prefs] + next2[2*prefs])>>1; \
114 int max = FFMAX3(d-e, d-c, FFMIN(b-c, f-e)); \
115 int min = FFMIN3(d-e, d-c, FFMAX(b-c, f-e)); \
116 \
117 diff = FFMAX3(diff, min, -max); \
118 } \
119 \
120 if (spatial_pred > d + diff) \
121 spatial_pred = d + diff; \
122 else if (spatial_pred < d - diff) \
123 spatial_pred = d - diff; \
124 \
125 dst[0] = spatial_pred; \
126 \
127 dst++; \
128 cur++; \
129 prev++; \
130 next++; \
131 prev2++; \
132 next2++; \
133 }
134
yadif_filter_line_c(uint8_t * dst,uint8_t * prev,uint8_t * cur,uint8_t * next,int w,int prefs,int mrefs,int parity,int mode)135 static void yadif_filter_line_c(uint8_t *dst, uint8_t *prev, uint8_t *cur, uint8_t *next, int w, int prefs, int mrefs, int parity, int mode) {
136 int x;
137 uint8_t *prev2= parity ? prev : cur ;
138 uint8_t *next2= parity ? cur : next;
139 FILTER
140 }
141
yadif_filter_line_c_16bit(uint16_t * dst,uint16_t * prev,uint16_t * cur,uint16_t * next,int w,int prefs,int mrefs,int parity,int mode)142 static void yadif_filter_line_c_16bit(uint16_t *dst, uint16_t *prev, uint16_t *cur, uint16_t *next, int w, int prefs, int mrefs, int parity, int mode) {
143 int x;
144 uint16_t *prev2= parity ? prev : cur ;
145 uint16_t *next2= parity ? cur : next;
146 mrefs /= 2;
147 prefs /= 2;
148 FILTER
149 }
150