diff options
Diffstat (limited to 'v4l2-apps/util/v4l2-ctl.cpp')
-rw-r--r-- | v4l2-apps/util/v4l2-ctl.cpp | 627 |
1 files changed, 447 insertions, 180 deletions
diff --git a/v4l2-apps/util/v4l2-ctl.cpp b/v4l2-apps/util/v4l2-ctl.cpp index 57d98fc13..417721c57 100644 --- a/v4l2-apps/util/v4l2-ctl.cpp +++ b/v4l2-apps/util/v4l2-ctl.cpp @@ -34,6 +34,7 @@ #include <errno.h> #include <sys/ioctl.h> #include <sys/time.h> +#include <dirent.h> #include <math.h> #include <sys/klog.h> @@ -43,6 +44,7 @@ #include <vector> #include <map> #include <string> +#include <algorithm> /* Short option list @@ -77,15 +79,25 @@ enum Option { OptSetVideoFormat = 'v', OptGetSlicedVbiOutFormat = 128, - OptSetSlicedVbiOutFormat, OptGetOverlayFormat, - //OptSetOverlayFormat, TODO OptGetOutputOverlayFormat, - OptSetOutputOverlayFormat, OptGetVbiFormat, - //OptSetVbiFormat, TODO OptGetVbiOutFormat, + OptGetVideoOutFormat, + OptSetSlicedVbiOutFormat, + OptSetOutputOverlayFormat, + OptSetOverlayFormat, + //OptSetVbiFormat, TODO //OptSetVbiOutFormat, TODO + OptSetVideoOutFormat, + OptTryVideoOutFormat, + OptTrySlicedVbiOutFormat, + OptTrySlicedVbiFormat, + OptTryVideoFormat, + OptTryOutputOverlayFormat, + OptTryOverlayFormat, + //OptTryVbiFormat, TODO + //OptTryVbiOutFormat, TODO OptAll, OptStreamOff, OptStreamOn, @@ -93,8 +105,7 @@ enum Option { OptListFormats, OptLogStatus, OptVerbose, - OptGetVideoOutFormat, - OptSetVideoOutFormat, + OptSilent, OptGetSlicedVbiCap, OptGetSlicedVbiOutCap, OptGetFBuf, @@ -118,12 +129,14 @@ enum Option { OptGetOverlayCropCap, OptGetOutputOverlayCropCap, OptOverlay, + OptListDevices, OptLast = 256 }; static char options[OptLast]; static int app_result; +static int verbose; static unsigned capabilities; @@ -142,6 +155,9 @@ static ctrl_get_list get_ctrls; typedef std::map<std::string,std::string> ctrl_set_map; static ctrl_set_map set_ctrls; +typedef std::vector<std::string> dev_vec; +typedef std::map<std::string, std::string> dev_map; + typedef struct { unsigned flag; const char *str; @@ -160,6 +176,10 @@ static const flag_def service_def[] = { #define FmtHeight (1L<<1) #define FmtChromaKey (1L<<2) #define FmtGlobalAlpha (1L<<3) +#define FmtPixelFormat (1L<<4) +#define FmtLeft (1L<<5) +#define FmtTop (1L<<6) +#define FmtField (1L<<7) /* crop specified */ #define CropWidth (1L<<0) @@ -174,8 +194,10 @@ static struct option long_options[] = { {"device", required_argument, 0, OptSetDevice}, {"get-fmt-video", no_argument, 0, OptGetVideoFormat}, {"set-fmt-video", required_argument, 0, OptSetVideoFormat}, + {"try-fmt-video", required_argument, 0, OptTryVideoFormat}, {"get-fmt-video-out", no_argument, 0, OptGetVideoOutFormat}, {"set-fmt-video-out", required_argument, 0, OptSetVideoOutFormat}, + {"try-fmt-video-out", required_argument, 0, OptTryVideoOutFormat}, {"help", no_argument, 0, OptHelp}, {"get-output", no_argument, 0, OptGetOutput}, {"set-output", required_argument, 0, OptSetOutput}, @@ -205,12 +227,17 @@ static struct option long_options[] = { {"verbose", no_argument, 0, OptVerbose}, {"log-status", no_argument, 0, OptLogStatus}, {"get-fmt-overlay", no_argument, 0, OptGetOverlayFormat}, + {"set-fmt-overlay", required_argument, 0, OptSetOverlayFormat}, + {"try-fmt-overlay", required_argument, 0, OptTryOverlayFormat}, {"get-fmt-output-overlay", no_argument, 0, OptGetOutputOverlayFormat}, {"set-fmt-output-overlay", required_argument, 0, OptSetOutputOverlayFormat}, + {"try-fmt-output-overlay", required_argument, 0, OptTryOutputOverlayFormat}, {"get-fmt-sliced-vbi", no_argument, 0, OptGetSlicedVbiFormat}, {"set-fmt-sliced-vbi", required_argument, 0, OptSetSlicedVbiFormat}, + {"try-fmt-sliced-vbi", required_argument, 0, OptTrySlicedVbiFormat}, {"get-fmt-sliced-vbi-out", no_argument, 0, OptGetSlicedVbiOutFormat}, {"set-fmt-sliced-vbi-out", required_argument, 0, OptSetSlicedVbiOutFormat}, + {"try-fmt-sliced-vbi-out", required_argument, 0, OptTrySlicedVbiOutFormat}, {"get-fmt-vbi", no_argument, 0, OptGetVbiFormat}, {"get-fmt-vbi-out", no_argument, 0, OptGetVbiOutFormat}, {"get-sliced-vbi-cap", no_argument, 0, OptGetSlicedVbiCap}, @@ -230,132 +257,144 @@ static struct option long_options[] = { {"get-crop-output-overlay", no_argument, 0, OptGetOutputOverlayCrop}, {"set-crop-output-overlay", required_argument, 0, OptSetOutputOverlayCrop}, {"overlay", required_argument, 0, OptOverlay}, + {"list-devices", no_argument, 0, OptListDevices}, {0, 0, 0, 0} }; static void usage(void) { printf("Usage:\n"); - printf("Common options:\n"); - printf(" --all display all information available\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"); - printf(" set the controls to the values specified [VIDIOC_S_EXT_CTRLS]\n"); - printf(" -D, --info show driver info [VIDIOC_QUERYCAP]\n"); - printf(" -d, --device=<dev> use device <dev> instead of /dev/video0\n"); - printf(" if <dev> is a single digit, then /dev/video<dev> is used\n"); - printf(" -F, --get-freq query the frequency [VIDIOC_G_FREQUENCY]\n"); - printf(" -f, --set-freq=<freq>\n"); - printf(" set the frequency to <freq> MHz [VIDIOC_S_FREQUENCY]\n"); - printf(" -h, --help display this help message\n"); - printf(" -I, --get-input query the video input [VIDIOC_G_INPUT]\n"); - printf(" -i, --set-input=<num>\n"); - printf(" set the video input to <num> [VIDIOC_S_INPUT]\n"); - printf(" -l, --list-ctrls display all controls and their values [VIDIOC_QUERYCTRL]\n"); - printf(" -L, --list-ctrls-menus\n"); - printf(" display all controls, their values and the menus [VIDIOC_QUERYMENU]\n"); - printf(" -N, --list-outputs display video outputs [VIDIOC_ENUMOUTPUT]\n"); - printf(" -n, --list-inputs display video inputs [VIDIOC_ENUMINPUT]\n"); - printf(" -O, --get-output query the video output [VIDIOC_G_OUTPUT]\n"); - printf(" -o, --set-output=<num>\n"); - printf(" set the video output to <num> [VIDIOC_S_OUTPUT]\n"); - printf(" -S, --get-standard\n"); - printf(" query the video standard [VIDIOC_G_STD]\n"); - printf(" -s, --set-standard=<num>\n"); - printf(" set the video standard to <num> [VIDIOC_S_STD]\n"); - printf(" <num> can be a numerical v4l2_std value, or it can be one of:\n"); - printf(" pal-X (X = B/G/H/N/Nc/I/D/K/M/60) or just 'pal' (V4L2_STD_PAL)\n"); - printf(" ntsc-X (X = M/J/K) or just 'ntsc' (V4L2_STD_NTSC)\n"); - printf(" secam-X (X = B/G/H/D/K/L/Lc) or just 'secam' (V4L2_STD_SECAM)\n"); - printf(" --list-standards display supported video standards [VIDIOC_ENUMSTD]\n"); - printf(" -T, --get-tuner query the tuner settings [VIDIOC_G_TUNER]\n"); - printf(" -t, --set-tuner=<mode>\n"); - printf(" set the audio mode of the tuner [VIDIOC_S_TUNER]\n"); - printf(" Possible values: mono, stereo, lang2, lang1, bilingual\n"); - printf(" --list-formats display supported video formats [VIDIOC_ENUM_FMT]\n"); - printf(" -V, --get-fmt-video\n"); - printf(" query the video capture format [VIDIOC_G_FMT]\n"); - printf(" -v, --set-fmt-video=width=<w>,height=<h>\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=<w>,height=<h>\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-fmt-output-overlay\n"); - printf(" query the video output overlay format [VIDIOC_G_FMT]\n"); - printf(" --set-fmt-output-overlay=chromakey=<key>,global_alpha=<alpha>\n"); - printf(" set the video output overlay format [VIDIOC_S_FMT]\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-out\n"); - printf(" query the sliced VBI output format [VIDIOC_G_FMT]\n"); - printf(" --set-fmt-sliced-vbi-out=<mode>\n"); - printf(" set the sliced VBI output 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-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(" --overlay=<on> turn overlay on (1) or off (0) (VIDIOC_OVERLAY)\n"); - printf(" --get-fbuf query the overlay framebuffer data [VIDIOC_G_FBUF]\n"); - printf(" --set-fbuf=chromakey=<0/1>,global_alpha=<0/1>,local_alpha=<0/1>,local_inv_alpha=<0/1>\n"); - printf(" set the overlay framebuffer [VIDIOC_S_FBUF]\n"); - printf(" --get-cropcap query the crop capabilities [VIDIOC_CROPCAP]\n"); - printf(" --get-crop query the video capture crop window [VIDIOC_G_CROP]\n"); - printf(" --set-crop=top=<x>,left=<y>,width=<w>,height=<h>\n"); - printf(" set the video capture crop window [VIDIOC_S_CROP]\n"); - printf(" --get-cropcap-output\n"); - printf(" query the crop capabilities for video output [VIDIOC_CROPCAP]\n"); - printf(" --get-crop-output query the video output crop window [VIDIOC_G_CROP]\n"); - printf(" --set-crop-output=top=<x>,left=<y>,width=<w>,height=<h>\n"); - printf(" set the video output crop window [VIDIOC_S_CROP]\n"); - printf(" --get-cropcap-overlay\n"); - printf(" query the crop capabilities for video overlay [VIDIOC_CROPCAP]\n"); - printf(" --get-crop-overlay query the video overlay crop window [VIDIOC_G_CROP]\n"); - printf(" --set-crop-overlay=top=<x>,left=<y>,width=<w>,height=<h>\n"); - printf(" set the video overlay crop window [VIDIOC_S_CROP]\n"); - printf(" --get-cropcap-output-overlay\n"); - printf(" query the crop capabilities for video output overlays [VIDIOC_CROPCAP]\n"); - printf(" --get-crop-output-overlay\n"); - printf(" query the video output overlay crop window [VIDIOC_G_CROP]\n"); - printf(" --set-crop-output-overlay=top=<x>,left=<y>,width=<w>,height=<h>\n"); - printf(" set the video output overlay 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"); - printf(" --streamon turn the stream on [VIDIOC_STREAMOFF]\n"); - printf(" --log-status log the board status in the kernel log [VIDIOC_LOG_STATUS]\n"); + printf("Common options:\n" + " --all display all information available\n" + " -C, --get-ctrl=<ctrl>[,<ctrl>...]\n" + " get the value of the controls [VIDIOC_G_EXT_CTRLS]\n" + " -c, --set-ctrl=<ctrl>=<val>[,<ctrl>=<val>...]\n" + " set the controls to the values specified [VIDIOC_S_EXT_CTRLS]\n" + " -D, --info show driver info [VIDIOC_QUERYCAP]\n" + " -d, --device=<dev> use device <dev> instead of /dev/video0\n" + " if <dev> is a single digit, then /dev/video<dev> is used\n" + " -F, --get-freq query the frequency [VIDIOC_G_FREQUENCY]\n" + " -f, --set-freq=<freq>\n" + " set the frequency to <freq> MHz [VIDIOC_S_FREQUENCY]\n" + " -h, --help display this help message\n" + " -I, --get-input query the video input [VIDIOC_G_INPUT]\n" + " -i, --set-input=<num>\n" + " set the video input to <num> [VIDIOC_S_INPUT]\n" + " -l, --list-ctrls display all controls and their values [VIDIOC_QUERYCTRL]\n" + " -L, --list-ctrls-menus\n" + " display all controls, their values and the menus [VIDIOC_QUERYMENU]\n" + " -N, --list-outputs display video outputs [VIDIOC_ENUMOUTPUT]\n" + " -n, --list-inputs display video inputs [VIDIOC_ENUMINPUT]\n" + " -O, --get-output query the video output [VIDIOC_G_OUTPUT]\n" + " -o, --set-output=<num>\n" + " set the video output to <num> [VIDIOC_S_OUTPUT]\n" + " -S, --get-standard\n" + " query the video standard [VIDIOC_G_STD]\n" + " -s, --set-standard=<num>\n" + " set the video standard to <num> [VIDIOC_S_STD]\n" + " <num> can be a numerical v4l2_std value, or it can be one of:\n" + " pal-X (X = B/G/H/N/Nc/I/D/K/M/60) or just 'pal' (V4L2_STD_PAL)\n" + " ntsc-X (X = M/J/K) or just 'ntsc' (V4L2_STD_NTSC)\n" + " secam-X (X = B/G/H/D/K/L/Lc) or just 'secam' (V4L2_STD_SECAM)\n" + " --list-standards display supported video standards [VIDIOC_ENUMSTD]\n" + " -T, --get-tuner query the tuner settings [VIDIOC_G_TUNER]\n" + " -t, --set-tuner=<mode>\n" + " set the audio mode of the tuner [VIDIOC_S_TUNER]\n" + " Possible values: mono, stereo, lang2, lang1, bilingual\n" + " --list-formats display supported video formats [VIDIOC_ENUM_FMT]\n" + " -V, --get-fmt-video\n" + " query the video capture format [VIDIOC_G_FMT]\n" + " -v, --set-fmt-video=width=<w>,height=<h>,pixelformat=<f>\n" + " set the video capture format [VIDIOC_S_FMT]\n" + " pixelformat is either the format index as reported by\n" + " --list-formats, or the fourcc value as a string\n" + " --list-devices list all v4l devices\n" + " --silent only set the result code, do not print any messages\n" + " --verbose turn on verbose ioctl status reporting\n" + "\n"); + printf("Uncommon options:\n" + " --try-fmt-video=width=<w>,height=<h>,pixelformat=<f>\n" + " try the video capture format [VIDIOC_TRY_FMT]\n" + " pixelformat is either the format index as reported by\n" + " --list-formats, or the fourcc value as a string\n" + " --get-fmt-video-out\n" + " query the video output format [VIDIOC_G_FMT]\n" + " --set-fmt-video-out=width=<w>,height=<h>\n" + " set the video output format [VIDIOC_S_FMT]\n" + " --try-fmt-video-out=width=<w>,height=<h>\n" + " try the video output format [VIDIOC_TRY_FMT]\n" + " --get-fmt-overlay query the video overlay format [VIDIOC_G_FMT]\n" + " --get-fmt-output-overlay\n" + " query the video output overlay format [VIDIOC_G_FMT]\n" + " --set-fmt-overlay\n" + " --try-fmt-overlay\n" + " --set-fmt-output-overlay\n" + " --try-fmt-output-overlay=chromakey=<key>,global_alpha=<alpha>,\n" + " top=<t>,left=<l>,width=<w>,height=<h>,field=<f>\n" + " set/try the video or video output overlay format [VIDIOC_TRY_FMT]\n" + " <f> can be one of:\n" + " any, none, top, bottom, interlaced, seq_tb, seq_bt, alternate,\n" + " interlaced_tb, interlaced_bt\n" + " --get-sliced-vbi-cap\n" + " query the sliced VBI capture capabilities [VIDIOC_G_SLICED_VBI_CAP]\n" + " --get-sliced-vbi-out-cap\n" + " query the sliced VBI output capabilities [VIDIOC_G_SLICED_VBI_CAP]\n" + " -B, --get-fmt-sliced-vbi\n" + " query the sliced VBI capture format [VIDIOC_G_FMT]\n" + " --get-fmt-sliced-vbi-out\n" + " query the sliced VBI output format [VIDIOC_G_FMT]\n" + " -b, --set-fmt-sliced-vbi\n" + " --try-fmt-sliced-vbi\n" + " --set-fmt-sliced-vbi-out\n" + " --try-fmt-sliced-vbi-out=<mode>\n" + " (try to) set the sliced VBI capture/output format to <mode> [VIDIOC_S/TRY_FMT]\n" + " <mode> is a comma separated list of:\n" + " off: turn off sliced VBI (cannot be combined with other modes)\n" + " teletext: teletext (PAL/SECAM)\n" + " cc: closed caption (NTSC)\n" + " wss: widescreen signal (PAL/SECAM)\n" + " vps: VPS (PAL/SECAM)\n" + " --get-fmt-vbi query the VBI capture format [VIDIOC_G_FMT]\n" + " --get-fmt-vbi-out query the VBI output format [VIDIOC_G_FMT]\n" + " --overlay=<on> turn overlay on (1) or off (0) (VIDIOC_OVERLAY)\n" + " --get-fbuf query the overlay framebuffer data [VIDIOC_G_FBUF]\n" + " --set-fbuf=chromakey=<0/1>,global_alpha=<0/1>,local_alpha=<0/1>,local_inv_alpha=<0/1>\n" + " set the overlay framebuffer [VIDIOC_S_FBUF]\n" + " --get-cropcap query the crop capabilities [VIDIOC_CROPCAP]\n" + " --get-crop query the video capture crop window [VIDIOC_G_CROP]\n" + " --set-crop=top=<x>,left=<y>,width=<w>,height=<h>\n" + " set the video capture crop window [VIDIOC_S_CROP]\n" + " --get-cropcap-output\n" + " query the crop capabilities for video output [VIDIOC_CROPCAP]\n" + " --get-crop-output query the video output crop window [VIDIOC_G_CROP]\n" + " --set-crop-output=top=<x>,left=<y>,width=<w>,height=<h>\n" + " set the video output crop window [VIDIOC_S_CROP]\n" + " --get-cropcap-overlay\n" + " query the crop capabilities for video overlay [VIDIOC_CROPCAP]\n" + " --get-crop-overlay query the video overlay crop window [VIDIOC_G_CROP]\n" + " --set-crop-overlay=top=<x>,left=<y>,width=<w>,height=<h>\n" + " set the video overlay crop window [VIDIOC_S_CROP]\n" + " --get-cropcap-output-overlay\n" + " query the crop capabilities for video output overlays [VIDIOC_CROPCAP]\n" + " --get-crop-output-overlay\n" + " query the video output overlay crop window [VIDIOC_G_CROP]\n" + " --set-crop-output-overlay=top=<x>,left=<y>,width=<w>,height=<h>\n" + " set the video output overlay crop window [VIDIOC_S_CROP]\n" + " --get-audio-input query the audio input [VIDIOC_G_AUDIO]\n" + " --set-audio-input=<num>\n" + " set the audio input to <num> [VIDIOC_S_AUDIO]\n" + " --get-audio-output query the audio output [VIDIOC_G_AUDOUT]\n" + " --set-audio-output=<num>\n" + " set the audio output to <num> [VIDIOC_S_AUDOUT]\n" + " --list-audio-outputs\n" + " display audio outputs [VIDIOC_ENUMAUDOUT]\n" + " --list-audio-inputs\n" + " display audio inputs [VIDIOC_ENUMAUDIO]\n" + "\n"); + printf("Expert options:\n" + " --streamoff turn the stream off [VIDIOC_STREAMOFF]\n" + " --streamon turn the stream on [VIDIOC_STREAMOFF]\n" + " --log-status log the board status in the kernel log [VIDIOC_LOG_STATUS]\n"); exit(0); } @@ -634,13 +673,17 @@ static void find_controls(int fd) for (id = V4L2_CID_USER_BASE; id < V4L2_CID_LASTP1; id++) { qctrl.id = id; if (ioctl(fd, VIDIOC_QUERYCTRL, &qctrl) == 0 && - !(qctrl.flags & V4L2_CTRL_FLAG_DISABLED)) + !(qctrl.flags & V4L2_CTRL_FLAG_DISABLED)) { ctrl_str2id[name2var(qctrl.name)] = qctrl.id; + ctrl_id2str[qctrl.id] = name2var(qctrl.name); + } } for (qctrl.id = V4L2_CID_PRIVATE_BASE; ioctl(fd, VIDIOC_QUERYCTRL, &qctrl) == 0; qctrl.id++) { - if (!(qctrl.flags & V4L2_CTRL_FLAG_DISABLED)) + if (!(qctrl.flags & V4L2_CTRL_FLAG_DISABLED)) { ctrl_str2id[name2var(qctrl.name)] = qctrl.id; + ctrl_id2str[qctrl.id] = name2var(qctrl.name); + } } } @@ -697,7 +740,7 @@ static void printfbuf(const struct v4l2_framebuffer &fb) printf("\tBase : 0x%p\n", fb.base); printf("\tWidth : %d\n", fb.fmt.width); printf("\tHeight : %d\n", fb.fmt.height); - printf("\tPixel Format : %s\n", fcc2s(fb.fmt.pixelformat).c_str()); + printf("\tPixel Format : '%s'\n", fcc2s(fb.fmt.pixelformat).c_str()); if (!is_ext) { printf("\tBytes per Line: %d\n", fb.fmt.bytesperline); printf("\tSize image : %d\n", fb.fmt.sizeimage); @@ -736,7 +779,7 @@ static void printfmt(struct v4l2_format vfmt) case V4L2_BUF_TYPE_VIDEO_CAPTURE: case V4L2_BUF_TYPE_VIDEO_OUTPUT: printf("\tWidth/Height : %u/%u\n", vfmt.fmt.pix.width, vfmt.fmt.pix.height); - printf("\tPixel Format : %s\n", fcc2s(vfmt.fmt.pix.pixelformat).c_str()); + printf("\tPixel Format : '%s'\n", fcc2s(vfmt.fmt.pix.pixelformat).c_str()); printf("\tField : %s\n", field2s(vfmt.fmt.pix.field).c_str()); printf("\tBytes per Line: %u\n", vfmt.fmt.pix.bytesperline); printf("\tSize Image : %u\n", vfmt.fmt.pix.sizeimage); @@ -794,8 +837,9 @@ static void print_video_formats(int fd, enum v4l2_buf_type type) fmt.index = 0; fmt.type = type; while (ioctl(fd, VIDIOC_ENUM_FMT, &fmt) >= 0) { + printf("\tIndex : %d\n", fmt.index); printf("\tType : %s\n", buftype2s(type).c_str()); - printf("\tPixelformat : %s", fcc2s(fmt.pixelformat).c_str()); + printf("\tPixel Format: '%s'", fcc2s(fmt.pixelformat).c_str()); if (fmt.flags) printf(" (compressed)"); printf("\n"); @@ -1009,19 +1053,97 @@ static int doioctl(int fd, int request, void *parm, const char *name) if (retVal < 0) { app_result = -1; } - if (!options[OptVerbose]) return retVal; - printf("%s: ", name); + if (options[OptSilent]) return retVal; if (retVal < 0) - printf("failed: %s\n", strerror(errno)); - else - printf("ok\n"); + printf("%s: failed: %s\n", name, strerror(errno)); + else if (verbose) + printf("%s: ok\n", name); return retVal; } -static int parse_subopt(char **subs, char * const *subopts, char **value) +static bool is_v4l_dev(const char *name) { - int opt = getsubopt(subs, subopts, value); + return !memcmp(name, "vtx", 3) || + !memcmp(name, "video", 5) || + !memcmp(name, "radio", 5) || + !memcmp(name, "vbi", 3); +} + +static int calc_node_val(const char *s) +{ + int n = 0; + + s = strrchr(s, '/') + 1; + if (!memcmp(s, "video", 5)) n = 0; + else if (!memcmp(s, "radio", 5)) n = 0x100; + else if (!memcmp(s, "vbi", 3)) n = 0x200; + else if (!memcmp(s, "vtx", 3)) n = 0x300; + n += atol(s + (n >= 0x200 ? 3 : 5)); + return n; +} + +static bool sort_on_device_name(const std::string &s1, const std::string &s2) +{ + int n1 = calc_node_val(s1.c_str()); + int n2 = calc_node_val(s2.c_str()); + + return n1 < n2; +} + +static void list_devices() +{ + DIR *dp; + struct dirent *ep; + dev_vec files; + dev_map cards; + struct v4l2_capability vcap; + + dp = opendir("/dev"); + if (dp == NULL) { + perror ("Couldn't open the directory"); + return; + } + while (ep = readdir(dp)) + if (is_v4l_dev(ep->d_name)) + files.push_back(std::string("/dev/") + ep->d_name); + closedir(dp); + +#if 0 + dp = opendir("/dev/v4l"); + if (dp) { + while (ep = readdir(dp)) + if (is_v4l_dev(ep->d_name)) + files.push_back(std::string("/dev/v4l/") + ep->d_name); + closedir(dp); + } +#endif + + std::sort(files.begin(), files.end(), sort_on_device_name); + + for (dev_vec::iterator iter = files.begin(); + iter != files.end(); ++iter) { + int fd = open(iter->c_str(), O_RDWR); + std::string bus_info; + + if (fd < 0) + continue; + doioctl(fd, VIDIOC_QUERYCAP, &vcap, "VIDIOC_QUERYCAP"); + close(fd); + bus_info = (const char *)vcap.bus_info; + if (cards[bus_info].empty()) + cards[bus_info] += std::string((char *)vcap.card) + " (" + bus_info + "):\n"; + cards[bus_info] += "\t" + (*iter) + "\n"; + } + for (dev_map::iterator iter = cards.begin(); + iter != cards.end(); ++iter) { + printf("%s\n", iter->second.c_str()); + } +} + +static int parse_subopt(char **subs, const char * const *subopts, char **value) +{ + int opt = getsubopt(subs, (char * const *)subopts, value); if (opt == -1) { fprintf(stderr, "Invalid suboptions specified\n"); @@ -1094,7 +1216,7 @@ static void parse_crop(char *optarg, unsigned int &set_crop, v4l2_rect &vcrop) char *subs = optarg; while (*subs != '\0') { - static char *const subopts[] = { + static const char *const subopts[] = { "left", "top", "width", @@ -1123,6 +1245,21 @@ static void parse_crop(char *optarg, unsigned int &set_crop, v4l2_rect &vcrop) } } +static enum v4l2_field parse_field(const char *s) +{ + if (!strcmp(s, "any")) return V4L2_FIELD_ANY; + if (!strcmp(s, "none")) return V4L2_FIELD_NONE; + if (!strcmp(s, "top")) return V4L2_FIELD_TOP; + if (!strcmp(s, "bottom")) return V4L2_FIELD_BOTTOM; + if (!strcmp(s, "interlaced")) return V4L2_FIELD_INTERLACED; + if (!strcmp(s, "seq_tb")) return V4L2_FIELD_SEQ_TB; + if (!strcmp(s, "seq_bt")) return V4L2_FIELD_SEQ_BT; + if (!strcmp(s, "alternate")) return V4L2_FIELD_ALTERNATE; + if (!strcmp(s, "interlaced_tb")) return V4L2_FIELD_INTERLACED_TB; + if (!strcmp(s, "interlaced_bt")) return V4L2_FIELD_INTERLACED_BT; + return V4L2_FIELD_ANY; +} + int main(int argc, char **argv) { char *value, *subs; @@ -1138,19 +1275,21 @@ int main(int argc, char **argv) unsigned int set_crop_overlay = 0; unsigned int set_crop_out_overlay = 0; unsigned int set_fbuf = 0; + unsigned int set_overlay_fmt = 0; unsigned int set_overlay_fmt_out = 0; int mode = V4L2_TUNER_MODE_STEREO; /* set audio mode */ /* command args */ int ch; - char *device = strdup("/dev/video0"); /* -d device */ + const char *device = "/dev/video0"; /* -d device */ struct v4l2_format vfmt; /* set_format/get_format for video */ struct v4l2_format vfmt_out; /* set_format/get_format video output */ struct v4l2_format vbi_fmt; /* set_format/get_format for sliced VBI */ struct v4l2_format vbi_fmt_out; /* set_format/get_format for sliced VBI output */ struct v4l2_format raw_fmt; /* set_format/get_format for VBI */ struct v4l2_format raw_fmt_out; /* set_format/get_format for VBI output */ + struct v4l2_format overlay_fmt; /* set_format/get_format video overlay */ struct v4l2_format overlay_fmt_out; /* set_format/get_format video overlay output */ struct v4l2_tuner tuner; /* set_tuner/get_tuner */ struct v4l2_capability vcap; /* list_cap */ @@ -1170,14 +1309,18 @@ int main(int argc, char **argv) struct v4l2_frequency vf; /* get_freq/set_freq */ struct v4l2_standard vs; /* list_std */ int overlay; /* overlay */ + unsigned int *set_overlay_fmt_ptr; + struct v4l2_format *overlay_fmt_ptr; char short_options[26 * 2 * 2 + 1]; int idx = 0; + int ret; memset(&vfmt, 0, sizeof(vfmt)); memset(&vbi_fmt, 0, sizeof(vbi_fmt)); memset(&raw_fmt, 0, sizeof(raw_fmt)); memset(&vfmt_out, 0, sizeof(vfmt_out)); memset(&vbi_fmt_out, 0, sizeof(vbi_fmt_out)); + memset(&overlay_fmt, 0, sizeof(overlay_fmt)); memset(&overlay_fmt_out, 0, sizeof(overlay_fmt_out)); memset(&raw_fmt_out, 0, sizeof(raw_fmt_out)); memset(&tuner, 0, sizeof(tuner)); @@ -1220,19 +1363,23 @@ int main(int argc, char **argv) usage(); return 0; case OptSetDevice: - device = strdup(optarg); + device = optarg; if (device[0] >= '0' && device[0] <= '9' && device[1] == 0) { + static char newdev[20]; char dev = device[0]; - sprintf(device, "/dev/video%c", dev); + sprintf(newdev, "/dev/video%c", dev); + device = newdev; } break; case OptSetVideoFormat: + case OptTryVideoFormat: subs = optarg; while (*subs != '\0') { - static char *const subopts[] = { + static const char *const subopts[] = { "width", "height", + "pixelformat", NULL }; @@ -1245,13 +1392,23 @@ int main(int argc, char **argv) vfmt.fmt.pix.height = strtol(value, 0L, 0); set_fmts |= FmtHeight; break; + case 2: + if (strlen(value) == 4) + vfmt.fmt.pix.pixelformat = + v4l2_fourcc(value[0], value[1], + value[2], value[3]); + else + vfmt.fmt.pix.pixelformat = strtol(value, 0L, 0); + set_fmts |= FmtPixelFormat; + break; } } break; case OptSetVideoOutFormat: + case OptTryVideoOutFormat: subs = optarg; while (*subs != '\0') { - static char *const subopts[] = { + static const char *const subopts[] = { "width", "height", NULL @@ -1269,23 +1426,63 @@ int main(int argc, char **argv) } } break; + case OptSetOverlayFormat: + case OptTryOverlayFormat: case OptSetOutputOverlayFormat: + case OptTryOutputOverlayFormat: + switch (ch) { + case OptSetOverlayFormat: + case OptTryOverlayFormat: + set_overlay_fmt_ptr = &set_overlay_fmt; + overlay_fmt_ptr = &overlay_fmt; + break; + case OptSetOutputOverlayFormat: + case OptTryOutputOverlayFormat: + set_overlay_fmt_ptr = &set_overlay_fmt_out; + overlay_fmt_ptr = &overlay_fmt_out; + break; + } subs = optarg; while (*subs != '\0') { - static char *const subopts[] = { + static const char *const subopts[] = { "chromakey", "global_alpha", + "left", + "top", + "width", + "height", + "field", NULL }; switch (parse_subopt(&subs, subopts, &value)) { case 0: - overlay_fmt_out.fmt.win.chromakey = strtol(value, 0L, 0); - set_overlay_fmt_out |= FmtChromaKey; + overlay_fmt_ptr->fmt.win.chromakey = strtol(value, 0L, 0); + *set_overlay_fmt_ptr |= FmtChromaKey; break; case 1: - overlay_fmt_out.fmt.win.global_alpha = strtol(value, 0L, 0); - set_overlay_fmt_out |= FmtGlobalAlpha; + overlay_fmt_ptr->fmt.win.global_alpha = strtol(value, 0L, 0); + *set_overlay_fmt_ptr |= FmtGlobalAlpha; + break; + case 2: + overlay_fmt_ptr->fmt.win.w.left = strtol(value, 0L, 0); + *set_overlay_fmt_ptr |= FmtLeft; + break; + case 3: + overlay_fmt_ptr->fmt.win.w.top = strtol(value, 0L, 0); + *set_overlay_fmt_ptr |= FmtTop; + break; + case 4: + overlay_fmt_ptr->fmt.win.w.width = strtol(value, 0L, 0); + *set_overlay_fmt_ptr |= FmtWidth; + break; + case 5: + overlay_fmt_ptr->fmt.win.w.height = strtol(value, 0L, 0); + *set_overlay_fmt_ptr |= FmtHeight; + break; + case 6: + overlay_fmt_ptr->fmt.win.field = parse_field(value); + *set_overlay_fmt_ptr |= FmtField; break; } } @@ -1293,7 +1490,7 @@ int main(int argc, char **argv) case OptSetFBuf: subs = optarg; while (*subs != '\0') { - static char *const subopts[] = { + static const char *const subopts[] = { "chromakey", "global_alpha", "local_alpha", @@ -1419,16 +1616,18 @@ int main(int argc, char **argv) break; case OptSetSlicedVbiFormat: case OptSetSlicedVbiOutFormat: + case OptTrySlicedVbiFormat: + case OptTrySlicedVbiOutFormat: { bool foundOff = false; v4l2_format *fmt = &vbi_fmt; - if (ch == OptSetSlicedVbiOutFormat) + if (ch == OptSetSlicedVbiOutFormat || ch == OptTrySlicedVbiOutFormat) fmt = &vbi_fmt_out; fmt->fmt.sliced.service_set = 0; subs = optarg; while (*subs != '\0') { - static char *const subopts[] = { + static const char *const subopts[] = { "off", "teletext", "cc", @@ -1466,6 +1665,9 @@ int main(int argc, char **argv) } break; } + case OptListDevices: + list_devices(); + break; case ':': fprintf(stderr, "Option `%s' requires a value\n", argv[optind]); @@ -1492,8 +1694,8 @@ int main(int argc, char **argv) strerror(errno)); exit(1); } - free(device); + verbose = options[OptVerbose]; doioctl(fd, VIDIOC_QUERYCAP, &vcap, "VIDIOC_QUERYCAP"); capabilities = vcap.capabilities; find_controls(fd); @@ -1531,6 +1733,7 @@ int main(int argc, char **argv) options[OptGetFBuf] = 1; options[OptGetCropCap] = 1; options[OptGetOutputCropCap] = 1; + options[OptSilent] = 1; } /* Information Opts */ @@ -1613,7 +1816,7 @@ int main(int argc, char **argv) } } - if (options[OptSetVideoFormat]) { + if (options[OptSetVideoFormat] || options[OptTryVideoFormat]) { struct v4l2_format in_vfmt; in_vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; @@ -1622,11 +1825,29 @@ int main(int argc, char **argv) in_vfmt.fmt.pix.width = vfmt.fmt.pix.width; if (set_fmts & FmtHeight) in_vfmt.fmt.pix.height = vfmt.fmt.pix.height; - doioctl(fd, VIDIOC_S_FMT, &in_vfmt, "VIDIOC_S_FMT"); + if (set_fmts & FmtPixelFormat) { + in_vfmt.fmt.pix.pixelformat = vfmt.fmt.pix.pixelformat; + if (in_vfmt.fmt.pix.pixelformat < 256) { + struct v4l2_fmtdesc fmt; + + fmt.index = in_vfmt.fmt.pix.pixelformat; + fmt.type = in_vfmt.type; + if (doioctl(fd, VIDIOC_ENUM_FMT, &fmt, "VIDIOC_ENUM_FMT")) + goto set_vid_fmt_error; + in_vfmt.fmt.pix.pixelformat = fmt.pixelformat; + } + } + if (options[OptSetVideoFormat]) + ret = doioctl(fd, VIDIOC_S_FMT, &in_vfmt, "VIDIOC_S_FMT"); + else + ret = doioctl(fd, VIDIOC_TRY_FMT, &in_vfmt, "VIDIOC_TRY_FMT"); + if (ret == 0 && verbose) + printfmt(in_vfmt); } } +set_vid_fmt_error: - if (options[OptSetVideoOutFormat]) { + if (options[OptSetVideoOutFormat] || options[OptTryVideoOutFormat]) { struct v4l2_format in_vfmt; in_vfmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; @@ -1635,35 +1856,65 @@ int main(int argc, char **argv) in_vfmt.fmt.pix.width = vfmt_out.fmt.pix.width; if (set_fmts_out & FmtHeight) in_vfmt.fmt.pix.height = vfmt_out.fmt.pix.height; - doioctl(fd, VIDIOC_S_FMT, &in_vfmt, "VIDIOC_S_FMT"); + + if (options[OptSetVideoOutFormat]) + ret = doioctl(fd, VIDIOC_S_FMT, &in_vfmt, "VIDIOC_S_FMT"); + else + ret = doioctl(fd, VIDIOC_TRY_FMT, &in_vfmt, "VIDIOC_TRY_FMT"); + if (ret == 0 && verbose) + printfmt(in_vfmt); } } - if (options[OptSetSlicedVbiFormat]) { - if (vbi_fmt.fmt.sliced.service_set == 0) { - // switch to raw mode - vbi_fmt.type = V4L2_BUF_TYPE_VBI_CAPTURE; - if (doioctl(fd, VIDIOC_G_FMT, &vbi_fmt, "VIDIOC_G_FMT") == 0) - doioctl(fd, VIDIOC_S_FMT, &vbi_fmt, "VIDIOC_S_FMT"); - } else { - vbi_fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; - doioctl(fd, VIDIOC_S_FMT, &vbi_fmt, "VIDIOC_S_FMT"); - } + if (options[OptSetSlicedVbiFormat] || options[OptTrySlicedVbiFormat]) { + vbi_fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; + if (options[OptSetSlicedVbiFormat]) + ret = doioctl(fd, VIDIOC_S_FMT, &vbi_fmt, "VIDIOC_S_FMT"); + else + ret = doioctl(fd, VIDIOC_TRY_FMT, &vbi_fmt, "VIDIOC_TRY_FMT"); + if (ret == 0 && verbose) + printfmt(vbi_fmt); } - if (options[OptSetSlicedVbiOutFormat]) { - if (vbi_fmt_out.fmt.sliced.service_set == 0) { - // switch to raw mode - vbi_fmt_out.type = V4L2_BUF_TYPE_VBI_OUTPUT; - if (doioctl(fd, VIDIOC_G_FMT, &vbi_fmt_out, "VIDIOC_G_FMT") == 0) - doioctl(fd, VIDIOC_S_FMT, &vbi_fmt_out, "VIDIOC_S_FMT"); - } else { - vbi_fmt_out.type = V4L2_BUF_TYPE_SLICED_VBI_OUTPUT; - doioctl(fd, VIDIOC_S_FMT, &vbi_fmt_out, "VIDIOC_S_FMT"); + if (options[OptSetSlicedVbiOutFormat] || options[OptTrySlicedVbiOutFormat]) { + vbi_fmt_out.type = V4L2_BUF_TYPE_SLICED_VBI_OUTPUT; + if (options[OptSetSlicedVbiOutFormat]) + ret = doioctl(fd, VIDIOC_S_FMT, &vbi_fmt_out, "VIDIOC_S_FMT"); + else + ret = doioctl(fd, VIDIOC_TRY_FMT, &vbi_fmt_out, "VIDIOC_TRY_FMT"); + if (ret == 0 && verbose) + printfmt(vbi_fmt_out); + } + + if (options[OptSetOverlayFormat] || options[OptTryOverlayFormat]) { + struct v4l2_format fmt; + + fmt.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; + if (doioctl(fd, VIDIOC_G_FMT, &fmt, "VIDIOC_G_FMT") == 0) { + if (set_overlay_fmt & FmtChromaKey) + fmt.fmt.win.chromakey = overlay_fmt.fmt.win.chromakey; + if (set_overlay_fmt & FmtGlobalAlpha) + fmt.fmt.win.global_alpha = overlay_fmt.fmt.win.global_alpha; + if (set_overlay_fmt & FmtLeft) + fmt.fmt.win.w.left = overlay_fmt.fmt.win.w.left; + if (set_overlay_fmt & FmtTop) + fmt.fmt.win.w.top = overlay_fmt.fmt.win.w.top; + if (set_overlay_fmt & FmtWidth) + fmt.fmt.win.w.width = overlay_fmt.fmt.win.w.width; + if (set_overlay_fmt & FmtHeight) + fmt.fmt.win.w.height = overlay_fmt.fmt.win.w.height; + if (set_overlay_fmt & FmtField) + fmt.fmt.win.field = overlay_fmt.fmt.win.field; + if (options[OptSetOverlayFormat]) + ret = doioctl(fd, VIDIOC_S_FMT, &fmt, "VIDIOC_S_FMT"); + else + ret = doioctl(fd, VIDIOC_TRY_FMT, &fmt, "VIDIOC_TRY_FMT"); + if (ret == 0 && verbose) + printfmt(fmt); } } - if (options[OptSetOutputOverlayFormat]) { + if (options[OptSetOutputOverlayFormat] || options[OptTryOutputOverlayFormat]) { struct v4l2_format fmt; fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY; @@ -1672,7 +1923,22 @@ int main(int argc, char **argv) fmt.fmt.win.chromakey = overlay_fmt_out.fmt.win.chromakey; if (set_overlay_fmt_out & FmtGlobalAlpha) fmt.fmt.win.global_alpha = overlay_fmt_out.fmt.win.global_alpha; - doioctl(fd, VIDIOC_S_FMT, &fmt, "VIDIOC_S_FMT"); + if (set_overlay_fmt_out & FmtLeft) + fmt.fmt.win.w.left = overlay_fmt_out.fmt.win.w.left; + if (set_overlay_fmt_out & FmtTop) + fmt.fmt.win.w.top = overlay_fmt_out.fmt.win.w.top; + if (set_overlay_fmt_out & FmtWidth) + fmt.fmt.win.w.width = overlay_fmt_out.fmt.win.w.width; + if (set_overlay_fmt_out & FmtHeight) + fmt.fmt.win.w.height = overlay_fmt_out.fmt.win.w.height; + if (set_overlay_fmt_out & FmtField) + fmt.fmt.win.field = overlay_fmt_out.fmt.win.field; + if (options[OptSetOutputOverlayFormat]) + ret = doioctl(fd, VIDIOC_S_FMT, &fmt, "VIDIOC_S_FMT"); + else + ret = doioctl(fd, VIDIOC_TRY_FMT, &fmt, "VIDIOC_TRY_FMT"); + if (ret == 0 && verbose) + printfmt(fmt); } } @@ -1992,6 +2258,7 @@ int main(int argc, char **argv) memset(&vt, 0, sizeof(struct v4l2_tuner)); if (doioctl(fd, VIDIOC_G_TUNER, &vt, "VIDIOC_G_TUNER") == 0) { printf("Tuner:\n"); + printf("\tName : %s\n", vt.name); printf("\tCapabilities : %s\n", tcap2s(vt.capability).c_str()); if (vt.capability & V4L2_TUNER_CAP_LOW) printf("\tFrequency range : %.1f MHz - %.1f MHz\n", @@ -1999,7 +2266,7 @@ int main(int argc, char **argv) else printf("\tFrequency range : %.1f MHz - %.1f MHz\n", vt.rangelow / 16.0, vt.rangehigh / 16.0); - printf("\tSignal strength : %d%%\n", (int)(vt.signal / 655.35)); + printf("\tSignal strength/AFC : %d%%/%d\n", (int)(vt.signal / 655.35), vt.afc); printf("\tCurrent audio mode : %s\n", audmode2s(vt.audmode)); printf("\tAvailable subchannels: %s\n", rxsubchans2s(vt.rxsubchans).c_str()); @@ -2113,7 +2380,7 @@ int main(int argc, char **argv) while (ioctl(fd, VIDIOC_ENUMSTD, &vs) >= 0) { if (vs.index) printf("\n"); - printf("\tindex : %d\n", vs.index); + printf("\tIndex : %d\n", vs.index); printf("\tID : 0x%016llX\n", (unsigned long long)vs.id); printf("\tName : %s\n", vs.name); printf("\tFrame period: %d/%d\n", |