summaryrefslogtreecommitdiff
path: root/v4l2-apps
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@infradead.org>2006-11-28 08:03:23 -0200
committerMauro Carvalho Chehab <mchehab@infradead.org>2006-11-28 08:03:23 -0200
commit05222402b72fa35a14adb35db4e51e55d3b72f2f (patch)
treece5a78e12fb23de330787a3d4d440433af1f6f78 /v4l2-apps
parent87fc384f35e1ee563498df696b57b908a215a499 (diff)
parent080a587ad1c509488047ab48c14f424b3e3c2cd9 (diff)
downloadmediapointer-dvb-s2-05222402b72fa35a14adb35db4e51e55d3b72f2f.tar.gz
mediapointer-dvb-s2-05222402b72fa35a14adb35db4e51e55d3b72f2f.tar.bz2
merge: http://linuxtv.org/hg/~mkrufky/lgdt330x
From: Mauro Carvalho Chehab <mchehab@infradead.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'v4l2-apps')
-rw-r--r--v4l2-apps/lib/Makefile2
-rw-r--r--v4l2-apps/lib/v4l2_driver.c577
-rw-r--r--v4l2-apps/lib/v4l2_driver.h72
-rw-r--r--v4l2-apps/test/Makefile8
-rw-r--r--v4l2-apps/test/driver-test.c80
-rw-r--r--v4l2-apps/test/ioctl-test.c19
-rw-r--r--v4l2-apps/util/qv4l2/general-tab.cpp2
-rw-r--r--v4l2-apps/util/qv4l2/general-tab.h1
-rw-r--r--v4l2-apps/util/v4l2-ctl.cpp71
-rwxr-xr-xv4l2-apps/util/v4l_rec.pl74
10 files changed, 865 insertions, 41 deletions
diff --git a/v4l2-apps/lib/Makefile b/v4l2-apps/lib/Makefile
index a69615bdc..f123f3380 100644
--- a/v4l2-apps/lib/Makefile
+++ b/v4l2-apps/lib/Makefile
@@ -4,7 +4,7 @@ CPPFLAGS += -I../../linux/include -I..
includes = v4l2.h
-objects = frequencies.o
+objects = frequencies.o v4l2_driver.o
sharedlib = libv4l2.so
staticlib = libv4l2.a
diff --git a/v4l2-apps/lib/v4l2_driver.c b/v4l2-apps/lib/v4l2_driver.c
new file mode 100644
index 000000000..e656a550d
--- /dev/null
+++ b/v4l2-apps/lib/v4l2_driver.c
@@ -0,0 +1,577 @@
+/*
+ Copyright (C) 2006 Mauro Carvalho Chehab <mchehab@infradead.org>
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "v4l2_driver.h"
+
+/****************************************************************************
+ Auxiliary routines
+ ****************************************************************************/
+static void free_list(struct drv_list **list_ptr)
+{
+ struct drv_list *prev,*cur;
+
+ if (list_ptr==NULL)
+ return;
+
+ prev=*list_ptr;
+ if (prev==NULL)
+ return;
+
+ do {
+ cur=prev->next;
+ if (prev->curr)
+ free (prev->curr); // Free data
+ free (prev); // Free list
+ prev=cur;
+ } while (prev);
+
+ *list_ptr=NULL;
+}
+
+/****************************************************************************
+ Auxiliary Arrays to aid debug messages
+ ****************************************************************************/
+char *v4l2_field_names[] = {
+ [V4L2_FIELD_ANY] = "any",
+ [V4L2_FIELD_NONE] = "none",
+ [V4L2_FIELD_TOP] = "top",
+ [V4L2_FIELD_BOTTOM] = "bottom",
+ [V4L2_FIELD_INTERLACED] = "interlaced",
+ [V4L2_FIELD_SEQ_TB] = "seq-tb",
+ [V4L2_FIELD_SEQ_BT] = "seq-bt",
+ [V4L2_FIELD_ALTERNATE] = "alternate",
+};
+
+char *v4l2_type_names[] = {
+ [V4L2_BUF_TYPE_VIDEO_CAPTURE] = "video-cap",
+ [V4L2_BUF_TYPE_VIDEO_OVERLAY] = "video-over",
+ [V4L2_BUF_TYPE_VIDEO_OUTPUT] = "video-out",
+ [V4L2_BUF_TYPE_VBI_CAPTURE] = "vbi-cap",
+ [V4L2_BUF_TYPE_VBI_OUTPUT] = "vbi-out",
+ [V4L2_BUF_TYPE_SLICED_VBI_CAPTURE] = "sliced-vbi-cap",
+ [V4L2_BUF_TYPE_SLICED_VBI_OUTPUT] = "slicec-vbi-out",
+};
+
+static char *v4l2_memory_names[] = {
+ [V4L2_MEMORY_MMAP] = "mmap",
+ [V4L2_MEMORY_USERPTR] = "userptr",
+ [V4L2_MEMORY_OVERLAY] = "overlay",
+};
+
+#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(*arr))
+#define prt_names(a,arr) (((a)<ARRAY_SIZE(arr))?arr[a]:"unknown")
+
+char *prt_caps(uint32_t caps)
+{
+ static char s[4096]="";
+
+ if (V4L2_CAP_VIDEO_CAPTURE & caps)
+ strcat (s,"CAPTURE ");
+ if (V4L2_CAP_VIDEO_OUTPUT & caps)
+ strcat (s,"OUTPUT ");
+ if (V4L2_CAP_VIDEO_OVERLAY & caps)
+ strcat (s,"OVERLAY ");
+ if (V4L2_CAP_VBI_CAPTURE & caps)
+ strcat (s,"VBI_CAPTURE ");
+ if (V4L2_CAP_VBI_OUTPUT & caps)
+ strcat (s,"VBI_OUTPUT ");
+ if (V4L2_CAP_SLICED_VBI_CAPTURE & caps)
+ strcat (s,"SLICED_VBI_CAPTURE ");
+ if (V4L2_CAP_SLICED_VBI_OUTPUT & caps)
+ strcat (s,"SLICED_VBI_OUTPUT ");
+ if (V4L2_CAP_RDS_CAPTURE & caps)
+ strcat (s,"RDS_CAPTURE ");
+ if (V4L2_CAP_TUNER & caps)
+ strcat (s,"TUNER ");
+ if (V4L2_CAP_AUDIO & caps)
+ strcat (s,"AUDIO ");
+ if (V4L2_CAP_RADIO & caps)
+ strcat (s,"RADIO ");
+ if (V4L2_CAP_READWRITE & caps)
+ strcat (s,"READWRITE ");
+ if (V4L2_CAP_ASYNCIO & caps)
+ strcat (s,"ASYNCIO ");
+ if (V4L2_CAP_STREAMING & caps)
+ strcat (s,"STREAMING ");
+
+ return s;
+}
+/****************************************************************************
+ Open/Close V4L2 devices
+ ****************************************************************************/
+int v4l2_open (char *device, int debug, struct v4l2_driver *drv)
+{
+ int ret;
+
+ memset(drv,0,sizeof(*drv));
+
+ drv->debug=debug;
+
+ if ((drv->fd = open(device, O_RDONLY)) < 0) {
+ perror("Couldn't open video0");
+ return(errno);
+ }
+
+ ret=ioctl(drv->fd,VIDIOC_QUERYCAP,(void *) &drv->cap);
+ if (ret>=0 && drv->debug) {
+ printf ("driver=%s, card=%s, bus=%s, version=%d.%d.%d, "
+ "capabilities=%s\n",
+ drv->cap.driver,drv->cap.card,drv->cap.bus_info,
+ (drv->cap.version >> 16) & 0xff,
+ (drv->cap.version >> 8) & 0xff,
+ drv->cap.version & 0xff,
+ prt_caps(drv->cap.capabilities));
+
+
+ }
+ return ret;
+}
+
+int v4l2_close (struct v4l2_driver *drv)
+{
+ free_list(&drv->stds);
+ free_list(&drv->inputs);
+ free_list(&drv->fmt_caps);
+
+ return (close(drv->fd));
+}
+
+/****************************************************************************
+ V4L2 Eumberations
+ ****************************************************************************/
+int v4l2_enum_stds (struct v4l2_driver *drv)
+{
+ struct v4l2_standard *p=NULL;
+ struct drv_list *list;
+ int ok=0,ret,i;
+ v4l2_std_id id;
+
+ free_list(&drv->stds);
+
+ list=drv->stds=calloc(1,sizeof(drv->stds));
+ assert (list!=NULL);
+
+ for (i=0; ok==0; i++) {
+ p=calloc(1,sizeof(*p));
+ assert (p);
+
+ p->index=i;
+ ok=ioctl(drv->fd,VIDIOC_ENUMSTD,p);
+ if (ok<0) {
+ ok=errno;
+ free(p);
+ break;
+ }
+ if (drv->debug) {
+ printf ("STANDARD: index=%d, id=0x%08x, name=%s, fps=%.3f, "
+ "framelines=%d\n", p->index,
+ (unsigned int)p->id, p->name,
+ 1.*p->frameperiod.denominator/p->frameperiod.numerator,
+ p->framelines);
+ }
+ if (list->curr) {
+ list->next=calloc(1,sizeof(*list->next));
+ list=list->next;
+ assert (list!=NULL);
+ }
+ list->curr=p;
+ }
+ if (i>0 && ok==-EINVAL)
+ return 0;
+
+ return ok;
+}
+
+int v4l2_enum_input (struct v4l2_driver *drv)
+{
+ struct v4l2_input *p=NULL;
+ struct drv_list *list;
+ int ok=0,ret,i;
+ v4l2_std_id id;
+
+ free_list(&drv->inputs);
+
+ list=drv->inputs=calloc(1,sizeof(drv->inputs));
+ assert (list!=NULL);
+
+ for (i=0; ok==0; i++) {
+ p=calloc(1,sizeof(*p));
+ assert (p);
+ p->index=i;
+ ok=ioctl(drv->fd,VIDIOC_ENUMINPUT,p);
+ if (ok<0) {
+ ok=errno;
+ free(p);
+ break;
+ }
+ if (drv->debug) {
+ printf ("INPUT: index=%d, name=%s, type=%d, audioset=%d, "
+ "tuner=%d, std=%08x, status=%d\n",
+ p->index,p->name,p->type,p->audioset, p->tuner,
+ (unsigned int)p->std, p->status);
+ }
+ if (list->curr) {
+ list->next=calloc(1,sizeof(*list->next));
+ list=list->next;
+ assert (list!=NULL);
+ }
+ list->curr=p;
+ }
+ if (i>0 && ok==-EINVAL)
+ return 0;
+ return ok;
+}
+
+int v4l2_enum_fmt (struct v4l2_driver *drv, enum v4l2_buf_type type)
+{
+ struct v4l2_fmtdesc *p=NULL;
+ struct v4l2_format fmt;
+ struct drv_list *list;
+ int ok=0,ret,i;
+ v4l2_std_id id;
+
+ free_list(&drv->fmt_caps);
+
+ list=drv->fmt_caps=calloc(1,sizeof(drv->fmt_caps));
+ assert (list!=NULL);
+
+ for (i=0; ok==0; i++) {
+ p=calloc(1,sizeof(*p));
+ assert (p!=NULL);
+
+ p->index=i;
+ p->type =type;
+
+ ok=ioctl(drv->fd,VIDIOC_ENUM_FMT,p);
+ if (ok<0) {
+ ok=errno;
+ free(p);
+ break;
+ }
+ if (drv->debug) {
+ printf ("FORMAT: index=%d, type=%d, flags=%d, description=%s\n\t"
+ "pixelformat=0x%08x\n",
+ p->index, p->type, p->flags,p->description,
+ p->pixelformat);
+ }
+ if (list->curr) {
+ list->next=calloc(1,sizeof(*list->next));
+ list=list->next;
+ assert (list!=NULL);
+ }
+ list->curr=p;
+ }
+ if (i>0 && ok==-EINVAL)
+ return 0;
+ return ok;
+}
+
+/****************************************************************************
+ Set routines - currently, it also checks results with Get
+ ****************************************************************************/
+int v4l2_setget_std (struct v4l2_driver *drv, enum v4l2_direction dir, v4l2_std_id *id)
+{
+ v4l2_std_id s_id=*id;
+ int ret=0;
+ char s[256];
+
+ if (dir & V4L2_SET) {
+ ret=ioctl(drv->fd,VIDIOC_S_STD,&s_id);
+ if (ret<0) {
+ ret=errno;
+
+ sprintf (s,"while trying to set STD to %08x",
+ (unsigned int) *id);
+ perror(s);
+ }
+ }
+
+ if (dir & V4L2_GET) {
+ ret=ioctl(drv->fd,VIDIOC_G_STD,&s_id);
+ if (ret<0) {
+ ret=errno;
+ perror ("while trying to get STD id");
+ }
+ }
+
+ if (dir == V4L2_SET_GET) {
+ if (*id & s_id) {
+ if (*id != s_id) {
+ printf ("Warning: Received a std subset (%08x"
+ " std) while trying to adjust to %08x\n",
+ (unsigned int) s_id,(unsigned int) *id);
+ }
+ } else {
+ fprintf (stderr,"Error: Received %08x std while trying"
+ " to adjust to %08x\n",
+ (unsigned int) s_id,(unsigned int) *id);
+ }
+ }
+ return ret;
+}
+
+int v4l2_setget_input (struct v4l2_driver *drv, enum v4l2_direction dir, struct v4l2_input *input)
+{
+ int ok=0,ret,i;
+ unsigned int inp=input->index;
+ char s[256];
+
+ if (dir & V4L2_SET) {
+ ret=ioctl(drv->fd,VIDIOC_S_INPUT,input);
+ if (ret<0) {
+ ret=errno;
+ sprintf (s,"while trying to set INPUT to %d\n", inp);
+ perror(s);
+ }
+ }
+
+ if (dir & V4L2_GET) {
+ ret=ioctl(drv->fd,VIDIOC_G_INPUT,input);
+ if (ret<0) {
+ perror ("while trying to get INPUT id\n");
+ }
+ }
+
+ if (dir & V4L2_SET_GET) {
+ if (input->index != inp) {
+ printf ("Input is different than expected (received %i, set %i)\n",
+ inp, input->index);
+ }
+ }
+
+ return ok;
+}
+
+int v4l2_gettryset_fmt_cap (struct v4l2_driver *drv, enum v4l2_direction dir,
+ struct v4l2_format *fmt,uint32_t width, uint32_t height,
+ uint32_t pixelformat, enum v4l2_field field)
+{
+ struct v4l2_pix_format *pix=&(fmt->fmt.pix);
+ int ret=0;
+
+ fmt->type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ if (dir == V4L2_GET) {
+ ret=ioctl(drv->fd,VIDIOC_G_FMT,fmt);
+ if (ret < 0) {
+ ret=errno;
+ perror("VIDIOC_G_FMT failed\n");
+ }
+ return ret;
+ } else if (dir & (~(V4L2_TRY|V4L2_SET)) ) {
+ perror ("Invalid direction\n");
+ return EINVAL;
+ }
+
+ if (dir & (V4L2_TRY|V4L2_SET)) {
+ pix->width = width;
+ pix->height = height;
+ pix->pixelformat = pixelformat;
+ pix->field = field;
+ /*
+ enum v4l2_colorspace colorspace;
+ */
+
+ if (dir & V4L2_TRY) {
+ ret=ioctl(drv->fd,VIDIOC_TRY_FMT,fmt);
+ if (ret < 0) {
+ perror("VIDIOC_TRY_FMT failed\n");
+ }
+ }
+
+ if (dir & V4L2_SET) {
+ ret=ioctl(drv->fd,VIDIOC_S_FMT,fmt);
+ if (ret < 0) {
+ perror("VIDIOC_S_FMT failed\n");
+ }
+ drv->sizeimage=pix->sizeimage;
+ }
+
+ if (pix->pixelformat != pixelformat) {
+ fprintf(stderr,"Error: asked for format %d, received %d",pixelformat,
+ pix->pixelformat);
+ }
+
+ if (pix->width != width) {
+ fprintf(stderr,"Error: asked for format %d, received %d\n",width,
+ pix->width);
+ }
+
+ if (pix->height != height) {
+ fprintf(stderr,"Error: asked for format %d, received %d\n",height,
+ pix->height);
+ }
+
+ if (pix->bytesperline == 0 ) {
+ fprintf(stderr,"Error: bytesperline = 0\n");
+ }
+
+ if (pix->sizeimage == 0 ) {
+ fprintf(stderr,"Error: sizeimage = 0\n");
+ }
+ }
+
+ if (drv->debug)
+ printf( "FMT SET: %dx%d, fourcc=%c%c%c%c, %d bytes/line,"
+ " %d bytes/frame, colorspace=0x%08x\n",
+ pix->width,pix->height,
+ pix->pixelformat & 0xff,
+ (pix->pixelformat >> 8) & 0xff,
+ (pix->pixelformat >> 16) & 0xff,
+ (pix->pixelformat >> 24) & 0xff,
+ pix->bytesperline,
+ pix->sizeimage,
+ pix->colorspace);
+
+ return 0;
+}
+
+/****************************************************************************
+ Get routines
+ ****************************************************************************/
+int v4l2_get_parm (struct v4l2_driver *drv)
+{
+ int ret;
+ struct v4l2_captureparm *c;
+
+ drv->parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ if ((ret=ioctl(drv->fd,VIDIOC_G_PARM,&drv->parm))>=0) {
+ c=&drv->parm.parm.capture;
+ printf ("PARM: capability=%d, capturemode=%d, frame time =%.3f ns "
+ "ext=%x, readbuf=%d\n",
+ c->capability,
+ c->capturemode,
+ 100.*c->timeperframe.numerator/c->timeperframe.denominator,
+ c->extendedmode, c->readbuffers);
+ } else {
+ ret=errno;
+
+ perror ("VIDIOC_G_PARM");
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ Queue Control
+ ****************************************************************************/
+
+int v4l2_mmap_bufs(struct v4l2_driver *drv, unsigned int num_buffers)
+{
+ uint32_t i;
+
+ if (drv->sizeimage==0) {
+ fprintf(stderr,"Image size is zero! Can't proceed\n");
+ return -1;
+ }
+ /* Requests the specified number of buffers */
+ drv->reqbuf.count = num_buffers;
+ drv->reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ drv->reqbuf.memory = V4L2_MEMORY_MMAP;
+
+ if (ioctl(drv->fd,VIDIOC_REQBUFS,&drv->reqbuf)<0) {
+ perror("reqbufs");
+ return errno;
+ }
+
+ if (drv->debug)
+ printf ("REQBUFS: count=%d, type=%s, memory=%s\n",
+ drv->reqbuf.count,
+ prt_names(drv->reqbuf.type,v4l2_type_names),
+ prt_names(drv->reqbuf.memory,v4l2_memory_names));
+
+ /* Frees previous allocations, if required */
+ if (drv->v4l2_bufs)
+ free(drv->v4l2_bufs);
+ if (drv->bufs)
+ free(drv->bufs);
+
+ /* Allocates the required number of buffers */
+ drv->v4l2_bufs=calloc(drv->reqbuf.count, sizeof(drv->v4l2_bufs));
+ assert(drv->v4l2_bufs!=NULL);
+ drv->bufs=calloc(drv->reqbuf.count, drv->sizeimage);
+ assert(drv->bufs);
+
+ for (i = 0; i < drv->reqbuf.count; i++) {
+ struct v4l2_buffer *p=drv->v4l2_bufs[i];
+ struct v4l2_timecode *tc;
+
+ /* Requests kernel buffers to be mmapped */
+ p=calloc(1,sizeof(*p));
+ assert (p!=NULL);
+ p->index = i;
+ p->type = drv->reqbuf.type;
+ p->memory = V4L2_MEMORY_MMAP;
+ if (ioctl(drv->fd,VIDIOC_QUERYBUF,p)<0) {
+ int ret=errno;
+ perror("querybuf");
+
+ free(drv->v4l2_bufs);
+ free(drv->bufs);
+
+ drv->v4l2_bufs=NULL;
+ drv->bufs=NULL;
+ return ret;
+ }
+
+ if (drv->debug) {
+ printf ("QUERYBUF: %02ld:%02d:%02d.%08ld index=%d, type=%s, "
+ "bytesused=%d, flags=0x%08x, "
+ "field=%s, sequence=%d, memory=%s, offset=0x%08x\n",
+ (p->timestamp.tv_sec/3600),
+ (int)(p->timestamp.tv_sec/60)%60,
+ (int)(p->timestamp.tv_sec%60),
+ p->timestamp.tv_usec,
+ p->index,
+ prt_names(p->type,v4l2_type_names),
+ p->bytesused,p->flags,
+ prt_names(p->field,v4l2_field_names),
+ p->sequence,
+ prt_names(p->memory,v4l2_memory_names),
+ p->m.offset);
+ tc=&p->timecode;
+ printf ("TIMECODE: %02d:%02d:%02d type=%d, "
+ "flags=0x%08x, frames=%d, userbits=0x%08x\n",
+ tc->hours,tc->minutes,tc->seconds,
+ tc->type, tc->flags, tc->frames, *(uint32_t *) tc->userbits);
+ }
+
+printf("offset=0x%08x\n",p->m.offset);
+ drv->bufs[i].length = drv->sizeimage;
+ drv->bufs[i].start = mmap(NULL, drv->bufs[i].length, PROT_READ | PROT_WRITE,
+ MAP_SHARED, drv->fd, p->m.offset);
+ if (MAP_FAILED == drv->bufs) {
+ perror("mmap");
+
+// free(drv->v4l2_bufs);
+// free(drv->bufs);
+
+// drv->v4l2_bufs=NULL;
+// drv->bufs=NULL;
+ return errno;
+ }
+ }
+ return 0;
+}
diff --git a/v4l2-apps/lib/v4l2_driver.h b/v4l2-apps/lib/v4l2_driver.h
new file mode 100644
index 000000000..5e04c1e86
--- /dev/null
+++ b/v4l2-apps/lib/v4l2_driver.h
@@ -0,0 +1,72 @@
+/*
+ Copyright (C) 2006 Mauro Carvalho Chehab <mchehab@infradead.org>
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+ */
+
+#include <stdint.h>
+#include <sys/time.h>
+#include <linux/videodev2.h>
+
+struct drv_list {
+ void *curr;
+ struct drv_list *next;
+};
+
+struct v4l2_t_buf {
+ void *start;
+ size_t length;
+};
+
+struct v4l2_driver {
+ int fd; /* Driver descriptor */
+
+ int debug;
+
+ /* V4L2 structs */
+ struct v4l2_capability cap;
+ struct v4l2_streamparm parm;
+
+ /* Several lists to be used to store enumbered values */
+ struct drv_list *stds,*inputs,*fmt_caps;
+
+ /* Stream control */
+ struct v4l2_requestbuffers reqbuf;
+ struct v4l2_buffer **v4l2_bufs;
+ struct v4l2_t_buf *bufs;
+ uint32_t sizeimage;
+
+ /* Queue control */
+ uint32_t waitq, currq;
+};
+
+enum v4l2_direction {
+ V4L2_GET = 1, // Bit 1
+ V4L2_SET = 2, // Bit 2
+ V4L2_SET_GET = 3, // Bits 1 and 2 - sets then gets and compare
+ V4L2_TRY = 4, // Bit 3
+ V4L2_TRY_SET = 6, // Bits 3 and 2 - try then sets
+ V4L2_TRY_SET_GET = 7, // Bits 3, 2 and 1- try, sets and gets
+};
+
+int v4l2_open (char *device, int debug, struct v4l2_driver *drv);
+int v4l2_close (struct v4l2_driver *drv);
+int v4l2_enum_stds (struct v4l2_driver *drv);
+int v4l2_enum_input (struct v4l2_driver *drv);
+int v4l2_enum_fmt (struct v4l2_driver *drv,enum v4l2_buf_type type);
+int v4l2_get_parm (struct v4l2_driver *drv);
+int v4l2_setget_std (struct v4l2_driver *drv, enum v4l2_direction dir, v4l2_std_id *id);
+int v4l2_setget_input (struct v4l2_driver *drv, enum v4l2_direction dir, struct v4l2_input *input);
+int v4l2_gettryset_fmt_cap (struct v4l2_driver *drv, enum v4l2_direction dir,
+ struct v4l2_format *fmt,uint32_t width, uint32_t height,
+ uint32_t pixelformat, enum v4l2_field field);
+int v4l2_mmap_bufs(struct v4l2_driver *drv, unsigned int num_buffers);
+
diff --git a/v4l2-apps/test/Makefile b/v4l2-apps/test/Makefile
index b6a83b2b3..6c1edf6a5 100644
--- a/v4l2-apps/test/Makefile
+++ b/v4l2-apps/test/Makefile
@@ -6,7 +6,8 @@ binaries = ioctl-test \
sliced-vbi-test \
sliced-vbi-detect \
vbi-test \
- v4lgrab
+ v4lgrab \
+ driver-test
.PHONY: all clean install
@@ -17,4 +18,9 @@ clean::
install:
+../lib/libv4l2.a: ../lib/v4l2_driver.c ../lib/frequencies.c
+ make -C ../lib libv4l2.a
+
+driver-test: driver-test.o ../lib/libv4l2.a
+
include ../Make.rules
diff --git a/v4l2-apps/test/driver-test.c b/v4l2-apps/test/driver-test.c
new file mode 100644
index 000000000..809ee170c
--- /dev/null
+++ b/v4l2-apps/test/driver-test.c
@@ -0,0 +1,80 @@
+/*
+ driver-test.c - This program tests V4L2 kernel drivers
+
+ Copyright (C) 2006 Mauro Carvalho Chehab <mchehab@infradead.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ */
+
+#include "../lib/v4l2_driver.h"
+#include <stdio.h>
+
+int main(void)
+{
+ struct v4l2_driver drv;
+ struct drv_list *cur;
+
+ if (v4l2_open ("/dev/video0", 1,&drv)<0) {
+ perror("open");
+ return -1;
+ }
+ if (v4l2_enum_stds (&drv)<0) {
+ perror("enum_stds");
+ }
+
+ /* Tries all video standards */
+ for (cur=drv.stds;cur!=NULL;cur=cur->next) {
+ v4l2_std_id id=((struct v4l2_standard *)cur->curr)->id;
+ if (cur->curr)
+ if (v4l2_setget_std (&drv, V4L2_SET_GET, &id))
+ perror("set_std");
+ }
+
+ if (v4l2_enum_input (&drv)<0) {
+ perror("enum_input");
+ }
+
+ /* Tries all video inputs */
+ for (cur=drv.inputs;cur!=NULL;cur=cur->next) {
+ struct v4l2_input input;
+ input.index=((struct v4l2_input* )cur->curr)->index;
+ if (cur->curr)
+ if (v4l2_setget_input (&drv, V4L2_SET_GET, &input))
+ perror("set_input");
+ }
+
+ if (v4l2_enum_fmt (&drv,V4L2_BUF_TYPE_VIDEO_CAPTURE)<0) {
+ perror("enum_fmt_cap");
+ }
+
+ /* Tries all formats */
+ for (cur=drv.fmt_caps;cur!=NULL;cur=cur->next) {
+ struct v4l2_format fmt;
+ uint32_t pixelformat=((struct v4l2_fmtdesc *)cur->curr)->pixelformat;
+ if (cur->curr) {
+ if (v4l2_gettryset_fmt_cap (&drv,V4L2_SET,&fmt, 640, 480,
+ pixelformat,V4L2_FIELD_ANY))
+ perror("set_input");
+ }
+ }
+
+ if (v4l2_get_parm (&drv)<0) {
+ perror("get_parm");
+ }
+
+ v4l2_mmap_bufs(&drv, 2);
+
+ if (v4l2_close (&drv)<0) {
+ perror("close");
+ return -1;
+ }
+ return 0;
+}
diff --git a/v4l2-apps/test/ioctl-test.c b/v4l2-apps/test/ioctl-test.c
index 6d78ad0f8..f483338fb 100644
--- a/v4l2-apps/test/ioctl-test.c
+++ b/v4l2-apps/test/ioctl-test.c
@@ -51,8 +51,9 @@ typedef u_int32_t u32;
/* All possible parameters used on v4l ioctls */
union v4l_parms {
int i;
- unsigned long l;
- u32 u_32;
+ unsigned long u64;
+ u32 u32;
+ v4l2_std_id id;
#ifdef CONFIG_VIDEO_V4L1_COMPAT
/* V4L1 structs */
@@ -148,10 +149,12 @@ int ioctls[] = {
VIDIOC_ENUMAUDOUT,/* struct v4l2_audioout */
VIDIOC_ENUM_FMT,/* struct v4l2_fmtdesc */
VIDIOC_ENUMINPUT,/* struct v4l2_input */
+ VIDIOC_G_INPUT,/* int */
+ VIDIOC_S_INPUT,/* int */
VIDIOC_ENUMOUTPUT,/* struct v4l2_output */
VIDIOC_ENUMSTD,/* struct v4l2_standard */
-// VIDIOC_G_AUDIO_OLD,/* struct v4l2_audio */
-// VIDIOC_G_AUDOUT_OLD,/* struct v4l2_audioout */
+ VIDIOC_G_STD, /*v4l2_std_id */
+ VIDIOC_S_STD, /*v4l2_std_id */
VIDIOC_G_CROP,/* struct v4l2_crop */
VIDIOC_G_CTRL,/* struct v4l2_control */
VIDIOC_G_FMT,/* struct v4l2_format */
@@ -159,7 +162,6 @@ int ioctls[] = {
VIDIOC_G_MODULATOR,/* struct v4l2_modulator */
VIDIOC_G_PARM,/* struct v4l2_streamparm */
VIDIOC_G_TUNER,/* struct v4l2_tuner */
-// VIDIOC_OVERLAY_OLD,/* int */
VIDIOC_QBUF,/* struct v4l2_buffer */
VIDIOC_QUERYBUF,/* struct v4l2_buffer */
VIDIOC_QUERYCTRL,/* struct v4l2_queryctrl */
@@ -172,6 +174,12 @@ int ioctls[] = {
VIDIOC_S_PARM,/* struct v4l2_streamparm */
VIDIOC_TRY_FMT,/* struct v4l2_format */
+#if 0
+ VIDIOC_G_AUDIO_OLD,/* struct v4l2_audio */
+ VIDIOC_G_AUDOUT_OLD,/* struct v4l2_audioout */
+ VIDIOC_OVERLAY_OLD,/* int */
+#endif
+
#ifdef INTERNAL
/* V4L2 internal ioctls */
AUDC_SET_RADIO,/* no args */
@@ -201,6 +209,7 @@ int ioctls[] = {
#define S_IOCTLS sizeof(ioctls)/sizeof(ioctls[0])
/********************************************************************/
+
int main (void)
{
int fd=0, ret=0;
diff --git a/v4l2-apps/util/qv4l2/general-tab.cpp b/v4l2-apps/util/qv4l2/general-tab.cpp
index a19cf911b..87a0f520d 100644
--- a/v4l2-apps/util/qv4l2/general-tab.cpp
+++ b/v4l2-apps/util/qv4l2/general-tab.cpp
@@ -295,7 +295,7 @@ void GeneralTab::updateStandard()
tvStandard->setCurrentItem(vs.index);
what.sprintf("TV Standard (0x%llX)\n"
"Frame period: %f (%d/%d)\n"
- "Frame lines: %d\n", std,
+ "Frame lines: %d\n", (long long int)std,
(double)vs.frameperiod.numerator / vs.frameperiod.denominator,
vs.frameperiod.numerator, vs.frameperiod.denominator,
vs.framelines);
diff --git a/v4l2-apps/util/qv4l2/general-tab.h b/v4l2-apps/util/qv4l2/general-tab.h
index 44003fd40..110632014 100644
--- a/v4l2-apps/util/qv4l2/general-tab.h
+++ b/v4l2-apps/util/qv4l2/general-tab.h
@@ -21,6 +21,7 @@
#ifndef GENERAL_TAB_H
#define GENERAL_TAB_H
+#include <sys/time.h>
#include <linux/videodev2.h>
#include <qgrid.h>
diff --git a/v4l2-apps/util/v4l2-ctl.cpp b/v4l2-apps/util/v4l2-ctl.cpp
index a90dd76eb..7dabb3969 100644
--- a/v4l2-apps/util/v4l2-ctl.cpp
+++ b/v4l2-apps/util/v4l2-ctl.cpp
@@ -51,10 +51,8 @@
In general the lower case is used to set something and the upper
case is used to retrieve a setting. */
enum Option {
- OptGetAudioInput = 'A',
- OptSetAudioInput = 'a',
- OptGetAudioOutput = 'B',
- OptSetAudioOutput = 'b',
+ OptGetSlicedVbiFormat = 'B',
+ OptSetSlicedVbiFormat = 'b',
OptGetCtrl = 'C',
OptSetCtrl = 'c',
OptSetDevice = 'd',
@@ -70,8 +68,6 @@ enum Option {
OptListInputs = 'n',
OptGetOutput = 'O',
OptSetOutput = 'o',
- OptListAudioOutputs = 'Q',
- OptListAudioInputs = 'q',
OptGetStandard = 'S',
OptSetStandard = 's',
OptGetTuner = 'T',
@@ -79,9 +75,7 @@ enum Option {
OptGetVideoFormat = 'V',
OptSetVideoFormat = 'v',
- OptGetSlicedVbiFormat = 128,
- OptSetSlicedVbiFormat,
- OptGetSlicedVbiOutFormat,
+ OptGetSlicedVbiOutFormat = 128,
OptSetSlicedVbiOutFormat,
OptGetOverlayFormat,
//OptSetOverlayFormat, TODO
@@ -102,6 +96,12 @@ enum Option {
OptGetSlicedVbiOutCap,
OptGetVideoCrop,
OptSetVideoCrop,
+ OptGetAudioInput,
+ OptSetAudioInput,
+ OptGetAudioOutput,
+ OptSetAudioOutput,
+ OptListAudioOutputs,
+ OptListAudioInputs,
OptLast = 256
};
@@ -199,15 +199,18 @@ static struct option long_options[] = {
static void usage(void)
{
printf("Usage:\n");
+ printf("Common options:\n");
printf(" --all display all information available\n");
- printf(" -A, --get-audio-input\n");
- printf(" query the audio input [VIDIOC_G_AUDIO]\n");
- printf(" -a, --set-audio-input=<num>\n");
- printf(" set the audio input to <num> [VIDIOC_S_AUDIO]\n");
- printf(" -B, --get-audio-output\n");
- printf(" query the audio output [VIDIOC_G_AUDOUT]\n");
- printf(" -b, --set-audio-output=<num>\n");
- printf(" set the audio output to <num> [VIDIOC_S_AUDOUT]\n");
+ printf(" -B, --get-fmt-sliced-vbi\n");
+ printf(" query the sliced VBI capture format [VIDIOC_G_FMT]\n");
+ printf(" -b, --set-fmt-sliced-vbi=<mode>\n");
+ printf(" set the sliced VBI capture format to <mode> [VIDIOC_S_FMT]\n");
+ printf(" <mode> is a comma separated list of:\n");
+ printf(" off: turn off sliced VBI (cannot be combined with other modes)\n");
+ printf(" teletext: teletext (PAL/SECAM)\n");
+ printf(" cc: closed caption (NTSC)\n");
+ printf(" wss: widescreen signal (PAL/SECAM)\n");
+ printf(" vps: VPS (PAL/SECAM)\n");
printf(" -C, --get-ctrl=<ctrl>[,<ctrl>...]\n");
printf(" get the value of the controls [VIDIOC_G_EXT_CTRLS]\n");
printf(" -c, --set-ctrl=<ctrl>=<val>[,<ctrl>=<val>...]\n");
@@ -252,30 +255,19 @@ static void usage(void)
printf(" query the video capture format [VIDIOC_G_FMT]\n");
printf(" -v, --set-fmt-video=width=<x>,height=<y>\n");
printf(" set the video capture format [VIDIOC_S_FMT]\n");
+ printf(" --verbose turn on verbose ioctl error reporting.\n");
+ printf("\n");
+ printf("Uncommon options:\n");
printf(" --get-fmt-video-out\n");
printf(" query the video output format [VIDIOC_G_FMT]\n");
printf(" --set-fmt-video-out=width=<x>,height=<y>\n");
printf(" set the video output format [VIDIOC_S_FMT]\n");
printf(" --get-fmt-overlay\n");
printf(" query the video overlay format [VIDIOC_G_FMT]\n");
- printf(" --get-crop-video\n");
- printf(" query the video capture crop window [VIDIOC_G_CROP]\n");
- printf(" --set-crop-video=top=<x>,left=<y>,width=<w>,height=<h>\n");
- printf(" set the video capture crop window [VIDIOC_S_CROP]\n");
printf(" --get-sliced-vbi-cap\n");
printf(" query the sliced VBI capture capabilities [VIDIOC_G_SLICED_VBI_CAP]\n");
printf(" --get-sliced-vbi-out-cap\n");
printf(" query the sliced VBI output capabilities [VIDIOC_G_SLICED_VBI_CAP]\n");
- printf(" --get-fmt-sliced-vbi\n");
- printf(" query the sliced VBI capture format [VIDIOC_G_FMT]\n");
- printf(" --set-fmt-sliced-vbi=<mode>\n");
- printf(" set the sliced VBI capture format to <mode> [VIDIOC_S_FMT]\n");
- printf(" <mode> is a comma separated list of:\n");
- printf(" off: turn off sliced VBI (cannot be combined with other modes)\n");
- printf(" teletext: teletext (PAL/SECAM)\n");
- printf(" cc: closed caption (NTSC)\n");
- printf(" wss: widescreen signal (PAL/SECAM)\n");
- printf(" vps: VPS (PAL/SECAM)\n");
printf(" --get-fmt-sliced-vbi-out\n");
printf(" query the sliced VBI output format [VIDIOC_G_FMT]\n");
printf(" --set-fmt-sliced-vbi-out=<mode>\n");
@@ -288,7 +280,20 @@ static void usage(void)
printf(" vps: VPS (PAL/SECAM)\n");
printf(" --get-fmt-vbi query the VBI capture format [VIDIOC_G_FMT]\n");
printf(" --get-fmt-vbi-out query the VBI output format [VIDIOC_G_FMT]\n");
- printf(" --verbose turn on verbose ioctl error reporting.\n");
+ printf(" --get-crop-video\n");
+ printf(" query the video capture crop window [VIDIOC_G_CROP]\n");
+ printf(" --set-crop-video=top=<x>,left=<y>,width=<w>,height=<h>\n");
+ printf(" set the video capture crop window [VIDIOC_S_CROP]\n");
+ printf(" --get-audio-input query the audio input [VIDIOC_G_AUDIO]\n");
+ printf(" --set-audio-input=<num>\n");
+ printf(" set the audio input to <num> [VIDIOC_S_AUDIO]\n");
+ printf(" --get-audio-output query the audio output [VIDIOC_G_AUDOUT]\n");
+ printf(" --set-audio-output=<num>\n");
+ printf(" set the audio output to <num> [VIDIOC_S_AUDOUT]\n");
+ printf(" --list-audio-outputs\n");
+ printf(" display audio outputs [VIDIOC_ENUMAUDOUT]\n");
+ printf(" --list-audio-inputs\n");
+ printf(" display audio inputs [VIDIOC_ENUMAUDIO]\n");
printf("\n");
printf("Expert options:\n");
printf(" --streamoff turn the stream off [VIDIOC_STREAMOFF]\n");
@@ -404,7 +409,7 @@ static std::string flags2s(unsigned val, const flag_def *def)
static void print_sliced_vbi_cap(struct v4l2_sliced_vbi_cap &cap)
{
-// printf("\tType : %s\n", buftype2s(vfmt.type).c_str());
+ printf("\tType : %s\n", buftype2s(cap.type).c_str());
printf("\tService Set : %s\n",
flags2s(cap.service_set, service_def).c_str());
for (int i = 0; i < 24; i++) {
diff --git a/v4l2-apps/util/v4l_rec.pl b/v4l2-apps/util/v4l_rec.pl
new file mode 100755
index 000000000..b533af097
--- /dev/null
+++ b/v4l2-apps/util/v4l_rec.pl
@@ -0,0 +1,74 @@
+#!/usr/bin/perl
+use strict;
+
+# This is a very simple script to record a v4l program with ffmpeg or mencode
+# Currenlty, works only with PAL-M or NTSC with ntsc-cable freqs
+#
+# mencode is easier due to usage of ALSA
+
+my $station = shift or die "Usage: $0 <station> [standard] [device]";
+my $dev;
+my $std;
+
+# Parameters with optional values
+
+$std=shift or $std='PAL-M';
+$dev=shift or $dev="/dev/video1";
+
+##############################################
+# Those stuff bellow are currently "hardcoded"
+
+my $acard=0;
+my $rec_ctrl="Aux,0";
+my $file="out.mpg";
+my $vbitrate=1500;
+my $abitrate=224;
+
+##############################################
+# Those stuff bellow are NTSC / PAL-M specific
+
+my $list="/usr/share/xawtv/ntsc-cable.list";
+my $fps=30000/1001;
+my $width=640;
+my $height=480;
+##############################################
+
+my $on=0;
+my $freq;
+
+open IN,$list or die "$list not found";
+
+while (<IN>) {
+ if ($on) {
+ if (m/freq\s*=\s*(\d+)(\d..)/) {
+ $freq="$1.$2";
+ $on=0;
+ }
+ };
+
+ if (m/[\[]($station)[\]]/) {
+ $on=1;
+ }
+}
+
+close IN;
+
+if ( !$freq ) {
+ printf "Can't find station $station\n";
+ exit;
+}
+
+printf "setting to channel $station, standard $std, freq=$freq on device $dev\n";
+system "v4l2-ctl -d $dev -f $freq -s $std";
+
+printf "Programming alsa to capture on $rec_ctrl at hw $acard\n";
+system "amixer -c $acard sset $rec_ctrl 80% unmute cap";
+system "amixer -c $acard sset Capture 15%";
+
+printf "recording with ffmpeg on device $dev\n";
+
+my $encode="/usr/bin/mencoder -tv driver=v4l2:device=$dev:norm=$std:width=$width:height=$height:input=0:alsa:adevice=hw.".$acard.":amode=1:forceaudio:fps=$fps tv:// -o $file -oac mp3lame -lameopts cbr:br=$abitrate -ovc lavc -lavcopts dia=-2:vcodec=mpeg4:vbitrate=$vbitrate -noodml";
+#my $encode="ffmpeg -ad /dev/dsp".$acard." -vd $dev -tvstd $std -s ".$width."x".$height." -vcodec mpeg2video -f mpeg test.mpg";
+
+print "$encode\n";
+exec $encode;