~ubuntu-branches/debian/sid/v4l-utils/sid

« back to all changes in this revision

Viewing changes to utils/qv4l2-qt4/v4l2-api.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Gregor Jasny
  • Date: 2010-02-28 19:44:15 UTC
  • Revision ID: james.westby@ubuntu.com-20100228194415-067hdj8rvawj91zw
Tags: upstream-0.7.90
ImportĀ upstreamĀ versionĀ 0.7.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* v4l2-api: low-level wrapper around v4l2 devices
 
2
 *
 
3
 * Copyright (C) 2009 Hans Verkuil <hverkuil@xs4all.nl>
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or
 
6
 * modify it under the terms of the GNU General Public License
 
7
 * as published by the Free Software Foundation; either version 2
 
8
 * of the License, or (at your option) any later version.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 * GNU General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License
 
16
 * along with this program; if not, write to the Free Software
 
17
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
18
 */
 
19
 
 
20
#include <fcntl.h>
 
21
#include <sys/ioctl.h>
 
22
#include <sys/mman.h>
 
23
#include <errno.h>
 
24
#include <limits.h>
 
25
#include <libv4l2.h>
 
26
#include "v4l2-api.h"
 
27
 
 
28
bool v4l2::open(const QString &device, bool useWrapper)
 
29
{
 
30
        m_device = device;
 
31
        m_useWrapper = useWrapper;
 
32
        m_fd = ::open(device.toAscii(), O_RDWR | O_NONBLOCK);
 
33
        if (m_fd < 0) {
 
34
                error("Cannot open " + device);
 
35
                return false;
 
36
        }
 
37
        if (!querycap(m_capability)) {
 
38
                ::close(m_fd);
 
39
                m_fd = -1;
 
40
                error(device + " is not a V4L2 device");
 
41
                return false;
 
42
        }
 
43
 
 
44
        if (m_useWrapper) {
 
45
                int fd = ::v4l2_fd_open(m_fd, V4L2_ENABLE_ENUM_FMT_EMULATION);
 
46
 
 
47
                if (fd < 0) {
 
48
                        m_useWrapper = false;
 
49
                        error("Cannot use libv4l2 wrapper for " + device);
 
50
                }
 
51
        }
 
52
        return true;
 
53
}
 
54
 
 
55
void v4l2::close()
 
56
{
 
57
        if (useWrapper())
 
58
                ::v4l2_close(m_fd);
 
59
        else
 
60
                ::close(m_fd);
 
61
        m_fd = -1;
 
62
}
 
63
 
 
64
int v4l2::ioctl(unsigned cmd, void *arg)
 
65
{
 
66
        if (useWrapper())
 
67
                return v4l2_ioctl(m_fd, cmd, arg);
 
68
        return ::ioctl(m_fd, cmd, arg);
 
69
}
 
70
 
 
71
bool v4l2::ioctl(const QString &descr, unsigned cmd, void *arg)
 
72
{
 
73
        clear();
 
74
        int err = ioctl(cmd, arg);
 
75
 
 
76
        if (err < 0) {
 
77
                QString s = strerror(errno);
 
78
                error(descr + ": " + s);
 
79
        }
 
80
        return err >= 0;
 
81
}
 
82
 
 
83
int v4l2::read(unsigned char *p, int size)
 
84
{
 
85
        if (useWrapper())
 
86
                return v4l2_read(m_fd, p, size);
 
87
        return ::read(m_fd, p, size);
 
88
}
 
89
 
 
90
void *v4l2::mmap(size_t length, __off64_t offset)
 
91
{
 
92
        if (useWrapper())
 
93
                return v4l2_mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, m_fd, offset);
 
94
        return ::mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, m_fd, offset);
 
95
}
 
96
 
 
97
int v4l2::munmap(void *start, size_t length)
 
98
{
 
99
        if (useWrapper())
 
100
                return v4l2_munmap(start, length);
 
101
        return ::munmap(start, length);
 
102
}
 
103
 
 
104
void v4l2::error(const QString &error)
 
105
{
 
106
        if (!error.isEmpty())
 
107
                fprintf(stderr, "%s\n", error.toAscii().data());
 
108
}
 
109
 
 
110
QString v4l2::pixfmt2s(unsigned id)
 
111
{
 
112
        QString pixfmt;
 
113
 
 
114
        pixfmt += (char)(id & 0xff);
 
115
        pixfmt += (char)((id >> 8) & 0xff);
 
116
        pixfmt += (char)((id >> 16) & 0xff);
 
117
        pixfmt += (char)((id >> 24) & 0xff);
 
118
        return pixfmt;
 
119
}
 
120
 
 
121
bool v4l2::querycap(v4l2_capability &cap)
 
122
{
 
123
        memset(&cap, 0, sizeof(cap));
 
124
        return ioctl(VIDIOC_QUERYCAP, &cap) >= 0;
 
125
}
 
126
 
 
127
bool v4l2::queryctrl(v4l2_queryctrl &qc)
 
128
{
 
129
        return ioctl(VIDIOC_QUERYCTRL, &qc) >= 0;
 
130
}
 
131
 
 
132
bool v4l2::querymenu(v4l2_querymenu &qm)
 
133
{
 
134
        return ioctl(VIDIOC_QUERYMENU, &qm) >= 0;
 
135
}
 
136
 
 
137
bool v4l2::g_tuner(v4l2_tuner &tuner)
 
138
{
 
139
        memset(&tuner, 0, sizeof(tuner));
 
140
        if (ioctl(VIDIOC_G_TUNER, &tuner) < 0)
 
141
                return false;
 
142
        if (tuner.rangehigh > INT_MAX)
 
143
                tuner.rangehigh = INT_MAX;
 
144
        return true;
 
145
}
 
146
 
 
147
bool v4l2::g_input(int &input)
 
148
{
 
149
        return ioctl(VIDIOC_G_INPUT, &input) >= 0;
 
150
}
 
151
 
 
152
bool v4l2::s_input(int input)
 
153
{
 
154
        return ioctl("Set Input", VIDIOC_S_INPUT, &input);
 
155
}
 
156
 
 
157
bool v4l2::g_output(int &output)
 
158
{
 
159
        return ioctl(VIDIOC_G_OUTPUT, &output) >= 0;
 
160
}
 
161
 
 
162
bool v4l2::s_output(int output)
 
163
{
 
164
        return ioctl("Set Output", VIDIOC_S_OUTPUT, &output);
 
165
}
 
166
 
 
167
bool v4l2::g_audio(v4l2_audio &audio)
 
168
{
 
169
        memset(&audio, 0, sizeof(audio));
 
170
        return ioctl(VIDIOC_G_AUDIO, &audio) >= 0;
 
171
}
 
172
 
 
173
bool v4l2::s_audio(int input)
 
174
{
 
175
        v4l2_audio audio;
 
176
 
 
177
        memset(&audio, 0, sizeof(audio));
 
178
        audio.index = input;
 
179
        return ioctl("Set Audio Input", VIDIOC_S_AUDIO, &audio);
 
180
}
 
181
 
 
182
bool v4l2::g_audout(v4l2_audioout &audout)
 
183
{
 
184
        memset(&audout, 0, sizeof(audout));
 
185
        return ioctl(VIDIOC_G_AUDOUT, &audout) >= 0;
 
186
}
 
187
 
 
188
bool v4l2::s_audout(int output)
 
189
{
 
190
        v4l2_audioout audout;
 
191
 
 
192
        memset(&audout, 0, sizeof(audout));
 
193
        audout.index = output;
 
194
        return ioctl("Set Audio Output", VIDIOC_S_AUDOUT, &audout);
 
195
}
 
196
 
 
197
bool v4l2::g_std(v4l2_std_id &std)
 
198
{
 
199
        return ioctl(VIDIOC_G_STD, &std) >= 0;
 
200
}
 
201
 
 
202
bool v4l2::s_std(v4l2_std_id std)
 
203
{
 
204
        return ioctl("Set TV Standard", VIDIOC_S_STD, &std);
 
205
}
 
206
 
 
207
bool v4l2::g_frequency(v4l2_frequency &freq)
 
208
{
 
209
        memset(&freq, 0, sizeof(freq));
 
210
        freq.type = V4L2_TUNER_ANALOG_TV;
 
211
        return ioctl(VIDIOC_G_FREQUENCY, &freq) >= 0;
 
212
}
 
213
 
 
214
bool v4l2::s_frequency(v4l2_frequency &freq)
 
215
{
 
216
        return ioctl("Set Frequency", VIDIOC_S_FREQUENCY, &freq);
 
217
}
 
218
 
 
219
bool v4l2::s_frequency(int val)
 
220
{
 
221
        v4l2_frequency f;
 
222
 
 
223
        memset(&f, 0, sizeof(f));
 
224
        f.type = V4L2_TUNER_ANALOG_TV;
 
225
        f.frequency = val;
 
226
        return s_frequency(f);
 
227
}
 
228
 
 
229
bool v4l2::g_fmt_cap(v4l2_format &fmt)
 
230
{
 
231
        memset(&fmt, 0, sizeof(fmt));
 
232
        fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
233
        return ioctl(VIDIOC_G_FMT, &fmt) >= 0;
 
234
}
 
235
 
 
236
bool v4l2::g_fmt_out(v4l2_format &fmt)
 
237
{
 
238
        memset(&fmt, 0, sizeof(fmt));
 
239
        fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
 
240
        return ioctl(VIDIOC_G_FMT, &fmt) >= 0;
 
241
}
 
242
 
 
243
bool v4l2::try_fmt(v4l2_format &fmt)
 
244
{
 
245
        return ioctl("Try Capture Format", VIDIOC_TRY_FMT, &fmt);
 
246
}
 
247
 
 
248
bool v4l2::s_fmt(v4l2_format &fmt)
 
249
{
 
250
        return ioctl("Set Capture Format", VIDIOC_S_FMT, &fmt);
 
251
}
 
252
 
 
253
bool v4l2::enum_input(v4l2_input &in, bool init)
 
254
{
 
255
        if (init)
 
256
                memset(&in, 0, sizeof(in));
 
257
        else
 
258
                in.index++;
 
259
        return ioctl(VIDIOC_ENUMINPUT, &in) >= 0;
 
260
}
 
261
 
 
262
bool v4l2::enum_output(v4l2_output &out, bool init)
 
263
{
 
264
        if (init)
 
265
                memset(&out, 0, sizeof(out));
 
266
        else
 
267
                out.index++;
 
268
        return ioctl(VIDIOC_ENUMOUTPUT, &out) >= 0;
 
269
}
 
270
 
 
271
bool v4l2::enum_audio(v4l2_audio &audio, bool init)
 
272
{
 
273
        if (init)
 
274
                memset(&audio, 0, sizeof(audio));
 
275
        else
 
276
                audio.index++;
 
277
        return ioctl(VIDIOC_ENUMAUDIO, &audio) >= 0;
 
278
}
 
279
 
 
280
bool v4l2::enum_audout(v4l2_audioout &audout, bool init)
 
281
{
 
282
        if (init)
 
283
                memset(&audout, 0, sizeof(audout));
 
284
        else
 
285
                audout.index++;
 
286
        return ioctl(VIDIOC_ENUMAUDOUT, &audout) >= 0;
 
287
}
 
288
 
 
289
bool v4l2::enum_std(v4l2_standard &std, bool init, int index)
 
290
{
 
291
        if (init) {
 
292
                memset(&std, 0, sizeof(std));
 
293
                std.index = index;
 
294
        } else {
 
295
                std.index++;
 
296
        }
 
297
        return ioctl(VIDIOC_ENUMSTD, &std) >= 0;
 
298
}
 
299
 
 
300
bool v4l2::enum_fmt_cap(v4l2_fmtdesc &fmt, bool init, int index)
 
301
{
 
302
        if (init) {
 
303
                memset(&fmt, 0, sizeof(fmt));
 
304
                fmt.index = index;
 
305
        } else {
 
306
                fmt.index++;
 
307
        }
 
308
        fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
309
        return ioctl(VIDIOC_ENUM_FMT, &fmt) >= 0;
 
310
}
 
311
 
 
312
bool v4l2::enum_fmt_out(v4l2_fmtdesc &fmt, bool init, int index)
 
313
{
 
314
        if (init) {
 
315
                memset(&fmt, 0, sizeof(fmt));
 
316
                fmt.index = index;
 
317
        } else {
 
318
                fmt.index++;
 
319
        }
 
320
        fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
 
321
        return ioctl(VIDIOC_ENUM_FMT, &fmt) >= 0;
 
322
}
 
323
 
 
324
bool v4l2::enum_framesizes(v4l2_frmsizeenum &frm, __u32 init_pixfmt, int index)
 
325
{
 
326
        if (init_pixfmt) {
 
327
                memset(&frm, 0, sizeof(frm));
 
328
                frm.pixel_format = init_pixfmt;
 
329
                frm.index = index;
 
330
        } else {
 
331
                frm.index++;
 
332
        }
 
333
        return ioctl(VIDIOC_ENUM_FRAMESIZES, &frm) >= 0;
 
334
}
 
335
 
 
336
bool v4l2::enum_frameintervals(v4l2_frmivalenum &frm, __u32 init_pixfmt, __u32 w, __u32 h, int index)
 
337
{
 
338
        if (init_pixfmt) {
 
339
                memset(&frm, 0, sizeof(frm));
 
340
                frm.pixel_format = init_pixfmt;
 
341
                frm.width = w;
 
342
                frm.height = h;
 
343
                frm.index = index;
 
344
        } else {
 
345
                frm.index++;
 
346
        }
 
347
        return ioctl(VIDIOC_ENUM_FRAMEINTERVALS, &frm) >= 0;
 
348
}
 
349
 
 
350
bool v4l2::reqbufs_user_cap(v4l2_requestbuffers &reqbuf, int count)
 
351
{
 
352
        memset(&reqbuf, 0, sizeof (reqbuf));
 
353
        reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
354
        reqbuf.memory = V4L2_MEMORY_USERPTR;
 
355
        reqbuf.count = count;
 
356
 
 
357
        return ioctl(VIDIOC_REQBUFS, &reqbuf) >= 0;
 
358
}
 
359
 
 
360
bool v4l2::reqbufs_mmap_cap(v4l2_requestbuffers &reqbuf, int count)
 
361
{
 
362
        memset(&reqbuf, 0, sizeof (reqbuf));
 
363
        reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
364
        reqbuf.memory = V4L2_MEMORY_MMAP;
 
365
        reqbuf.count = count;
 
366
 
 
367
        return ioctl(VIDIOC_REQBUFS, &reqbuf) >= 0;
 
368
}
 
369
 
 
370
bool v4l2::dqbuf_mmap_cap(v4l2_buffer &buf)
 
371
{
 
372
        memset(&buf, 0, sizeof(buf));
 
373
        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
374
        buf.memory = V4L2_MEMORY_MMAP;
 
375
        return ioctl(VIDIOC_DQBUF, &buf) >= 0;
 
376
}
 
377
 
 
378
bool v4l2::dqbuf_user_cap(v4l2_buffer &buf)
 
379
{
 
380
        memset(&buf, 0, sizeof(buf));
 
381
        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
382
        buf.memory = V4L2_MEMORY_USERPTR;
 
383
        return ioctl(VIDIOC_DQBUF, &buf) >= 0;
 
384
}
 
385
 
 
386
bool v4l2::qbuf(v4l2_buffer &buf)
 
387
{
 
388
        return ioctl(VIDIOC_QBUF, &buf) >= 0;
 
389
}
 
390
 
 
391
bool v4l2::qbuf_mmap_cap(int index)
 
392
{
 
393
        v4l2_buffer buf;
 
394
 
 
395
        memset(&buf, 0, sizeof(buf));
 
396
        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
397
        buf.memory = V4L2_MEMORY_MMAP;
 
398
        buf.index = index;
 
399
        return qbuf(buf);
 
400
}
 
401
 
 
402
bool v4l2::qbuf_user_cap(int index, void *ptr, int length)
 
403
{
 
404
        v4l2_buffer buf;
 
405
 
 
406
        memset(&buf, 0, sizeof(buf));
 
407
        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
408
        buf.memory = V4L2_MEMORY_USERPTR;
 
409
        buf.m.userptr = (unsigned long)ptr;
 
410
        buf.length = length;
 
411
        buf.index = index;
 
412
        return qbuf(buf);
 
413
}
 
414
 
 
415
bool v4l2::streamon_cap()
 
416
{
 
417
        enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
418
 
 
419
        return ioctl("Start Capture", VIDIOC_STREAMON, &type);
 
420
}
 
421
 
 
422
bool v4l2::streamoff_cap()
 
423
{
 
424
        enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
425
 
 
426
        return ioctl("Stop Capture", VIDIOC_STREAMOFF, &type);
 
427
}
 
428
 
 
429
bool v4l2::reqbufs_user_out(v4l2_requestbuffers &reqbuf)
 
430
{
 
431
        memset(&reqbuf, 0, sizeof (reqbuf));
 
432
        reqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
 
433
        reqbuf.memory = V4L2_MEMORY_USERPTR;
 
434
 
 
435
        return ioctl(VIDIOC_REQBUFS, &reqbuf) >= 0;
 
436
}
 
437
 
 
438
bool v4l2::reqbufs_mmap_out(v4l2_requestbuffers &reqbuf, int count)
 
439
{
 
440
        memset(&reqbuf, 0, sizeof (reqbuf));
 
441
        reqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
 
442
        reqbuf.memory = V4L2_MEMORY_MMAP;
 
443
        reqbuf.count = count;
 
444
 
 
445
        return ioctl(VIDIOC_REQBUFS, &reqbuf) >= 0;
 
446
}
 
447
 
 
448
bool v4l2::dqbuf_mmap_out(v4l2_buffer &buf)
 
449
{
 
450
        memset(&buf, 0, sizeof(buf));
 
451
        buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
 
452
        buf.memory = V4L2_MEMORY_MMAP;
 
453
        return ioctl("dqbuf", VIDIOC_DQBUF, &buf);
 
454
}
 
455
 
 
456
bool v4l2::dqbuf_user_out(v4l2_buffer &buf)
 
457
{
 
458
        memset(&buf, 0, sizeof(buf));
 
459
        buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
 
460
        buf.memory = V4L2_MEMORY_USERPTR;
 
461
        return ioctl(VIDIOC_DQBUF, &buf) >= 0;
 
462
}
 
463
 
 
464
bool v4l2::qbuf_mmap_out(int index, int bytesused)
 
465
{
 
466
        v4l2_buffer buf;
 
467
 
 
468
        memset(&buf, 0, sizeof(buf));
 
469
        buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
 
470
        buf.memory = V4L2_MEMORY_MMAP;
 
471
        buf.index = index;
 
472
        buf.bytesused = bytesused;
 
473
        return qbuf(buf);
 
474
}
 
475
 
 
476
bool v4l2::qbuf_user_out(void *ptr, int length)
 
477
{
 
478
        v4l2_buffer buf;
 
479
 
 
480
        memset(&buf, 0, sizeof(buf));
 
481
        buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
 
482
        buf.memory = V4L2_MEMORY_USERPTR;
 
483
        buf.m.userptr = (unsigned long)ptr;
 
484
        buf.length = length;
 
485
        return qbuf(buf);
 
486
}
 
487
 
 
488
bool v4l2::streamon_out()
 
489
{
 
490
        enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
 
491
 
 
492
        return ioctl("Start Output", VIDIOC_STREAMON, &type);
 
493
}
 
494
 
 
495
bool v4l2::streamoff_out()
 
496
{
 
497
        enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
 
498
 
 
499
        return ioctl("Stop Output", VIDIOC_STREAMOFF, &type);
 
500
}