libcvd
diskbuffer2.h
1 #ifndef CVD_DISKBUFFER2_H
2 #define CVD_DISKBUFFER2_H
3 
4 #include <errno.h>
5 #include <fstream>
6 #include <string>
7 #include <utility>
8 #include <vector>
9 
10 #include <cvd/diskbuffer2_frame.h>
11 #include <cvd/image_io.h>
12 #include <cvd/localvideobuffer.h>
13 #include <cvd/videobufferflags.h>
14 
15 namespace CVD
16 {
17 //
18 // GLOBLIST
24 std::vector<std::string> globlist(const std::string& gl);
25 
26 namespace Exceptions
27 {
30  namespace DiskBuffer2
31  {
35  {
36  using CVD::Exceptions::VideoBuffer::All::All;
37  };
40  struct NoFiles : public All
41  {
42  NoFiles();
43  };
46  struct BadFile : public All
47  {
48  BadFile(const std::string&, int);
49  };
52  struct BadImage : public All
53  {
54  BadImage(const std::string& file, const std::string& error);
55  };
58  struct BadImageSize : public All
59  {
60  BadImageSize(const std::string& file);
61  };
64  struct EndOfBuffer : public All
65  {
66  EndOfBuffer();
67  };
70  struct BadSeek : public All
71  {
72  BadSeek(double t);
73  };
74 
75  }
76 }
77 
85 template <typename T>
87 {
88  public:
95  DiskBuffer2(const std::vector<std::string>& names, double fps, VideoBufferFlags::OnEndOfBuffer eob = VideoBufferFlags::RepeatLastFrame);
96 
97  virtual ImageRef size() { return my_size; }
98 
102  virtual bool frame_pending() { return frame_ready; }
103 
104  virtual DiskBuffer2Frame<T>* get_frame();
105  virtual void put_frame(VideoFrame<T>* f);
106  virtual void seek_to(double t);
107 
111  {
112  end_of_buffer_behaviour = eob;
113  }
114 
115  virtual double frame_rate()
116  {
117  return frames_per_sec;
118  }
119 
120  protected:
121  ImageRef my_size;
122  int next_frame;
123  double start_time;
124  double time_per_frame, frames_per_sec;
125  bool frame_ready;
126  std::vector<std::string> file_names;
127  VideoBufferFlags::OnEndOfBuffer end_of_buffer_behaviour;
128 };
129 
130 //
131 // CONSTRUCTOR
132 //
133 template <typename T>
134 inline DiskBuffer2<T>::DiskBuffer2(const std::vector<std::string>& names, double fps, VideoBufferFlags::OnEndOfBuffer eob)
135  : LocalVideoBuffer<T>(VideoBufferType::NotLive)
136  , end_of_buffer_behaviour(eob)
137 {
138  frames_per_sec = fps;
139 
140  start_time = 0;
141  next_frame = 0;
142  time_per_frame = 1 / fps;
143 
144  file_names = names;
145 
146  if(file_names.size() == 0)
148 
149  Image<T> foo;
150  std::ifstream im;
151  im.open(names[0].c_str(), std::ios::in | std::ios::binary);
152 
153  if(!im.good())
154  throw Exceptions::DiskBuffer2::BadFile(names[0], errno);
155 
156  try
157  {
158  img_load(foo, im);
159  }
160  catch(Exceptions::Image_IO::All err)
161  {
162  throw Exceptions::DiskBuffer2::BadImage(names[0], err.what());
163  }
164 
165  my_size = foo.size();
166  frame_ready = true;
167 }
168 
169 //
170 // GET FRAME
171 //
172 template <typename T>
174 {
175  if(next_frame < 0)
176  next_frame = 0;
177 
178  if(!frame_pending())
180 
181  Image<T> foo(my_size);
182 
183  std::ifstream im_file(file_names[next_frame].c_str(), std::ios::in | std::ios::binary);
184 
185  if(!im_file.good())
186  throw Exceptions::DiskBuffer2::BadFile(file_names[next_frame], errno);
187 
188  try
189  {
190  img_load(foo, im_file);
191  }
193  {
194  throw Exceptions::DiskBuffer2::BadImage(file_names[next_frame], err.what());
195  }
196 
197  DiskBuffer2Frame<T>* vf = new DiskBuffer2Frame<T>(next_frame * time_per_frame + start_time, std::move(foo), file_names[next_frame]);
198 
199  next_frame++;
200 
201  if(next_frame > (int)file_names.size() - 1)
202  {
203  switch(end_of_buffer_behaviour)
204  {
206  next_frame = file_names.size() - 1;
207  break;
208 
210  frame_ready = false;
211  break;
212 
214  next_frame = 0;
215  break;
216  }
217  }
218 
219  return vf;
220 }
221 
222 //
223 // PUT FRAME
224 //
225 template <typename T>
227 {
228  //Check that the type is correct...
229  DiskBuffer2Frame<T>* db2f = dynamic_cast<DiskBuffer2Frame<T>*>(f);
230 
231  if(db2f == NULL)
233  else
234  delete db2f;
235 }
236 
237 //
238 // SEEK TO
239 //
240 template <typename T>
241 inline void DiskBuffer2<T>::seek_to(double t)
242 {
243  // t is in ms, but work in seconds
244  // round the answer to the nearest whole frame
245  int frameno = static_cast<int>((t - start_time) / time_per_frame + 0.5);
246  if(frameno < 0 || static_cast<unsigned int>(frameno) > (file_names.size() - 1))
248  next_frame = frameno;
249  frame_ready = true;
250 }
251 }
252 
253 #endif
OnEndOfBuffer
If it is a finite buffer (a video file, for example), what should happen when the end of the buffer i...
Definition: videobufferflags.h:14
An error occurred trying to open a file.
Definition: diskbuffer2.h:46
seek_to() was called for an invalid timestamp
Definition: diskbuffer2.h:70
All classes and functions are within the CVD namespace.
Definition: argb.h:6
ImageRef size() const
What is the size of this image?
Definition: image.h:557
Base class for all DiskBuffer2 exceptions.
Definition: diskbuffer2.h:34
Loop the buffer, so that the next time get_frame() is called it returns the first frame in the buffer...
Definition: videobufferflags.h:18
virtual ImageRef size()
The size of the VideoFrames returned by this buffer.
Definition: diskbuffer2.h:97
The file loaded was a different size from the first frame.
Definition: diskbuffer2.h:58
virtual double frame_rate()
What is the (expected) frame rate of this video buffer, in frames per second?
Definition: diskbuffer2.h:115
virtual void put_frame(VideoFrame< T > *f)
Tell the buffer that you are finished with this frame.
Definition: diskbuffer2.h:226
std::vector< std::string > globlist(const std::string &gl)
Make a list of strings from a UNIX-style pattern pathname expansion.
Definition: win32.cpp:41
virtual void on_end_of_buffer(VideoBufferFlags::OnEndOfBuffer eob)
What should the buffer do when it reaches the end of the list of files?
Definition: diskbuffer2.h:110
The semsntics of the videobuffer. See VideoFrame::type()
Definition: videobuffer.h:12
DiskBuffer2(const std::vector< std::string > &names, double fps, VideoBufferFlags::OnEndOfBuffer eob=VideoBufferFlags::RepeatLastFrame)
Construct a DiskBuffer2 from a vector of filenames.
Definition: diskbuffer2.h:134
Continue to return the final frame when get_frame() is called (with the same timestamp) ...
Definition: videobufferflags.h:16
Set the return value of frame_pending() to false and throw an EndOfBuffer exception if get_frame() is...
Definition: videobufferflags.h:17
Play a series of image files as a video stream.
Definition: diskbuffer2.h:86
An error occurred trying to read a file as an image.
Definition: diskbuffer2.h:52
Base class for a VideoBuffer which manages its own memory for each VideoFrame that it provides...
Definition: localvideobuffer.h:17
Definition: image_ref.h:29
The VideoBuffer was unable to successfully complete a VideoBuffer::put_frame() operation.
Definition: videobuffer.h:160
An empty list of filename strings was passed to the buffer.
Definition: diskbuffer2.h:40
Base class for all VideoBuffer exceptions.
Definition: videobuffer.h:153
A frame from a VideoBuffer.
Definition: videoframe.h:35
A frame from a DiskBuffer2.
Definition: diskbuffer2_frame.h:19
virtual bool frame_pending()
Is there another frame waiting in the buffer? By default, this always returns true, but if the VideoBufferFlags::OnEndOfBuffer setting is VideoBufferFlags::UnsetPending, this will return false after the last frame has been returned by get_frame()
Definition: diskbuffer2.h:102
A full image which manages its own data.
Definition: image.h:623
get_frame() was called when at the end of the buffer
Definition: diskbuffer2.h:64
virtual void seek_to(double t)
Go to a particular point in the video buffer (only implemented in buffers of recorded video) ...
Definition: diskbuffer2.h:241
Base class for all Image_IO exceptions.
Definition: load_and_save.h:27
virtual DiskBuffer2Frame< T > * get_frame()
Returns the next frame from the buffer. This function blocks until a frame is ready.
Definition: diskbuffer2.h:173