4 * Classes to support streaming video input (grabbing) and output.
6 * Portable Windows Library
8 * Copyright (c) 1998-2000 Equivalence Pty. Ltd.
9 * Copyright (c) 2003 March Networks
11 * The contents of this file are subject to the Mozilla Public License
12 * Version 1.0 (the "License"); you may not use this file except in
13 * compliance with the License. You may obtain a copy of the License at
14 * http://www.mozilla.org/MPL/
16 * Software distributed under the License is distributed on an "AS IS"
17 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
18 * the License for the specific language governing rights and limitations
21 * The Original Code is Portable Windows Library.
23 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
25 * First V4L2 capture code written by March Networks
26 * (http://www.marchnetworks.com)
28 * This code is based on the Video4Linux 1 code.
30 * Contributor(s): Guilhem Tardy (gtardy@salyens.com)
33 * - fix the devices detection code using the new code from the V4L1 plugin
34 * - make that code work
37 * Revision 1.1 2004/09/21 12:54:23 dsandras
38 * Added initial port to the new pwlib API/V4L2 API for the video4linux 2 code of Guilhem Tardy. Thanks!
40 * Revision 1.0 2003/03/03 12:27:00 guilhem
45 #pragma implementation "vidinput_v4l2.h"
47 #include "vidinput_v4l2.h"
50 PCREATE_VIDINPUT_PLUGIN(V4L2
, PVideoInputV4l2Device
);
52 #define MAJOR(a) (int)((unsigned short) (a) >> 8)
53 #define MINOR(a) (int)((unsigned short) (a) & 0xFF)
56 ///////////////////////////////////////////////////////////////////////////////
57 // PVideoInputV4l2Device
59 PVideoInputV4l2Device::PVideoInputV4l2Device()
65 canSetFrameRate
= FALSE
;
69 PVideoInputV4l2Device::~PVideoInputV4l2Device()
75 #ifndef V4L2_PIX_FMT_H263
76 #define V4L2_PIX_FMT_H263 v4l2_fourcc('H','2','6','3')
81 const char * colourFormat
;
83 } colourFormatTab
[] = {
84 { "Grey", V4L2_PIX_FMT_GREY
}, //Entries in this table correspond
85 { "RGB32", V4L2_PIX_FMT_RGB32
}, //(line by line) to those in the
86 { "RGB24", V4L2_PIX_FMT_RGB24
}, // PVideoDevice ColourFormat table.
87 { "RGB565", V4L2_PIX_FMT_RGB565
},
88 { "RGB555", V4L2_PIX_FMT_RGB555
},
89 { "YUV411", V4L2_PIX_FMT_Y41P
},
90 { "YUV411P", V4L2_PIX_FMT_YUV411P
},
91 { "YUV420", V4L2_PIX_FMT_NV21
},
92 { "YUV420P", V4L2_PIX_FMT_YUV420
},
93 { "YUV422", V4L2_PIX_FMT_YYUV
},
94 { "YUV422P", V4L2_PIX_FMT_YUV422P
},
95 { "JPEG", V4L2_PIX_FMT_JPEG
},
96 { "H263", V4L2_PIX_FMT_H263
}
100 BOOL
PVideoInputV4l2Device::Open(const PString
& devName
, BOOL startImmediate
)
102 PTRACE(1,"PVidInDev\tOpen()\tvideoFd:" << videoFd
);
105 PTRACE(1,"PVidInDev\tOpen()\tdevName:" << devName
<< " videoFd:" << videoFd
);
106 deviceName
= devName
;
107 videoFd
= ::open((const char *)devName
, O_RDWR
);
109 PTRACE(1,"PVidInDev\topen failed : " << ::strerror(errno
));
113 PTRACE(6,"PVidInDev\topen, fd=" << videoFd
);
115 // get the device capabilities
116 if (::ioctl(videoFd
, VIDIOC_QUERYCAP
, &videoCapability
) < 0) {
117 PTRACE(1,"PVidInDev\tQUERYCAP failed : " << ::strerror(errno
));
124 canRead
= videoCapability
.capabilities
& V4L2_CAP_READWRITE
;
125 canStream
= videoCapability
.capabilities
& V4L2_CAP_STREAMING
;
126 canSelect
= videoCapability
.capabilities
& V4L2_CAP_ASYNCIO
;
128 // set height and width
129 frameHeight
= QCIFHeight
;
130 frameWidth
= QCIFWidth
;
133 // get the capture parameters
134 videoStreamParm
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
135 if (::ioctl(videoFd
, VIDIOC_G_PARM
, &videoStreamParm
) < 0) {
136 PTRACE(1,"PVidInDev\tG_PARM failed : " << ::strerror(errno
));
142 canSetFrameRate
= videoStreamParm
.parm
.capture
.capability
& V4L2_CAP_TIMEPERFRAME
;
143 PVideoDevice::SetFrameRate (10000000 * videoStreamParm
.parm
.capture
.timeperframe
.numerator
/ videoStreamParm
.parm
.capture
.timeperframe
.denominator
);
150 BOOL
PVideoInputV4l2Device::IsOpen()
156 BOOL
PVideoInputV4l2Device::Close()
158 PTRACE(1,"PVidInDev\tClose()\tvideoFd:" << videoFd
<< " started:" << started
);
166 PTRACE(6,"PVidInDev\tclose, fd=" << videoFd
);
172 canSetFrameRate
= FALSE
;
175 PTRACE(1,"PVidInDev\tClose()\tvideoFd:" << videoFd
<< " started:" << started
);
180 BOOL
PVideoInputV4l2Device::Start()
182 // automatically set mapping
183 if (!isMapped
&& !SetMapping()) {
185 canStream
= FALSE
; // don't try again
190 PTRACE(6,"PVidInDev\tstart streaming, fd=" << videoFd
);
192 struct v4l2_buffer buf
;
193 if (::ioctl(videoFd
, VIDIOC_QBUF
, &buf
) < 0) {
194 PTRACE(3,"PVidInDev\tVIDIOC_QBUF failed : " << ::strerror(errno
));
198 buf
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
200 if (::ioctl(videoFd
, VIDIOC_STREAMON
, &buf
.type
) < 0) {
201 PTRACE(3,"PVidInDev\tSTREAMON failed : " << ::strerror(errno
));
206 // requeue all buffers
207 for (buf
.index
= 0; buf
.index
< videoBufferCount
; buf
.index
++) {
208 PTRACE(3,"PVidInDev\tQBUF for index:" << buf
.index
);
209 if (::ioctl(videoFd
, VIDIOC_QBUF
, &buf
) < 0) {
210 PTRACE(3,"PVidInDev\tQBUF failed : " << ::strerror(errno
));
220 BOOL
PVideoInputV4l2Device::Stop()
223 PTRACE(6,"PVidInDev\tstop streaming, fd=" << videoFd
);
225 int type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
227 if (::ioctl(videoFd
, VIDIOC_STREAMOFF
, &type
) < 0) {
228 PTRACE(3,"PVidInDev\tSTREAMOFF failed : " << ::strerror(errno
));
233 // no need to dequeue filled buffers, as this is handled by V4L2 at the next VIDIOC_STREAMON
240 BOOL
PVideoInputV4l2Device::IsCapturing()
247 void PVideoInputV4l2Device::ReadDeviceDirectory(PDirectory devdir, POrdinalToString & vid)
253 PString filename = devdir.GetEntryName();
254 PString devname = devdir + filename;
255 if (devdir.IsSubDir())
256 ReadDeviceDirectory(devname, vid);
260 if (devdir.GetInfo(info) && info.type == PFileInfo::CharDevice) {
262 if (lstat(devname, &s) == 0) {
264 static const int deviceNumbers[] = { 81 };
265 for (PINDEX i = 0; i < PARRAYSIZE(deviceNumbers); i++) {
266 if (MAJOR(s.st_rdev) == deviceNumbers[i]) {
268 PINDEX num = MINOR(s.st_rdev);
269 if (num <= 63 && num >= 0) {
270 vid.SetAt(num, devname);
277 } while (devdir.Next());
283 PStringList
PVideoInputV4l2Device::GetInputDeviceNames()
285 PDirectory
procVideo("/proc/video/dev");
288 devList
.RemoveAll ();
289 if (procVideo
.Exists()) {
290 if (procVideo
.Open(PFileInfo::RegularFile
)) {
292 PString entry
= procVideo
.GetEntryName();
294 if (entry
.Left(7) == "capture") {
295 PString thisDevice
= "/dev/video" + entry
.Mid(7);
298 if ((videoFd
= ::open(thisDevice
, O_RDONLY
)) >= 0) {
299 struct v4l2_capability videoCaps
;
301 if (::ioctl(videoFd
, VIDIOC_QUERYCAP
, &videoCaps
) >= 0 &&
302 videoCaps
.capabilities
== V4L2_CAP_VIDEO_CAPTURE
) {
303 devList
.AppendString(thisDevice
);
308 } while (procVideo
.Next());
311 if (devList
.GetSize () == 0) {
313 devList
+= PString ("/dev/video0");
314 devList
+= PString ("/dev/video1");
316 /* if (devList.GetSize() == 0) {
317 POrdinalToString vid;
318 ReadDeviceDirectory("/dev/", vid);
320 for (PINDEX i = 0; i < vid.GetSize(); i++) {
321 PINDEX cardnum = vid.GetKeyAt(i);
322 int fd = ::open(vid[cardnum], O_RDONLY | O_NONBLOCK);
323 if ((fd >= 0) || (errno == EBUSY)) {
326 devList += vid[cardnum];
335 BOOL
PVideoInputV4l2Device::SetVideoFormat(VideoFormat newFormat
)
337 if (newFormat
== Auto
) {
338 if (SetVideoFormat(PAL
) ||
339 SetVideoFormat(NTSC
) ||
340 SetVideoFormat(SECAM
))
346 if (!PVideoDevice::SetVideoFormat(newFormat
)) {
347 PTRACE(1,"PVideoDevice::SetVideoFormat failed for format " << newFormat
);
354 } static const fmt
[3] = { {V4L2_STD_PAL
, "PAL"},
355 {V4L2_STD_NTSC
, "NTSC"},
356 {V4L2_STD_SECAM
, "SECAM"} };
358 struct v4l2_standard videoEnumStd
;
359 videoEnumStd
.index
= 0;
361 if (::ioctl(videoFd
, VIDIOC_ENUMSTD
, &videoEnumStd
) < 0) {
362 PTRACE(1,"VideoInputDevice\tEnumStd failed : " << ::strerror(errno
));
365 if (videoEnumStd
.id
== fmt
[newFormat
].code
) {
368 videoEnumStd
.index
++;
371 // set the video standard
372 if (::ioctl(videoFd
, VIDIOC_S_STD
, &videoEnumStd
.id
) < 0) {
373 PTRACE(1,"VideoInputDevice\tS_STD failed : " << ::strerror(errno
));
377 PTRACE(6,"PVidInDev\tset video format \"" << fmt
[newFormat
].name
<< "\", fd=" << videoFd
);
383 int PVideoInputV4l2Device::GetNumChannels()
385 // if opened, return the capability value, else 1 as in videoio.cxx
388 struct v4l2_input videoEnumInput
;
389 videoEnumInput
.index
= 0;
391 if (::ioctl(videoFd
, VIDIOC_ENUMINPUT
, &videoEnumInput
) < 0) {
392 PTRACE(1,"VideoInputDevice\tEnumInput failed : " << ::strerror(errno
));
396 videoEnumInput
.index
++;
399 return videoEnumInput
.index
;
406 BOOL
PVideoInputV4l2Device::SetChannel(int newChannel
)
408 if (!PVideoDevice::SetChannel(newChannel
)) {
409 PTRACE(1,"PVideoDevice::SetChannel failed for channel " << newChannel
);
414 if (::ioctl(videoFd
, VIDIOC_S_INPUT
, &channelNumber
) < 0) {
415 PTRACE(1,"VideoInputDevice\tS_INPUT failed : " << ::strerror(errno
));
419 PTRACE(6,"PVidInDev\tset channel " << newChannel
<< ", fd=" << videoFd
);
425 BOOL
PVideoInputV4l2Device::SetVideoChannelFormat (int newChannel
, VideoFormat videoFormat
)
427 if (!SetChannel(newChannel
) ||
428 !SetVideoFormat(videoFormat
))
435 BOOL
PVideoInputV4l2Device::SetColourFormat(const PString
& newFormat
)
437 PINDEX colourFormatIndex
= 0;
438 while (newFormat
!= colourFormatTab
[colourFormatIndex
].colourFormat
) {
440 if (colourFormatIndex
>= PARRAYSIZE(colourFormatTab
))
444 if (!PVideoDevice::SetColourFormat(newFormat
)) {
445 PTRACE(3,"PVidInDev\tSetColourFormat failed for colour format " << newFormat
);
449 BOOL resume
= started
;
453 struct v4l2_format videoFormat
;
454 videoFormat
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
456 // get the colour format
457 if (::ioctl(videoFd
, VIDIOC_G_FMT
, &videoFormat
) < 0) {
458 PTRACE(1,"PVidInDev\tG_FMT failed : " << ::strerror(errno
));
462 videoFormat
.fmt
.pix
.pixelformat
= colourFormatTab
[colourFormatIndex
].code
;
464 // set the colour format
465 if (::ioctl(videoFd
, VIDIOC_S_FMT
, &videoFormat
) < 0) {
466 PTRACE(1,"PVidInDev\tS_FMT failed : " << ::strerror(errno
));
467 PTRACE(1,"\tused code of " << videoFormat
.fmt
.pix
.pixelformat
<< " for palette: " << colourFormatTab
[colourFormatIndex
].colourFormat
);
471 // get the colour format again to be careful about broken drivers
472 if (::ioctl(videoFd
, VIDIOC_G_FMT
, &videoFormat
) < 0) {
473 PTRACE(1,"PVidInDev\tG_FMT failed : " << ::strerror(errno
));
477 if (videoFormat
.fmt
.pix
.pixelformat
!= colourFormatTab
[colourFormatIndex
].code
) {
478 PTRACE(3,"PVidInDev\tcolour format mismatch.");
482 frameBytes
= videoFormat
.fmt
.pix
.sizeimage
;
484 PTRACE(6,"PVidInDev\tset colour format \"" << newFormat
<< "\", fd=" << videoFd
);
493 BOOL
PVideoInputV4l2Device::SetFrameRate(unsigned rate
)
495 if (!PVideoDevice::SetFrameRate(rate
)) {
496 PTRACE(3,"PVidInDev\tSetFrameRate failed for rate " << rate
);
500 if (canSetFrameRate
) {
501 videoStreamParm
.parm
.capture
.timeperframe
.numerator
= 10000000;
502 videoStreamParm
.parm
.capture
.timeperframe
.denominator
= (rate
? rate
: 1);
504 // set the stream parameters
505 if (::ioctl(videoFd
, VIDIOC_S_PARM
, &videoStreamParm
) < 0) {
506 PTRACE(1,"PVidInDev\tS_PARM failed : "<< ::strerror(errno
));
510 PTRACE(6,"PVidInDev\tset frame rate " << rate
<< "fps, fd=" << videoFd
);
517 BOOL
PVideoInputV4l2Device::GetFrameSizeLimits(unsigned & minWidth
,
518 unsigned & minHeight
,
520 unsigned & maxHeight
)
522 /* Not used in V4L2 */
527 BOOL
PVideoInputV4l2Device::SetFrameSize(unsigned width
, unsigned height
)
529 if (!PVideoDevice::SetFrameSize(width
, height
)) {
530 PTRACE(3,"PVidInDev\tSetFrameSize failed for size " << width
<< "x" << height
);
534 BOOL resume
= started
;
538 if (!VerifyHardwareFrameSize(width
, height
)) {
539 PTRACE(3,"PVidInDev\tVerifyHardwareFrameSize failed for size " << width
<< "x" << height
);
543 PTRACE(6,"PVidInDev\tset frame size " << width
<< "x" << height
<< ", fd=" << videoFd
);
552 PINDEX
PVideoInputV4l2Device::GetMaxFrameBytes()
554 if (converter
!= NULL
) {
555 PINDEX bytes
= converter
->GetMaxDstFrameBytes();
556 if (bytes
> frameBytes
)
564 BOOL
PVideoInputV4l2Device::SetMapping()
569 struct v4l2_requestbuffers reqbuf
;
570 reqbuf
.count
= 2; // we shouldn't need more
571 reqbuf
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
572 reqbuf
.memory
= V4L2_MEMORY_MMAP
;
574 if (::ioctl(videoFd
, VIDIOC_REQBUFS
, &reqbuf
) < 0 ||
576 reqbuf
.count
> NUM_VIDBUF
) {
577 PTRACE(3,"PVidInDev\tREQBUFS failed : " << ::strerror(errno
));
581 struct v4l2_buffer buf
;
582 buf
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
584 videoBufferCount
= reqbuf
.count
;
585 for (buf
.index
= 0; buf
.index
< videoBufferCount
; buf
.index
++) {
586 if (::ioctl(videoFd
, VIDIOC_QUERYBUF
, &buf
) < 0) {
587 PTRACE(3,"PVidInDev\tQUERYBUF failed : " << ::strerror(errno
));
591 if ((videoBuffer
[buf
.index
] = (BYTE
*)::mmap(0, buf
.length
, PROT_READ
|PROT_WRITE
, MAP_SHARED
, videoFd
, buf
.m
.offset
)) == MAP_FAILED
) {
592 PTRACE(3,"PVidInDev\tmmap failed : " << ::strerror(errno
));
599 PTRACE(7,"PVidInDev\tset mapping for " << videoBufferCount
<< " buffers, fd=" << videoFd
);
606 void PVideoInputV4l2Device::ClearMapping()
608 if (!canStream
) // 'isMapped' wouldn't handle partial mappings
611 struct v4l2_buffer buf
;
612 buf
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
614 for (buf
.index
= 0; ; buf
.index
++) {
615 if (::ioctl(videoFd
, VIDIOC_QUERYBUF
, &buf
) < 0)
618 ::munmap(videoBuffer
[buf
.index
], buf
.length
);
623 PTRACE(7,"PVidInDev\tclear mapping, fd=" << videoFd
);
627 BOOL
PVideoInputV4l2Device::GetFrame(PBYTEArray
& frame
)
630 if (!GetFrameData(frame
.GetPointer(GetMaxFrameBytes()), &returned
))
633 frame
.SetSize(returned
);
638 BOOL
PVideoInputV4l2Device::GetFrameData(BYTE
* buffer
, PINDEX
* bytesReturned
)
640 PTRACE(1,"PVidInDev\tGetFrameData()");
646 if (!GetFrameDataNoDelay(buffer
, bytesReturned
))
649 delay
= PTime() - previousFrameTime
;
650 } while (delay
.GetMilliSeconds() < msBetweenFrames
);
652 previousFrameTime
= PTime();
657 return GetFrameDataNoDelay(buffer
, bytesReturned
);
661 BOOL
PVideoInputV4l2Device::GetFrameDataNoDelay(BYTE
* buffer
, PINDEX
* bytesReturned
)
663 PTRACE(1,"PVidInDev\tGetFrameDataNoDelay()\tstarted:" << started
<< " canSelect:" << canSelect
);
666 return NormalReadProcess(buffer
, bytesReturned
);
675 FD_SET(videoFd, &rfds);
676 tv.tv_sec = 2; // wait up to 2 seconds
679 PTRACE(1,"PVidInDev\tselect");
682 ret = ::select(videoFd+1, &rfds, NULL, NULL, &tv);
683 while (ret < 0 && errno == EINTR);
686 PTRACE(1,"PVidInDev\tselect failed : " << ::strerror(errno));
691 struct v4l2_buffer buf
;
693 PTRACE(1,"PVidInDev\tdqbuf");
695 buf
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
697 if (::ioctl(videoFd
, VIDIOC_DQBUF
, &buf
) < 0) {
698 PTRACE(1,"PVidInDev\tDQBUF failed : " << ::strerror(errno
));
702 // If converting on the fly do it from frame store to output buffer,
703 // otherwise do straight copy.
704 if (converter
!= NULL
)
705 converter
->Convert(videoBuffer
[buf
.index
], buffer
, bytesReturned
);
707 memcpy(buffer
, videoBuffer
[buf
.index
], buf
.bytesused
);
708 if (bytesReturned
!= NULL
)
709 *bytesReturned
= buf
.bytesused
;
712 PTRACE(8,"PVidInDev\tget frame data of " << buf
.bytesused
<< "bytes, fd=" << videoFd
);
714 // requeue the buffer
715 if (::ioctl(videoFd
, VIDIOC_QBUF
, &buf
) < 0) {
716 PTRACE(1,"PVidInDev\tQBUF failed : " << ::strerror(errno
));
723 // This video device does not support memory mapping - so use
724 // normal read process to extract a frame of video data.
725 BOOL
PVideoInputV4l2Device::NormalReadProcess(BYTE
* buffer
, PINDEX
* bytesReturned
)
733 bytesRead
= ::read(videoFd
, buffer
, frameBytes
);
734 while (bytesRead
< 0 && errno
== EINTR
);
737 PTRACE(1,"PVidInDev\tread failed");
741 if ((PINDEX
)bytesRead
!= frameBytes
) {
742 PTRACE(1,"PVidInDev\tread returned fewer bytes than expected");
743 // May result from a compressed format, otherwise indicates an error.
746 if (converter
!= NULL
)
747 return converter
->ConvertInPlace(buffer
, bytesReturned
);
749 if (bytesReturned
!= NULL
)
750 *bytesReturned
= (PINDEX
)bytesRead
;
755 BOOL
PVideoInputV4l2Device::VerifyHardwareFrameSize(unsigned width
,
758 struct v4l2_format videoFormat
;
759 videoFormat
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
761 // get the frame size
762 if (::ioctl(videoFd
, VIDIOC_G_FMT
, &videoFormat
) < 0) {
763 PTRACE(1,"PVidInDev\tG_FMT failed : " << ::strerror(errno
));
767 videoFormat
.fmt
.pix
.width
= width
;
768 videoFormat
.fmt
.pix
.height
= height
;
770 // set the frame size
771 if (::ioctl(videoFd
, VIDIOC_S_FMT
, &videoFormat
) < 0) {
772 PTRACE(1,"PVidInDev\tS_FMT failed : " << ::strerror(errno
));
773 PTRACE(1,"\tused frame size of " << videoFormat
.fmt
.pix
.width
<< "x" << videoFormat
.fmt
.pix
.height
);
777 // get the frame size again to be careful about broken drivers
778 if (::ioctl(videoFd
, VIDIOC_G_FMT
, &videoFormat
) < 0) {
779 PTRACE(1,"PVidInDev\tG_FMT failed : " << ::strerror(errno
));
783 if ((videoFormat
.fmt
.pix
.width
!= width
) || (videoFormat
.fmt
.pix
.height
!= height
)) {
784 PTRACE(3,"PVidInDev\tframe size mismatch.");
785 // allow the device to return actual frame size
786 PVideoDevice::SetFrameSize(videoFormat
.fmt
.pix
.width
, videoFormat
.fmt
.pix
.height
);
790 frameBytes
= videoFormat
.fmt
.pix
.sizeimage
;
794 int PVideoInputV4l2Device::GetBrightness()
799 struct v4l2_control c
;
800 c
.id
= V4L2_CID_BRIGHTNESS
;
802 if (::ioctl(videoFd
, VIDIOC_G_CTRL
, &c
) < 0)
805 frameBrightness
= c
.value
;
806 return frameBrightness
;
809 int PVideoInputV4l2Device::GetWhiteness()
814 struct v4l2_control c
;
815 c
.id
= V4L2_CID_WHITENESS
;
817 if (::ioctl(videoFd
, VIDIOC_G_CTRL
, &c
) < 0)
820 frameWhiteness
= c
.value
;
821 return frameWhiteness
;
824 int PVideoInputV4l2Device::GetColour()
829 struct v4l2_control c
;
830 c
.id
= V4L2_CID_SATURATION
;
832 if (::ioctl(videoFd
, VIDIOC_G_CTRL
, &c
) < 0)
835 frameColour
= c
.value
;
839 int PVideoInputV4l2Device::GetContrast()
844 struct v4l2_control c
;
845 c
.id
= V4L2_CID_CONTRAST
;
847 if (::ioctl(videoFd
, VIDIOC_G_CTRL
, &c
) < 0)
850 frameContrast
= c
.value
;
851 return frameContrast
;
854 int PVideoInputV4l2Device::GetHue()
859 struct v4l2_control c
;
862 if (::ioctl(videoFd
, VIDIOC_G_CTRL
, &c
) < 0)
869 BOOL
PVideoInputV4l2Device::SetBrightness(unsigned newBrightness
)
874 struct v4l2_queryctrl q
;
875 q
.id
= V4L2_CID_BRIGHTNESS
;
877 if (::ioctl(videoFd
, VIDIOC_QUERYCTRL
, &q
) < 0)
880 struct v4l2_control c
;
881 c
.id
= V4L2_CID_BRIGHTNESS
;
882 c
.value
= q
.minimum
+ ((q
.maximum
-q
.minimum
) * newBrightness
) >> 16;
884 if (::ioctl(videoFd
, VIDIOC_S_CTRL
, &c
) < 0)
887 frameBrightness
= newBrightness
;
891 BOOL
PVideoInputV4l2Device::SetWhiteness(unsigned newWhiteness
)
896 struct v4l2_queryctrl q
;
897 q
.id
= V4L2_CID_WHITENESS
;
899 if (::ioctl(videoFd
, VIDIOC_QUERYCTRL
, &q
) < 0)
902 struct v4l2_control c
;
903 c
.id
= V4L2_CID_WHITENESS
;
904 c
.value
= q
.minimum
+ ((q
.maximum
-q
.minimum
) * newWhiteness
) >> 16;
906 if (::ioctl(videoFd
, VIDIOC_S_CTRL
, &c
) < 0)
909 frameWhiteness
= newWhiteness
;
913 BOOL
PVideoInputV4l2Device::SetColour(unsigned newColour
)
918 struct v4l2_queryctrl q
;
919 q
.id
= V4L2_CID_SATURATION
;
921 if (::ioctl(videoFd
, VIDIOC_QUERYCTRL
, &q
) < 0)
924 struct v4l2_control c
;
925 c
.id
= V4L2_CID_SATURATION
;
926 c
.value
= q
.minimum
+ ((q
.maximum
-q
.minimum
) * newColour
) >> 16;
928 if (::ioctl(videoFd
, VIDIOC_S_CTRL
, &c
) < 0)
931 frameColour
= newColour
;
935 BOOL
PVideoInputV4l2Device::SetContrast(unsigned newContrast
)
940 struct v4l2_queryctrl q
;
941 q
.id
= V4L2_CID_CONTRAST
;
943 if (::ioctl(videoFd
, VIDIOC_QUERYCTRL
, &q
) < 0)
946 struct v4l2_control c
;
947 c
.id
= V4L2_CID_CONTRAST
;
948 c
.value
= q
.minimum
+ ((q
.maximum
-q
.minimum
) * newContrast
) >> 16;
950 if (::ioctl(videoFd
, VIDIOC_S_CTRL
, &c
) < 0)
953 frameContrast
= newContrast
;
957 BOOL
PVideoInputV4l2Device::SetHue(unsigned newHue
)
962 struct v4l2_queryctrl q
;
965 if (::ioctl(videoFd
, VIDIOC_QUERYCTRL
, &q
) < 0)
968 struct v4l2_control c
;
970 c
.value
= q
.minimum
+ ((q
.maximum
-q
.minimum
) * newHue
) >> 16;
972 if (::ioctl(videoFd
, VIDIOC_S_CTRL
, &c
) < 0)
979 BOOL
PVideoInputV4l2Device::GetParameters (int *whiteness
, int *brightness
,
980 int *colour
, int *contrast
, int *hue
)
985 struct v4l2_control c
;
987 c
.id
= V4L2_CID_WHITENESS
;
988 if (::ioctl(videoFd
, VIDIOC_G_CTRL
, &c
) < 0)
991 frameWhiteness
= c
.value
;
992 c
.id
= V4L2_CID_BRIGHTNESS
;
993 if (::ioctl(videoFd
, VIDIOC_G_CTRL
, &c
) < 0)
994 frameBrightness
= -1;
996 frameBrightness
= c
.value
;
997 c
.id
= V4L2_CID_SATURATION
;
998 if (::ioctl(videoFd
, VIDIOC_G_CTRL
, &c
) < 0)
1001 frameColour
= c
.value
;
1002 c
.id
= V4L2_CID_CONTRAST
;
1003 if (::ioctl(videoFd
, VIDIOC_G_CTRL
, &c
) < 0)
1006 frameContrast
= c
.value
;
1007 c
.id
= V4L2_CID_HUE
;
1008 if (::ioctl(videoFd
, VIDIOC_G_CTRL
, &c
) < 0)
1013 *whiteness
= frameWhiteness
;
1014 *brightness
= frameBrightness
;
1015 *colour
= frameColour
;
1016 *contrast
= frameContrast
;
1022 BOOL
PVideoInputV4l2Device::TestAllFormats()
1028 // End Of File ///////////////////////////////////////////////////////////////