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