EMAN2
v4l2io.cpp
Go to the documentation of this file.
1/*
2 * Author: Steven Ludtke, 04/10/2003 (sludtke@bcm.edu)
3 * Copyright (c) 2000-2006 Baylor College of Medicine
4 *
5 * This software is issued under a joint BSD/GNU license. You may use the
6 * source code in this file under either license. However, note that the
7 * complete EMAN2 and SPARX software packages have some GPL dependencies,
8 * so you are responsible for compliance with the licenses of these packages
9 * if you opt to use BSD licensing. The warranty disclaimer below holds
10 * in either instance.
11 *
12 * This complete copyright notice must be included in any revised version of the
13 * source code. Additional authorship citations may be added, but existing
14 * author citations must be preserved.
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 *
30 * */
31
32#ifdef ENABLE_V4L2
33#include "v4l2io.h"
34#include "geometry.h"
35#include "util.h"
36#include "portable_fileio.h"
37
38#include <climits>
39#include <cctype>
40#include <sys/ioctl.h>
41#include <errno.h>
42#include <sys/types.h>
43#include <sys/stat.h>
44#include <fcntl.h>
45
46using namespace EMAN;
47struct v4l2_format v4l2_fmt; // should be a static member, but doesn't seem to work right
48
49static int xioctl (int v4l_file, int request, void *arg)
50{
51 int r;
52
53 do r = ioctl (v4l_file, request, arg);
54 while (-1 == r && EINTR == errno);
55
56 return r;
57}
58
59void errno_exit (const char *s)
60{
61 fprintf (stderr, "%s error %d, %s\n",s, errno, strerror (errno));
62 exit (EXIT_FAILURE);
63}
64
65
66V4L2IO::V4L2IO(const string & fname, IOMode rw)
67{
68 filename=(char *)malloc(file.length()+1);
69 strcpy(filename,file.c_str());
70 v4l_file=0;
71 nx = 0;
72 ny = 0;
73 initialized=false;
74
75}
76
78{
79// if (v4l_file) {
80 //close(v4l_file);
81 //v4l_file = 0;
82 //}
83 if (filename) free(filename);
84}
85
86void V4L2IO::init() {
88 static int ginit=-1;
89
90 if (ginit==-1) ginit=globalinit(filename,0,90,48,8,200,210); // planets on webcam
91// if (ginit==-1) ginit=globalinit(filename,0,80,48,0,240,220); // good for deep sky on webcam
92 //if (ginit==-1) ginit=globalinit(filename,0,12,-1,60);
93 v4l_file=ginit;
94
95 initialized=true;
96
98}
99
100int V4L2IO::globalinit(const char *fsp,int input,int brt,int cont,int gamma,int expos,int gain)
101{
102 ENTERFUNC;
103
104// v4l_file = open (filename, O_RDWR | O_NONBLOCK, 0);
105 int vfile = open (fsp, O_RDWR, 0);
106
107 unsigned int min;
108 struct v4l2_capability cap;
109 struct v4l2_cropcap cropcap;
110 struct v4l2_crop crop;
111
112 if (-1 == xioctl (vfile, VIDIOC_QUERYCAP, &cap)) {
113 if (EINVAL == errno) {
114 fprintf (stderr, "%s is not a V4L2 device, try /dev/vbi*\n",fsp);
115 exit (-1);
116 } else {
117 errno_exit ("VIDIOC_QUERYCAP");
118 }
119 }
120
121 printf("driver: %s\ncard %s\n",cap.driver,cap.card);
122
123 if (-1 == xioctl (vfile, VIDIOC_S_INPUT, &input)) errno_exit ("VIDIOC_S_INPUT");
124
125 int std=V4L2_STD_NTSC_M;
126 if (-1 == xioctl (vfile, VIDIOC_S_STD, &std)) printf("Can't set NTSC standard\n");
127
128
129 if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
130 fprintf (stderr, "%s is not a video capture device\n",fsp);
131 exit (EXIT_FAILURE);
132 }
133
134 if (!(cap.capabilities & V4L2_CAP_READWRITE)) {
135 fprintf (stderr, "%s does not support read i/o\n",fsp);
136 exit (EXIT_FAILURE);
137 }
138
139/* cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
140 if (-1 == xioctl (vfile, VIDIOC_CROPCAP, &cropcap)) {
141 fprintf(stderr,"VIDIOC_CROPCAP failed %d %d %d %d\n",cropcap.bounds.left,cropcap.bounds.top,cropcap.bounds.width,cropcap.bounds.height);
142// exit(EXIT_FAILURE);
143 }
144
145 crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
146 crop.c = cropcap.defrect;
147
148 if (-1 == xioctl (vfile, VIDIOC_S_CROP, &crop)) {
149 switch (errno) {
150 case EINVAL:
151 //Cropping not supported.
152 break;
153 default:
154 // Errors ignored.
155 break;
156 }
157 }
158*/
159
160 /*
161 printf("Supported formats:\n");
162 struct v4l2_fmtdesc fdq;
163 fdq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
164 for (int idx=0; idx<100; idx++) {
165 fdq.index=idx;
166 if (xioctl(vfile,VIDIOC_ENUM_FMT,&fdq)==-1) break;
167 printf("%4s %s\n",&fdq.pixelformat,fdq.description);
168 }
169 */
170
171// memset(&v4l2_fmt,0,sizeof(v4l2_fmt));
172 v4l2_fmt.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
173 if (-1 == xioctl (vfile, VIDIOC_G_FMT, &v4l2_fmt)) errno_exit ("VIDIOC_G_FMT");
174
175 v4l2_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
176 v4l2_fmt.fmt.pix.width = 640;
177 v4l2_fmt.fmt.pix.height = 480;
178// v4l2_fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_GREY;
179 v4l2_fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;
180// v4l2_fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
181// v4l2_fmt.fmt.pix.field = V4L2_FIELD_NONE;
182// v4l2_fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
183
184 if (-1 == xioctl (vfile, VIDIOC_S_FMT, &v4l2_fmt)) errno_exit ("VIDIOC_S_FMT");
185
186 /* Note VIDIOC_S_FMT may change width and height. */
187
188 /* Buggy driver paranoia. */
189 min = v4l2_fmt.fmt.pix.width * 2;
190 if (v4l2_fmt.fmt.pix.bytesperline < min)
191 v4l2_fmt.fmt.pix.bytesperline = min;
192 min = v4l2_fmt.fmt.pix.bytesperline * v4l2_fmt.fmt.pix.height;
193 if (v4l2_fmt.fmt.pix.sizeimage < min)
194 v4l2_fmt.fmt.pix.sizeimage = min;
195
196 printf("fmt.fmt.pix.width = %d\n",v4l2_fmt.fmt.pix.width);
197 printf("fmt.fmt.pix.height = %d\n",v4l2_fmt.fmt.pix.height);
198 printf("fmt.fmt.pix.pixelformat = %4s\n",&v4l2_fmt.fmt.pix.pixelformat);
199 printf("fmt.fmt.pix.bytesperline = %d\n",v4l2_fmt.fmt.pix.bytesperline);
200 printf("fmt.fmt.pix.sizeimage = %d\n",v4l2_fmt.fmt.pix.sizeimage);
201// printf("fmt.fmt.pix.field = %d\n",v4l2_fmt.fmt.pix.field);
202
203 struct v4l2_queryctrl qc;
204 struct v4l2_control con;
205
206 qc.id=V4L2_CID_BRIGHTNESS;
207 ioctl(vfile,VIDIOC_QUERYCTRL,&qc);
208 printf("brightness = %d - %d by %d %d\n",qc.minimum,qc.maximum,qc.step,qc.default_value);
209
210 qc.id=V4L2_CID_CONTRAST;
211 ioctl(vfile,VIDIOC_QUERYCTRL,&qc);
212 printf("contrast = %d - %d by %d %d\n",qc.minimum,qc.maximum,qc.step,qc.default_value);
213
214 qc.id=V4L2_CID_GAMMA;
215 ioctl(vfile,VIDIOC_QUERYCTRL,&qc);
216 printf("gamma = %d - %d by %d %d\n",qc.minimum,qc.maximum,qc.step,qc.default_value);
217
218 qc.id=V4L2_CID_EXPOSURE;
219 ioctl(vfile,VIDIOC_QUERYCTRL,&qc);
220 printf("exposure = %d - %d by %d %d\n",qc.minimum,qc.maximum,qc.step,qc.default_value);
221
222 qc.id=V4L2_CID_GAIN;
223 ioctl(vfile,VIDIOC_QUERYCTRL,&qc);
224 printf("gain = %d - %d by %d %d\n",qc.minimum,qc.maximum,qc.step,qc.default_value);
225
226 con.id=V4L2_CID_AUTOGAIN;
227 con.value=0;
228 ioctl(vfile,VIDIOC_S_CTRL,&con);
229
230 if (brt!=-1) {
231 con.id=V4L2_CID_BRIGHTNESS;
232 con.value=brt;
233 ioctl(vfile,VIDIOC_S_CTRL,&con);
234 }
235
236 if (cont!=-1) {
237 con.id=V4L2_CID_CONTRAST;
238 con.value=cont;
239 ioctl(vfile,VIDIOC_S_CTRL,&con);
240 }
241
242 if (gamma!=-1) {
243 con.id=V4L2_CID_GAMMA;
244 con.value=gamma;
245 ioctl(vfile,VIDIOC_S_CTRL,&con);
246 }
247
248 if (expos!=-1) {
249 con.id=V4L2_CID_EXPOSURE;
250 con.value=expos;
251 ioctl(vfile,VIDIOC_S_CTRL,&con);
252 }
253
254 if (gain!=-1) {
255 con.id=V4L2_CID_GAIN;
256 con.value=gain;
257 ioctl(vfile,VIDIOC_S_CTRL,&con);
258 }
259
260// close(vfile);
261 EXITFUNC;
262 return vfile;
263}
264
265bool V4L2IO::is_valid(const void *first_block)
266{
267 ENTERFUNC;
268 return true;
269}
270
271int V4L2IO::read_header(Dict & dict, int image_index, const Region * area, bool)
272{
273 ENTERFUNC;
274
275 if(image_index == -1) {
276 image_index = 0;
277 }
278
279 if(image_index != 0) {
280 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().");
281 }
282
283 if (!initialized) init();
284
285 dict["nx"] = (int)(v4l2_fmt.fmt.pix.width);
286 dict["ny"] = (int)(v4l2_fmt.fmt.pix.height);
287 dict["nz"] = 1;
288
289 dict["datatype"] = EMUtil::EM_UCHAR;
290
291 EXITFUNC;
292 return 0;
293}
294
295int V4L2IO::write_header(const Dict & dict, int image_index, const Region*,
296 EMUtil::EMDataType, bool)
297{
298 ENTERFUNC;
299 LOGWARN("V4L write is not supported.");
300 EXITFUNC;
301 return 1; // No write capability
302}
303
304int V4L2IO::read_data(float *data, int image_index, const Region * area, bool)
305{
306 if (!initialized) init();
307
308 Region tmp(0,0,v4l2_fmt.fmt.pix.width,v4l2_fmt.fmt.pix.height);
309 if (!area) area=&tmp;
310
311 int x,y;
312 ENTERFUNC;
313 unsigned char *dbuf = (unsigned char *)malloc(v4l2_fmt.fmt.pix.sizeimage);
314
315 read(v4l_file,dbuf,v4l2_fmt.fmt.pix.sizeimage);
316 read(v4l_file,dbuf,v4l2_fmt.fmt.pix.sizeimage);
317
318/* int count=v4l2_fmt.fmt.pix.sizeimage;
319 int pos=0;
320 while (count) {
321 int c=read(v4l_file,dbuf+pos,count);
322 printf("# %d\n",c);
323 if (c==-1) { printf("ern %d\n",errno); break; }
324 count-=c;
325 pos+=c;
326 }
327
328 printf("buf.length=%d area.x=%d area.y=%d\n",v4l2_fmt.fmt.pix.sizeimage,(int)area->size[0],(int)area->size[1]);
329 */
330
331 for (y=0; y<area->size[1]; y++) {
332 for (x=0; x<area->size[0]; x++) {
333// This is for YUYV
334// data[(int)(area->size[0]*(area->size[1]-y-1)+x)]=dbuf[v4l2_fmt.fmt.pix.bytesperline*y+x*2]/256.0;
335// This is for YUV420
336// data[(int)(area->size[0]*(area->size[1]-y-1)+x)]=dbuf[v4l2_fmt.fmt.pix.bytesperline*y+x]/256.0;
337 data[(int)(area->size[0]*(area->size[1]-y-1)+x)]=dbuf[(int)area->size[0]*y+x]/256.0;
338 }
339 }
340
341// int sum=0;
342// for (x=0; x<v4l2_fmt.fmt.pix.sizeimage; x++) sum+=dbuf[x];
343// printf("%d\n",sum);
344
345 free(dbuf);
346 EXITFUNC;
347 return 0;
348}
349
350int V4L2IO::write_data(float *data, int image_index, const Region* ,
351 EMUtil::EMDataType, bool)
352{
353 ENTERFUNC;
354
355 EXITFUNC;
356 return 1;
357}
358
359void V4L2IO::flush()
360{
361
362}
363
364
366{
367 return false;
368}
369
371{
372 return 1;
373}
374
375#endif
Dict is a dictionary to store <string, EMObject> pair.
Definition: emobject.h:385
EMDataType
Image pixel data type used in EMAN.
Definition: emutil.h:92
@ EM_UCHAR
Definition: emutil.h:95
virtual void flush()=0
Flush the IO buffer.
virtual int write_header(const Dict &dict, int image_index=0, const Region *area=0, EMUtil::EMDataType filestoragetype=EMUtil::EM_FLOAT, bool use_host_endian=true)=0
Write a header to an image.
bool initialized
Definition: imageio.h:355
virtual int write_data(float *data, int image_index=0, const Region *area=0, EMUtil::EMDataType filestoragetype=EMUtil::EM_FLOAT, bool use_host_endian=true)=0
Write data to an image.
virtual bool is_complex_mode()=0
Is this an complex image or not.
virtual int read_header(Dict &dict, int image_index=0, const Region *area=0, bool is_3d=false)=0
Read the header from an image.
virtual int read_data(float *data, int image_index=0, const Region *area=0, bool is_3d=false)=0
Read the data from an image.
FILE * file
Definition: imageio.h:354
virtual void init()=0
Do some initialization before doing the read/write.
virtual bool is_image_big_endian()=0
Is this image in big endian or not.
Region defines a 2D or 3D rectangular region specified by its origin coordinates and all edges' sizes...
Definition: geometry.h:497
FloatSize size
Definition: geometry.h:655
static int globalinit(const char *fsp, int input=0, int brt=-1, int cont=-1, int gamma=-1, int expos=-1, int gain=-1)
int ny
Definition: v4l2io.h:62
static bool is_valid(const void *first_block)
int nx
Definition: v4l2io.h:61
char * filename
Definition: v4l2io.h:57
int v4l_file
Definition: v4l2io.h:58
#define ImageReadException(filename, desc)
Definition: exception.h:204
#define LOGWARN
Definition: log.h:53
#define ENTERFUNC
Definition: log.h:48
#define EXITFUNC
Definition: log.h:49
E2Exception class.
Definition: aligner.h:40
#define y(i, j)
Definition: projector.cpp:1516
#define x(i)
Definition: projector.cpp:1517