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

Revision 4342, 49.6 KB (checked in by douglask, 5 years ago)

V4L2 code fix to prevent infinite loops with broken VIDIOC_ENUM_FMT ioctls

Fix a dumb mistake with the setting of width_ and height_

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