From 7275da27eb5aa09ee9b599ace5e153848edd54a8 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 12 Nov 2006 03:07:30 -0200 Subject: Improved ioctl-test From: Mauro Carvalho Chehab Now, it tests and diagnostics some api troubles. Still lacks several ioctls. Signed-off-by: Mauro Carvalho Chehab --- v4l2-apps/test/ioctl-test.c | 212 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 207 insertions(+), 5 deletions(-) (limited to 'v4l2-apps') diff --git a/v4l2-apps/test/ioctl-test.c b/v4l2-apps/test/ioctl-test.c index 6d78ad0f8..335ccf102 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,193 @@ int ioctls[] = { #define S_IOCTLS sizeof(ioctls)/sizeof(ioctls[0]) /********************************************************************/ + +int get_capabilities (int fd, union v4l_parms *p) +{ + int ret; + + ret=ioctl(fd,VIDIOC_QUERYCAP,(void *) &p); + if (ret>=0) { + struct v4l2_capability *pq= (struct v4l2_capability *)&p; + printf ("driver=%s, card=%s, bus=%s, version=0x%08x, " + "capabilities=0x%08x\n", + pq->driver,pq->card,pq->bus_info, + pq->version, + pq->capabilities); + } + return ret; +} + +#define ERR "*** ERROR " +#define WARN "* Warning " + +int get_set_stds (int fd, union v4l_parms *p) +{ + struct v4l2_standard *pq=(void *)p; + int ok=0,ret,i; + v4l2_std_id id; + + for (i=0; ok==0; i++) { + pq->index=i; + ok=ioctl(fd,VIDIOC_ENUMSTD,pq); + if (ok>=0) { + printf ("STANDARD: index=%d, id=%Ld, name=%s, fps=%.3f, " + "framelines=%d\n", pq->index, + (unsigned long long)pq->id, pq->name, + 1.*pq->frameperiod.denominator/pq->frameperiod.numerator, + pq->framelines); + } else + break; + id=pq->id; + p->id=id; + ret=ioctl(fd,VIDIOC_S_STD,p); + if (ret) { + printf (ERR "%i while trying to set STD to %08x\n",ret, + (unsigned int) id); + } + ret=ioctl(fd,VIDIOC_G_STD,p); + if (ret) { + printf (ERR "%i while trying to get STD id\n",ret); + } + if (id & p->id) { + if (id != p->id) { + printf (WARN "Received a std subset (%08x std) while trying to adjust to %08x\n", + (unsigned int) p->id,(unsigned int) id); + } + } else + printf (ERR "Received %08x std while trying to adjust to %08x\n", + (unsigned int) p->id,(unsigned int) id); + + } + return ok; +} + +int get_set_inputs (int fd, union v4l_parms *arg) +{ + struct v4l2_input *p=(void *)arg; + int ok=0,ret,i; + int input; + + for (i=0; ok==0; i++) { + p->index=i; + ok=ioctl(fd,VIDIOC_ENUMINPUT,p); + if (ok>=0) { + + 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); + + } else + break; + input=p->index; + arg->i=input; + ret=ioctl(fd,VIDIOC_S_INPUT,arg); + if (ret) { + printf (ERR "%i while trying to set INPUT to %d\n",ret, + input); + } + ret=ioctl(fd,VIDIOC_G_INPUT,arg); + if (ret) { + printf (ERR "%i while trying to get INPUT id\n",ret); + } + if (input != arg->i) { + printf ("Input is different than expected (received %i, set %i)\n", + input, p->index); + } + } + return ok; +} + +int get_set_formats (int fd, union v4l_parms *arg) +{ + struct v4l2_fmtdesc *p=(void *)arg; + int ok=0,ret,i; + struct v4l2_format fmt; + struct v4l2_streamparm parm; + struct v4l2_captureparm *c; + + + for (i=0; ok==0; i++) { + p->index=i; + p->type=V4L2_BUF_TYPE_VIDEO_CAPTURE; + + ok=ioctl(fd,VIDIOC_ENUM_FMT,p); + if (ok>=0) { + 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); + } else + break; + + parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (ioctl(fd,VIDIOC_G_PARM,&parm)>=0) { + c=&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 + perror ("VIDIOC_G_PARM"); + +#if 0 + fmt.type=p->type; + fmt.pixelformat=p->pixelformat; + + ret=ioctl(fd,VIDIOC_G_FMT,arg); + if (ret < 0) { + printf("VIDIOC_G_FMT failed\n"); + continue; + } + + switch (f->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + + err = cx8800_try_fmt(dev,fh,f); + if (0 != err) + return err; + + fmt.pixelformat=p->pixelformat; + fmt. + fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); + fh->width = f->fmt.pix.width; + fh->height = f->fmt.pix.height; + fh->vidq.field = f->fmt.pix.field; + return 0; + case V4L2_BUF_TYPE_VBI_CAPTURE: + cx8800_vbi_fmt(dev, f); + return 0; + default: + printf(WARN "format type not implemented\n"); + continue; + } + + + input=p->index; + arg->i=input; + ret=ioctl(fd,VIDIOC_S_INPUT,arg); + if (ret) { + printf (ERR "%i while trying to set INPUT to %d\n",ret, + input); + } + ret=ioctl(fd,VIDIOC_G_INPUT,arg); + if (ret) { + printf (ERR "%i while trying to get INPUT id\n",ret); + } + if (input != arg->i) { + printf ("Input is different than expected (received %i, set %i)\n", + input, p->index); + } +#endif + } + return ok; +} + int main (void) { int fd=0, ret=0; @@ -213,11 +408,18 @@ int main (void) return(-1); } + get_capabilities (fd, &p); + get_set_stds (fd, &p); + get_set_inputs (fd, &p); + get_set_formats (fd, &p); + +#if 0 for (i=0;i Date: Sun, 12 Nov 2006 13:24:27 +0100 Subject: Improve usage message and short options for v4l2-ctl From: Hans Verkuil Several uncommon actions had a short option, while some common actions only had a long option. Reorganized this. Also split the usage message in common and uncommon options. Signed-off-by: Hans Verkuil --- v4l2-apps/util/v4l2-ctl.cpp | 69 ++++++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 32 deletions(-) (limited to 'v4l2-apps') diff --git a/v4l2-apps/util/v4l2-ctl.cpp b/v4l2-apps/util/v4l2-ctl.cpp index a90dd76eb..0e90c064d 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=\n"); - printf(" set the audio input to [VIDIOC_S_AUDIO]\n"); - printf(" -B, --get-audio-output\n"); - printf(" query the audio output [VIDIOC_G_AUDOUT]\n"); - printf(" -b, --set-audio-output=\n"); - printf(" set the audio output to [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=\n"); + printf(" set the sliced VBI capture format to [VIDIOC_S_FMT]\n"); + printf(" 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=[,...]\n"); printf(" get the value of the controls [VIDIOC_G_EXT_CTRLS]\n"); printf(" -c, --set-ctrl==[,=...]\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=,height=\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=,height=\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=,left=,width=,height=\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=\n"); - printf(" set the sliced VBI capture format to [VIDIOC_S_FMT]\n"); - printf(" 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=\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=,left=,width=,height=\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=\n"); + printf(" set the audio input to [VIDIOC_S_AUDIO]\n"); + printf(" --get-audio-output query the audio output [VIDIOC_G_AUDOUT]\n"); + printf(" --set-audio-output=\n"); + printf(" set the audio output to [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"); -- cgit v1.2.3 From b13643285e0e18e972d16cd49ab402b9ee99cd94 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 12 Nov 2006 13:26:12 +0100 Subject: Print buffer type for struct v4l2_sliced_vbi_cap. From: Hans Verkuil This was commented out because the type was missing in v4l2_sliced_vbi_cap. It's now added, so this can now be used. Signed-off-by: Hans Verkuil --- v4l2-apps/util/v4l2-ctl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'v4l2-apps') diff --git a/v4l2-apps/util/v4l2-ctl.cpp b/v4l2-apps/util/v4l2-ctl.cpp index 0e90c064d..7dabb3969 100644 --- a/v4l2-apps/util/v4l2-ctl.cpp +++ b/v4l2-apps/util/v4l2-ctl.cpp @@ -409,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++) { -- cgit v1.2.3 From 59a5e56909050658c0831e97198ac26998008e6e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 14 Nov 2006 08:41:05 -0200 Subject: Added a simple V4L TV record perl script From: Mauro Carvalho Chehab This script can be used to test V4L TV record on STD/M video standards. Should be easy to adapt it to be used with other video standards. Signed-off-by: Mauro Carvalho Chehab --- v4l2-apps/util/v4l_rec.pl | 74 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100755 v4l2-apps/util/v4l_rec.pl (limited to 'v4l2-apps') 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 [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 () { + 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; -- cgit v1.2.3 From e73ea31dcd5884251424ccbf13a0d515f8914c27 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 15 Nov 2006 07:26:27 -0200 Subject: Fix compiation bug on qv4l2 From: Mauro Carvalho Chehab sys/time.h is required to include videodev2.h at userspace. thanks to audetto@tiscalli.it for pointing it. Also fixed a warning at a printf. Signed-off-by: Mauro Carvalho Chehab --- v4l2-apps/util/qv4l2/general-tab.cpp | 2 +- v4l2-apps/util/qv4l2/general-tab.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'v4l2-apps') 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 #include #include -- cgit v1.2.3 From 06700d6b31366059ca963dd4aba34ea2e57aaa05 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 15 Nov 2006 15:42:04 -0200 Subject: Initiated v4l-apps/lib V4L2 functions From: Mauro Carvalho Chehab - Created v4l2_driver.c with some basic functions to: . Enum STD, INPUT and FORMAT . GET/SET STD and INPUT . GET PARAM - ioctl-test reverted back to a simple "brute-force" all ioctl call; - driver-test created to: . test V4L2 kernel drivers; . implement all functions provided by v4l2 library - driver-test should grow following the changes at v4l2-apps/lib Signed-off-by: Mauro Carvalho Chehab --- v4l2-apps/lib/Makefile | 2 +- v4l2-apps/lib/v4l2_driver.c | 307 +++++++++++++++++++++++++++++++++++++++++++ v4l2-apps/lib/v4l2_driver.h | 49 +++++++ v4l2-apps/test/Makefile | 8 +- v4l2-apps/test/driver-test.c | 65 +++++++++ v4l2-apps/test/ioctl-test.c | 193 --------------------------- 6 files changed, 429 insertions(+), 195 deletions(-) create mode 100644 v4l2-apps/lib/v4l2_driver.c create mode 100644 v4l2-apps/lib/v4l2_driver.h create mode 100644 v4l2-apps/test/driver-test.c (limited to 'v4l2-apps') 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..7714d8112 --- /dev/null +++ b/v4l2-apps/lib/v4l2_driver.c @@ -0,0 +1,307 @@ +/* + Copyright (C) 2006 Mauro Carvalho Chehab + + 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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; +} + +/**************************************************************************** + 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=0x%08x, " + "capabilities=0x%08x\n", + drv->cap.driver,drv->cap.card,drv->cap.bus_info, + drv->cap.version,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)); + + for (i=0; ok==0; i++) { + p=calloc(1,sizeof(*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; + } + 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)); + + for (i=0; ok==0; i++) { + p=calloc(1,sizeof(*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; + } + list->curr=p; + } + if (i>0 && ok==-EINVAL) + return 0; + return ok; +} + +int v4l2_enum_fmt_cap (struct v4l2_driver *drv) +{ + 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)); + + for (i=0; ok==0; i++) { + p=calloc(1,sizeof(*p)); + p->index=i; + p->type =V4L2_BUF_TYPE_VIDEO_CAPTURE; + + 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; + } + 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; +} + +/**************************************************************************** + 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; +} diff --git a/v4l2-apps/lib/v4l2_driver.h b/v4l2-apps/lib/v4l2_driver.h new file mode 100644 index 000000000..a6f46dea3 --- /dev/null +++ b/v4l2-apps/lib/v4l2_driver.h @@ -0,0 +1,49 @@ +/* + Copyright (C) 2006 Mauro Carvalho Chehab + + 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 +#include + +struct drv_list { + void *curr; + struct drv_list *next; +}; + +struct v4l2_driver { + int fd; /* Driver descriptor */ + + int debug; + + struct v4l2_capability cap; + + struct v4l2_streamparm parm; + + struct drv_list *stds,*inputs,*fmt_caps; +}; + +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 +}; + +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_cap (struct v4l2_driver *drv); +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); 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..cf3511fc4 --- /dev/null +++ b/v4l2-apps/test/driver-test.c @@ -0,0 +1,65 @@ +/* + driver-test.c - This program tests V4L2 kernel drivers + + Copyright (C) 2006 Mauro Carvalho Chehab + + 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 + +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_cap (&drv)<0) { + perror("enum_fmt_cap"); + } + if (v4l2_get_parm (&drv)<0) { + perror("get_parm"); + } + 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 335ccf102..f483338fb 100644 --- a/v4l2-apps/test/ioctl-test.c +++ b/v4l2-apps/test/ioctl-test.c @@ -210,192 +210,6 @@ int ioctls[] = { /********************************************************************/ -int get_capabilities (int fd, union v4l_parms *p) -{ - int ret; - - ret=ioctl(fd,VIDIOC_QUERYCAP,(void *) &p); - if (ret>=0) { - struct v4l2_capability *pq= (struct v4l2_capability *)&p; - printf ("driver=%s, card=%s, bus=%s, version=0x%08x, " - "capabilities=0x%08x\n", - pq->driver,pq->card,pq->bus_info, - pq->version, - pq->capabilities); - } - return ret; -} - -#define ERR "*** ERROR " -#define WARN "* Warning " - -int get_set_stds (int fd, union v4l_parms *p) -{ - struct v4l2_standard *pq=(void *)p; - int ok=0,ret,i; - v4l2_std_id id; - - for (i=0; ok==0; i++) { - pq->index=i; - ok=ioctl(fd,VIDIOC_ENUMSTD,pq); - if (ok>=0) { - printf ("STANDARD: index=%d, id=%Ld, name=%s, fps=%.3f, " - "framelines=%d\n", pq->index, - (unsigned long long)pq->id, pq->name, - 1.*pq->frameperiod.denominator/pq->frameperiod.numerator, - pq->framelines); - } else - break; - id=pq->id; - p->id=id; - ret=ioctl(fd,VIDIOC_S_STD,p); - if (ret) { - printf (ERR "%i while trying to set STD to %08x\n",ret, - (unsigned int) id); - } - ret=ioctl(fd,VIDIOC_G_STD,p); - if (ret) { - printf (ERR "%i while trying to get STD id\n",ret); - } - if (id & p->id) { - if (id != p->id) { - printf (WARN "Received a std subset (%08x std) while trying to adjust to %08x\n", - (unsigned int) p->id,(unsigned int) id); - } - } else - printf (ERR "Received %08x std while trying to adjust to %08x\n", - (unsigned int) p->id,(unsigned int) id); - - } - return ok; -} - -int get_set_inputs (int fd, union v4l_parms *arg) -{ - struct v4l2_input *p=(void *)arg; - int ok=0,ret,i; - int input; - - for (i=0; ok==0; i++) { - p->index=i; - ok=ioctl(fd,VIDIOC_ENUMINPUT,p); - if (ok>=0) { - - 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); - - } else - break; - input=p->index; - arg->i=input; - ret=ioctl(fd,VIDIOC_S_INPUT,arg); - if (ret) { - printf (ERR "%i while trying to set INPUT to %d\n",ret, - input); - } - ret=ioctl(fd,VIDIOC_G_INPUT,arg); - if (ret) { - printf (ERR "%i while trying to get INPUT id\n",ret); - } - if (input != arg->i) { - printf ("Input is different than expected (received %i, set %i)\n", - input, p->index); - } - } - return ok; -} - -int get_set_formats (int fd, union v4l_parms *arg) -{ - struct v4l2_fmtdesc *p=(void *)arg; - int ok=0,ret,i; - struct v4l2_format fmt; - struct v4l2_streamparm parm; - struct v4l2_captureparm *c; - - - for (i=0; ok==0; i++) { - p->index=i; - p->type=V4L2_BUF_TYPE_VIDEO_CAPTURE; - - ok=ioctl(fd,VIDIOC_ENUM_FMT,p); - if (ok>=0) { - 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); - } else - break; - - parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (ioctl(fd,VIDIOC_G_PARM,&parm)>=0) { - c=&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 - perror ("VIDIOC_G_PARM"); - -#if 0 - fmt.type=p->type; - fmt.pixelformat=p->pixelformat; - - ret=ioctl(fd,VIDIOC_G_FMT,arg); - if (ret < 0) { - printf("VIDIOC_G_FMT failed\n"); - continue; - } - - switch (f->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - - err = cx8800_try_fmt(dev,fh,f); - if (0 != err) - return err; - - fmt.pixelformat=p->pixelformat; - fmt. - fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); - fh->width = f->fmt.pix.width; - fh->height = f->fmt.pix.height; - fh->vidq.field = f->fmt.pix.field; - return 0; - case V4L2_BUF_TYPE_VBI_CAPTURE: - cx8800_vbi_fmt(dev, f); - return 0; - default: - printf(WARN "format type not implemented\n"); - continue; - } - - - input=p->index; - arg->i=input; - ret=ioctl(fd,VIDIOC_S_INPUT,arg); - if (ret) { - printf (ERR "%i while trying to set INPUT to %d\n",ret, - input); - } - ret=ioctl(fd,VIDIOC_G_INPUT,arg); - if (ret) { - printf (ERR "%i while trying to get INPUT id\n",ret); - } - if (input != arg->i) { - printf ("Input is different than expected (received %i, set %i)\n", - input, p->index); - } -#endif - } - return ok; -} - int main (void) { int fd=0, ret=0; @@ -408,18 +222,11 @@ int main (void) return(-1); } - get_capabilities (fd, &p); - get_set_stds (fd, &p); - get_set_inputs (fd, &p); - get_set_formats (fd, &p); - -#if 0 for (i=0;i Date: Wed, 15 Nov 2006 17:49:14 -0200 Subject: Improved v4l2_driver From: Mauro Carvalho Chehab - Better presentation of version - Make v4l2_enum_fmt generic for all types - Added v4l2_gettryset_fmt_cap to GET/TRY/SET fmt on capture - driver-test now sets a video format Signed-off-by: Mauro Carvalho Chehab --- v4l2-apps/lib/v4l2_driver.c | 93 ++++++++++++++++++++++++++++++++++++++++++-- v4l2-apps/lib/v4l2_driver.h | 17 +++++--- v4l2-apps/test/driver-test.c | 14 ++++++- 3 files changed, 114 insertions(+), 10 deletions(-) (limited to 'v4l2-apps') diff --git a/v4l2-apps/lib/v4l2_driver.c b/v4l2-apps/lib/v4l2_driver.c index 7714d8112..1b0a61109 100644 --- a/v4l2-apps/lib/v4l2_driver.c +++ b/v4l2-apps/lib/v4l2_driver.c @@ -68,10 +68,13 @@ int v4l2_open (char *device, int debug, struct v4l2_driver *drv) ret=ioctl(drv->fd,VIDIOC_QUERYCAP,(void *) &drv->cap); if (ret>=0 && drv->debug) { - printf ("driver=%s, card=%s, bus=%s, version=0x%08x, " + printf ("driver=%s, card=%s, bus=%s, version=%d.%d.%d, " "capabilities=0x%08x\n", drv->cap.driver,drv->cap.card,drv->cap.bus_info, - drv->cap.version,drv->cap.capabilities); + (drv->cap.version >> 16) & 0xff, + (drv->cap.version >> 8) & 0xff, + drv->cap.version & 0xff, + drv->cap.capabilities); } return ret; } @@ -164,7 +167,7 @@ int v4l2_enum_input (struct v4l2_driver *drv) return ok; } -int v4l2_enum_fmt_cap (struct v4l2_driver *drv) +int v4l2_enum_fmt (struct v4l2_driver *drv, enum v4l2_buf_type type) { struct v4l2_fmtdesc *p=NULL; struct v4l2_format fmt; @@ -179,7 +182,7 @@ int v4l2_enum_fmt_cap (struct v4l2_driver *drv) for (i=0; ok==0; i++) { p=calloc(1,sizeof(*p)); p->index=i; - p->type =V4L2_BUF_TYPE_VIDEO_CAPTURE; + p->type =type; ok=ioctl(drv->fd,VIDIOC_ENUM_FMT,p); if (ok<0) { @@ -280,6 +283,88 @@ int v4l2_setget_input (struct v4l2_driver *drv, enum v4l2_direction dir, struct 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"); + } + } + + 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 ****************************************************************************/ diff --git a/v4l2-apps/lib/v4l2_driver.h b/v4l2-apps/lib/v4l2_driver.h index a6f46dea3..aac00834f 100644 --- a/v4l2-apps/lib/v4l2_driver.h +++ b/v4l2-apps/lib/v4l2_driver.h @@ -10,9 +10,9 @@ 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 #include #include @@ -34,16 +34,23 @@ struct v4l2_driver { }; 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_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_cap (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); + diff --git a/v4l2-apps/test/driver-test.c b/v4l2-apps/test/driver-test.c index cf3511fc4..53ce6b9d7 100644 --- a/v4l2-apps/test/driver-test.c +++ b/v4l2-apps/test/driver-test.c @@ -51,9 +51,21 @@ int main(void) perror("set_input"); } - if (v4l2_enum_fmt_cap (&drv)<0) { + 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"); } -- cgit v1.2.3 From f90bff01fa3468160e9403fb488c1f319c30c6dd Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 16 Nov 2006 12:02:28 -0200 Subject: Start adding v4l2_mmap_bufs to prepare for stream From: Mauro Carvalho Chehab This method requests buffers and maps it into a mmaped memory. Still under testing. Still need other stuff to make stream to work. Signed-off-by: Mauro Carvalho Chehab --- v4l2-apps/lib/v4l2_driver.c | 176 ++++++++++++++++++++++++++++++++++++++++++- v4l2-apps/lib/v4l2_driver.h | 21 ++++-- v4l2-apps/test/driver-test.c | 3 + 3 files changed, 192 insertions(+), 8 deletions(-) (limited to 'v4l2-apps') diff --git a/v4l2-apps/lib/v4l2_driver.c b/v4l2-apps/lib/v4l2_driver.c index 1b0a61109..e79ffb0b5 100644 --- a/v4l2-apps/lib/v4l2_driver.c +++ b/v4l2-apps/lib/v4l2_driver.c @@ -10,9 +10,10 @@ 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. - */ +/* FIXME: Add checks at calloc for out-of-memory errors */ + #include #include #include @@ -20,6 +21,7 @@ #include #include #include +#include #include #include @@ -50,6 +52,74 @@ static void free_list(struct drv_list **list_ptr) *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)fd,VIDIOC_QUERYCAP,(void *) &drv->cap); if (ret>=0 && drv->debug) { printf ("driver=%s, card=%s, bus=%s, version=%d.%d.%d, " - "capabilities=0x%08x\n", + "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, - drv->cap.capabilities); + prt_caps(drv->cap.capabilities)); + + } return ret; } @@ -324,6 +396,7 @@ int v4l2_gettryset_fmt_cap (struct v4l2_driver *drv, enum v4l2_direction dir, if (ret < 0) { perror("VIDIOC_S_FMT failed\n"); } + drv->sizeimage=pix->sizeimage; } if (pix->pixelformat != pixelformat) { @@ -390,3 +463,100 @@ int v4l2_get_parm (struct v4l2_driver *drv) 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)); + drv->bufs=calloc(drv->reqbuf.count, drv->sizeimage); + + 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)); + p->index = i; + p->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + 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/userptr=0x%08lx\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.userptr); + 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); + } + + drv->bufs = mmap(NULL, drv->sizeimage, 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 index aac00834f..f429f01cd 100644 --- a/v4l2-apps/lib/v4l2_driver.h +++ b/v4l2-apps/lib/v4l2_driver.h @@ -22,15 +22,25 @@ struct drv_list { }; struct v4l2_driver { - int fd; /* Driver descriptor */ + int fd; /* Driver descriptor */ - int debug; + int debug; - struct v4l2_capability cap; + /* V4L2 structs */ + struct v4l2_capability cap; + struct v4l2_streamparm parm; - struct v4l2_streamparm parm; + /* Several lists to be used to store enumbered values */ + struct drv_list *stds,*inputs,*fmt_caps; - struct drv_list *stds,*inputs,*fmt_caps; + /* Stream control */ + struct v4l2_requestbuffers reqbuf; + struct v4l2_buffer **v4l2_bufs; + uint8_t **bufs; + uint32_t sizeimage; + + /* Queue control */ + uint32_t waitq, currq; }; enum v4l2_direction { @@ -53,4 +63,5 @@ int v4l2_setget_input (struct v4l2_driver *drv, enum v4l2_direction dir, struct 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/driver-test.c b/v4l2-apps/test/driver-test.c index 53ce6b9d7..809ee170c 100644 --- a/v4l2-apps/test/driver-test.c +++ b/v4l2-apps/test/driver-test.c @@ -69,6 +69,9 @@ int main(void) if (v4l2_get_parm (&drv)<0) { perror("get_parm"); } + + v4l2_mmap_bufs(&drv, 2); + if (v4l2_close (&drv)<0) { perror("close"); return -1; -- cgit v1.2.3 From 489aa7d623c6e9ed7e78453d7c2d611f600cc944 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 16 Nov 2006 13:19:18 -0200 Subject: Fix v4l2_mmap_bufs and add checks for memory allocation From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- v4l2-apps/lib/v4l2_driver.c | 31 +++++++++++++++++++++++-------- v4l2-apps/lib/v4l2_driver.h | 7 ++++++- 2 files changed, 29 insertions(+), 9 deletions(-) (limited to 'v4l2-apps') diff --git a/v4l2-apps/lib/v4l2_driver.c b/v4l2-apps/lib/v4l2_driver.c index e79ffb0b5..e656a550d 100644 --- a/v4l2-apps/lib/v4l2_driver.c +++ b/v4l2-apps/lib/v4l2_driver.c @@ -12,8 +12,7 @@ Lesser General Public License for more details. */ -/* FIXME: Add checks at calloc for out-of-memory errors */ - +#include #include #include #include @@ -173,9 +172,12 @@ int v4l2_enum_stds (struct v4l2_driver *drv) 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) { @@ -193,6 +195,7 @@ int v4l2_enum_stds (struct v4l2_driver *drv) if (list->curr) { list->next=calloc(1,sizeof(*list->next)); list=list->next; + assert (list!=NULL); } list->curr=p; } @@ -212,9 +215,11 @@ int v4l2_enum_input (struct v4l2_driver *drv) 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) { @@ -231,6 +236,7 @@ int v4l2_enum_input (struct v4l2_driver *drv) if (list->curr) { list->next=calloc(1,sizeof(*list->next)); list=list->next; + assert (list!=NULL); } list->curr=p; } @@ -250,9 +256,12 @@ int v4l2_enum_fmt (struct v4l2_driver *drv, enum v4l2_buf_type type) 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; @@ -271,6 +280,7 @@ int v4l2_enum_fmt (struct v4l2_driver *drv, enum v4l2_buf_type type) if (list->curr) { list->next=calloc(1,sizeof(*list->next)); list=list->next; + assert (list!=NULL); } list->curr=p; } @@ -294,7 +304,7 @@ int v4l2_setget_std (struct v4l2_driver *drv, enum v4l2_direction dir, v4l2_std_ ret=errno; sprintf (s,"while trying to set STD to %08x", - (unsigned int) id); + (unsigned int) *id); perror(s); } } @@ -500,7 +510,9 @@ int v4l2_mmap_bufs(struct v4l2_driver *drv, unsigned int num_buffers) /* 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]; @@ -508,8 +520,9 @@ int v4l2_mmap_bufs(struct v4l2_driver *drv, unsigned int num_buffers) /* Requests kernel buffers to be mmapped */ p=calloc(1,sizeof(*p)); + assert (p!=NULL); p->index = i; - p->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + p->type = drv->reqbuf.type; p->memory = V4L2_MEMORY_MMAP; if (ioctl(drv->fd,VIDIOC_QUERYBUF,p)<0) { int ret=errno; @@ -526,7 +539,7 @@ int v4l2_mmap_bufs(struct v4l2_driver *drv, unsigned int num_buffers) 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/userptr=0x%08lx\n", + "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), @@ -537,7 +550,7 @@ int v4l2_mmap_bufs(struct v4l2_driver *drv, unsigned int num_buffers) prt_names(p->field,v4l2_field_names), p->sequence, prt_names(p->memory,v4l2_memory_names), - p->m.userptr); + p->m.offset); tc=&p->timecode; printf ("TIMECODE: %02d:%02d:%02d type=%d, " "flags=0x%08x, frames=%d, userbits=0x%08x\n", @@ -545,8 +558,10 @@ int v4l2_mmap_bufs(struct v4l2_driver *drv, unsigned int num_buffers) tc->type, tc->flags, tc->frames, *(uint32_t *) tc->userbits); } - drv->bufs = mmap(NULL, drv->sizeimage, PROT_READ | PROT_WRITE, - MAP_SHARED, drv->fd, p->m.offset); +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"); diff --git a/v4l2-apps/lib/v4l2_driver.h b/v4l2-apps/lib/v4l2_driver.h index f429f01cd..5e04c1e86 100644 --- a/v4l2-apps/lib/v4l2_driver.h +++ b/v4l2-apps/lib/v4l2_driver.h @@ -21,6 +21,11 @@ struct drv_list { struct drv_list *next; }; +struct v4l2_t_buf { + void *start; + size_t length; +}; + struct v4l2_driver { int fd; /* Driver descriptor */ @@ -36,7 +41,7 @@ struct v4l2_driver { /* Stream control */ struct v4l2_requestbuffers reqbuf; struct v4l2_buffer **v4l2_bufs; - uint8_t **bufs; + struct v4l2_t_buf *bufs; uint32_t sizeimage; /* Queue control */ -- cgit v1.2.3