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