libcvd-members
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[libcvd-members] libcvd Makefile.in cvd/Linux/v4lcontrol.h cvd_s...


From: Gerhard Reitmayr
Subject: [libcvd-members] libcvd Makefile.in cvd/Linux/v4lcontrol.h cvd_s...
Date: Fri, 28 Jul 2006 14:05:40 +0000

CVSROOT:        /cvsroot/libcvd
Module name:    libcvd
Changes by:     Gerhard Reitmayr <gerhard>      06/07/28 14:05:40

Modified files:
        .              : Makefile.in 
Added files:
        cvd/Linux      : v4lcontrol.h 
        cvd_src/Linux  : v4lcontrol.cc 

Log message:
        added a class to control parameters of v4l2 devices

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/libcvd/Makefile.in?cvsroot=libcvd&r1=1.47&r2=1.48
http://cvs.savannah.gnu.org/viewcvs/libcvd/cvd/Linux/v4lcontrol.h?cvsroot=libcvd&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/libcvd/cvd_src/Linux/v4lcontrol.cc?cvsroot=libcvd&rev=1.1

Patches:
Index: Makefile.in
===================================================================
RCS file: /cvsroot/libcvd/libcvd/Makefile.in,v
retrieving revision 1.47
retrieving revision 1.48
diff -u -b -r1.47 -r1.48
--- Makefile.in 6 Jul 2006 16:44:58 -0000       1.47
+++ Makefile.in 28 Jul 2006 14:05:40 -0000      1.48
@@ -156,7 +156,8 @@
 
 ifeq (@have_v4l2buffer@,yes)
        CVD_OBJS+=cvd_src/Linux/v4l2buffer.o \
-                 cvd_src/Linux/v4lbuffer.o
+               cvd_src/Linux/v4lbuffer.o \
+               cvd_src/Linux/v4lcontrol.o
 endif
 
 ifeq (@have_v4l1buffer@,yes)

Index: cvd/Linux/v4lcontrol.h
===================================================================
RCS file: cvd/Linux/v4lcontrol.h
diff -N cvd/Linux/v4lcontrol.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ cvd/Linux/v4lcontrol.h      28 Jul 2006 14:05:40 -0000      1.1
@@ -0,0 +1,182 @@
+#ifndef CVD_V4LCONTROL_H
+#define CVD_V4LCONTROL_H
+
+#include <string>
+#include <map>
+#include <vector>
+
+#include <linux/videodev.h>
+
+#include <cvd/exceptions.h>
+
+namespace CVD {
+
+namespace Exceptions
+{
+    /// @ingroup gException
+    namespace V4LControl
+    {
+    /// @ingroup gException
+    struct All: public CVD::Exceptions::All
+    {
+    };
+    /// Error opening the device
+    /// @ingroup gException
+    struct DeviceOpen: public All {DeviceOpen(std::string dev); ///< Construct 
from the device name
+    };
+
+    /// Unsupported parameter
+    /// @ingroup gException
+    struct ParameterNotSupported: public All {
+        ParameterNotSupported(std::string);  ///< Construct from parameter name
+        ParameterNotSupported(unsigned int); ///< Construct from parameter id
+    };
+
+    /// Error querying value
+    /// @ingroup gException
+    struct GetValue: public All {GetValue(std::string); ///< Construct from 
parameter name
+    };
+
+    /// Error setting value
+    /// @ingroup gException
+    struct SetValue: public All {SetValue(std::string); ///< Construct from 
parameter name
+    };
+
+    /// Error querying device parameters
+    /// @ingroup gException
+    struct QueryParameters: public All {QueryParameters(std::string); ///< 
Construct from message
+    };
+
+    }
+}
+
+
+/**
+exposes the V4L2 API to set parameters on a capture device. It can be used
+in parallel to a v4lbuffer object to control and query all parameters 
supported.
+Several abstraction levels are supported. On the highest there are individual
+member functions for various fixed parameters. The next level supports 
querying and
+setting/getting values for all parameters supported by the driver. Finally,
+low-level access using V4L2 structs is supported as well.
+
address@hidden gVideo
+*/
+class V4LControl {
+public:
+    V4LControl( int fd, bool report = true );
+    V4LControl( const std::string & name, bool report = true );
+
+    /// @name HighLevel
+    /// High level interface to set specific parameters without much hassle.
+    /// These might fail if the parameter is not supported by the device and do
+    /// not throw exceptions. Moreover ranges of parameter values are 
abstracted
+    /// to lie within the intervall [0,1].
+    /// If you want to have more control, use the lower level interface 
described in
+    /// @ref Generic .
+    //@{
+    void exposure( int );
+    int  exposure(void);
+
+    void autoexposure(bool);
+    bool autoexposure();
+
+    void gain( double );
+    double gain(void);
+
+    void autogain(bool);
+    bool autogain(void);
+
+    void brightness(double);
+    double brightness(void);
+
+    void contrast(double);
+    double contrast(void);
+
+    void saturation(double);
+    double saturation(void);
+    //@}
+
+    /// @name Generic
+    /// generic high level interface abstracting the v4l2 structs
+    //@{
+    unsigned int getId( const std::string & name ) const;
+    std::string getName( unsigned int id ) const;
+    std::vector<unsigned int> supportedParameters(void) const;
+    std::vector<std::string> supportedParameterNames(void) const;
+
+    inline bool isSupported( const std::string & name ) const {
+        return (controlNames.find(name) != controlNames.end());
+    }
+    inline void set( const std::string & name, int value ){
+        set(getId(name), value);
+    }
+    inline int get( const std::string & name ){
+        return get(getId(name));
+    }
+    inline int type( const std::string & name ){
+        return type(getId(name));
+    }
+    inline std::map<unsigned int, std::string> menuValues( const std::string & 
name ){
+        return menuValues(getId(name));
+    }
+    inline int defaultValue( const std::string & name ){
+        return defaultValue(getId(name));
+    }
+    inline int min( const std::string & name ){
+        return min(getId(name));
+    }
+    inline int max( const std::string & name ){
+        return max(getId(name));
+    }
+    inline int step( const std::string & name ){
+        return step(getId(name));
+    }
+
+    inline bool isSupported( unsigned int id ) const {
+        return (controlData.find(id) != controlData.end());
+    }
+    void set( unsigned int id, int value);
+    int get( unsigned int id );
+    int type( unsigned int id );
+    std::map<unsigned int, std::string> menuValues( unsigned int id ) const ;
+    int defaultValue( unsigned int id ) const;
+    int min( unsigned int id ) const;
+    int max( unsigned int id ) const;
+    int step( unsigned int id ) const;
+    //@}
+
+    /// @name LowLevel
+    /// low level interface using v4l2 structs
+    //@{
+    int getQueryStruct( v4l2_queryctrl & query ) const;
+    void getMenuStruct( unsigned int id, std::vector<v4l2_querymenu> & menu ) 
const;
+    int setControlStruct( v4l2_control & value );
+    int getControlStruct( v4l2_control & value ) const;
+    //@}
+
+    /// return file descriptor for the opened device
+    inline int getFile(void) const { return device; }
+
+    /// return file name of the opened device
+    inline const std::string & getDevice(void) const { return deviceName; }
+
+    /// set error reporting
+    inline void setReportErrors( bool report ) { reportErrors = report; }
+    inline bool getReportErrors(void) const { return reportErrors; }
+
+protected:
+    int device;
+    std::string deviceName;
+    struct v4l2_control control;
+    bool reportErrors;
+
+    void queryControls(void);
+
+    std::map<std::string, unsigned int> controlNames;
+    std::map<unsigned int, v4l2_queryctrl> controlData;
+    std::map<unsigned int, std::vector<v4l2_querymenu> >  menuData;
+};
+
+} // namespace CVD
+
+#endif

Index: cvd_src/Linux/v4lcontrol.cc
===================================================================
RCS file: cvd_src/Linux/v4lcontrol.cc
diff -N cvd_src/Linux/v4lcontrol.cc
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ cvd_src/Linux/v4lcontrol.cc 28 Jul 2006 14:05:40 -0000      1.1
@@ -0,0 +1,316 @@
+#include <cvd/Linux/v4lcontrol.h>
+
+#include <iostream>
+#include <sstream>
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+using namespace std;
+
+template <typename T>
+static inline double toUnit( T val, T min, T max){
+    double interval = max - min;
+    return (val - min)/interval;
+}
+
+template <typename T>
+static inline T fromUnit( double val, T min, T max){
+    double interval = max - min;
+    return static_cast<T>(val * interval - min);
+}
+
+namespace CVD {
+
+Exceptions::V4LControl::DeviceOpen::DeviceOpen(string device)
+{
+    what = "V4LControl: failed to open \""+device+ "\": " + strerror(errno);
+}
+
+Exceptions::V4LControl::ParameterNotSupported::ParameterNotSupported(string 
parameter)
+{
+    what = "V4LControl: parameter \"" + parameter + "\" is not supported.";
+}
+
+Exceptions::V4LControl::ParameterNotSupported::ParameterNotSupported(unsigned 
int id)
+{
+    ostringstream os;
+    os << "V4LControl: parameter " << id << " is not supported.";
+    what = os.str();
+}
+
+Exceptions::V4LControl::GetValue::GetValue(string parameter)
+{
+    what = "V4LControl: query value \""+parameter+ "\" failed: " + 
strerror(errno);
+}
+
+Exceptions::V4LControl::SetValue::SetValue(string parameter)
+{
+    what = "V4LControl: setting value \""+parameter+ "\" failed: " + 
strerror(errno);
+}
+
+Exceptions::V4LControl::QueryParameters::QueryParameters(string msg)
+{
+    what = "V4LControl: Querying parameters failed: \""+msg+ "\": " + 
strerror(errno);
+}
+
+V4LControl::V4LControl( int fd, bool report ) : device(fd), deviceName(""), 
reportErrors(report) {
+    memset(&control, 0, sizeof(control));
+    queryControls();
+}
+
+V4LControl::V4LControl( const std::string & name, bool report  ) : device(0), 
deviceName(name), reportErrors(report) {
+    if( -1 == (device = open(deviceName.c_str(), O_RDWR | O_NONBLOCK))){
+        throw Exceptions::V4LControl::DeviceOpen(deviceName);
+    }
+    memset(&control, 0, sizeof(control));
+    queryControls();
+}
+
+void V4LControl::exposure( int value ){
+    if(!isSupported(V4L2_CID_EXPOSURE))
+        return;
+    set(V4L2_CID_EXPOSURE, value);
+}
+
+int V4LControl::exposure(void){
+    if(!isSupported(V4L2_CID_EXPOSURE))
+        return 0;
+    return get(V4L2_CID_EXPOSURE);
+}
+
+void V4LControl::autoexposure(bool value){
+    if(!isSupported("Auto Exposure"))
+        return;
+    set("Auto Exposure", value);
+}
+
+bool V4LControl::autoexposure(){
+    if(!isSupported("Auto Exposure"))
+        return false;
+    return get("Auto Exposure");
+}
+
+void V4LControl::gain( double value ){
+    if(!isSupported(V4L2_CID_GAIN))
+        return;
+    set(V4L2_CID_GAIN, fromUnit(value, min(V4L2_CID_GAIN), 
max(V4L2_CID_GAIN)));
+}
+
+double V4LControl::gain(void){
+    if(!isSupported(V4L2_CID_GAIN))
+        return 0;
+    return toUnit(get(V4L2_CID_GAIN), min(V4L2_CID_GAIN), max(V4L2_CID_GAIN));
+}
+
+void V4LControl::autogain(bool value){
+    if(!isSupported(V4L2_CID_AUTOGAIN))
+        return;
+    set(V4L2_CID_AUTOGAIN, value);
+}
+
+bool V4LControl::autogain(void){
+    if(!isSupported(V4L2_CID_AUTOGAIN))
+        return false;
+    return get(V4L2_CID_AUTOGAIN);
+}
+
+void V4LControl::brightness(double value){
+    if(!isSupported(V4L2_CID_BRIGHTNESS))
+        return;
+    set(V4L2_CID_BRIGHTNESS, fromUnit(value, min(V4L2_CID_BRIGHTNESS), 
max(V4L2_CID_BRIGHTNESS)));
+}
+
+double V4LControl::brightness(void){
+    if(!isSupported(V4L2_CID_BRIGHTNESS))
+        return 0;
+    return toUnit(get(V4L2_CID_BRIGHTNESS), min(V4L2_CID_BRIGHTNESS), 
max(V4L2_CID_BRIGHTNESS));
+}
+
+void V4LControl::contrast(double value){
+    if(!isSupported(V4L2_CID_CONTRAST))
+        return;
+    set(V4L2_CID_CONTRAST, fromUnit(value, min(V4L2_CID_CONTRAST), 
max(V4L2_CID_CONTRAST)));
+}
+
+double V4LControl::contrast(void){
+    if(!isSupported(V4L2_CID_CONTRAST))
+        return 0;
+    return toUnit(get(V4L2_CID_CONTRAST), min(V4L2_CID_CONTRAST), 
max(V4L2_CID_CONTRAST));
+}
+
+void V4LControl::saturation(double value){
+    if(!isSupported(V4L2_CID_SATURATION))
+        return;
+    set(V4L2_CID_SATURATION, fromUnit(value, min(V4L2_CID_SATURATION), 
max(V4L2_CID_SATURATION)));
+}
+
+double V4LControl::saturation(void){
+    if(!isSupported(V4L2_CID_SATURATION))
+        return 0;
+    return toUnit(get(V4L2_CID_SATURATION), min(V4L2_CID_SATURATION), 
max(V4L2_CID_SATURATION));
+}
+
+void V4LControl::queryControls(void){
+    controlData.clear();
+    controlNames.clear();
+    menuData.clear();
+
+    struct v4l2_queryctrl queryctrl;
+    memset(&queryctrl, 0, sizeof(queryctrl));
+    for (unsigned int i = V4L2_CID_BASE;  i < V4L2_CID_LASTP1; i++) {
+        queryctrl.id = i;
+        if (0 == getQueryStruct(queryctrl)) {
+            if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
+                continue;
+            controlData[queryctrl.id] = queryctrl;
+            controlNames[(const char *)queryctrl.name] = queryctrl.id;
+            if (queryctrl.type == V4L2_CTRL_TYPE_MENU) {
+                vector<v4l2_querymenu> menus;
+                getMenuStruct( queryctrl.id, menus);
+                menuData[queryctrl.id].swap(menus);
+            }
+        } else {
+            if (errno != EINVAL) {
+                throw Exceptions::V4LControl::QueryParameters("standard 
controls");
+            }
+        }
+    }
+    for (queryctrl.id = V4L2_CID_PRIVATE_BASE;;queryctrl.id++) {
+        if (0 == getQueryStruct(queryctrl)) {
+            if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
+                continue;
+            controlData[queryctrl.id] = queryctrl;
+            controlNames[(const char *)queryctrl.name] = queryctrl.id;
+            if (queryctrl.type == V4L2_CTRL_TYPE_MENU) {
+                vector<v4l2_querymenu> menus;
+                getMenuStruct( queryctrl.id, menus);
+                menuData[queryctrl.id].swap(menus);
+            }
+        } else {
+            break;
+        }
+    }
+}
+
+unsigned int V4LControl::getId( const std::string & name ) const {
+    map<string, unsigned int>::const_iterator id = controlNames.find(name);
+    if(id == controlNames.end())
+        return V4L2_CID_LASTP1;
+    return id->second;
+}
+
+string V4LControl::getName( unsigned int id ) const {
+    map<unsigned int, v4l2_queryctrl>::const_iterator control = 
controlData.find(id);
+    if(control == controlData.end())
+        return "";
+    return (const char *)control->second.name;
+}
+
+vector<unsigned int> V4LControl::supportedParameters(void) const {
+    vector<unsigned int> result(controlNames.size());
+    vector<unsigned int>::iterator id = result.begin();
+    for(map<string, unsigned int>::const_iterator param = 
controlNames.begin(); param != controlNames.end(); ++param, ++id)
+        *id = param->second;
+    return result;
+}
+
+vector<string> V4LControl::supportedParameterNames(void) const {
+    vector<string> result(controlNames.size());
+    vector<string>::iterator id = result.begin();
+    for(map<string, unsigned int>::const_iterator param = 
controlNames.begin(); param != controlNames.end(); ++param, ++id)
+        *id = param->first;
+    return result;
+}
+
+void V4LControl::set( unsigned int id, int value){
+    control.id = id;
+    if(!isSupported(control.id))
+        throw Exceptions::V4LControl::ParameterNotSupported(id);
+    control.value = value;
+    if(-1 == setControlStruct( control ))
+        if( errno != EBUSY )
+            throw Exceptions::V4LControl::SetValue(getName(id));
+}
+
+int V4LControl::get( unsigned int id ){
+    control.id = id;
+    if(!isSupported(control.id))
+        throw Exceptions::V4LControl::ParameterNotSupported(id);
+    if(-1 == getControlStruct( control ))
+        if( errno != EBUSY )
+            throw Exceptions::V4LControl::GetValue(getName(id));
+    return control.value;
+}
+
+int V4LControl::type( unsigned int id ){
+    return controlData[id].type;
+}
+
+map<unsigned int, string> V4LControl::menuValues( unsigned int id ) const {
+    if(!isSupported(id))
+        throw Exceptions::V4LControl::ParameterNotSupported(id);
+    map<unsigned int, string> result;
+    const vector<v4l2_querymenu> & menu = menuData.find(id)->second;
+    for(vector<v4l2_querymenu>::const_iterator m = menu.begin(); m != 
menu.end(); m++)
+        result[m->index] = (const char *)m->name;
+    return result;
+}
+
+int V4LControl::defaultValue( unsigned int id ) const {
+    if(!isSupported(id))
+        throw Exceptions::V4LControl::ParameterNotSupported(id);
+    return controlData.find(id)->second.default_value;
+}
+
+int V4LControl::min( unsigned int id ) const {
+    if(!isSupported(id))
+        throw Exceptions::V4LControl::ParameterNotSupported(id);
+    return controlData.find(id)->second.minimum;
+}
+
+int V4LControl::max( unsigned int id ) const {
+    if(!isSupported(id))
+        throw Exceptions::V4LControl::ParameterNotSupported(id);
+    return controlData.find(id)->second.maximum;
+}
+
+int V4LControl::step( unsigned int id ) const{
+    if(!isSupported(id))
+        throw Exceptions::V4LControl::ParameterNotSupported(id);
+    return controlData.find(id)->second.step;
+}
+
+int V4LControl::getQueryStruct( v4l2_queryctrl & query ) const {
+    return ioctl (device, VIDIOC_QUERYCTRL, &query);
+}
+
+void V4LControl::getMenuStruct( unsigned int id, vector<v4l2_querymenu> & menu 
) const {
+    if(!isSupported(id))
+        throw Exceptions::V4LControl::ParameterNotSupported(id);
+    menu.clear();
+    struct v4l2_querymenu querymenu;
+    memset (&querymenu, 0, sizeof (querymenu));
+    querymenu.id = id;
+    int last;
+    const struct v4l2_queryctrl & data = controlData.find(id)->second;
+
+    for (querymenu.index = data.minimum; querymenu.index <= data.maximum; 
querymenu.index++) {
+        if (0 != (last = ioctl (device, VIDIOC_QUERYMENU, &querymenu)))
+            throw Exceptions::V4LControl::QueryParameters("reading menu item");
+        menu.push_back(querymenu);
+    }
+}
+
+int V4LControl::setControlStruct( v4l2_control & control ){
+    return ioctl(device, VIDIOC_S_CTRL, &control);
+}
+
+int V4LControl::getControlStruct( v4l2_control & control ) const {
+    return ioctl(device, VIDIOC_G_CTRL, &control);
+}
+
+}




reply via email to

[Prev in Thread] Current Thread [Next in Thread]