cvd/Linux/v4lbuffer.h

00001 /*
00002     This file is part of the CVD Library.
00003 
00004     Copyright (C) 2005 The Authors
00005 
00006     This library is free software; you can redistribute it and/or
00007     modify it under the terms of the GNU Lesser General Public
00008     License as published by the Free Software Foundation; either
00009     version 2.1 of the License, or (at your option) any later version.
00010 
00011     This library is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014     Lesser General Public License for more details.
00015 
00016     You should have received a copy of the GNU Lesser General Public
00017     License along with this library; if not, write to the Free Software
00018     Foundation, Inc.,
00019     51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00020 */
00021 //-*- c++ -*-
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

Generated on Wed Feb 18 10:23:01 2009 for CVD by  doxygen 1.5.3