CVD 0.8
|
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/deinterlacebuffer.h> 00015 #include <cvd/colourspaces.h> 00016 #include <cvd/videobufferwithdata.h> 00017 #include <cvd/readaheadvideobuffer.h> 00018 00019 #include <cvd/diskbuffer2.h> 00020 #include <cvd/serverpushjpegbuffer.h> 00021 00022 namespace CVD { 00023 struct ParseException : public Exceptions::All 00024 { 00025 ParseException(const std::string& what_) { what = what_; } 00026 }; 00027 00028 struct VideoSourceException : public Exceptions::All 00029 { 00030 VideoSourceException(const std::string& what_) { what = what_; } 00031 }; 00032 00033 struct VideoSource 00034 { 00035 std::string protocol; 00036 std::string identifier; 00037 typedef std::vector<std::pair<std::string,std::string> > option_list; 00038 option_list options; 00039 }; 00040 00041 std::ostream& operator<<(std::ostream& out, const VideoSource& vs); 00042 00043 void parse(std::istream& in, VideoSource& vs); 00044 template <class T> VideoBuffer<T>* open_video_source(const std::string& src); 00045 00047 // 00048 // Server push JPEG buffer 00049 // 00050 00051 template<class T, bool Implemented = Pixel::DefaultConvertible<T>::is> struct makeJPEGStream 00052 { 00053 static VideoBuffer<T>* make(const std::string& filename) 00054 { 00055 using std::auto_ptr; 00056 using std::ifstream; 00057 00058 auto_ptr<std::ifstream> stream(new ifstream(filename.c_str())); 00059 00060 auto_ptr<VideoBuffer<T> > buf(static_cast<VideoBuffer<T>*>(new ServerPushJpegBuffer<T>(*stream))); 00061 return new VideoBufferWithData<T, std::ifstream>(buf, stream); 00062 } 00063 }; 00064 00065 template<class T> struct makeJPEGStream<T, false> 00066 { 00067 static VideoBuffer<T>* make(const std::string&) 00068 { 00069 throw VideoSourceException("ServerPushJpegBuffer cannot handle type " + PNM::type_name<T>::name()); 00070 } 00071 }; 00072 00073 void get_jpegstream_options(const VideoSource& vs, int& fps); 00074 00075 00077 // 00078 // Deinterlace buffer 00079 // 00080 void get_deinterlace_options(const VideoSource& vs, DeinterlaceBufferFields::Fields& fields, bool&); 00081 00082 00083 namespace Internal{ 00084 template<class T> struct CanDeinterlace 00085 { 00086 static const bool can = std::numeric_limits<T>::is_specialized; 00087 }; 00088 00089 template<class T> struct CanDeinterlace<Rgb<T> > 00090 { 00091 static const bool can = CanDeinterlace<T>::can; 00092 }; 00093 }; 00094 00095 template<class T, bool B = Internal::CanDeinterlace<T>::can> struct makeDeinterlaceBuffer 00096 { 00097 static VideoBuffer<T>* make(DeinterlaceBufferFields::Fields f, bool& linedouble, const std::string& url) 00098 { 00099 std::auto_ptr<VideoBuffer<T> > source = std::auto_ptr<VideoBuffer<T> > (static_cast<VideoBuffer<T>*>(open_video_source<T>(url))); 00100 std::auto_ptr<VideoBuffer<T> > de_int = std::auto_ptr<VideoBuffer<T> > (static_cast<DeinterlaceBuffer<T>*>(new DeinterlaceBuffer<T>(*source, f, linedouble))); 00101 return new VideoBufferWithData<T, VideoBuffer<T> >(de_int, source); 00102 } 00103 }; 00104 00105 template<class T> struct makeDeinterlaceBuffer<T, 0> 00106 { 00107 static VideoBuffer<T>* make(DeinterlaceBufferFields::Fields, bool&, const std::string&) 00108 { 00109 throw VideoSourceException("DeinterlaceBuffer cannot handle input type"); 00110 } 00111 }; 00113 // 00114 // Colourspace conversion buffer 00115 // 00116 00117 void get_colourspace_options(const VideoSource& vs, std::string& from); 00118 00119 template<class Out, class In, bool can_convert> struct MakeConverter{ 00120 static VideoBuffer<Out>* make(const std::string& r) 00121 { 00122 std::auto_ptr<VideoBuffer<In> > buf = std::auto_ptr<VideoBuffer<In> > (static_cast<VideoBuffer<In>*>(open_video_source<In>(r))); 00123 std::auto_ptr<VideoBuffer<Out> > cvt = std::auto_ptr<VideoBuffer<Out> >(static_cast<VideoBuffer<Out>*>( new ColourspaceBuffer<Out, In>(*buf))); 00124 return new VideoBufferWithData<Out, VideoBuffer<In> >(cvt, buf); 00125 } 00126 }; 00127 00128 template<class Out, class In> struct MakeConverter<Out, In, false> 00129 { 00130 static VideoBuffer<Out>* make(const std::string&) 00131 { 00132 throw VideoSourceException("ColorspaceBuffer cannot convert from " + PNM::type_name<In>::name() + " to " + PNM::type_name<Out>::name()); 00133 } 00134 }; 00135 00136 template<class T> struct MakeConverter<T, T, true>{ 00137 static VideoBuffer<T>* make(const std::string& r) 00138 { 00139 return open_video_source<T>(r); 00140 } 00141 }; 00142 00143 template<class Out, class In> VideoBuffer<Out>* makeConvertBufferBit(const std::string& r) 00144 { 00145 return MakeConverter<Out, In, IsConvertible<In, Out>::is >::make(r); 00146 }; 00147 00148 template<class T> VideoBuffer<T>* makeColourspaceBuffer(const std::string& c, const std::string& r) 00149 { 00150 00151 if(c == "byte" || c == "mono" || c == "gray" || c == "grey") 00152 return makeConvertBufferBit<T, byte>(r); 00153 else if(c == "rgb<byte>" || c == "rgb") 00154 return makeConvertBufferBit<T, Rgb<byte> >(r); 00155 else if(c == "yuv411") 00156 return makeConvertBufferBit<T, yuv411>(r); 00157 else if(c == "yuv422") 00158 return makeConvertBufferBit<T, yuv422>(r); 00159 else if(c == "yuv420p") 00160 return makeConvertBufferBit<T, yuv420p>(r); 00161 else if(c == "vuy422") 00162 return makeConvertBufferBit<T, vuy422>(r); 00163 else if(c == "bayer_bggr") 00164 return makeConvertBufferBit<T, bayer_bggr>(r); 00165 else if(c == "bayer_gbrg") 00166 return makeConvertBufferBit<T, bayer_gbrg>(r); 00167 else if(c == "bayer_grbg") 00168 return makeConvertBufferBit<T, bayer_grbg>(r); 00169 else if(c == "bayer_rggb") 00170 return makeConvertBufferBit<T, bayer_rggb>(r); 00171 else if(c == "bayer_bggr16be") 00172 return makeConvertBufferBit<T, bayer_bggr16be>(r); 00173 else if(c == "bayer_gbrg16be") 00174 return makeConvertBufferBit<T, bayer_gbrg16be>(r); 00175 else if(c == "bayer_grbg16be") 00176 return makeConvertBufferBit<T, bayer_grbg16be>(r); 00177 else if(c == "bayer_rggb16be") 00178 return makeConvertBufferBit<T, bayer_rggb16be>(r); 00179 else 00180 throw VideoSourceException("ColorspaceBuffer cannot handle type " + c); 00181 } 00182 00184 // 00185 // DiskBuffer2 buffer 00186 // 00187 00188 // This has to be done with conditional compilation. 00189 00190 00191 #ifdef CVD_HAVE_GLOB 00192 template<class T, bool Implemented = Pixel::DefaultConvertible<T>::is> struct makeDiskBuffer2 00193 { 00194 static VideoBuffer<T>* make(const std::string& files, double fps, VideoBufferFlags::OnEndOfBuffer eob) 00195 { 00196 return new DiskBuffer2<T>(globlist(files), fps, eob); 00197 } 00198 }; 00199 00200 template<class T> struct makeDiskBuffer2<T, false> 00201 { 00202 static VideoBuffer<T>* make(const std::string& , double , VideoBufferFlags::OnEndOfBuffer) 00203 { 00204 throw VideoSourceException("DiskBuffer2 cannot handle type " + PNM::type_name<T>::name()); 00205 } 00206 }; 00207 00208 #else 00209 template<class T, bool Implemented = 0> struct makeDiskBuffer2 00210 { 00211 static VideoBuffer<T>* make(const std::string& , double , VideoBufferFlags::OnEndOfBuffer) 00212 { 00213 throw VideoSourceException("DiskBuffer2 (shell glob expansion) is not compiled in to libcvd."); 00214 } 00215 }; 00216 #endif 00217 00218 void get_files_options(const VideoSource& vs, int& fps, int& ra_frames, VideoBufferFlags::OnEndOfBuffer& eob); 00219 00221 // 00222 // v4l1 buffer 00223 // 00224 00225 template <class T> VideoBuffer<T>* makeV4L1Buffer(const std::string&, const ImageRef& ) 00226 { 00227 throw VideoSourceException("V4L1Buffer cannot handle types other than byte, bayer, yuv422, Rgb<byte>"); 00228 } 00229 00230 template <> VideoBuffer<byte>* makeV4L1Buffer(const std::string& dev, const ImageRef& size); 00231 template <> VideoBuffer<bayer>* makeV4L1Buffer(const std::string& dev, const ImageRef& size); 00232 template <> VideoBuffer<yuv422>* makeV4L1Buffer(const std::string& dev, const ImageRef& size); 00233 template <> VideoBuffer<Rgb<byte> >* makeV4L1Buffer(const std::string& dev, const ImageRef& size); 00234 00235 void get_v4l1_options(const VideoSource& vs, ImageRef& size); 00236 00238 // 00239 // v4l buffer 00240 // 00241 00242 template <class T> VideoBuffer<T>* makeV4LBuffer(const std::string&, const ImageRef&, int, bool, bool) 00243 { 00244 throw VideoSourceException("V4LBuffer cannot handle types other than byte, bayer, yuv422, vuy422, Rgb<byte>"); 00245 } 00246 00247 template <> VideoBuffer<byte>* makeV4LBuffer(const std::string& dev, const ImageRef& size, int input, bool interlaced, bool verbose); 00248 template <> VideoBuffer<bayer_grbg>* makeV4LBuffer(const std::string& dev, const ImageRef& size, int input, bool interlaced, bool verbose); 00249 template <> VideoBuffer<yuv422>* makeV4LBuffer(const std::string& dev, const ImageRef& size, int input, bool interlaced, bool verbose); 00250 template <> VideoBuffer<vuy422>* makeV4LBuffer(const std::string& dev, const ImageRef& size, int input, bool interlaced, bool verbose); 00251 template <> VideoBuffer<Rgb<byte> >* makeV4LBuffer(const std::string& dev, const ImageRef& size, int input, bool interlaced, bool verbose); 00252 template <> VideoBuffer<Rgb8>* makeV4LBuffer(const std::string& dev, const ImageRef& size, int input, bool interlaced, bool verbose); 00253 00254 void get_v4l2_options(const VideoSource& vs, ImageRef& size, int& input, bool& interlaced, bool& verbose); 00255 00256 00258 // 00259 // video file buffer 00260 // 00261 00262 template <class T> VideoBuffer<T>* makeVideoFileBuffer(const std::string& , VideoBufferFlags::OnEndOfBuffer ) 00263 { 00264 throw VideoSourceException("VideoFileBuffer cannot handle types other than byte, Rgb<byte>"); 00265 } 00266 00267 template <> VideoBuffer<byte>* makeVideoFileBuffer(const std::string& file, VideoBufferFlags::OnEndOfBuffer eob); 00268 template <> VideoBuffer<Rgb<byte> >* makeVideoFileBuffer(const std::string& file, VideoBufferFlags::OnEndOfBuffer eob); 00269 00270 void get_file_options(const VideoSource& vs, int& ra_frames, VideoBufferFlags::OnEndOfBuffer& eob); 00271 00273 // 00274 // DC1394 buffer 00275 // 00276 template <class T> VideoBuffer<T>* makeDVBuffer2(int , ImageRef , float , ImageRef, bool, bool, int) 00277 { 00278 throw VideoSourceException("DVBuffer2 cannot handle " + PNM::type_name<T>::name()); 00279 } 00280 00281 template <> VideoBuffer<byte>* makeDVBuffer2(int cam, ImageRef size, float fps, ImageRef offset, bool verbose, bool bus_reset, int format7_mode); 00282 template <> VideoBuffer<unsigned short>* makeDVBuffer2(int cam, ImageRef size, float fps, ImageRef offset, bool verbose, bool bus_reset, int format7_mode); 00283 template <> VideoBuffer<yuv411>* makeDVBuffer2(int cam, ImageRef size, float fps, ImageRef offset, bool verbose, bool bus_reset, int format7_mode); 00284 template <> VideoBuffer<yuv422>* makeDVBuffer2(int cam, ImageRef size, float fps, ImageRef offset, bool verbose, bool bus_reset, int format7_mode); 00285 template <> VideoBuffer<Rgb<byte> >* makeDVBuffer2(int cam, ImageRef size, float fps, ImageRef offset, bool verbose, bool bus_reset, int format7_mode); 00286 template <> VideoBuffer<bayer_bggr>* makeDVBuffer2(int cam, ImageRef size, float fps, ImageRef offset, bool verbose, bool bus_reset, int format7_mode); 00287 template <> VideoBuffer<bayer_gbrg>* makeDVBuffer2(int cam, ImageRef size, float fps, ImageRef offset, bool verbose, bool bus_reset, int format7_mode); 00288 template <> VideoBuffer<bayer_grbg>* makeDVBuffer2(int cam, ImageRef size, float fps, ImageRef offset, bool verbose, bool bus_reset, int format7_mode); 00289 template <> VideoBuffer<bayer_rggb>* makeDVBuffer2(int cam, ImageRef size, float fps, ImageRef offset, bool verbose, bool bus_reset, int format7_mode); 00290 template <> VideoBuffer<bayer_bggr16be>* makeDVBuffer2(int cam, ImageRef size, float fps, ImageRef offset, bool verbose, bool bus_reset, int format7_mode); 00291 template <> VideoBuffer<bayer_gbrg16be>* makeDVBuffer2(int cam, ImageRef size, float fps, ImageRef offset, bool verbose, bool bus_reset, int format7_mode); 00292 template <> VideoBuffer<bayer_grbg16be>* makeDVBuffer2(int cam, ImageRef size, float fps, ImageRef offset, bool verbose, bool bus_reset, int format7_mode); 00293 template <> VideoBuffer<bayer_rggb16be>* makeDVBuffer2(int cam, ImageRef size, float fps, ImageRef offset, bool verbose, bool bus_reset, int format7_mode); 00294 00295 void get_dc1394_options(const VideoSource& vs, ImageRef& size, float& fps, ImageRef& offset, bool& verbose, bool& bus_reset, int& format7_mode); 00296 00298 // 00299 // QuickTime buffer 00300 // 00301 00302 template <class T> VideoBuffer<T> * makeQTBuffer( const ImageRef & , int , bool, bool ) 00303 { 00304 throw VideoSourceException("QTBuffer cannot handle " + PNM::type_name<T>::name()); 00305 } 00306 template <> VideoBuffer<vuy422> * makeQTBuffer( const ImageRef & size, int input, bool showsettings, bool verbose); 00307 template <> VideoBuffer<yuv422> * makeQTBuffer( const ImageRef & size, int input, bool showsettings, bool verbose); 00308 template <> VideoBuffer<Rgb<byte> > * makeQTBuffer( const ImageRef & size, int input, bool showsettings, bool verbose); 00309 00310 void get_qt_options(const VideoSource & vs, ImageRef & size, bool & showsettings, bool & verbose); 00311 00312 00314 // 00315 // video source handler 00316 // 00317 00318 template <class T> VideoBuffer<T>* open_video_source(const VideoSource& vs) 00319 { 00320 using std::auto_ptr; 00321 if(vs.protocol == "jpegstream") 00322 { 00323 int ra_frames=0; 00324 get_jpegstream_options(vs, ra_frames); 00325 00326 auto_ptr<VideoBuffer<T> > jpeg_buffer(makeJPEGStream<T>::make(vs.identifier)); 00327 00328 if(ra_frames == 0) 00329 return jpeg_buffer.release(); 00330 else 00331 { 00332 auto_ptr<VideoBuffer<T> > b(new ReadAheadVideoBuffer<T>(*(jpeg_buffer.get()), ra_frames)); 00333 return new VideoBufferWithData<T, VideoBuffer<T> >(b, jpeg_buffer); 00334 } 00335 } 00336 else if(vs.protocol == "deinterlace") 00337 { 00338 DeinterlaceBufferFields::Fields f=DeinterlaceBufferFields::OddEven; 00339 bool linedouble=false; 00340 00341 get_deinterlace_options(vs, f, linedouble); 00342 00343 return makeDeinterlaceBuffer<T>::make(f, linedouble, vs.identifier); 00344 } 00345 else if(vs.protocol == "colourspace") 00346 { 00347 std::string from = "byte"; 00348 get_colourspace_options(vs, from); 00349 00350 return makeColourspaceBuffer<T>(from, vs.identifier); 00351 } 00352 else if (vs.protocol == "files") { 00353 int fps, ra_frames=0; 00354 VideoBufferFlags::OnEndOfBuffer eob; 00355 get_files_options(vs, fps, ra_frames, eob); 00356 VideoBuffer<T>* vb = makeDiskBuffer2<T>::make(vs.identifier, fps, eob); 00357 if (ra_frames) 00358 vb = new ReadAheadVideoBuffer<T>(*vb, ra_frames); 00359 return vb; 00360 } 00361 else if (vs.protocol == "v4l1") { 00362 ImageRef size; 00363 get_v4l1_options(vs, size); 00364 return makeV4L1Buffer<T>(vs.identifier, size); 00365 } 00366 else if (vs.protocol == "v4l2") { 00367 ImageRef size; 00368 int input; 00369 bool interlaced, verbose; 00370 get_v4l2_options(vs, size, input, interlaced, verbose); 00371 return makeV4LBuffer<T>(vs.identifier, size, input, interlaced, verbose); 00372 } 00373 else if (vs.protocol == "dc1394") { 00374 int cam_no = atoi(vs.identifier.c_str()); 00375 ImageRef size, offset; 00376 float fps; 00377 bool verbose; 00378 bool bus_reset; 00379 int format7_mode; 00380 get_dc1394_options(vs, size, fps, offset, verbose, bus_reset, format7_mode); 00381 return makeDVBuffer2<T>(cam_no, size, fps, offset, verbose, bus_reset, format7_mode); 00382 } 00383 else if (vs.protocol == "file") { 00384 int ra_frames = 0; 00385 VideoBufferFlags::OnEndOfBuffer eob; 00386 get_file_options(vs, ra_frames, eob); 00387 VideoBuffer<T>* vb = makeVideoFileBuffer<T>(vs.identifier, eob); 00388 if (ra_frames) 00389 vb = new ReadAheadVideoBuffer<T>(*vb, ra_frames); 00390 return vb; 00391 } 00392 else if (vs.protocol == "qt") { 00393 ImageRef size; 00394 bool showsettings, verbose; 00395 int input = atoi(vs.identifier.c_str()); 00396 get_qt_options(vs, size, showsettings, verbose); 00397 return makeQTBuffer<T>(size, input, showsettings, verbose); 00398 } 00399 else 00400 throw VideoSourceException("undefined video source protocol: '" + vs.protocol + "'\n\t valid protocols: " 00401 "colourspace, jpegstream, " 00402 "file, " 00403 "v4l2, " 00404 "v4l1, " 00405 "dc1394, " 00406 "qt, " 00407 "files" 00408 ); 00409 } 00410 00417 template <class T> VideoBuffer<T>* open_video_source(std::istream& in) 00418 { 00419 VideoSource vs; 00420 parse(in, vs); 00421 return open_video_source<T>(vs); 00422 } 00423 00561 template <class T> VideoBuffer<T>* open_video_source(const std::string& src) 00562 { 00563 std::istringstream in(src); 00564 return open_video_source<T>(in); 00565 } 00566 } 00567 00568 #endif