ViSP  2.10.0
vpVideoReader.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 * Read videos and image sequences.
36 *
37 * Authors:
38 * Nicolas Melchior
39 * Fabien Spindler
40 *
41 *****************************************************************************/
42 
48 #include <visp/vpDebug.h>
49 #include <visp/vpVideoReader.h>
50 
51 #include <iostream>
52 #include <fstream>
53 #include <limits> // numeric_limits
54 
59  : imSequence(NULL),
60 #ifdef VISP_HAVE_FFMPEG
61  ffmpeg(NULL),
62 #elif VISP_HAVE_OPENCV_VERSION >= 0x020100
63  capture(), frame(),
64 #endif
65  formatType(FORMAT_UNKNOWN), initFileName(false), isOpen(false), frameCount(0),
66  firstFrame(0), lastFrame(0), firstFrameIndexIsSet(false), lastFrameIndexIsSet(false)
67 {
68 }
69 
74 {
75  if (imSequence != NULL)
76  {
77  delete imSequence;
78  }
79 #ifdef VISP_HAVE_FFMPEG
80  if (ffmpeg != NULL)
81  {
82  delete ffmpeg;
83  }
84 #endif
85 }
86 
87 
97 void vpVideoReader::setFileName(const char *filename)
98 {
99  if (!filename || *filename == '\0')
100  {
101  vpERROR_TRACE("filename empty ") ;
102  throw (vpImageException(vpImageException::noFileNameError,"filename empty ")) ;
103  }
104 
105  if (strlen( filename ) >= FILENAME_MAX) {
107  "Not enough memory to intialize the file name"));
108  }
109 
110  strcpy(this->fileName,filename);
111 
112  formatType = getFormat(fileName);
113 
114  if (formatType == FORMAT_UNKNOWN) {
115  throw(vpException(vpException::badValue, "Filename extension not supported"));
116  }
117 
118  initFileName = true;
119 }
120 
130 void vpVideoReader::setFileName(const std::string &filename)
131 {
132  setFileName(filename.c_str());
133 }
134 
143 {
144  if (!initFileName)
145  {
146  vpERROR_TRACE("The generic filename has to be set");
147  throw (vpImageException(vpImageException::noFileNameError,"filename empty"));
148  }
149 
150  if (isImageExtensionSupported())
151  {
152  imSequence = new vpDiskGrabber;
153  imSequence->setGenericName(fileName);
154  if (firstFrameIndexIsSet)
155  imSequence->setImageNumber(firstFrame);
156  }
157  else if (isVideoExtensionSupported())
158  {
159 #ifdef VISP_HAVE_FFMPEG
160  ffmpeg = new vpFFMPEG;
161  if(!ffmpeg->openStream(fileName, vpFFMPEG::COLORED))
162  throw (vpException(vpException::ioError ,"Could not open the video with ffmpeg"));
163  ffmpeg->initStream();
164 #elif VISP_HAVE_OPENCV_VERSION >= 0x020100
165  capture.open(fileName);
166 
167  if(!capture.isOpened())
168  {
169  throw (vpException(vpException::ioError ,"Could not open the video with opencv"));
170  }
171 #else
172  //vpERROR_TRACE("To read video files ViSP should be build with ffmpeg or opencv 3rd party libraries.");
173  throw (vpException(vpException::fatalError ,"To read video files ViSP should be build with ffmpeg or opencv 3rd >= 2.1.0 party libraries."));
174 #endif
175  }
176  else if (formatType == FORMAT_UNKNOWN)
177  {
178  //vpERROR_TRACE("The format of the file does not correspond to a readable format.");
179  throw (vpException(vpException::fatalError ,"The format of the file does not correspond to a readable format supported by ViSP."));
180  }
181 
182  findFirstFrameIndex();
183  frameCount = firstFrame;
184  if(!getFrame(I, firstFrame))
185  {
186  //vpERROR_TRACE("Could not read the video first frame");
187  throw (vpException(vpException::ioError ,"Could not read the video first frame"));
188  }
189 
190  height = I.getHeight();
191  width = I.getWidth();
192 
193  isOpen = true;
194  findLastFrameIndex();
195 }
196 
197 
206 {
207  if (!initFileName)
208  {
209  vpERROR_TRACE("The generic filename has to be set");
210  throw (vpImageException(vpImageException::noFileNameError,"filename empty"));
211  }
212 
213  if (isImageExtensionSupported())
214  {
215  imSequence = new vpDiskGrabber;
216  imSequence->setGenericName(fileName);
217  if (firstFrameIndexIsSet)
218  imSequence->setImageNumber(firstFrame);
219  }
220  else if (isVideoExtensionSupported())
221  {
222 #ifdef VISP_HAVE_FFMPEG
223  ffmpeg = new vpFFMPEG;
224  if (!ffmpeg->openStream(fileName, vpFFMPEG::GRAY_SCALED))
225  throw (vpException(vpException::ioError ,"Could not open the video with ffmpeg"));
226  ffmpeg->initStream();
227 #elif VISP_HAVE_OPENCV_VERSION >= 0x020100
228  capture.open(fileName);
229 
230  if(!capture.isOpened())
231  {
232  throw (vpException(vpException::ioError ,"Could not open the video with opencv"));
233  }
234 #else
235  //vpERROR_TRACE("To read video files ViSP should be build with ffmpeg or opencv 3rd party libraries.");
236  throw (vpException(vpException::fatalError ,"To read video files ViSP should be build with ffmpeg or opencv >= 2.1.0 3rd party libraries."));
237 #endif
238  }
239  else if (formatType == FORMAT_UNKNOWN)
240  {
241  //vpERROR_TRACE("The format of the file does not correspond to a readable format.");
242  throw (vpException(vpException::fatalError ,"The format of the file does not correspond to a readable format supported by ViSP."));
243  }
244 
245  findFirstFrameIndex();
246  frameCount = firstFrame;
247  if(!getFrame(I,firstFrame))
248  {
249  //vpERROR_TRACE("Could not read the video first frame");
250  throw (vpException(vpException::ioError ,"Could not read the video first frame"));
251  }
252 
253  height = I.getHeight();
254  width = I.getWidth();
255 
256  isOpen = true;
257  findLastFrameIndex();
258 }
259 
260 
271 {
272  if (!isOpen) {
273  open(I);
274  }
275 
276  //getFrame(I,frameCount);
277  if (imSequence != NULL)
278  {
279  imSequence->acquire(I);
280  frameCount++; // next index
281  }
282 #ifdef VISP_HAVE_FFMPEG
283  else if (ffmpeg !=NULL)
284  {
285  ffmpeg->acquire(I);
286  frameCount++; // next index
287  }
288 #elif VISP_HAVE_OPENCV_VERSION >= 0x020100
289  else
290  {
291  capture >> frame;
292 #if VISP_HAVE_OPENCV_VERSION >= 0x030000
293  frameCount = (long) capture.get(cv::CAP_PROP_POS_FRAMES); // next index
294 #else
295  frameCount = (long) capture.get(CV_CAP_PROP_POS_FRAMES); // next index
296 #endif
297 
298  if(frame.empty())
299  setLastFrameIndex(frameCount-1);
300  else
301  vpImageConvert::convert(frame, I);
302  }
303 #endif
304 }
305 
306 
315 {
316  if (!isOpen) {
317  open(I);
318  }
319 
320  if (imSequence != NULL)
321  {
322  imSequence->acquire(I);
323  frameCount++; // next index
324  }
325 #ifdef VISP_HAVE_FFMPEG
326  else if (ffmpeg != NULL)
327  {
328  ffmpeg->acquire(I);
329  frameCount++; // next index
330  }
331 #elif VISP_HAVE_OPENCV_VERSION >= 0x020100
332  else
333  {
334  capture >> frame;
335 #if VISP_HAVE_OPENCV_VERSION >= 0x030000
336  frameCount = (long) capture.get(cv::CAP_PROP_POS_FRAMES); // next index
337 #else
338  frameCount = (long) capture.get(CV_CAP_PROP_POS_FRAMES); // next index
339 #endif
340 
341  if(frame.empty())
342  setLastFrameIndex(frameCount-1);
343  else
344  vpImageConvert::convert(frame, I);
345  }
346 #endif
347 }
348 
349 
362 bool vpVideoReader::getFrame(vpImage<vpRGBa> &I, long frame_index)
363 {
364  if (imSequence != NULL)
365  {
366  try
367  {
368  imSequence->acquire(I, frame_index);
369  frameCount = frame_index + 1; // next index
370  }
371  catch(...)
372  {
373  vpERROR_TRACE("Couldn't find the %u th frame", frame_index) ;
374  return false;
375  }
376  }
377  else
378  {
379 #ifdef VISP_HAVE_FFMPEG
380  if(!ffmpeg->getFrame(I, (unsigned int)frame_index))
381  {
382  vpERROR_TRACE("Couldn't find the %ld th frame", frame_index) ;
383  return false;
384  }
385  frameCount = frame_index + 1; // next index
386 #elif defined(VISP_HAVE_OPENCV) && (VISP_HAVE_OPENCV_VERSION >= 0x030000)
387  if(!capture.set(cv::CAP_PROP_POS_FRAMES, frame_index))
388  {
389  vpERROR_TRACE("Couldn't find the %ld th frame", frame_index) ;
390  return false;
391  }
392 
393  capture >> frame;
394  frameCount = (long) capture.get(cv::CAP_PROP_POS_FRAMES); // next index
395  if(frame.empty())
396  setLastFrameIndex(frameCount-1);
397  else
398  vpImageConvert::convert(frame, I);
399 #elif defined(VISP_HAVE_OPENCV) && (VISP_HAVE_OPENCV_VERSION >= 0x020100)
400  if(!capture.set(CV_CAP_PROP_POS_FRAMES, frame_index))
401  {
402  vpERROR_TRACE("Couldn't find the %ld th frame", frame_index) ;
403  return false;
404  }
405 
406  capture >> frame;
407  frameCount = (long) capture.get(CV_CAP_PROP_POS_FRAMES); // next index
408  if(frame.empty())
409  setLastFrameIndex(frameCount-1);
410  else
411  vpImageConvert::convert(frame, I);
412 #endif
413  }
414 
415  return true;
416 }
417 
418 
432 {
433  if (imSequence != NULL)
434  {
435  try
436  {
437  imSequence->acquire(I, frame_index);
438  frameCount = frame_index + 1;
439  }
440  catch(...)
441  {
442  vpERROR_TRACE("Couldn't find the %u th frame", frame_index) ;
443  return false;
444  }
445  }
446  else
447  {
448 #ifdef VISP_HAVE_FFMPEG
449  if(!ffmpeg->getFrame(I, (unsigned int)frame_index))
450  {
451  vpERROR_TRACE("Couldn't find the %ld th frame", frame_index) ;
452  return false;
453  }
454  frameCount = frame_index + 1; // next index
455 #elif VISP_HAVE_OPENCV_VERSION >= 0x030000
456  if(!capture.set(cv::CAP_PROP_POS_FRAMES, frame_index))
457  {
458  vpERROR_TRACE("Couldn't find the %ld th frame", frame_index) ;
459  return false;
460  }
461  capture >> frame;
462  frameCount = (long) capture.get(cv::CAP_PROP_POS_FRAMES); // next index
463  if(frame.empty())
464  setLastFrameIndex(frameCount-1);
465  else
466  vpImageConvert::convert(frame, I);
467 #elif VISP_HAVE_OPENCV_VERSION >= 0x020100
468  if(!capture.set(CV_CAP_PROP_POS_FRAMES, frame_index))
469  {
470  vpERROR_TRACE("Couldn't find the %ld th frame", frame_index); // next index
471  return false;
472  }
473  capture >> frame;
474  frameCount = (long) capture.get(CV_CAP_PROP_POS_FRAMES);
475  if(frame.empty())
476  setLastFrameIndex(frameCount-1);
477  else
478  vpImageConvert::convert(frame, I);
479 #endif
480  }
481 
482  return true;
483 }
484 
485 
491 vpVideoReader::vpVideoFormatType
492  vpVideoReader::getFormat(const char *filename)
493 {
494  std::string sfilename(filename);
495 
496  std::string ext = vpVideoReader::getExtension(sfilename);
497 
498  if (ext.compare(".PGM") == 0)
499  return FORMAT_PGM;
500  else if (ext.compare(".pgm") == 0)
501  return FORMAT_PGM;
502  else if (ext.compare(".PPM") == 0)
503  return FORMAT_PPM;
504  else if (ext.compare(".ppm") == 0)
505  return FORMAT_PPM;
506  else if (ext.compare(".JPG") == 0)
507  return FORMAT_JPEG;
508  else if (ext.compare(".jpg") == 0)
509  return FORMAT_JPEG;
510  else if (ext.compare(".JPEG") == 0)
511  return FORMAT_JPEG;
512  else if (ext.compare(".jpeg") == 0)
513  return FORMAT_JPEG;
514  else if (ext.compare(".PNG") == 0)
515  return FORMAT_PNG;
516  else if (ext.compare(".png") == 0)
517  return FORMAT_PNG;
518  else if (ext.compare(".TIFF") == 0)
519  return FORMAT_TIFF;
520  else if (ext.compare(".tiff") == 0)
521  return FORMAT_TIFF;
522  else if (ext.compare(".BMP") == 0)
523  return FORMAT_BMP;
524  else if (ext.compare(".bmp") == 0)
525  return FORMAT_BMP;
526  else if (ext.compare(".DIB") == 0)
527  return FORMAT_DIB;
528  else if (ext.compare(".dib") == 0)
529  return FORMAT_DIB;
530  else if (ext.compare(".PBM") == 0)
531  return FORMAT_PBM;
532  else if (ext.compare(".PBM") == 0)
533  return FORMAT_PBM;
534  else if (ext.compare(".SR") == 0)
535  return FORMAT_PBM;
536  else if (ext.compare(".sr") == 0)
537  return FORMAT_PBM;
538  else if (ext.compare(".RAS") == 0)
539  return FORMAT_RASTER;
540  else if (ext.compare(".ras") == 0)
541  return FORMAT_RASTER;
542  else if (ext.compare(".JP2") == 0)
543  return FORMAT_JPEG2000;
544  else if (ext.compare(".jp2") == 0)
545  return FORMAT_JPEG2000;
546  else if (ext.compare(".AVI") == 0)
547  return FORMAT_AVI;
548  else if (ext.compare(".avi") == 0)
549  return FORMAT_AVI;
550  else if (ext.compare(".MPEG") == 0)
551  return FORMAT_MPEG;
552  else if (ext.compare(".mpeg") == 0)
553  return FORMAT_MPEG;
554  else if (ext.compare(".MPG") == 0)
555  return FORMAT_MPEG;
556  else if (ext.compare(".mpg") == 0)
557  return FORMAT_MPEG;
558  else if (ext.compare(".MPEG4") == 0)
559  return FORMAT_MPEG4;
560  else if (ext.compare(".mpeg4") == 0)
561  return FORMAT_MPEG4;
562  else if (ext.compare(".MP4") == 0)
563  return FORMAT_MPEG4;
564  else if (ext.compare(".mp4") == 0)
565  return FORMAT_MPEG4;
566  else if (ext.compare(".MOV") == 0)
567  return FORMAT_MOV;
568  else if (ext.compare(".mov") == 0)
569  return FORMAT_MOV;
570  else if (ext.compare(".OGV") == 0)
571  return FORMAT_OGV;
572  else if (ext.compare(".ogv") == 0)
573  return FORMAT_OGV;
574  else if (ext.compare(".WMV") == 0)
575  return FORMAT_WMV;
576  else if (ext.compare(".wmv") == 0)
577  return FORMAT_WMV;
578  else if (ext.compare(".FLV") == 0)
579  return FORMAT_FLV;
580  else if (ext.compare(".flv") == 0)
581  return FORMAT_FLV;
582  else if (ext.compare(".MKV") == 0)
583  return FORMAT_MKV;
584  else if (ext.compare(".mkv") == 0)
585  return FORMAT_MKV;
586  else
587  return FORMAT_UNKNOWN;
588 }
589 
590 // return the extension of the file including the dot
591 std::string vpVideoReader::getExtension(const std::string &filename)
592 {
593  // extract the extension
594  size_t dot = filename.find_last_of(".");
595  std::string ext = filename.substr(dot, filename.size()-1);
596  return ext;
597 }
598 
599 
603 void
604  vpVideoReader::findLastFrameIndex()
605 {
606  if (!isOpen)
607  {
608  vpERROR_TRACE("Use the open method before");
609  throw (vpException(vpException::notInitialized,"file not yet opened"));
610  }
611 
612  if (imSequence != NULL)
613  {
614  if (! lastFrameIndexIsSet) {
615  char name[FILENAME_MAX];
616  int image_number = firstFrame;
617  bool failed;
618  do
619  {
620  std::fstream file;
621  sprintf(name,fileName,image_number) ;
622  file.open(name, std::ios::in);
623  failed = file.fail();
624  if (!failed) {
625  file.close();
626  image_number++;
627  }
628  }while(!failed);
629 
630  lastFrame = image_number;
631  }
632  }
633 
634 #ifdef VISP_HAVE_FFMPEG
635  else if (ffmpeg != NULL) {
636  if (! lastFrameIndexIsSet) {
637  lastFrame = (long)(ffmpeg->getFrameNumber());
638  }
639  }
640 #elif VISP_HAVE_OPENCV_VERSION >= 0x030000
641  else if (! lastFrameIndexIsSet)
642  {
643  lastFrame = (long) capture.get(cv::CAP_PROP_FRAME_COUNT);
644  if(lastFrame <= 2) // with tutorial/matching/video-postcard.mpeg it return 2 with OpenCV 3.0.0
645  {
646  //std::cout << "Warning: Problem with cv::CAP_PROP_FRAME_COUNT. We set video last frame to an arbitrary value (1000)." << std::endl;
647  lastFrame = 100000; // Set lastFrame to an arbitrary value
648  }
649  lastFrame--; //Last frame index = total frame count - 1
650  }
651 #elif VISP_HAVE_OPENCV_VERSION >= 0x020100
652  else if (! lastFrameIndexIsSet)
653  {
654  lastFrame = (long) capture.get(CV_CAP_PROP_FRAME_COUNT);
655  if(lastFrame <= 2) // with tutorial/matching/video-postcard.mpeg it return 2 with OpenCV 2.4.10
656  {
657  //std::cout << "Warning: Problem with CV_CAP_PROP_FRAME_COUNT. We set video last frame to an arbitrary value (1000)." << std::endl;
658  lastFrame = 100000; // Set lastFrame to an arbitrary value
659  }
660  lastFrame--; //Last frame index = total frame count - 1
661  }
662 #endif
663 }
667 void
668  vpVideoReader::findFirstFrameIndex()
669 {
670  if (imSequence != NULL)
671  {
672  if (! firstFrameIndexIsSet) {
673  char name[FILENAME_MAX];
674  int image_number = 0;
675  bool failed;
676  do {
677  std::fstream file;
678  sprintf(name, fileName, image_number) ;
679  file.open(name, std::ios::in);
680  failed = file.fail();
681  if (!failed) file.close();
682  image_number++;
683  } while(failed);
684 
685  firstFrame = image_number - 1;
686  imSequence->setImageNumber(firstFrame);
687  }
688  }
689 #ifdef VISP_HAVE_FFMPEG
690  else if (ffmpeg != NULL) {
691  if (! firstFrameIndexIsSet) {
692  firstFrame = (long)(0);
693  }
694  }
695 #elif VISP_HAVE_OPENCV_VERSION >= 0x020100
696  else if (! firstFrameIndexIsSet)
697  {
698  firstFrame = (long) (0);
699  }
700 #endif
701 }
702 
709 {
710  double framerate = -1.;
711 
712 #ifdef VISP_HAVE_FFMPEG
713  if (ffmpeg != NULL)
714  {
715  framerate = ffmpeg->getFramerate();
716  }
717 #elif VISP_HAVE_OPENCV_VERSION >= 0x030000
718  framerate = capture.get(cv::CAP_PROP_FPS);
719  // if(framerate == 0)
720  if(std::fabs(framerate) <= std::numeric_limits<double>::epsilon())
721  {
722  vpERROR_TRACE("Problem with cv::CAP_PROP_FPS") ;
723  }
724 #elif VISP_HAVE_OPENCV_VERSION >= 0x020100
725  framerate = capture.get(CV_CAP_PROP_FPS);
726  // if(framerate == 0)
727  if(std::fabs(framerate) <= std::numeric_limits<double>::epsilon())
728  {
729  vpERROR_TRACE("Problem with CV_CAP_PROP_FPS") ;
730  }
731 #endif
732  return framerate;
733 }
734 
738 bool vpVideoReader::isImageExtensionSupported()
739 {
740  return (formatType == FORMAT_PGM ||
741  formatType == FORMAT_PPM ||
742  formatType == FORMAT_JPEG ||
743  formatType == FORMAT_PNG ||
744  formatType == FORMAT_TIFF ||
745  formatType == FORMAT_BMP ||
746  formatType == FORMAT_DIB ||
747  formatType == FORMAT_PBM ||
748  formatType == FORMAT_RASTER ||
749  formatType == FORMAT_JPEG2000);
750 }
751 
755 bool vpVideoReader::isVideoExtensionSupported()
756 {
757  return (formatType == FORMAT_AVI ||
758  formatType == FORMAT_MPEG ||
759  formatType == FORMAT_MPEG4 ||
760  formatType == FORMAT_MOV ||
761  formatType == FORMAT_OGV ||
762  formatType == FORMAT_WMV ||
763  formatType == FORMAT_FLV ||
764  formatType == FORMAT_MKV);
765 }
double getFramerate() const
Definition: vpFFMPEG.h:223
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 getFrame(vpImage< vpRGBa > &I, unsigned int frameNumber)
Definition: vpFFMPEG.cpp:294
error that can be emited by ViSP classes.
Definition: vpException.h:76
Error that can be emited by the vpImage class and its derivates.
unsigned long getFrameNumber() const
Definition: vpFFMPEG.h:216
void open(vpImage< vpRGBa > &I)
bool getFrame(vpImage< vpRGBa > &I, long frame)
unsigned int height
Number of rows in the image.
bool openStream(const char *filename, vpFFMPEGColorType color_type)
Definition: vpFFMPEG.cpp:99
void acquire(vpImage< vpRGBa > &I)
This class interfaces the FFmpeg library to enable video stream reading or writing.
Definition: vpFFMPEG.h:149
void setImageNumber(long number)
void setFileName(const char *filename)
Class to grab (ie. read) images from the disk.
void setLastFrameIndex(const long last_frame)
bool acquire(vpImage< vpRGBa > &I)
Definition: vpFFMPEG.cpp:348
double getFramerate()
unsigned int getHeight() const
Definition: vpImage.h:152
void acquire(vpImage< unsigned char > &I)
bool initStream()
Definition: vpFFMPEG.cpp:235
unsigned int width
Number of columns in the image.
void setGenericName(const char *genericName)