Visual Servoing Platform  version 3.5.0 under development (2022-02-15)
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/io/vpVideoWriter.h>
47 
48 #if VISP_HAVE_OPENCV_VERSION >= 0x020200
49 #include <opencv2/imgproc/imgproc.hpp>
50 #endif
51 
56  :
57 #if VISP_HAVE_OPENCV_VERSION >= 0x020100
58  m_writer(), m_framerate(25.0),
59 #endif
60  m_formatType(FORMAT_UNKNOWN), m_videoName(), m_frameName(),
61  m_initFileName(false), m_isOpen(false), m_frameCount(0), m_firstFrame(0),
62  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 
87 void vpVideoWriter::setFileName(const std::string &filename)
88 {
89  if (filename.empty()) {
90  throw(vpImageException(vpImageException::noFileNameError, "Filename empty in video writer"));
91  }
92 
93  m_videoName = filename;
94  m_frameName = filename;
95 
96  m_formatType = getFormat(filename);
97 
98  if (m_formatType == FORMAT_UNKNOWN) {
99  throw(vpException(vpException::badValue, "Filename extension not supported in video writer"));
100  }
101 
102  m_initFileName = true;
103 }
104 
111 {
112  if (! m_initFileName) {
113  throw(vpImageException(vpImageException::noFileNameError, "The generic filename has to be set in video writer"));
114  }
115 
116  if (m_formatType == FORMAT_PGM || m_formatType == FORMAT_PPM || m_formatType == FORMAT_JPEG || m_formatType == FORMAT_PNG) {
117  m_width = I.getWidth();
118  m_height = I.getHeight();
119  } else if (m_formatType == FORMAT_AVI || m_formatType == FORMAT_MPEG || m_formatType == FORMAT_MPEG4 ||
120  m_formatType == FORMAT_MOV) {
121 #if VISP_HAVE_OPENCV_VERSION >= 0x020100
122  m_writer = cv::VideoWriter(m_videoName, m_fourcc, m_framerate,
123  cv::Size(static_cast<int>(I.getWidth()), static_cast<int>(I.getHeight())));
124 
125  if (! m_writer.isOpened()) {
126  throw(vpException(vpException::fatalError, "Could not open encode the video with OpenCV"));
127  }
128 #else
129  throw(vpException(vpException::fatalError, "To encode video files ViSP should be build with OpenCV >= 2.1.0"));
130 #endif
131  }
132 
133  m_frameCount = m_firstFrame;
134 
135  m_isOpen = true;
136 }
137 
144 {
145  if (! m_initFileName) {
146  throw(vpImageException(vpImageException::noFileNameError, "The generic filename has to be set in video writer"));
147  }
148 
149  if (m_formatType == FORMAT_PGM || m_formatType == FORMAT_PPM || m_formatType == FORMAT_JPEG || m_formatType == FORMAT_PNG) {
150  m_width = I.getWidth();
151  m_height = I.getHeight();
152  } else if (m_formatType == FORMAT_AVI || m_formatType == FORMAT_MPEG || m_formatType == FORMAT_MPEG4 ||
153  m_formatType == FORMAT_MOV) {
154 #if VISP_HAVE_OPENCV_VERSION >= 0x020100
155  m_writer = cv::VideoWriter(m_videoName, m_fourcc, m_framerate,
156  cv::Size(static_cast<int>(I.getWidth()), static_cast<int>(I.getHeight())));
157 
158  if (! m_writer.isOpened()) {
159  throw(vpException(vpException::fatalError, "Could not open encode the video with OpenCV"));
160  }
161 #else
162  throw(vpException(vpException::fatalError, "To encode video files ViSP should be build with OpenCV >= 2.1.0"));
163 #endif
164  }
165 
166  m_frameCount = m_firstFrame;
167 
168  m_isOpen = true;
169 }
170 
181 {
182  if (! m_isOpen) {
183  throw(vpException(vpException::notInitialized, "The video has to be open first with video writer open() method"));
184  }
185 
186  if (m_formatType == FORMAT_PGM || m_formatType == FORMAT_PPM || m_formatType == FORMAT_JPEG || m_formatType == FORMAT_PNG) {
187  char name[FILENAME_MAX];
188  sprintf(name, m_videoName.c_str(), m_frameCount);
189  vpImageIo::write(I, name);
190  m_frameName = std::string(name);
191  } else {
192 #if VISP_HAVE_OPENCV_VERSION >= 0x020100
193  cv::Mat matFrame;
194  vpImageConvert::convert(I, matFrame);
195  m_writer << matFrame;
196 #endif
197  }
198 
199  m_frameCount += m_frameStep;
200 }
201 
212 {
213  if (! m_isOpen) {
214  throw(vpException(vpException::notInitialized, "The video has to be open first with video writer open() method"));
215  }
216 
217  if (m_formatType == FORMAT_PGM || m_formatType == FORMAT_PPM || m_formatType == FORMAT_JPEG || m_formatType == FORMAT_PNG) {
218  char name[FILENAME_MAX];
219  sprintf(name, m_videoName.c_str(), m_frameCount);
220  vpImageIo::write(I, name);
221  m_frameName = std::string(name);
222  } else {
223 #if VISP_HAVE_OPENCV_VERSION >= 0x030000
224  cv::Mat matFrame, rgbMatFrame;
225  vpImageConvert::convert(I, matFrame);
226  cv::cvtColor(matFrame, rgbMatFrame, cv::COLOR_GRAY2BGR);
227  m_writer << rgbMatFrame;
228 #elif VISP_HAVE_OPENCV_VERSION >= 0x020100
229  cv::Mat matFrame, rgbMatFrame;
230  vpImageConvert::convert(I, matFrame);
231  cv::cvtColor(matFrame, rgbMatFrame, CV_GRAY2BGR);
232  m_writer << rgbMatFrame;
233 #endif
234  }
235 
236  m_frameCount += m_frameStep;
237 }
238 
243 {
244  if (! m_isOpen) {
245  throw(vpException(vpException::notInitialized, "Cannot close video writer: not yet opened"));
246  }
247 }
248 
254 vpVideoWriter::vpVideoFormatType vpVideoWriter::getFormat(const std::string &filename)
255 {
256  std::string ext = vpVideoWriter::getExtension(filename);
257 
258  if (ext.compare(".PGM") == 0)
259  return FORMAT_PGM;
260  else if (ext.compare(".pgm") == 0)
261  return FORMAT_PGM;
262  else if (ext.compare(".PPM") == 0)
263  return FORMAT_PPM;
264  else if (ext.compare(".ppm") == 0)
265  return FORMAT_PPM;
266  else if (ext.compare(".JPG") == 0)
267  return FORMAT_JPEG;
268  else if (ext.compare(".jpg") == 0)
269  return FORMAT_JPEG;
270  else if (ext.compare(".JPEG") == 0)
271  return FORMAT_JPEG;
272  else if (ext.compare(".jpeg") == 0)
273  return FORMAT_JPEG;
274  else if (ext.compare(".PNG") == 0)
275  return FORMAT_PNG;
276  else if (ext.compare(".png") == 0)
277  return FORMAT_PNG;
278  else if (ext.compare(".AVI") == 0)
279  return FORMAT_AVI;
280  else if (ext.compare(".avi") == 0)
281  return FORMAT_AVI;
282  else if (ext.compare(".MPEG") == 0)
283  return FORMAT_MPEG;
284  else if (ext.compare(".mpeg") == 0)
285  return FORMAT_MPEG;
286  else if (ext.compare(".MPG") == 0)
287  return FORMAT_MPEG;
288  else if (ext.compare(".mpg") == 0)
289  return FORMAT_MPEG;
290  else if (ext.compare(".MPEG4") == 0)
291  return FORMAT_MPEG4;
292  else if (ext.compare(".mpeg4") == 0)
293  return FORMAT_MPEG4;
294  else if (ext.compare(".MP4") == 0)
295  return FORMAT_MPEG4;
296  else if (ext.compare(".mp4") == 0)
297  return FORMAT_MPEG4;
298  else if (ext.compare(".MOV") == 0)
299  return FORMAT_MOV;
300  else if (ext.compare(".mov") == 0)
301  return FORMAT_MOV;
302  else
303  return FORMAT_UNKNOWN;
304 }
305 
306 // return the extension of the file including the dot
307 std::string vpVideoWriter::getExtension(const std::string &filename)
308 {
309  // extract the extension
310  size_t dot = filename.find_last_of(".");
311  std::string ext = filename.substr(dot, filename.size() - 1);
312  return ext;
313 }
314 
320 void vpVideoWriter::setFirstFrameIndex(int first_frame) {
321  if (first_frame < 0) {
322  throw(vpException(vpException::fatalError, "Video writer first frame index cannot be negative"));
323  }
324  m_firstFrame = first_frame;
325 }
Used to indicate that a value is not in the allowed range.
Definition: vpException.h:97
void setFirstFrameIndex(int first_frame)
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
error that can be emited by ViSP classes.
Definition: vpException.h:71
virtual ~vpVideoWriter()
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:293
void saveFrame(vpImage< vpRGBa > &I)
void open(vpImage< vpRGBa > &I)
unsigned int getHeight() const
Definition: vpImage.h:188
Used to indicate that a parameter is not initialized.
Definition: vpException.h:98
void setFileName(const std::string &filename)
unsigned int getWidth() const
Definition: vpImage.h:246