SLProject  4.3.020
A platform independent 3D computer graphics framework for desktop OS, Android, iOS and online in web browsers
SENSVideoStream.cpp
Go to the documentation of this file.
1 #include "SENSVideoStream.h"
2 #include "SENS.h"
3 #include "SENSException.h"
4 #include <Utils.h>
5 #include "SENSUtils.h"
6 #include "SENSCamera.h"
7 
8 SENSVideoStream::SENSVideoStream(const std::string& videoFileName,
9  bool videoLoops,
10  bool mirrorH,
11  bool mirrorV,
12  float targetFps)
13  : _videoLoops(videoLoops),
14  _mirrorH(mirrorH),
15  _mirrorV(mirrorV)
16 {
17  if (!Utils::fileExists(videoFileName))
18  {
19  throw SENSException(SENSType::VIDEO, "Video file does not exist: " + videoFileName, __LINE__, __FILE__);
20  }
21 
22  _cap.open(videoFileName);
23  if (!_cap.isOpened())
24  throw SENSException(SENSType::VIDEO, "Could not open video file stream: " + videoFileName, __LINE__, __FILE__);
25 
26  _videoFrameSize = {(int)_cap.get(cv::CAP_PROP_FRAME_WIDTH), (int)_cap.get(cv::CAP_PROP_FRAME_HEIGHT)};
27  _frameCount = (int)_cap.get(cv::CAP_PROP_FRAME_COUNT);
28  _fps = (float)_cap.get(cv::CAP_PROP_FPS);
29 
30  if (targetFps == 0)
31  _targetFps = _fps;
32  else
33  _targetFps = targetFps;
34 
35  _videoFileName = videoFileName;
36 }
37 
39 {
40  if (!_cap.isOpened())
41  throw SENSException(SENSType::VIDEO, "Video file stream is not open!", __LINE__, __FILE__);
42 
43  if (_videoLoops)
44  {
45  if (_cap.get(cv::CAP_PROP_POS_FRAMES) == _frameCount)
46  _cap.set(cv::CAP_PROP_POS_FRAMES, 0);
47  }
48 
49  SENSFramePtr sensFrame;
50  cv::Mat bgrImg;
51  cv::Mat grayImg;
52 
53  if (_cap.read(bgrImg))
54  {
56  cv::cvtColor(bgrImg, grayImg, cv::COLOR_BGR2GRAY);
57 
58  sensFrame = std::make_unique<SENSFrame>(
59  SENSClock::now(),
60  bgrImg,
61  grayImg,
62  _mirrorH,
63  _mirrorV,
64  1.0f,
65  cv::Mat(),
66  bgrImg.cols,
67  bgrImg.rows);
68  }
69 
70  return sensFrame;
71 }
72 
74 {
75  if (!_cap.isOpened())
76  throw SENSException(SENSType::VIDEO, "Video file stream is not open!", __LINE__, __FILE__);
77 
78  if (_videoLoops)
79  {
80  if (_cap.get(cv::CAP_PROP_POS_FRAMES) == _frameCount)
81  _cap.set(cv::CAP_PROP_POS_FRAMES, 0);
82  }
83 
84  SENSFramePtr sensFrame;
85  cv::Mat bgrImg;
86  cv::Mat grayImg;
87 
88  float frameDuration = 1.0f / _targetFps;
89  int frameIndex = (int)_cap.get(cv::CAP_PROP_POS_FRAMES);
90  int skippedFrame = 0;
91  float frameTime;
92  float lastFrameTime = frameIndex / _fps;
93  do
94  {
95  skippedFrame++;
96  frameTime = (float)(frameIndex + skippedFrame) / _fps;
97  } while ((frameTime - lastFrameTime) < frameDuration);
98 
99  float frameError = (frameTime - lastFrameTime - frameDuration); //Compute overflow
100  int nbFrame = (int)(frameIndex * _targetFps / _fps); //Expected number of frames
101  float totalError = (nbFrame * frameError); //Total cumulated error
102  if ((fmod(totalError, frameDuration) + frameError) > frameDuration && skippedFrame > 1)
103  {
104  skippedFrame--;
105  }
106 
107  moveCapturePosition(skippedFrame);
108 
109  if (_cap.read(bgrImg))
110  {
112  cv::cvtColor(bgrImg, grayImg, cv::COLOR_BGR2GRAY);
113 
114  sensFrame = std::make_unique<SENSFrame>(
115  SENSClock::now(),
116  bgrImg,
117  grayImg,
118  _mirrorH,
119  _mirrorV,
120  1.0,
121  cv::Mat(),
122  bgrImg.cols,
123  bgrImg.rows);
124  }
125 
126  return sensFrame;
127 }
128 
130 {
131  int frameIndex = (int)_cap.get(cv::CAP_PROP_POS_FRAMES);
132  int skippedFrame = 0;
133  float frameTime;
134  float currentFrameTime = frameIndex / _fps;
135 
136  do
137  {
138  frameTime = frameIndex - skippedFrame / _fps;
139  skippedFrame++;
140  } while ((currentFrameTime - frameTime) > 1.0 / _targetFps);
141 
142  moveCapturePosition(-skippedFrame + 1);
143  return grabNextFrame();
144 }
145 
147 {
149  return grabNextFrame();
150 }
151 
153 {
154  int frameIndex = (int)_cap.get(cv::CAP_PROP_POS_FRAMES);
155  frameIndex += n;
156 
157  if (frameIndex < 0)
158  frameIndex = 0;
159  else if (frameIndex > _frameCount)
160  frameIndex = _frameCount;
161 
162  _cap.set(cv::CAP_PROP_POS_FRAMES, frameIndex);
163 }
164 
165 void SENSVideoStream::setCalibration(SENSCalibration calibration, bool buildUndistortionMaps)
166 {
167  if (!_cap.isOpened())
168  throw SENSException(SENSType::CAM, "setCalibration not possible if video stream is not started!", __LINE__, __FILE__);
169 
170  _calibration = std::make_unique<SENSCalibration>(calibration);
171  //now we adapt the calibration to the target size
172  if (_videoFrameSize.width != calibration.imageSize().width || _videoFrameSize.height != calibration.imageSize().height)
173  _calibration->adaptForNewResolution({_videoFrameSize.width, _videoFrameSize.height}, buildUndistortionMaps);
174 }
175 
177 {
178  _calibration = std::make_unique<SENSCalibration>(_videoFrameSize,
179  fovGuess,
180  false,
181  false,
184 }
std::shared_ptr< SENSFrame > SENSFramePtr
Definition: SENSFrame.h:73
cv::Size imageSize() const
cv::Size2i _videoFrameSize
SENSFramePtr grabPreviousFrame()
const SENSCalibration *const calibration() const
void setCalibration(SENSCalibration calibration, bool buildUndistortionMaps)
SENSFramePtr grabNextFrame()
void guessAndSetCalibration(float fovGuess)
cv::VideoCapture _cap
void moveCapturePosition(int n)
std::string _videoFileName
SENSFramePtr grabNextResampledFrame()
SENSVideoStream(const std::string &videoFileName, bool videoLoops, bool mirrorH, bool mirrorV, float targetFps=0)
SENSFramePtr grabPreviousResampledFrame()
std::unique_ptr< SENSCalibration > _calibration
Class for holding computer information.
Definition: Utils.h:288
void mirrorImage(cv::Mat &img, bool mirrorH, bool mirrorV)
Definition: SENSUtils.cpp:170
std::vector< char > & get(std::string path)
Definition: SLIOMemory.cpp:24
bool fileExists(const string &pathfilename)
Returns true if a file exists.
Definition: Utils.cpp:894