Skip to content

Commit f567e55

Browse files
committed
[libuvc] fix issue #21
1 parent 657c88c commit f567e55

File tree

3 files changed

+103
-11
lines changed

3 files changed

+103
-11
lines changed

libuvc/libuvc.c

Lines changed: 78 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,11 @@ struct v4l2_ctx {
6666
struct iovec buf[MAX_V4L_BUF];
6767
int buf_index;
6868
int req_count;
69+
bool qbuf_done;
6970
struct v4l2_capability cap;
7071
uint32_t ctrl_flags;
7172
struct v4l2_queryctrl controls[MAX_V4L2_CID];
73+
struct uvc_ctx *parent;
7274
};
7375

7476
static int v4l2_get_cap(struct v4l2_ctx *vc)
@@ -120,11 +122,10 @@ static char *v4l2_fourcc_parse(char *buf, int len, uint32_t pix)
120122
if (len < 5) {
121123
return NULL;
122124
}
123-
snprintf(buf, len, "%c%c%c%c",
124-
(pix&0x000000FF),
125-
(pix&0x0000FF00)>>8,
126-
(pix&0x00FF0000)>>16,
127-
(pix&0xFF000000)>>24);
125+
snprintf(buf, len, "%c%c%c%c", (pix&0x000000FF),
126+
(pix&0x0000FF00)>>8,
127+
(pix&0x00FF0000)>>16,
128+
(pix&0xFF000000)>>24);
128129
return buf;
129130
}
130131

@@ -185,14 +186,12 @@ static void v4l2_get_cid(struct v4l2_ctx *vc)
185186
qctrl = &vc->controls[i];
186187
qctrl->id = v4l2_cid_supported[i];
187188
if (-1 == ioctl(vc->fd, VIDIOC_QUERYCTRL, qctrl)) {
188-
//printf("\t%s is not supported!\n", qctrl->name);
189189
continue;
190190
}
191191
vc->ctrl_flags |= 1 << i;
192192
memset(&control, 0, sizeof (control));
193193
control.id = v4l2_cid_supported[i];
194194
if (-1 == ioctl(vc->fd, VIDIOC_G_CTRL, &control)) {
195-
//printf("ioctl VIDIOC_G_CTRL %s failed!\n", qctrl->name);
196195
continue;
197196
}
198197
printf("\t%s, range: [%d, %d], default: %d, current: %d\n",
@@ -229,7 +228,6 @@ static int v4l2_set_format(struct v4l2_ctx *vc)
229228
v4l2_fourcc_parse(pixel, sizeof(pixel), V4L2_PIX_FMT_YUYV));
230229
}
231230
if (vc->width > 0 || vc->height > 0) {
232-
//set v4l2 pixel format
233231
pix->width = vc->width;
234232
pix->height = vc->height;
235233
} else {
@@ -287,6 +285,7 @@ static int v4l2_req_buf(struct v4l2_ctx *vc)
287285
return -1;
288286
}
289287
}
288+
vc->qbuf_done = true;
290289
//stream on
291290
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
292291
if (-1 == ioctl(vc->fd, VIDIOC_STREAMON, &type)) {
@@ -345,18 +344,27 @@ static int v4l2_buf_enqueue(struct v4l2_ctx *vc)
345344
.index = vc->buf_index
346345
};
347346

347+
if (vc->qbuf_done) {
348+
return 0;
349+
}
348350
if (-1 == ioctl(vc->fd, VIDIOC_QBUF, &buf)) {
349351
printf("%s ioctl(VIDIOC_QBUF) failed: %d\n", __func__, errno);
350352
return -1;
351353
}
354+
vc->qbuf_done = true;
352355
return 0;
353356
}
354357

355358
static int v4l2_buf_dequeue(struct v4l2_ctx *vc, struct frame *f)
356359
{
357360
struct v4l2_buffer buf;
361+
memset(&buf, 0, sizeof(buf));
358362
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
359363
buf.memory = V4L2_MEMORY_MMAP;
364+
if (!vc->qbuf_done) {
365+
printf("v4l2 need VIDIOC_QBUF first!\n");
366+
return -1;
367+
}
360368
while (1) {
361369
if (-1 == ioctl(vc->fd, VIDIOC_DQBUF, &buf)) {
362370
printf("%s ioctl(VIDIOC_DQBUF) failed: %d\n", __func__, errno);
@@ -368,7 +376,9 @@ static int v4l2_buf_dequeue(struct v4l2_ctx *vc, struct frame *f)
368376
}
369377
break;
370378
}
379+
vc->qbuf_done = false;
371380
vc->buf_index = buf.index;
381+
memcpy(&vc->parent->timestamp, &buf.timestamp, sizeof(struct timeval));
372382
f->index = buf.index;
373383
f->buf.iov_base = vc->buf[buf.index].iov_base;
374384
f->buf.iov_len = buf.bytesused;
@@ -432,6 +442,7 @@ struct uvc_ctx *uvc_open(const char *dev, int width, int height)
432442
printf("v4l2_open %s failed!\n", dev);
433443
goto failed;
434444
}
445+
vc->parent = uvc;
435446
uvc->width = width;
436447
uvc->height = height;
437448
uvc->opaque = vc;
@@ -444,10 +455,68 @@ struct uvc_ctx *uvc_open(const char *dev, int width, int height)
444455
int uvc_read(struct uvc_ctx *uvc, void *buf, size_t len)
445456
{
446457
struct v4l2_ctx *vc = (struct v4l2_ctx *)uvc->opaque;
447-
v4l2_write(vc);
458+
if (-1 == v4l2_write(vc)) {
459+
return -1;
460+
}
448461
return v4l2_read(vc, buf, len);
449462
}
450463

464+
static int v4l2_set_control(struct v4l2_ctx *vc, uint32_t cid, int value)
465+
{
466+
int i;
467+
struct v4l2_control control;
468+
int ret = -1;
469+
for (i = 0; v4l2_cid_supported[i]; i++) {
470+
if (!(vc->ctrl_flags & (1 << i))) {
471+
continue;
472+
}
473+
if (cid != v4l2_cid_supported[i]) {
474+
continue;
475+
}
476+
struct v4l2_queryctrl *ctrl = &vc->controls[i];
477+
478+
memset(&control, 0, sizeof (control));
479+
control.id = v4l2_cid_supported[i];
480+
switch (ctrl->type) {
481+
case V4L2_CTRL_TYPE_INTEGER://0~255
482+
value = control.value =
483+
(value * (ctrl->maximum - ctrl->minimum) / 256) + ctrl->minimum;
484+
ret = ioctl(vc->fd, VIDIOC_S_CTRL, &control);
485+
break;
486+
487+
case V4L2_CTRL_TYPE_BOOLEAN:
488+
value = control.value = value ? 1 : 0;
489+
ret = ioctl(vc->fd, VIDIOC_S_CTRL, &control);
490+
break;
491+
492+
default:
493+
printf("control type not supported yet");
494+
return -1;
495+
}
496+
printf("setting %s to %d\n", ctrl->name, value);
497+
}
498+
return ret;
499+
}
500+
501+
int uvc_ioctl(struct uvc_ctx *c, uint32_t cmd, void *buf, int len)
502+
{
503+
struct v4l2_ctx *vc = (struct v4l2_ctx *)c->opaque;
504+
struct video_ctrl *vctrl;
505+
switch (cmd) {
506+
case UVC_GET_CAP:
507+
v4l2_get_cap(vc);
508+
break;
509+
case UVC_SET_CTRL:
510+
vctrl = (struct video_ctrl *)buf;
511+
v4l2_set_control(vc, vctrl->cmd, vctrl->val);
512+
break;
513+
default:
514+
printf("cmd %d not supported yet!\n", cmd);
515+
break;
516+
}
517+
return 0;
518+
}
519+
451520
void uvc_close(struct uvc_ctx *uvc)
452521
{
453522
if (!uvc) {

libuvc/libuvc.h

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@
1818
#ifndef LIBUVC_H
1919
#define LIBUVC_H
2020

21-
#include <stddef.h>
21+
#include <stdio.h>
22+
#include <stdint.h>
23+
#include <sys/ioctl.h>
24+
#include <sys/time.h>
2225

2326
#ifdef __cplusplus
2427
extern "C" {
@@ -28,12 +31,28 @@ struct uvc_ctx {
2831
int fd;
2932
int width;
3033
int height;
34+
struct timeval timestamp;
3135
void *opaque;
3236
};
3337

38+
struct video_cap {
39+
uint8_t desc[32];
40+
uint32_t version;
41+
};
42+
43+
struct video_ctrl {
44+
uint32_t cmd;
45+
uint32_t val;
46+
};
47+
48+
#define UVC_GET_CAP _IOWR('V', 0, struct video_cap)
49+
#define UVC_SET_CTRL _IOWR('V', 1, struct video_ctrl)
50+
51+
3452
struct uvc_ctx *uvc_open(const char *dev, int width, int height);
3553
int uvc_print_info(struct uvc_ctx *c);
3654
int uvc_read(struct uvc_ctx *c, void *buf, size_t len);
55+
int uvc_ioctl(struct uvc_ctx *c, uint32_t cmd, void *buf, int len);
3756
void uvc_close(struct uvc_ctx *c);
3857

3958

libuvc/test_libuvc.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,16 @@ int main(int argc, char **argv)
2929
struct uvc_ctx *uvc = uvc_open("/dev/video0", 640, 480);
3030
uvc_print_info(uvc);
3131
struct file *fp = file_open("uvc.yuv", F_CREATE);
32-
for (int i = 0; i < 20; ++i) {
32+
for (int i = 0; i < 64; ++i) {
3333
memset(frm, 0, flen);
3434
size = uvc_read(uvc, frm, flen);
35+
if (size == -1) {
36+
continue;
37+
}
3538
file_write(fp, frm, size);
3639
}
3740
file_close(fp);
41+
uvc_ioctl(uvc, UVC_GET_CAP, NULL, 0);
3842
uvc_close(uvc);
3943
return 0;
4044
}

0 commit comments

Comments
 (0)