Merge CV, ver=5.1; ops/methods from HV, and interface from CV where possible
[goodguy/history.git] / cinelerra-5.1 / cinelerra / devicev4l2base.h
diff --git a/cinelerra-5.1/cinelerra/devicev4l2base.h b/cinelerra-5.1/cinelerra/devicev4l2base.h
new file mode 100644 (file)
index 0000000..e492e87
--- /dev/null
@@ -0,0 +1,130 @@
+
+/*
+ * CINELERRA
+ * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef DEVICEV4L2BASE_H
+#define DEVICEV4L2BASE_H
+
+#include "channel.inc"
+#include "condition.h"
+#include "vframe.inc"
+#include "devicev4l2base.inc"
+#include "mutex.inc"
+#include "thread.h"
+#include "vframe.h"
+#include "videodevice.inc"
+
+class DeviceV4L2BufferQ
+{
+       volatile int in, out;
+        int limit, *buffers;
+        Mutex *bfr_lock;
+public:
+       DeviceV4L2BufferQ(int qsize);
+       ~DeviceV4L2BufferQ();
+       int q(int bfr);
+       int dq();
+       int dq(Condition *time_lock, int time_out);
+       int sz();
+       void reset() { in = out = 0; }
+};
+
+// Another thread which puts back buffers asynchronously of the buffer
+// grabber.  Because 2.6.7 drivers block the buffer enqueuer.
+class DeviceV4L2Put : public Thread
+{
+       DeviceV4L2Base *v4l2;
+public:
+        DeviceV4L2Put(DeviceV4L2Base *v4l2);
+        ~DeviceV4L2Put();
+
+        void run();
+       DeviceV4L2BufferQ *putq;
+       Condition *buffer_lock;
+        int done;
+       void put_buffer(int bfr) {
+               if( !putq->q(bfr) ) buffer_lock->unlock();
+       }
+};
+
+class DeviceV4L2VFrame : public VFrame {
+       unsigned char *dev_data;
+       unsigned long dev_size;
+public:
+       unsigned char *get_dev_data() { return dev_data; }
+       unsigned long get_dev_size() { return dev_size; }
+
+       DeviceV4L2VFrame(int dev_fd, unsigned long ofs, unsigned long sz);
+       ~DeviceV4L2VFrame();
+};
+
+class DeviceV4L2Base : public Thread
+{
+       friend class DeviceV4L2Put;
+       DeviceV4L2Put *put_thread;
+       Mutex *v4l2_lock;
+// Some of the drivers in 2.6.7 can't handle simultaneous QBUF and DQBUF calls.
+        Mutex *qbfrs_lock;
+       Condition *video_lock;
+       DeviceV4L2VFrame **device_buffers;
+        Channel *device_channel;
+        DeviceV4L2BufferQ *getq;
+
+        int done;
+       int opened;
+       int streamon;
+       int dev_status;
+       int total_buffers;
+       volatile int q_bfrs;
+// COMPRESSED or another color model the device should use.
+        int color_model;
+       int dev_fd;
+
+       int dev_open();
+       void dev_close();
+       int v4l2_open(int color_model);
+       int v4l2_status();
+
+       int vioctl (unsigned long int req, void *arg);
+       static unsigned int cmodel_to_device(int color_model);
+       void run();
+public:
+       DeviceV4L2Base();
+       ~DeviceV4L2Base();
+
+        virtual VideoDevice *v4l2_device() = 0;
+
+       int v4l2_fd() { return dev_fd; }
+       int open_dev(int color_model);
+       void close_dev();
+       int status_dev();
+       virtual int start_dev();
+       virtual int stop_dev();
+       int get_sources();
+       int is_opened() { return opened; }
+       int dev_signal() { return dev_status; }
+       VFrame *device_buffer(int bfr) { return device_buffers[bfr]; }
+       int get_color_model() { return color_model; }
+       int get_buffer() { return getq->dq(video_lock,V4L2_BUFFER_TIMEOUT); }
+       void put_buffer(int bfr) { put_thread->put_buffer(bfr); }
+       int putq_sz() { return put_thread->putq->sz(); }
+};
+
+#endif