Visual Servoing Platform  version 3.5.1 under development (2022-07-06)
vpVideoWriter.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2019 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See http://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description:
32  * Write image sequences.
33  *
34  * Authors:
35  * Nicolas Melchior
36  * Fabien Spindler
37  *
38  *****************************************************************************/
39 
45 #include <visp3/core/vpDebug.h>
46 #include <visp3/core/vpIoTools.h>
47 #include <visp3/io/vpVideoWriter.h>
48 
49 #if VISP_HAVE_OPENCV_VERSION >= 0x020200
50 #include <opencv2/imgproc/imgproc.hpp>
51 #endif
52 
57  :
58 #if VISP_HAVE_OPENCV_VERSION >= 0x020100
59  m_writer(), m_framerate(25.0),
60 #endif
61  m_formatType(FORMAT_UNKNOWN), m_videoName(), m_frameName(), m_initFileName(false), m_isOpen(false), m_frameCount(0),
62  m_firstFrame(0), m_width(0), m_height(0), m_frameStep(1)
63 {
64 #if VISP_HAVE_OPENCV_VERSION >= 0x030000
65  m_fourcc = cv::VideoWriter::fourcc('P', 'I', 'M', '1');
66 #elif VISP_HAVE_OPENCV_VERSION >= 0x020100
67  m_fourcc = CV_FOURCC('P', 'I', 'M', '1'); // default is a MPEG-1 codec
68 #endif
69 }
70 
75 
90 void vpVideoWriter::setFileName(const std::string &filename)
91 {
92  if (filename.empty()) {
93  throw(vpImageException(vpImageException::noFileNameError, "Filename empty in video writer"));
94  }
95 
96  m_videoName = filename;
97  m_frameName = filename;
98 
99  m_formatType = getFormat(filename);
100 
101  if (m_formatType == FORMAT_UNKNOWN) {
102  throw(vpException(vpException::badValue, "Filename extension not supported in video writer"));
103  }
104 
105  m_initFileName = true;
106 }
107 
117 {
118  if (!m_initFileName) {
119  throw(vpImageException(vpImageException::noFileNameError, "The generic filename has to be set in video writer"));
120  }
121 
123 
124  if (m_formatType == FORMAT_PGM || m_formatType == FORMAT_PPM || m_formatType == FORMAT_JPEG ||
125  m_formatType == FORMAT_PNG) {
126  m_width = I.getWidth();
127  m_height = I.getHeight();
128  } else if (m_formatType == FORMAT_AVI || m_formatType == FORMAT_MPEG || m_formatType == FORMAT_MPEG4 ||
129  m_formatType == FORMAT_MOV) {
130 #if VISP_HAVE_OPENCV_VERSION >= 0x020100
131  m_writer = cv::VideoWriter(m_videoName, m_fourcc, m_framerate,
132  cv::Size(static_cast<int>(I.getWidth()), static_cast<int>(I.getHeight())));
133 
134  if (!m_writer.isOpened()) {
135  throw(vpException(vpException::fatalError, "Could not encode the video with OpenCV"));
136  }
137 #else
138  throw(vpException(vpException::fatalError, "To encode video files ViSP should be build with OpenCV >= 2.1.0"));
139 #endif
140  }
141 
142  m_frameCount = m_firstFrame;
143 
144  m_isOpen = true;
145 }
146 
156 {
157  if (!m_initFileName) {
158  throw(vpImageException(vpImageException::noFileNameError, "The generic filename has to be set in video writer"));
159  }
160 
162 
163  if (m_formatType == FORMAT_PGM || m_formatType == FORMAT_PPM || m_formatType == FORMAT_JPEG ||
164  m_formatType == FORMAT_PNG) {
165  m_width = I.getWidth();
166  m_height = I.getHeight();
167  } else if (m_formatType == FORMAT_AVI || m_formatType == FORMAT_MPEG || m_formatType == FORMAT_MPEG4 ||
168  m_formatType == FORMAT_MOV) {
169 #if VISP_HAVE_OPENCV_VERSION >= 0x020100
170  m_writer = cv::VideoWriter(m_videoName, m_fourcc, m_framerate,
171  cv::Size(static_cast<int>(I.getWidth()), static_cast<int>(I.getHeight())));
172 
173  if (!m_writer.isOpened()) {
174  throw(vpException(vpException::fatalError, "Could not encode the video with OpenCV"));
175  }
176 #else
177  throw(vpException(vpException::fatalError, "To encode video files ViSP should be build with OpenCV >= 2.1.0"));
178 #endif
179  }
180 
181  m_frameCount = m_firstFrame;
182 
183  m_isOpen = true;
184 }
185 
196 {
197  if (!m_isOpen) {
198  throw(vpException(vpException::notInitialized, "The video has to be open first with video writer open() method"));
199  }
200 
201  if (m_formatType == FORMAT_PGM || m_formatType == FORMAT_PPM || m_formatType == FORMAT_JPEG ||
202  m_formatType == FORMAT_PNG) {
203  char name[FILENAME_MAX];
204  sprintf(name, m_videoName.c_str(), m_frameCount);
205  vpImageIo::write(I, name);
206  m_frameName = std::string(name);
207  } else {
208 #if VISP_HAVE_OPENCV_VERSION >= 0x020100
209  cv::Mat matFrame;
210  vpImageConvert::convert(I, matFrame);
211  m_writer << matFrame;
212 #endif
213  }
214 
215  m_frameCount += m_frameStep;
216 }
217 
228 {
229  if (!m_isOpen) {
230  throw(vpException(vpException::notInitialized, "The video has to be open first with video writer open() method"));
231  }
232 
233  if (m_formatType == FORMAT_PGM || m_formatType == FORMAT_PPM || m_formatType == FORMAT_JPEG ||
234  m_formatType == FORMAT_PNG) {
235  char name[FILENAME_MAX];
236  sprintf(name, m_videoName.c_str(), m_frameCount);
237  vpImageIo::write(I, name);
238  m_frameName = std::string(name);
239  } else {
240 #if VISP_HAVE_OPENCV_VERSION >= 0x030000
241  cv::Mat matFrame, rgbMatFrame;
242  vpImageConvert::convert(I, matFrame);
243  cv::cvtColor(matFrame, rgbMatFrame, cv::COLOR_GRAY2BGR);
244  m_writer << rgbMatFrame;
245 #elif VISP_HAVE_OPENCV_VERSION >= 0x020100
246  cv::Mat matFrame, rgbMatFrame;
247  vpImageConvert::convert(I, matFrame);
248  cv::cvtColor(matFrame, rgbMatFrame, CV_GRAY2BGR);
249  m_writer << rgbMatFrame;
250 #endif
251  }
252 
253  m_frameCount += m_frameStep;
254 }
255 
260 {
261  if (!m_isOpen) {
262  throw(vpException(vpException::notInitialized, "Cannot close video writer: not yet opened"));
263  }
264 }
265 
271 vpVideoWriter::vpVideoFormatType vpVideoWriter::getFormat(const std::string &filename)
272 {
273  std::string ext = vpVideoWriter::getExtension(filename);
274 
275  if (ext.compare(".PGM") == 0)
276  return FORMAT_PGM;
277  else if (ext.compare(".pgm") == 0)
278  return FORMAT_PGM;
279  else if (ext.compare(".PPM") == 0)
280  return FORMAT_PPM;
281  else if (ext.compare(".ppm") == 0)
282  return FORMAT_PPM;
283  else if (ext.compare(".JPG") == 0)
284  return FORMAT_JPEG;
285  else if (ext.compare(".jpg") == 0)
286  return FORMAT_JPEG;
287  else if (ext.compare(".JPEG") == 0)
288  return FORMAT_JPEG;
289  else if (ext.compare(".jpeg") == 0)
290  return FORMAT_JPEG;
291  else if (ext.compare(".PNG") == 0)
292  return FORMAT_PNG;
293  else if (ext.compare(".png") == 0)
294  return FORMAT_PNG;
295  else if (ext.compare(".AVI") == 0)
296  return FORMAT_AVI;
297  else if (ext.compare(".avi") == 0)
298  return FORMAT_AVI;
299  else if (ext.compare(".MPEG") == 0)
300  return FORMAT_MPEG;
301  else if (ext.compare(".mpeg") == 0)
302  return FORMAT_MPEG;
303  else if (ext.compare(".MPG") == 0)
304  return FORMAT_MPEG;
305  else if (ext.compare(".mpg") == 0)
306  return FORMAT_MPEG;
307  else if (ext.compare(".MPEG4") == 0)
308  return FORMAT_MPEG4;
309  else if (ext.compare(".mpeg4") == 0)
310  return FORMAT_MPEG4;
311  else if (ext.compare(".MP4") == 0)
312  return FORMAT_MPEG4;
313  else if (ext.compare(".mp4") == 0)
314  return FORMAT_MPEG4;
315  else if (ext.compare(".MOV") == 0)
316  return FORMAT_MOV;
317  else if (ext.compare(".mov") == 0)
318  return FORMAT_MOV;
319  else
320  return FORMAT_UNKNOWN;
321 }
322 
323 // return the extension of the file including the dot
324 std::string vpVideoWriter::getExtension(const std::string &filename)
325 {
326  // extract the extension
327  size_t dot = filename.find_last_of(".");
328  std::string ext = filename.substr(dot, filename.size() - 1);
329  return ext;
330 }
331 
338 {
339  if (first_frame < 0) {
340  throw(vpException(vpException::fatalError, "Video writer first frame index cannot be negative"));
341  }
342  m_firstFrame = first_frame;
343 }
error that can be emited by ViSP classes.
Definition: vpException.h:72
@ badValue
Used to indicate that a value is not in the allowed range.
Definition: vpException.h:97
@ notInitialized
Used to indicate that a parameter is not initialized.
Definition: vpException.h:98
@ fatalError
Fatal error.
Definition: vpException.h:96
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
Error that can be emited by the vpImage class and its derivates.
static void write(const vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Definition: vpImageIo.cpp:292
unsigned int getWidth() const
Definition: vpImage.h:246
unsigned int getHeight() const
Definition: vpImage.h:188
static void makeDirectory(const std::string &dirname)
Definition: vpIoTools.cpp:568
static std::string getParent(const std::string &pathname)
Definition: vpIoTools.cpp:1620
void saveFrame(vpImage< vpRGBa > &I)
virtual ~vpVideoWriter()
void setFileName(const std::string &filename)
void open(vpImage< vpRGBa > &I)
void setFirstFrameIndex(int first_frame)