root/vic/branches/mpeg4/video/grabber-v4l2.cpp @ 4340

Revision 4340, 47.6 KB (checked in by douglask, 5 years ago)

Code now supports 720x576, 360x288 & 180x144.

In particular, the Kworld USB2800 only supports 360x288, 360x576 & 720x288, so VIC V4L2 capture now works for it with 360x288.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* =========================================================================
2
3     Copyright (c) 1997 Regents of Koji OKAMURA, oka@kobe-u.ac.jp
4     All rights reserved.
5
6     largely rewritten for new bttv/video4linux interface
7     by Gerd Knorr <kraxel@cs.tu-berlin.de>
8
9     Added brightness, contrast, hue and saturation controls.
10     by Jean-Marc Orliaguet <jmo@medialab.chalmers.se>
11
12     Added support for various YUV byte orders.
13     by Jean-Marc Orliaguet <jmo@medialab.chalmers.se>
14
15     Added support for NTSC/PAL/SECAM video norm selection. (14/10/99)
16     by Jean-Marc Orliaguet <jmo@medialab.chalmers.se>
17
18     Early stage V4L2 implementation. (v0.92a)
19     by Jean-Marc Orliaguet <jmo@medialab.chalmers.se>
20     Capture code taken from xcaptest.c V4L2 demo app (Bill Dirks)
21     Some code contributed by Malcolm Caldwell <malcolm@it.ntu.edu.au>
22
23     Added support for MJPEG/JPEG.
24     Added gamma and gain controls.
25     by Douglas Kosovic <douglask@itee.uq.edu.au>
26     MJPEG/JPEG support uses Tiny Jpeg Decoder from :
27     http://www.saillard.org/programs_and_patches/tinyjpegdecoder/
28
29   ========================================================================= */
30
31#include <stdio.h>
32#include <stdlib.h>
33#include <unistd.h>
34#include <string.h>
35#include <signal.h>
36#include <errno.h>
37#include <endian.h>
38
39#include <sys/types.h>
40#include <sys/fcntl.h>
41#include <sys/ioctl.h>
42#include <sys/time.h>
43#include <sys/mman.h>
44
45#include <X11/Xlib.h>
46#include <X11/Xutil.h>
47#include <X11/keysym.h>
48
49extern "C"
50{
51#include <asm/types.h>
52#include <linux/videodev2.h>
53}
54
55#ifdef HAVE_LIBV4L
56#include <libv4l2.h>
57#else
58#define v4l2_open open
59#define v4l2_close close
60#define v4l2_ioctl ioctl
61#define v4l2_read read
62#define v4l2_mmap mmap
63#define v4l2_munmap munmap
64#include "tinyjpeg.h"
65#endif
66
67#include "grabber.h"
68#include "vic_tcl.h"
69#include "device-input.h"
70#include "module.h"
71
72/* here you can tune the device names */
73static const char *devlist[] = {
74    "/dev/video0", "/dev/video1", "/dev/video2", "/dev/video3",
75    "/dev/video4", "/dev/video5", "/dev/video6", "/dev/video7",
76    "/dev/video8", "/dev/video9", "/dev/video10", "/dev/video11",
77    NULL
78};
79
80#define PAL_BT601_WIDTH   720
81#define PAL_BT601_HEIGHT  576
82#define VGA_WIDTH  640
83#define VGA_HEIGHT 480
84#define CIF_WIDTH   352
85#define CIF_HEIGHT  288
86
87#define CF_422 0
88#define CF_420 1
89#define CF_CIF 2
90
91#define CS_VC        0 /* 4CIF (704x576), CIF (352x288), QCIF (176x144) */
92#define CS_VGA       1 /* VGA (640x480), 1/4 VGA (320x240), 1/16 VGA (160x120) */
93#define CS_BT601_PAL 2 /* ITU-R Recommendation BT.601 720x576 (plus 360x288 & 180x144) */
94
95/* YUV Byte order */
96#define BYTE_ORDER_YUYV 0
97#define BYTE_ORDER_YVYU 1
98#define BYTE_ORDER_UYVY 2
99#define BYTE_ORDER_VYUY 3
100
101/* V4L2 driver specific controls */
102#ifndef V4L2_CID_POWER_LINE_FREQUENCY
103#define V4L2_CID_POWER_LINE_FREQUENCY (V4L2_CID_PRIVATE_BASE + 1)
104#endif
105#ifndef V4L2_CID_FOCUS_AUTO
106#define V4L2_CID_FOCUS_AUTO           (V4L2_CID_PRIVATE_BASE + 4)
107#endif
108#ifndef V4L2_CID_FOCUS_ABSOLUTE
109#define V4L2_CID_FOCUS_ABSOLUTE       (V4L2_CID_PRIVATE_BASE + 5)
110#endif
111#ifndef V4L2_CID_FOCUS_RELATIVE
112#define V4L2_CID_FOCUS_RELATIVE       (V4L2_CID_PRIVATE_BASE + 6)
113#endif
114
115typedef struct tag_vimage
116{
117        struct v4l2_buffer      vidbuf;
118        char                    *data;
119}       VIMAGE;
120
121
122#define STREAMBUFS 2
123
124class V4l2Grabber : public Grabber
125{
126public:
127        V4l2Grabber(const char * cformat, const char *dev);
128        virtual ~V4l2Grabber();
129
130        virtual int  command(int argc, const char*const* argv);
131        virtual void start();
132        virtual void stop();
133        virtual int  grab();
134
135
136protected:
137        void format();
138        void setsize();
139
140        void packed422_to_planar422(char *, const char*);
141        void packed422_to_planar420(char *, const char*);
142
143#ifndef HAVE_LIBV4L
144        void jpeg_to_planar420(char *, const char*);
145#endif
146
147        void setctrl(int, int, const char *, int);
148
149        struct v4l2_capability   capability;
150        struct v4l2_input        *inputs;
151        struct v4l2_input        input;
152        struct v4l2_queryctrl    qctrl;
153        struct v4l2_format       fmt;
154        struct v4l2_requestbuffers req;
155
156        /* mmap */
157        int                      have_mmap;
158        VIMAGE                   vimage[STREAMBUFS];
159        struct v4l2_buffer       tempbuf;
160        int                      buf_sync;
161
162        __u32   pixelformat;
163        int fd_;
164        int format_;
165        int have_YUV422;
166        int have_YUV422P;
167        int have_YUV420P;
168        int have_MJPEG;
169        int have_JPEG;
170
171        int byteorder_;
172        int cformat_;
173        int port_;
174        int norm_;
175
176        unsigned char *tm_;
177        int width_;
178        int height_;
179        int max_width_;
180        int max_height_;
181        int decimate_;
182        int bytesused_;
183
184#ifndef HAVE_LIBV4L
185        struct jdec_private *jpegdec_;
186#endif
187};
188
189/* ----------------------------------------------------------------- */
190
191class V4l2Device : public InputDevice
192{
193public:
194        V4l2Device(const char *dev, const char*, char *attr);
195        virtual int command(int argc, const char*const* argv);
196
197private:
198        const char *dev_;
199};
200
201
202V4l2Device::V4l2Device(const char *dev, const char *name, char *attr) : InputDevice(name)
203{
204        dev_ = dev;
205        attributes_ = attr;
206        debug_msg("V4L2:  ==> %s\n",attr);
207}
208
209int V4l2Device::command(int argc, const char*const* argv)
210{
211        Tcl& tcl = Tcl::instance();
212
213
214        if (argc == 3) {
215                if (strcmp(argv[1], "open") == 0) {
216                        TclObject* o = 0;
217                        o = new V4l2Grabber(argv[2],dev_);
218                        if (o != 0)
219                                tcl.result(o->name());
220                        return (TCL_OK);
221                }
222
223        }
224        return (InputDevice::command(argc, argv));
225}
226
227/* ----------------------------------------------------------------- */
228
229class V4l2Scanner
230{
231public:
232        V4l2Scanner(const char **dev);
233};
234
235static V4l2Scanner find_video4linux_devices(devlist);
236
237V4l2Scanner::V4l2Scanner(const char **dev)
238{
239        struct v4l2_capability   capability;
240        struct v4l2_input        input;
241
242        int  k,i,err,fd;
243        char *nick, *attr;
244
245        // VIC_DEVICE env variable selects V4L device with AGTk 3.02 and earlier
246        // but doesn't work if V4L2 devices are listed before the V4L device
247        // so don't list V4L2 devices if VIC_DEVICE env variable is set.
248        const char *myDev = getenv("VIC_DEVICE");
249        if (myDev != 0)
250        {
251                 return;
252        }
253
254        for (i = 0; dev[i] != NULL; i++) {
255                debug_msg("V4L2: trying %s... ",dev[i]);
256                if (-1 == (fd = v4l2_open(dev[i],O_RDWR))) {
257                        debug_msg("Error opening: %s : %s\n", dev[i], strerror(errno));
258                        continue;
259                }
260#ifdef HAVE_LIBV4L
261                if (-1 == v4l2_fd_open(fd,V4L2_ENABLE_ENUM_FMT_EMULATION)) {
262                        perror("V4L2: v4l2_fd_open V4L2_ENABLE_ENUM_FMT_EMULATION");
263                        v4l2_close(fd);
264                        continue;
265                }
266#endif
267                memset(&capability,0,sizeof(capability));
268                if (-1 == v4l2_ioctl(fd,VIDIOC_QUERYCAP,&capability)) {
269                        perror("V4L2: ioctl VIDIOC_QUERYCAP");
270                        v4l2_close(fd);
271                        continue;
272                }
273
274                if (capability.capabilities & V4L2_CAP_VIDEO_CAPTURE == 0) {
275                        debug_msg("%s, %s can't capture\n",capability.card,capability.bus_info);
276                        v4l2_close(fd);
277                        continue;
278                }
279
280                attr = new char[512];
281                strcpy(attr,"format { 420 422 cif } ");
282                strcat(attr,"size { small large cif } ");
283
284                debug_msg("V4L2:   ports:");
285                strcat(attr,"port { ");
286                //input.index = 0;
287                memset(&input, 0, sizeof(input));
288                while (-1 != v4l2_ioctl(fd, VIDIOC_ENUMINPUT, &input)) {
289                        if (-1 == v4l2_ioctl(fd,VIDIOC_S_INPUT,&input.index)) {
290                                debug_msg("ioctl VIDIOC_S_INPUT: %s", strerror(errno));
291                        } else {
292
293                                debug_msg(" %s: ", (char*)input.name);
294                                for (unsigned int s=0 ; s<strlen((char*)input.name) ; s++)
295                                        if (input.name[s]==' ') input.name[s]='-';
296                                strcat(attr,(const char*)input.name);
297                                strcat(attr," ");
298                        }
299                        input.index++;
300                }
301                debug_msg("\n");
302                strcat(attr,"} ");
303
304                debug_msg("V4L2:   norms: ");
305                strcat(attr,"type { ");
306
307                for (k = 0, err = 0; err == 0; ++k)
308                {
309                        struct v4l2_standard     estd;
310                        memset(&estd,0,sizeof(estd));
311                        estd.index = k;
312                        err = v4l2_ioctl(fd, VIDIOC_ENUMSTD, &estd);
313                        if (!err) {
314                                strcat(attr, (const char*)estd.name);
315                                strcat(attr," ");
316                                debug_msg("%s ", estd.name);
317                        }
318                }
319                debug_msg("\n");
320
321                strcat(attr,"} ");
322
323                nick = new char[strlen((char*)capability.card)+strlen(dev[i])+7];
324                sprintf(nick,"V4L2-%s %s",capability.card, dev[i]);
325                new V4l2Device(dev[i],nick,attr);
326                fprintf(stderr, "Attached to V4L2 device: %s\n", nick);
327                v4l2_close(fd);
328        }
329}
330
331/* ----------------------------------------------------------------- */
332
333V4l2Grabber::V4l2Grabber(const char *cformat, const char *dev)
334{
335
336        fd_ = open(dev, O_RDWR);
337        if (fd_ < 0) {
338                perror("open");
339                return;
340        }
341        have_mmap = 0;
342        have_YUV422 = 0;
343        have_YUV422P = 0;
344        have_YUV420P = 0;
345        have_MJPEG = 0;
346        have_JPEG = 0;
347
348#ifndef HAVE_LIBV4L
349        jpegdec_ = NULL;
350#endif
351
352        struct v4l2_capability cap;
353        memset(&cap,0,sizeof(cap));
354        if (-1 == v4l2_ioctl(fd_,VIDIOC_QUERYCAP,&cap)) {
355                perror("ioctl VIDIOC_QUERYCAP");
356        } else {
357                if ( !(cap.capabilities & V4L2_CAP_READWRITE) && !(cap.capabilities & V4L2_CAP_STREAMING)) {
358                        debug_msg("V4L2: fatal: device does not support read()/write() calls or streaming capture.\n");
359                        status_=-1;
360                        return;
361                }
362        }
363
364        memset(&fmt,0,sizeof(fmt));
365        fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
366        v4l2_ioctl(fd_, VIDIOC_G_FMT, &fmt);
367
368        unsigned int test_width[] =  {CIF_WIDTH,  PAL_BT601_WIDTH/2,  VGA_WIDTH/2,  0};
369        unsigned int test_height[] = {CIF_HEIGHT, PAL_BT601_HEIGHT/2, VGA_HEIGHT/2, 0};
370        for (unsigned int i = 0; test_width[i] != 0; i++) {
371                fmt.fmt.pix.width = test_width[i];
372                fmt.fmt.pix.height = test_height[i];
373                fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;
374                if (-1 != v4l2_ioctl(fd_, VIDIOC_S_FMT, &fmt) ) {
375                        if (fmt.fmt.pix.height == test_height[i] && fmt.fmt.pix.width == test_width[i]) {
376                                have_YUV420P = 1;
377                                debug_msg("Device supports V4L2_PIX_FMT_YUV420 capture at %dx%d\n",test_width[i],test_height[i]);
378                        } else {
379                                debug_msg("V4L2_PIX_FMT_YUV420 capture at %dx%d not supported, returned %dx%d\n",test_width[i],test_height[i],fmt.fmt.pix.width,fmt.fmt.pix.height);
380                        }
381                }
382
383                fmt.fmt.pix.width = test_width[i];
384                fmt.fmt.pix.height = test_height[i];
385                fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV422P;
386                if (-1 != v4l2_ioctl(fd_, VIDIOC_S_FMT, &fmt) ) {
387                        if (fmt.fmt.pix.height == test_height[i] && fmt.fmt.pix.width == test_width[i]) {
388                                have_YUV422P = 1;
389                                debug_msg("Device supports V4L2_PIX_FMT_YUV422 capture at %dx%d\n",test_width[i],test_height[i]);
390                        } else {
391                                debug_msg("V4L2_PIX_FMT_YUV422 capture at %dx%d not supported, returned %dx%d\n",test_width[i],test_height[i],fmt.fmt.pix.width,fmt.fmt.pix.height);
392                        }
393                }
394
395                fmt.fmt.pix.width = test_width[i];
396                fmt.fmt.pix.height = test_height[i];
397                fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
398                if (-1 != v4l2_ioctl(fd_, VIDIOC_S_FMT, &fmt) ) {
399                        if (fmt.fmt.pix.height == test_height[i] && fmt.fmt.pix.width == test_width[i]) {
400                                have_YUV422 = 1;
401                                debug_msg("Device supports V4L2_PIX_FMT_YUYV (YUV 4:2:2) capture at %dx%d\n",test_width[i],test_height[i]);
402                        } else {
403                                debug_msg("V4L2_PIX_FMT_YUYV (YUV 4:2:2) capture at %dx%d not supported, returned %dx%d\n",test_width[i],test_height[i],fmt.fmt.pix.width,fmt.fmt.pix.height);
404                        }
405                }
406
407#ifdef HAVE_LIBV4L
408                fmt.fmt.pix.width = test_width[i];
409                fmt.fmt.pix.height = test_height[i];
410                fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
411                if (-1 != v4l2_ioctl(fd_, VIDIOC_S_FMT, &fmt) ) {
412                        if (fmt.fmt.pix.height == test_height[i] && fmt.fmt.pix.width == test_width[i]) {
413                                have_MJPEG = 1;
414                                debug_msg("Device supports V4L2_PIX_FMT_MJPEG capture at %dx%d\n",test_width[i],test_height[i]);
415                        } else {
416                                debug_msg("V4L2_PIX_FMT_MJPEG capture at %dx%d not supported, returned %dx%d\n",test_width[i],test_height[i],fmt.fmt.pix.width,fmt.fmt.pix.height);
417                        }
418                }
419
420                fmt.fmt.pix.width = test_width[i];
421                fmt.fmt.pix.height = test_height[i];
422                fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG;
423                if (-1 != v4l2_ioctl(fd_, VIDIOC_S_FMT, &fmt) ) {
424                        if (fmt.fmt.pix.height == test_height[i] && fmt.fmt.pix.width == test_width[i]) {
425                                have_MJPEG = 1;
426                                debug_msg("Device supports V4L2_PIX_FMT_JPEG capture at %dx%d\n",test_width[i],test_height[i]);
427                        } else {
428                                debug_msg("V4L2_PIX_FMT_JPEG capture at %dx%d not supported, returned %dx%d\n",test_width[i],test_height[i],fmt.fmt.pix.width,fmt.fmt.pix.height);
429                        }
430                }
431#endif
432        }
433
434        if( !( have_YUV422P || have_YUV422 || have_YUV420P || have_MJPEG || have_JPEG)){
435                debug_msg("No suitable pixelformat found\n");
436                v4l2_close(fd_);
437                status_=-1;
438                return;
439        }
440
441        struct v4l2_requestbuffers reqbuf;
442        memset(&reqbuf,0,sizeof(reqbuf));
443        reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
444        reqbuf.memory = V4L2_MEMORY_MMAP;
445        reqbuf.count = 20;
446        have_mmap = 1;
447        if (-1 == v4l2_ioctl(fd_, VIDIOC_REQBUFS, &reqbuf)) {
448                if (errno == EINVAL) {
449                        printf("Video capturing or mmap-streaming is not supported\n");
450                        have_mmap = 0;
451                        status_=-1;
452                } else {
453                        perror ("VIDIOC_REQBUFS");
454                        have_mmap = 0;
455                }
456        }
457
458        /* fill in defaults */
459        if(!strcmp(cformat, "420"))
460                cformat_ = CF_420;
461        if(!strcmp(cformat, "422"))
462                cformat_ = CF_422;
463        if(!strcmp(cformat, "cif"))
464                cformat_ = CF_CIF;
465
466        port_      = 0;
467        norm_      = 0;
468        decimate_  = 2;
469        running_   = 0;
470
471}
472
473
474V4l2Grabber::~V4l2Grabber()
475{
476        int i;
477        debug_msg("V4L2: destructor\n");
478
479        if (have_mmap) {
480                for (i = 0; i < STREAMBUFS; ++i) {
481                        if (vimage[i].data)
482                                v4l2_munmap(vimage[i].data,
483                                            vimage[i].vidbuf.length);
484                        vimage[i].data = NULL;
485                }
486        } else {
487                if (vimage[0].data)
488                        free(vimage[0].data);
489                vimage[0].data = NULL;
490        }
491        v4l2_close(fd_);
492
493#ifndef HAVE_LIBV4L
494        if (jpegdec_) {
495                tinyjpeg_free(jpegdec_);
496        }
497#endif
498
499}
500
501int V4l2Grabber::command(int argc, const char*const* argv)
502{
503        int i, err;
504
505        Tcl &tcl = Tcl::instance();
506
507        byteorder_ = 0;
508
509        if ( tcl.attr("yuv_byteOrder") != NULL )
510                byteorder_ = atoi( tcl.attr("yuv_byteOrder") );
511
512        if ( ! ((byteorder_ >= 0) && (byteorder_ <= 3)) ) byteorder_=0;
513
514        if (argc == 3) {
515                if (strcmp(argv[1], "decimate") == 0) {
516                        decimate_ = atoi(argv[2]);
517
518                        if (running_) {
519                                stop(); start();
520                        }
521                        return (TCL_OK);
522                }
523
524                if (strcmp(argv[1], "port") == 0) {
525
526                        for (i = 0, err = 0; err == 0; ++i) {
527                                struct v4l2_input inp;
528                                memset(&inp,0,sizeof(inp));
529                                inp.index = i;
530                                err = v4l2_ioctl(fd_, VIDIOC_ENUMINPUT, &inp);
531                                if (!err) {
532
533                                        char input[32];
534                                        unsigned int s;
535                                        for ( s=0 ; s<= strlen((const char*)inp.name) ; s++ )
536                                                        if (inp.name[s]==' ') input[s]='-'; else input[s]=inp.name[s];
537
538                                        if ( !strcmp(input,argv[2])) {
539                                                port_ = i;
540                                                break;
541                                        }
542                                }
543                        }
544                        if (running_) {
545                                stop(); start();
546                        }
547
548                        return (TCL_OK);
549                }
550
551
552                if (strcmp(argv[1], "brightness") == 0) {
553                        setctrl(atoi(argv[2]), V4L2_CID_BRIGHTNESS, "Brightness", 0);
554                        return (TCL_OK);
555                }
556
557                if (strcmp(argv[1], "hue") == 0) {
558                        setctrl(atoi(argv[2]), V4L2_CID_HUE, "Hue", 0);
559                        return (TCL_OK);
560                }
561
562                if (strcmp(argv[1], "contrast") == 0) {
563                        setctrl(atoi(argv[2]), V4L2_CID_CONTRAST, "Contrast", 0);
564                        return (TCL_OK);
565                }
566
567                if (strcmp(argv[1], "saturation") == 0) {
568                        setctrl(atoi(argv[2]), V4L2_CID_SATURATION, "Saturation", 0);
569                        return (TCL_OK);
570                }
571
572                if (strcmp(argv[1], "gamma") == 0) {
573                        setctrl(atoi(argv[2]), V4L2_CID_GAMMA, "Gamma", 0);
574                        return (TCL_OK);
575                }
576
577                if (strcmp(argv[1], "gain") == 0) {
578                        setctrl(atoi(argv[2]), V4L2_CID_GAIN, "Gain", 0);
579                        return (TCL_OK);
580                }
581
582                if (strcmp(argv[1], "antiflicker") == 0) {
583                        struct v4l2_queryctrl qctrl;
584                        struct v4l2_control ctrl;
585
586                        memset (&qctrl, 0, sizeof(qctrl));
587                        qctrl.id = V4L2_CID_POWER_LINE_FREQUENCY;
588                        if (-1 != v4l2_ioctl(fd_, VIDIOC_QUERYCTRL, &qctrl)) {
589                                if (strcmp((char *)qctrl.name, "Power Line Frequency") == 0) {
590                                        ctrl.id = qctrl.id;
591                                        ctrl.value = atoi(argv[2]);
592                                        if (-1 == v4l2_ioctl(fd_, VIDIOC_S_CTRL, &ctrl))
593                                                perror("ioctl  VIDIOC_S_CTRL");
594                                        else
595                                                debug_msg( "V4L2: V4L2_CID_POWER_LINE_FREQUENCY = %d\n", ctrl.value);
596                                 }
597                        }
598                        return (TCL_OK);
599                }
600
601                if (strcmp(argv[1], "controls") == 0) {
602                        if (strcmp(argv[2], "reset") == 0) {
603                                debug_msg( "V4L2: Resetting controls\n");
604
605                                setctrl(atoi(argv[2]), V4L2_CID_BRIGHTNESS, "Brightness", 1);
606                                setctrl(atoi(argv[2]), V4L2_CID_HUE, "Hue", 1);
607                                setctrl(atoi(argv[2]), V4L2_CID_CONTRAST, "Contrast", 1);
608                                setctrl(atoi(argv[2]), V4L2_CID_SATURATION, "Saturation", 1);
609                                setctrl(atoi(argv[2]), V4L2_CID_GAMMA, "Gamma", 1);
610                                setctrl(atoi(argv[2]), V4L2_CID_GAIN, "Gain", 1);
611                                return (TCL_OK);
612                        }
613                }
614
615                if (strcmp(argv[1], "yuv_byteorder") == 0) {
616                        debug_msg("V4L2: asked for yuv_byteorder\n");
617                        return (TCL_OK);
618                }
619
620                if (strcmp(argv[1], "fps") == 0) {
621                        debug_msg("V4L2: fps %s\n",argv[2]);
622                }
623
624
625                if (strcmp(argv[1], "type") == 0 || strcmp(argv[1], "format") == 0) {
626
627                        for (int k = 0, err = 0; err == 0; ++k)
628                        {
629                                struct v4l2_standard     estd;
630                                memset(&estd,0,sizeof(estd));
631                                estd.index = k;
632                                if ( !(err = v4l2_ioctl(fd_, VIDIOC_ENUMSTD, &estd)) )
633                                        if ( strcasecmp(argv[2], (const char *)estd.name) == 0)
634                                                norm_ = k;
635                        }
636
637                        if (running_) {
638                                stop(); start();
639                        }
640
641                        return (TCL_OK);
642                }
643
644        } else if (argc == 2) {
645                if (strcmp(argv[1], "format") == 0 ||
646                        strcmp(argv[1], "type") == 0) {
647                        return (TCL_OK);
648                }
649        }
650
651        return (Grabber::command(argc, argv));
652}
653
654void V4l2Grabber::start()
655{
656        int     err;
657        int     i;
658
659        if (fd_ > 0 ) {
660                debug_msg("\nV4L2: start\n");
661
662                format();
663
664                if (have_mmap) {
665                        buf_sync = 1;
666
667                        memset(&req, 0, sizeof(req));
668                        req.count = STREAMBUFS;
669                        req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
670                        req.memory = V4L2_MEMORY_MMAP;
671                        err = v4l2_ioctl(fd_, VIDIOC_REQBUFS, &req);
672                        if (err < 0 || req.count < 1) {
673                                debug_msg("REQBUFS returned error %d, count %d\n", errno,req.count);
674                                return;
675                        }
676
677                        for (i = 0; i < (int)req.count; ++i) {
678                                vimage[i].vidbuf.index = i;
679                                vimage[i].vidbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
680                                vimage[i].vidbuf.memory = V4L2_MEMORY_MMAP;
681                                err = v4l2_ioctl(fd_, VIDIOC_QUERYBUF, &vimage[i].vidbuf);
682                                if (err < 0) {
683                                        debug_msg("QUERYBUF returned error %d\n", errno);
684                                        return;
685                                }
686                                vimage[i].data = (typeof(vimage[0].data)) v4l2_mmap(0,  vimage[i].vidbuf.length, PROT_READ|PROT_WRITE, MAP_SHARED, fd_, vimage[i].vidbuf.m.offset);
687
688                                if ((long)vimage[i].data == -1) {
689                                        debug_msg("V4L2: mmap() returned error %d\n", errno);
690                                        return;
691                                } else debug_msg("V4L2: mmap()'ed buffer at 0x%lx (%u bytes)\n", (unsigned long)vimage[i].data, vimage[i].vidbuf.length);
692                        }
693
694                        for (i = 0; i < (int)req.count; ++i)
695                                if ((err = v4l2_ioctl(fd_, VIDIOC_QBUF, &vimage[i].vidbuf))) {
696                                        debug_msg("QBUF returned error %d\n",errno);
697                                        return;
698                                }
699
700                        err = v4l2_ioctl(fd_, VIDIOC_STREAMON, &vimage[0].vidbuf.type);
701                        if (err)
702                                debug_msg("STREAMON returned error %d\n",errno);
703
704                } else {
705                        vimage[0].data = (typeof(vimage[0].data)) malloc(fmt.fmt.pix.sizeimage);
706
707                        if (vimage[0].data == NULL) {
708                                debug_msg("malloc(%d) failed\n", fmt.fmt.pix.sizeimage);
709                                return;
710                        } else debug_msg("V4L2: malloc()'ed buffer (%d bytes)\n", fmt.fmt.pix.sizeimage);
711                }
712
713                Grabber::start();
714                running_ = 1;
715        }
716}
717
718void V4l2Grabber::stop()
719{
720        debug_msg("V4L2: stop\n");
721        int i, err;
722
723        if (have_mmap) {
724                if ( fd_ > 0 ) {
725                        i = V4L2_BUF_TYPE_VIDEO_CAPTURE;
726                        if ( (err = v4l2_ioctl(fd_, VIDIOC_STREAMOFF, &i) ) )
727                                debug_msg("V4L2: VIDIOC_STREAMOFF failed\n");
728                }
729
730                tempbuf.type = vimage[0].vidbuf.type;
731                while ((err = v4l2_ioctl(fd_, VIDIOC_DQBUF, &tempbuf)) < 0 &&
732                       (errno == EINTR));
733
734                if (err < 0) {
735                        debug_msg("V4L2: VIDIOC_DQBUF failed: %s\n", strerror(errno));
736                }
737
738                for (i = 0; i < STREAMBUFS; ++i) {
739                        if (vimage[i].data)
740                                err = v4l2_munmap(vimage[i].data, vimage[i].vidbuf.length);
741                        vimage[i].data = NULL;
742                }
743
744
745        } else {
746                if (vimage[0].data)
747                        free(vimage[0].data);
748                vimage[0].data = NULL;
749        }
750
751        Grabber::stop();
752        running_ = 0;
753}
754
755int V4l2Grabber::grab()
756{
757        char  *fr=NULL;
758        fd_set                  rdset;
759        struct timeval          timeout;
760        int                     n;
761
762        bytesused_ = 0;
763        if (have_mmap) {
764                FD_ZERO(&rdset);
765                FD_SET(fd_, &rdset);
766                timeout.tv_sec = 0;
767                timeout.tv_usec = 0;
768                n = select(fd_+1, &rdset, NULL, NULL, &timeout);
769
770                if (n == 0)
771                        return (0);
772                else if (FD_ISSET(fd_, &rdset)) {
773                        memset(&tempbuf, 0, sizeof(struct v4l2_buffer));
774                        tempbuf.type = vimage[0].vidbuf.type;
775                        tempbuf.memory = vimage[0].vidbuf.memory;
776                        if (-1 == v4l2_ioctl(fd_, VIDIOC_DQBUF, &tempbuf))
777                                perror("ioctl  VIDIOC_DQBUF");
778
779                        if (  (req.count > 1) ) buf_sync++;
780                        fr = vimage[buf_sync%2].data;
781                        bytesused_ = tempbuf.bytesused;
782
783                }
784
785        } else {
786                fr = vimage[0].data;
787                v4l2_read(fd_, vimage[0].data, fmt.fmt.pix.sizeimage);
788                bytesused_ = fmt.fmt.pix.sizeimage;
789        }
790
791        switch (cformat_) {
792        case CF_420:
793        case CF_CIF:
794                if( have_YUV420P )
795                       memcpy((void *)frame_, (const void *)fr, (size_t)height_*width_*3/2)
796;
797                else if( have_YUV422 )
798                       packed422_to_planar420((char*)frame_,fr);
799#ifndef HAVE_LIBV4L
800                else if( have_MJPEG || have_JPEG) {
801                       jpeg_to_planar420((char*)frame_,fr);
802                }
803#endif
804                break;
805
806        case CF_422:
807                if (have_YUV422P)
808                       memcpy((void *)frame_, (const void *)fr, (size_t)height_*width_*2);
809                else if( have_YUV422 )
810                       packed422_to_planar422((char*)frame_,fr);
811#ifndef HAVE_LIBV4L
812                else if( have_MJPEG  || have_JPEG)
813                       // jpeg_to_planar422((char*)frame_,fr);
814#endif
815                break;
816        }
817
818        if (have_mmap)
819                v4l2_ioctl(fd_, VIDIOC_QBUF, &vimage[buf_sync%2].vidbuf);
820
821        suppress(frame_);
822        saveblks(frame_);
823        YuvFrame f(media_ts(), frame_, crvec_, outw_, outh_);
824        return (target_->consume(&f));
825}
826
827
828void V4l2Grabber::packed422_to_planar422(char *dest, const char *src)
829{
830    int i;
831    char *y,*u,*v;
832    unsigned int a, *srca;
833
834    srca = (unsigned int *)src;
835
836    i = (width_ * height_)/2;
837    y = dest;
838    u = y + width_ * height_;
839    v = u + width_ * height_ / 2;
840
841    switch (byteorder_) {
842    case BYTE_ORDER_YUYV:
843        while (--i) {
844                a = *(srca++);
845#if BYTE_ORDER == LITTLE_ENDIAN 
846                *(y++) = a & 0xff;
847                a >>= 8;
848                *(u++) = a & 0xff;
849                a >>= 8;
850                *(y++) = a & 0xff;
851                a >>= 8;
852                *(v++) = a & 0xff;
853#else
854                *(v++) = a & 0xff;
855                a >>= 8;
856                *(y++) = a & 0xff;
857                a >>= 8;
858                *(u++) = a & 0xff;
859                a >>= 8;
860                *(y++) = a & 0xff;
861#endif
862        }
863        break;
864
865    case BYTE_ORDER_YVYU:
866        while (--i) {
867                a = *(srca++);
868#if BYTE_ORDER == LITTLE_ENDIAN 
869                *(y++) = a & 0xff;
870                a >>= 8;
871                *(v++) = a & 0xff;
872                a >>= 8;
873                *(y++) = a & 0xff;
874                a >>= 8;
875                *(u++) = a & 0xff;
876#else
877                *(u++) = a & 0xff;
878                a >>= 8;
879                *(y++) = a & 0xff;
880                a >>= 8;
881                *(v++) = a & 0xff;
882                a >>= 8;
883                *(y++) = a & 0xff;
884#endif
885        }
886        break;
887
888    case BYTE_ORDER_UYVY:
889        while (--i) {
890                a = *(srca++);
891#if BYTE_ORDER == LITTLE_ENDIAN 
892                *(u++) = a & 0xff;
893                a >>= 8;
894                *(y++) = a & 0xff;
895                a >>= 8;
896                *(v++) = a & 0xff;
897                a >>= 8;
898                *(y++) = a & 0xff;
899#else
900                *(y++) = a & 0xff;
901                a >>= 8;
902                *(v++) = a & 0xff;
903                a >>= 8;
904                *(y++) = a & 0xff;
905                a >>= 8;
906                *(u++) = a & 0xff;
907#endif
908        }
909        break;
910
911    case BYTE_ORDER_VYUY:
912        while (--i) {
913                a = *(srca++);
914#if BYTE_ORDER == LITTLE_ENDIAN 
915                *(v++) = a & 0xff;
916                a >>= 8;
917                *(y++) = a & 0xff;
918                a >>= 8;
919                *(u++) = a & 0xff;
920                a >>= 8;
921                *(y++) = a & 0xff;
922#else
923                *(y++) = a & 0xff;
924                a >>= 8;
925                *(u++) = a & 0xff;
926                a >>= 8;
927                *(y++) = a & 0xff;
928                a >>= 8;
929                *(v++) = a & 0xff;
930#endif
931        }
932        break;
933    }
934
935}
936
937void V4l2Grabber::packed422_to_planar420(char *dest, const char *src)
938{
939    int  a1,b;
940    char *y,*u,*v;
941    unsigned int a, *srca;
942
943    srca = (unsigned int *)src;
944
945    y = dest;
946    u = y + width_ * height_;
947    v = u + width_ * height_ / 4;
948
949    switch (byteorder_) {
950    case BYTE_ORDER_YUYV:
951        for (a1 = height_; a1 > 0; a1 -= 2) {
952                for (b = width_; b > 0; b -= 2) {
953                        a = *(srca++);
954#if BYTE_ORDER == LITTLE_ENDIAN 
955                        *(y++) = a & 0xff; a >>= 8;
956                        *(u++) = a & 0xff; a >>= 8;
957                        *(y++) = a & 0xff; a >>= 8;
958                        *(v++) = a & 0xff;
959#else
960                        *(v++) = a & 0xff; a >>= 8;
961                        *(y+1) = a & 0xff; a >>= 8;
962                        *(u++) = a & 0xff; a >>= 8;
963                        *(y) = a;  y += 2;
964#endif
965                }
966                for (b = width_; b > 0; b -= 2) {
967                        a = *(srca++);
968#if BYTE_ORDER == LITTLE_ENDIAN 
969                        *(y++) = a & 0xff; a >>= 16;
970                        *(y++) = a & 0xff;
971#else
972                        a >>= 8;
973                        *(y+1) = a & 0xff; a >>= 16;
974                        *(y) = a; y += 2;
975#endif
976                }
977        }
978        break;
979
980    case BYTE_ORDER_YVYU:
981        for (a1 = height_; a1 > 0; a1 -= 2) {
982                for (b = width_; b > 0; b -= 2) {
983                        a = *(srca++);
984#if BYTE_ORDER == LITTLE_ENDIAN 
985                        *(y++) = a & 0xff; a >>= 8;
986                        *(v++) = a & 0xff; a >>= 8;
987                        *(y++) = a & 0xff; a >>= 8;
988                        *(u++) = a & 0xff;
989#else
990                        *(u++) = a & 0xff; a >>= 8;
991                        *(y+1) = a & 0xff; a >>= 8;
992                        *(v++) = a & 0xff; a >>= 8;
993                        *(y) = a;  y += 2;
994#endif
995                }
996                for (b = width_; b > 0; b -= 2) {
997                        a = *(srca++);
998#if BYTE_ORDER == LITTLE_ENDIAN 
999                        *(y++) = a & 0xff; a >>= 16;
1000                        *(y++) = a & 0xff;
1001#else
1002                        a >>= 8;
1003                        *(y+1) = a & 0xff; a >>= 16;
1004                        *(y) = a; y += 2;
1005#endif
1006                }
1007        }
1008        break;
1009
1010    case BYTE_ORDER_UYVY:
1011        for (a1 = height_; a1 > 0; a1 -= 2) {
1012                for (b = width_; b > 0; b -= 2) {
1013                        a = *(srca++);
1014#if BYTE_ORDER == LITTLE_ENDIAN 
1015                        *(u++) = a & 0xff; a >>= 8;
1016                        *(y++) = a & 0xff; a >>= 8;
1017                        *(v++) = a & 0xff; a >>= 8;
1018                        *(y++) = a & 0xff;
1019#else
1020                        *(y+1) = a & 0xff; a >>= 8;
1021                        *(v++) = a & 0xff; a >>= 8;
1022                        *(y) = a & 0xff; a >>= 8;
1023                        *(u++) = a & 0xff;
1024                        y += 2;
1025#endif
1026                }
1027                for (b = width_; b > 0; b -= 2) {
1028                        a = *(srca++);
1029#if BYTE_ORDER == LITTLE_ENDIAN 
1030                        a >>= 8;
1031                        *(y++) = a & 0xff; a >>= 16;
1032                        *(y++) = a & 0xff;
1033#else
1034                        *(y+1) = a & 0xff; a >>= 16;
1035                        *(y) = a; y += 2;
1036#endif
1037                }
1038        }
1039        break;
1040
1041    case BYTE_ORDER_VYUY:
1042        for (a1 = height_; a1 > 0; a1 -= 2) {
1043                for (b = width_; b > 0; b -= 2) {
1044                        a = *(srca++);
1045#if BYTE_ORDER == LITTLE_ENDIAN 
1046                        *(v++) = a & 0xff; a >>= 8;
1047                        *(y++) = a & 0xff; a >>= 8;
1048                        *(u++) = a & 0xff; a >>= 8;
1049                        *(y++) = a & 0xff;
1050#else
1051                        *(y+1) = a & 0xff; a >>= 8;
1052                        *(u++) = a & 0xff; a >>= 8;
1053                        *(y) = a & 0xff; a >>= 8;
1054                        *(v++) = a & 0xff;
1055                        y += 2;
1056#endif
1057                }
1058                for (b = width_; b > 0; b -= 2) {
1059                        a = *(srca++);
1060#if BYTE_ORDER == LITTLE_ENDIAN 
1061                        a >>= 8;
1062                        *(y++) = a & 0xff; a >>= 16;
1063                        *(y++) = a & 0xff;
1064#else
1065                        *(y+1) = a & 0xff; a >>= 16;
1066                        *(y) = a; y += 2;
1067#endif
1068                }
1069        }
1070        break;
1071    }
1072}
1073
1074#ifndef HAVE_LIBV4L
1075void V4l2Grabber::jpeg_to_planar420(char *dest, const char *src)
1076{
1077        char *y,*u,*v;
1078        unsigned char *components[4];
1079
1080        y = dest;
1081        u = y + width_ * height_;
1082        v = u + width_ * height_ /4;
1083
1084        components[0] = (unsigned char *) y;
1085        components[1] = (unsigned char *) u;
1086        components[2] = (unsigned char *) v;
1087
1088        if (jpegdec_ == NULL) {
1089                jpegdec_ = tinyjpeg_init();
1090                if (jpegdec_ == NULL) {
1091                        return;
1092                }
1093                tinyjpeg_set_flags(jpegdec_, TINYJPEG_FLAGS_MJPEG_TABLE);
1094        }
1095        tinyjpeg_set_components(jpegdec_, components, 4);
1096        if (tinyjpeg_parse_header(jpegdec_, (unsigned char *)src, bytesused_) < 0) {
1097               debug_msg("V4L2 Jpeg error: %s", tinyjpeg_get_errorstring(jpegdec_));
1098               return;
1099        }
1100        if (tinyjpeg_decode(jpegdec_, TINYJPEG_FMT_YUV420P) < 0) {
1101               debug_msg("V4L2 Jpeg error: %s", tinyjpeg_get_errorstring(jpegdec_));
1102               return;
1103        }
1104}
1105#endif
1106
1107
1108void V4l2Grabber::format()
1109{
1110
1111        struct v4l2_standard    standard;
1112
1113        int i, err;
1114        int input;
1115        int format_ok = 0;
1116        int capture_standard = CS_VC; // initially try video conferencing resolutions
1117
1118        switch (cformat_) {
1119        case CF_420:
1120        case CF_CIF:
1121                if( have_YUV420P )
1122                       pixelformat = V4L2_PIX_FMT_YUV420;
1123                else if( have_YUV422 )
1124                       pixelformat = V4L2_PIX_FMT_YUYV;
1125#ifndef HAVE_LIBV4L
1126                else if( have_MJPEG )
1127                       pixelformat = V4L2_PIX_FMT_MJPEG;
1128                else if( have_JPEG )
1129                       pixelformat = V4L2_PIX_FMT_JPEG;
1130#endif
1131                break;
1132
1133        case CF_422:
1134                if (have_YUV422P)
1135                       pixelformat = V4L2_PIX_FMT_YUV422P;
1136                else if( have_YUV422 )
1137                       pixelformat = V4L2_PIX_FMT_YUYV;
1138#ifndef HAVE_LIBV4L
1139                else if( have_MJPEG )
1140                       pixelformat = V4L2_PIX_FMT_MJPEG;
1141                else if( have_JPEG )
1142                       pixelformat = V4L2_PIX_FMT_JPEG;
1143#endif
1144                break;
1145        }
1146
1147        while ( !format_ok ) {
1148                width_  = CIF_WIDTH  *2  / decimate_;
1149                height_ = CIF_HEIGHT *2  / decimate_;
1150
1151                debug_msg("V4L2: format");
1152                switch (cformat_) {
1153                case CF_CIF:
1154                        set_size_420(width_, height_);
1155                        debug_msg(" cif\n");
1156                        break;
1157                case CF_420:
1158                        set_size_420(width_, height_);
1159                        debug_msg(" 420\n");
1160                        break;
1161                case CF_422:
1162                        set_size_422(width_, height_);
1163                        debug_msg(" 422\n");
1164                        break;
1165                }
1166                debug_msg("decimate: %d\n",decimate_);
1167
1168                memset(&standard,0,sizeof(standard));
1169                standard.index = norm_;
1170                err = v4l2_ioctl(fd_, VIDIOC_ENUMSTD, &standard);
1171                if (!err) {
1172                        if (-1 == v4l2_ioctl(fd_, VIDIOC_S_STD, &standard.id))
1173                                perror("ioctl VIDIOC_S_STD");
1174                        else debug_msg("V4L2: setting norm to %s\n",standard.name);
1175                }
1176
1177                input = port_;
1178                if ((err = v4l2_ioctl(fd_, VIDIOC_S_INPUT, &input)) )
1179                        debug_msg("S_INPUT returned error %d\n",errno);
1180                else debug_msg("V4L2: setting input port to %d\n", port_);
1181
1182                for (i = 0, err = 0; err == 0; ++i) {
1183                        struct v4l2_fmtdesc     fmtd;
1184                        memset(&fmtd,0,sizeof(fmtd));
1185                        fmtd.index = i;
1186                        fmtd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1187                        err = v4l2_ioctl(fd_, VIDIOC_ENUM_FMT, &fmtd);
1188                        if (err) {
1189                                debug_msg("VIDIOC_ENUM_FMT returned error %d\n",errno);
1190                        } else {
1191                                if (fmtd.pixelformat == pixelformat) {
1192                                        memset(&fmt,0,sizeof(fmt));
1193                                        fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1194                                        v4l2_ioctl(fd_, VIDIOC_G_FMT, &fmt);
1195                                        fmt.fmt.pix.width = width_;
1196                                        fmt.fmt.pix.height = height_;
1197                                        fmt.fmt.pix.field = V4L2_FIELD_ANY;
1198                                        fmt.fmt.pix.pixelformat = pixelformat;
1199
1200                                        if ( (err = v4l2_ioctl(fd_, VIDIOC_S_FMT, &fmt) ) )
1201                                                debug_msg("\nV4L2: Failed to set format\n");
1202
1203                                        if ( ( fmt.fmt.pix.width != (unsigned int)width_ ) ||
1204                                                                ( fmt.fmt.pix.height !=  (unsigned int)height_ ) ) {
1205
1206                                                debug_msg("V4L2: failed to set format! requested %dx%d, got %dx%d\n", width_, height_, fmt.fmt.pix.width, fmt.fmt.pix.height);
1207
1208                                                switch(decimate_) {
1209                                                case 1:
1210                                                        switch (capture_standard) {
1211                                                        case CS_VC :
1212                                                                debug_msg("V4L2: trying VGA resolution ...\n");
1213                                                                width_ = VGA_WIDTH;
1214                                                                height_ = VGA_HEIGHT;
1215                                                                capture_standard = CS_VGA;
1216                                                                break;
1217                                                        case CS_VGA :
1218                                                                debug_msg("V4L2: trying ITU-R BT.601 PAL resolution ...\n");
1219                                                                width_ = PAL_BT601_WIDTH;
1220                                                                height_ = PAL_BT601_HEIGHT;
1221                                                                capture_standard = CS_BT601_PAL;
1222                                                                break;
1223                                                        default :
1224                                                                debug_msg("V4L2: trying resolution under ...\n");
1225                                                                decimate_ = 2;
1226                                                                capture_standard = CS_VC;
1227                                                        }
1228                                                        break;
1229                                                case 2:
1230                                                        switch (capture_standard) {
1231                                                        case CS_VC :
1232                                                                debug_msg("V4L2: trying 1/4 VGA resolution ...\n");
1233                                                                width_ = VGA_WIDTH / 2;
1234                                                                height_ = VGA_HEIGHT / 2;
1235                                                                capture_standard = CS_VGA;
1236                                                                break;
1237                                                        case CS_VGA :
1238                                                                debug_msg("V4L2: trying 1/4 ITU-R BT.601 PAL resolution ...\n");
1239                                                                width_ = PAL_BT601_WIDTH / 2;
1240                                                                height_ = PAL_BT601_HEIGHT / 2;
1241                                                                capture_standard = CS_BT601_PAL;
1242                                                                break;
1243                                                        default :
1244                                                                debug_msg("V4L2: trying resolution under ...\n");
1245                                                                decimate_ = 4;
1246                                                                capture_standard = CS_VC;
1247                                                        }
1248                                                        break;
1249                                                default:
1250                                                        switch (capture_standard) {
1251                                                        case CS_VC :
1252                                                                debug_msg("V4L2: trying 1/16 VGA resolution ...\n");
1253                                                                width_ = VGA_WIDTH / 4;
1254                                                                height_ = VGA_HEIGHT / 4;
1255                                                                capture_standard = CS_VGA;
1256                                                                break;
1257                                                        case CS_VGA :
1258                                                                debug_msg("V4L2: trying 1/16 ITU-R BT.601 PAL resolution ...\n");
1259                                                                width_ = PAL_BT601_WIDTH / 4;
1260                                                                height_ = PAL_BT601_HEIGHT / 4;
1261                                                                capture_standard = CS_BT601_PAL;
1262                                                                break;
1263                                                        default :
1264                                                                debug_msg("V4L2: giving up ...\n");
1265                                                                format_ok = 1;
1266                                                                capture_standard = CS_VC;
1267                                                        }
1268                                                        break;
1269
1270                                                }
1271
1272                                        } else {
1273                                                debug_msg("V4L2: setting format: width=%d height=%d\n", fmt.fmt.pix.width, fmt.fmt.pix.height);
1274                                                format_ok = 1;
1275                                        }
1276                                        break;
1277                                }
1278
1279                        }
1280                }
1281        }
1282
1283
1284        allocref();
1285}
1286
1287void V4l2Grabber::setctrl(int val, int cid, const char *controlname, int reset)
1288{
1289        struct v4l2_queryctrl qctrl;
1290        struct v4l2_control ctrl;
1291
1292        qctrl.id = cid;
1293        if (-1 != v4l2_ioctl(fd_, VIDIOC_QUERYCTRL, &qctrl)) {
1294                if ( !(qctrl.flags & V4L2_CTRL_FLAG_DISABLED) ) {
1295
1296                        ctrl.id = cid;
1297                        if ( reset )
1298                                ctrl.value = qctrl.default_value;
1299                        else
1300                                ctrl.value = qctrl.minimum + (qctrl.maximum - qctrl.minimum) * val/256;
1301                        if (-1 == v4l2_ioctl(fd_, VIDIOC_S_CTRL,&ctrl))
1302                                perror("ioctl  VIDIOC_S_CTRL");
1303                        else debug_msg( "V4L2: %s = %d\n", controlname, val);
1304                }
1305        }
1306        return;
1307}
Note: See TracBrowser for help on using the browser.