00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef CVD_V4LBUFFER_H
00023 #define CVD_V4LBUFFER_H
00024
00025 #include <cvd/config.h>
00026
00027 #include <vector>
00028
00029 #ifdef CVD_INTERNAL_HAVE_STRANGE_V4L2
00030 #include <videodevx/videodev.h>
00031 #else
00032 #include <linux/videodev.h>
00033 #endif
00034
00035
00036
00037 #include <cvd/videobuffer.h>
00038 #include <cvd/byte.h>
00039 #include <cvd/rgb.h>
00040 #include <cvd/rgb8.h>
00041 #include <cvd/timer.h>
00042 #include <cvd/colourspaces.h>
00043 #include <fcntl.h>
00044
00045 namespace CVD {
00046
00047 namespace Exceptions
00048 {
00050 namespace V4LBuffer
00051 {
00053 struct All: public CVD::Exceptions::VideoBuffer::All
00054 {
00055 };
00058 struct DeviceOpen: public All {DeviceOpen(std::string dev);
00059 };
00062 struct DeviceSetup: public All {DeviceSetup(std::string dev, std::string action);
00063 };
00066 struct PutFrame: public All {PutFrame(std::string dev, std::string msg);
00067 };
00070 struct GetFrame: public All {GetFrame(std::string dev, std::string msg);
00071 };
00072 }
00073 }
00074
00075 namespace V4L
00076 {
00077 #ifndef DOXYGEN_IGNORE_INTERNAL
00078 template<class C> struct format;
00079
00080 template<> struct format<byte>
00081 {
00082 static const unsigned int v4l2_fmt = V4L2_PIX_FMT_GREY;
00083 static const unsigned int v4l1_palette = VIDEO_PALETTE_GREY;
00084 };
00085
00086 #ifdef V4L2_PIX_FMT_SBGGR8
00087 template<> struct format<bayer>
00088 {
00089 static const unsigned int v4l2_fmt = V4L2_PIX_FMT_SBGGR8;
00090 static const unsigned int v4l1_palette = VIDEO_PALETTE_RAW;
00091 };
00092 #endif
00093
00094 template<> struct format<yuv422>
00095 {
00096 static const unsigned int v4l2_fmt = V4L2_PIX_FMT_YUYV;
00097 static const unsigned int v4l1_palette = VIDEO_PALETTE_YUV422;
00098 };
00099
00100 template<> struct format<yuv420p>
00101 {
00102 static const unsigned int v4l2_fmt = V4L2_PIX_FMT_YUV420;
00103 static const unsigned int v4l1_palette = VIDEO_PALETTE_YUV420P;
00104 };
00105
00106 template<> struct format<Rgb<byte> >
00107 {
00108 static const unsigned int v4l2_fmt = V4L2_PIX_FMT_RGB24;
00109 static const unsigned int v4l1_palette = VIDEO_PALETTE_RGB24;
00110 };
00111
00112 template<> struct format<Rgb8>
00113 {
00114 static const unsigned int v4l2_fmt = V4L2_PIX_FMT_RGB32;
00115 static const unsigned int v4l1_palette = VIDEO_PALETTE_RGB32;
00116 };
00117 #endif
00118
00119 class V4L2Client
00120 {
00121 public:
00122 struct Buffer {
00123 int id;
00124 unsigned char* data;
00125 double when;
00126 };
00127 V4L2Client(int fd, unsigned int fmt, ImageRef size, int input, bool fields, int frame_per_second, bool verbose);
00128 ImageRef getSize();
00129 Buffer getFrame();
00130 void releaseFrame(int id);
00131 double getRate();
00132 bool pendingFrame();
00133 virtual ~V4L2Client();
00134 int num_buffers()
00135 {
00136 return num_bufs;
00137 }
00138 private:
00139 int num_bufs;
00140 struct State;
00141 State* state;
00142 };
00143
00144 class V4L1Client;
00145
00146 };
00147
00148
00152 template <class T> class V4LBuffer : public VideoBuffer<T>
00153 {
00154 public:
00155 V4LBuffer(const std::string & dev, ImageRef size, int input=-1, bool fields=false, int frames_per_second=0, bool verbose=0)
00156 :VideoBuffer<T>(VideoBufferType::Flushable),
00157 devname(dev)
00158 {
00159 int device = open(devname.c_str(), O_RDWR | O_NONBLOCK);
00160 if (device == -1)
00161 throw Exceptions::V4LBuffer::DeviceOpen(dev);
00162 try {
00163 v4l2 = new V4L::V4L2Client(device, V4L::format<T>::v4l2_fmt, size, input, fields,frames_per_second, verbose);
00164 }
00165 catch (std::string& s) {
00166 v4l2 = 0;
00167 throw Exceptions::V4LBuffer::DeviceSetup(devname, "V4L2: "+s);
00168 }
00169 v4l1 = 0;
00170 }
00171 virtual ImageRef size() { return v4l2 ? v4l2->getSize() : ImageRef(-1,-1); }
00172 virtual VideoFrame<T> * get_frame() {
00173 if (v4l2) {
00174 try {
00175 V4L::V4L2Client::Buffer buffer = v4l2->getFrame();
00176 return new V4LFrame(buffer.id, buffer.when, buffer.data, v4l2->getSize());
00177 } catch (std::string& s) {
00178 throw Exceptions::V4LBuffer::GetFrame(devname, "V4L2: "+s);
00179 }
00180 } else {
00181 throw Exceptions::V4LBuffer::GetFrame(devname, "V4L1 not yet supported by V4LBuffer");
00182 }
00183 }
00184 virtual void put_frame(VideoFrame<T>* f) {
00185 V4LFrame* vf = dynamic_cast<V4LFrame*>(f);
00186 if (vf == 0)
00187 throw Exceptions::V4LBuffer::PutFrame(devname, "Invalid VideoFrame");
00188 int id = vf->id;
00189 delete vf;
00190 if (v4l2) {
00191 try {
00192 v4l2->releaseFrame(id);
00193 } catch (std::string& s) {
00194 throw Exceptions::V4LBuffer::PutFrame(devname, "V4L2: "+s);
00195 }
00196 } else {
00197 throw Exceptions::V4LBuffer::PutFrame(devname, "V4L1 not yet supported by V4LBuffer");
00198 }
00199 }
00200 virtual bool frame_pending() { return v4l2->pendingFrame(); }
00201 virtual double frame_rate() { return v4l2 ? v4l2->getRate() : 0.0; }
00202 virtual ~V4LBuffer() {
00203 if (v4l2)
00204 delete v4l2;
00205 }
00206
00207 int num_buffers()
00208 {
00209 if (v4l2) {
00210 return v4l2->num_buffers();
00211 } else {
00212 throw Exceptions::V4LBuffer::PutFrame(devname, "V4L1 not yet supported by V4LBuffer");
00213 }
00214 }
00215
00216 const std::string & device_name() const { return devname; }
00217
00218 private:
00219 struct V4LFrame : public VideoFrame<T> {
00220 V4LFrame(int i, double t, void* data, ImageRef size) : VideoFrame<T>(t,reinterpret_cast<T*>(data),size), id(i) {}
00221 int id;
00222 friend class V4LBuffer<T>;
00223 };
00224 std::string devname;
00225 V4L::V4L2Client* v4l2;
00226 V4L::V4L1Client* v4l1;
00227 V4LBuffer( V4LBuffer& copyof ) {}
00228 void operator=( V4LBuffer& copyof ) {}
00229 };
00230
00231 };
00232 #endif