Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

v4l2io.cpp

Go to the documentation of this file.
00001 
00005 /*
00006  * Author: Steven Ludtke, 04/10/2003 (sludtke@bcm.edu)
00007  * Copyright (c) 2000-2006 Baylor College of Medicine
00008  * 
00009  * This software is issued under a joint BSD/GNU license. You may use the
00010  * source code in this file under either license. However, note that the
00011  * complete EMAN2 and SPARX software packages have some GPL dependencies,
00012  * so you are responsible for compliance with the licenses of these packages
00013  * if you opt to use BSD licensing. The warranty disclaimer below holds
00014  * in either instance.
00015  * 
00016  * This complete copyright notice must be included in any revised version of the
00017  * source code. Additional authorship citations may be added, but existing
00018  * author citations must be preserved.
00019  * 
00020  * This program is free software; you can redistribute it and/or modify
00021  * it under the terms of the GNU General Public License as published by
00022  * the Free Software Foundation; either version 2 of the License, or
00023  * (at your option) any later version.
00024  * 
00025  * This program is distributed in the hope that it will be useful,
00026  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00027  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00028  * GNU General Public License for more details.
00029  * 
00030  * You should have received a copy of the GNU General Public License
00031  * along with this program; if not, write to the Free Software
00032  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00033  * 
00034  * */
00035 
00036 #ifdef ENABLE_V4L2
00037 #include "v4l2io.h"
00038 #include "geometry.h"
00039 #include "util.h"
00040 #include "portable_fileio.h"
00041 
00042 #include <climits>
00043 #include <cctype>
00044 #include <sys/ioctl.h>
00045 #include <errno.h>
00046 #include <sys/types.h>
00047 #include <sys/stat.h>
00048 #include <fcntl.h>
00049 
00050 using namespace EMAN;
00051 struct v4l2_format v4l2_fmt;    // should be a static member, but doesn't seem to work right
00052 
00053 static int xioctl (int v4l_file, int request, void *arg)
00054 {
00055         int r;
00056 
00057         do r = ioctl (v4l_file, request, arg);
00058         while (-1 == r && EINTR == errno);
00059 
00060         return r;
00061 }
00062 
00063 void errno_exit (const char *s)
00064 {
00065         fprintf (stderr, "%s error %d, %s\n",s, errno, strerror (errno));
00066         exit (EXIT_FAILURE);
00067 }
00068 
00069 
00070 V4L2IO::V4L2IO(const string & file, IOMode rw)
00071 {
00072         filename=(char *)malloc(file.length()+1);
00073         strcpy(filename,file.c_str());
00074         v4l_file=0;
00075         nx = 0;
00076         ny = 0;
00077         initialized=false;
00078 
00079 }
00080 
00081 V4L2IO::~V4L2IO()
00082 {
00083 //      if (v4l_file) {
00084                 //close(v4l_file);
00085                 //v4l_file = 0;
00086         //}
00087         if (filename) free(filename);
00088 }
00089 
00090 void V4L2IO::init() {
00091         ENTERFUNC;
00092         static int ginit=-1;
00093         
00094         if (ginit==-1) ginit=globalinit(filename,0,90,48,8,200,210); // planets on webcam
00095 //      if (ginit==-1) ginit=globalinit(filename,0,80,48,0,240,220); // good for deep sky on webcam
00096         //if (ginit==-1) ginit=globalinit(filename,0,12,-1,60);
00097         v4l_file=ginit;
00098         
00099         initialized=true;
00100 
00101         EXITFUNC;
00102 }
00103 
00104 int V4L2IO::globalinit(const char *fsp,int input,int brt,int cont,int gamma,int expos,int gain)
00105 {
00106         ENTERFUNC;
00107         
00108 //      v4l_file = open (filename, O_RDWR | O_NONBLOCK, 0);
00109         int vfile = open (fsp, O_RDWR, 0);
00110 
00111         unsigned int min;
00112         struct v4l2_capability cap;
00113         struct v4l2_cropcap cropcap;
00114         struct v4l2_crop crop;
00115         
00116         if (-1 == xioctl (vfile, VIDIOC_QUERYCAP, &cap)) {
00117                         if (EINVAL == errno) {
00118                                         fprintf (stderr, "%s is not a V4L2 device, try /dev/vbi*\n",fsp);
00119                                         exit (-1);
00120                         } else {
00121                                         errno_exit ("VIDIOC_QUERYCAP");
00122                         }
00123         }
00124         
00125         printf("driver: %s\ncard %s\n",cap.driver,cap.card);
00126         
00127         if (-1 == xioctl (vfile, VIDIOC_S_INPUT, &input)) errno_exit ("VIDIOC_S_INPUT");
00128         
00129         int std=V4L2_STD_NTSC_M;
00130         if (-1 == xioctl (vfile, VIDIOC_S_STD, &std)) printf("Can't set NTSC standard\n");
00131         
00132         
00133         if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
00134                         fprintf (stderr, "%s is not a video capture device\n",fsp);
00135                         exit (EXIT_FAILURE);
00136         }
00137         
00138         if (!(cap.capabilities & V4L2_CAP_READWRITE)) {
00139                         fprintf (stderr, "%s does not support read i/o\n",fsp);
00140                         exit (EXIT_FAILURE);
00141         }
00142         
00143 /*      cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00144         if (-1 == xioctl (vfile, VIDIOC_CROPCAP, &cropcap)) {
00145                 fprintf(stderr,"VIDIOC_CROPCAP failed %d %d %d %d\n",cropcap.bounds.left,cropcap.bounds.top,cropcap.bounds.width,cropcap.bounds.height);
00146 //              exit(EXIT_FAILURE);
00147         }
00148         
00149         crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00150         crop.c = cropcap.defrect;
00151         
00152         if (-1 == xioctl (vfile, VIDIOC_S_CROP, &crop)) {
00153                         switch (errno) {
00154                         case EINVAL:
00155                                         //Cropping not supported.
00156                                         break;
00157                         default:
00158                                         // Errors ignored.
00159                                         break;
00160                         }
00161         }
00162 */
00163 
00164         /*
00165         printf("Supported formats:\n");
00166         struct v4l2_fmtdesc fdq;
00167         fdq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
00168         for (int idx=0; idx<100; idx++) {
00169                 fdq.index=idx;
00170                 if (xioctl(vfile,VIDIOC_ENUM_FMT,&fdq)==-1) break;
00171                 printf("%4s %s\n",&fdq.pixelformat,fdq.description);
00172         }
00173         */
00174 
00175 //      memset(&v4l2_fmt,0,sizeof(v4l2_fmt));
00176         v4l2_fmt.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
00177         if (-1 == xioctl (vfile, VIDIOC_G_FMT, &v4l2_fmt)) errno_exit ("VIDIOC_G_FMT");
00178         
00179         v4l2_fmt.type                = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00180         v4l2_fmt.fmt.pix.width       = 640; 
00181         v4l2_fmt.fmt.pix.height      = 480;
00182 //      v4l2_fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_GREY;
00183         v4l2_fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;
00184 //      v4l2_fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
00185 //      v4l2_fmt.fmt.pix.field       = V4L2_FIELD_NONE;
00186 //      v4l2_fmt.fmt.pix.field       = V4L2_FIELD_INTERLACED;
00187         
00188         if (-1 == xioctl (vfile, VIDIOC_S_FMT, &v4l2_fmt)) errno_exit ("VIDIOC_S_FMT");
00189         
00190         /* Note VIDIOC_S_FMT may change width and height. */
00191         
00192         /* Buggy driver paranoia. */
00193         min = v4l2_fmt.fmt.pix.width * 2;
00194         if (v4l2_fmt.fmt.pix.bytesperline < min)
00195                         v4l2_fmt.fmt.pix.bytesperline = min;
00196         min = v4l2_fmt.fmt.pix.bytesperline * v4l2_fmt.fmt.pix.height;
00197         if (v4l2_fmt.fmt.pix.sizeimage < min)
00198                         v4l2_fmt.fmt.pix.sizeimage = min;
00199         
00200         printf("fmt.fmt.pix.width = %d\n",v4l2_fmt.fmt.pix.width);
00201         printf("fmt.fmt.pix.height = %d\n",v4l2_fmt.fmt.pix.height);
00202         printf("fmt.fmt.pix.pixelformat = %4s\n",&v4l2_fmt.fmt.pix.pixelformat);
00203         printf("fmt.fmt.pix.bytesperline = %d\n",v4l2_fmt.fmt.pix.bytesperline);
00204         printf("fmt.fmt.pix.sizeimage = %d\n",v4l2_fmt.fmt.pix.sizeimage);
00205 //      printf("fmt.fmt.pix.field = %d\n",v4l2_fmt.fmt.pix.field); 
00206         
00207         struct v4l2_queryctrl qc;
00208         struct v4l2_control con;
00209 
00210         qc.id=V4L2_CID_BRIGHTNESS;
00211         ioctl(vfile,VIDIOC_QUERYCTRL,&qc);
00212         printf("brightness = %d - %d by %d %d\n",qc.minimum,qc.maximum,qc.step,qc.default_value);
00213 
00214         qc.id=V4L2_CID_CONTRAST;
00215         ioctl(vfile,VIDIOC_QUERYCTRL,&qc);
00216         printf("contrast = %d - %d by %d %d\n",qc.minimum,qc.maximum,qc.step,qc.default_value);
00217 
00218         qc.id=V4L2_CID_GAMMA;
00219         ioctl(vfile,VIDIOC_QUERYCTRL,&qc);
00220         printf("gamma = %d - %d by %d %d\n",qc.minimum,qc.maximum,qc.step,qc.default_value);
00221 
00222         qc.id=V4L2_CID_EXPOSURE;
00223         ioctl(vfile,VIDIOC_QUERYCTRL,&qc);
00224         printf("exposure = %d - %d by %d %d\n",qc.minimum,qc.maximum,qc.step,qc.default_value);
00225 
00226         qc.id=V4L2_CID_GAIN;
00227         ioctl(vfile,VIDIOC_QUERYCTRL,&qc);
00228         printf("gain = %d - %d by %d %d\n",qc.minimum,qc.maximum,qc.step,qc.default_value);
00229 
00230         con.id=V4L2_CID_AUTOGAIN;
00231         con.value=0;
00232         ioctl(vfile,VIDIOC_S_CTRL,&con);
00233         
00234         if (brt!=-1) {
00235         con.id=V4L2_CID_BRIGHTNESS;
00236         con.value=brt;
00237         ioctl(vfile,VIDIOC_S_CTRL,&con);
00238         }
00239 
00240         if (cont!=-1) {
00241         con.id=V4L2_CID_CONTRAST;
00242         con.value=cont;
00243         ioctl(vfile,VIDIOC_S_CTRL,&con);
00244         }
00245 
00246         if (gamma!=-1) {
00247         con.id=V4L2_CID_GAMMA;
00248         con.value=gamma;
00249         ioctl(vfile,VIDIOC_S_CTRL,&con);
00250         }
00251 
00252         if (expos!=-1) {
00253         con.id=V4L2_CID_EXPOSURE;
00254         con.value=expos;
00255         ioctl(vfile,VIDIOC_S_CTRL,&con);
00256         }
00257 
00258         if (gain!=-1) {
00259         con.id=V4L2_CID_GAIN;
00260         con.value=gain;
00261         ioctl(vfile,VIDIOC_S_CTRL,&con);
00262         }
00263 
00264 //      close(vfile);
00265         EXITFUNC;
00266         return vfile;
00267 }
00268 
00269 bool V4L2IO::is_valid(const void *first_block)
00270 {
00271         ENTERFUNC;
00272         return true;
00273 }
00274 
00275 int V4L2IO::read_header(Dict & dict, int image_index, const Region * area, bool)
00276 {
00277         ENTERFUNC;
00278         
00279         if(image_index == -1) {
00280                 image_index = 0;
00281         }
00282 
00283         if(image_index != 0) {
00284                 throw ImageReadException(filename, "no stack allowed for MRC image. For take 2D slice out of 3D image, read the 3D image first, then use get_clip().");
00285         }
00286         
00287         if (!initialized) init();
00288         
00289         dict["nx"] = (int)(v4l2_fmt.fmt.pix.width);
00290         dict["ny"] = (int)(v4l2_fmt.fmt.pix.height);
00291         dict["nz"] = 1;
00292                         
00293         dict["datatype"] = EMUtil::EM_UCHAR;
00294         
00295         EXITFUNC;
00296         return 0;
00297 }
00298 
00299 int V4L2IO::write_header(const Dict & dict, int image_index, const Region*,
00300                                                 EMUtil::EMDataType, bool)
00301 {
00302         ENTERFUNC;      
00303         LOGWARN("V4L write is not supported.");
00304         EXITFUNC;
00305         return 1;       // No write capability
00306 }
00307 
00308 int V4L2IO::read_data(float *data, int image_index, const Region * area, bool)
00309 {
00310         if (!initialized) init();
00311         
00312         Region tmp(0,0,v4l2_fmt.fmt.pix.width,v4l2_fmt.fmt.pix.height);
00313         if (!area) area=&tmp;
00314         
00315         int x,y;
00316         ENTERFUNC;
00317         unsigned char *dbuf = (unsigned char *)malloc(v4l2_fmt.fmt.pix.sizeimage);
00318 
00319         read(v4l_file,dbuf,v4l2_fmt.fmt.pix.sizeimage);
00320         read(v4l_file,dbuf,v4l2_fmt.fmt.pix.sizeimage);
00321 
00322 /*      int count=v4l2_fmt.fmt.pix.sizeimage;
00323         int pos=0;
00324         while (count) {
00325                 int c=read(v4l_file,dbuf+pos,count);
00326                 printf("# %d\n",c);
00327                 if (c==-1) { printf("ern %d\n",errno); break; }
00328                 count-=c;
00329                 pos+=c;
00330         }
00331         
00332         printf("buf.length=%d  area.x=%d area.y=%d\n",v4l2_fmt.fmt.pix.sizeimage,(int)area->size[0],(int)area->size[1]);
00333         */
00334         
00335         for (y=0; y<area->size[1]; y++) {
00336                 for (x=0; x<area->size[0]; x++) {
00337 // This is for YUYV
00338 //                      data[(int)(area->size[0]*(area->size[1]-y-1)+x)]=dbuf[v4l2_fmt.fmt.pix.bytesperline*y+x*2]/256.0;
00339 // This is for YUV420
00340 //                      data[(int)(area->size[0]*(area->size[1]-y-1)+x)]=dbuf[v4l2_fmt.fmt.pix.bytesperline*y+x]/256.0;
00341                         data[(int)(area->size[0]*(area->size[1]-y-1)+x)]=dbuf[(int)area->size[0]*y+x]/256.0;
00342                 }
00343         }
00344 
00345 //      int sum=0;
00346 //      for (x=0; x<v4l2_fmt.fmt.pix.sizeimage; x++) sum+=dbuf[x];
00347 //      printf("%d\n",sum);
00348         
00349         free(dbuf);
00350         EXITFUNC;
00351         return 0;
00352 }
00353 
00354 int V4L2IO::write_data(float *data, int image_index, const Region* ,
00355                                           EMUtil::EMDataType, bool)
00356 {
00357         ENTERFUNC;
00358 
00359         EXITFUNC;
00360         return 1;
00361 }
00362 
00363 void V4L2IO::flush()
00364 {
00365 
00366 }
00367 
00368 
00369 bool V4L2IO::is_complex_mode()
00370 {
00371         return false;
00372 }
00373 
00374 bool V4L2IO::is_image_big_endian()
00375 {
00376         return 1;
00377 }
00378 
00379 #endif

Generated on Tue Jun 11 13:40:45 2013 for EMAN2 by  doxygen 1.3.9.1