Visual Servoing Platform  version 3.0.0
vpVideoWriter.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2015 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * ("GPL") version 2 as published by the Free Software Foundation.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See http://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * Write image sequences.
32  *
33  * Authors:
34  * Nicolas Melchior
35  * Fabien Spindler
36  *
37  *****************************************************************************/
38 
44 #include <visp3/core/vpDebug.h>
45 #include <visp3/io/vpVideoWriter.h>
46 
47 #if VISP_HAVE_OPENCV_VERSION >= 0x020200
48 # include <opencv2/imgproc/imgproc.hpp>
49 #endif
50 
51 
56 #ifdef VISP_HAVE_FFMPEG
57  ffmpeg(NULL),
58 # if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54,51,110) // libavcodec 54.51.100
59  codec(CODEC_ID_MPEG1VIDEO),
60 # else
61  codec(AV_CODEC_ID_MPEG1VIDEO),
62 # endif
63  bit_rate(500000),
64  framerate(25),
65 #elif VISP_HAVE_OPENCV_VERSION >= 0x020100
66  writer(), fourcc(0), framerate(0.),
67 #endif
68  formatType(FORMAT_UNKNOWN), initFileName(false), isOpen(false), frameCount(0),
69  firstFrame(0), width(0), height(0)
70 {
71  initFileName = false;
72  firstFrame = 0;
73  frameCount = 0;
74  isOpen = false;
75  width = height = 0;
76 #ifdef VISP_HAVE_FFMPEG
77  ffmpeg = NULL;
78 # if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54,51,110) // libavcodec 54.51.100
79  codec = CODEC_ID_MPEG1VIDEO;
80 # else
81  codec = AV_CODEC_ID_MPEG1VIDEO;
82 # endif
83  bit_rate = 500000;
84  framerate = 25;
85 #elif VISP_HAVE_OPENCV_VERSION >= 0x030000
86  framerate = 25.0;
87  fourcc = cv::VideoWriter::fourcc('P','I','M','1');
88 #elif VISP_HAVE_OPENCV_VERSION >= 0x020100
89  framerate = 25.0;
90  fourcc = CV_FOURCC('P','I','M','1'); // default is a MPEG-1 codec
91 #endif
92 }
93 
94 
99 {
100  #ifdef VISP_HAVE_FFMPEG
101  if (ffmpeg != NULL)
102  delete ffmpeg;
103  #endif
104 }
105 
106 
114 void vpVideoWriter::setFileName(const char *filename)
115 {
116  if (!filename || *filename == '\0')
117  {
118  vpERROR_TRACE("filename empty ") ;
119  throw (vpImageException(vpImageException::noFileNameError,"filename empty ")) ;
120  }
121 
122  if (strlen( filename ) >= FILENAME_MAX) {
124  "Not enough memory to intialize the file name"));
125  }
126 
127  strcpy(this->fileName,filename);
128 
129  formatType = getFormat(fileName);
130 
131  if (formatType == FORMAT_UNKNOWN) {
132  throw(vpException(vpException::badValue, "Filename extension not supported"));
133  }
134 
135  initFileName = true;
136 }
137 
145 void vpVideoWriter::setFileName(const std::string &filename)
146 {
147  setFileName(filename.c_str());
148 }
149 
156 {
157  if (!initFileName)
158  {
159  vpERROR_TRACE("The generic filename has to be set");
160  throw (vpImageException(vpImageException::noFileNameError,"filename empty"));
161  }
162 
163  if (formatType == FORMAT_PGM ||
164  formatType == FORMAT_PPM ||
165  formatType == FORMAT_JPEG ||
166  formatType == FORMAT_PNG)
167  {
168  width = I.getWidth();
169  height = I.getHeight();
170  }
171  else if (formatType == FORMAT_AVI ||
172  formatType == FORMAT_MPEG ||
173  formatType == FORMAT_MPEG4 ||
174  formatType == FORMAT_MOV)
175  {
176 #ifdef VISP_HAVE_FFMPEG
177  ffmpeg = new vpFFMPEG;
178  ffmpeg->setFramerate(framerate);
179  ffmpeg->setBitRate(bit_rate);
180  if(!ffmpeg->openEncoder(fileName, I.getWidth(), I.getHeight(), codec)) {
181  throw (vpException(vpException::ioError ,"Could not open encode the video with ffmpeg"));
182  }
183 #elif VISP_HAVE_OPENCV_VERSION >= 0x020100
184  writer = cv::VideoWriter(fileName, fourcc, framerate, cv::Size((int)I.getWidth(), (int)I.getHeight()));
185 
186  if(!writer.isOpened())
187  {
188  //vpERROR_TRACE("Could not open encode the video with opencv");
189  throw (vpException(vpException::fatalError , "Could not open encode the video with opencv"));
190  }
191 #else
192  //vpERROR_TRACE("To encode video files ViSP should be build with ffmpeg or opencv 3rd party libraries.");
193  throw (vpException(vpException::fatalError ,"To encode video files ViSP should be build with ffmpeg or opencv 3rd >= 2.1.0 party libraries."));
194 #endif
195  }
196 
197  frameCount = firstFrame;
198 
199  isOpen = true;
200 }
201 
202 
209 {
210  if (!initFileName)
211  {
212  vpERROR_TRACE("The generic filename has to be set");
213  throw (vpImageException(vpImageException::noFileNameError,"filename empty"));
214  }
215 
216  if (formatType == FORMAT_PGM ||
217  formatType == FORMAT_PPM ||
218  formatType == FORMAT_JPEG ||
219  formatType == FORMAT_PNG)
220  {
221  width = I.getWidth();
222  height = I.getHeight();
223  }
224  else if (formatType == FORMAT_AVI ||
225  formatType == FORMAT_MPEG ||
226  formatType == FORMAT_MPEG4 ||
227  formatType == FORMAT_MOV)
228  {
229 #ifdef VISP_HAVE_FFMPEG
230  ffmpeg = new vpFFMPEG;
231  ffmpeg->setFramerate(framerate);
232  ffmpeg->setBitRate(bit_rate);
233  if(!ffmpeg->openEncoder(fileName, I.getWidth(), I.getHeight(), codec)) {
234  throw (vpException(vpException::ioError ,"Could not encode the video with ffmpeg"));
235  }
236 #elif VISP_HAVE_OPENCV_VERSION >= 0x020100
237  writer = cv::VideoWriter(fileName, fourcc, framerate, cv::Size((int)I.getWidth(), (int)I.getHeight()));
238 
239  if(!writer.isOpened())
240  {
241  vpERROR_TRACE("Could not encode the video with opencv");
242  throw (vpException(vpException::ioError ,"Could not encode the video with opencv"));
243  }
244 #else
245  //vpERROR_TRACE("To encode video files ViSP should be build with ffmpeg or opencv 3rd party libraries.");
246  throw (vpException(vpException::fatalError ,"To encode video files ViSP should be build with ffmpeg or opencv 3rd >= 2.1.0 party libraries."));
247 #endif
248  }
249 
250  frameCount = firstFrame;
251 
252  isOpen = true;
253 }
254 
255 
264 {
265  if (!isOpen)
266  {
267  vpERROR_TRACE("The video has to be open first with the open method");
268  throw (vpException(vpException::notInitialized,"file not yet opened"));
269  }
270 
271 
272  if (formatType == FORMAT_PGM ||
273  formatType == FORMAT_PPM ||
274  formatType == FORMAT_JPEG ||
275  formatType == FORMAT_PNG)
276  {
277  char name[FILENAME_MAX];
278 
279  sprintf(name,fileName,frameCount);
280 
281  vpImageIo::write(I, name);
282  }
283  else
284  {
285 #ifdef VISP_HAVE_FFMPEG
286  ffmpeg->saveFrame(I);
287 #elif VISP_HAVE_OPENCV_VERSION >= 0x020100
288  cv::Mat matFrame;
289  vpImageConvert::convert(I, matFrame);
290  writer << matFrame;
291 #endif
292  }
293 
294  frameCount++;
295 }
296 
297 
306 {
307  if (!isOpen)
308  {
309  vpERROR_TRACE("The video has to be open first with the open method");
310  throw (vpException(vpException::notInitialized,"file not yet opened"));
311  }
312 
313  if (formatType == FORMAT_PGM ||
314  formatType == FORMAT_PPM ||
315  formatType == FORMAT_JPEG ||
316  formatType == FORMAT_PNG)
317  {
318  char name[FILENAME_MAX];
319 
320  sprintf(name,fileName,frameCount);
321 
322  vpImageIo::write(I, name);
323  }
324  else
325  {
326 #ifdef VISP_HAVE_FFMPEG
327  ffmpeg->saveFrame(I);
328 #elif VISP_HAVE_OPENCV_VERSION >= 0x030000
329  cv::Mat matFrame, rgbMatFrame;
330  vpImageConvert::convert(I, matFrame);
331  cv::cvtColor(matFrame, rgbMatFrame, cv::COLOR_GRAY2BGR);
332  writer << rgbMatFrame;
333 #elif VISP_HAVE_OPENCV_VERSION >= 0x020100
334  cv::Mat matFrame, rgbMatFrame;
335  vpImageConvert::convert(I, matFrame);
336  cv::cvtColor(matFrame, rgbMatFrame, CV_GRAY2BGR);
337  writer << rgbMatFrame;
338 #endif
339  }
340 
341  frameCount++;
342 }
343 
344 
349 {
350  if (!isOpen)
351  {
352  vpERROR_TRACE("The video has to be open first with the open method");
353  throw (vpException(vpException::notInitialized,"file not yet opened"));
354  }
355  #ifdef VISP_HAVE_FFMPEG
356  if (ffmpeg != NULL)
357  {
358  ffmpeg->endWrite();
359  }
360  #endif
361 }
362 
363 
369 vpVideoWriter::vpVideoFormatType
370 vpVideoWriter::getFormat(const char *filename)
371 {
372  std::string sfilename(filename);
373 
374  std::string ext = vpVideoWriter::getExtension(sfilename);
375 
376  if (ext.compare(".PGM") == 0)
377  return FORMAT_PGM;
378  else if (ext.compare(".pgm") == 0)
379  return FORMAT_PGM;
380  else if (ext.compare(".PPM") == 0)
381  return FORMAT_PPM;
382  else if (ext.compare(".ppm") == 0)
383  return FORMAT_PPM;
384  else if (ext.compare(".JPG") == 0)
385  return FORMAT_JPEG;
386  else if (ext.compare(".jpg") == 0)
387  return FORMAT_JPEG;
388  else if (ext.compare(".JPEG") == 0)
389  return FORMAT_JPEG;
390  else if (ext.compare(".jpeg") == 0)
391  return FORMAT_JPEG;
392  else if (ext.compare(".PNG") == 0)
393  return FORMAT_PNG;
394  else if (ext.compare(".png") == 0)
395  return FORMAT_PNG;
396  else if (ext.compare(".AVI") == 0)
397  return FORMAT_AVI;
398  else if (ext.compare(".avi") == 0)
399  return FORMAT_AVI;
400  else if (ext.compare(".MPEG") == 0)
401  return FORMAT_MPEG;
402  else if (ext.compare(".mpeg") == 0)
403  return FORMAT_MPEG;
404  else if (ext.compare(".MPG") == 0)
405  return FORMAT_MPEG;
406  else if (ext.compare(".mpg") == 0)
407  return FORMAT_MPEG;
408  else if (ext.compare(".MPEG4") == 0)
409  return FORMAT_MPEG4;
410  else if (ext.compare(".mpeg4") == 0)
411  return FORMAT_MPEG4;
412  else if (ext.compare(".MP4") == 0)
413  return FORMAT_MPEG4;
414  else if (ext.compare(".mp4") == 0)
415  return FORMAT_MPEG4;
416  else if (ext.compare(".MOV") == 0)
417  return FORMAT_MOV;
418  else if (ext.compare(".mov") == 0)
419  return FORMAT_MOV;
420  else
421  return FORMAT_UNKNOWN;
422 }
423 
424 // return the extension of the file including the dot
425 std::string vpVideoWriter::getExtension(const std::string &filename)
426 {
427  // extract the extension
428  size_t dot = filename.find_last_of(".");
429  std::string ext = filename.substr(dot, filename.size()-1);
430  return ext;
431 }
static void write(const vpImage< unsigned char > &I, const char *filename)
Definition: vpImageIo.cpp:472
void setBitRate(const unsigned int rate)
Definition: vpFFMPEG.h:253
unsigned int getWidth() const
Definition: vpImage.h:161
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
#define vpERROR_TRACE
Definition: vpDebug.h:391
bool saveFrame(vpImage< vpRGBa > &I)
Definition: vpFFMPEG.cpp:752
error that can be emited by ViSP classes.
Definition: vpException.h:73
Error that can be emited by the vpImage class and its derivates.
This class interfaces the FFmpeg library to enable video stream reading or writing.
Definition: vpFFMPEG.h:145
void saveFrame(vpImage< vpRGBa > &I)
void open(vpImage< vpRGBa > &I)
void setFileName(const char *filename)
unsigned int getHeight() const
Definition: vpImage.h:152
bool endWrite()
Definition: vpFFMPEG.cpp:834
bool openEncoder(const char *filename, unsigned int width, unsigned int height, AVCodecID codec=AV_CODEC_ID_MPEG1VIDEO)
Definition: vpFFMPEG.cpp:668
void setFramerate(const int framerate)
Definition: vpFFMPEG.h:259