libcvd
videosource.h
1 #ifndef VIDEOSOURCE_H
2 #define VIDEOSOURCE_H
3 
4 #include <cstdlib>
5 #include <fstream>
6 #include <iostream>
7 #include <map>
8 #include <memory>
9 #include <sstream>
10 #include <string>
11 #include <vector>
12 
13 #include <cvd/config.h>
14 
15 #include <cvd/colourspacebuffer.h>
16 #include <cvd/colourspaces.h>
17 #include <cvd/deinterlacebuffer.h>
18 #include <cvd/video/skipbuffer.h>
19 #include <cvd/videobufferwithdata.h>
20 
21 #include <cvd/diskbuffer2.h>
22 #include <cvd/serverpushjpegbuffer.h>
23 
24 namespace CVD
25 {
27 {
28  ParseException(const std::string& what_)
29  : Exceptions::All(what_)
30  {
31  }
32 };
33 
35 {
36  VideoSourceException(const std::string& what_)
37  : Exceptions::All(what_)
38  {
39  }
40 };
41 
43 {
44  std::string protocol;
45  std::string identifier;
46  typedef std::vector<std::pair<std::string, std::string>> option_list;
47  option_list options;
48 };
49 
50 std::ostream& operator<<(std::ostream& out, const VideoSource& vs);
51 
52 void parse(std::istream& in, VideoSource& vs);
53 template <class T>
54 VideoBuffer<T>* open_video_source(const std::string& src);
55 
57 //
58 // Server push JPEG buffer
59 //
60 
61 template <class T, bool Implemented = Pixel::DefaultConvertible<T>::is>
63 {
64  static VideoBuffer<T>* make(const std::string& filename)
65  {
66  using std::ifstream;
67  using std::make_unique;
68  using std::unique_ptr;
69 
70  unique_ptr<std::ifstream> stream = std::make_unique<ifstream>(filename);
71  unique_ptr<VideoBuffer<T>> buf = make_unique<ServerPushJpegBuffer<T>>(*stream);
72 
73  return new VideoBufferWithData<T, std::ifstream>(buf, stream);
74  }
75 };
76 
77 template <class T>
78 struct makeJPEGStream<T, false>
79 {
80  static VideoBuffer<T>* make(const std::string&)
81  {
82  throw VideoSourceException("ServerPushJpegBuffer cannot handle type " + PNM::type_name<T>::name());
83  }
84 };
85 
86 void get_jpegstream_options(const VideoSource& vs, int& fps);
87 
89 //
90 // Deinterlace buffer
91 //
92 void get_deinterlace_options(const VideoSource& vs, DeinterlaceBufferFields::Fields& fields, bool&);
93 
94 namespace Internal
95 {
96  template <class T>
98  {
99  static const bool can = std::numeric_limits<T>::is_specialized;
100  };
101 
102  template <class T>
103  struct CanDeinterlace<Rgb<T>>
104  {
105  static const bool can = CanDeinterlace<T>::can;
106  };
107 };
108 
109 template <class T, bool B = Internal::CanDeinterlace<T>::can>
111 {
112  static VideoBuffer<T>* make(DeinterlaceBufferFields::Fields f, bool& linedouble, const std::string& url)
113  {
114  auto source = std::unique_ptr<VideoBuffer<T>>(open_video_source<T>(url));
115  std::unique_ptr<VideoBuffer<T>> buf = std::make_unique<DeinterlaceBuffer<T>>(*source, f, linedouble);
116  return new VideoBufferWithData<T, VideoBuffer<T>>(buf, source);
117  }
118 };
119 
120 template <class T>
122 {
123  static VideoBuffer<T>* make(DeinterlaceBufferFields::Fields, bool&, const std::string&)
124  {
125  throw VideoSourceException("DeinterlaceBuffer cannot handle input type");
126  }
127 };
128 
130 //
131 // Colourspace conversion buffer
132 //
133 
134 void get_skip_options(const VideoSource& vs, bool& do_seek, double& seek, int& drop);
135 template <class T>
137 {
138  static VideoBuffer<T>* make(bool do_seek, double seek, int drop, const std::string& url)
139  {
140  auto source = std::unique_ptr<VideoBuffer<T>>(open_video_source<T>(url));
141  std::unique_ptr<VideoBuffer<T>> buf = std::make_unique<SkipBuffer<T>>(*source, do_seek, seek, drop);
142  return new VideoBufferWithData<T, VideoBuffer<T>>(buf, source);
143  }
144 };
145 
147 //
148 // Colourspace conversion buffer
149 //
150 
151 void get_colourspace_options(const VideoSource& vs, std::string& from);
152 
153 template <class Out, class In, bool can_convert>
155 {
156  static VideoBuffer<Out>* make(const std::string& r)
157  {
158  std::unique_ptr<VideoBuffer<In>> buf { open_video_source<In>(r) };
159 
160  std::unique_ptr<VideoBuffer<Out>> cvt = std::make_unique<ColourspaceBuffer<Out, In>>(*buf);
161  return new VideoBufferWithData<Out, VideoBuffer<In>>(cvt, buf);
162  }
163 };
164 
165 template <class Out, class In>
166 struct MakeConverter<Out, In, false>
167 {
168  static VideoBuffer<Out>* make(const std::string&)
169  {
170  throw VideoSourceException("ColorspaceBuffer cannot convert from " + PNM::type_name<In>::name() + " to " + PNM::type_name<Out>::name());
171  }
172 };
173 
174 template <class T>
175 struct MakeConverter<T, T, true>
176 {
177  static VideoBuffer<T>* make(const std::string& r)
178  {
179  return open_video_source<T>(r);
180  }
181 };
182 
183 template <class Out, class In>
184 VideoBuffer<Out>* makeConvertBufferBit(const std::string& r)
185 {
187 };
188 
189 template <class T>
190 VideoBuffer<T>* makeColourspaceBuffer(const std::string& c, const std::string& r)
191 {
192 
193  if(c == "byte" || c == "mono" || c == "gray" || c == "grey")
194  return makeConvertBufferBit<T, byte>(r);
195  else if(c == "rgb<byte>" || c == "rgb")
196  return makeConvertBufferBit<T, Rgb<byte>>(r);
197  //else if(c == "yuv411")
198  //return makeConvertBufferBit<T, yuv411>(r);
199  else if(c == "yuv422")
200  return makeConvertBufferBit<T, yuv422>(r);
201  else if(c == "yuv420p")
202  return makeConvertBufferBit<T, yuv420p>(r);
203  else if(c == "vuy422")
204  return makeConvertBufferBit<T, vuy422>(r);
205  else if(c == "bayer_bggr")
206  return makeConvertBufferBit<T, bayer_bggr>(r);
207  else if(c == "bayer_gbrg")
208  return makeConvertBufferBit<T, bayer_gbrg>(r);
209  else if(c == "bayer_grbg")
210  return makeConvertBufferBit<T, bayer_grbg>(r);
211  else if(c == "bayer_rggb")
212  return makeConvertBufferBit<T, bayer_rggb>(r);
213  else if(c == "bayer_bggr16be")
214  return makeConvertBufferBit<T, bayer_bggr16be>(r);
215  else if(c == "bayer_gbrg16be")
216  return makeConvertBufferBit<T, bayer_gbrg16be>(r);
217  else if(c == "bayer_grbg16be")
218  return makeConvertBufferBit<T, bayer_grbg16be>(r);
219  else if(c == "bayer_rggb16be")
220  return makeConvertBufferBit<T, bayer_rggb16be>(r);
221  else
222  throw VideoSourceException("ColorspaceBuffer cannot handle type " + c);
223 }
224 
226 //
227 // DiskBuffer2 buffer
228 //
229 
230 // This has to be done with conditional compilation.
231 
232 #ifdef CVD_HAVE_GLOB
233 template <class T, bool Implemented = Pixel::DefaultConvertible<T>::is>
234 struct makeDiskBuffer2
235 {
236  static VideoBuffer<T>* make(const std::string& files, double fps, VideoBufferFlags::OnEndOfBuffer eob)
237  {
238  return new DiskBuffer2<T>(globlist(files), fps, eob);
239  }
240 };
241 
242 template <class T>
243 struct makeDiskBuffer2<T, false>
244 {
245  static VideoBuffer<T>* make(const std::string&, double, VideoBufferFlags::OnEndOfBuffer)
246  {
247  throw VideoSourceException("DiskBuffer2 cannot handle type " + PNM::type_name<T>::name());
248  }
249 };
250 
251 #else
252 template <class T, bool Implemented = 0>
254 {
255  static VideoBuffer<T>* make(const std::string&, double, VideoBufferFlags::OnEndOfBuffer)
256  {
257  throw VideoSourceException("DiskBuffer2 (shell glob expansion) is not compiled in to libcvd.");
258  }
259 };
260 #endif
261 
262 void get_files_options(const VideoSource& vs, int& fps, VideoBufferFlags::OnEndOfBuffer& eob);
263 
265 //
266 // v4l buffer
267 //
268 
269 template <class T>
270 VideoBuffer<T>* makeV4LBuffer(const std::string&, const ImageRef&, int, bool, bool)
271 {
272  throw VideoSourceException("V4LBuffer cannot handle types other than byte, bayer, yuv422, vuy422, Rgb<byte>");
273 }
274 
275 template <>
276 VideoBuffer<byte>* makeV4LBuffer(const std::string& dev, const ImageRef& size, int input, bool interlaced, bool verbose);
277 template <>
278 VideoBuffer<bayer_grbg>* makeV4LBuffer(const std::string& dev, const ImageRef& size, int input, bool interlaced, bool verbose);
279 template <>
280 VideoBuffer<yuv422>* makeV4LBuffer(const std::string& dev, const ImageRef& size, int input, bool interlaced, bool verbose);
281 template <>
282 VideoBuffer<vuy422>* makeV4LBuffer(const std::string& dev, const ImageRef& size, int input, bool interlaced, bool verbose);
283 template <>
284 VideoBuffer<yuv420p>* makeV4LBuffer(const std::string& dev, const ImageRef& size, int input, bool interlaced, bool verbose);
285 template <>
286 VideoBuffer<Rgb<byte>>* makeV4LBuffer(const std::string& dev, const ImageRef& size, int input, bool interlaced, bool verbose);
287 template <>
288 VideoBuffer<Rgb8>* makeV4LBuffer(const std::string& dev, const ImageRef& size, int input, bool interlaced, bool verbose);
289 
290 void get_v4l2_options(const VideoSource& vs, ImageRef& size, int& input, bool& interlaced, bool& verbose);
291 
293 //
294 // uvc buffer
295 //
296 
297 template <class T>
298 VideoBuffer<T>* makeUVCBuffer(const std::string&, const ImageRef&, double, bool, bool)
299 {
300  throw VideoSourceException("UVCBuffer cannot handle types other than yuv422, or Rgb<byte>");
301 }
302 
303 template <>
304 VideoBuffer<yuv422>* makeUVCBuffer(const std::string& dev, const ImageRef& size, double fps, bool mjpeg, bool verbose);
305 template <>
306 VideoBuffer<Rgb<byte>>* makeUVCBuffer(const std::string& dev, const ImageRef& size, double fps, bool mjpeg, bool verbose);
307 
308 void get_uvc_options(const VideoSource& vs, ImageRef& size, double& fps, bool& mjpeg, bool& verbose);
309 
311 //
312 // video file buffer
313 //
314 
315 template <class T>
316 VideoBuffer<T>* makeVideoFileBuffer(const std::string&, VideoBufferFlags::OnEndOfBuffer, bool, const std::string&, const std::map<std::string, std::string>&)
317 {
318  throw VideoSourceException("VideoFileBuffer cannot handle types other than byte, Rgb<byte>");
319 }
320 
321 template <>
322 VideoBuffer<byte>* makeVideoFileBuffer(const std::string& file, VideoBufferFlags::OnEndOfBuffer eob, bool verbose, const std::string& formatname, const std::map<std::string, std::string>&);
323 template <>
324 VideoBuffer<Rgb<byte>>* makeVideoFileBuffer(const std::string& file, VideoBufferFlags::OnEndOfBuffer eob, bool verbose, const std::string& formatname, const std::map<std::string, std::string>&);
325 
326 void get_file_options(const VideoSource& vs, VideoBufferFlags::OnEndOfBuffer& eob, bool& verbose, std::string& formatname, std::map<std::string, std::string>&);
327 
329 //
330 // DC1394 buffer
331 //
332 template <class T>
333 VideoBuffer<T>* makeDVBuffer2(int, ImageRef, float, ImageRef, bool, bool, int)
334 {
335  throw VideoSourceException("DVBuffer2 cannot handle " + PNM::type_name<T>::name());
336 }
337 
338 template <>
339 VideoBuffer<byte>* makeDVBuffer2(int cam, ImageRef size, float fps, ImageRef offset, bool verbose, bool bus_reset, int format7_mode);
340 template <>
341 VideoBuffer<unsigned short>* makeDVBuffer2(int cam, ImageRef size, float fps, ImageRef offset, bool verbose, bool bus_reset, int format7_mode);
342 //template <> VideoBuffer<yuv411>* makeDVBuffer2(int cam, ImageRef size, float fps, ImageRef offset, bool verbose, bool bus_reset, int format7_mode);
343 template <>
344 VideoBuffer<yuv422>* makeDVBuffer2(int cam, ImageRef size, float fps, ImageRef offset, bool verbose, bool bus_reset, int format7_mode);
345 template <>
346 VideoBuffer<Rgb<byte>>* makeDVBuffer2(int cam, ImageRef size, float fps, ImageRef offset, bool verbose, bool bus_reset, int format7_mode);
347 template <>
348 VideoBuffer<bayer_bggr>* makeDVBuffer2(int cam, ImageRef size, float fps, ImageRef offset, bool verbose, bool bus_reset, int format7_mode);
349 template <>
350 VideoBuffer<bayer_gbrg>* makeDVBuffer2(int cam, ImageRef size, float fps, ImageRef offset, bool verbose, bool bus_reset, int format7_mode);
351 template <>
352 VideoBuffer<bayer_grbg>* makeDVBuffer2(int cam, ImageRef size, float fps, ImageRef offset, bool verbose, bool bus_reset, int format7_mode);
353 template <>
354 VideoBuffer<bayer_rggb>* makeDVBuffer2(int cam, ImageRef size, float fps, ImageRef offset, bool verbose, bool bus_reset, int format7_mode);
355 template <>
356 VideoBuffer<bayer_bggr16be>* makeDVBuffer2(int cam, ImageRef size, float fps, ImageRef offset, bool verbose, bool bus_reset, int format7_mode);
357 template <>
358 VideoBuffer<bayer_gbrg16be>* makeDVBuffer2(int cam, ImageRef size, float fps, ImageRef offset, bool verbose, bool bus_reset, int format7_mode);
359 template <>
360 VideoBuffer<bayer_grbg16be>* makeDVBuffer2(int cam, ImageRef size, float fps, ImageRef offset, bool verbose, bool bus_reset, int format7_mode);
361 template <>
362 VideoBuffer<bayer_rggb16be>* makeDVBuffer2(int cam, ImageRef size, float fps, ImageRef offset, bool verbose, bool bus_reset, int format7_mode);
363 
364 void get_dc1394_options(const VideoSource& vs, ImageRef& size, float& fps, ImageRef& offset, bool& verbose, bool& bus_reset, int& format7_mode);
365 
367 //
368 // video source handler
369 //
370 
371 template <class T>
373 {
374  if(vs.protocol == "jpegstream")
375  {
376  return makeJPEGStream<T>::make(vs.identifier);
377  }
378  else if(vs.protocol == "deinterlace")
379  {
381  bool linedouble = false;
382 
383  get_deinterlace_options(vs, f, linedouble);
384 
385  return makeDeinterlaceBuffer<T>::make(f, linedouble, vs.identifier);
386  }
387  else if(vs.protocol == "skip")
388  {
389  double seek = 0;
390  bool do_seek = 0;
391  int drop = 0;
392 
393  get_skip_options(vs, do_seek, seek, drop);
394 
395  return makeSkipBuffer<T>::make(do_seek, seek, drop, vs.identifier);
396  }
397  else if(vs.protocol == "colourspace" || vs.protocol == "colorspace")
398  {
399  std::string from = "byte";
400  get_colourspace_options(vs, from);
401 
402  return makeColourspaceBuffer<T>(from, vs.identifier);
403  }
404  else if(vs.protocol == "files")
405  {
406  int fps;
408  get_files_options(vs, fps, eob);
409  return makeDiskBuffer2<T>::make(vs.identifier, fps, eob);
410  }
411  else if(vs.protocol == "v4l2")
412  {
413  ImageRef size;
414  int input;
415  bool interlaced, verbose;
416  get_v4l2_options(vs, size, input, interlaced, verbose);
417  return makeV4LBuffer<T>(vs.identifier, size, input, interlaced, verbose);
418  }
419  else if(vs.protocol == "uvc")
420  {
421  ImageRef size;
422  bool mjpeg, verbose;
423  double fps;
424  get_uvc_options(vs, size, fps, mjpeg, verbose);
425  return makeUVCBuffer<T>(vs.identifier, size, fps, mjpeg, verbose);
426  }
427  else if(vs.protocol == "dc1394")
428  {
429  int cam_no = atoi(vs.identifier.c_str());
430  ImageRef size, offset;
431  float fps;
432  bool verbose;
433  bool bus_reset;
434  int format7_mode;
435  get_dc1394_options(vs, size, fps, offset, verbose, bus_reset, format7_mode);
436  return makeDVBuffer2<T>(cam_no, size, fps, offset, verbose, bus_reset, format7_mode);
437  }
438  else if(vs.protocol == "file" || vs.protocol == "ffmpeg")
439  {
441  bool verbose = 0;
442  std::string formatname = "";
443  std::map<std::string, std::string> opts;
444  get_file_options(vs, eob, verbose, formatname, opts);
445  return makeVideoFileBuffer<T>(vs.identifier, eob, verbose, formatname, opts);
446  }
447  else
448  throw VideoSourceException("undefined video source protocol: '" + vs.protocol + "'\n\t valid protocols: "
449  "colourspace, jpegstream, "
450  "file, "
451  "v4l2, "
452  "dc1394, "
453  "files, "
454  "uvc");
455 }
456 
463 template <class T>
465 {
466  VideoSource vs;
467  parse(in, vs);
468  return open_video_source<T>(vs);
469 }
470 
611 template <class T>
612 VideoBuffer<T>* open_video_source(const std::string& src)
613 {
614  std::istringstream in(src);
615  return open_video_source<T>(in);
616 }
617 }
618 
619 #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
A colour consisting of red, green and blue components.
Definition: rgb.h:25
All classes and functions are within the CVD namespace.
Definition: argb.h:6
Definition: videosource.h:136
Definition: videosource.h:34
Base class for objects which provide a typed video stream.
Definition: videobuffer.h:88
Definition: videosource.h:26
VideoBuffer< T > * open_video_source(const std::string &src)
opens a video device described by a video source url.
Definition: videosource.h:612
Definition: videosource.h:97
Definition: videosource.h:154
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
Play a series of image files as a video stream.
Definition: diskbuffer2.h:86
Base class for all CVD exceptions.
Definition: exceptions.h:15
Definition: videosource.h:253
Definition: image_ref.h:29
Definition: videosource.h:110
Both fields, presenting the odd lines from each frame first.
Definition: deinterlacebuffer.h:70
Definition: videosource.h:42
Definition: name_builtin_types.h:11
Definition: videosource.h:62
Fields
Definition: deinterlacebuffer.h:66
Certain video buffers, especially the decorator classes, and buffers such as ServerPushJpegBuffer hav...
Definition: videobufferwithdata.h:17