@@ -66,9 +66,11 @@ struct v4l2_ctx {
66
66
struct iovec buf [MAX_V4L_BUF ];
67
67
int buf_index ;
68
68
int req_count ;
69
+ bool qbuf_done ;
69
70
struct v4l2_capability cap ;
70
71
uint32_t ctrl_flags ;
71
72
struct v4l2_queryctrl controls [MAX_V4L2_CID ];
73
+ struct uvc_ctx * parent ;
72
74
};
73
75
74
76
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)
120
122
if (len < 5 ) {
121
123
return NULL ;
122
124
}
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 );
128
129
return buf ;
129
130
}
130
131
@@ -185,14 +186,12 @@ static void v4l2_get_cid(struct v4l2_ctx *vc)
185
186
qctrl = & vc -> controls [i ];
186
187
qctrl -> id = v4l2_cid_supported [i ];
187
188
if (-1 == ioctl (vc -> fd , VIDIOC_QUERYCTRL , qctrl )) {
188
- //printf("\t%s is not supported!\n", qctrl->name);
189
189
continue ;
190
190
}
191
191
vc -> ctrl_flags |= 1 << i ;
192
192
memset (& control , 0 , sizeof (control ));
193
193
control .id = v4l2_cid_supported [i ];
194
194
if (-1 == ioctl (vc -> fd , VIDIOC_G_CTRL , & control )) {
195
- //printf("ioctl VIDIOC_G_CTRL %s failed!\n", qctrl->name);
196
195
continue ;
197
196
}
198
197
printf ("\t%s, range: [%d, %d], default: %d, current: %d\n" ,
@@ -229,7 +228,6 @@ static int v4l2_set_format(struct v4l2_ctx *vc)
229
228
v4l2_fourcc_parse (pixel , sizeof (pixel ), V4L2_PIX_FMT_YUYV ));
230
229
}
231
230
if (vc -> width > 0 || vc -> height > 0 ) {
232
- //set v4l2 pixel format
233
231
pix -> width = vc -> width ;
234
232
pix -> height = vc -> height ;
235
233
} else {
@@ -287,6 +285,7 @@ static int v4l2_req_buf(struct v4l2_ctx *vc)
287
285
return -1 ;
288
286
}
289
287
}
288
+ vc -> qbuf_done = true;
290
289
//stream on
291
290
type = V4L2_BUF_TYPE_VIDEO_CAPTURE ;
292
291
if (-1 == ioctl (vc -> fd , VIDIOC_STREAMON , & type )) {
@@ -345,18 +344,27 @@ static int v4l2_buf_enqueue(struct v4l2_ctx *vc)
345
344
.index = vc -> buf_index
346
345
};
347
346
347
+ if (vc -> qbuf_done ) {
348
+ return 0 ;
349
+ }
348
350
if (-1 == ioctl (vc -> fd , VIDIOC_QBUF , & buf )) {
349
351
printf ("%s ioctl(VIDIOC_QBUF) failed: %d\n" , __func__ , errno );
350
352
return -1 ;
351
353
}
354
+ vc -> qbuf_done = true;
352
355
return 0 ;
353
356
}
354
357
355
358
static int v4l2_buf_dequeue (struct v4l2_ctx * vc , struct frame * f )
356
359
{
357
360
struct v4l2_buffer buf ;
361
+ memset (& buf , 0 , sizeof (buf ));
358
362
buf .type = V4L2_BUF_TYPE_VIDEO_CAPTURE ;
359
363
buf .memory = V4L2_MEMORY_MMAP ;
364
+ if (!vc -> qbuf_done ) {
365
+ printf ("v4l2 need VIDIOC_QBUF first!\n" );
366
+ return -1 ;
367
+ }
360
368
while (1 ) {
361
369
if (-1 == ioctl (vc -> fd , VIDIOC_DQBUF , & buf )) {
362
370
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)
368
376
}
369
377
break ;
370
378
}
379
+ vc -> qbuf_done = false;
371
380
vc -> buf_index = buf .index ;
381
+ memcpy (& vc -> parent -> timestamp , & buf .timestamp , sizeof (struct timeval ));
372
382
f -> index = buf .index ;
373
383
f -> buf .iov_base = vc -> buf [buf .index ].iov_base ;
374
384
f -> buf .iov_len = buf .bytesused ;
@@ -432,6 +442,7 @@ struct uvc_ctx *uvc_open(const char *dev, int width, int height)
432
442
printf ("v4l2_open %s failed!\n" , dev );
433
443
goto failed ;
434
444
}
445
+ vc -> parent = uvc ;
435
446
uvc -> width = width ;
436
447
uvc -> height = height ;
437
448
uvc -> opaque = vc ;
@@ -444,10 +455,68 @@ struct uvc_ctx *uvc_open(const char *dev, int width, int height)
444
455
int uvc_read (struct uvc_ctx * uvc , void * buf , size_t len )
445
456
{
446
457
struct v4l2_ctx * vc = (struct v4l2_ctx * )uvc -> opaque ;
447
- v4l2_write (vc );
458
+ if (-1 == v4l2_write (vc )) {
459
+ return -1 ;
460
+ }
448
461
return v4l2_read (vc , buf , len );
449
462
}
450
463
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
+
451
520
void uvc_close (struct uvc_ctx * uvc )
452
521
{
453
522
if (!uvc ) {
0 commit comments