1793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* This is the contributed code:
2793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
3793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerFile:             cvcap_v4l.cpp
4793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerCurrent Location: ../opencv-0.9.6/otherlibs/videoio
5793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
6793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerOriginal Version: 2003-03-12  Magnus Lundin lundin@mlu.mine.nu
7793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerOriginal Comments:
8793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
9793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerML:This set of files adds support for firevre and usb cameras.
10793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerFirst it tries to install a firewire camera,
11793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerif that fails it tries a v4l/USB camera
12793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerIt has been tested with the motempl sample program
13793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
14793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerFirst Patch:  August 24, 2004 Travis Wood   TravisOCV@tkwood.com
15793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerFor Release:  OpenCV-Linux Beta4  opencv-0.9.6
16793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerTested On:    LMLBT44 with 8 video inputs
17793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerProblems?     Post your questions at answers.opencv.org,
18793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler              Report bugs at code.opencv.org,
19793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler              Submit your fixes at https://github.com/Itseez/opencv/
20793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerPatched Comments:
21793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
22793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerTW: The cv cam utils that came with the initial release of OpenCV for LINUX Beta4
23793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerwere not working.  I have rewritten them so they work for me. At the same time, trying
24793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerto keep the original code as ML wrote it as unchanged as possible.  No one likes to debug
25793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslersomeone elses code, so I resisted changes as much as possible.  I have tried to keep the
26793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslersame "ideas" where applicable, that is, where I could figure out what the previous author
27793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerintended. Some areas I just could not help myself and had to "spiffy-it-up" my way.
28793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
29793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerThese drivers should work with other V4L frame capture cards other then my bttv
30793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerdriven frame capture card.
31793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
32793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerRe Written driver for standard V4L mode. Tested using LMLBT44 video capture card.
33793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerStandard bttv drivers are on the LMLBT44 with up to 8 Inputs.
34793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
35793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerThis utility was written with the help of the document:
36793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerhttp://pages.cpsc.ucalgary.ca/~sayles/VFL_HowTo
37793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presleras a general guide for interfacing into the V4l standard.
38793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
39793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerMade the index value passed for icvOpenCAM_V4L(index) be the number of the
40793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslervideo device source in the /dev tree. The -1 uses original /dev/video.
41793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
42793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerIndex  Device
43793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  0    /dev/video0
44793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  1    /dev/video1
45793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  2    /dev/video2
46793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  3    /dev/video3
47793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  ...
48793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  7    /dev/video7
49793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerwith
50793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  -1   /dev/video
51793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
52793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerTW: You can select any video source, but this package was limited from the start to only
53793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerONE camera opened at any ONE time.
54793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerThis is an original program limitation.
55793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerIf you are interested, I will make my version available to other OpenCV users.  The big
56793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerdifference in mine is you may pass the camera number as part of the cv argument, but this
57793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerconvention is non standard for current OpenCV calls and the camera number is not currently
58793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerpassed into the called routine.
59793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
60793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerSecond Patch:   August 28, 2004 Sfuncia Fabio fiblan@yahoo.it
61793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerFor Release:  OpenCV-Linux Beta4 Opencv-0.9.6
62793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
63793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerFS: this patch fix not sequential index of device (unplugged device), and real numCameras.
64793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    for -1 index (icvOpenCAM_V4L) i dont use /dev/video but real device available, because
65793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if /dev/video is a link to /dev/video0 and i unplugged device on /dev/video0, /dev/video
66793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    is a bad link. I search the first available device with indexList.
67793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
68793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerThird Patch:   December 9, 2004 Frederic Devernay Frederic.Devernay@inria.fr
69793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerFor Release:  OpenCV-Linux Beta4 Opencv-0.9.6
70793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
71793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler[FD] I modified the following:
72793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler - handle YUV420P, YUV420, and YUV411P palettes (for many webcams) without using floating-point
73793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler - cvGrabFrame should not wait for the end of the first frame, and should return quickly
74793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   (see videoio doc)
75793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler - cvRetrieveFrame should in turn wait for the end of frame capture, and should not
76793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   trigger the capture of the next frame (the user choses when to do it using GrabFrame)
77793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   To get the old behavior, re-call cvRetrieveFrame just after cvGrabFrame.
78793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler - having global bufferIndex and FirstCapture variables makes the code non-reentrant
79793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (e.g. when using several cameras), put these in the CvCapture struct.
80793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler - according to V4L HowTo, incrementing the buffer index must be done before VIDIOCMCAPTURE.
81793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler - the VID_TYPE_SCALES stuff from V4L HowTo is wrong: image size can be changed
82793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   even if the hardware does not support scaling (e.g. webcams can have several
83793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   resolutions available). Just don't try to set the size at 640x480 if the hardware supports
84793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   scaling: open with the default (probably best) image size, and let the user scale it
85793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   using SetProperty.
86793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler - image size can be changed by two subsequent calls to SetProperty (for width and height)
87793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler - bug fix: if the image size changes, realloc the new image only when it is grabbed
88793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler - issue errors only when necessary, fix error message formatting.
89793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
90793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerFourth Patch: Sept 7, 2005 Csaba Kertesz sign@freemail.hu
91793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerFor Release:  OpenCV-Linux Beta5 OpenCV-0.9.7
92793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
93793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerI modified the following:
94793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  - Additional Video4Linux2 support :)
95793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  - Use mmap functions (v4l2)
96793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  - New methods are internal:
97793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    try_palette_v4l2 -> rewrite try_palette for v4l2
98793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    mainloop_v4l2, read_image_v4l2 -> this methods are moved from official v4l2 capture.c example
99793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    try_init_v4l -> device v4l initialisation
100793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    try_init_v4l2 -> device v4l2 initialisation
101793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    autosetup_capture_mode_v4l -> autodetect capture modes for v4l
102793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    autosetup_capture_mode_v4l2 -> autodetect capture modes for v4l2
103793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  - Modifications are according with Video4Linux old codes
104793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  - Video4Linux handling is automatically if it does not recognize a Video4Linux2 device
105793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  - Tested successfully with Logitech Quickcam Express (V4L), Creative Vista (V4L) and Genius VideoCam Notebook (V4L2)
106793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  - Correct source lines with compiler warning messages
107793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  - Information message from v4l/v4l2 detection
108793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
109793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerFifth Patch: Sept 7, 2005 Csaba Kertesz sign@freemail.hu
110793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerFor Release:  OpenCV-Linux Beta5 OpenCV-0.9.7
111793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
112793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerI modified the following:
113793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  - SN9C10x chip based webcams support
114793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  - New methods are internal:
115793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    bayer2rgb24, sonix_decompress -> decoder routines for SN9C10x decoding from Takafumi Mizuno <taka-qce@ls-a.jp> with his pleasure :)
116793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  - Tested successfully with Genius VideoCam Notebook (V4L2)
117793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
118793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerSixth Patch: Sept 10, 2005 Csaba Kertesz sign@freemail.hu
119793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerFor Release:  OpenCV-Linux Beta5 OpenCV-0.9.7
120793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
121793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerI added the following:
122793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  - Add capture control support (hue, saturation, brightness, contrast, gain)
123793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  - Get and change V4L capture controls (hue, saturation, brightness, contrast)
124793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  - New method is internal:
125793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    icvSetControl -> set capture controls
126793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  - Tested successfully with Creative Vista (V4L)
127793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
128793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerSeventh Patch: Sept 10, 2005 Csaba Kertesz sign@freemail.hu
129793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerFor Release:  OpenCV-Linux Beta5 OpenCV-0.9.7
130793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
131793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerI added the following:
132793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  - Detect, get and change V4L2 capture controls (hue, saturation, brightness, contrast, gain)
133793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  - New methods are internal:
134793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    v4l2_scan_controls_enumerate_menu, v4l2_scan_controls -> detect capture control intervals
135793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  - Tested successfully with Genius VideoCam Notebook (V4L2)
136793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
137793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler8th patch: Jan 5, 2006, Olivier.Bornet@idiap.ch
138793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerAdd support of V4L2_PIX_FMT_YUYV and V4L2_PIX_FMT_MJPEG.
139793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerWith this patch, new webcams of Logitech, like QuickCam Fusion works.
140793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerNote: For use these webcams, look at the UVC driver at
141793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerhttp://linux-uvc.berlios.de/
142793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
143793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler9th patch: Mar 4, 2006, Olivier.Bornet@idiap.ch
144793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler- try V4L2 before V4L, because some devices are V4L2 by default,
145793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  but they try to implement the V4L compatibility layer.
146793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  So, I think this is better to support V4L2 before V4L.
147793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler- better separation between V4L2 and V4L initialization. (this was needed to support
148793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  some drivers working, but not fully with V4L2. (so, we do not know when we
149793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  need to switch from V4L2 to V4L.
150793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
151793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler10th patch: July 02, 2008, Mikhail Afanasyev fopencv@theamk.com
152793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerFix reliability problems with high-resolution UVC cameras on linux
153793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerthe symptoms were damaged image and 'Corrupt JPEG data: premature end of data segment' on stderr
154793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler- V4L_ABORT_BADJPEG detects JPEG warnings and turns them into errors, so bad images
155793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  could be filtered out
156793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler- USE_TEMP_BUFFER fixes the main problem (improper buffer management) and
157793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  prevents bad images in the first place
158793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
159793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler11th patch: Apr 13, 2010, Filipe Almeida filipe.almeida@ist.utl.pt
160793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler- Tries to setup all properties first through v4l2_ioctl call.
161793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler- Allows setting up all Video4Linux properties through cvSetCaptureProperty instead of only CV_CAP_PROP_BRIGHTNESS, CV_CAP_PROP_CONTRAST, CV_CAP_PROP_SATURATION, CV_CAP_PROP_HUE, CV_CAP_PROP_GAIN and CV_CAP_PROP_EXPOSURE.
162793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
163793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler12th patch: Apr 16, 2010, Filipe Almeida filipe.almeida@ist.utl.pt
164793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler- CvCaptureCAM_V4L structure cleanup (no longer needs <PROPERTY>_{min,max,} variables)
165793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler- Introduction of v4l2_ctrl_range - minimum and maximum allowed values for v4l controls
166793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler- Allows setting up all Video4Linux properties through cvSetCaptureProperty using input values between 0.0 and 1.0
167793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler- Gets v4l properties first through v4l2_ioctl call (ignores capture->is_v4l2_device)
168793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler- cvGetCaptureProperty adjusted to support the changes
169793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler- Returns device properties to initial values after device closes
170793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
171793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler13th patch: Apr 27, 2010, Filipe Almeida filipe.almeida@ist.utl.pt
172793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler- Solved problem mmaping the device using uvcvideo driver (use o v4l2_mmap instead of mmap)
173793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslermake & enjoy!
174793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
175793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler14th patch: May 10, 2010, Filipe Almeida filipe.almeida@ist.utl.pt
176793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler- Bug #142: Solved/Workaround "setting frame width and height does not work"
177793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  There was a problem setting up the size when the input is a v4l2 device
178793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  The workaround closes the camera and reopens it with the new definition
179793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  Planning for future rewrite of this whole library (July/August 2010)
180793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
181793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler15th patch: May 12, 2010, Filipe Almeida filipe.almeida@ist.utl.pt
182793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler- Broken compile of library (include "_videoio.h")
183793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
184793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler16th patch: Dec 16, 2014, Joseph Howse josephhowse@nummist.com
185793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler- Allow getting/setting CV_CAP_PROP_MODE. These values are supported:
186793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    - CV_CAP_MODE_BGR  : BGR24 (default)
187793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    - CV_CAP_MODE_RGB  : RGB24
188793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    - CV_CAP_MODE_GRAY : Y8, extracted from YUV420
189793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler- Tested successfully on these cameras:
190793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    - PlayStation 3 Eye
191793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    - Logitech C920
192793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    - Odroid USB-CAM 720P
193793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
194793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler17th patch: May 9, 2015, Matt Sandler
195793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler added supported for CV_CAP_PROP_POS_MSEC, CV_CAP_PROP_POS_FRAMES, CV_CAP_PROP_FPS
196793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
197793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler*/
198793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
199793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/*M///////////////////////////////////////////////////////////////////////////////////////
200793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
201793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
202793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
203793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//  By downloading, copying, installing or using the software you agree to this license.
204793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//  If you do not agree to this license, do not download, install,
205793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//  copy or use the software.
206793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
207793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
208793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//                        Intel License Agreement
209793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//                For Open Source Computer Vision Library
210793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
211793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// Copyright (C) 2000, Intel Corporation, all rights reserved.
212793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// Third party copyrights are property of their respective owners.
213793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
214793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// Redistribution and use in source and binary forms, with or without modification,
215793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// are permitted provided that the following conditions are met:
216793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
217793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//   * Redistribution's of source code must retain the above copyright notice,
218793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//     this list of conditions and the following disclaimer.
219793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
220793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//   * Redistribution's in binary form must reproduce the above copyright notice,
221793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//     this list of conditions and the following disclaimer in the documentation
222793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//     and/or other materials provided with the distribution.
223793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
224793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//   * The name of Intel Corporation may not be used to endorse or promote products
225793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//     derived from this software without specific prior written permission.
226793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
227793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// This software is provided by the copyright holders and contributors "as is" and
228793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// any express or implied warranties, including, but not limited to, the implied
229793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// warranties of merchantability and fitness for a particular purpose are disclaimed.
230793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// In no event shall the Intel Corporation or contributors be liable for any direct,
231793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// indirect, incidental, special, exemplary, or consequential damages
232793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// (including, but not limited to, procurement of substitute goods or services;
233793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// loss of use, data, or profits; or business interruption) however caused
234793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// and on any theory of liability, whether in contract, strict liability,
235793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// or tort (including negligence or otherwise) arising in any way out of
236793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// the use of this software, even if advised of the possibility of such damage.
237793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
238793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//M*/
239793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
240793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "precomp.hpp"
241793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
242793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#if !defined WIN32 && defined HAVE_LIBV4L
243793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
244793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define CLEAR(x) memset (&(x), 0, sizeof (x))
245793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
246793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include <stdio.h>
247793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include <unistd.h>
248793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include <fcntl.h>
249793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include <errno.h>
250793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include <sys/types.h>
251793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include <sys/mman.h>
252793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include <string.h>
253793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include <stdlib.h>
254793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include <asm/types.h>          /* for videodev2.h */
255793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include <assert.h>
256793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include <sys/stat.h>
257793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include <sys/ioctl.h>
258793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
259793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#ifdef HAVE_CAMV4L
260793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include <linux/videodev.h>
261793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif
262793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#ifdef HAVE_CAMV4L2
263793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include <linux/videodev2.h>
264793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif
265793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
266793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include <libv4l1.h>
267793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include <libv4l2.h>
268793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
269793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* Defaults - If your board can do better, set it here.  Set for the most common type inputs. */
270793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define DEFAULT_V4L_WIDTH  640
271793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define DEFAULT_V4L_HEIGHT 480
272793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
273793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define CHANNEL_NUMBER 1
274793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define MAX_CAMERAS 8
275793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
276793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
277793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// default and maximum number of V4L buffers, not including last, 'special' buffer
278793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define MAX_V4L_BUFFERS 10
279793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define DEFAULT_V4L_BUFFERS 4
280793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
281793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// if enabled, copies data from the buffer. this uses a bit more memory,
282793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//  but much more reliable for some UVC cameras
283793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define USE_TEMP_BUFFER
284793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
285793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define MAX_DEVICE_DRIVER_NAME 80
286793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
287793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* Device Capture Objects */
288793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* V4L2 structure */
289793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstruct buffer
290793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
291793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  void *  start;
292793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  size_t  length;
293793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler};
294793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic unsigned int n_buffers = 0;
295793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
296793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* TODO: Dilemas: */
297793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* TODO: Consider drop the use of this data structure and perform ioctl to obtain needed values */
298793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* TODO: Consider at program exit return controls to the initial values - See v4l2_free_ranges function */
299793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* TODO: Consider at program exit reset the device to default values - See v4l2_free_ranges function */
300793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslertypedef struct v4l2_ctrl_range {
301793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  __u32 ctrl_id;
302793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  __s32 initial_value;
303793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  __s32 current_value;
304793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  __s32 minimum;
305793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  __s32 maximum;
306793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  __s32 default_value;
307793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} v4l2_ctrl_range;
308793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
309793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslertypedef struct CvCaptureCAM_V4L
310793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
311793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    char* deviceName;
312793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int deviceHandle;
313793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int bufferIndex;
314793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int FirstCapture;
315793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
316793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int width; int height;
317793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int mode;
318793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
319793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    struct video_capability capability;
320793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    struct video_window     captureWindow;
321793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    struct video_picture    imageProperties;
322793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    struct video_mbuf       memoryBuffer;
323793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    struct video_mmap       *mmaps;
324793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    char *memoryMap;
325793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    IplImage frame;
326793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
327793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   /* V4L2 variables */
328793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   buffer buffers[MAX_V4L_BUFFERS + 1];
329793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   struct v4l2_capability cap;
330793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   struct v4l2_input inp;
331793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   struct v4l2_format form;
332793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   struct v4l2_crop crop;
333793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   struct v4l2_cropcap cropcap;
334793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   struct v4l2_requestbuffers req;
335793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   struct v4l2_jpegcompression compr;
336793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   struct v4l2_control control;
337793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   enum v4l2_buf_type type;
338793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   struct v4l2_queryctrl queryctrl;
339793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
340793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   struct timeval timestamp;
341793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
342793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   /** value set the buffer of V4L*/
343793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   int sequence;
344793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
345793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   /* V4L2 control variables */
346793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   v4l2_ctrl_range** v4l2_ctrl_ranges;
347793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   int v4l2_ctrl_count;
348793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
349793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   int is_v4l2_device;
350793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
351793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerCvCaptureCAM_V4L;
352793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
353793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic void icvCloseCAM_V4L( CvCaptureCAM_V4L* capture );
354793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
355793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic int icvGrabFrameCAM_V4L( CvCaptureCAM_V4L* capture );
356793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int );
357793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerCvCapture* cvCreateCameraCapture_V4L( int index );
358793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
359793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic double icvGetPropertyCAM_V4L( CvCaptureCAM_V4L* capture, int property_id );
360793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic int    icvSetPropertyCAM_V4L( CvCaptureCAM_V4L* capture, int property_id, double value );
361793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
362793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic int icvSetVideoSize( CvCaptureCAM_V4L* capture, int w, int h);
363793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
364793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/***********************   Implementations  ***************************************/
365793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
366793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic int numCameras = 0;
367793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic int indexList = 0;
368793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
369793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// IOCTL handling for V4L2
370793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#ifdef HAVE_IOCTL_ULONG
371793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic int xioctl( int fd, unsigned long request, void *arg)
372793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#else
373793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic int xioctl( int fd, int request, void *arg)
374793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif
375793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
376793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
377793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  int r;
378793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
379793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
380793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  do r = v4l2_ioctl (fd, request, arg);
381793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  while (-1 == r && EINTR == errno);
382793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
383793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  return r;
384793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
385793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
386793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
387793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
388793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* Simple test program: Find number of Video Sources available.
389793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   Start from 0 and go to MAX_CAMERAS while checking for the device with that name.
390793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   If it fails on the first attempt of /dev/video0, then check if /dev/video is valid.
391793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   Returns the global numCameras with the correct value (we hope) */
392793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
393793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic void icvInitCapture_V4L() {
394793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   int deviceHandle;
395793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   int CameraNumber;
396793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   char deviceName[MAX_DEVICE_DRIVER_NAME];
397793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
398793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   CameraNumber = 0;
399793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   while(CameraNumber < MAX_CAMERAS) {
400793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      /* Print the CameraNumber at the end of the string with a width of one character */
401793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      sprintf(deviceName, "/dev/video%1d", CameraNumber);
402793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      /* Test using an open to see if this new device name really does exists. */
403793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      deviceHandle = open(deviceName, O_RDONLY);
404793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      if (deviceHandle != -1) {
405793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         /* This device does indeed exist - add it to the total so far */
406793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    // add indexList
407793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    indexList|=(1 << CameraNumber);
408793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        numCameras++;
409793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
410793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (deviceHandle != -1)
411793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      close(deviceHandle);
412793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      /* Set up to test the next /dev/video source in line */
413793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      CameraNumber++;
414793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   } /* End while */
415793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
416793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}; /* End icvInitCapture_V4L */
417793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
418793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
419793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic int try_init_v4l(CvCaptureCAM_V4L* capture, char *deviceName)
420793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
421793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
422793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
423793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  // if detect = -1 then unable to open device
424793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  // if detect = 0 then detected nothing
425793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  // if detect = 1 then V4L device
426793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  int detect = 0;
427793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
428793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
429793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  // Test device for V4L compability
430793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
431793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  /* Test using an open to see if this new device name really does exists. */
432793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  /* No matter what the name - it still must be opened! */
433793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  capture->deviceHandle = v4l1_open(deviceName, O_RDWR);
434793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
435793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
436793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  if (capture->deviceHandle == 0)
437793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  {
438793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    detect = -1;
439793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
440793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    icvCloseCAM_V4L(capture);
441793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  }
442793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
443793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  if (detect == 0)
444793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  {
445793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    /* Query the newly opened device for its capabilities */
446793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (v4l1_ioctl(capture->deviceHandle, VIDIOCGCAP, &capture->capability) < 0)
447793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
448793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      detect = 0;
449793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
450793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      icvCloseCAM_V4L(capture);
451793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
452793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      else
453793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
454793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      detect = 1;
455793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
456793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  }
457793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
458793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  return detect;
459793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
460793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
461793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
462793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
463793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic int try_init_v4l2(CvCaptureCAM_V4L* capture, char *deviceName)
464793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
465793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
466793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  // if detect = -1 then unable to open device
467793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  // if detect = 0 then detected nothing
468793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  // if detect = 1 then V4L2 device
469793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  int detect = 0;
470793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
471793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
472793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  // Test device for V4L2 compability
473793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
474793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  /* Open and test V4L2 device */
475793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  capture->deviceHandle = v4l2_open (deviceName, O_RDWR /* required */ | O_NONBLOCK, 0);
476793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
477793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
478793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
479793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  if (capture->deviceHandle == 0)
480793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  {
481793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    detect = -1;
482793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
483793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    icvCloseCAM_V4L(capture);
484793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  }
485793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
486793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  if (detect == 0)
487793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  {
488793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    CLEAR (capture->cap);
489793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (-1 == xioctl (capture->deviceHandle, VIDIOC_QUERYCAP, &capture->cap))
490793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
491793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      detect = 0;
492793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
493793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      icvCloseCAM_V4L(capture);
494793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
495793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      else
496793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
497793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      CLEAR (capture->capability);
498793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      capture->capability.type = capture->cap.capabilities;
499793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
500793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      /* Query channels number */
501793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      if (-1 != xioctl (capture->deviceHandle, VIDIOC_G_INPUT, &capture->capability.channels))
502793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      {
503793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        detect = 1;
504793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      }
505793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
506793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  }
507793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
508793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  return detect;
509793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
510793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
511793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
512793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
513793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic void v4l2_free_ranges(CvCaptureCAM_V4L* capture) {
514793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  int i;
515793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  if (capture->v4l2_ctrl_ranges != NULL) {
516793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    for (i = 0; i < capture->v4l2_ctrl_count; i++) {
517793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      /* Return device to initial values: */
518793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      /* double value = (capture->v4l2_ctrl_ranges[i]->initial_value == 0)?0.0:((float)capture->v4l2_ctrl_ranges[i]->initial_value - capture->v4l2_ctrl_ranges[i]->minimum) / (capture->v4l2_ctrl_ranges[i]->maximum - capture->v4l2_ctrl_ranges[i]->minimum); */
519793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      /* Return device to default values: */
520793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      /* double value = (capture->v4l2_ctrl_ranges[i]->default_value == 0)?0.0:((float)capture->v4l2_ctrl_ranges[i]->default_value - capture->v4l2_ctrl_ranges[i]->minimum + 1) / (capture->v4l2_ctrl_ranges[i]->maximum - capture->v4l2_ctrl_ranges[i]->minimum); */
521793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
522793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      /* icvSetPropertyCAM_V4L(capture, capture->v4l2_ctrl_ranges[i]->ctrl_id, value); */
523793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      free(capture->v4l2_ctrl_ranges[i]);
524793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
525793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  }
526793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  free(capture->v4l2_ctrl_ranges);
527793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  capture->v4l2_ctrl_count  = 0;
528793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  capture->v4l2_ctrl_ranges = NULL;
529793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
530793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
531793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic void v4l2_add_ctrl_range(CvCaptureCAM_V4L* capture, v4l2_control* ctrl) {
532793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  v4l2_ctrl_range* range    = (v4l2_ctrl_range*)malloc(sizeof(v4l2_ctrl_range));
533793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  range->ctrl_id            = ctrl->id;
534793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  range->initial_value      = ctrl->value;
535793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  range->current_value      = ctrl->value;
536793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  range->minimum            = capture->queryctrl.minimum;
537793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  range->maximum            = capture->queryctrl.maximum;
538793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  range->default_value      = capture->queryctrl.default_value;
539793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  capture->v4l2_ctrl_ranges[capture->v4l2_ctrl_count] = range;
540793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  capture->v4l2_ctrl_count += 1;
541793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  capture->v4l2_ctrl_ranges = (v4l2_ctrl_range**)realloc((v4l2_ctrl_range**)capture->v4l2_ctrl_ranges, (capture->v4l2_ctrl_count + 1) * sizeof(v4l2_ctrl_range*));
542793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
543793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
544793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic int v4l2_get_ctrl_default(CvCaptureCAM_V4L* capture, __u32 id) {
545793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  int i;
546793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  for (i = 0; i < capture->v4l2_ctrl_count; i++) {
547793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (id == capture->v4l2_ctrl_ranges[i]->ctrl_id) {
548793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      return capture->v4l2_ctrl_ranges[i]->default_value;
549793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
550793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  }
551793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  return -1;
552793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
553793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
554793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic int v4l2_get_ctrl_min(CvCaptureCAM_V4L* capture, __u32 id) {
555793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  int i;
556793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  for (i = 0; i < capture->v4l2_ctrl_count; i++) {
557793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (id == capture->v4l2_ctrl_ranges[i]->ctrl_id) {
558793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      return capture->v4l2_ctrl_ranges[i]->minimum;
559793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
560793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  }
561793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  return -1;
562793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
563793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
564793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic int v4l2_get_ctrl_max(CvCaptureCAM_V4L* capture, __u32 id) {
565793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  int i;
566793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  for (i = 0; i < capture->v4l2_ctrl_count; i++) {
567793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (id == capture->v4l2_ctrl_ranges[i]->ctrl_id) {
568793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      return capture->v4l2_ctrl_ranges[i]->maximum;
569793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
570793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  }
571793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  return -1;
572793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
573793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
574793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
575793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic void v4l2_scan_controls(CvCaptureCAM_V4L* capture) {
576793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
577793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  __u32 ctrl_id;
578793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  struct v4l2_control c;
579793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  if (capture->v4l2_ctrl_ranges != NULL) {
580793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    v4l2_free_ranges(capture);
581793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  }
582793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  capture->v4l2_ctrl_ranges = (v4l2_ctrl_range**)malloc(sizeof(v4l2_ctrl_range*));
583793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#ifdef V4L2_CTRL_FLAG_NEXT_CTRL
584793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  /* Try the extended control API first */
585793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  capture->queryctrl.id      = V4L2_CTRL_FLAG_NEXT_CTRL;
586793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  if(0 == v4l2_ioctl (capture->deviceHandle, VIDIOC_QUERYCTRL, &capture->queryctrl)) {
587793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    do {
588793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      c.id = capture->queryctrl.id;
589793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      capture->queryctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
590793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      if(capture->queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) {
591793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        continue;
592793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      }
593793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      if(capture->queryctrl.type != V4L2_CTRL_TYPE_INTEGER &&
594793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         capture->queryctrl.type != V4L2_CTRL_TYPE_BOOLEAN &&
595793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         capture->queryctrl.type != V4L2_CTRL_TYPE_MENU) {
596793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        continue;
597793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      }
598793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      if(v4l2_ioctl(capture->deviceHandle, VIDIOC_G_CTRL, &c) == 0) {
599793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        v4l2_add_ctrl_range(capture, &c);
600793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      }
601793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
602793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    } while(0 == v4l2_ioctl (capture->deviceHandle, VIDIOC_QUERYCTRL, &capture->queryctrl));
603793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  } else
604793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif
605793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  {
606793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    /* Check all the standard controls */
607793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    for(ctrl_id=V4L2_CID_BASE; ctrl_id<V4L2_CID_LASTP1; ctrl_id++) {
608793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      capture->queryctrl.id = ctrl_id;
609793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      if(v4l2_ioctl(capture->deviceHandle, VIDIOC_QUERYCTRL, &capture->queryctrl) == 0) {
610793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if(capture->queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) {
611793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler          continue;
612793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
613793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if(capture->queryctrl.type != V4L2_CTRL_TYPE_INTEGER &&
614793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler           capture->queryctrl.type != V4L2_CTRL_TYPE_BOOLEAN &&
615793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler           capture->queryctrl.type != V4L2_CTRL_TYPE_MENU) {
616793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler          continue;
617793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
618793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        c.id = ctrl_id;
619793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
620793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if(v4l2_ioctl(capture->deviceHandle, VIDIOC_G_CTRL, &c) == 0) {
621793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler          v4l2_add_ctrl_range(capture, &c);
622793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
623793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      }
624793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
625793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
626793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    /* Check any custom controls */
627793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    for(ctrl_id=V4L2_CID_PRIVATE_BASE; ; ctrl_id++) {
628793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      capture->queryctrl.id = ctrl_id;
629793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      if(v4l2_ioctl(capture->deviceHandle, VIDIOC_QUERYCTRL, &capture->queryctrl) == 0) {
630793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if(capture->queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) {
631793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler          continue;
632793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
633793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
634793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
635793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if(capture->queryctrl.type != V4L2_CTRL_TYPE_INTEGER &&
636793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler           capture->queryctrl.type != V4L2_CTRL_TYPE_BOOLEAN &&
637793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler           capture->queryctrl.type != V4L2_CTRL_TYPE_MENU) {
638793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler           continue;
639793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
640793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
641793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        c.id = ctrl_id;
642793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
643793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if(v4l2_ioctl(capture->deviceHandle, VIDIOC_G_CTRL, &c) == 0) {
644793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler          v4l2_add_ctrl_range(capture, &c);
645793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
646793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      } else {
647793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        break;
648793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      }
649793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
650793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  }
651793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
652793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
653793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic inline int channels_for_mode(int mode)
654793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
655793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    switch(mode) {
656793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    case CV_CAP_MODE_GRAY:
657793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return 1;
658793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    case CV_CAP_MODE_YUYV:
659793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return 2;
660793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    default:
661793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return 3;
662793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
663793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
664793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
665793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic int _capture_V4L2 (CvCaptureCAM_V4L *capture, char *deviceName)
666793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
667793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   int detect_v4l2 = 0;
668793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
669793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   capture->deviceName = strdup(deviceName);
670793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
671793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   detect_v4l2 = try_init_v4l2(capture, deviceName);
672793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
673793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   if (detect_v4l2 != 1) {
674793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       /* init of the v4l2 device is not OK */
675793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       return -1;
676793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   }
677793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
678793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   /* starting from here, we assume we are in V4L2 mode */
679793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   capture->is_v4l2_device = 1;
680793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
681793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   capture->v4l2_ctrl_ranges = NULL;
682793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   capture->v4l2_ctrl_count = 0;
683793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
684793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   /* Scan V4L2 controls */
685793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   v4l2_scan_controls(capture);
686793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
687793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   if ((capture->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) {
688793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      /* Nope. */
689793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      fprintf( stderr, "VIDEOIO ERROR: V4L2: device %s is unable to capture video memory.\n",deviceName);
690793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      icvCloseCAM_V4L(capture);
691793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      return -1;
692793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   }
693793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
694793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   /* The following code sets the CHANNEL_NUMBER of the video input.  Some video sources
695793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   have sub "Channel Numbers".  For a typical V4L TV capture card, this is usually 1.
696793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   I myself am using a simple NTSC video input capture card that uses the value of 1.
697793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   If you are not in North America or have a different video standard, you WILL have to change
698793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   the following settings and recompile/reinstall.  This set of settings is based on
699793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   the most commonly encountered input video source types (like my bttv card) */
700793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
701793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   if(capture->inp.index > 0) {
702793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       CLEAR (capture->inp);
703793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       capture->inp.index = CHANNEL_NUMBER;
704793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       /* Set only channel number to CHANNEL_NUMBER */
705793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       /* V4L2 have a status field from selected video mode */
706793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       if (-1 == xioctl (capture->deviceHandle, VIDIOC_ENUMINPUT, &capture->inp))
707793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       {
708793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         fprintf (stderr, "VIDEOIO ERROR: V4L2: Aren't able to set channel number\n");
709793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         icvCloseCAM_V4L (capture);
710793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         return -1;
711793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       }
712793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   } /* End if */
713793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
714793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   /* Find Window info */
715793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   CLEAR (capture->form);
716793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
717793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
718793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   if (-1 == xioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form)) {
719793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       fprintf( stderr, "VIDEOIO ERROR: V4L2: Could not obtain specifics of capture window.\n\n");
720793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       icvCloseCAM_V4L(capture);
721793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       return -1;
722793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   }
723793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
724793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  /* libv4l will convert from any format to V4L2_PIX_FMT_BGR24,
725793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     V4L2_PIX_FMT_RGV24, or V4L2_PIX_FMT_YUV420 */
726793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  unsigned int requestedPixelFormat;
727793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  switch (capture->mode) {
728793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  case CV_CAP_MODE_RGB:
729793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    requestedPixelFormat = V4L2_PIX_FMT_RGB24;
730793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    break;
731793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  case CV_CAP_MODE_GRAY:
732793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    requestedPixelFormat = V4L2_PIX_FMT_YUV420;
733793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    break;
734793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  case CV_CAP_MODE_YUYV:
735793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    requestedPixelFormat = V4L2_PIX_FMT_YUYV;
736793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    break;
737793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  default:
738793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    requestedPixelFormat = V4L2_PIX_FMT_BGR24;
739793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    break;
740793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  }
741793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  CLEAR (capture->form);
742793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  capture->form.type                = V4L2_BUF_TYPE_VIDEO_CAPTURE;
743793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  capture->form.fmt.pix.pixelformat = requestedPixelFormat;
744793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  capture->form.fmt.pix.field       = V4L2_FIELD_ANY;
745793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  capture->form.fmt.pix.width       = capture->width;
746793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  capture->form.fmt.pix.height      = capture->height;
747793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
748793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  if (-1 == xioctl (capture->deviceHandle, VIDIOC_S_FMT, &capture->form)) {
749793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      fprintf(stderr, "VIDEOIO ERROR: libv4l unable to ioctl S_FMT\n");
750793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      return -1;
751793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  }
752793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
753793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  if (requestedPixelFormat != capture->form.fmt.pix.pixelformat) {
754793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      fprintf( stderr, "VIDEOIO ERROR: libv4l unable convert to requested pixfmt\n");
755793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      return -1;
756793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  }
757793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
758793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   /* icvSetVideoSize(capture, DEFAULT_V4L_WIDTH, DEFAULT_V4L_HEIGHT); */
759793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
760793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   unsigned int min;
761793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
762793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   /* Buggy driver paranoia. */
763793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   min = capture->form.fmt.pix.width * 2;
764793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
765793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   if (capture->form.fmt.pix.bytesperline < min)
766793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       capture->form.fmt.pix.bytesperline = min;
767793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
768793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   min = capture->form.fmt.pix.bytesperline * capture->form.fmt.pix.height;
769793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
770793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   if (capture->form.fmt.pix.sizeimage < min)
771793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       capture->form.fmt.pix.sizeimage = min;
772793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
773793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   CLEAR (capture->req);
774793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
775793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   unsigned int buffer_number = DEFAULT_V4L_BUFFERS;
776793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
777793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   try_again:
778793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
779793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   capture->req.count = buffer_number;
780793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   capture->req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
781793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   capture->req.memory = V4L2_MEMORY_MMAP;
782793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
783793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   if (-1 == xioctl (capture->deviceHandle, VIDIOC_REQBUFS, &capture->req))
784793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   {
785793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       if (EINVAL == errno)
786793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       {
787793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         fprintf (stderr, "%s does not support memory mapping\n", deviceName);
788793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       } else {
789793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         perror ("VIDIOC_REQBUFS");
790793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       }
791793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       /* free capture, and returns an error code */
792793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       icvCloseCAM_V4L (capture);
793793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       return -1;
794793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   }
795793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
796793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   if (capture->req.count < buffer_number)
797793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   {
798793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       if (buffer_number == 1)
799793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       {
800793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler           fprintf (stderr, "Insufficient buffer memory on %s\n", deviceName);
801793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
802793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler           /* free capture, and returns an error code */
803793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler           icvCloseCAM_V4L (capture);
804793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler           return -1;
805793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       } else {
806793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         buffer_number--;
807793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   fprintf (stderr, "Insufficient buffer memory on %s -- decreaseing buffers\n", deviceName);
808793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
809793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   goto try_again;
810793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       }
811793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   }
812793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
813793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   for (n_buffers = 0; n_buffers < capture->req.count; ++n_buffers)
814793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   {
815793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       struct v4l2_buffer buf;
816793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
817793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       CLEAR (buf);
818793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
819793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
820793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       buf.memory = V4L2_MEMORY_MMAP;
821793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       buf.index = n_buffers;
822793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
823793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       if (-1 == xioctl (capture->deviceHandle, VIDIOC_QUERYBUF, &buf)) {
824793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler           perror ("VIDIOC_QUERYBUF");
825793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
826793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler           /* free capture, and returns an error code */
827793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler           icvCloseCAM_V4L (capture);
828793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler           return -1;
829793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       }
830793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
831793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       capture->buffers[n_buffers].length = buf.length;
832793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       capture->buffers[n_buffers].start =
833793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         v4l2_mmap (NULL /* start anywhere */,
834793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    buf.length,
835793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    PROT_READ | PROT_WRITE /* required */,
836793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    MAP_SHARED /* recommended */,
837793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    capture->deviceHandle, buf.m.offset);
838793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
839793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       if (MAP_FAILED == capture->buffers[n_buffers].start) {
840793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler           perror ("mmap");
841793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
842793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler           /* free capture, and returns an error code */
843793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler           icvCloseCAM_V4L (capture);
844793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler           return -1;
845793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       }
846793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
847793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#ifdef USE_TEMP_BUFFER
848793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       if (n_buffers == 0) {
849793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler           if (capture->buffers[MAX_V4L_BUFFERS].start) {
850793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler               free(capture->buffers[MAX_V4L_BUFFERS].start);
851793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler               capture->buffers[MAX_V4L_BUFFERS].start = NULL;
852793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       }
853793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
854793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler           capture->buffers[MAX_V4L_BUFFERS].start = malloc(buf.length);
855793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler           capture->buffers[MAX_V4L_BUFFERS].length = buf.length;
856793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       };
857793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif
858793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   }
859793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
860793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   /* Set up Image data */
861793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   cvInitImageHeader( &capture->frame,
862793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                      cvSize( capture->captureWindow.width,
863793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                              capture->captureWindow.height ),
864793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                      IPL_DEPTH_8U, channels_for_mode(capture->mode),
865793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                      IPL_ORIGIN_TL, 4 );
866793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   /* Allocate space for RGBA data */
867793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   capture->frame.imageData = (char *)cvAlloc(capture->frame.imageSize);
868793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
869793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   return 1;
870793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}; /* End _capture_V4L2 */
871793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
872793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
873793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic int _capture_V4L (CvCaptureCAM_V4L *capture, char *deviceName)
874793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
875793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   int detect_v4l = 0;
876793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
877793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   detect_v4l = try_init_v4l(capture, deviceName);
878793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
879793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   if (detect_v4l == -1)
880793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   {
881793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     fprintf (stderr, "VIDEOIO ERROR: V4L"
882793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler              ": device %s: Unable to open for READ ONLY\n", deviceName);
883793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
884793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     return -1;
885793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   }
886793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
887793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   if (detect_v4l <= 0)
888793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   {
889793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     fprintf (stderr, "VIDEOIO ERROR: V4L"
890793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler              ": device %s: Unable to query number of channels\n", deviceName);
891793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
892793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     return -1;
893793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   }
894793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
895793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   {
896793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     if ((capture->capability.type & VID_TYPE_CAPTURE) == 0) {
897793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       /* Nope. */
898793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       fprintf( stderr, "VIDEOIO ERROR: V4L: "
899793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                "device %s is unable to capture video memory.\n",deviceName);
900793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       icvCloseCAM_V4L(capture);
901793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       return -1;
902793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     }
903793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
904793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   }
905793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
906793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
907793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   /* The following code sets the CHANNEL_NUMBER of the video input.  Some video sources
908793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   have sub "Channel Numbers".  For a typical V4L TV capture card, this is usually 1.
909793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   I myself am using a simple NTSC video input capture card that uses the value of 1.
910793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   If you are not in North America or have a different video standard, you WILL have to change
911793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   the following settings and recompile/reinstall.  This set of settings is based on
912793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   the most commonly encountered input video source types (like my bttv card) */
913793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
914793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   {
915793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
916793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     if(capture->capability.channels>0) {
917793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
918793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       struct video_channel selectedChannel;
919793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
920793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       selectedChannel.channel=CHANNEL_NUMBER;
921793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       if (v4l1_ioctl(capture->deviceHandle, VIDIOCGCHAN , &selectedChannel) != -1) {
922793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler          /* set the video mode to ( VIDEO_MODE_PAL, VIDEO_MODE_NTSC, VIDEO_MODE_SECAM) */
923793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//           selectedChannel.norm = VIDEO_MODE_NTSC;
924793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler          if (v4l1_ioctl(capture->deviceHandle, VIDIOCSCHAN , &selectedChannel) == -1) {
925793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler             /* Could not set selected channel - Oh well */
926793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler             //printf("\n%d, %s not NTSC capable.\n",selectedChannel.channel, selectedChannel.name);
927793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler          } /* End if */
928793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       } /* End if */
929793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     } /* End if */
930793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
931793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   }
932793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
933793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   {
934793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
935793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     if(v4l1_ioctl(capture->deviceHandle, VIDIOCGWIN, &capture->captureWindow) == -1) {
936793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       fprintf( stderr, "VIDEOIO ERROR: V4L: "
937793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                "Could not obtain specifics of capture window.\n\n");
938793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       icvCloseCAM_V4L(capture);
939793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       return -1;
940793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     }
941793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
942793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   }
943793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
944793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   {
945793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      if(v4l1_ioctl(capture->deviceHandle, VIDIOCGPICT, &capture->imageProperties) < 0) {
946793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         fprintf( stderr, "VIDEOIO ERROR: V4L: Unable to determine size of incoming image\n");
947793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         icvCloseCAM_V4L(capture);
948793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         return -1;
949793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      }
950793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
951793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      int requestedVideoPalette;
952793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      int depth;
953793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      switch (capture->mode) {
954793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      case CV_CAP_MODE_GRAY:
955793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        requestedVideoPalette = VIDEO_PALETTE_YUV420;
956793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        depth = 8;
957793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        break;
958793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      case CV_CAP_MODE_YUYV:
959793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        requestedVideoPalette = VIDEO_PALETTE_YUYV;
960793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        depth = 16;
961793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        break;
962793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      default:
963793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        requestedVideoPalette = VIDEO_PALETTE_RGB24;
964793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        depth = 24;
965793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        break;
966793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      }
967793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      capture->imageProperties.depth = depth;
968793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      capture->imageProperties.palette = requestedVideoPalette;
969793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      if (v4l1_ioctl(capture->deviceHandle, VIDIOCSPICT, &capture->imageProperties) < 0) {
970793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        fprintf( stderr, "VIDEOIO ERROR: libv4l unable to ioctl VIDIOCSPICT\n\n");
971793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        icvCloseCAM_V4L(capture);
972793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return -1;
973793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      }
974793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      if (v4l1_ioctl(capture->deviceHandle, VIDIOCGPICT, &capture->imageProperties) < 0) {
975793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        fprintf( stderr, "VIDEOIO ERROR: libv4l unable to ioctl VIDIOCGPICT\n\n");
976793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        icvCloseCAM_V4L(capture);
977793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return -1;
978793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      }
979793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      if (capture->imageProperties.palette != requestedVideoPalette) {
980793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        fprintf( stderr, "VIDEOIO ERROR: libv4l unable convert to requested pixfmt\n\n");
981793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        icvCloseCAM_V4L(capture);
982793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return -1;
983793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      }
984793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
985793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   }
986793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
987793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   {
988793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
989793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     v4l1_ioctl(capture->deviceHandle, VIDIOCGMBUF, &capture->memoryBuffer);
990793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     capture->memoryMap  = (char *)v4l1_mmap(0,
991793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                                   capture->memoryBuffer.size,
992793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                                   PROT_READ | PROT_WRITE,
993793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                                   MAP_SHARED,
994793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                                   capture->deviceHandle,
995793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                                   0);
996793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     if (capture->memoryMap == MAP_FAILED) {
997793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        fprintf( stderr, "VIDEOIO ERROR: V4L: Mapping Memmory from video source error: %s\n", strerror(errno));
998793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        icvCloseCAM_V4L(capture);
999793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return -1;
1000793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     }
1001793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1002793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     /* Set up video_mmap structure pointing to this memory mapped area so each image may be
1003793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        retrieved from an index value */
1004793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     capture->mmaps = (struct video_mmap *)
1005793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 (malloc(capture->memoryBuffer.frames * sizeof(struct video_mmap)));
1006793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     if (!capture->mmaps) {
1007793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        fprintf( stderr, "VIDEOIO ERROR: V4L: Could not memory map video frames.\n");
1008793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        icvCloseCAM_V4L(capture);
1009793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return -1;
1010793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     }
1011793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1012793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   }
1013793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1014793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   /* Set up Image data */
1015793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   cvInitImageHeader( &capture->frame,
1016793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                      cvSize( capture->captureWindow.width,
1017793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                              capture->captureWindow.height ),
1018793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                      IPL_DEPTH_8U, channels_for_mode(capture->mode),
1019793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                      IPL_ORIGIN_TL, 4 );
1020793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   /* Allocate space for RGBA data */
1021793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   capture->frame.imageData = (char *)cvAlloc(capture->frame.imageSize);
1022793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1023793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   return 1;
1024793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}; /* End _capture_V4L */
1025793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1026793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic CvCaptureCAM_V4L * icvCaptureFromCAM_V4L (int index)
1027793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
1028793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   static int autoindex;
1029793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   autoindex = 0;
1030793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1031793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   char deviceName[MAX_DEVICE_DRIVER_NAME];
1032793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1033793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   if (!numCameras)
1034793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      icvInitCapture_V4L(); /* Havent called icvInitCapture yet - do it now! */
1035793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   if (!numCameras)
1036793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     return NULL; /* Are there any /dev/video input sources? */
1037793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1038793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   //search index in indexList
1039793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   if ( (index>-1) && ! ((1 << index) & indexList) )
1040793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   {
1041793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     fprintf( stderr, "VIDEOIO ERROR: V4L: index %d is not correct!\n",index);
1042793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     return NULL; /* Did someone ask for not correct video source number? */
1043793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   }
1044793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   /* Allocate memory for this humongus CvCaptureCAM_V4L structure that contains ALL
1045793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      the handles for V4L processing */
1046793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   CvCaptureCAM_V4L * capture = (CvCaptureCAM_V4L*)cvAlloc(sizeof(CvCaptureCAM_V4L));
1047793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   if (!capture) {
1048793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      fprintf( stderr, "VIDEOIO ERROR: V4L: Could not allocate memory for capture process.\n");
1049793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      return NULL;
1050793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   }
1051793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1052793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#ifdef USE_TEMP_BUFFER
1053793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   capture->buffers[MAX_V4L_BUFFERS].start = NULL;
1054793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif
1055793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1056793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   /* Select camera, or rather, V4L video source */
1057793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   if (index<0) { // Asking for the first device available
1058793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     for (; autoindex<MAX_CAMERAS;autoindex++)
1059793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (indexList & (1<<autoindex))
1060793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        break;
1061793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     if (autoindex==MAX_CAMERAS)
1062793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return NULL;
1063793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     index=autoindex;
1064793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     autoindex++;// i can recall icvOpenCAM_V4l with index=-1 for next camera
1065793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   }
1066793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   /* Print the CameraNumber at the end of the string with a width of one character */
1067793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   sprintf(deviceName, "/dev/video%1d", index);
1068793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1069793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   /* w/o memset some parts  arent initialized - AKA: Fill it with zeros so it is clean */
1070793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   memset(capture,0,sizeof(CvCaptureCAM_V4L));
1071793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   /* Present the routines needed for V4L funtionality.  They are inserted as part of
1072793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      the standard set of cv calls promoting transparency.  "Vector Table" insertion. */
1073793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   capture->FirstCapture = 1;
1074793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1075793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   /* set the default size */
1076793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   capture->width  = DEFAULT_V4L_WIDTH;
1077793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   capture->height = DEFAULT_V4L_HEIGHT;
1078793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1079793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   if (_capture_V4L2 (capture, deviceName) == -1) {
1080793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       icvCloseCAM_V4L(capture);
1081793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       capture->is_v4l2_device = 0;
1082793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       if (_capture_V4L (capture, deviceName) == -1) {
1083793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler           icvCloseCAM_V4L(capture);
1084793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler           return NULL;
1085793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       }
1086793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   } else {
1087793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       capture->is_v4l2_device = 1;
1088793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   }
1089793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1090793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   return capture;
1091793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}; /* End icvOpenCAM_V4L */
1092793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1093793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#ifdef HAVE_CAMV4L2
1094793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1095793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic int read_frame_v4l2(CvCaptureCAM_V4L* capture) {
1096793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    struct v4l2_buffer buf;
1097793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1098793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    CLEAR (buf);
1099793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1100793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1101793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    buf.memory = V4L2_MEMORY_MMAP;
1102793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1103793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (-1 == xioctl (capture->deviceHandle, VIDIOC_DQBUF, &buf)) {
1104793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        switch (errno) {
1105793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        case EAGAIN:
1106793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            return 0;
1107793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1108793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        case EIO:
1109793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            /* Could ignore EIO, see spec. */
1110793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1111793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            /* fall through */
1112793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1113793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        default:
1114793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            /* display the error and stop processing */
1115793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            perror ("VIDIOC_DQBUF");
1116793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            return 1;
1117793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
1118793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   }
1119793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1120793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   assert(buf.index < capture->req.count);
1121793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1122793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#ifdef USE_TEMP_BUFFER
1123793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   memcpy(capture->buffers[MAX_V4L_BUFFERS].start,
1124793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    capture->buffers[buf.index].start,
1125793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    capture->buffers[MAX_V4L_BUFFERS].length );
1126793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   capture->bufferIndex = MAX_V4L_BUFFERS;
1127793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   //printf("got data in buff %d, len=%d, flags=0x%X, seq=%d, used=%d)\n",
1128793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   //   buf.index, buf.length, buf.flags, buf.sequence, buf.bytesused);
1129793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#else
1130793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   capture->bufferIndex = buf.index;
1131793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif
1132793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1133793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   if (-1 == xioctl (capture->deviceHandle, VIDIOC_QBUF, &buf))
1134793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       perror ("VIDIOC_QBUF");
1135793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1136793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   //set timestamp in capture struct to be timestamp of most recent frame
1137793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   /** where timestamps refer to the instant the field or frame was received by the driver, not the capture time*/
1138793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   capture->timestamp = buf.timestamp;   //printf( "timestamp update done \n");
1139793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   capture->sequence = buf.sequence;
1140793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1141793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   return 1;
1142793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
1143793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1144793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic void mainloop_v4l2(CvCaptureCAM_V4L* capture) {
1145793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    unsigned int count;
1146793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1147793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    count = 1;
1148793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1149793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    while (count-- > 0) {
1150793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        for (;;) {
1151793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            fd_set fds;
1152793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            struct timeval tv;
1153793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            int r;
1154793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1155793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            FD_ZERO (&fds);
1156793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            FD_SET (capture->deviceHandle, &fds);
1157793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1158793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            /* Timeout. */
1159793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            tv.tv_sec = 10;
1160793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            tv.tv_usec = 0;
1161793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1162793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            r = select (capture->deviceHandle+1, &fds, NULL, NULL, &tv);
1163793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1164793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if (-1 == r) {
1165793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                if (EINTR == errno)
1166793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    continue;
1167793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1168793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                perror ("select");
1169793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
1170793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1171793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if (0 == r) {
1172793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                fprintf (stderr, "select timeout\n");
1173793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1174793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                /* end the infinite loop */
1175793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                break;
1176793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
1177793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1178793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if (read_frame_v4l2 (capture))
1179793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                break;
1180793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
1181793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
1182793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
1183793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1184793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic int icvGrabFrameCAM_V4L(CvCaptureCAM_V4L* capture) {
1185793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1186793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   if (capture->FirstCapture) {
1187793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      /* Some general initialization must take place the first time through */
1188793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1189793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      /* This is just a technicality, but all buffers must be filled up before any
1190793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         staggered SYNC is applied.  SO, filler up. (see V4L HowTo) */
1191793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1192793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      if (capture->is_v4l2_device == 1)
1193793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      {
1194793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1195793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        for (capture->bufferIndex = 0;
1196793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler             capture->bufferIndex < ((int)capture->req.count);
1197793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler             ++capture->bufferIndex)
1198793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
1199793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1200793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler          struct v4l2_buffer buf;
1201793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1202793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler          CLEAR (buf);
1203793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1204793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler          buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1205793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler          buf.memory      = V4L2_MEMORY_MMAP;
1206793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler          buf.index       = (unsigned long)capture->bufferIndex;
1207793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1208793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler          if (-1 == xioctl (capture->deviceHandle, VIDIOC_QBUF, &buf)) {
1209793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler              perror ("VIDIOC_QBUF");
1210793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler              return 0;
1211793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler          }
1212793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
1213793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1214793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        /* enable the streaming */
1215793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        capture->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1216793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if (-1 == xioctl (capture->deviceHandle, VIDIOC_STREAMON,
1217793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                          &capture->type)) {
1218793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            /* error enabling the stream */
1219793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            perror ("VIDIOC_STREAMON");
1220793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            return 0;
1221793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
1222793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      } else
1223793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      {
1224793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1225793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        for (capture->bufferIndex = 0;
1226793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         capture->bufferIndex < (capture->memoryBuffer.frames-1);
1227793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         ++capture->bufferIndex) {
1228793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1229793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler          capture->mmaps[capture->bufferIndex].frame  = capture->bufferIndex;
1230793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler          capture->mmaps[capture->bufferIndex].width  = capture->captureWindow.width;
1231793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler          capture->mmaps[capture->bufferIndex].height = capture->captureWindow.height;
1232793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler          capture->mmaps[capture->bufferIndex].format = capture->imageProperties.palette;
1233793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1234793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler          if (v4l1_ioctl(capture->deviceHandle, VIDIOCMCAPTURE, &capture->mmaps[capture->bufferIndex]) == -1) {
1235793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            fprintf( stderr, "VIDEOIO ERROR: V4L: Initial Capture Error: Unable to load initial memory buffers.\n");
1236793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            return 0;
1237793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler          }
1238793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
1239793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1240793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      }
1241793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1242793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      /* preparation is ok */
1243793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      capture->FirstCapture = 0;
1244793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   }
1245793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1246793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   if (capture->is_v4l2_device == 1)
1247793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   {
1248793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1249793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     mainloop_v4l2(capture);
1250793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1251793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   } else
1252793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   {
1253793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1254793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   capture->mmaps[capture->bufferIndex].frame  = capture->bufferIndex;
1255793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   capture->mmaps[capture->bufferIndex].width  = capture->captureWindow.width;
1256793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   capture->mmaps[capture->bufferIndex].height = capture->captureWindow.height;
1257793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   capture->mmaps[capture->bufferIndex].format = capture->imageProperties.palette;
1258793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1259793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   if (v4l1_ioctl (capture->deviceHandle, VIDIOCMCAPTURE,
1260793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler           &capture->mmaps[capture->bufferIndex]) == -1) {
1261793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      /* capture is on the way, so just exit */
1262793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      return 1;
1263793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   }
1264793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1265793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     ++capture->bufferIndex;
1266793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     if (capture->bufferIndex == capture->memoryBuffer.frames) {
1267793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        capture->bufferIndex = 0;
1268793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     }
1269793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1270793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   }
1271793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1272793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   return(1);
1273793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
1274793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1275793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int) {
1276793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1277793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  if (capture->is_v4l2_device == 0)
1278793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  {
1279793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1280793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    /* [FD] this really belongs here */
1281793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (v4l1_ioctl(capture->deviceHandle, VIDIOCSYNC, &capture->mmaps[capture->bufferIndex].frame) == -1) {
1282793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      fprintf( stderr, "VIDEOIO ERROR: V4L: Could not SYNC to video stream. %s\n", strerror(errno));
1283793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
1284793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1285793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  }
1286793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1287793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   /* Now get what has already been captured as a IplImage return */
1288793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1289793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   /* First, reallocate imageData if the frame size changed */
1290793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1291793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  if (capture->is_v4l2_device == 1)
1292793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  {
1293793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1294793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if(((unsigned long)capture->frame.width != capture->form.fmt.pix.width)
1295793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       || ((unsigned long)capture->frame.height != capture->form.fmt.pix.height)) {
1296793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        cvFree(&capture->frame.imageData);
1297793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        cvInitImageHeader( &capture->frame,
1298793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                           cvSize( capture->form.fmt.pix.width,
1299793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                                   capture->form.fmt.pix.height ),
1300793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                           IPL_DEPTH_8U, channels_for_mode(capture->mode),
1301793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                           IPL_ORIGIN_TL, 4 );
1302793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       capture->frame.imageData = (char *)cvAlloc(capture->frame.imageSize);
1303793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
1304793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1305793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  } else
1306793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  {
1307793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1308793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if((capture->frame.width != capture->mmaps[capture->bufferIndex].width)
1309793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      || (capture->frame.height != capture->mmaps[capture->bufferIndex].height)) {
1310793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       cvFree(&capture->frame.imageData);
1311793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       cvInitImageHeader( &capture->frame,
1312793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                          cvSize( capture->captureWindow.width,
1313793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                                  capture->captureWindow.height ),
1314793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                          IPL_DEPTH_8U, channels_for_mode(capture->mode),
1315793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                          IPL_ORIGIN_TL, 4 );
1316793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       capture->frame.imageData = (char *)cvAlloc(capture->frame.imageSize);
1317793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
1318793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1319793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  }
1320793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1321793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  if (capture->is_v4l2_device == 1)
1322793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  {
1323793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1324793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if(capture->buffers[capture->bufferIndex].start){
1325793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      memcpy((char *)capture->frame.imageData,
1326793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         (char *)capture->buffers[capture->bufferIndex].start,
1327793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         capture->frame.imageSize);
1328793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
1329793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1330793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  } else
1331793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif /* HAVE_CAMV4L2 */
1332793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  {
1333793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1334793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    switch(capture->imageProperties.palette) {
1335793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      case VIDEO_PALETTE_RGB24:
1336793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      case VIDEO_PALETTE_YUV420:
1337793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      case VIDEO_PALETTE_YUYV:
1338793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        memcpy((char *)capture->frame.imageData,
1339793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler           (char *)(capture->memoryMap + capture->memoryBuffer.offsets[capture->bufferIndex]),
1340793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler           capture->frame.imageSize);
1341793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        break;
1342793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      default:
1343793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        fprintf( stderr,
1344793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 "VIDEOIO ERROR: V4L: Cannot convert from palette %d to mode %d\n",
1345793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 capture->imageProperties.palette,
1346793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 capture->mode);
1347793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return 0;
1348793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
1349793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1350793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  }
1351793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1352793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   return(&capture->frame);
1353793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
1354793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1355793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* TODO: review this adaptation */
1356793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic double icvGetPropertyCAM_V4L (CvCaptureCAM_V4L* capture,
1357793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                                     int property_id ) {
1358793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  char name[32];
1359793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  int is_v4l2_device = 0;
1360793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      /* initialize the control structure */
1361793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  switch (property_id) {
1362793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    case CV_CAP_PROP_FRAME_WIDTH:
1363793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    case CV_CAP_PROP_FRAME_HEIGHT:
1364793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      CLEAR (capture->form);
1365793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1366793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      if (-1 == xioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form)) {
1367793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler          /* display an error message, and return an error code */
1368793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler          perror ("VIDIOC_G_FMT");
1369793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if (v4l1_ioctl (capture->deviceHandle, VIDIOCGWIN, &capture->captureWindow) < 0) {
1370793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler          fprintf (stderr, " ERROR: V4L: Unable to determine size of incoming image\n");
1371793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler          icvCloseCAM_V4L(capture);
1372793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler          return -1;
1373793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        } else {
1374793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler          int retval = (property_id == CV_CAP_PROP_FRAME_WIDTH)?capture->captureWindow.width:capture->captureWindow.height;
1375793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler          return retval / 0xFFFF;
1376793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
1377793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      }
1378793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      return (property_id == CV_CAP_PROP_FRAME_WIDTH)?capture->form.fmt.pix.width:capture->form.fmt.pix.height;
1379793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1380793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    case CV_CAP_PROP_POS_MSEC:
1381793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if (capture->FirstCapture) {
1382793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            return 0;
1383793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        } else {
1384793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            //would be maximally numerically stable to cast to convert as bits, but would also be counterintuitive to decode
1385793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            return 1000 * capture->timestamp.tv_sec + ((double) capture->timestamp.tv_usec) / 1000;
1386793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
1387793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        break;
1388793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1389793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    case CV_CAP_PROP_POS_FRAMES:
1390793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return capture->sequence;
1391793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        break;
1392793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1393793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    case CV_CAP_PROP_FPS: {
1394793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        struct v4l2_streamparm sp;
1395793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        memset (&sp, 0, sizeof(struct v4l2_streamparm));
1396793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        sp.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1397793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if (xioctl (capture->deviceHandle, VIDIOC_G_PARM, &sp) < 0){
1398793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            fprintf(stderr, "VIDEOIO ERROR: V4L: Unable to get camera FPS\n");
1399793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            return (double) -1;
1400793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
1401793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1402793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        // this is the captureable, not per say what you'll get..
1403793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        double framesPerSec = sp.parm.capture.timeperframe.denominator / (double)  sp.parm.capture.timeperframe.numerator ;
1404793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return framesPerSec;
1405793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
1406793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    break;
1407793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1408793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1409793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    case CV_CAP_PROP_MODE:
1410793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      return capture->mode;
1411793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      break;
1412793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    case CV_CAP_PROP_BRIGHTNESS:
1413793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      sprintf(name, "Brightness");
1414793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      capture->control.id = V4L2_CID_BRIGHTNESS;
1415793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      break;
1416793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    case CV_CAP_PROP_CONTRAST:
1417793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      sprintf(name, "Contrast");
1418793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      capture->control.id = V4L2_CID_CONTRAST;
1419793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      break;
1420793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    case CV_CAP_PROP_SATURATION:
1421793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      sprintf(name, "Saturation");
1422793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      capture->control.id = V4L2_CID_SATURATION;
1423793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      break;
1424793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    case CV_CAP_PROP_HUE:
1425793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      sprintf(name, "Hue");
1426793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      capture->control.id = V4L2_CID_HUE;
1427793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      break;
1428793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    case CV_CAP_PROP_GAIN:
1429793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      sprintf(name, "Gain");
1430793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      capture->control.id = V4L2_CID_GAIN;
1431793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      break;
1432793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    case CV_CAP_PROP_EXPOSURE:
1433793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      sprintf(name, "Exposure");
1434793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      capture->control.id = V4L2_CID_EXPOSURE;
1435793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      break;
1436793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    default:
1437793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      sprintf(name, "<unknown property string>");
1438793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      capture->control.id = property_id;
1439793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  }
1440793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1441793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  if(v4l2_ioctl(capture->deviceHandle, VIDIOC_G_CTRL, &capture->control) == 0) {
1442793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    /* all went well */
1443793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    is_v4l2_device = 1;
1444793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  } else {
1445793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    fprintf(stderr, "VIDEOIO ERROR: V4L2: Unable to get property %s(%u) - %s\n", name, capture->control.id, strerror(errno));
1446793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  }
1447793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1448793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  if (is_v4l2_device == 1) {
1449793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      /* get the min/max values */
1450793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      int v4l2_min = v4l2_get_ctrl_min(capture, capture->control.id);
1451793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      int v4l2_max = v4l2_get_ctrl_max(capture, capture->control.id);
1452793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1453793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      if ((v4l2_min == -1) && (v4l2_max == -1)) {
1454793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        fprintf(stderr, "VIDEOIO ERROR: V4L2: Property %s(%u) not supported by device\n", name, property_id);
1455793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return -1;
1456793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      }
1457793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1458793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      /* all was OK, so convert to 0.0 - 1.0 range, and return the value */
1459793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      return ((float)capture->control.value - v4l2_min) / (v4l2_max - v4l2_min);
1460793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1461793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  } else {
1462793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    /* TODO: review this section */
1463793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int retval = -1;
1464793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1465793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    switch (property_id) {
1466793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      case CV_CAP_PROP_BRIGHTNESS:
1467793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        retval = capture->imageProperties.brightness;
1468793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        break;
1469793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      case CV_CAP_PROP_CONTRAST:
1470793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        retval = capture->imageProperties.contrast;
1471793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        break;
1472793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      case CV_CAP_PROP_SATURATION:
1473793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        retval = capture->imageProperties.colour;
1474793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        break;
1475793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      case CV_CAP_PROP_HUE:
1476793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        retval = capture->imageProperties.hue;
1477793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        break;
1478793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      case CV_CAP_PROP_GAIN:
1479793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        fprintf(stderr, "VIDEOIO ERROR: V4L: Gain control in V4L is not supported\n");
1480793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return -1;
1481793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        break;
1482793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      case CV_CAP_PROP_EXPOSURE:
1483793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        fprintf(stderr, "VIDEOIO ERROR: V4L: Exposure control in V4L is not supported\n");
1484793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return -1;
1485793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        break;
1486793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
1487793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1488793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (retval == -1) {
1489793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      /* there was a problem */
1490793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      return -1;
1491793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
1492793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    /* all was OK, so convert to 0.0 - 1.0 range, and return the value */
1493793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return float (retval) / 0xFFFF;
1494793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  }
1495793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
1496793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1497793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic int icvSetVideoSize( CvCaptureCAM_V4L* capture, int w, int h) {
1498793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1499793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  if (capture->is_v4l2_device == 1)
1500793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  {
1501793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    char deviceName[MAX_DEVICE_DRIVER_NAME];
1502793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    sprintf(deviceName, "%s", capture->deviceName);
1503793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    icvCloseCAM_V4L(capture);
1504793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    _capture_V4L2(capture, deviceName);
1505793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1506793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int cropHeight;
1507793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int cropWidth;
1508793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    switch (capture->mode) {
1509793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    case CV_CAP_MODE_GRAY:
1510793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      cropHeight = h*8;
1511793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      cropWidth = w*8;
1512793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      break;
1513793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    case CV_CAP_MODE_YUYV:
1514793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      cropHeight = h*16;
1515793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      cropWidth = w*16;
1516793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      break;
1517793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    default:
1518793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      cropHeight = h*24;
1519793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      cropWidth = w*24;
1520793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      break;
1521793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
1522793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    CLEAR (capture->crop);
1523793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    capture->crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1524793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    capture->crop.c.left       = 0;
1525793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    capture->crop.c.top        = 0;
1526793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    capture->crop.c.height     = cropHeight;
1527793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    capture->crop.c.width      = cropWidth;
1528793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1529793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    /* set the crop area, but don't exit if the device don't support croping */
1530793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    xioctl (capture->deviceHandle, VIDIOC_S_CROP, &capture->crop);
1531793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1532793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    CLEAR (capture->form);
1533793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1534793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1535793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    /* read the current setting, mainly to retreive the pixelformat information */
1536793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    xioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form);
1537793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1538793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    /* set the values we want to change */
1539793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    capture->form.fmt.pix.width = w;
1540793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    capture->form.fmt.pix.height = h;
1541793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    capture->form.fmt.win.chromakey = 0;
1542793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    capture->form.fmt.win.field = V4L2_FIELD_ANY;
1543793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    capture->form.fmt.win.clips = 0;
1544793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    capture->form.fmt.win.clipcount = 0;
1545793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    capture->form.fmt.pix.field = V4L2_FIELD_ANY;
1546793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1547793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    /* ask the device to change the size
1548793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     * don't test if the set of the size is ok, because some device
1549793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     * don't allow changing the size, and we will get the real size
1550793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     * later */
1551793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    xioctl (capture->deviceHandle, VIDIOC_S_FMT, &capture->form);
1552793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1553793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    /* try to set framerate to 30 fps */
1554793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1555793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    struct v4l2_streamparm setfps;
1556793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    memset (&setfps, 0, sizeof(struct v4l2_streamparm));
1557793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1558793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    setfps.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1559793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    setfps.parm.capture.timeperframe.numerator = 1;
1560793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    setfps.parm.capture.timeperframe.denominator = 30;
1561793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1562793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    xioctl (capture->deviceHandle, VIDIOC_S_PARM, &setfps);
1563793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1564793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1565793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    /* we need to re-initialize some things, like buffers, because the size has
1566793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     * changed */
1567793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    capture->FirstCapture = 1;
1568793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1569793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    /* Get window info again, to get the real value */
1570793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (-1 == xioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form))
1571793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
1572793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      fprintf(stderr, "VIDEOIO ERROR: V4L/V4L2: Could not obtain specifics of capture window.\n\n");
1573793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1574793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      icvCloseCAM_V4L(capture);
1575793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1576793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      return 0;
1577793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
1578793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1579793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return 0;
1580793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1581793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  } else
1582793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  {
1583793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1584793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (capture==0) return 0;
1585793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     if (w>capture->capability.maxwidth) {
1586793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       w=capture->capability.maxwidth;
1587793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     }
1588793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     if (h>capture->capability.maxheight) {
1589793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       h=capture->capability.maxheight;
1590793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     }
1591793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1592793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     capture->captureWindow.width=w;
1593793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     capture->captureWindow.height=h;
1594793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1595793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     if (ioctl(capture->deviceHandle, VIDIOCSWIN, &capture->captureWindow) < 0) {
1596793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       icvCloseCAM_V4L(capture);
1597793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       return 0;
1598793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     }
1599793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1600793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     if (ioctl(capture->deviceHandle, VIDIOCGWIN, &capture->captureWindow) < 0) {
1601793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       icvCloseCAM_V4L(capture);
1602793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       return 0;
1603793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     }
1604793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1605793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     capture->FirstCapture = 1;
1606793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1607793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  }
1608793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1609793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  return 0;
1610793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1611793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
1612793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1613793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic int icvSetControl (CvCaptureCAM_V4L* capture, int property_id, double value) {
1614793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  struct v4l2_control c;
1615793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  __s32 ctrl_value;
1616793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  char name[32];
1617793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  int is_v4l2  = 1;
1618793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  int v4l2_min = 0;
1619793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  int v4l2_max = 255;
1620793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  if (capture->v4l2_ctrl_ranges == NULL) {
1621793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    v4l2_scan_controls(capture);
1622793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  }
1623793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1624793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  CLEAR (capture->control);
1625793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  CLEAR (capture->queryctrl);
1626793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1627793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  /* get current values */
1628793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  switch (property_id) {
1629793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    case CV_CAP_PROP_BRIGHTNESS:
1630793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      sprintf(name, "Brightness");
1631793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      capture->control.id = V4L2_CID_BRIGHTNESS;
1632793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      break;
1633793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    case CV_CAP_PROP_CONTRAST:
1634793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      sprintf(name, "Contrast");
1635793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      capture->control.id = V4L2_CID_CONTRAST;
1636793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      break;
1637793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    case CV_CAP_PROP_SATURATION:
1638793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      sprintf(name, "Saturation");
1639793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      capture->control.id = V4L2_CID_SATURATION;
1640793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      break;
1641793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    case CV_CAP_PROP_HUE:
1642793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      sprintf(name, "Hue");
1643793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      capture->control.id = V4L2_CID_HUE;
1644793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      break;
1645793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    case CV_CAP_PROP_GAIN:
1646793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      sprintf(name, "Gain");
1647793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      capture->control.id = V4L2_CID_GAIN;
1648793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      break;
1649793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    case CV_CAP_PROP_EXPOSURE:
1650793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      sprintf(name, "Exposure");
1651793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      capture->control.id = V4L2_CID_EXPOSURE;
1652793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      break;
1653793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    default:
1654793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      sprintf(name, "<unknown property string>");
1655793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      capture->control.id = property_id;
1656793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  }
1657793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1658793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  v4l2_min = v4l2_get_ctrl_min(capture, capture->control.id);
1659793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  v4l2_max = v4l2_get_ctrl_max(capture, capture->control.id);
1660793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1661793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  if ((v4l2_min == -1) && (v4l2_max == -1)) {
1662793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    fprintf(stderr, "VIDEOIO ERROR: V4L: Property %s(%u) not supported by device\n", name, property_id);
1663793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return -1;
1664793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  }
1665793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1666793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  if(v4l2_ioctl(capture->deviceHandle, VIDIOC_G_CTRL, &capture->control) == 0) {
1667793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    /* all went well */
1668793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  } else {
1669793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    fprintf(stderr, "VIDEOIO ERROR: V4L2: Unable to get property %s(%u) - %s\n", name, capture->control.id, strerror(errno));
1670793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  }
1671793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1672793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  if (v4l2_max != 0) {
1673793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    double val = value;
1674793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (value < 0.0) {
1675793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      val = 0.0;
1676793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    } else if (value > 1.0) {
1677793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      val = 1.0;
1678793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
1679793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    ctrl_value = val * (double)(v4l2_max - v4l2_min) + v4l2_min;
1680793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  } else {
1681793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    ctrl_value = v4l2_get_ctrl_default(capture, capture->control.id) * (double)(v4l2_max - v4l2_min) + v4l2_min;
1682793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  }
1683793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1684793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  /* try and set value as if it was a v4l2 device */
1685793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  c.id    = capture->control.id;
1686793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  c.value = ctrl_value;
1687793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  if (v4l2_ioctl(capture->deviceHandle, VIDIOC_S_CTRL, &c) != 0) {
1688793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    /* The driver may clamp the value or return ERANGE, ignored here */
1689793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (errno != ERANGE) {
1690793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      fprintf(stderr, "VIDEOIO ERROR: V4L2: Failed to set control \"%d\": %s (value %d)\n", c.id, strerror(errno), c.value);
1691793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      is_v4l2 = 0;
1692793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    } else {
1693793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      return 0;
1694793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
1695793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  } else {
1696793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return 0;
1697793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  }
1698793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1699793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  if (is_v4l2 == 0) { /* use v4l1_ioctl */
1700793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    fprintf(stderr, "VIDEOIO WARNING: Setting property %u through v4l2 failed. Trying with v4l1.\n", c.id);
1701793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int v4l_value;
1702793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    /* scale the value to the wanted integer one */
1703793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    v4l_value = (int)(0xFFFF * value);
1704793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1705793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    switch (property_id) {
1706793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      case CV_CAP_PROP_BRIGHTNESS:
1707793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        capture->imageProperties.brightness = v4l_value;
1708793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        break;
1709793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      case CV_CAP_PROP_CONTRAST:
1710793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        capture->imageProperties.contrast = v4l_value;
1711793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        break;
1712793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      case CV_CAP_PROP_SATURATION:
1713793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        capture->imageProperties.colour = v4l_value;
1714793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        break;
1715793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      case CV_CAP_PROP_HUE:
1716793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        capture->imageProperties.hue = v4l_value;
1717793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        break;
1718793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      case CV_CAP_PROP_GAIN:
1719793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler          fprintf(stderr, "VIDEOIO ERROR: V4L: Gain control in V4L is not supported\n");
1720793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return -1;
1721793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    case CV_CAP_PROP_EXPOSURE:
1722793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        fprintf(stderr, "VIDEOIO ERROR: V4L: Exposure control in V4L is not supported\n");
1723793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return -1;
1724793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    default:
1725793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        fprintf(stderr, "VIDEOIO ERROR: V4L: property #%d is not supported\n", property_id);
1726793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return -1;
1727793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
1728793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1729793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (v4l1_ioctl(capture->deviceHandle, VIDIOCSPICT, &capture->imageProperties) < 0){
1730793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      fprintf(stderr, "VIDEOIO ERROR: V4L: Unable to set video informations\n");
1731793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      icvCloseCAM_V4L(capture);
1732793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      return -1;
1733793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
1734793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  }
1735793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1736793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  /* all was OK */
1737793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  return 0;
1738793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
1739793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1740793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic int icvSetPropertyCAM_V4L(CvCaptureCAM_V4L* capture, int property_id, double value){
1741793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    static int width = 0, height = 0;
1742793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int retval;
1743793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1744793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    /* initialization */
1745793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    retval = 0;
1746793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1747793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    /* two subsequent calls setting WIDTH and HEIGHT will change
1748793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       the video size */
1749793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    /* the first one will return an error, though. */
1750793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1751793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    switch (property_id) {
1752793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    case CV_CAP_PROP_FRAME_WIDTH:
1753793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        width = cvRound(value);
1754793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        capture->width = width;
1755793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if(width !=0 && height != 0) {
1756793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            retval = icvSetVideoSize( capture, width, height);
1757793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            width = height = 0;
1758793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
1759793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        break;
1760793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    case CV_CAP_PROP_FRAME_HEIGHT:
1761793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        height = cvRound(value);
1762793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        capture->height = height;
1763793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if(width !=0 && height != 0) {
1764793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            retval = icvSetVideoSize( capture, width, height);
1765793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            width = height = 0;
1766793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
1767793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        break;
1768793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    case CV_CAP_PROP_MODE:
1769793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        int mode;
1770793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        mode = cvRound(value);
1771793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if (capture->mode != mode) {
1772793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            switch (mode) {
1773793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            case CV_CAP_MODE_BGR:
1774793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            case CV_CAP_MODE_RGB:
1775793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            case CV_CAP_MODE_GRAY:
1776793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            case CV_CAP_MODE_YUYV:
1777793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                capture->mode = mode;
1778793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                /* recreate the capture buffer for the same output resolution
1779793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                   but a different pixel format */
1780793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                retval = icvSetVideoSize(capture, capture->width, capture->height);
1781793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                break;
1782793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            default:
1783793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                fprintf(stderr, "VIDEOIO ERROR: V4L/V4L2: Unsupported mode: %d\n", mode);
1784793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                retval=0;
1785793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                break;
1786793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
1787793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
1788793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        break;
1789793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    case CV_CAP_PROP_FPS:
1790793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        struct v4l2_streamparm setfps;
1791793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        memset (&setfps, 0, sizeof(struct v4l2_streamparm));
1792793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        setfps.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1793793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        setfps.parm.capture.timeperframe.numerator = 1;
1794793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        setfps.parm.capture.timeperframe.denominator = value;
1795793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if (xioctl (capture->deviceHandle, VIDIOC_S_PARM, &setfps) < 0){
1796793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            fprintf(stderr, "VIDEOIO ERROR: V4L: Unable to set camera FPS\n");
1797793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            retval=0;
1798793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
1799793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        break;
1800793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    default:
1801793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        retval = icvSetControl(capture, property_id, value);
1802793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
1803793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1804793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    /* return the the status */
1805793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return retval;
1806793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
1807793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1808793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic void icvCloseCAM_V4L( CvCaptureCAM_V4L* capture ){
1809793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   /* Deallocate space - Hopefully, no leaks */
1810793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   if (capture) {
1811793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     v4l2_free_ranges(capture);
1812793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     if (capture->is_v4l2_device == 0) {
1813793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       if (capture->mmaps) {
1814793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         free(capture->mmaps);
1815793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       }
1816793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       if (capture->memoryMap) {
1817793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         v4l1_munmap(capture->memoryMap, capture->memoryBuffer.size);
1818793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       }
1819793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       if (capture->deviceHandle != -1) {
1820793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         v4l1_close(capture->deviceHandle);
1821793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       }
1822793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     } else {
1823793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       capture->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1824793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       if (xioctl(capture->deviceHandle, VIDIOC_STREAMOFF, &capture->type) < 0) {
1825793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         perror ("Unable to stop the stream.");
1826793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       }
1827793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       for (unsigned int n_buffers2 = 0; n_buffers2 < capture->req.count; ++n_buffers2) {
1828793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         if (-1 == v4l2_munmap (capture->buffers[n_buffers2].start, capture->buffers[n_buffers2].length)) {
1829793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler           perror ("munmap");
1830793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         }
1831793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       }
1832793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1833793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       if (capture->deviceHandle != -1) {
1834793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         v4l2_close(capture->deviceHandle);
1835793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       }
1836793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     }
1837793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1838793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     if (capture->frame.imageData)
1839793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       cvFree(&capture->frame.imageData);
1840793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1841793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#ifdef USE_TEMP_BUFFER
1842793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     if (capture->buffers[MAX_V4L_BUFFERS].start) {
1843793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       free(capture->buffers[MAX_V4L_BUFFERS].start);
1844793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       capture->buffers[MAX_V4L_BUFFERS].start = NULL;
1845793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     }
1846793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif
1847793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1848793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     free(capture->deviceName);
1849793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     capture->deviceName = NULL;
1850793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     //v4l2_free_ranges(capture);
1851793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     //cvFree((void **)capture);
1852793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   }
1853793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler};
1854793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1855793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1856793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerclass CvCaptureCAM_V4L_CPP : CvCapture
1857793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
1858793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerpublic:
1859793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    CvCaptureCAM_V4L_CPP() { captureV4L = 0; }
1860793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    virtual ~CvCaptureCAM_V4L_CPP() { close(); }
1861793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1862793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    virtual bool open( int index );
1863793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    virtual void close();
1864793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1865793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    virtual double getProperty(int) const;
1866793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    virtual bool setProperty(int, double);
1867793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    virtual bool grabFrame();
1868793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    virtual IplImage* retrieveFrame(int);
1869793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerprotected:
1870793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1871793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    CvCaptureCAM_V4L* captureV4L;
1872793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler};
1873793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1874793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerbool CvCaptureCAM_V4L_CPP::open( int index )
1875793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
1876793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    close();
1877793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    captureV4L = icvCaptureFromCAM_V4L(index);
1878793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return captureV4L != 0;
1879793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
1880793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1881793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslervoid CvCaptureCAM_V4L_CPP::close()
1882793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
1883793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if( captureV4L )
1884793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
1885793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        icvCloseCAM_V4L( captureV4L );
1886793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        cvFree( &captureV4L );
1887793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
1888793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
1889793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1890793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerbool CvCaptureCAM_V4L_CPP::grabFrame()
1891793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
1892793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return captureV4L ? icvGrabFrameCAM_V4L( captureV4L ) != 0 : false;
1893793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
1894793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1895793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerIplImage* CvCaptureCAM_V4L_CPP::retrieveFrame(int)
1896793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
1897793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return captureV4L ? icvRetrieveFrameCAM_V4L( captureV4L, 0 ) : 0;
1898793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
1899793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1900793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerdouble CvCaptureCAM_V4L_CPP::getProperty( int propId ) const
1901793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
1902793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return captureV4L ? icvGetPropertyCAM_V4L( captureV4L, propId ) : 0.0;
1903793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
1904793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1905793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerbool CvCaptureCAM_V4L_CPP::setProperty( int propId, double value )
1906793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
1907793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return captureV4L ? icvSetPropertyCAM_V4L( captureV4L, propId, value ) != 0 : false;
1908793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
1909793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1910793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerCvCapture* cvCreateCameraCapture_V4L( int index )
1911793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
1912793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    CvCaptureCAM_V4L_CPP* capture = new CvCaptureCAM_V4L_CPP;
1913793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1914793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if( capture->open( index ))
1915793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return (CvCapture*)capture;
1916793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1917793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    delete capture;
1918793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return 0;
1919793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
1920793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1921793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif
1922