1 /***************************************************************************
2 * *
3 * This program is free software; you can redistribute it and/or modify *
4 * it under the terms of the GNU General Public License as published by *
5 * the Free Software Foundation; either version 2 of the License, or *
6 * (at your option) any later version. *
7 * *
8 ***************************************************************************/
9
10 #include <math.h>
11 #include <string>
12 #include "ADM_default.h"
13 #include "ADM_coreVideoFilter.h"
14 #include "DIA_coreToolkit.h"
15 #include "DIA_factory.h"
16 #include "ADM_vidMisc.h"
17 #include "fade.h"
18 #include "fade_desc.cpp"
19 /**
20 \class AVDM_FadeTo
21 * \brief fade video plugin
22 */
23 class AVDM_FadeTo : public ADM_coreVideoFilterCached
24 {
25 protected:
26 fade param;
27 uint32_t mx;
28 void boundsCheck(void);
29 bool buildLut(void);
30 ADMImage *first;
31 bool process(ADMImage *source,ADMImage *source2, ADMImage *dest,int offset);
32 public:
33 AVDM_FadeTo(ADM_coreVideoFilter *previous,CONFcouple *conf);
34 ~AVDM_FadeTo();
35
36 virtual const char *getConfiguration(void); /// Return current configuration as a human readable string
37 virtual bool getNextFrame(uint32_t *fn,ADMImage *image); /// Return the next image
38 virtual bool getCoupledConf(CONFcouple **couples); /// Return the current filter configuration
39 virtual void setCoupledConf(CONFcouple *couples);
40 virtual bool configure(void); /// Start graphical user interface
41 uint16_t lookupLuma[256][256];
42 uint16_t lookupChroma[256][256];
43
44 };
45
46 // Add the hook to make it valid plugin
47
48
49
50 DECLARE_VIDEO_FILTER(AVDM_FadeTo,
51 1,0,0, // Version
52 ADM_UI_ALL, // UI
53 VF_TRANSFORM, // Category
54 "fadeTo", // internal name (must be uniq!)
55 QT_TRANSLATE_NOOP("fadeTo","Fade"), // Display name
56 QT_TRANSLATE_NOOP("fadeTo","Fade.") // Description
57 );
58 /**
59 * \fn configure
60 * \brief UI configuration
61 * @param
62 * @return
63 */
configure()64 bool AVDM_FadeTo::configure()
65 {
66 uint32_t eInOut=(uint32_t)param.inOut;
67
68 diaMenuEntry fadeDirection[2]={
69 {0,QT_TRANSLATE_NOOP("fadeTo","From"),QT_TRANSLATE_NOOP("fadeTo","Fade from the first picture into movie")},
70 {1,QT_TRANSLATE_NOOP("fadeTo","To"),QT_TRANSLATE_NOOP("fadeTo","Fade from movie to the first picture")}
71 };
72
73 diaElemMenu menu(&(eInOut),QT_TRANSLATE_NOOP("fadeTo","_Fade direction:"),2,fadeDirection);
74 diaElemTimeStamp start(&(param.startFade),QT_TRANSLATE_NOOP("fadeTo","_Start time:"),0,mx);
75 diaElemTimeStamp end(&(param.endFade),QT_TRANSLATE_NOOP("fadeTo","_End time:"),0,mx);
76 diaElem *elems[3]={&menu,&start,&end};
77
78 if( diaFactoryRun(QT_TRANSLATE_NOOP("fadeTo","Fade"),3,elems))
79 {
80 param.inOut=(bool)eInOut;
81 buildLut();
82 boundsCheck();
83 return 1;
84 }
85 return 0;
86 }
87 /**
88 * \fn getConfiguration
89 *
90 */
getConfiguration(void)91 const char *AVDM_FadeTo::getConfiguration(void)
92 {
93 static char conf[256];
94 std::string start=std::string(ADM_us2plain(param.startFade*1000LL));
95 std::string end=std::string(ADM_us2plain(param.endFade*1000LL));
96 const char *type=(param.inOut)? "to" : "from";
97 snprintf(conf,255," Fade %s: Start %s End %s",type,start.c_str(),end.c_str());
98 return conf;
99 }
100
101 /**
102 * \fn ctor
103 * @param in
104 * @param couples
105 */
AVDM_FadeTo(ADM_coreVideoFilter * in,CONFcouple * setup)106 AVDM_FadeTo::AVDM_FadeTo(ADM_coreVideoFilter *in,CONFcouple *setup) : ADM_coreVideoFilterCached(3,in,setup)
107 {
108 mx=(uint32_t)(in->getInfo()->totalDuration/1000);
109 if(!setup || !ADM_paramLoad(setup,fade_param,¶m))
110 {
111 // Default value
112 param.startFade=0;
113 param.endFade=0;
114 param.inOut=false;
115 }
116 buildLut();
117 nextFrame=0;
118 first=NULL;
119 }
120 /**
121 * \fn setCoupledConf
122 * \brief save current setup from couples
123 * @param couples
124 */
setCoupledConf(CONFcouple * couples)125 void AVDM_FadeTo::setCoupledConf(CONFcouple *couples)
126 {
127 ADM_paramLoad(couples, fade_param, ¶m);
128 }
129
130 /**
131 * \fn getCoupledConf
132 * @param couples
133 * @return setup as couples
134 */
getCoupledConf(CONFcouple ** couples)135 bool AVDM_FadeTo::getCoupledConf(CONFcouple **couples)
136 {
137 return ADM_paramSave(couples, fade_param,¶m);
138 }
139
140 /**
141 * \fn dtor
142 */
~AVDM_FadeTo(void)143 AVDM_FadeTo::~AVDM_FadeTo(void)
144 {
145 if(first)
146 {
147 delete first;
148 first=NULL;
149 }
150 }
151 /**
152 *
153 * @param source
154 * @param source2
155 * @param dest
156 * @param offset
157 * @return
158 */
process(ADMImage * source,ADMImage * source2,ADMImage * dest,int offset)159 bool AVDM_FadeTo::process(ADMImage *source,ADMImage *source2, ADMImage *dest,int offset)
160 {
161 uint8_t *splanes[3],*splanes2[3],*dplanes[3];
162 int spitches[3],spitches2[3],dpitches[3];
163
164 source->GetReadPlanes(splanes);
165 source->GetPitches(spitches);
166 source2->GetReadPlanes(splanes2);
167 source2->GetPitches(spitches2);
168 dest->GetWritePlanes(dplanes);
169 dest->GetPitches(dpitches);
170
171 for(int i=0;i<3;i++)
172 {
173 uint16_t *indx=lookupChroma[offset];
174 uint16_t *revindex=lookupChroma[255-offset];
175 int colorOffset=128<<8;
176 if(!i)
177 {
178 indx=lookupLuma[offset];
179 revindex=lookupLuma[255-offset];
180 colorOffset=0;
181 }
182 int w=(int)dest->GetWidth((ADM_PLANE)i);
183 int h=(int)dest->GetHeight((ADM_PLANE)i);
184 uint8_t *s=splanes[i];
185 uint8_t *s2=splanes2[i];
186 uint8_t *d=dplanes[i];
187 for(int y=0;y<h;y++)
188 {
189 for(int x=0;x<w;x++)
190 {
191 int value=s[x];
192 int value2=s2[x];
193 d[x]=(indx[value]+revindex[value2]-colorOffset)>>8;
194 }
195 d+=dpitches[i];
196 s+=spitches[i];
197 s2+=spitches2[i];
198 }
199 }
200 return true;
201 }
202
203 /**
204 * \fn getNextFrame
205 * @param fn
206 * @param image
207 * @return
208 */
getNextFrame(uint32_t * fn,ADMImage * image)209 bool AVDM_FadeTo::getNextFrame(uint32_t *fn,ADMImage *image)
210 {
211 *fn=nextFrame;
212 ADMImage *next= vidCache->getImage(nextFrame);
213 if(!next)
214 {
215 ADM_info("[Fade] Cant get image \n");
216 return false;
217 }
218 image->Pts=next->Pts;
219 uint64_t absPts=next->Pts+getAbsoluteStartTime();
220 bool out_of_scope=false;
221
222 if(absPts<param.startFade*1000LL) out_of_scope=true;
223 if(absPts>param.endFade*1000LL) out_of_scope=true;
224
225 if(!out_of_scope && !first)
226 {
227 first=new ADMImageDefault(next->GetWidth (PLANAR_Y),next->GetHeight(PLANAR_Y));
228 first->duplicateFull (next);
229 }
230 if( out_of_scope || !first)
231 {
232 image->duplicate(next);
233 nextFrame++;
234 vidCache->unlockAll();
235 return true;
236 }
237 double scope=1000LL*(param.endFade-param.startFade);
238 double in;
239 if(!scope)
240 {
241 scope=1;
242 in=1;
243 }else
244 {
245 in=absPts-param.startFade*1000LL;
246 }
247 in=in/scope;
248 in*=255;
249
250 uint32_t offset=(uint32_t)floor(in+0.4); // normalized to 0--255, begin -- end
251
252 process(first,next,image,offset);
253
254 vidCache->unlockAll();
255 nextFrame++;
256 return 1;
257 }
258 /**
259 * \fn buildLut
260 * \brief compute the Lut we will be using
261 * @return
262 */
buildLut(void)263 bool AVDM_FadeTo::buildLut(void)
264 {
265 float f,ration;
266 for(int i=0;i<256;i++)
267 {
268 if(!param.inOut)
269 ration=255.-i;
270 else
271 ration=(float)i;
272 for(int r=0;r<256;r++)
273 {
274 f=(float)r;
275 f=f*ration;
276 lookupLuma[i][r]=(uint16_t)(f+0.4);
277
278 f=r-128.;
279 f=f*ration;
280 lookupChroma[i][r]=(128<<8)+(uint16_t)(f+0.4);
281 }
282 }
283 return true;
284 }
285 /**
286 * \fn boundsCheck
287 * \brief Reset invalid start and end values
288 */
boundsCheck(void)289 void AVDM_FadeTo::boundsCheck(void)
290 {
291 if(param.endFade < param.startFade)
292 {
293 uint32_t tmp=param.startFade;
294 param.startFade=param.endFade;
295 param.endFade=tmp;
296 }
297 if(param.endFade > mx)
298 param.endFade=mx;
299 if(param.startFade > mx)
300 param.startFade=0;
301 }
302 //EOF
303