00001 #ifndef VIDEOSOURCE_H 00002 #define VIDEOSOURCE_H 00003 00004 #include <iostream> 00005 #include <sstream> 00006 #include <string> 00007 #include <vector> 00008 #include <cstdlib> 00009 00010 #include <cvd/config.h> 00011 00012 #include <cvd/readaheadvideobuffer.h> 00013 #include <cvd/colourspaces.h> 00014 00015 #include <cvd/diskbuffer2.h> 00016 #include <cvd/serverpushjpegbuffer.h> 00017 00018 #if CVD_HAVE_FFMPEG 00019 #include <cvd/videofilebuffer.h> 00020 #endif 00021 00022 #if CVD_INTERNAL_HAVE_V4LBUFFER 00023 #include <cvd/Linux/v4lbuffer.h> 00024 #endif 00025 00026 #if CVD_HAVE_V4L1BUFFER 00027 #include <cvd/Linux/v4l1buffer.h> 00028 #endif 00029 00030 #if CVD_HAVE_DVBUFFER 00031 #include <cvd/Linux/dvbuffer.h> 00032 #endif 00033 00034 #if CVD_HAVE_QTBUFFER 00035 #include <cvd/OSX/qtbuffer.h> 00036 #endif 00037 00038 namespace CVD { 00039 struct ParseException : public Exceptions::All 00040 { 00041 ParseException(const std::string& what_) { what = what_; } 00042 }; 00043 00044 struct VideoSourceException : public Exceptions::All 00045 { 00046 VideoSourceException(const std::string& what_) { what = what_; } 00047 }; 00048 00049 struct VideoSource 00050 { 00051 std::string protocol; 00052 std::string identifier; 00053 typedef std::vector<std::pair<std::string,std::string> > option_list; 00054 option_list options; 00055 }; 00056 00057 std::ostream& operator<<(std::ostream& out, const VideoSource& vs); 00058 00059 void parse(std::istream& in, VideoSource& vs); 00060 00061 template <class T> VideoBuffer<T>* makeJPEGStream(const std::string& filename) 00062 { 00063 using std::auto_ptr; 00064 using std::ifstream; 00065 00066 auto_ptr<ifstream> stream(new ifstream(filename.c_str())); 00067 00068 ServerPushJpegBuffer<T>* b = new ServerPushJpegBuffer<T>(*stream.get()); 00069 00070 auto_ptr<VideoBufferData> h(new VideoBufferDataAuto<ifstream>(stream.release())); 00071 00072 b->extra_data = h; 00073 return b; 00074 } 00075 00076 template <> inline VideoBuffer<vuy422> * makeJPEGStream(const std::string&) 00077 { 00078 throw VideoSourceException("DiskBuffer2 cannot handle type vuy422"); 00079 } 00080 00081 template <> inline VideoBuffer<yuv422> * makeJPEGStream(const std::string&) 00082 { 00083 throw VideoSourceException("DiskBuffer2 cannot handle type yuv422"); 00084 } 00085 void get_jpegstream_options(const VideoSource& vs, int& fps); 00086 00087 00088 00089 #ifdef CVD_HAVE_GLOB 00090 template <class T> VideoBuffer<T>* makeDiskBuffer2(const std::vector<std::string>& files, double fps, VideoBufferFlags::OnEndOfBuffer eob) 00091 { 00092 return new DiskBuffer2<T>(files, fps, eob); 00093 } 00094 template <> inline VideoBuffer<vuy422> * makeDiskBuffer2(const std::vector<std::string>& , double , VideoBufferFlags::OnEndOfBuffer ) 00095 { 00096 throw VideoSourceException("DiskBuffer2 cannot handle type vuy422"); 00097 } 00098 template <> inline VideoBuffer<yuv422> * makeDiskBuffer2(const std::vector<std::string>& , double , VideoBufferFlags::OnEndOfBuffer ) 00099 { 00100 throw VideoSourceException("DiskBuffer2 cannot handle type yuv422"); 00101 } 00102 #endif 00103 00104 void get_files_options(const VideoSource& vs, int& fps, int& ra_frames, VideoBufferFlags::OnEndOfBuffer& eob); 00105 00106 #if CVD_HAVE_V4L1BUFFER 00107 template <class T> VideoBuffer<T>* makeV4L1Buffer(const std::string&, const ImageRef& ) 00108 { 00109 throw VideoSourceException("V4L1Buffer cannot handle types other than byte, bayer, yuv422, Rgb<byte>"); 00110 } 00111 00112 template <> VideoBuffer<byte>* makeV4L1Buffer(const std::string& dev, const ImageRef& size); 00113 template <> VideoBuffer<bayer>* makeV4L1Buffer(const std::string& dev, const ImageRef& size); 00114 template <> VideoBuffer<yuv422>* makeV4L1Buffer(const std::string& dev, const ImageRef& size); 00115 template <> VideoBuffer<Rgb<byte> >* makeV4L1Buffer(const std::string& dev, const ImageRef& size); 00116 00117 void get_v4l1_options(const VideoSource& vs, ImageRef& size); 00118 00119 #endif 00120 00121 00122 #if CVD_INTERNAL_HAVE_V4LBUFFER 00123 template <class T> VideoBuffer<T>* makeV4LBuffer(const std::string& dev, const ImageRef& size, int input, bool interlaced, bool verbose) 00124 { 00125 throw VideoSourceException("V4LBuffer cannot handle types other than byte, bayer, yuv422, Rgb<byte>"); 00126 } 00127 00128 template <> VideoBuffer<byte>* makeV4LBuffer(const std::string& dev, const ImageRef& size, int input, bool interlaced, bool verbose); 00129 template <> VideoBuffer<bayer>* makeV4LBuffer(const std::string& dev, const ImageRef& size, int input, bool interlaced, bool verbose); 00130 template <> VideoBuffer<yuv422>* makeV4LBuffer(const std::string& dev, const ImageRef& size, int input, bool interlaced, bool verbose); 00131 template <> VideoBuffer<Rgb<byte> >* makeV4LBuffer(const std::string& dev, const ImageRef& size, int input, bool interlaced, bool verbose); 00132 template <> VideoBuffer<Rgb8>* makeV4LBuffer(const std::string& dev, const ImageRef& size, int input, bool interlaced, bool verbose); 00133 00134 void get_v4l2_options(const VideoSource& vs, ImageRef& size, int& input, bool& interlaced, bool& verbose); 00135 00136 #endif 00137 00138 00139 #if CVD_HAVE_FFMPEG 00140 template <class T> VideoBuffer<T>* makeVideoFileBuffer(const std::string& , VideoBufferFlags::OnEndOfBuffer ) 00141 { 00142 throw VideoSourceException("VideoFileBuffer cannot handle types other than byte, Rgb<byte>"); 00143 } 00144 00145 template <> VideoBuffer<byte>* makeVideoFileBuffer(const std::string& file, VideoBufferFlags::OnEndOfBuffer eob); 00146 template <> VideoBuffer<Rgb<byte> >* makeVideoFileBuffer(const std::string& file, VideoBufferFlags::OnEndOfBuffer eob); 00147 00148 void get_file_options(const VideoSource& vs, int& ra_frames, VideoBufferFlags::OnEndOfBuffer& eob); 00149 00150 #endif 00151 00152 #if CVD_HAVE_DVBUFFER 00153 template <class T> VideoBuffer<T>* makeDVBuffer2(int , int , int , int , int ) 00154 { 00155 throw VideoSourceException("DVBuffer2 cannot handle types other than byte, Rgb<byte>"); 00156 } 00157 00158 template <> VideoBuffer<byte>* makeDVBuffer2(int cam, int dmabufs, int bright, int exposure, int fps); 00159 template <> VideoBuffer<Rgb<byte> >* makeDVBuffer2(int cam, int dmabufs, int bright, int exposure, int fps); 00160 00161 void get_dc1394_options(const VideoSource& vs, int& dma_bufs, int& bright, int& exposure, int& fps); 00162 00163 #endif 00164 00165 #if CVD_HAVE_QTBUFFER 00166 template <class T> VideoBuffer<T> * makeQTBuffer( const ImageRef & , int , bool ) 00167 { 00168 throw VideoSourceException("QTBuffer cannot handle types other than vuy422"); 00169 } 00170 template <> VideoBuffer<vuy422> * makeQTBuffer( const ImageRef & size, int input, bool showsettings); 00171 template <> VideoBuffer<yuv422> * makeQTBuffer( const ImageRef & size, int input, bool showsettings); 00172 00173 void get_qt_options(const VideoSource & vs, ImageRef & size, bool & showsettings); 00174 #endif 00175 00176 template <class T> VideoBuffer<T>* open_video_source(const VideoSource& vs) 00177 { 00178 using std::auto_ptr; 00179 if(vs.protocol == "jpegstream") 00180 { 00181 int ra_frames=0; 00182 get_jpegstream_options(vs, ra_frames); 00183 00184 auto_ptr<VideoBuffer<T> > jpeg_buffer(makeJPEGStream<T>(vs.identifier)); 00185 00186 if(ra_frames == 0) 00187 return jpeg_buffer.release(); 00188 else 00189 { 00190 auto_ptr<VideoBuffer<T> > b(new ReadAheadVideoBuffer<T>(*(jpeg_buffer.get()), ra_frames)); 00191 auto_ptr<VideoBufferData> h(new VideoBufferDataAuto<VideoBuffer<T> >(jpeg_buffer.release())); 00192 b->extra_data = h; 00193 return b.release(); 00194 } 00195 } 00196 #if CVD_HAVE_GLOB 00197 else if (vs.protocol == "files") { 00198 int fps, ra_frames=0; 00199 VideoBufferFlags::OnEndOfBuffer eob; 00200 get_files_options(vs, fps, ra_frames, eob); 00201 VideoBuffer<T>* vb = makeDiskBuffer2<T>(globlist(vs.identifier), fps, eob); 00202 if (ra_frames) 00203 vb = new ReadAheadVideoBuffer<T>(*vb, ra_frames); 00204 return vb; 00205 } 00206 #endif 00207 00208 00209 #if CVD_HAVE_V4L1BUFFER 00210 else if (vs.protocol == "v4l1") { 00211 ImageRef size; 00212 get_v4l1_options(vs, size); 00213 return makeV4L1Buffer<T>(vs.identifier, size); 00214 } 00215 #endif 00216 #if CVD_INTERNAL_HAVE_V4LBUFFER 00217 else if (vs.protocol == "v4l2") { 00218 ImageRef size; 00219 int input; 00220 bool interlaced, verbose; 00221 get_v4l2_options(vs, size, input, interlaced, verbose); 00222 return makeV4LBuffer<T>(vs.identifier, size, input, interlaced, verbose); 00223 } 00224 #endif 00225 #if CVD_HAVE_DVBUFFER 00226 else if (vs.protocol == "dc1394") { 00227 int cam_no = atoi(vs.identifier.c_str()); 00228 int dma_bufs, bright, exposure, fps; 00229 get_dc1394_options(vs, dma_bufs, bright, exposure, fps); 00230 return makeDVBuffer2<T>(cam_no, dma_bufs, bright, exposure, fps); 00231 } 00232 #endif 00233 #if CVD_HAVE_FFMPEG 00234 else if (vs.protocol == "file") { 00235 int ra_frames = 0; 00236 VideoBufferFlags::OnEndOfBuffer eob; 00237 get_file_options(vs, ra_frames, eob); 00238 VideoBuffer<T>* vb = makeVideoFileBuffer<T>(vs.identifier, eob); 00239 if (ra_frames) 00240 vb = new ReadAheadVideoBuffer<T>(*vb, ra_frames); 00241 return vb; 00242 } 00243 #endif 00244 #if CVD_HAVE_QTBUFFER 00245 else if (vs.protocol == "qt") { 00246 ImageRef size; 00247 bool showsettings; 00248 int input = atoi(vs.identifier.c_str()); 00249 get_qt_options(vs, size, showsettings); 00250 return makeQTBuffer<T>(size, input, showsettings); 00251 } 00252 #endif 00253 else 00254 throw VideoSourceException("undefined video source protocol: '" + vs.protocol + "'\n\t valid protocols: " 00255 "jpegstream, " 00256 #if CVD_HAVE_FFMPEG 00257 "file, " 00258 #endif 00259 #if CVD_INTERNAL_HAVE_V4LBUFFER 00260 "v4l2, " 00261 #endif 00262 #if CVD_HAVE_V4L1BUFFER 00263 "v4l1, " 00264 #endif 00265 #if CVD_HAVE_DVBUFFER 00266 "dc1394, " 00267 #endif 00268 #if CVD_HAVE_QTBUFFER 00269 "qt, " 00270 #endif 00271 #ifdef CVD_HAVE_GLOB 00272 "files" 00273 #endif 00274 ); 00275 } 00276 00283 template <class T> VideoBuffer<T>* open_video_source(std::istream& in) 00284 { 00285 VideoSource vs; 00286 parse(in, vs); 00287 return open_video_source<T>(vs); 00288 } 00289 00396 template <class T> VideoBuffer<T>* open_video_source(const std::string& src) 00397 { 00398 std::istringstream in(src); 00399 return open_video_source<T>(in); 00400 } 00401 } 00402 00403 #endif