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,&param))
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, &param);
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,&param);
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