1 /***************************************************************************
2 \file stillimage.cpp
3 \author eumagga0x2a @mailbox.org
4 \brief Duplicate frame for a given duration
5 ***************************************************************************/
6
7 /***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
16 #include "ADM_default.h"
17 #include "ADM_vidMisc.h"
18 #include "ADM_coreVideoFilter.h"
19 #include "DIA_coreToolkit.h"
20 #include "DIA_factory.h"
21
22 #include "confStillimage.h"
23 #include "confStillimage_desc.cpp"
24
25 #if 1
26 #define aprintf(...) {}
27 #else
28 #define aprintf printf
29 #endif
30
31 /**
32 \class stillimage
33 */
34 class stillimage : public ADM_coreVideoFilter
35 {
36 protected:
37 configuration params;
38 uint64_t from, begin, end;
39 uint64_t timeIncrement;
40 uint32_t frameNb, nbStillImages;
41 ADMImage *stillPicture;
42
43 bool updateTimingInfo(void);
44 void cleanup(void);
45
46 public:
47 stillimage(ADM_coreVideoFilter *in, CONFcouple *conf);
48 ~stillimage();
49 virtual const char *getConfiguration(void); // Return current configuration as a human-readable string
50 virtual bool getNextFrame(uint32_t *fn, ADMImage *image); // Get the next image
51 virtual bool getCoupledConf(CONFcouple **couples); // Get the current filter configuration
52 virtual void setCoupledConf(CONFcouple *couples);
53 virtual bool goToTime(uint64_t usSeek);
54 virtual bool getTimeRange(uint64_t *startTme, uint64_t *endTme); // Provide an updated time range for the next filter
55 virtual bool configure(void); // Start graphical user interface
56 };
57
58 DECLARE_VIDEO_FILTER( stillimage, // Class
59 1,0,0, // Version
60 ADM_UI_ALL, // UI
61 VF_TRANSFORM, // Category
62 "stillimage", // Internal name (must be unique!)
63 QT_TRANSLATE_NOOP("stillimage", "Still Image"), // Display name
64 QT_TRANSLATE_NOOP("stillimage", "Duplicate frames for a given duration.") // Description
65 );
66
67 /**
68 \fn getConfiguration
69 */
getConfiguration(void)70 const char *stillimage::getConfiguration(void)
71 {
72 static char buf[256];
73 snprintf(buf, 255, "Duplicate frame at %s for %.3f s",
74 ADM_us2plain(1000LL*params.start),
75 (double)params.duration/1000.);
76 return buf;
77 }
78 /**
79 \fn ctor
80 */
stillimage(ADM_coreVideoFilter * in,CONFcouple * setup)81 stillimage::stillimage( ADM_coreVideoFilter *in, CONFcouple *setup ) : ADM_coreVideoFilter(in, setup)
82 {
83 if(!setup || !ADM_paramLoad(setup, configuration_param, ¶ms))
84 {
85 // Default values
86 params.start=0; // the first frame
87 params.duration=10000; // 10 seconds
88 }
89
90 from=in->getAbsoluteStartTime();
91 timeIncrement=in->getInfo()->frameIncrement;
92 updateTimingInfo();
93 stillPicture=NULL;
94 frameNb=0;
95 nbStillImages=0;
96 }
97
98 /**
99 \fn dtor
100 */
~stillimage()101 stillimage::~stillimage()
102 {
103 cleanup();
104 }
105
106 /**
107 \fn cleanup
108 */
cleanup(void)109 void stillimage::cleanup(void)
110 {
111 if(stillPicture)
112 delete stillPicture;
113 stillPicture=NULL;
114 }
115
116 /**
117 \fn getCoupledConf
118 */
getCoupledConf(CONFcouple ** couples)119 bool stillimage::getCoupledConf(CONFcouple **couples)
120 {
121 return ADM_paramSave(couples, configuration_param, ¶ms);
122 }
123
124 /**
125 \fn setCoupledConf
126 */
setCoupledConf(CONFcouple * couples)127 void stillimage::setCoupledConf(CONFcouple *couples)
128 {
129 ADM_paramLoad(couples, configuration_param, ¶ms);
130 }
131
132 /**
133 \fn goToTime
134 */
goToTime(uint64_t usSeek)135 bool stillimage::goToTime(uint64_t usSeek)
136 {
137 cleanup();
138 uint64_t time=usSeek;
139 if(time >= begin && time <= end)
140 time=begin;
141 else if(time > end)
142 time-=end-begin;
143 return previousFilter->goToTime(time);
144 }
145
146 /**
147 \fn getTimeRange
148 */
getTimeRange(uint64_t * startTme,uint64_t * endTme)149 bool stillimage::getTimeRange(uint64_t *startTme, uint64_t *endTme)
150 {
151 *startTme=0;
152 *endTme=info.totalDuration;
153 return true;
154 }
155
156 /**
157 \fn getNextFrame
158 */
getNextFrame(uint32_t * fn,ADMImage * image)159 bool stillimage::getNextFrame(uint32_t *fn, ADMImage *image)
160 {
161 // we have the image and are within range
162 if(stillPicture && stillPicture->Pts < end)
163 {
164 uint64_t pts=stillPicture->Pts;
165 pts+=timeIncrement;
166 stillPicture->Pts=pts;
167 // output our image instead of requesting a new frame from the previous filter
168 image->duplicate(stillPicture);
169 frameNb++;
170 *fn=frameNb;
171 nbStillImages++;
172 aprintf("[stillimage] stillPicture PTS = %s, frame %d\n",ADM_us2plain(pts),*fn);
173 return true;
174 }
175 // not in range, get a frame from the previous filter
176 if(!previousFilter->getNextFrame(fn,image))
177 return false;
178 uint64_t pts=image->Pts;
179 if(pts==ADM_NO_PTS || pts < begin)
180 {
181 *fn+=nbStillImages;
182 return true;
183 }
184 aprintf("[stillimage] original image PTS = %" PRIu64" ms\n",pts/1000);
185 // now in range, create our image
186 if(!stillPicture)
187 {
188 aprintf("[stillimage] creating stillPicture\n");
189 stillPicture=new ADMImageDefault(previousFilter->getInfo()->width, previousFilter->getInfo()->height);
190 stillPicture->duplicate(image);
191 frameNb=*fn;
192 return true;
193 }
194 // past the end, adjust the PTS and the frame count
195 pts+=end-begin;
196 image->Pts=pts;
197 *fn+=nbStillImages;
198 aprintf("[stillimage] final image PTS = %" PRIu64" ms, frame %d\n",pts/1000,*fn);
199
200 return true;
201 }
202
203 /**
204 \fn updateTimingInfo
205 \brief perform a sanity check and update info with the new totalDuration
206 */
updateTimingInfo(void)207 bool stillimage::updateTimingInfo(void)
208 {
209 uint64_t old=previousFilter->getInfo()->totalDuration;
210 if(1000LL*params.start + timeIncrement > old)
211 {
212 if(old > timeIncrement)
213 params.start=(uint32_t)((old-timeIncrement)/1000);
214 else
215 params.start=0;
216 }
217
218 begin=1000LL*params.start;
219 end=begin+1000LL*params.duration;
220 if(from < begin)
221 {
222 begin-=from;
223 end-=from;
224 }else if(from < end)
225 {
226 begin=0;
227 end-=from;
228 }else
229 {
230 begin=end=0;
231 }
232
233 info.totalDuration=old+end-begin;
234 return true;
235 }
236
237 /**
238 \fn configure
239 */
configure(void)240 bool stillimage::configure(void)
241 {
242 uint32_t dur=(uint32_t)(previousFilter->getInfo()->totalDuration/1000LL);
243 uint32_t max9h=9*3600*1000;
244
245 diaElemTimeStamp start(¶ms.start,QT_TRANSLATE_NOOP("stillimage","_Start time:"),0,dur);
246 diaElemTimeStamp duration(¶ms.duration,QT_TRANSLATE_NOOP("stillimage","_Duration:"),0,max9h);
247
248 diaElem *elems[2]={&start,&duration};
249 bool r=diaFactoryRun(QT_TRANSLATE_NOOP("stillimage","Still Image"),2,elems);
250 updateTimingInfo();
251 return r;
252 }
253
254 //EOF
255