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