1 /*
2 * Copyright (C) 2006-2011 Michael Niedermayer <michaelni@gmx.at>
3 * 2010 James Darnley <james.darnley@gmail.com>
4
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22
23 #define MAX_ALIGN 8
24
25 /**
26 \fn getConfiguration
27 \brief Return current setting as a string
28 */
getNextFrame(uint32_t * fn,ADMImage * image)29 bool yadifFilter::getNextFrame(uint32_t *fn,ADMImage *image)
30 {
31
32 int mode;
33 int parity;
34 int tff;
35 int iplane;
36 int n;
37 ADMImage *src, *dst, * prev, *next;
38
39
40 mode = configuration.mode;
41
42 if (mode & 1)
43 {
44 n = (nextFrame>>1); // bob
45 }
46 else
47 n = nextFrame;
48
49 src = vidCache->getImage(n);
50 *fn=nextFrame;
51 if(!src) return false;
52
53
54 // If possible get previous image...
55 if (n>0)
56 prev = vidCache->getImage( n-1); // get previous frame
57 else
58 prev= src; // get very first frame
59
60 ADM_assert(prev);
61 next=vidCache->getImage(n+1);
62 if(!next) next=src;
63 ADM_assert(next);
64
65 dst = image;
66 dst->copyInfo(src);
67
68 if(!prev || !src || !next)
69 {
70 printf("Failed to read frame for frame %u\n",nextFrame);
71 vidCache->unlockAll();
72 return 0;
73 }
74
75 // Construct a frame based on the information of the current frame
76 // contained in the "vi" struct.
77 #if 0 //MEANX
78 if (configuration.order == -1)
79 // tff = avs_is_tff(&p->vi) == 0 ? 0 : 1; // 0 or 1
80 tff = avs_get_parity(p->child, n) ? 1 : 0; // 0 or 1
81 else
82 tff = configuration.parity;
83 #endif
84 tff = (configuration.parity > 0) ? 0 : 1;
85 parity = (mode & 1) ? (nextFrame & 1) ^ (1^tff) : (tff ^ 1); // 0 or 1
86
87 //MEANX cpu = avs_get_cpu_flags(p->env);
88
89 for (iplane = 0; iplane<3; iplane++)
90 {
91 ADM_PLANE plane = (iplane==0) ? PLANAR_Y : (iplane==1) ? PLANAR_U : PLANAR_V;
92
93 const unsigned char* srcp = src->GetWritePtr(plane);
94 // Request a Read pointer from the current source frame
95
96 const unsigned char* prevp0 = prev->GetWritePtr( plane);
97 unsigned char* prevp = (unsigned char*) prevp0; // with same pitch
98 // Request a Read pointer from the prev source frame.
99
100 const unsigned char* nextp0 = next->GetWritePtr( plane);
101 unsigned char* nextp = (unsigned char*) nextp0; // with same pitch
102 // Request a Read pointer from the next source frame.
103
104 unsigned char* dstp = dst->GetWritePtr( plane);
105 // Request a Write pointer from the newly created destination image.
106 // You can request a writepointer to images that have just been
107
108 const int dst_pitch = dst->GetPitch( plane);
109 // Requests pitch (length of a line) of the destination image.
110 // For more information on pitch see: http://www.avisynth.org/index.php?page=WorkingWithImages
111 // (short version - pitch is always equal to or greater than width to allow for seriously fast assembly code)
112
113 const int width =dst->GetPitch( plane);
114 // Requests rowsize (number of used bytes in a line.
115 // See the link above for more information.
116
117 const int height = dst->GetHeight( plane);
118 // Requests the height of the destination image.
119
120 const int src_pitch = src->GetPitch(plane);
121 const int prev_pitch = prev->GetPitch(plane);
122 const int next_pitch = next->GetPitch(plane);
123
124 // in v.0.1-0.3 all source pitches are assumed equal (for simplicity)
125 // consider other (rare) case
126 if (prev_pitch != src_pitch)
127 {
128 prevp = (unsigned char *)ADM_alloc(height*src_pitch);
129 int h;
130 for (h=0; h<0; h++)
131 memcpy(prevp+h*src_pitch, prevp0+h*prev_pitch, width);
132 }
133
134 if (next_pitch != src_pitch)
135 {
136 nextp = (unsigned char *)ADM_alloc(height*src_pitch);
137 int h;
138 for (h=0; h<0; h++)
139 memcpy(nextp+h*src_pitch, nextp0+h*next_pitch, width);
140 }
141
142 filter_plane(mode, dstp, dst_pitch, prevp, srcp, nextp, src_pitch, width, height, parity, tff, 0);
143 if (prev_pitch != src_pitch)
144 ADM_dealloc(prevp);
145 if (next_pitch != src_pitch)
146 ADM_dealloc(nextp);
147 }
148 vidCache->unlockAll();
149
150 if (mode & 1)
151 {
152 if(nextFrame&1)
153 image->Pts+= info.frameIncrement;
154 }
155 //printf("out PTs=%"PRIu64", nextFrame=%d,inc=%d\n",image->Pts,(int)nextFrame,(int)info.frameIncrement);
156 nextFrame++;
157 filter_end();
158 return 1;
159 }
160
161
filter_plane(int mode,uint8_t * dst,int dst_stride,const uint8_t * prev0,const uint8_t * cur0,const uint8_t * next0,int refs,int w,int h,int parity,int tff,int mmx)162 void yadifFilter::filter_plane(int mode, uint8_t *dst, int dst_stride, const uint8_t *prev0, const uint8_t *cur0, const uint8_t *next0, int refs, int w, int h, int parity, int tff, int mmx)
163 {
164 int df = 1;
165 int pix_3 = 3 * df;
166 int edge = 3 + MAX_ALIGN / df - 1;
167 //memcpy(dst, cur0, w);
168 //memcpy(dst + dst_stride, cur0 + refs, w);
169 for(int y=0; y<h; y++){
170 if(((y ^ parity) & 1)){
171 const uint8_t *prev= prev0 + y*refs;
172 const uint8_t *cur = cur0 + y*refs;
173 const uint8_t *next= next0 + y*refs;
174 uint8_t *dst2= dst + y*dst_stride;
175 int mode = y == 1 || y + 2 == h ? 2 : 0;
176 filter_line(dst2 + pix_3, prev + pix_3, cur + pix_3, next + pix_3,
177 w - edge,
178 y + 1 < h ? refs : -refs,
179 y ? -refs : refs,
180 parity ^ tff, mode);
181 filter_edges(dst2, prev, cur, next,
182 w,
183 y + 1 < h ? refs : -refs,
184 y ? -refs : refs,
185 parity ^ tff, mode);
186
187 }else{
188 memcpy(dst + y*dst_stride, cur0 + y*refs, w);
189 }
190 }
191 //memcpy(dst + (h-1)*dst_stride, cur0 + (h-1)*refs, w);
192
193 }
194
195 //--- ff ---
196 #define CHECK(j)\
197 { int score = FFABS(cur[mrefs - 1 + (j)] - cur[prefs - 1 - (j)])\
198 + FFABS(cur[mrefs +(j)] - cur[prefs -(j)])\
199 + FFABS(cur[mrefs + 1 + (j)] - cur[prefs + 1 - (j)]);\
200 if (score < spatial_score) {\
201 spatial_score= score;\
202 spatial_pred= (cur[mrefs +(j)] + cur[prefs -(j)])>>1;\
203
204 /* The is_not_edge argument here controls when the code will enter a branch
205 * which reads up to and including x-3 and x+3. */
206
207 #define FILTER(start, end, is_not_edge) \
208 for (x = start; x < end; x++) { \
209 int c = cur[mrefs]; \
210 int d = (prev2[0] + next2[0])>>1; \
211 int e = cur[prefs]; \
212 int temporal_diff0 = FFABS(prev2[0] - next2[0]); \
213 int temporal_diff1 =(FFABS(prev[mrefs] - c) + FFABS(prev[prefs] - e) )>>1; \
214 int temporal_diff2 =(FFABS(next[mrefs] - c) + FFABS(next[prefs] - e) )>>1; \
215 int diff = FFMAX3(temporal_diff0 >> 1, temporal_diff1, temporal_diff2); \
216 int spatial_pred = (c+e) >> 1; \
217 \
218 if (is_not_edge) {\
219 int spatial_score = FFABS(cur[mrefs - 1] - cur[prefs - 1]) + FFABS(c-e) \
220 + FFABS(cur[mrefs + 1] - cur[prefs + 1]) - 1; \
221 CHECK(-1) CHECK(-2) }} }} \
222 CHECK( 1) CHECK( 2) }} }} \
223 }\
224 \
225 if (!(mode&2)) { \
226 int b = (prev2[2 * mrefs] + next2[2 * mrefs])>>1; \
227 int f = (prev2[2 * prefs] + next2[2 * prefs])>>1; \
228 int max = FFMAX3(d - e, d - c, FFMIN(b - c, f - e)); \
229 int min = FFMIN3(d - e, d - c, FFMAX(b - c, f - e)); \
230 \
231 diff = FFMAX3(diff, min, -max); \
232 } \
233 \
234 if (spatial_pred > d + diff) \
235 spatial_pred = d + diff; \
236 else if (spatial_pred < d - diff) \
237 spatial_pred = d - diff; \
238 \
239 dst[0] = spatial_pred; \
240 \
241 dst++; \
242 cur++; \
243 prev++; \
244 next++; \
245 prev2++; \
246 next2++; \
247 }
248
filter_line_c(uint8_t * dst1,const uint8_t * prev1,const uint8_t * cur1,const uint8_t * next1,int w,int prefs,int mrefs,int parity,int mode)249 void filter_line_c(uint8_t *dst1,
250 const uint8_t *prev1, const uint8_t *cur1, const uint8_t *next1,
251 int w, int prefs, int mrefs, int parity, int mode)
252 {
253 uint8_t *dst = (uint8_t *) dst1;
254 uint8_t *prev = (uint8_t *)prev1;
255 uint8_t *cur = (uint8_t *)cur1;
256 uint8_t *next = (uint8_t *)next1;
257 int x;
258 uint8_t *prev2 = parity ? prev : cur ;
259 uint8_t *next2 = parity ? cur : next;
260
261 /* The function is called with the pointers already pointing to data[3] and
262 * with 6 subtracted from the width. This allows the FILTER macro to be
263 * called so that it processes all the pixels normally. A constant value of
264 * true for is_not_edge lets the compiler ignore the if statement. */
265 FILTER(0, w, 1)
266 }
267
268
filter_edges_c(uint8_t * dst1,const uint8_t * prev1,const uint8_t * cur1,const uint8_t * next1,int w,int prefs,int mrefs,int parity,int mode)269 void filter_edges_c(uint8_t *dst1, const uint8_t *prev1, const uint8_t *cur1, const uint8_t *next1,
270 int w, int prefs, int mrefs, int parity, int mode)
271 {
272 uint8_t *dst = (uint8_t *)dst1;
273 uint8_t *prev = (uint8_t *)prev1;
274 uint8_t *cur = (uint8_t *)cur1;
275 uint8_t *next = (uint8_t *)next1;
276 int x;
277 uint8_t *prev2 = parity ? prev : cur ;
278 uint8_t *next2 = parity ? cur : next;
279
280 const int edge = MAX_ALIGN - 1;
281
282 /* Only edge pixels need to be processed here. A constant value of false
283 * for is_not_edge should let the compiler ignore the whole branch. */
284 FILTER(0, 3, 0)
285
286 dst = (uint8_t*)dst1 + w - edge;
287 prev = (uint8_t*)prev1 + w - edge;
288 cur = (uint8_t*)cur1 + w - edge;
289 next = (uint8_t*)next1 + w - edge;
290 prev2 = (uint8_t*)(parity ? prev : cur);
291 next2 = (uint8_t*)(parity ? cur : next);
292
293 FILTER(w - edge, w - 3, 1)
294 FILTER(w - 3, w, 0)
295 }
296
297