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