1 /***************************************************************************
2     \file ADM_vs.cpp
3     \author (C) 2015 by mean    email                : fixounet@free.fr
4     \brief VapourSynth demuxer
5 
6  ***************************************************************************/
7 
8 /***************************************************************************
9  *                                                                         *
10  *   This program is free software; you can redistribute it and/or modify  *
11  *   it under the terms of the GNU General Public License as published by  *
12  *   the Free Software Foundation; either version 2 of the License, or     *
13  *   (at your option) any later version.                                   *
14  *                                                                         *
15  ***************************************************************************/
16 
17 #include "ADM_default.h"
18 #include "fourcc.h"
19 #include "ADM_vs.h"
20 #include "ADM_vsInternal.h"
21 static const VSAPI *vsapi = NULL;
22 #if 0
23     #define aprintf printf
24 #else
25     #define aprintf(...) {}
26 #endif
27 uint32_t ADM_UsecFromFps1000(uint32_t fps1000);
28 extern vsDynaLoader dynaLoader;
29 /**
30       \fn open
31       \brief open the flv file, gather infos and build index(es).
32 */
33 
open(const char * name)34 uint8_t vsHeader::open(const char *name)
35 {
36     ADM_info("Opening %s as VapourSynth file\n",name);
37     inited+=!!dynaLoader.init();
38     if(!inited)
39     {
40         ADM_warning("Cannot initialize vsapi script_init. Check PYTHONPATH\n");
41         return false;
42     }
43     if(!vsapi)
44     {
45         vsapi = dynaLoader.getVSApi();
46         if(!vsapi)
47         {
48             ADM_warning("Cannot get vsAPI entry point\n");
49             close();
50             return 0;
51         }
52     }
53     ADM_info("VapourSynth init ok, opening file..\n");
54     if (dynaLoader.evaluateFile(&_script, name, 0))
55     {
56         ADM_warning("Evaluate script failed <%s>\n", dynaLoader.getError(_script));
57         close();
58         return 0;
59     }
60     _node = dynaLoader.getOutput(_script, 0);
61     if (!_node)
62     {
63         ADM_warning("vsscript_getOutputNode failed\n");
64         close();
65         return 0;
66     }
67 
68     const VSVideoInfo *vi = vsapi->getVideoInfo(_node);
69     if(!vi)
70     {
71         ADM_warning("Cannot get information on node\n");
72         close();
73         return 0;
74     }
75     ADM_info("Format    : %s\n",vi->format->name);
76     ADM_info("FrameRate : %d / %d\n",vi->fpsNum,vi->fpsDen);
77     ADM_info("Width     : %d\n",vi->width);
78     ADM_info("Height    : %d\n",vi->height);
79     ADM_info("Frames    : %d\n",vi->numFrames);
80     ADM_info("Flags     : 0x%x\n",vi->flags);
81 
82     double fps1000;
83     if(vi->fpsDen)
84     {
85         fps1000=1000.*((double)vi->fpsNum /(double)vi-> fpsDen);
86     }else
87     {
88 
89         fps1000=25000;
90     }
91     //--
92     _videostream.dwRate=vi->fpsNum;
93     _videostream.dwScale=vi-> fpsDen;
94 
95     ADM_info("Fps1000=%d\n",(int)fps1000);
96 
97     _mainaviheader.dwMicroSecPerFrame=ADM_UsecFromFps1000(fps1000);
98     _video_bih.biBitCount=24;
99     _videostream.dwInitialFrames= 0;
100     _videostream.dwStart= 0;
101     _video_bih.biHeight=_mainaviheader.dwHeight=vi->height  ;
102     _video_bih.biWidth=_mainaviheader.dwWidth=vi->width;
103     _isvideopresent=true;
104     _isaudiopresent=false;
105     _nbFrames=vi->numFrames;
106     _videostream.dwLength=_mainaviheader.dwTotalFrames=_nbFrames;
107     _videostream.fccType=_videostream.fccHandler=_video_bih.biCompression=fourCC::get((uint8_t *)"YV12");
108     return true;
109 }
110 /**
111         \fn getVideoDuration
112         \brief Returns duration of video in us
113 */
getVideoDuration(void)114 uint64_t vsHeader::getVideoDuration(void)
115 {
116     uint64_t d=_mainaviheader.dwMicroSecPerFrame;
117     if(_nbFrames)
118         d+=getTimeForFrame(_nbFrames-1);
119     return d;
120 }
121 /**
122  *
123  * @param frame
124  * @param flags
125  * @return
126  */
setFlag(uint32_t frame,uint32_t flags)127 uint8_t  vsHeader::setFlag(uint32_t frame,uint32_t flags)
128 {
129     return 0;
130 }
getFlags(uint32_t frame,uint32_t * flags)131 uint32_t vsHeader::getFlags(uint32_t frame,uint32_t *flags)
132 {
133     *flags=AVI_KEY_FRAME;
134     if(frame>=_mainaviheader.dwTotalFrames)
135     {
136         ADM_warning("Frame out of bounds: %u / %u\n",frame,_mainaviheader.dwTotalFrames);
137         return 0;
138     }
139     return 1;
140 }
141 
142 /**
143     \fn getAudioInfo
144     \brief returns wav header for stream i (=0)
145 */
getAudioInfo(uint32_t i)146 WAVHeader *vsHeader::getAudioInfo(uint32_t i )
147 {
148       return NULL;
149 }
150 /**
151  *
152  * @param frame
153  * @return
154  */
getTime(uint32_t frame)155 uint64_t vsHeader::getTime(uint32_t frame)
156 {
157     return getTimeForFrame(frame);
158 }
159 /**
160    \fn getAudioStream
161 */
162 
getAudioStream(uint32_t i,ADM_audioStream ** audio)163 uint8_t   vsHeader::getAudioStream(uint32_t i,ADM_audioStream  **audio)
164 {
165   *audio=NULL;
166   return 0;
167 }
168 /**
169     \fn getNbAudioStreams
170 
171 */
getNbAudioStreams(void)172 uint8_t   vsHeader::getNbAudioStreams(void)
173 {
174    return 0;
175 }
176 /**
177     \fn close
178     \brief cleanup
179 */
180 
close(void)181 uint8_t vsHeader::close(void)
182 {
183     if(vsapi && _node)
184     {
185         vsapi->freeNode(_node);
186         _node=NULL;
187     }
188     if(_script)
189     {
190         dynaLoader.freeScript(_script);
191         _script=NULL;
192     }
193     while(inited)
194     {
195         inited--;
196         dynaLoader.finalize();
197     }
198     vsapi=NULL;
199     return 1;
200 }
201 /**
202     \fn vsHeader
203     \brief constructor
204 */
205 
vsHeader(void)206  vsHeader::vsHeader( void ) : vidHeader()
207 {
208     inited=0;
209     _script=NULL;
210     _node = NULL;
211 }
212 /**
213     \fn vsHeader
214     \brief destructor
215 */
216 
~vsHeader()217  vsHeader::~vsHeader(  )
218 {
219   close();
220 }
221 
222 
223 /**
224         \fn getFrame
225 */
226 
getFrame(uint32_t frame,ADMCompressedImage * img)227 uint8_t  vsHeader::getFrame(uint32_t frame,ADMCompressedImage *img)
228 {
229     if(frame>=_nbFrames) return false;
230 
231     char errMsg[1024];
232     const int mapp[3]={0,2,1};
233 
234     const VSFrameRef *vsframe = vsapi->getFrame(frame, _node, errMsg, sizeof(errMsg));
235     if (!vsframe)
236     {
237         ADM_error("Error getting frame %d\n",frame);
238         return false;
239     }
240     img->flags=AVI_KEY_FRAME;
241     img->dataLength=(_mainaviheader.dwHeight*_mainaviheader.dwWidth*3)>>1;
242     img->demuxerPts=getTimeForFrame(frame);
243     img->demuxerDts=img->demuxerPts;
244     img->demuxerFrameNo=frame; // not sure
245     uint8_t *target=img->data;
246 #if 0
247     const VSVideoInfo *vi = vsapi->getVideoInfo(_node);
248     if(!vi)
249     {
250         ADM_error("Error getting getVideoInfo for frame %d\n",frame);
251         return false;
252     }
253 #endif
254     for (int plane = 0; plane < 3; plane++)
255     {
256         int p=mapp[plane];
257         int stride = vsapi->getStride(vsframe, p);
258         const uint8_t *readPtr = vsapi->getReadPtr(vsframe, p);
259 
260         if(!readPtr)
261         {
262             ADM_error("Cannot get pointer for frame %p\n",p);
263             return false;
264         }
265 
266         int rowSize = _mainaviheader.dwWidth;
267         int height  = _mainaviheader.dwHeight;
268         if(p)
269          {
270              rowSize>>=1;height>>=1;
271          }
272          for (int y = 0; y < height; y++)
273          {
274 
275              memcpy(target,readPtr,rowSize);
276              target  += rowSize; // useless memcpy...
277              readPtr += stride;
278          }
279     }
280     vsapi->freeFrame(vsframe);
281     return true;
282 }
283 /**
284         \fn getExtraHeaderData
285 */
getExtraHeaderData(uint32_t * len,uint8_t ** data)286 uint8_t  vsHeader::getExtraHeaderData(uint32_t *len, uint8_t **data)
287 {
288         *len=0;
289         *data=NULL;
290         return 1;
291 }
292 /**
293  *
294  */
Dump(void)295  void     vsHeader::Dump(void)
296  {
297      return;
298  }
299 /**
300       \fn getFrameSize
301       \brief return the size of frame frame
302 */
getFrameSize(uint32_t frame,uint32_t * size)303 uint8_t vsHeader::getFrameSize (uint32_t frame, uint32_t * size)
304 {
305   *size = (_video_bih.biHeight*_video_bih.biWidth*3)>>1;
306   return 1;
307 }
308 
309 /**
310  * \fn getTimeForFrame
311  * @param frame
312  * @return
313  */
getTimeForFrame(int frame)314 uint64_t vsHeader::getTimeForFrame(int frame)
315 {
316     double d=1000000.;
317     d*=(double)_videostream.dwScale;
318     d/=(double)_videostream.dwRate;
319     d*=frame;
320     return (uint64_t)d;
321 }
322 /**
323     \fn getPtsDts
324 */
getPtsDts(uint32_t frame,uint64_t * pts,uint64_t * dts)325 bool    vsHeader::getPtsDts(uint32_t frame,uint64_t *pts,uint64_t *dts)
326 {
327     *dts=getTimeForFrame(frame);
328     *pts=*dts;
329     return true;
330 }
331 /**
332         \fn setPtsDts
333 */
setPtsDts(uint32_t frame,uint64_t pts,uint64_t dts)334 bool    vsHeader::setPtsDts(uint32_t frame,uint64_t pts,uint64_t dts)
335 {
336        return false;
337 }
338 
339 //EOF
340