1 /*
2 *
3 * Ported from yadif c plugin, then ported from ffmpeg vf_yadif
4 *
5 *
6 * Copyright (C) 2006-2011 Michael Niedermayer <michaelni@gmx.at>
7 * 2010 James Darnley <james.darnley@gmail.com>
8
9 * This file is part of FFmpeg.
10 *
11 * FFmpeg is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * FFmpeg is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with FFmpeg; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 *
26 Yadif C-plugin for Avisynth 2.5 - Yet Another DeInterlacing Filter
27 Copyright (C)2007 Alexander G. Balakhnin aka Fizick http://avisynth.org.ru
28 Port of YADIF filter from MPlayer
29 Copyright (C) 2006 Michael Niedermayer <michaelni@gmx.at>
30
31 This program is free software; you can redistribute it and/or modify
32 it under the terms of the GNU General Public License as published by
33 the Free Software Foundation.
34
35 This program is distributed in the hope that it will be useful,
36 but WITHOUT ANY WARRANTY; without even the implied warranty of
37 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 GNU General Public License for more details.
39
40 You should have received a copy of the GNU General Public License
41 along with this program; if not, write to the Free Software
42 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
43
44 Avisynth_C plugin
45 Assembler optimized for GNU C compiler
46
47 */
48
49 #include "ADM_default.h"
50 #include "ADM_coreVideoFilter.h"
51 #include "ADM_videoFilterCache.h"
52 #include "DIA_factory.h"
53 #include "yadif.h"
54 #include "yadif_desc.cpp"
55 #include "libavutil/common.h"
56 #if defined( ADM_CPU_X86)
57 #define CAN_DO_INLINE_X86_ASM
58 #endif
59
60
61 //************************************************
62
63
64 static void 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);
65 static void 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);
filter_end_c(void)66 static void filter_end_c(void) {};
67
68 //===========================================================================//
69 #ifdef CAN_DO_INLINE_X86_ASM
70 extern "C"
71 {
72 void filter_end_sse(void); // emms , not needed for sse2
73 void adm_yadif_filter_line_sse2( 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);
74 void adm_yadif_filter_line_ssse3( 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);
75 }
76 #endif
77
78
79 enum YADIFMode {
80 YADIF_MODE_SEND_FRAME = 0, ///< send 1 frame for each frame
81 YADIF_MODE_SEND_FIELD = 1, ///< send 1 frame for each field
82 YADIF_MODE_SEND_FRAME_NOSPATIAL = 2, ///< send 1 frame for each frame but skips spatial interlacing check
83 YADIF_MODE_SEND_FIELD_NOSPATIAL = 3, ///< send 1 frame for each field but skips spatial interlacing check
84 };
85
86 enum YADIFParity {
87 YADIF_PARITY_TFF = 0, ///< top field first
88 YADIF_PARITY_BFF = 1, ///< bottom field first
89 YADIF_PARITY_AUTO = -1, ///< auto detection
90 };
91
92 enum YADIFDeint {
93 YADIF_DEINT_ALL = 0, ///< deinterlace all frames
94 YADIF_DEINT_INTERLACED = 1, ///< only deinterlace frames marked as interlaced
95 };
96
97
98 //
99 /**
100 \class yadifFilter
101 */
102 class yadifFilter : public ADM_coreVideoFilterCached
103 {
104 protected:
105 yadif configuration;
106 void updateInfo(void);
107 public:
108 yadifFilter(ADM_coreVideoFilter *previous,CONFcouple *conf);
~yadifFilter()109 ~yadifFilter() {};
110
111 virtual const char *getConfiguration(void); /// Return current configuration as a human readable string
112 virtual bool getNextFrame(uint32_t *fn,ADMImage *image); /// Return the next image
113 virtual bool getCoupledConf(CONFcouple **couples) ; /// Return the current filter configuration
114 virtual void setCoupledConf(CONFcouple *couples);
115 virtual bool configure(void) ; /// Start graphical user interface
116 virtual bool goToTime(uint64_t usSeek);
117
118 protected:
119 void (*filter_line) (uint8_t *dst, const uint8_t *prev, const uint8_t *cur, const uint8_t *next, int w, int prefs, int mrefs, int parity, int mode);
120 void (*filter_edges)(uint8_t *dst, const uint8_t *prev, const uint8_t *cur, const uint8_t *next, int w, int prefs, int mrefs, int parity, int mode);
121 void (*filter_end)(void);
122
123 void 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);
124 };
125
126 // Add the hook to make it valid plugin
127 DECLARE_VIDEO_FILTER( yadifFilter, // Class
128 1,0,0, // Version
129 ADM_UI_ALL, // UI
130 VF_INTERLACING, // Category
131 "yadif", // internal name (must be uniq!)
132 QT_TRANSLATE_NOOP("yadif","Yadif"), // Display name
133 QT_TRANSLATE_NOOP("yadif","Yadif, port of avisynth version (c) Fizick.") // Description
134 );
135
136 //
137
138 /**
139 \fn constructor
140 */
yadifFilter(ADM_coreVideoFilter * in,CONFcouple * setup)141 yadifFilter::yadifFilter(ADM_coreVideoFilter *in, CONFcouple *setup):
142 ADM_coreVideoFilterCached(10,in,setup)
143 {
144 if(!setup || !ADM_paramLoad(setup,yadif_param,&configuration))
145 {
146 // Default value
147 configuration.mode=YADIF_MODE_SEND_FRAME;
148 configuration.deint=YADIF_DEINT_ALL;
149 configuration.parity=YADIF_PARITY_TFF;
150 }
151 updateInfo();
152
153 filter_line=filter_line_c;
154 filter_edges=filter_edges_c;
155 filter_end=filter_end_c;
156
157 #ifdef CAN_DO_INLINE_X86_ASM
158 if (CpuCaps::hasSSSE3())
159 {
160 filter_line=adm_yadif_filter_line_ssse3;
161 }else
162 if (CpuCaps::hasSSE2())
163 {
164 filter_line=adm_yadif_filter_line_sse2;
165 }
166 #endif
167
168 myName="yadif";
169 }
170 /**
171 \fn updateInfo
172 */
updateInfo(void)173 void yadifFilter::updateInfo(void)
174 {
175 memcpy(&info,previousFilter->getInfo(),sizeof(info));
176 if(configuration.mode &1 ) // Bob
177 {
178 info.frameIncrement/=2;
179 if(info.timeBaseNum && info.timeBaseDen)
180 {
181 if(info.timeBaseDen<=30000 && (info.timeBaseNum & 1))
182 info.timeBaseDen*=2;
183 else
184 info.timeBaseNum/=2;
185 }
186 }
187 }
188 /**
189 \fn configure
190 */
configure(void)191 bool yadifFilter::configure( void)
192 {
193
194 diaMenuEntry tMode[]={
195 {0, QT_TRANSLATE_NOOP("yadif","Frame : Temporal & spatial check"),NULL},
196 {1, QT_TRANSLATE_NOOP("yadif","Field : Temporal & spatial check"),NULL},
197 {2, QT_TRANSLATE_NOOP("yadif","Frame : Skip spatial temporal check"),NULL},
198 {3, QT_TRANSLATE_NOOP("yadif","Field : Skip spatial temporal check"),NULL}
199 };
200 diaMenuEntry tOrder[]={
201 //{0, QT_TRANSLATE_NOOP("yadif","Auto"),NULL},
202 {1, QT_TRANSLATE_NOOP("yadif","Top field first"),NULL},
203 {2, QT_TRANSLATE_NOOP("yadif","Bottom field first"),NULL}
204 };
205
206 diaMenuEntry tDeint[]={
207 {0, QT_TRANSLATE_NOOP("yadif","Deint all"),NULL},
208 {1, QT_TRANSLATE_NOOP("yadif","Deint interlaced"),NULL}
209 };
210
211
212 uint32_t parity=configuration.parity+1;
213 diaElemMenu mMode(&(configuration.mode), QT_TRANSLATE_NOOP("yadif","_Mode:"), 4,tMode);
214 diaElemMenu mDeint(&(configuration.deint), QT_TRANSLATE_NOOP("yadif","_Deint:"), 2,tDeint);
215 diaElemMenu mOrder(&(parity), QT_TRANSLATE_NOOP("yadif","_Order:"), 2,tOrder);
216 diaElem *elems[]={&mMode,&mOrder}; //,&mDeint};
217
218 if(diaFactoryRun(QT_TRANSLATE_NOOP("yadif","yadif"),sizeof(elems)/sizeof(diaElem *),elems))
219 {
220 configuration.parity=(int)parity-1;
221 updateInfo();
222 return 1;
223 }
224 return 0;
225 }
226 /**
227 \fn getCoupledConf
228 \brief Return our current configuration as couple name=value
229 */
getCoupledConf(CONFcouple ** couples)230 bool yadifFilter::getCoupledConf(CONFcouple **couples)
231 {
232 return ADM_paramSave(couples, yadif_param,&configuration);
233 }
234
setCoupledConf(CONFcouple * couples)235 void yadifFilter::setCoupledConf(CONFcouple *couples)
236 {
237 ADM_paramLoad(couples, yadif_param, &configuration);
238 }
239
240 /**
241 \fn getConfiguration
242 \brief Return current setting as a string
243 */
getConfiguration(void)244 const char *yadifFilter::getConfiguration(void)
245 {
246 static char conf[80];
247 conf[0]=0;
248 snprintf(conf,80,"yadif : mode=%d, order=%d, deint=%d\n",
249 (int)configuration.mode, (int)configuration.parity,(int)configuration.deint);
250 return conf;
251 }
252
253 /**
254 \fn goToTime
255 \brief Seek in filter preview mode
256 */
goToTime(uint64_t usSeek)257 bool yadifFilter::goToTime(uint64_t usSeek)
258 {
259 uint32_t oldFrameIncrement=info.frameIncrement;
260 if(configuration.mode &1) // Bob
261 info.frameIncrement*=2;
262 bool r=ADM_coreVideoFilterCached::goToTime(usSeek);
263 info.frameIncrement=oldFrameIncrement;
264 return r;
265 }
266
267 #include "ADM_vidYadif_body.cpp"
268