Visual Servoing Platform  version 3.5.1 under development (2023-02-03)
vpVideoWriter.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2022 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  *****************************************************************************/
35 
41 #include <visp3/core/vpDebug.h>
42 #include <visp3/core/vpIoTools.h>
43 #include <visp3/io/vpVideoWriter.h>
44 
45 #if VISP_HAVE_OPENCV_VERSION >= 0x020200
46 #include <opencv2/imgproc/imgproc.hpp>
47 #endif
48 
53  :
54 #if VISP_HAVE_OPENCV_VERSION >= 0x020100
55  m_writer(), m_framerate(25.0),
56 #endif
57  m_formatType(FORMAT_UNKNOWN), m_videoName(), m_frameName(), m_initFileName(false), m_isOpen(false), m_frameCount(0),
58  m_firstFrame(0), m_width(0), m_height(0), m_frameStep(1)
59 {
60 #if VISP_HAVE_OPENCV_VERSION >= 0x030000
61  m_fourcc = cv::VideoWriter::fourcc('P', 'I', 'M', '1');
62 #elif VISP_HAVE_OPENCV_VERSION >= 0x020100
63  m_fourcc = CV_FOURCC('P', 'I', 'M', '1'); // default is a MPEG-1 codec
64 #endif
65 }
66 
71 
86 void vpVideoWriter::setFileName(const std::string &filename)
87 {
88  if (filename.empty()) {
89  throw(vpImageException(vpImageException::noFileNameError, "Filename empty in video writer"));
90  }
91 
92  m_videoName = filename;
93  m_frameName = filename;
94 
95  m_formatType = getFormat(filename);
96 
97  if (m_formatType == FORMAT_UNKNOWN) {
98  throw(vpException(vpException::badValue, "Filename extension not supported in video writer"));
99  }
100 
101  m_initFileName = true;
102 }
103 
113 {
114  if (!m_initFileName) {
115  throw(vpImageException(vpImageException::noFileNameError, "The generic filename has to be set in video writer"));
116  }
117 
119 
120  if (m_formatType == FORMAT_PGM || m_formatType == FORMAT_PPM || m_formatType == FORMAT_JPEG ||
121  m_formatType == FORMAT_PNG) {
122  m_width = I.getWidth();
123  m_height = I.getHeight();
124  } else if (m_formatType == FORMAT_AVI || m_formatType == FORMAT_MPEG || m_formatType == FORMAT_MPEG4 ||
125  m_formatType == FORMAT_MOV) {
126 #if VISP_HAVE_OPENCV_VERSION >= 0x020100
127  m_writer = cv::VideoWriter(m_videoName, m_fourcc, m_framerate,
128  cv::Size(static_cast<int>(I.getWidth()), static_cast<int>(I.getHeight())));
129 
130  if (!m_writer.isOpened()) {
131  throw(vpException(vpException::fatalError, "Could not encode the video with OpenCV"));
132  }
133 #else
134  throw(vpException(vpException::fatalError, "To encode video files ViSP should be build with OpenCV >= 2.1.0"));
135 #endif
136  }
137 
138  m_frameCount = m_firstFrame;
139 
140  m_isOpen = true;
141 }
142 
152 {
153  if (!m_initFileName) {
154  throw(vpImageException(vpImageException::noFileNameError, "The generic filename has to be set in video writer"));
155  }
156 
158 
159  if (m_formatType == FORMAT_PGM || m_formatType == FORMAT_PPM || m_formatType == FORMAT_JPEG ||
160  m_formatType == FORMAT_PNG) {
161  m_width = I.getWidth();
162  m_height = I.getHeight();
163  } else if (m_formatType == FORMAT_AVI || m_formatType == FORMAT_MPEG || m_formatType == FORMAT_MPEG4 ||
164  m_formatType == FORMAT_MOV) {
165 #if VISP_HAVE_OPENCV_VERSION >= 0x020100
166  m_writer = cv::VideoWriter(m_videoName, m_fourcc, m_framerate,
167  cv::Size(static_cast<int>(I.getWidth()), static_cast<int>(I.getHeight())));
168 
169  if (!m_writer.isOpened()) {
170  throw(vpException(vpException::fatalError, "Could not encode the video with OpenCV"));
171  }
172 #else
173  throw(vpException(vpException::fatalError, "To encode video files ViSP should be build with OpenCV >= 2.1.0"));
174 #endif
175  }
176 
177  m_frameCount = m_firstFrame;
178 
179  m_isOpen = true;
180 }
181 
192 {
193  if (!m_isOpen) {
194  throw(vpException(vpException::notInitialized, "The video has to be open first with video writer open() method"));
195  }
196 
197  if (m_formatType == FORMAT_PGM || m_formatType == FORMAT_PPM || m_formatType == FORMAT_JPEG ||
198  m_formatType == FORMAT_PNG) {
199  char name[FILENAME_MAX];
200  snprintf(name, FILENAME_MAX, m_videoName.c_str(), m_frameCount);
201  vpImageIo::write(I, name);
202  m_frameName = std::string(name);
203  } else {
204 #if VISP_HAVE_OPENCV_VERSION >= 0x020100
205  cv::Mat matFrame;
206  vpImageConvert::convert(I, matFrame);
207  m_writer << matFrame;
208 #endif
209  }
210 
211  m_frameCount += m_frameStep;
212 }
213 
224 {
225  if (!m_isOpen) {
226  throw(vpException(vpException::notInitialized, "The video has to be open first with video writer open() method"));
227  }
228 
229  if (m_formatType == FORMAT_PGM || m_formatType == FORMAT_PPM || m_formatType == FORMAT_JPEG ||
230  m_formatType == FORMAT_PNG) {
231  char name[FILENAME_MAX];
232  snprintf(name, FILENAME_MAX, m_videoName.c_str(), m_frameCount);
233  vpImageIo::write(I, name);
234  m_frameName = std::string(name);
235  } else {
236 #if VISP_HAVE_OPENCV_VERSION >= 0x030000
237  cv::Mat matFrame, rgbMatFrame;
238  vpImageConvert::convert(I, matFrame);
239  cv::cvtColor(matFrame, rgbMatFrame, cv::COLOR_GRAY2BGR);
240  m_writer << rgbMatFrame;
241 #elif VISP_HAVE_OPENCV_VERSION >= 0x020100
242  cv::Mat matFrame, rgbMatFrame;
243  vpImageConvert::convert(I, matFrame);
244  cv::cvtColor(matFrame, rgbMatFrame, CV_GRAY2BGR);
245  m_writer << rgbMatFrame;
246 #endif
247  }
248 
249  m_frameCount += m_frameStep;
250 }
251 
256 {
257  if (!m_isOpen) {
258  throw(vpException(vpException::notInitialized, "Cannot close video writer: not yet opened"));
259  }
260 }
261 
267 vpVideoWriter::vpVideoFormatType vpVideoWriter::getFormat(const std::string &filename)
268 {
269  std::string ext = vpVideoWriter::getExtension(filename);
270 
271  if (ext.compare(".PGM") == 0)
272  return FORMAT_PGM;
273  else if (ext.compare(".pgm") == 0)
274  return FORMAT_PGM;
275  else if (ext.compare(".PPM") == 0)
276  return FORMAT_PPM;
277  else if (ext.compare(".ppm") == 0)
278  return FORMAT_PPM;
279  else if (ext.compare(".JPG") == 0)
280  return FORMAT_JPEG;
281  else if (ext.compare(".jpg") == 0)
282  return FORMAT_JPEG;
283  else if (ext.compare(".JPEG") == 0)
284  return FORMAT_JPEG;
285  else if (ext.compare(".jpeg") == 0)
286  return FORMAT_JPEG;
287  else if (ext.compare(".PNG") == 0)
288  return FORMAT_PNG;
289  else if (ext.compare(".png") == 0)
290  return FORMAT_PNG;
291  else if (ext.compare(".AVI") == 0)
292  return FORMAT_AVI;
293  else if (ext.compare(".avi") == 0)
294  return FORMAT_AVI;
295  else if (ext.compare(".MPEG") == 0)
296  return FORMAT_MPEG;
297  else if (ext.compare(".mpeg") == 0)
298  return FORMAT_MPEG;
299  else if (ext.compare(".MPG") == 0)
300  return FORMAT_MPEG;
301  else if (ext.compare(".mpg") == 0)
302  return FORMAT_MPEG;
303  else if (ext.compare(".MPEG4") == 0)
304  return FORMAT_MPEG4;
305  else if (ext.compare(".mpeg4") == 0)
306  return FORMAT_MPEG4;
307  else if (ext.compare(".MP4") == 0)
308  return FORMAT_MPEG4;
309  else if (ext.compare(".mp4") == 0)
310  return FORMAT_MPEG4;
311  else if (ext.compare(".MOV") == 0)
312  return FORMAT_MOV;
313  else if (ext.compare(".mov") == 0)
314  return FORMAT_MOV;
315  else
316  return FORMAT_UNKNOWN;
317 }
318 
319 // return the extension of the file including the dot
320 std::string vpVideoWriter::getExtension(const std::string &filename)
321 {
322  // extract the extension
323  size_t dot = filename.find_last_of(".");
324  std::string ext = filename.substr(dot, filename.size() - 1);
325  return ext;
326 }
327 
334 {
335  if (first_frame < 0) {
336  throw(vpException(vpException::fatalError, "Video writer first frame index cannot be negative"));
337  }
338  m_firstFrame = first_frame;
339 }
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:247
unsigned int getHeight() const
Definition: vpImage.h:189
static void makeDirectory(const std::string &dirname)
Definition: vpIoTools.cpp:578
static std::string getParent(const std::string &pathname)
Definition: vpIoTools.cpp:1633
void saveFrame(vpImage< vpRGBa > &I)
virtual ~vpVideoWriter()
void setFileName(const std::string &filename)
void open(vpImage< vpRGBa > &I)
void setFirstFrameIndex(int first_frame)