1 /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
2 /*
3  * V4L2 C++ helper header providing wrappers to simplify access to the various
4  * v4l2 functions.
5  *
6  * Copyright 2014-2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
7  */
8 
9 #ifndef _CV4L_HELPERS_H_
10 #define _CV4L_HELPERS_H_
11 
12 #include <limits.h>
13 #include <v4l-helpers.h>
14 
15 #define cv4l_ioctl(cmd, arg) v4l_named_ioctl(g_v4l_fd(), #cmd, cmd, arg)
16 
17 class cv4l_fd : v4l_fd {
18 public:
cv4l_fd()19 	cv4l_fd()
20 	{
21 		v4l_fd_init(this);
22 	}
cv4l_fd(cv4l_fd * fd)23 	cv4l_fd(cv4l_fd *fd)
24 	{
25 		*this = *fd;
26 	}
27 	cv4l_fd &operator= (const cv4l_fd &_fd)
28 	{
29 		memcpy(this, &_fd, sizeof(_fd));
30 		if (_fd.fd >= 0)
31 			fd = dup(_fd.fd);
32 		return *this;
33 	}
34 
is_subdev()35 	bool is_subdev() const { return v4l_fd_is_subdev(this); }
is_media()36 	bool is_media() const { return v4l_fd_is_media(this); }
is_v4l2()37 	bool is_v4l2() const { return v4l_fd_is_v4l2(this); }
g_type()38 	uint32_t g_type() const { return type; }
s_type(uint32_t type)39 	void s_type(uint32_t type) { v4l_s_type(this, type); }
g_selection_type()40 	uint32_t g_selection_type() const { return v4l_g_selection_type(this); }
g_caps()41 	uint32_t g_caps() const { return caps; }
g_fd()42 	int g_fd() const { return fd; }
g_v4l_fd()43 	v4l_fd *g_v4l_fd() { return this; }
g_direct()44 	bool g_direct() const { return v4l_fd_g_direct(this); }
s_direct(bool direct)45 	void s_direct(bool direct) { v4l_fd_s_direct(this, direct); }
g_trace()46 	unsigned int g_trace() const { return v4l_fd_g_trace(this); }
s_trace(unsigned int trace)47 	void s_trace(unsigned int trace) { v4l_fd_s_trace(this, trace); }
48 
49 	int open(const char *devname, bool non_blocking = false) { return v4l_open(this, devname, non_blocking); }
s_fd(int fd,const char * devname,bool direct)50 	int s_fd(int fd, const char *devname, bool direct) { return v4l_s_fd(this, fd, devname, direct); }
51 	int subdev_open(const char *devname, bool non_blocking = false) { return v4l_subdev_open(this, devname, non_blocking); }
subdev_s_fd(int fd,const char * devname)52 	int subdev_s_fd(int fd, const char *devname) { return v4l_subdev_s_fd(this, fd, devname); }
53 	int media_open(const char *devname, bool non_blocking = false) { return v4l_media_open(this, devname, non_blocking); }
media_s_fd(int fd,const char * devname)54 	int media_s_fd(int fd, const char *devname) { return v4l_media_s_fd(this, fd, devname); }
close()55 	int close() { return v4l_close(this); }
56 	int reopen(bool non_blocking = false) { return v4l_reopen(this, non_blocking); }
read(void * buffer,size_t n)57 	ssize_t read(void *buffer, size_t n) { return v4l_read(this, buffer, n); }
write(const void * buffer,size_t n)58 	ssize_t write(const void *buffer, size_t n) { return v4l_write(this, buffer, n); }
mmap(size_t length,off_t offset)59 	void *mmap(size_t length, off_t offset) { return v4l_mmap(this, length, offset); }
munmap(void * start,size_t length)60 	int munmap(void *start, size_t length) { return v4l_munmap(this, start, length); }
61 
has_vid_cap()62 	bool has_vid_cap() const { return v4l_has_vid_cap(this); }
has_vid_out()63 	bool has_vid_out() const { return v4l_has_vid_out(this); }
has_vid_m2m()64 	bool has_vid_m2m() const { return v4l_has_vid_m2m(this); }
has_vid_mplane()65 	bool has_vid_mplane() const { return v4l_has_vid_mplane(this); }
has_overlay_cap()66 	bool has_overlay_cap() const { return v4l_has_overlay_cap(this); }
has_overlay_out()67 	bool has_overlay_out() const { return v4l_has_overlay_out(this); }
has_raw_vbi_cap()68 	bool has_raw_vbi_cap() const { return v4l_has_raw_vbi_cap(this); }
has_sliced_vbi_cap()69 	bool has_sliced_vbi_cap() const { return v4l_has_sliced_vbi_cap(this); }
has_vbi_cap()70 	bool has_vbi_cap() const { return v4l_has_vbi_cap(this); }
has_raw_vbi_out()71 	bool has_raw_vbi_out() const { return v4l_has_raw_vbi_out(this); }
has_sliced_vbi_out()72 	bool has_sliced_vbi_out() const { return v4l_has_sliced_vbi_out(this); }
has_vbi_out()73 	bool has_vbi_out() const { return v4l_has_vbi_out(this); }
has_vbi()74 	bool has_vbi() const { return v4l_has_vbi(this); }
has_radio_rx()75 	bool has_radio_rx() const { return v4l_has_radio_rx(this); }
has_radio_tx()76 	bool has_radio_tx() const { return v4l_has_radio_tx(this); }
has_rds_cap()77 	bool has_rds_cap() const { return v4l_has_rds_cap(this); }
has_rds_out()78 	bool has_rds_out() const { return v4l_has_rds_out(this); }
has_sdr_cap()79 	bool has_sdr_cap() const { return v4l_has_sdr_cap(this); }
has_sdr_out()80 	bool has_sdr_out() const { return v4l_has_sdr_out(this); }
has_hwseek()81 	bool has_hwseek() const { return v4l_has_hwseek(this); }
has_rw()82 	bool has_rw() const { return v4l_has_rw(this); }
has_streaming()83 	bool has_streaming() const { return v4l_has_streaming(this); }
has_ext_pix_format()84 	bool has_ext_pix_format() const { return v4l_has_ext_pix_format(this); }
85 
86 	int querycap(v4l2_capability &cap, bool force = false)
87 	{
88 		if (force)
89 			return cv4l_ioctl(VIDIOC_QUERYCAP, &cap);
90 		cap = this->cap;
91 		return 0;
92 	}
93 
queryctrl(v4l2_queryctrl & qc)94 	int queryctrl(v4l2_queryctrl &qc)
95 	{
96 		return cv4l_ioctl(VIDIOC_QUERYCTRL, &qc);
97 	}
98 
querymenu(v4l2_querymenu & qm)99 	int querymenu(v4l2_querymenu &qm)
100 	{
101 		return cv4l_ioctl(VIDIOC_QUERYMENU, &qm);
102 	}
103 
104 	int query_ext_ctrl(v4l2_query_ext_ctrl &qec, bool next_ctrl = false, bool next_compound = false)
105 	{
106 		return v4l_query_ext_ctrl(this, &qec, next_ctrl, next_compound);
107 	}
108 
g_ctrl(v4l2_control & ctrl)109 	int g_ctrl(v4l2_control &ctrl)
110 	{
111 		return cv4l_ioctl(VIDIOC_G_CTRL, &ctrl);
112 	}
113 
s_ctrl(v4l2_control & ctrl)114 	int s_ctrl(v4l2_control &ctrl)
115 	{
116 		return cv4l_ioctl(VIDIOC_S_CTRL, &ctrl);
117 	}
118 
g_ext_ctrls(v4l2_ext_controls & ec)119 	int g_ext_ctrls(v4l2_ext_controls &ec)
120 	{
121 		return v4l_g_ext_ctrls(this, &ec);
122 	}
123 
try_ext_ctrls(v4l2_ext_controls & ec)124 	int try_ext_ctrls(v4l2_ext_controls &ec)
125 	{
126 		return v4l_try_ext_ctrls(this, &ec);
127 	}
128 
s_ext_ctrls(v4l2_ext_controls & ec)129 	int s_ext_ctrls(v4l2_ext_controls &ec)
130 	{
131 		return v4l_s_ext_ctrls(this, &ec);
132 	}
133 
134 	int g_fmt(v4l2_format &fmt, unsigned type = 0)
135 	{
136 		return v4l_g_fmt(this, &fmt, type);
137 	}
138 
139 	int try_fmt(v4l2_format &fmt, bool zero_bpl = true)
140 	{
141 		return v4l_try_fmt(this, &fmt, zero_bpl);
142 	}
143 
144 	int s_fmt(v4l2_format &fmt, bool zero_bpl = true)
145 	{
146 		return v4l_s_fmt(this, &fmt, zero_bpl);
147 	}
148 
g_selection(v4l2_selection & sel)149 	int g_selection(v4l2_selection &sel)
150 	{
151 		return v4l_g_selection(this, &sel);
152 	}
153 
s_selection(v4l2_selection & sel)154 	int s_selection(v4l2_selection &sel)
155 	{
156 		return v4l_s_selection(this, &sel);
157 	}
158 
g_frame_selection(v4l2_selection & sel,uint32_t field)159 	int g_frame_selection(v4l2_selection &sel, uint32_t field)
160 	{
161 		return v4l_g_frame_selection(this, &sel, field);
162 	}
163 
s_frame_selection(v4l2_selection & sel,uint32_t field)164 	int s_frame_selection(v4l2_selection &sel, uint32_t field)
165 	{
166 		return v4l_s_frame_selection(this, &sel, field);
167 	}
168 
169 	int g_tuner(v4l2_tuner &tuner, unsigned index = 0)
170 	{
171 		memset(&tuner, 0, sizeof(tuner));
172 		tuner.index = index;
173 		int ret = cv4l_ioctl(VIDIOC_G_TUNER, &tuner);
174 		if (ret == 0 && tuner.rangehigh > INT_MAX)
175 			tuner.rangehigh = INT_MAX;
176 		return ret;
177 	}
178 
s_tuner(v4l2_tuner & tuner)179 	int s_tuner(v4l2_tuner &tuner)
180 	{
181 		return cv4l_ioctl(VIDIOC_S_TUNER, &tuner);
182 	}
183 
184 	int g_modulator(v4l2_modulator &modulator, unsigned index = 0)
185 	{
186 		memset(&modulator, 0, sizeof(modulator));
187 		modulator.index = index;
188 		return cv4l_ioctl(VIDIOC_G_MODULATOR, &modulator);
189 	}
190 
s_modulator(v4l2_modulator & modulator)191 	int s_modulator(v4l2_modulator &modulator)
192 	{
193 		return cv4l_ioctl(VIDIOC_S_MODULATOR, &modulator);
194 	}
195 
196 	int enum_input(v4l2_input &in, bool init = false, int index = 0)
197 	{
198 		if (init) {
199 			memset(&in, 0, sizeof(in));
200 			in.index = index;
201 		} else {
202 			in.index++;
203 		}
204 		return cv4l_ioctl(VIDIOC_ENUMINPUT, &in);
205 	}
206 
207 	int enum_output(v4l2_output &out, bool init = false, int index = 0)
208 	{
209 		if (init) {
210 			memset(&out, 0, sizeof(out));
211 			out.index = index;
212 		} else {
213 			out.index++;
214 		}
215 		return cv4l_ioctl(VIDIOC_ENUMOUTPUT, &out);
216 	}
217 
218 	int enum_audio(v4l2_audio &audio, bool init = false, int index = 0)
219 	{
220 		if (init) {
221 			memset(&audio, 0, sizeof(audio));
222 			audio.index = index;
223 		} else {
224 			audio.index++;
225 		}
226 		return cv4l_ioctl(VIDIOC_ENUMAUDIO, &audio);
227 	}
228 
229 	int enum_audout(v4l2_audioout &audout, bool init = false, int index = 0)
230 	{
231 		if (init) {
232 			memset(&audout, 0, sizeof(audout));
233 			audout.index = index;
234 		} else {
235 			audout.index++;
236 		}
237 		return cv4l_ioctl(VIDIOC_ENUMAUDOUT, &audout);
238 	}
239 
has_crop()240 	bool has_crop()
241 	{
242 		v4l2_selection sel;
243 
244 		memset(&sel, 0, sizeof(sel));
245 		sel.type = g_selection_type();
246 		sel.target = V4L2_SEL_TGT_CROP;
247 		return g_selection(sel) != ENOTTY;
248 	}
249 
has_compose()250 	bool has_compose()
251 	{
252 		v4l2_selection sel;
253 
254 		memset(&sel, 0, sizeof(sel));
255 		sel.type = g_selection_type();
256 		sel.target = V4L2_SEL_TGT_COMPOSE;
257 		return g_selection(sel) != ENOTTY;
258 	}
259 
cur_io_has_crop()260 	bool cur_io_has_crop()
261 	{
262 		v4l2_selection sel;
263 
264 		memset(&sel, 0, sizeof(sel));
265 		sel.type = g_selection_type();
266 		sel.target = V4L2_SEL_TGT_CROP;
267 		return g_selection(sel) == 0;
268 	}
269 
cur_io_has_compose()270 	bool cur_io_has_compose()
271 	{
272 		v4l2_selection sel;
273 
274 		memset(&sel, 0, sizeof(sel));
275 		sel.type = g_selection_type();
276 		sel.target = V4L2_SEL_TGT_COMPOSE;
277 		return g_selection(sel) == 0;
278 	}
279 
subscribe_event(v4l2_event_subscription & sub)280 	int subscribe_event(v4l2_event_subscription &sub)
281 	{
282 		return cv4l_ioctl(VIDIOC_SUBSCRIBE_EVENT, &sub);
283 	}
284 
unsubscribe_event(v4l2_event_subscription & sub)285 	int unsubscribe_event(v4l2_event_subscription &sub)
286 	{
287 		return cv4l_ioctl(VIDIOC_UNSUBSCRIBE_EVENT, &sub);
288 	}
289 
dqevent(v4l2_event & ev)290 	int dqevent(v4l2_event &ev)
291 	{
292 		return cv4l_ioctl(VIDIOC_DQEVENT, &ev);
293 	}
294 
g_input(uint32_t & input)295 	int g_input(uint32_t &input)
296 	{
297 		return cv4l_ioctl(VIDIOC_G_INPUT, &input);
298 	}
299 
s_input(uint32_t input)300 	int s_input(uint32_t input)
301 	{
302 		return cv4l_ioctl(VIDIOC_S_INPUT, &input);
303 	}
304 
g_output(uint32_t & output)305 	int g_output(uint32_t &output)
306 	{
307 		return cv4l_ioctl(VIDIOC_G_OUTPUT, &output);
308 	}
309 
s_output(uint32_t output)310 	int s_output(uint32_t output)
311 	{
312 		return cv4l_ioctl(VIDIOC_S_OUTPUT, &output);
313 	}
314 
g_audio(v4l2_audio & audio)315 	int g_audio(v4l2_audio &audio)
316 	{
317 		memset(&audio, 0, sizeof(audio));
318 		return cv4l_ioctl(VIDIOC_G_AUDIO, &audio);
319 	}
320 
s_audio(uint32_t input)321 	int s_audio(uint32_t input)
322 	{
323 		v4l2_audio audio;
324 
325 		memset(&audio, 0, sizeof(audio));
326 		audio.index = input;
327 		return cv4l_ioctl(VIDIOC_S_AUDIO, &audio);
328 	}
329 
g_audout(v4l2_audioout & audout)330 	int g_audout(v4l2_audioout &audout)
331 	{
332 		memset(&audout, 0, sizeof(audout));
333 		return cv4l_ioctl(VIDIOC_G_AUDOUT, &audout);
334 	}
335 
s_audout(uint32_t output)336 	int s_audout(uint32_t output)
337 	{
338 		v4l2_audioout audout;
339 
340 		memset(&audout, 0, sizeof(audout));
341 		audout.index = output;
342 		return cv4l_ioctl(VIDIOC_S_AUDOUT, &audout);
343 	}
344 
g_std(v4l2_std_id & std)345 	int g_std(v4l2_std_id &std)
346 	{
347 		return cv4l_ioctl(VIDIOC_G_STD, &std);
348 	}
349 
s_std(v4l2_std_id std)350 	int s_std(v4l2_std_id std)
351 	{
352 		return cv4l_ioctl(VIDIOC_S_STD, &std);
353 	}
354 
query_std(v4l2_std_id & std)355 	int query_std(v4l2_std_id &std)
356 	{
357 		return cv4l_ioctl(VIDIOC_QUERYSTD, &std);
358 	}
359 
dv_timings_cap(v4l2_dv_timings_cap & cap)360 	int dv_timings_cap(v4l2_dv_timings_cap &cap)
361 	{
362 		cap.pad = 0;
363 		memset(cap.reserved, 0, sizeof(cap.reserved));
364 		return cv4l_ioctl(VIDIOC_DV_TIMINGS_CAP, &cap);
365 	}
366 
g_dv_timings(v4l2_dv_timings & timings)367 	int g_dv_timings(v4l2_dv_timings &timings)
368 	{
369 		return cv4l_ioctl(VIDIOC_G_DV_TIMINGS, &timings);
370 	}
371 
s_dv_timings(v4l2_dv_timings & timings)372 	int s_dv_timings(v4l2_dv_timings &timings)
373 	{
374 		if (timings.type == V4L2_DV_BT_656_1120)
375 			memset(timings.bt.reserved, 0,
376 			       sizeof(timings.bt.reserved));
377 		return cv4l_ioctl(VIDIOC_S_DV_TIMINGS, &timings);
378 	}
379 
query_dv_timings(v4l2_dv_timings & timings)380 	int query_dv_timings(v4l2_dv_timings &timings)
381 	{
382 		return cv4l_ioctl(VIDIOC_QUERY_DV_TIMINGS, &timings);
383 	}
384 
385 	int g_frequency(v4l2_frequency &freq, unsigned index = 0)
386 	{
387 		memset(&freq, 0, sizeof(freq));
388 		freq.tuner = index;
389 		freq.type = V4L2_TUNER_ANALOG_TV;
390 		return cv4l_ioctl(VIDIOC_G_FREQUENCY, &freq);
391 	}
392 
s_frequency(v4l2_frequency & freq)393 	int s_frequency(v4l2_frequency &freq)
394 	{
395 		return cv4l_ioctl(VIDIOC_S_FREQUENCY, &freq);
396 	}
397 
g_priority(uint32_t & prio)398 	int g_priority(uint32_t &prio)
399 	{
400 		return cv4l_ioctl(VIDIOC_G_PRIORITY, &prio);
401 	}
402 
403 	int s_priority(uint32_t prio = V4L2_PRIORITY_DEFAULT)
404 	{
405 		return cv4l_ioctl(VIDIOC_S_PRIORITY, &prio);
406 	}
407 
408 	int streamon(uint32_t type = 0)
409 	{
410 		if (type == 0)
411 			type = g_type();
412 		return cv4l_ioctl(VIDIOC_STREAMON, &type);
413 	}
414 
415 	int streamoff(uint32_t type = 0)
416 	{
417 		if (type == 0)
418 			type = g_type();
419 		return cv4l_ioctl(VIDIOC_STREAMOFF, &type);
420 	}
421 
querybuf(v4l_buffer & buf)422 	int querybuf(v4l_buffer &buf)
423 	{
424 		return v4l_buffer_querybuf(this, &buf,
425 					   v4l_buffer_g_index(&buf));
426 	}
427 
querybuf(v4l_buffer & buf,unsigned index)428 	int querybuf(v4l_buffer &buf, unsigned index)
429 	{
430 		return v4l_buffer_querybuf(this, &buf, index);
431 	}
432 
dqbuf(v4l_buffer & buf)433 	int dqbuf(v4l_buffer &buf)
434 	{
435 		return v4l_buffer_dqbuf(this, &buf);
436 	}
437 
qbuf(v4l_buffer & buf)438 	int qbuf(v4l_buffer &buf)
439 	{
440 		return v4l_buffer_qbuf(this, &buf);
441 	}
442 
prepare_buf(v4l_buffer & buf)443 	int prepare_buf(v4l_buffer &buf)
444 	{
445 		return v4l_buffer_prepare_buf(this, &buf);
446 	}
447 
448 	int enum_std(v4l2_standard &std, bool init = false, int index = 0)
449 	{
450 		if (init) {
451 			memset(&std, 0, sizeof(std));
452 			std.index = index;
453 		} else {
454 			std.index++;
455 		}
456 		return cv4l_ioctl(VIDIOC_ENUMSTD, &std);
457 	}
458 
459 	int enum_freq_bands(v4l2_frequency_band &band, unsigned tuner, bool init = false, int index = 0)
460 	{
461 		if (init) {
462 			memset(&band, 0, sizeof(band));
463 			band.index = index;
464 		} else {
465 			band.index++;
466 		}
467 		band.tuner = tuner;
468 		if (has_radio_tx() || has_radio_rx())
469 			band.type = V4L2_TUNER_RADIO;
470 		else
471 			band.type = V4L2_TUNER_ANALOG_TV;
472 		return cv4l_ioctl(VIDIOC_ENUM_FREQ_BANDS, &band);
473 	}
474 
475 	int enum_dv_timings(v4l2_enum_dv_timings &timings, bool init = false, int index = 0)
476 	{
477 		if (init) {
478 			memset(&timings, 0, sizeof(timings));
479 			timings.index = index;
480 		} else {
481 			timings.index++;
482 		}
483 		return cv4l_ioctl(VIDIOC_ENUM_DV_TIMINGS, &timings);
484 	}
485 
486 	int enum_fmt(v4l2_fmtdesc &fmt, bool init = false, int index = 0, unsigned type = 0)
487 	{
488 		if (init) {
489 			memset(&fmt, 0, sizeof(fmt));
490 			fmt.type = type ? type : g_type();
491 			fmt.index = index;
492 		} else {
493 			fmt.index++;
494 		}
495 		return cv4l_ioctl(VIDIOC_ENUM_FMT, &fmt);
496 	}
497 
498 	int enum_framesizes(v4l2_frmsizeenum &frm, uint32_t init_pixfmt = 0, int index = 0)
499 	{
500 		if (init_pixfmt) {
501 			memset(&frm, 0, sizeof(frm));
502 			frm.pixel_format = init_pixfmt;
503 			frm.index = index;
504 		} else {
505 			frm.index++;
506 		}
507 		return cv4l_ioctl(VIDIOC_ENUM_FRAMESIZES, &frm);
508 	}
509 
510 	int enum_frameintervals(v4l2_frmivalenum &frm, uint32_t init_pixfmt = 0, uint32_t w = 0, uint32_t h = 0, int index = 0)
511 	{
512 		if (init_pixfmt) {
513 			memset(&frm, 0, sizeof(frm));
514 			frm.pixel_format = init_pixfmt;
515 			frm.width = w;
516 			frm.height = h;
517 			frm.index = index;
518 		} else {
519 			frm.index++;
520 		}
521 		return cv4l_ioctl(VIDIOC_ENUM_FRAMEINTERVALS, &frm);
522 	}
523 
524 	int set_interval(v4l2_fract interval, unsigned type = 0)
525 	{
526 		v4l2_streamparm parm;
527 
528 		parm.type = type ? type : g_type();
529 		memset(parm.parm.capture.reserved, 0, sizeof(parm.parm.capture.reserved));
530 		if (cv4l_ioctl(VIDIOC_G_PARM, &parm) ||
531 		    !(parm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME))
532 			return -1;
533 
534 		parm.parm.capture.timeperframe = interval;
535 
536 		return cv4l_ioctl(VIDIOC_S_PARM, &parm);
537 	}
538 
539 	int get_interval(v4l2_fract &interval, unsigned type = 0)
540 	{
541 		v4l2_streamparm parm;
542 
543 		parm.type = type ? type : g_type();
544 		memset(parm.parm.capture.reserved, 0, sizeof(parm.parm.capture.reserved));
545 		if (cv4l_ioctl(VIDIOC_G_PARM, &parm) == 0 &&
546 		    (parm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME)) {
547 			interval = parm.parm.capture.timeperframe;
548 			return 0;
549 		}
550 
551 		return -1;
552 	}
553 
g_fbuf(v4l2_framebuffer & fbuf)554 	int g_fbuf(v4l2_framebuffer &fbuf)
555 	{
556 		return cv4l_ioctl(VIDIOC_G_FBUF, &fbuf);
557 	}
558 
s_fbuf(v4l2_framebuffer & fbuf)559 	int s_fbuf(v4l2_framebuffer &fbuf)
560 	{
561 		fbuf.fmt.priv = 0;
562 		return cv4l_ioctl(VIDIOC_S_FBUF, &fbuf);
563 	}
564 
overlay(bool enable)565 	int overlay(bool enable)
566 	{
567 		int ena = enable;
568 
569 		return cv4l_ioctl(VIDIOC_OVERLAY, &ena);
570 	}
571 
g_jpegcomp(v4l2_jpegcompression & jpeg)572 	int g_jpegcomp(v4l2_jpegcompression &jpeg)
573 	{
574 		return cv4l_ioctl(VIDIOC_G_JPEGCOMP, &jpeg);
575 	}
576 
s_jpegcomp(v4l2_jpegcompression & jpeg)577 	int s_jpegcomp(v4l2_jpegcompression &jpeg)
578 	{
579 		return cv4l_ioctl(VIDIOC_S_JPEGCOMP, &jpeg);
580 	}
581 
g_edid(v4l2_edid & edid)582 	int g_edid(v4l2_edid &edid)
583 	{
584 		memset(edid.reserved, 0, sizeof(edid.reserved));
585 		return cv4l_ioctl(VIDIOC_G_EDID, &edid);
586 	}
587 
s_edid(v4l2_edid & edid)588 	int s_edid(v4l2_edid &edid)
589 	{
590 		memset(edid.reserved, 0, sizeof(edid.reserved));
591 		return cv4l_ioctl(VIDIOC_S_EDID, &edid);
592 	}
593 
g_sliced_vbi_cap(v4l2_sliced_vbi_cap & cap)594 	int g_sliced_vbi_cap(v4l2_sliced_vbi_cap &cap)
595 	{
596 		memset(cap.reserved, 0, sizeof(cap.reserved));
597 		return cv4l_ioctl(VIDIOC_G_SLICED_VBI_CAP, &cap);
598 	}
599 
g_enc_index(v4l2_enc_idx & enc_idx)600 	int g_enc_index(v4l2_enc_idx &enc_idx)
601 	{
602 		return cv4l_ioctl(VIDIOC_G_ENC_INDEX, &enc_idx);
603 	}
604 
s_hw_freq_seek(v4l2_hw_freq_seek & seek)605 	int s_hw_freq_seek(v4l2_hw_freq_seek &seek)
606 	{
607 		memset(seek.reserved, 0, sizeof(seek.reserved));
608 		return cv4l_ioctl(VIDIOC_S_HW_FREQ_SEEK, &seek);
609 	}
610 
log_status()611 	int log_status()
612 	{
613 		return cv4l_ioctl(VIDIOC_LOG_STATUS, NULL);
614 	}
615 
encoder_cmd(v4l2_encoder_cmd & cmd)616 	int encoder_cmd(v4l2_encoder_cmd &cmd)
617 	{
618 		memset(&cmd.raw, 0, sizeof(cmd.raw));
619 		return cv4l_ioctl(VIDIOC_ENCODER_CMD, &cmd);
620 	}
621 
try_encoder_cmd(v4l2_encoder_cmd & cmd)622 	int try_encoder_cmd(v4l2_encoder_cmd &cmd)
623 	{
624 		memset(&cmd.raw, 0, sizeof(cmd.raw));
625 		return cv4l_ioctl(VIDIOC_TRY_ENCODER_CMD, &cmd);
626 	}
627 
decoder_cmd(v4l2_decoder_cmd & cmd)628 	int decoder_cmd(v4l2_decoder_cmd &cmd)
629 	{
630 		return cv4l_ioctl(VIDIOC_DECODER_CMD, &cmd);
631 	}
632 
try_decoder_cmd(v4l2_decoder_cmd & cmd)633 	int try_decoder_cmd(v4l2_decoder_cmd &cmd)
634 	{
635 		return cv4l_ioctl(VIDIOC_TRY_DECODER_CMD, &cmd);
636 	}
637 
638 	v4l2_fract g_pixel_aspect(unsigned &width, unsigned &height, unsigned type = 0)
639 	{
640 		v4l2_cropcap ratio;
641 		v4l2_dv_timings timings;
642 		v4l2_std_id std;
643 		static const v4l2_fract square = { 1, 1 };
644 		static const v4l2_fract hz50 = { 11, 12 };
645 		static const v4l2_fract hz60 = { 11, 10 };
646 
647 		ratio.type = type ? type : g_selection_type();
648 		if (cv4l_ioctl(VIDIOC_CROPCAP, &ratio) == 0) {
649 			width = ratio.defrect.width;
650 			height = ratio.defrect.height;
651 			if (ratio.pixelaspect.numerator && ratio.pixelaspect.denominator)
652 				return ratio.pixelaspect;
653 		}
654 
655 		width = 720;
656 		height = 480;
657 		if (!g_std(std)) {
658 			if (std & V4L2_STD_525_60)
659 				return hz60;
660 			if (std & V4L2_STD_625_50) {
661 				height = 576;
662 				return hz50;
663 			}
664 		}
665 
666 		if (!g_dv_timings(timings)) {
667 			width = timings.bt.width;
668 			height = timings.bt.height;
669 			if (width == 720 && height == 480)
670 				return hz60;
671 			if (width == 720 && height == 576) {
672 				height = 576;
673 				return hz50;
674 			}
675 			return square;
676 		}
677 		width = 0;
678 		height = 0;
679 		return square;
680 	}
681 };
682 
683 class cv4l_fmt : public v4l2_format {
684 public:
685 	cv4l_fmt(unsigned _type = 0)
686 	{
687 		v4l_format_init(this, _type);
688 	}
cv4l_fmt(const v4l2_format & _fmt)689 	cv4l_fmt(const v4l2_format &_fmt)
690 	{
691 		memcpy(this, &_fmt, sizeof(_fmt));
692 	}
693 
g_type()694 	uint32_t g_type() { return type; }
s_type(unsigned type)695 	void s_type(unsigned type) { v4l_format_init(this, type); }
g_width()696 	uint32_t g_width() const { return v4l_format_g_width(this); }
s_width(uint32_t width)697 	void s_width(uint32_t width) { v4l_format_s_width(this, width); }
g_height()698 	uint32_t g_height() const { return v4l_format_g_height(this); }
s_height(uint32_t height)699 	void s_height(uint32_t height) { v4l_format_s_height(this, height); }
g_frame_height()700 	uint32_t g_frame_height() const { return v4l_format_g_frame_height(this); }
s_frame_height(uint32_t height)701 	void s_frame_height(uint32_t height) { v4l_format_s_frame_height(this, height); }
g_pixelformat()702 	uint32_t g_pixelformat() const { return v4l_format_g_pixelformat(this); }
s_pixelformat(uint32_t pixelformat)703 	void s_pixelformat(uint32_t pixelformat) { v4l_format_s_pixelformat(this, pixelformat); }
g_colorspace()704 	unsigned g_colorspace() const { return v4l_format_g_colorspace(this); }
s_colorspace(unsigned colorspace)705 	void s_colorspace(unsigned colorspace) { v4l_format_s_colorspace(this, colorspace); }
g_xfer_func()706 	unsigned g_xfer_func() const { return v4l_format_g_xfer_func(this); }
s_xfer_func(unsigned xfer_func)707 	void s_xfer_func(unsigned xfer_func) { v4l_format_s_xfer_func(this, xfer_func); }
g_ycbcr_enc()708 	unsigned g_ycbcr_enc() const { return v4l_format_g_ycbcr_enc(this); }
g_hsv_enc()709 	unsigned g_hsv_enc() const { return v4l_format_g_hsv_enc(this); }
s_ycbcr_enc(unsigned ycbcr_enc)710 	void s_ycbcr_enc(unsigned ycbcr_enc) { v4l_format_s_ycbcr_enc(this, ycbcr_enc); }
g_quantization()711 	unsigned g_quantization() const { return v4l_format_g_quantization(this); }
s_quantization(unsigned quantization)712 	void s_quantization(unsigned quantization) { v4l_format_s_quantization(this, quantization); }
g_flags()713 	unsigned g_flags() const { return v4l_format_g_flags(this); }
s_flags(unsigned flags)714 	void s_flags(unsigned flags) { v4l_format_s_flags(this, flags); }
g_num_planes()715 	uint8_t g_num_planes() const { return v4l_format_g_num_planes(this); }
s_num_planes(uint8_t num_planes)716 	void s_num_planes(uint8_t num_planes) { v4l_format_s_num_planes(this, num_planes); }
717 	uint32_t g_bytesperline(unsigned plane = 0) const { return v4l_format_g_bytesperline(this, plane); }
718 	void s_bytesperline(uint32_t bytesperline, unsigned plane = 0) { v4l_format_s_bytesperline(this, plane, bytesperline); }
719 	uint32_t g_sizeimage(unsigned plane = 0) const { return v4l_format_g_sizeimage(this, plane); }
720 	void s_sizeimage(uint32_t sizeimage, unsigned plane = 0) { v4l_format_s_sizeimage(this, plane, sizeimage); }
g_field()721 	unsigned g_field() const { return v4l_format_g_field(this); }
s_field(unsigned field)722 	void s_field(unsigned field) { v4l_format_s_field(this, field); }
g_first_field(v4l2_std_id std)723 	unsigned g_first_field(v4l2_std_id std) const { return v4l_format_g_first_field(this, std); }
g_flds_per_frm()724 	unsigned g_flds_per_frm() const { return v4l_format_g_flds_per_frm(this); }
725 };
726 
727 class cv4l_buffer;
728 
729 class cv4l_queue : v4l_queue {
730 	friend class cv4l_buffer;
731 public:
732 	cv4l_queue(unsigned type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
733 		   unsigned memory = V4L2_MEMORY_MMAP)
734 	{
735 		v4l_queue_init(this, type, memory);
736 	}
init(unsigned type,unsigned memory)737 	void init(unsigned type, unsigned memory)
738 	{
739 		v4l_queue_init(this, type, memory);
740 	}
g_type()741 	unsigned g_type() const { return v4l_queue_g_type(this); }
g_memory()742 	unsigned g_memory() const { return v4l_queue_g_memory(this); }
g_buffers()743 	unsigned g_buffers() const { return v4l_queue_g_buffers(this); }
g_num_planes()744 	unsigned g_num_planes() const { return v4l_queue_g_num_planes(this); }
g_capabilities()745 	unsigned g_capabilities() const { return v4l_queue_g_capabilities(this); }
g_length(unsigned plane)746 	unsigned g_length(unsigned plane) const { return v4l_queue_g_length(this, plane); }
g_mem_offset(unsigned index,unsigned plane)747 	unsigned g_mem_offset(unsigned index, unsigned plane) const { return v4l_queue_g_mem_offset(this, index, plane); }
g_mmapping(unsigned index,unsigned plane)748 	void *g_mmapping(unsigned index, unsigned plane) const { return v4l_queue_g_mmapping(this, index, plane); }
s_mmapping(unsigned index,unsigned plane,void * m)749 	void s_mmapping(unsigned index, unsigned plane, void *m) { v4l_queue_s_mmapping(this, index, plane, m); }
g_userptr(unsigned index,unsigned plane)750 	void *g_userptr(unsigned index, unsigned plane) const { return v4l_queue_g_userptr(this, index, plane); }
s_userptr(unsigned index,unsigned plane,void * m)751 	void s_userptr(unsigned index, unsigned plane, void *m) { v4l_queue_s_userptr(this, index, plane, m); }
g_dataptr(unsigned index,unsigned plane)752 	void *g_dataptr(unsigned index, unsigned plane) const { return v4l_queue_g_dataptr(this, index, plane); }
g_fd(unsigned index,unsigned plane)753 	int g_fd(unsigned index, unsigned plane) const { return v4l_queue_g_fd(this, index, plane); }
s_fd(unsigned index,unsigned plane,int fd)754 	void s_fd(unsigned index, unsigned plane, int fd) { v4l_queue_s_fd(this, index, plane, fd); }
755 
756 	int reqbufs(cv4l_fd *fd, unsigned count = 0)
757 	{
758 		return v4l_queue_reqbufs(fd->g_v4l_fd(), this, count);
759 	}
has_create_bufs(cv4l_fd * fd)760 	bool has_create_bufs(cv4l_fd *fd) const
761 	{
762 		return v4l_queue_has_create_bufs(fd->g_v4l_fd(), this);
763 	}
764 	int create_bufs(cv4l_fd *fd, unsigned count, const v4l2_format *fmt = NULL)
765 	{
766 		return v4l_queue_create_bufs(fd->g_v4l_fd(), this, count, fmt);
767 	}
768 	int mmap_bufs(cv4l_fd *fd, unsigned from = 0)
769 	{
770 		return v4l_queue_mmap_bufs(fd->g_v4l_fd(), this, from);
771 	}
772 	int munmap_bufs(cv4l_fd *fd, unsigned from = 0)
773 	{
774 		return v4l_queue_munmap_bufs(fd->g_v4l_fd(), this, from);
775 	}
776 	int alloc_bufs(cv4l_fd *fd, unsigned from = 0)
777 	{
778 		return v4l_queue_alloc_bufs(fd->g_v4l_fd(), this, from);
779 	}
780 	int free_bufs(unsigned from = 0)
781 	{
782 		return v4l_queue_free_bufs(this, from);
783 	}
784 	int obtain_bufs(cv4l_fd *fd, unsigned from = 0)
785 	{
786 		return v4l_queue_obtain_bufs(fd->g_v4l_fd(), this, from);
787 	}
788 	int release_bufs(cv4l_fd *fd, unsigned from = 0)
789 	{
790 		return v4l_queue_release_bufs(fd->g_v4l_fd(), this, from);
791 	}
has_expbuf(cv4l_fd * fd)792 	bool has_expbuf(cv4l_fd *fd)
793 	{
794 		return v4l_queue_has_expbuf(fd->g_v4l_fd());
795 	}
export_bufs(cv4l_fd * fd,unsigned exp_type)796 	int export_bufs(cv4l_fd *fd, unsigned exp_type)
797 	{
798 		return v4l_queue_export_bufs(fd->g_v4l_fd(), this, exp_type);
799 	}
close_exported_fds()800 	void close_exported_fds()
801 	{
802 		v4l_queue_close_exported_fds(this);
803 	}
free(cv4l_fd * fd)804 	void free(cv4l_fd *fd)
805 	{
806 		v4l_queue_free(fd->g_v4l_fd(), this);
807 	}
buffer_init(v4l_buffer & buf,unsigned index)808 	void buffer_init(v4l_buffer &buf, unsigned index) const
809 	{
810 		v4l_queue_buffer_init(this, &buf, index);
811 	}
buffer_update(v4l_buffer & buf,unsigned index)812 	void buffer_update(v4l_buffer &buf, unsigned index) const
813 	{
814 		v4l_queue_buffer_update(this, &buf, index);
815 	}
816 	int queue_all(cv4l_fd *fd);
817 };
818 
819 class cv4l_buffer : public v4l_buffer {
820 public:
821 	cv4l_buffer(unsigned type = 0, unsigned memory = 0, unsigned index = 0)
822 	{
823 		init(type, memory, index);
824 	}
825 	cv4l_buffer(const cv4l_queue &q, unsigned index = 0)
826 	{
827 		init(q, index);
828 	}
cv4l_buffer(const cv4l_buffer & b)829 	cv4l_buffer(const cv4l_buffer &b)
830 	{
831 		init(b);
832 	}
833 	cv4l_buffer operator= (const cv4l_buffer &b)
834 	{
835 		return *this;
836 	}
~cv4l_buffer()837 	virtual ~cv4l_buffer() {}
838 
839 	void init(unsigned type = 0, unsigned memory = 0, unsigned index = 0)
840 	{
841 		v4l_buffer_init(this, type, memory, index);
842 	}
843 	void init(const cv4l_queue &q, unsigned index = 0)
844 	{
845 		q.buffer_init(*this, index);
846 	}
init(const cv4l_buffer & b)847 	void init(const cv4l_buffer &b)
848 	{
849 		memcpy((v4l2_buffer *)this, (v4l2_buffer *)&b, sizeof(b));
850 		if (v4l_type_is_planar(g_type()))
851 			buf.m.planes = planes;
852 	}
853 	void update(const cv4l_queue &q, unsigned index = 0)
854 	{
855 		q.buffer_update(*this, index);
856 	}
857 
g_index()858 	uint32_t g_index() const { return v4l_buffer_g_index(this); }
s_index(unsigned index)859 	void s_index(unsigned index) { v4l_buffer_s_index(this, index); }
g_request_fd()860 	int32_t g_request_fd() const { return v4l_buffer_g_request_fd(this); }
s_request_fd(int32_t request_fd)861 	void s_request_fd(int32_t request_fd) { v4l_buffer_s_request_fd(this, request_fd); }
g_type()862 	unsigned g_type() const { return v4l_buffer_g_type(this); }
g_memory()863 	unsigned g_memory() const { return v4l_buffer_g_memory(this); }
g_flags()864 	uint32_t g_flags() const { return v4l_buffer_g_flags(this); }
s_flags(uint32_t flags)865 	void s_flags(uint32_t flags) { v4l_buffer_s_flags(this, flags); }
or_flags(uint32_t flags)866 	void or_flags(uint32_t flags) { v4l_buffer_or_flags(this, flags); }
g_field()867 	unsigned g_field() const { return v4l_buffer_g_field(this); }
s_field(unsigned field)868 	void s_field(unsigned field) { v4l_buffer_s_field(this, field); }
869 
g_num_planes()870 	unsigned g_num_planes() const { return v4l_buffer_g_num_planes(this); }
871 	uint32_t g_mem_offset(unsigned plane = 0) const { return v4l_buffer_g_mem_offset(this, plane); }
872 	void *g_userptr(unsigned plane = 0) const { return v4l_buffer_g_userptr(this, plane); }
873 	void s_userptr(void *userptr, unsigned plane = 0) { v4l_buffer_s_userptr(this, plane, userptr); }
874 	int g_fd(unsigned plane = 0) const { return v4l_buffer_g_fd(this, plane); }
875 	void s_fd(int fd, unsigned plane = 0) { v4l_buffer_s_fd(this, plane, fd); }
876 	uint32_t g_bytesused(unsigned plane = 0) const { return v4l_buffer_g_bytesused(this, plane); }
877 	void s_bytesused(uint32_t bytesused, unsigned plane = 0) { v4l_buffer_s_bytesused(this, plane, bytesused); }
878 	uint32_t g_data_offset(unsigned plane = 0) const { return v4l_buffer_g_data_offset(this, plane); }
879 	void s_data_offset(uint32_t data_offset, unsigned plane = 0) { v4l_buffer_s_data_offset(this, plane, data_offset); }
880 	uint32_t g_length(unsigned plane = 0) const { return v4l_buffer_g_length(this, plane); }
881 	void s_length(unsigned length, unsigned plane = 0) { return v4l_buffer_s_length(this, plane, length); }
882 
g_sequence()883 	uint32_t g_sequence() const { return v4l_buffer_g_sequence(this); }
g_timestamp_type()884 	uint32_t g_timestamp_type() const { return v4l_buffer_g_timestamp_type(this); }
g_timestamp_src()885 	uint32_t g_timestamp_src() const { return v4l_buffer_g_timestamp_src(this); }
s_timestamp_src(uint32_t src)886 	void s_timestamp_src(uint32_t src) { v4l_buffer_s_timestamp_src(this, src); }
ts_is_copy()887 	bool ts_is_copy() const { return v4l_buffer_is_copy(this); }
g_timestamp()888 	const timeval &g_timestamp() const { return *v4l_buffer_g_timestamp(this); }
g_timestamp_ns()889 	uint64_t g_timestamp_ns() const { return v4l2_timeval_to_ns(v4l_buffer_g_timestamp(this)); }
s_timestamp(const timeval & tv)890 	void s_timestamp(const timeval &tv) { v4l_buffer_s_timestamp(this, &tv); }
s_timestamp_ts(const timespec & ts)891 	void s_timestamp_ts(const timespec &ts) { v4l_buffer_s_timestamp_ts(this, &ts); }
s_timestamp_clock()892 	void s_timestamp_clock() { v4l_buffer_s_timestamp_clock(this); }
g_timecode()893 	const v4l2_timecode &g_timecode() const { return *v4l_buffer_g_timecode(this); }
s_timecode(const v4l2_timecode & tc)894 	void s_timecode(const v4l2_timecode &tc) { v4l_buffer_s_timecode(this, &tc); }
895 };
896 
queue_all(cv4l_fd * fd)897 inline int cv4l_queue::queue_all(cv4l_fd *fd)
898 {
899 	cv4l_buffer buf;
900 
901 	for (unsigned i = 0; i < g_buffers(); i++) {
902 		buf.init(*this, i);
903 		int ret = fd->qbuf(buf);
904 		if (ret)
905 			return ret;
906 	}
907 	return 0;
908 }
909 
910 #endif
911