00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
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;
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
00084
00085
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);
00095
00096
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
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
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
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
00183 v4l2_fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;
00184
00185
00186
00187
00188 if (-1 == xioctl (vfile, VIDIOC_S_FMT, &v4l2_fmt)) errno_exit ("VIDIOC_S_FMT");
00189
00190
00191
00192
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
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
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;
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
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335 for (y=0; y<area->size[1]; y++) {
00336 for (x=0; x<area->size[0]; x++) {
00337
00338
00339
00340
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
00346
00347
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