00001 #ifndef VIDEOSOURCE_H
00002 #define VIDEOSOURCE_H
00003
00004 #include <iostream>
00005 #include <fstream>
00006 #include <sstream>
00007 #include <string>
00008 #include <vector>
00009 #include <cstdlib>
00010
00011 #include <cvd/config.h>
00012
00013 #include <cvd/colourspacebuffer.h>
00014 #include <cvd/colourspaces.h>
00015 #include <cvd/videobufferwithdata.h>
00016 #include <cvd/readaheadvideobuffer.h>
00017
00018 #include <cvd/diskbuffer2.h>
00019 #include <cvd/serverpushjpegbuffer.h>
00020
00021 namespace CVD {
00022 struct ParseException : public Exceptions::All
00023 {
00024 ParseException(const std::string& what_) { what = what_; }
00025 };
00026
00027 struct VideoSourceException : public Exceptions::All
00028 {
00029 VideoSourceException(const std::string& what_) { what = what_; }
00030 };
00031
00032 struct VideoSource
00033 {
00034 std::string protocol;
00035 std::string identifier;
00036 typedef std::vector<std::pair<std::string,std::string> > option_list;
00037 option_list options;
00038 };
00039
00040 std::ostream& operator<<(std::ostream& out, const VideoSource& vs);
00041
00042 void parse(std::istream& in, VideoSource& vs);
00043 template <class T> VideoBuffer<T>* open_video_source(const std::string& src);
00044
00046
00047
00048
00049
00050 template<class T, bool Implemented = Pixel::DefaultConvertible<T>::is> struct makeJPEGStream
00051 {
00052 static VideoBuffer<T>* make(const std::string& filename)
00053 {
00054 using std::auto_ptr;
00055 using std::ifstream;
00056
00057 auto_ptr<std::ifstream> stream(new ifstream(filename.c_str()));
00058
00059 auto_ptr<VideoBuffer<T> > buf(static_cast<VideoBuffer<T>*>(new ServerPushJpegBuffer<T>(*stream)));
00060 return new VideoBufferWithData<T, std::ifstream>(buf, stream);
00061 }
00062 };
00063
00064 template<class T> struct makeJPEGStream<T, false>
00065 {
00066 static VideoBuffer<T>* make(const std::string&)
00067 {
00068 throw VideoSourceException("ServerPushJpegBuffer cannot handle type " + PNM::type_name<T>::name());
00069 }
00070 };
00071
00072 void get_jpegstream_options(const VideoSource& vs, int& fps);
00073
00074
00076
00077
00078
00079
00080 void get_colourspace_options(const VideoSource& vs, std::string& from);
00081
00082 template<class Out, class In, bool can_convert> struct MakeConverter{
00083 static VideoBuffer<Out>* make(const std::string& r)
00084 {
00085 std::auto_ptr<VideoBuffer<In> > buf = std::auto_ptr<VideoBuffer<In> > (static_cast<VideoBuffer<In>*>(open_video_source<In>(r)));
00086 std::auto_ptr<VideoBuffer<Out> > cvt = std::auto_ptr<VideoBuffer<Out> >(static_cast<VideoBuffer<Out>*>( new ColourspaceBuffer<Out, In>(*buf)));
00087 return new VideoBufferWithData<Out, VideoBuffer<In> >(cvt, buf);
00088 }
00089 };
00090
00091 template<class Out, class In> struct MakeConverter<Out, In, false>
00092 {
00093 static VideoBuffer<Out>* make(const std::string&)
00094 {
00095 throw VideoSourceException("ColorspaceBuffer cannot convert from " + PNM::type_name<In>::name() + " to " + PNM::type_name<Out>::name());
00096 }
00097 };
00098
00099 template<class T> struct MakeConverter<T, T, true>{
00100 static VideoBuffer<T>* make(const std::string& r)
00101 {
00102 return open_video_source<T>(r);
00103 }
00104 };
00105
00106 template<class Out, class In> VideoBuffer<Out>* makeConvertBufferBit(const std::string& r)
00107 {
00108 return MakeConverter<Out, In, IsConvertible<In, Out>::is >::make(r);
00109 };
00110
00111 template<class T> VideoBuffer<T>* makeColourspaceBuffer(const std::string& c, const std::string& r)
00112 {
00113
00114 if(c == "byte" || c == "mono" || c == "gray" || c == "grey")
00115 return makeConvertBufferBit<T, byte>(r);
00116 else if(c == "rgb<byte>" || c == "rgb")
00117 return makeConvertBufferBit<T, Rgb<byte> >(r);
00118 else if(c == "yuv411")
00119 return makeConvertBufferBit<T, yuv411>(r);
00120 else if(c == "yuv422")
00121 return makeConvertBufferBit<T, yuv422>(r);
00122 else if(c == "yuv420p")
00123 return makeConvertBufferBit<T, yuv420p>(r);
00124 else if(c == "vuy422")
00125 return makeConvertBufferBit<T, vuy422>(r);
00126 else if(c == "bayer_bggr")
00127 return makeConvertBufferBit<T, bayer_bggr>(r);
00128 else if(c == "bayer_gbrg")
00129 return makeConvertBufferBit<T, bayer_gbrg>(r);
00130 else if(c == "bayer_grbg")
00131 return makeConvertBufferBit<T, bayer_grbg>(r);
00132 else if(c == "bayer_rggb")
00133 return makeConvertBufferBit<T, bayer_rggb>(r);
00134 else if(c == "bayer_bggr16be")
00135 return makeConvertBufferBit<T, bayer_bggr16be>(r);
00136 else if(c == "bayer_gbrg16be")
00137 return makeConvertBufferBit<T, bayer_gbrg16be>(r);
00138 else if(c == "bayer_grbg16be")
00139 return makeConvertBufferBit<T, bayer_grbg16be>(r);
00140 else if(c == "bayer_rggb16be")
00141 return makeConvertBufferBit<T, bayer_rggb16be>(r);
00142 else
00143 throw VideoSourceException("ColorspaceBuffer cannot handle type " + c);
00144 }
00145
00147
00148
00149
00150
00151 #ifdef CVD_HAVE_GLOB
00152 template<class T, bool Implemented = Pixel::DefaultConvertible<T>::is> struct makeDiskBuffer2
00153 {
00154 static VideoBuffer<T>* make(const std::vector<std::string>& files, double fps, VideoBufferFlags::OnEndOfBuffer eob)
00155 {
00156 return new DiskBuffer2<T>(files, fps, eob);
00157 }
00158 };
00159
00160 template<class T> struct makeDiskBuffer2<T, false>
00161 {
00162 static VideoBuffer<T>* make(const std::vector<std::string>& , double , VideoBufferFlags::OnEndOfBuffer)
00163 {
00164 throw VideoSourceException("DiskBuffer2 cannot handle type " + PNM::type_name<T>::name());
00165 }
00166 };
00167
00168 #endif
00169
00170 void get_files_options(const VideoSource& vs, int& fps, int& ra_frames, VideoBufferFlags::OnEndOfBuffer& eob);
00171
00173
00174
00175
00176
00177 template <class T> VideoBuffer<T>* makeV4L1Buffer(const std::string&, const ImageRef& )
00178 {
00179 throw VideoSourceException("V4L1Buffer cannot handle types other than byte, bayer, yuv422, Rgb<byte>");
00180 }
00181
00182 template <> VideoBuffer<byte>* makeV4L1Buffer(const std::string& dev, const ImageRef& size);
00183 template <> VideoBuffer<bayer>* makeV4L1Buffer(const std::string& dev, const ImageRef& size);
00184 template <> VideoBuffer<yuv422>* makeV4L1Buffer(const std::string& dev, const ImageRef& size);
00185 template <> VideoBuffer<Rgb<byte> >* makeV4L1Buffer(const std::string& dev, const ImageRef& size);
00186
00187 void get_v4l1_options(const VideoSource& vs, ImageRef& size);
00188
00190
00191
00192
00193
00194 template <class T> VideoBuffer<T>* makeV4LBuffer(const std::string&, const ImageRef&, int, bool, bool)
00195 {
00196 throw VideoSourceException("V4LBuffer cannot handle types other than byte, bayer, yuv422, vuy422, Rgb<byte>");
00197 }
00198
00199 template <> VideoBuffer<byte>* makeV4LBuffer(const std::string& dev, const ImageRef& size, int input, bool interlaced, bool verbose);
00200 template <> VideoBuffer<bayer_grbg>* makeV4LBuffer(const std::string& dev, const ImageRef& size, int input, bool interlaced, bool verbose);
00201 template <> VideoBuffer<yuv422>* makeV4LBuffer(const std::string& dev, const ImageRef& size, int input, bool interlaced, bool verbose);
00202 template <> VideoBuffer<vuy422>* makeV4LBuffer(const std::string& dev, const ImageRef& size, int input, bool interlaced, bool verbose);
00203 template <> VideoBuffer<Rgb<byte> >* makeV4LBuffer(const std::string& dev, const ImageRef& size, int input, bool interlaced, bool verbose);
00204 template <> VideoBuffer<Rgb8>* makeV4LBuffer(const std::string& dev, const ImageRef& size, int input, bool interlaced, bool verbose);
00205
00206 void get_v4l2_options(const VideoSource& vs, ImageRef& size, int& input, bool& interlaced, bool& verbose);
00207
00208
00210
00211
00212
00213
00214 template <class T> VideoBuffer<T>* makeVideoFileBuffer(const std::string& , VideoBufferFlags::OnEndOfBuffer )
00215 {
00216 throw VideoSourceException("VideoFileBuffer cannot handle types other than byte, Rgb<byte>");
00217 }
00218
00219 template <> VideoBuffer<byte>* makeVideoFileBuffer(const std::string& file, VideoBufferFlags::OnEndOfBuffer eob);
00220 template <> VideoBuffer<Rgb<byte> >* makeVideoFileBuffer(const std::string& file, VideoBufferFlags::OnEndOfBuffer eob);
00221
00222 void get_file_options(const VideoSource& vs, int& ra_frames, VideoBufferFlags::OnEndOfBuffer& eob);
00223
00225
00226
00227
00228 template <class T> VideoBuffer<T>* makeDVBuffer2(int , ImageRef , float , ImageRef, bool, bool, int)
00229 {
00230 throw VideoSourceException("DVBuffer2 cannot handle " + PNM::type_name<T>::name());
00231 }
00232
00233 template <> VideoBuffer<byte>* makeDVBuffer2(int cam, ImageRef size, float fps, ImageRef offset, bool verbose, bool bus_reset, int format7_mode);
00234 template <> VideoBuffer<unsigned short>* makeDVBuffer2(int cam, ImageRef size, float fps, ImageRef offset, bool verbose, bool bus_reset, int format7_mode);
00235 template <> VideoBuffer<yuv411>* makeDVBuffer2(int cam, ImageRef size, float fps, ImageRef offset, bool verbose, bool bus_reset, int format7_mode);
00236 template <> VideoBuffer<yuv422>* makeDVBuffer2(int cam, ImageRef size, float fps, ImageRef offset, bool verbose, bool bus_reset, int format7_mode);
00237 template <> VideoBuffer<Rgb<byte> >* makeDVBuffer2(int cam, ImageRef size, float fps, ImageRef offset, bool verbose, bool bus_reset, int format7_mode);
00238 template <> VideoBuffer<bayer_bggr>* makeDVBuffer2(int cam, ImageRef size, float fps, ImageRef offset, bool verbose, bool bus_reset, int format7_mode);
00239 template <> VideoBuffer<bayer_gbrg>* makeDVBuffer2(int cam, ImageRef size, float fps, ImageRef offset, bool verbose, bool bus_reset, int format7_mode);
00240 template <> VideoBuffer<bayer_grbg>* makeDVBuffer2(int cam, ImageRef size, float fps, ImageRef offset, bool verbose, bool bus_reset, int format7_mode);
00241 template <> VideoBuffer<bayer_rggb>* makeDVBuffer2(int cam, ImageRef size, float fps, ImageRef offset, bool verbose, bool bus_reset, int format7_mode);
00242 template <> VideoBuffer<bayer_bggr16be>* makeDVBuffer2(int cam, ImageRef size, float fps, ImageRef offset, bool verbose, bool bus_reset, int format7_mode);
00243 template <> VideoBuffer<bayer_gbrg16be>* makeDVBuffer2(int cam, ImageRef size, float fps, ImageRef offset, bool verbose, bool bus_reset, int format7_mode);
00244 template <> VideoBuffer<bayer_grbg16be>* makeDVBuffer2(int cam, ImageRef size, float fps, ImageRef offset, bool verbose, bool bus_reset, int format7_mode);
00245 template <> VideoBuffer<bayer_rggb16be>* makeDVBuffer2(int cam, ImageRef size, float fps, ImageRef offset, bool verbose, bool bus_reset, int format7_mode);
00246
00247 void get_dc1394_options(const VideoSource& vs, ImageRef& size, float& fps, ImageRef& offset, bool& verbose, bool& bus_reset, int& format7_mode);
00248
00250
00251
00252
00253
00254 template <class T> VideoBuffer<T> * makeQTBuffer( const ImageRef & , int , bool, bool )
00255 {
00256 throw VideoSourceException("QTBuffer cannot handle " + PNM::type_name<T>::name());
00257 }
00258 template <> VideoBuffer<vuy422> * makeQTBuffer( const ImageRef & size, int input, bool showsettings, bool verbose);
00259 template <> VideoBuffer<yuv422> * makeQTBuffer( const ImageRef & size, int input, bool showsettings, bool verbose);
00260 template <> VideoBuffer<Rgb<byte> > * makeQTBuffer( const ImageRef & size, int input, bool showsettings, bool verbose);
00261
00262 void get_qt_options(const VideoSource & vs, ImageRef & size, bool & showsettings, bool & verbose);
00263
00264
00266
00267
00268
00269
00270 template <class T> VideoBuffer<T>* open_video_source(const VideoSource& vs)
00271 {
00272 using std::auto_ptr;
00273 if(vs.protocol == "jpegstream")
00274 {
00275 int ra_frames=0;
00276 get_jpegstream_options(vs, ra_frames);
00277
00278 auto_ptr<VideoBuffer<T> > jpeg_buffer(makeJPEGStream<T>::make(vs.identifier));
00279
00280 if(ra_frames == 0)
00281 return jpeg_buffer.release();
00282 else
00283 {
00284 auto_ptr<VideoBuffer<T> > b(new ReadAheadVideoBuffer<T>(*(jpeg_buffer.get()), ra_frames));
00285 return new VideoBufferWithData<T, VideoBuffer<T> >(b, jpeg_buffer);
00286 }
00287 }
00288 else if(vs.protocol == "colourspace")
00289 {
00290 std::string from = "byte";
00291 get_colourspace_options(vs, from);
00292
00293 return makeColourspaceBuffer<T>(from, vs.identifier);
00294 }
00295 else if (vs.protocol == "files") {
00296 int fps, ra_frames=0;
00297 VideoBufferFlags::OnEndOfBuffer eob;
00298 get_files_options(vs, fps, ra_frames, eob);
00299 VideoBuffer<T>* vb = makeDiskBuffer2<T>::make(globlist(vs.identifier), fps, eob);
00300 if (ra_frames)
00301 vb = new ReadAheadVideoBuffer<T>(*vb, ra_frames);
00302 return vb;
00303 }
00304 else if (vs.protocol == "v4l1") {
00305 ImageRef size;
00306 get_v4l1_options(vs, size);
00307 return makeV4L1Buffer<T>(vs.identifier, size);
00308 }
00309 else if (vs.protocol == "v4l2") {
00310 ImageRef size;
00311 int input;
00312 bool interlaced, verbose;
00313 get_v4l2_options(vs, size, input, interlaced, verbose);
00314 return makeV4LBuffer<T>(vs.identifier, size, input, interlaced, verbose);
00315 }
00316 else if (vs.protocol == "dc1394") {
00317 int cam_no = atoi(vs.identifier.c_str());
00318 ImageRef size, offset;
00319 float fps;
00320 bool verbose;
00321 bool bus_reset;
00322 int format7_mode;
00323 get_dc1394_options(vs, size, fps, offset, verbose, bus_reset, format7_mode);
00324 return makeDVBuffer2<T>(cam_no, size, fps, offset, verbose, bus_reset, format7_mode);
00325 }
00326 else if (vs.protocol == "file") {
00327 int ra_frames = 0;
00328 VideoBufferFlags::OnEndOfBuffer eob;
00329 get_file_options(vs, ra_frames, eob);
00330 VideoBuffer<T>* vb = makeVideoFileBuffer<T>(vs.identifier, eob);
00331 if (ra_frames)
00332 vb = new ReadAheadVideoBuffer<T>(*vb, ra_frames);
00333 return vb;
00334 }
00335 else if (vs.protocol == "qt") {
00336 ImageRef size;
00337 bool showsettings, verbose;
00338 int input = atoi(vs.identifier.c_str());
00339 get_qt_options(vs, size, showsettings, verbose);
00340 return makeQTBuffer<T>(size, input, showsettings, verbose);
00341 }
00342 else
00343 throw VideoSourceException("undefined video source protocol: '" + vs.protocol + "'\n\t valid protocols: "
00344 "colourspace, jpegstream, "
00345 "file, "
00346 "v4l2, "
00347 "v4l1, "
00348 "dc1394, "
00349 "qt, "
00350 "files"
00351 );
00352 }
00353
00360 template <class T> VideoBuffer<T>* open_video_source(std::istream& in)
00361 {
00362 VideoSource vs;
00363 parse(in, vs);
00364 return open_video_source<T>(vs);
00365 }
00366
00494 template <class T> VideoBuffer<T>* open_video_source(const std::string& src)
00495 {
00496 std::istringstream in(src);
00497 return open_video_source<T>(in);
00498 }
00499 }
00500
00501 #endif