diff -Nru v4l-utils-1.0.0+r2263/contrib/au0828/parse_au0828.pl v4l-utils-1.0.0+r2364/contrib/au0828/parse_au0828.pl --- v4l-utils-1.0.0+r2263/contrib/au0828/parse_au0828.pl 1970-01-01 00:00:00.000000000 +0000 +++ v4l-utils-1.0.0+r2364/contrib/au0828/parse_au0828.pl 2014-08-12 09:02:18.000000000 +0000 @@ -0,0 +1,155 @@ +#!/usr/bin/perl +use strict; + +# Copyright (C) 2014 Mauro Carvalho Chehab +# Copyright (c) 2014 Samsung Electronics Co., Ltd. +# +# 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, version 2 of the License. +# +# 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. +# +# This small script parses USB dumps generated by several drivers, +# decoding USB bits. +# +# To use it, do: +# dmesg | ./parse_usb.pl +# +# Also, there are other utilities that produce similar outputs, and it +# is not hard to parse some USB analyzers log into the expected format. +# + +my %speed_map = ( + 0x07 => "250KHz", + 0x14 => "100KHz", + 0x40 => "30KHz", + 0x60 => "20KHz", +); + +sub type_req($) +{ + my $reqtype = shift; + my $s; + + if ($reqtype & 0x80) { + $s = "RD "; + } else { + $s = "WR "; + } + if (($reqtype & 0x60) == 0x20) { + $s .= "CLAS "; + } elsif (($reqtype & 0x60) == 0x40) { + $s .= "VEND "; + } elsif (($reqtype & 0x60) == 0x60) { + $s .= "RSVD "; + } + + if (($reqtype & 0x1f) == 0x00) { + $s .= "DEV "; + } elsif (($reqtype & 0x1f) == 0x01) { + $s .= "INT "; + } elsif (($reqtype & 0x1f) == 0x02) { + $s .= "EP "; + } elsif (($reqtype & 0x1f) == 0x03) { + $s .= "OTHER "; + } elsif (($reqtype & 0x1f) == 0x04) { + $s .= "PORT "; + } elsif (($reqtype & 0x1f) == 0x05) { + $s .= "RPIPE "; + } else { + $s .= sprintf "RECIP 0x%02x ", $reqtype & 0x1f; + } + + $s =~ s/\s+$//; + return $s; +} + +my $i2c_speed = "unknown"; +my $i2c_addr = "unknown"; +my @i2c_sbuf; +my @i2c_rbuf; +my $i2c_hold; + +while (<>) { + if (m/(.*)([0-9a-f].) ([0-9a-f].) ([0-9a-f].) ([0-9a-f].) ([0-9a-f].) ([0-9a-f].) ([0-9a-f].) ([0-9a-f].)[\<\>\s]+(.*)/) { + my $timestamp = $1; + my $reqtype = hex($2); + my $req = hex($3); + my $val = hex("$5$4"); + my $reg = hex("$7$6"); + my $wlen = hex("$9$8"); + my $payload = $10; + + $timestamp =~ s/^\s+//; + $timestamp =~ s/\s+$//; + + if (($reqtype == 0x40) && ($reg == 0x02ff)) { + # Start of an I2C tranfer + @i2c_sbuf = (); + @i2c_rbuf = (); + next; + } + if (($reqtype == 0x40) && ($reg == 0x0202)) { + # I2C speed + $i2c_speed = sprintf "0x%02x", $val; + $i2c_speed = $speed_map{$val} if defined($speed_map{$val}); + next; + } + + if (($reqtype == 0x40) && ($reg == 0x0203)) { + # I2C addr + $i2c_addr = $val >> 1; + next; + } + + if (($reqtype == 0x40) && ($reg == 0x0200)) { + # I2C trigger + $i2c_hold = ($val & 0x40) == 0x40; + + if (!$i2c_hold && ($val & 0x01)) { + printf "$timestamp au0828 I2C write addr = 0x%02x (speed = %s) ", $i2c_addr, $i2c_speed; + printf "0x%02x ", $_ foreach (@i2c_sbuf); + print "\n"; + + @i2c_sbuf = (); + } + + next; + } + + if (($reqtype == 0xc0) && ($reg == 0x0201)) { + # Wait to be ready + next; + } + + + if (($reqtype == 0x40) && ($reg == 0x0205)) { + # I2C write data + push @i2c_sbuf, $val; + + next; + } + + if (($reqtype == 0xc0) && ($reg == 0x0209)) { + # I2C read data + my @bytes = split(/ /, $payload); + push @i2c_rbuf, hex($_) foreach(@bytes); + + if (!$i2c_hold) { + printf "$timestamp au0828 I2C read addr = 0x%02x (speed = %s, len=%d) ", $i2c_addr, $i2c_speed, scalar(@i2c_rbuf); + printf "0x%02x ", $_ foreach (@i2c_rbuf); + print "\n"; + + @i2c_rbuf = (); + } + next; + } + + printf("%s %s(0x%02x), Req 0x%02x, register 0x%04x, value 0x%04x, wlen %d: %s\n", + $timestamp, type_req($reqtype), $reqtype, $req, $reg, $val, $wlen, $payload); + } +} diff -Nru v4l-utils-1.0.0+r2263/contrib/freebsd/include/linux/input.h v4l-utils-1.0.0+r2364/contrib/freebsd/include/linux/input.h --- v4l-utils-1.0.0+r2263/contrib/freebsd/include/linux/input.h 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/contrib/freebsd/include/linux/input.h 2014-08-12 09:02:18.000000000 +0000 @@ -5,10 +5,9 @@ * under the terms of the GNU General Public License version 2 as published by * the Free Software Foundation. */ -#ifndef _UAPI_INPUT_H -#define _UAPI_INPUT_H +#ifndef _INPUT_H +#define _INPUT_H -#ifndef __KERNEL__ #include #include #include @@ -50,7 +49,6 @@ #else #include #endif -#endif /* @@ -498,7 +496,10 @@ #define KEY_VIDEO_NEXT 241 /* drive next video source */ #define KEY_VIDEO_PREV 242 /* drive previous video source */ #define KEY_BRIGHTNESS_CYCLE 243 /* brightness up, after max is min */ -#define KEY_BRIGHTNESS_ZERO 244 /* brightness off, use ambient */ +#define KEY_BRIGHTNESS_AUTO 244 /* Set Auto Brightness: manual + brightness control is off, + rely on ambient */ +#define KEY_BRIGHTNESS_ZERO KEY_BRIGHTNESS_AUTO #define KEY_DISPLAY_OFF 245 /* display device to off state */ #define KEY_WWAN 246 /* Wireless WAN (LTE, UMTS, GSM, etc.) */ @@ -668,6 +669,7 @@ #define KEY_ADDRESSBOOK 0x1ad /* AL Contacts/Address Book */ #define KEY_MESSENGER 0x1ae /* AL Instant Messaging */ #define KEY_DISPLAYTOGGLE 0x1af /* Turn display (LCD) on and off */ +#define KEY_BRIGHTNESS_TOGGLE KEY_DISPLAYTOGGLE #define KEY_SPELLCHECK 0x1b0 /* AL Spell Check */ #define KEY_LOGOFF 0x1b1 /* AL Logoff */ @@ -759,6 +761,17 @@ #define KEY_ALS_TOGGLE 0x230 /* Ambient light sensor */ +#define KEY_BUTTONCONFIG 0x240 /* AL Button Configuration */ +#define KEY_TASKMANAGER 0x241 /* AL Task/Project Manager */ +#define KEY_JOURNAL 0x242 /* AL Log/Journal/Timecard */ +#define KEY_CONTROLPANEL 0x243 /* AL Control Panel */ +#define KEY_APPSELECT 0x244 /* AL Select Task/Application */ +#define KEY_SCREENSAVER 0x245 /* AL Screen Saver */ +#define KEY_VOICECOMMAND 0x246 /* Listening Voice Command */ + +#define KEY_BRIGHTNESS_MIN 0x250 /* Set Brightness to Minimum */ +#define KEY_BRIGHTNESS_MAX 0x251 /* Set Brightness to Maximum */ + #define BTN_TRIGGER_HAPPY 0x2c0 #define BTN_TRIGGER_HAPPY1 0x2c0 #define BTN_TRIGGER_HAPPY2 0x2c1 @@ -1114,7 +1127,7 @@ struct ff_envelope envelope; __u32 custom_len; - __s16 __user *custom_data; + __s16 *custom_data; }; /** @@ -1209,4 +1222,4 @@ #define FF_MAX 0x7f #define FF_CNT (FF_MAX+1) -#endif /* _UAPI_INPUT_H */ +#endif /* _INPUT_H */ diff -Nru v4l-utils-1.0.0+r2263/contrib/freebsd/include/linux/ivtv.h v4l-utils-1.0.0+r2364/contrib/freebsd/include/linux/ivtv.h --- v4l-utils-1.0.0+r2263/contrib/freebsd/include/linux/ivtv.h 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/contrib/freebsd/include/linux/ivtv.h 2014-08-12 09:02:18.000000000 +0000 @@ -21,6 +21,7 @@ #ifndef __LINUX_IVTV_H__ #define __LINUX_IVTV_H__ + #include #include #include @@ -49,9 +50,9 @@ struct ivtv_dma_frame { enum v4l2_buf_type type; /* V4L2_BUF_TYPE_VIDEO_OUTPUT */ uint32_t pixelformat; /* 0 == same as destination */ - void *y_source; /* if NULL and type == V4L2_BUF_TYPE_VIDEO_OUTPUT, + void *y_source; /* if NULL and type == V4L2_BUF_TYPE_VIDEO_OUTPUT, then just switch to user DMA YUV output mode */ - void *uv_source; /* Unused for RGB pixelformats */ + void *uv_source; /* Unused for RGB pixelformats */ struct v4l2_rect src; struct v4l2_rect dst; uint32_t src_width; diff -Nru v4l-utils-1.0.0+r2263/contrib/freebsd/include/linux/uinput.h v4l-utils-1.0.0+r2364/contrib/freebsd/include/linux/uinput.h --- v4l-utils-1.0.0+r2263/contrib/freebsd/include/linux/uinput.h 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/contrib/freebsd/include/linux/uinput.h 2014-08-12 09:02:18.000000000 +0000 @@ -31,8 +31,8 @@ * 0.1 20/06/2002 * - first public version */ -#ifndef _UAPI__UINPUT_H_ -#define _UAPI__UINPUT_H_ +#ifndef __UINPUT_H_ +#define __UINPUT_H_ #include @@ -144,4 +144,4 @@ int32_t absfuzz[ABS_CNT]; int32_t absflat[ABS_CNT]; }; -#endif /* _UAPI__UINPUT_H_ */ +#endif /* __UINPUT_H_ */ diff -Nru v4l-utils-1.0.0+r2263/contrib/freebsd/include/linux/v4l2-controls.h v4l-utils-1.0.0+r2364/contrib/freebsd/include/linux/v4l2-controls.h --- v4l-utils-1.0.0+r2263/contrib/freebsd/include/linux/v4l2-controls.h 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/contrib/freebsd/include/linux/v4l2-controls.h 2014-08-12 09:02:18.000000000 +0000 @@ -61,6 +61,7 @@ #define V4L2_CTRL_CLASS_DV 0x00a00000 /* Digital Video controls */ #define V4L2_CTRL_CLASS_FM_RX 0x00a10000 /* FM Receiver controls */ #define V4L2_CTRL_CLASS_RF_TUNER 0x00a20000 /* RF tuner controls */ +#define V4L2_CTRL_CLASS_DETECT 0x00a30000 /* Detection controls */ /* User-class control IDs */ @@ -756,6 +757,15 @@ #define V4L2_CID_RDS_TX_PTY (V4L2_CID_FM_TX_CLASS_BASE + 3) #define V4L2_CID_RDS_TX_PS_NAME (V4L2_CID_FM_TX_CLASS_BASE + 5) #define V4L2_CID_RDS_TX_RADIO_TEXT (V4L2_CID_FM_TX_CLASS_BASE + 6) +#define V4L2_CID_RDS_TX_MONO_STEREO (V4L2_CID_FM_TX_CLASS_BASE + 7) +#define V4L2_CID_RDS_TX_ARTIFICIAL_HEAD (V4L2_CID_FM_TX_CLASS_BASE + 8) +#define V4L2_CID_RDS_TX_COMPRESSED (V4L2_CID_FM_TX_CLASS_BASE + 9) +#define V4L2_CID_RDS_TX_DYNAMIC_PTY (V4L2_CID_FM_TX_CLASS_BASE + 10) +#define V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT (V4L2_CID_FM_TX_CLASS_BASE + 11) +#define V4L2_CID_RDS_TX_TRAFFIC_PROGRAM (V4L2_CID_FM_TX_CLASS_BASE + 12) +#define V4L2_CID_RDS_TX_MUSIC_SPEECH (V4L2_CID_FM_TX_CLASS_BASE + 13) +#define V4L2_CID_RDS_TX_ALT_FREQS_ENABLE (V4L2_CID_FM_TX_CLASS_BASE + 14) +#define V4L2_CID_RDS_TX_ALT_FREQS (V4L2_CID_FM_TX_CLASS_BASE + 15) #define V4L2_CID_AUDIO_LIMITER_ENABLED (V4L2_CID_FM_TX_CLASS_BASE + 64) #define V4L2_CID_AUDIO_LIMITER_RELEASE_TIME (V4L2_CID_FM_TX_CLASS_BASE + 65) @@ -900,6 +910,12 @@ }; #define V4L2_CID_RDS_RECEPTION (V4L2_CID_FM_RX_CLASS_BASE + 2) +#define V4L2_CID_RDS_RX_PTY (V4L2_CID_FM_RX_CLASS_BASE + 3) +#define V4L2_CID_RDS_RX_PS_NAME (V4L2_CID_FM_RX_CLASS_BASE + 4) +#define V4L2_CID_RDS_RX_RADIO_TEXT (V4L2_CID_FM_RX_CLASS_BASE + 5) +#define V4L2_CID_RDS_RX_TRAFFIC_ANNOUNCEMENT (V4L2_CID_FM_RX_CLASS_BASE + 6) +#define V4L2_CID_RDS_RX_TRAFFIC_PROGRAM (V4L2_CID_FM_RX_CLASS_BASE + 7) +#define V4L2_CID_RDS_RX_MUSIC_SPEECH (V4L2_CID_FM_RX_CLASS_BASE + 8) #define V4L2_CID_RF_TUNER_CLASS_BASE (V4L2_CTRL_CLASS_RF_TUNER | 0x900) #define V4L2_CID_RF_TUNER_CLASS (V4L2_CTRL_CLASS_RF_TUNER | 1) @@ -914,4 +930,20 @@ #define V4L2_CID_RF_TUNER_IF_GAIN (V4L2_CID_RF_TUNER_CLASS_BASE + 62) #define V4L2_CID_RF_TUNER_PLL_LOCK (V4L2_CID_RF_TUNER_CLASS_BASE + 91) + +/* Detection-class control IDs defined by V4L2 */ +#define V4L2_CID_DETECT_CLASS_BASE (V4L2_CTRL_CLASS_DETECT | 0x900) +#define V4L2_CID_DETECT_CLASS (V4L2_CTRL_CLASS_DETECT | 1) + +#define V4L2_CID_DETECT_MD_MODE (V4L2_CID_DETECT_CLASS_BASE + 1) +enum v4l2_detect_md_mode { + V4L2_DETECT_MD_MODE_DISABLED = 0, + V4L2_DETECT_MD_MODE_GLOBAL = 1, + V4L2_DETECT_MD_MODE_THRESHOLD_GRID = 2, + V4L2_DETECT_MD_MODE_REGION_GRID = 3, +}; +#define V4L2_CID_DETECT_MD_GLOBAL_THRESHOLD (V4L2_CID_DETECT_CLASS_BASE + 2) +#define V4L2_CID_DETECT_MD_THRESHOLD_GRID (V4L2_CID_DETECT_CLASS_BASE + 3) +#define V4L2_CID_DETECT_MD_REGION_GRID (V4L2_CID_DETECT_CLASS_BASE + 4) + #endif diff -Nru v4l-utils-1.0.0+r2263/contrib/freebsd/include/linux/videodev2.h v4l-utils-1.0.0+r2364/contrib/freebsd/include/linux/videodev2.h --- v4l-utils-1.0.0+r2263/contrib/freebsd/include/linux/videodev2.h 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/contrib/freebsd/include/linux/videodev2.h 2014-08-12 09:02:18.000000000 +0000 @@ -53,10 +53,9 @@ * Hans Verkuil * et al. */ -#ifndef _UAPI__LINUX_VIDEODEV2_H -#define _UAPI__LINUX_VIDEODEV2_H +#ifndef __LINUX_VIDEODEV2_H +#define __LINUX_VIDEODEV2_H -#ifndef __KERNEL__ #include #include #include @@ -91,8 +90,7 @@ #endif #endif -#else -#include +#ifdef __KERNEL__ #include #include #endif @@ -158,6 +156,10 @@ (field) == V4L2_FIELD_INTERLACED_BT ||\ (field) == V4L2_FIELD_SEQ_TB ||\ (field) == V4L2_FIELD_SEQ_BT) +#define V4L2_FIELD_HAS_T_OR_B(field) \ + ((field) == V4L2_FIELD_BOTTOM ||\ + (field) == V4L2_FIELD_TOP ||\ + (field) == V4L2_FIELD_ALTERNATE) enum v4l2_buf_type { V4L2_BUF_TYPE_VIDEO_CAPTURE = 1, @@ -302,6 +304,7 @@ #define V4L2_CAP_MODULATOR 0x00080000 /* has a modulator */ #define V4L2_CAP_SDR_CAPTURE 0x00100000 /* Is a SDR capture device */ +#define V4L2_CAP_EXT_PIX_FORMAT 0x00200000 /* Supports the extended pixel format */ #define V4L2_CAP_READWRITE 0x01000000 /* read/write systemcalls */ #define V4L2_CAP_ASYNCIO 0x02000000 /* async I/O */ @@ -321,6 +324,7 @@ uint32_t sizeimage; uint32_t colorspace; /* enum v4l2_colorspace */ uint32_t priv; /* private data, depends on pixelformat */ + uint32_t flags; /* format flags (V4L2_PIX_FMT_FLAG_*) */ }; /* Pixel format FOURCC depth Description */ @@ -328,7 +332,11 @@ /* RGB formats */ #define V4L2_PIX_FMT_RGB332 v4l2_fourcc('R', 'G', 'B', '1') /* 8 RGB-3-3-2 */ #define V4L2_PIX_FMT_RGB444 v4l2_fourcc('R', '4', '4', '4') /* 16 xxxxrrrr ggggbbbb */ +#define V4L2_PIX_FMT_ARGB444 v4l2_fourcc('A', 'R', '1', '2') /* 16 aaaarrrr ggggbbbb */ +#define V4L2_PIX_FMT_XRGB444 v4l2_fourcc('X', 'R', '1', '2') /* 16 xxxxrrrr ggggbbbb */ #define V4L2_PIX_FMT_RGB555 v4l2_fourcc('R', 'G', 'B', 'O') /* 16 RGB-5-5-5 */ +#define V4L2_PIX_FMT_ARGB555 v4l2_fourcc('A', 'R', '1', '5') /* 16 ARGB-1-5-5-5 */ +#define V4L2_PIX_FMT_XRGB555 v4l2_fourcc('X', 'R', '1', '5') /* 16 XRGB-1-5-5-5 */ #define V4L2_PIX_FMT_RGB565 v4l2_fourcc('R', 'G', 'B', 'P') /* 16 RGB-5-6-5 */ #define V4L2_PIX_FMT_RGB555X v4l2_fourcc('R', 'G', 'B', 'Q') /* 16 RGB-5-5-5 BE */ #define V4L2_PIX_FMT_RGB565X v4l2_fourcc('R', 'G', 'B', 'R') /* 16 RGB-5-6-5 BE */ @@ -336,7 +344,11 @@ #define V4L2_PIX_FMT_BGR24 v4l2_fourcc('B', 'G', 'R', '3') /* 24 BGR-8-8-8 */ #define V4L2_PIX_FMT_RGB24 v4l2_fourcc('R', 'G', 'B', '3') /* 24 RGB-8-8-8 */ #define V4L2_PIX_FMT_BGR32 v4l2_fourcc('B', 'G', 'R', '4') /* 32 BGR-8-8-8-8 */ +#define V4L2_PIX_FMT_ABGR32 v4l2_fourcc('A', 'R', '2', '4') /* 32 BGRA-8-8-8-8 */ +#define V4L2_PIX_FMT_XBGR32 v4l2_fourcc('X', 'R', '2', '4') /* 32 BGRX-8-8-8-8 */ #define V4L2_PIX_FMT_RGB32 v4l2_fourcc('R', 'G', 'B', '4') /* 32 RGB-8-8-8-8 */ +#define V4L2_PIX_FMT_ARGB32 v4l2_fourcc('B', 'A', '2', '4') /* 32 ARGB-8-8-8-8 */ +#define V4L2_PIX_FMT_XRGB32 v4l2_fourcc('B', 'X', '2', '4') /* 32 XRGB-8-8-8-8 */ /* Grey formats */ #define V4L2_PIX_FMT_GREY v4l2_fourcc('G', 'R', 'E', 'Y') /* 8 Greyscale */ @@ -473,6 +485,15 @@ /* SDR formats - used only for Software Defined Radio devices */ #define V4L2_SDR_FMT_CU8 v4l2_fourcc('C', 'U', '0', '8') /* IQ u8 */ #define V4L2_SDR_FMT_CU16LE v4l2_fourcc('C', 'U', '1', '6') /* IQ u16le */ +#define V4L2_SDR_FMT_CS8 v4l2_fourcc('C', 'S', '0', '8') /* complex s8 */ +#define V4L2_SDR_FMT_CS14LE v4l2_fourcc('C', 'S', '1', '4') /* complex s14le */ +#define V4L2_SDR_FMT_RU12LE v4l2_fourcc('R', 'U', '1', '2') /* real u12le */ + +/* priv field value to indicates that subsequent fields are valid. */ +#define V4L2_PIX_FMT_PRIV_MAGIC 0xfeedcafe + +/* Flags */ +#define V4L2_PIX_FMT_FLAG_PREMUL_ALPHA 0x00000001 /* * F O R M A T E N U M E R A T I O N @@ -778,7 +799,16 @@ /* FIXME: in theory we should pass something like PCI device + memory * region + offset instead of some physical address */ void *base; - struct v4l2_pix_format fmt; + struct { + uint32_t width; + uint32_t height; + uint32_t pixelformat; + uint32_t field; /* enum v4l2_field */ + uint32_t bytesperline; /* for padding, zero if unused */ + uint32_t sizeimage; + uint32_t colorspace; /* enum v4l2_colorspace */ + uint32_t priv; /* reserved field, set to 0 */ + } fmt; }; /* Flags for the 'capability' field. Read only */ #define V4L2_FBUF_CAP_EXTERNOVERLAY 0x0001 @@ -800,16 +830,16 @@ struct v4l2_clip { struct v4l2_rect c; - struct v4l2_clip *next; + struct v4l2_clip *next; }; struct v4l2_window { struct v4l2_rect w; uint32_t field; /* enum v4l2_field */ uint32_t chromakey; - struct v4l2_clip *clips; + struct v4l2_clip *clips; uint32_t clipcount; - void *bitmap; + void *bitmap; uint8_t global_alpha; }; @@ -1288,6 +1318,10 @@ int32_t value; int64_t value64; char *string; + uint8_t *p_u8; + uint16_t *p_u16; + uint32_t *p_u32; + void *ptr; }; } __attribute__ ((packed)); @@ -1302,6 +1336,7 @@ #define V4L2_CTRL_ID_MASK (0x0fffffff) #define V4L2_CTRL_ID2CLASS(id) ((id) & 0x0fff0000UL) #define V4L2_CTRL_DRIVER_PRIV(id) (((id) & 0xffff) >= 0x1000) +#define V4L2_CTRL_MAX_DIMS (4) enum v4l2_ctrl_type { V4L2_CTRL_TYPE_INTEGER = 1, @@ -1312,7 +1347,13 @@ V4L2_CTRL_TYPE_CTRL_CLASS = 6, V4L2_CTRL_TYPE_STRING = 7, V4L2_CTRL_TYPE_BITMASK = 8, - V4L2_CTRL_TYPE_INTEGER_MENU = 9, + V4L2_CTRL_TYPE_INTEGER_MENU = 9, + + /* Compound types are >= 0x0100 */ + V4L2_CTRL_COMPOUND_TYPES = 0x0100, + V4L2_CTRL_TYPE_U8 = 0x0100, + V4L2_CTRL_TYPE_U16 = 0x0101, + V4L2_CTRL_TYPE_U32 = 0x0102, }; /* Used in the VIDIOC_QUERYCTRL ioctl for querying controls */ @@ -1328,6 +1369,23 @@ uint32_t reserved[2]; }; +/* Used in the VIDIOC_QUERY_EXT_CTRL ioctl for querying extended controls */ +struct v4l2_query_ext_ctrl { + uint32_t id; + uint32_t type; + char name[32]; + int64_t minimum; + int64_t maximum; + uint64_t step; + int64_t default_value; + uint32_t flags; + uint32_t elem_size; + uint32_t elems; + uint32_t nr_of_dims; + uint32_t dims[V4L2_CTRL_MAX_DIMS]; + uint32_t reserved[32]; +}; + /* Used in the VIDIOC_QUERYMENU ioctl for querying menu items */ struct v4l2_querymenu { uint32_t id; @@ -1348,9 +1406,11 @@ #define V4L2_CTRL_FLAG_SLIDER 0x0020 #define V4L2_CTRL_FLAG_WRITE_ONLY 0x0040 #define V4L2_CTRL_FLAG_VOLATILE 0x0080 +#define V4L2_CTRL_FLAG_HAS_PAYLOAD 0x0100 -/* Query flag, to be ORed with the control ID */ +/* Query flags, to be ORed with the control ID */ #define V4L2_CTRL_FLAG_NEXT_CTRL 0x80000000 +#define V4L2_CTRL_FLAG_NEXT_COMPOUND 0x40000000 /* User-class control IDs defined by V4L2 */ #define V4L2_CID_MAX_CTRLS 1024 @@ -1616,6 +1676,12 @@ #define V4L2_VBI_UNSYNC (1 << 0) #define V4L2_VBI_INTERLACED (1 << 1) +/* ITU-R start lines for each field */ +#define V4L2_VBI_ITU_525_F1_START (1) +#define V4L2_VBI_ITU_525_F2_START (264) +#define V4L2_VBI_ITU_625_F1_START (1) +#define V4L2_VBI_ITU_625_F2_START (314) + /* Sliced VBI * * This implements is a proposal V4L2 API to allow SLICED VBI @@ -1739,6 +1805,7 @@ * @colorspace: enum v4l2_colorspace; supplemental to pixelformat * @plane_fmt: per-plane information * @num_planes: number of planes for this format + * @flags: format flags (V4L2_PIX_FMT_FLAG_*) */ struct v4l2_pix_format_mplane { uint32_t width; @@ -1749,16 +1816,19 @@ struct v4l2_plane_pix_format plane_fmt[VIDEO_MAX_PLANES]; uint8_t num_planes; - uint8_t reserved[11]; + uint8_t flags; + uint8_t reserved[10]; } __attribute__ ((packed)); /** * struct v4l2_sdr_format - SDR format definition * @pixelformat: little endian four character code (fourcc) + * @buffersize: maximum size in bytes required for data */ struct v4l2_sdr_format { uint32_t pixelformat; - uint8_t reserved[28]; + uint32_t buffersize; + uint8_t reserved[24]; } __attribute__ ((packed)); /** @@ -1805,6 +1875,7 @@ #define V4L2_EVENT_CTRL 3 #define V4L2_EVENT_FRAME_SYNC 4 #define V4L2_EVENT_SOURCE_CHANGE 5 +#define V4L2_EVENT_MOTION_DET 6 #define V4L2_EVENT_PRIVATE_START 0x08000000 /* Payload for V4L2_EVENT_VSYNC */ @@ -1842,6 +1913,21 @@ uint32_t changes; }; +#define V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ (1 << 0) + +/** + * struct v4l2_event_motion_det - motion detection event + * @flags: if V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ is set, then the + * frame_sequence field is valid. + * @frame_sequence: the frame sequence number associated with this event. + * @region_mask: which regions detected motion. + */ +struct v4l2_event_motion_det { + uint32_t flags; + uint32_t frame_sequence; + uint32_t region_mask; +}; + struct v4l2_event { uint32_t type; union { @@ -1849,6 +1935,7 @@ struct v4l2_event_ctrl ctrl; struct v4l2_event_frame_sync frame_sync; struct v4l2_event_src_change src_change; + struct v4l2_event_motion_det motion_det; uint8_t data[64]; } u; uint32_t pending; @@ -2039,9 +2126,11 @@ Never use these in applications! */ #define VIDIOC_DBG_G_CHIP_INFO _IOWR('V', 102, struct v4l2_dbg_chip_info) +#define VIDIOC_QUERY_EXT_CTRL _IOWR('V', 103, struct v4l2_query_ext_ctrl) + /* Reminder: when adding new ioctls please add support for them to drivers/media/video/v4l2-compat-ioctl32.c as well! */ #define BASE_VIDIOC_PRIVATE 192 /* 192-255 are private */ -#endif /* _UAPI__LINUX_VIDEODEV2_H */ +#endif /* __LINUX_VIDEODEV2_H */ diff -Nru v4l-utils-1.0.0+r2263/contrib/freebsd/Makefile.am v4l-utils-1.0.0+r2364/contrib/freebsd/Makefile.am --- v4l-utils-1.0.0+r2263/contrib/freebsd/Makefile.am 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/contrib/freebsd/Makefile.am 2014-08-12 09:02:18.000000000 +0000 @@ -5,12 +5,12 @@ sync-with-kernel: rm -rf .pc - for i in input.h ivtv.h uinput.h videodev2.h v4l2-controls.h v4l2-common.h do \ + for i in input.h ivtv.h uinput.h videodev2.h v4l2-controls.h v4l2-common.h; do \ mkdir -p include/linux/$$(dirname $$i); \ cp $(KERNEL_DIR)/usr/include/linux/$$i include/linux/$$i; \ done - for i in ivtv.h uinput.h videodev2.h v4l2-common.h do \ + for i in ivtv.h uinput.h videodev2.h v4l2-common.h; do \ sed -e 's/__u8/uint8_t/g' -e 's/__u16/uint16_t/g' -e 's/__u32/uint32_t/g' -e 's/__u64/uint64_t/g' -e 's/__s8/int8_t/g' -e 's/__s16/int16_t/g' -e 's/__s32/int32_t/g' -e 's/__s64/int64_t/g' -e 's/__le32/uint32_t/g' -e 's/__user//g' -i include/linux/$$i; \ done diff -Nru v4l-utils-1.0.0+r2263/contrib/test/ioctl_32.h v4l-utils-1.0.0+r2364/contrib/test/ioctl_32.h --- v4l-utils-1.0.0+r2263/contrib/test/ioctl_32.h 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/contrib/test/ioctl_32.h 2014-08-12 09:02:18.000000000 +0000 @@ -83,6 +83,7 @@ #define CMD32_VIDIOC_QUERYMENU 0xc02c5625 #define CMD32_VIDIOC_QUERYSTD 0x8008563f #define CMD32_VIDIOC_QUERY_DV_TIMINGS 0x80845663 +#define CMD32_VIDIOC_QUERY_EXT_CTRL 0xc0e85667 #define CMD32_VIDIOC_REQBUFS 0xc0145608 #define CMD32_VIDIOC_RESERVED 0x5601 #define CMD32_VIDIOC_STREAMOFF 0x40045613 diff -Nru v4l-utils-1.0.0+r2263/contrib/test/ioctl_64.h v4l-utils-1.0.0+r2364/contrib/test/ioctl_64.h --- v4l-utils-1.0.0+r2263/contrib/test/ioctl_64.h 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/contrib/test/ioctl_64.h 2014-08-12 09:02:18.000000000 +0000 @@ -83,6 +83,7 @@ #define CMD64_VIDIOC_QUERYMENU 0xc02c5625 #define CMD64_VIDIOC_QUERYSTD 0x8008563f #define CMD64_VIDIOC_QUERY_DV_TIMINGS 0x80845663 +#define CMD64_VIDIOC_QUERY_EXT_CTRL 0xc0e85667 #define CMD64_VIDIOC_REQBUFS 0xc0145608 #define CMD64_VIDIOC_RESERVED 0x5601 #define CMD64_VIDIOC_STREAMOFF 0x40045613 diff -Nru v4l-utils-1.0.0+r2263/contrib/test/ioctl-test.h v4l-utils-1.0.0+r2364/contrib/test/ioctl-test.h --- v4l-utils-1.0.0+r2263/contrib/test/ioctl-test.h 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/contrib/test/ioctl-test.h 2014-08-12 09:02:18.000000000 +0000 @@ -57,6 +57,7 @@ struct v4l2_jpegcompression p_v4l2_jpegcompression; struct v4l2_modulator p_v4l2_modulator; struct v4l2_output p_v4l2_output; + struct v4l2_query_ext_ctrl p_v4l2_query_ext_ctrl; struct v4l2_queryctrl p_v4l2_queryctrl; struct v4l2_querymenu p_v4l2_querymenu; struct v4l2_requestbuffers p_v4l2_requestbuffers; @@ -167,6 +168,7 @@ ioc(video, VIDIOC_QUERYMENU), /* struct v4l2_querymenu */ ioc(video, VIDIOC_QUERYSTD), /* v4l2_std_id */ ioc(video, VIDIOC_QUERY_DV_TIMINGS), /* struct v4l2_dv_timings */ + ioc(video, VIDIOC_QUERY_EXT_CTRL), /* struct v4l2_query_ext_ctrl */ ioc(video, VIDIOC_REQBUFS), /* struct v4l2_requestbuffers */ ioc(video, VIDIOC_RESERVED), /* void */ ioc(video, VIDIOC_STREAMOFF), /* int */ diff -Nru v4l-utils-1.0.0+r2263/contrib/test/Makefile.am v4l-utils-1.0.0+r2364/contrib/test/Makefile.am --- v4l-utils-1.0.0+r2263/contrib/test/Makefile.am 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/contrib/test/Makefile.am 2014-08-12 09:02:18.000000000 +0000 @@ -23,7 +23,7 @@ pixfmt_test_LDFLAGS = $(X11_LIBS) v4l2grab_SOURCES = v4l2grab.c -v4l2grab_LDADD = ../../lib/libv4l2/libv4l2.la ../../lib/libv4lconvert/libv4lconvert.la +v4l2grab_LDADD = ../../lib/libv4l2/libv4l2.la ../../lib/libv4lconvert/libv4lconvert.la -lpthread v4l2gl_SOURCES = v4l2gl.c v4l2gl_LDFLAGS = $(X11_LIBS) $(GL_LIBS) $(GLU_LIBS) diff -Nru v4l-utils-1.0.0+r2263/contrib/test/v4l2grab.c v4l-utils-1.0.0+r2364/contrib/test/v4l2grab.c --- v4l-utils-1.0.0+r2263/contrib/test/v4l2grab.c 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/contrib/test/v4l2grab.c 2014-08-12 09:02:18.000000000 +0000 @@ -24,8 +24,10 @@ #include #include "../../lib/include/libv4l2.h" #include +#include -#define CLEAR(x) memset(&(x), 0, sizeof(x)) +#define CLEAR_P(x,s) memset((x), 0, s) +#define CLEAR(x) CLEAR_P(&(x), sizeof(x)) struct buffer { void *start; @@ -46,22 +48,206 @@ } } +/* Used by the multi thread capture version */ +struct buffer_queue { + struct v4l2_buffer *buffers; + int buffers_size; + + int read_pos; + int write_pos; + int n_frames; + + int fd; + + pthread_mutex_t mutex; + pthread_cond_t buffer_cond; +}; + +/* Gets a buffer and puts it in the buffers list at write position, then + * notifies the consumer that a new buffer is ready to be used */ +static void *produce_buffer (void * p) +{ + struct buffer_queue *bq; + fd_set fds; + struct timeval tv; + int i; + struct v4l2_buffer *buf; + int r; + + bq = p; + + for (i = 0; i < bq->n_frames; i++) { + printf ("Prod: %d\n", i); + buf = &bq->buffers[bq->write_pos % bq->buffers_size]; + do { + FD_ZERO(&fds); + FD_SET(bq->fd, &fds); + + /* Timeout. */ + tv.tv_sec = 2; + tv.tv_usec = 0; + + r = select(bq->fd + 1, &fds, NULL, NULL, &tv); + } while ((r == -1 && (errno == EINTR))); + if (r == -1) { + perror("select"); + pthread_exit (NULL); + return NULL; + } + + CLEAR_P(buf, sizeof(struct v4l2_buffer)); + buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf->memory = V4L2_MEMORY_MMAP; + xioctl(bq->fd, VIDIOC_DQBUF, buf); + + pthread_mutex_lock (&bq->mutex); + bq->write_pos++; + printf ("Prod: %d (done)\n", i); + pthread_cond_signal (&bq->buffer_cond); + pthread_mutex_unlock (&bq->mutex); + + } + + pthread_exit (NULL); +} + +/* will create a separate thread that will produce the buffers and put + * into a circular array while this same thread will get the buffers from + * this array and 'render' them */ +static int capture_threads (int fd, struct buffer *buffers, int bufpool_size, + struct v4l2_format fmt, int n_frames, + char *out_dir, int sleep_ms) +{ + struct v4l2_buffer buf; + unsigned int i; + struct buffer_queue buf_queue; + pthread_t producer; + char out_name[25 + strlen(out_dir)]; + FILE *fout; + struct timespec sleeptime; + + if (sleep_ms) { + sleeptime.tv_sec = sleep_ms / 1000; + sleeptime.tv_nsec = (sleep_ms % 1000) * 1000000; + } + + buf_queue.buffers_size = bufpool_size * 2; + buf_queue.buffers = calloc(buf_queue.buffers_size, + sizeof(struct v4l2_buffer)); + buf_queue.fd = fd; + buf_queue.read_pos = 0; + buf_queue.write_pos = 0; + buf_queue.n_frames = n_frames; + pthread_mutex_init (&buf_queue.mutex, NULL); + pthread_cond_init (&buf_queue.buffer_cond, NULL); + + pthread_create (&producer, NULL, produce_buffer, &buf_queue); + + for (i = 0; i < n_frames; i++) { + printf ("Read: %d\n", i); + + /* wait for a buffer to be available in the queue */ + pthread_mutex_lock (&buf_queue.mutex); + while (buf_queue.read_pos == buf_queue.write_pos) { + pthread_cond_wait (&buf_queue.buffer_cond, + &buf_queue.mutex); + } + pthread_mutex_unlock (&buf_queue.mutex); + + if (sleep_ms) + nanosleep (&sleeptime, NULL); + + sprintf(out_name, "%s/out%03d.ppm", out_dir, i); + fout = fopen(out_name, "w"); + if (!fout) { + perror("Cannot open image"); + exit(EXIT_FAILURE); + } + fprintf(fout, "P6\n%d %d 255\n", + fmt.fmt.pix.width, fmt.fmt.pix.height); + buf = buf_queue.buffers[buf_queue.read_pos % + buf_queue.buffers_size]; + fwrite(buffers[buf.index].start, buf.bytesused, 1, fout); + fclose(fout); + + xioctl(fd, VIDIOC_QBUF, &buf); + + pthread_mutex_lock (&buf_queue.mutex); + buf_queue.read_pos++; + printf ("Read: %d (done)\n", i); + pthread_cond_signal (&buf_queue.buffer_cond); + pthread_mutex_unlock (&buf_queue.mutex); + } + + pthread_mutex_destroy (&buf_queue.mutex); + pthread_cond_destroy (&buf_queue.buffer_cond); + free (buf_queue.buffers); + return 0; +} + +static int capture_loop (int fd, struct buffer *buffers, struct v4l2_format fmt, + int n_frames, char *out_dir) +{ + struct v4l2_buffer buf; + unsigned int i; + struct timeval tv; + int r; + fd_set fds; + FILE *fout; + char out_name[25 + strlen(out_dir)]; + + for (i = 0; i < n_frames; i++) { + do { + FD_ZERO(&fds); + FD_SET(fd, &fds); + + /* Timeout. */ + tv.tv_sec = 2; + tv.tv_usec = 0; + + r = select(fd + 1, &fds, NULL, NULL, &tv); + } while ((r == -1 && (errno == EINTR))); + if (r == -1) { + perror("select"); + return errno; + } + + CLEAR(buf); + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + xioctl(fd, VIDIOC_DQBUF, &buf); + + sprintf(out_name, "%s/out%03d.ppm", out_dir, i); + fout = fopen(out_name, "w"); + if (!fout) { + perror("Cannot open image"); + exit(EXIT_FAILURE); + } + fprintf(fout, "P6\n%d %d 255\n", + fmt.fmt.pix.width, fmt.fmt.pix.height); + fwrite(buffers[buf.index].start, buf.bytesused, 1, fout); + fclose(fout); + + xioctl(fd, VIDIOC_QBUF, &buf); + } + return 0; +} + static int capture(char *dev_name, int x_res, int y_res, int n_frames, - char *out_dir) + char *out_dir, int block, int threads, int sleep_ms) { struct v4l2_format fmt; struct v4l2_buffer buf; struct v4l2_requestbuffers req; enum v4l2_buf_type type; - fd_set fds; - struct timeval tv; - int r, fd = -1; + int fd = -1; unsigned int i, n_buffers; - char out_name[25 + strlen(out_dir)]; - FILE *fout; struct buffer *buffers; - fd = v4l2_open(dev_name, O_RDWR | O_NONBLOCK, 0); + if (block) + fd = v4l2_open(dev_name, O_RDWR, 0); + else + fd = v4l2_open(dev_name, O_RDWR | O_NONBLOCK, 0); if (fd < 0) { perror("Cannot open device"); exit(EXIT_FAILURE); @@ -119,40 +305,11 @@ type = V4L2_BUF_TYPE_VIDEO_CAPTURE; xioctl(fd, VIDIOC_STREAMON, &type); - for (i = 0; i < n_frames; i++) { - do { - FD_ZERO(&fds); - FD_SET(fd, &fds); - - /* Timeout. */ - tv.tv_sec = 2; - tv.tv_usec = 0; - - r = select(fd + 1, &fds, NULL, NULL, &tv); - } while ((r == -1 && (errno == EINTR))); - if (r == -1) { - perror("select"); - return errno; - } - - CLEAR(buf); - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_MMAP; - xioctl(fd, VIDIOC_DQBUF, &buf); - - sprintf(out_name, "%s/out%03d.ppm", out_dir, i); - fout = fopen(out_name, "w"); - if (!fout) { - perror("Cannot open image"); - exit(EXIT_FAILURE); - } - fprintf(fout, "P6\n%d %d 255\n", - fmt.fmt.pix.width, fmt.fmt.pix.height); - fwrite(buffers[buf.index].start, buf.bytesused, 1, fout); - fclose(fout); - - xioctl(fd, VIDIOC_QBUF, &buf); - } + if (threads) + capture_threads(fd, buffers, 2, fmt, n_frames, out_dir, + sleep_ms); + else + capture_loop(fd, buffers, fmt, n_frames, out_dir); type = V4L2_BUF_TYPE_VIDEO_CAPTURE; xioctl(fd, VIDIOC_STREAMOFF, &type); @@ -179,6 +336,9 @@ {"xres", 'x', "XRES", 0, "horizontal resolution", 0}, {"yres", 'y', "YRES", 0, "vertical resolution", 0}, {"n-frames", 'n', "NFRAMES", 0, "number of frames to capture", 0}, + {"thread-enable", 't', "THREADS", 0, "if different threads should capture and save", 0}, + {"blockmode-enable", 'b', "BLOCKMODE", 0, "if blocking mode should be used", 0}, + {"sleep-time", 's', "SLEEP", 0, "how long should the consumer thread sleep to simulate the processing of a buffer (in ms)"}, { 0, 0, 0, 0, 0, 0 } }; @@ -188,6 +348,9 @@ static int x_res = 640; static int y_res = 480; static int n_frames = 20; +static int threads = 0; +static int block = 0; +static int sleep_ms = 0; static error_t parse_opt(int k, char *arg, struct argp_state *state) { @@ -215,6 +378,17 @@ if (val) n_frames = val; break; + case 't': + threads = 1; + break; + case 'b': + block = 1; + break; + case 's': + val = atoi(arg); + if (val) + sleep_ms = val; + break; default: return ARGP_ERR_UNKNOWN; } @@ -232,5 +406,6 @@ { argp_parse(&argp, argc, argv, 0, 0, 0); - return capture(dev_name, x_res, y_res, n_frames, out_dir); + return capture(dev_name, x_res, y_res, n_frames, out_dir, block, + threads, sleep_ms); } diff -Nru v4l-utils-1.0.0+r2263/contrib/usb_parse/parse_usb.pl v4l-utils-1.0.0+r2364/contrib/usb_parse/parse_usb.pl --- v4l-utils-1.0.0+r2263/contrib/usb_parse/parse_usb.pl 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/contrib/usb_parse/parse_usb.pl 2014-08-12 09:02:18.000000000 +0000 @@ -61,16 +61,19 @@ } while (<>) { - tr/A-F/a-f/; - if (m/([0-9a-f].) ([0-9a-f].) ([0-9a-f].) ([0-9a-f].) ([0-9a-f].) ([0-9a-f].) ([0-9a-f].) ([0-9a-f].)[\<\>\s]+(.*)/) { - my $reqtype = hex($1); - my $req = hex($2); - my $wvalue = hex("$4$3"); - my $windex = hex("$6$5"); - my $wlen = hex("$8$7"); - my $payload = $9; + if (m/(.*)([0-9a-f].) ([0-9a-f].) ([0-9a-f].) ([0-9a-f].) ([0-9a-f].) ([0-9a-f].) ([0-9a-f].) ([0-9a-f].)[\<\>\s]+(.*)/) { + my $timestamp = $1; + my $reqtype = hex($2); + my $req = hex($3); + my $wvalue = hex("$5$4"); + my $windex = hex("$7$6"); + my $wlen = hex("$9$8"); + my $payload = $10; - printf("%s, Req %3d, wValue: 0x%04x, wIndex 0x%04x, wlen %d: %s\n", - type_req($reqtype), $req, $wvalue, $windex, $wlen, $payload); + $timestamp =~ s/^\s+//; + $timestamp =~ s/\s+$//; + + printf("%s %s(0x%02x), Req 0x%02x, wValue: 0x%04x, wIndex 0x%04x, wlen %d: %s\n", + $timestamp, type_req($reqtype), $reqtype, $req, $wvalue, $windex, $wlen, $payload); } } diff -Nru v4l-utils-1.0.0+r2263/debian/bzr-builder.manifest v4l-utils-1.0.0+r2364/debian/bzr-builder.manifest --- v4l-utils-1.0.0+r2263/debian/bzr-builder.manifest 2014-07-17 01:36:34.000000000 +0000 +++ v4l-utils-1.0.0+r2364/debian/bzr-builder.manifest 2014-08-12 09:02:19.000000000 +0000 @@ -1,3 +1,3 @@ -# bzr-builder format 0.3 deb-version {debupstream}+r2263-62 -lp:libv4l revid:git-v1:a284f948921ba322a503dd172ed1bed50c4c09f4 +# bzr-builder format 0.3 deb-version {debupstream}+r2364-62 +lp:libv4l revid:git-v1:02b4e94eed8ae396e0b10a67e49acc2e0d4194de nest packaging lp:~libv4l/+junk/packaging debian revid:gjasny@googlemail.com-20130802220052-qsxdry1avvfrb27o diff -Nru v4l-utils-1.0.0+r2263/debian/changelog v4l-utils-1.0.0+r2364/debian/changelog --- v4l-utils-1.0.0+r2263/debian/changelog 2014-07-17 01:36:34.000000000 +0000 +++ v4l-utils-1.0.0+r2364/debian/changelog 2014-08-12 09:02:19.000000000 +0000 @@ -1,8 +1,8 @@ -v4l-utils (1.0.0+r2263-62~ubuntu13.10.1) saucy; urgency=low +v4l-utils (1.0.0+r2364-62~ubuntu13.10.1) saucy; urgency=low * Auto build. - -- Launchpad Package Builder Thu, 17 Jul 2014 01:36:34 +0000 + -- Launchpad Package Builder Tue, 12 Aug 2014 09:02:19 +0000 v4l-utils (1.0.0-1) unstable; urgency=low diff -Nru v4l-utils-1.0.0+r2263/include/linux/dvb/dmx.h v4l-utils-1.0.0+r2364/include/linux/dvb/dmx.h --- v4l-utils-1.0.0+r2263/include/linux/dvb/dmx.h 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/include/linux/dvb/dmx.h 2014-08-12 09:02:18.000000000 +0000 @@ -21,13 +21,11 @@ * */ -#ifndef _UAPI_DVBDMX_H_ -#define _UAPI_DVBDMX_H_ +#ifndef _DVBDMX_H_ +#define _DVBDMX_H_ #include -#ifndef __KERNEL__ #include -#endif #define DMX_FILTER_SIZE 16 @@ -152,4 +150,4 @@ #define DMX_ADD_PID _IOW('o', 51, __u16) #define DMX_REMOVE_PID _IOW('o', 52, __u16) -#endif /* _UAPI_DVBDMX_H_ */ +#endif /* _DVBDMX_H_ */ diff -Nru v4l-utils-1.0.0+r2263/include/linux/dvb/frontend.h v4l-utils-1.0.0+r2364/include/linux/dvb/frontend.h --- v4l-utils-1.0.0+r2263/include/linux/dvb/frontend.h 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/include/linux/dvb/frontend.h 2014-08-12 09:02:18.000000000 +0000 @@ -197,7 +197,6 @@ TRANSMISSION_MODE_C3780, } fe_transmit_mode_t; -#if defined(__DVB_CORE__) || !defined (__KERNEL__) typedef enum fe_bandwidth { BANDWIDTH_8_MHZ, BANDWIDTH_7_MHZ, @@ -207,7 +206,6 @@ BANDWIDTH_10_MHZ, BANDWIDTH_1_712_MHZ, } fe_bandwidth_t; -#endif typedef enum fe_guard_interval { GUARD_INTERVAL_1_32, @@ -239,7 +237,6 @@ INTERLEAVING_720, }; -#if defined(__DVB_CORE__) || !defined (__KERNEL__) struct dvb_qpsk_parameters { __u32 symbol_rate; /* symbol rate in Symbols per second */ fe_code_rate_t fec_inner; /* forward error correction (see above) */ @@ -282,7 +279,6 @@ fe_status_t status; struct dvb_frontend_parameters parameters; }; -#endif /* S2API Commands */ #define DTV_UNDEFINED 0 diff -Nru v4l-utils-1.0.0+r2263/include/linux/dvb/video.h v4l-utils-1.0.0+r2364/include/linux/dvb/video.h --- v4l-utils-1.0.0+r2263/include/linux/dvb/video.h 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/include/linux/dvb/video.h 2014-08-12 09:02:18.000000000 +0000 @@ -21,14 +21,12 @@ * */ -#ifndef _UAPI_DVBVIDEO_H_ -#define _UAPI_DVBVIDEO_H_ +#ifndef _DVBVIDEO_H_ +#define _DVBVIDEO_H_ #include -#ifndef __KERNEL__ #include #include -#endif typedef enum { VIDEO_FORMAT_4_3, /* Select 4:3 format */ @@ -154,7 +152,7 @@ struct video_still_picture { - char __user *iFrame; /* pointer to a single iframe in memory */ + char *iFrame; /* pointer to a single iframe in memory */ __s32 size; }; @@ -187,7 +185,7 @@ typedef struct video_spu_palette { /* SPU Palette information */ int length; - __u8 __user *palette; + __u8 *palette; } video_spu_palette_t; @@ -271,4 +269,4 @@ #define VIDEO_COMMAND _IOWR('o', 59, struct video_command) #define VIDEO_TRY_COMMAND _IOWR('o', 60, struct video_command) -#endif /* _UAPI_DVBVIDEO_H_ */ +#endif /* _DVBVIDEO_H_ */ diff -Nru v4l-utils-1.0.0+r2263/include/linux/fb.h v4l-utils-1.0.0+r2364/include/linux/fb.h --- v4l-utils-1.0.0+r2263/include/linux/fb.h 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/include/linux/fb.h 2014-08-12 09:02:18.000000000 +0000 @@ -1,5 +1,5 @@ -#ifndef _UAPI_LINUX_FB_H -#define _UAPI_LINUX_FB_H +#ifndef _LINUX_FB_H +#define _LINUX_FB_H #include #include @@ -16,9 +16,7 @@ #define FBIOGETCMAP 0x4604 #define FBIOPUTCMAP 0x4605 #define FBIOPAN_DISPLAY 0x4606 -#ifndef __KERNEL__ #define FBIO_CURSOR _IOWR('F', 0x08, struct fb_cursor) -#endif /* 0x4607-0x460B are defined below */ /* #define FBIOGET_MONITORSPEC 0x460C */ /* #define FBIOPUT_MONITORSPEC 0x460D */ @@ -399,4 +397,4 @@ #endif -#endif /* _UAPI_LINUX_FB_H */ +#endif /* _LINUX_FB_H */ diff -Nru v4l-utils-1.0.0+r2263/include/linux/ivtv.h v4l-utils-1.0.0+r2364/include/linux/ivtv.h --- v4l-utils-1.0.0+r2263/include/linux/ivtv.h 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/include/linux/ivtv.h 2014-08-12 09:02:18.000000000 +0000 @@ -21,7 +21,7 @@ #ifndef __LINUX_IVTV_H__ #define __LINUX_IVTV_H__ -#include + #include #include @@ -49,9 +49,9 @@ struct ivtv_dma_frame { enum v4l2_buf_type type; /* V4L2_BUF_TYPE_VIDEO_OUTPUT */ __u32 pixelformat; /* 0 == same as destination */ - void __user *y_source; /* if NULL and type == V4L2_BUF_TYPE_VIDEO_OUTPUT, + void *y_source; /* if NULL and type == V4L2_BUF_TYPE_VIDEO_OUTPUT, then just switch to user DMA YUV output mode */ - void __user *uv_source; /* Unused for RGB pixelformats */ + void *uv_source; /* Unused for RGB pixelformats */ struct v4l2_rect src; struct v4l2_rect dst; __u32 src_width; diff -Nru v4l-utils-1.0.0+r2263/include/linux/v4l2-controls.h v4l-utils-1.0.0+r2364/include/linux/v4l2-controls.h --- v4l-utils-1.0.0+r2263/include/linux/v4l2-controls.h 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/include/linux/v4l2-controls.h 2014-08-12 09:02:18.000000000 +0000 @@ -61,6 +61,7 @@ #define V4L2_CTRL_CLASS_DV 0x00a00000 /* Digital Video controls */ #define V4L2_CTRL_CLASS_FM_RX 0x00a10000 /* FM Receiver controls */ #define V4L2_CTRL_CLASS_RF_TUNER 0x00a20000 /* RF tuner controls */ +#define V4L2_CTRL_CLASS_DETECT 0x00a30000 /* Detection controls */ /* User-class control IDs */ @@ -756,6 +757,15 @@ #define V4L2_CID_RDS_TX_PTY (V4L2_CID_FM_TX_CLASS_BASE + 3) #define V4L2_CID_RDS_TX_PS_NAME (V4L2_CID_FM_TX_CLASS_BASE + 5) #define V4L2_CID_RDS_TX_RADIO_TEXT (V4L2_CID_FM_TX_CLASS_BASE + 6) +#define V4L2_CID_RDS_TX_MONO_STEREO (V4L2_CID_FM_TX_CLASS_BASE + 7) +#define V4L2_CID_RDS_TX_ARTIFICIAL_HEAD (V4L2_CID_FM_TX_CLASS_BASE + 8) +#define V4L2_CID_RDS_TX_COMPRESSED (V4L2_CID_FM_TX_CLASS_BASE + 9) +#define V4L2_CID_RDS_TX_DYNAMIC_PTY (V4L2_CID_FM_TX_CLASS_BASE + 10) +#define V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT (V4L2_CID_FM_TX_CLASS_BASE + 11) +#define V4L2_CID_RDS_TX_TRAFFIC_PROGRAM (V4L2_CID_FM_TX_CLASS_BASE + 12) +#define V4L2_CID_RDS_TX_MUSIC_SPEECH (V4L2_CID_FM_TX_CLASS_BASE + 13) +#define V4L2_CID_RDS_TX_ALT_FREQS_ENABLE (V4L2_CID_FM_TX_CLASS_BASE + 14) +#define V4L2_CID_RDS_TX_ALT_FREQS (V4L2_CID_FM_TX_CLASS_BASE + 15) #define V4L2_CID_AUDIO_LIMITER_ENABLED (V4L2_CID_FM_TX_CLASS_BASE + 64) #define V4L2_CID_AUDIO_LIMITER_RELEASE_TIME (V4L2_CID_FM_TX_CLASS_BASE + 65) @@ -900,6 +910,12 @@ }; #define V4L2_CID_RDS_RECEPTION (V4L2_CID_FM_RX_CLASS_BASE + 2) +#define V4L2_CID_RDS_RX_PTY (V4L2_CID_FM_RX_CLASS_BASE + 3) +#define V4L2_CID_RDS_RX_PS_NAME (V4L2_CID_FM_RX_CLASS_BASE + 4) +#define V4L2_CID_RDS_RX_RADIO_TEXT (V4L2_CID_FM_RX_CLASS_BASE + 5) +#define V4L2_CID_RDS_RX_TRAFFIC_ANNOUNCEMENT (V4L2_CID_FM_RX_CLASS_BASE + 6) +#define V4L2_CID_RDS_RX_TRAFFIC_PROGRAM (V4L2_CID_FM_RX_CLASS_BASE + 7) +#define V4L2_CID_RDS_RX_MUSIC_SPEECH (V4L2_CID_FM_RX_CLASS_BASE + 8) #define V4L2_CID_RF_TUNER_CLASS_BASE (V4L2_CTRL_CLASS_RF_TUNER | 0x900) #define V4L2_CID_RF_TUNER_CLASS (V4L2_CTRL_CLASS_RF_TUNER | 1) @@ -914,4 +930,20 @@ #define V4L2_CID_RF_TUNER_IF_GAIN (V4L2_CID_RF_TUNER_CLASS_BASE + 62) #define V4L2_CID_RF_TUNER_PLL_LOCK (V4L2_CID_RF_TUNER_CLASS_BASE + 91) + +/* Detection-class control IDs defined by V4L2 */ +#define V4L2_CID_DETECT_CLASS_BASE (V4L2_CTRL_CLASS_DETECT | 0x900) +#define V4L2_CID_DETECT_CLASS (V4L2_CTRL_CLASS_DETECT | 1) + +#define V4L2_CID_DETECT_MD_MODE (V4L2_CID_DETECT_CLASS_BASE + 1) +enum v4l2_detect_md_mode { + V4L2_DETECT_MD_MODE_DISABLED = 0, + V4L2_DETECT_MD_MODE_GLOBAL = 1, + V4L2_DETECT_MD_MODE_THRESHOLD_GRID = 2, + V4L2_DETECT_MD_MODE_REGION_GRID = 3, +}; +#define V4L2_CID_DETECT_MD_GLOBAL_THRESHOLD (V4L2_CID_DETECT_CLASS_BASE + 2) +#define V4L2_CID_DETECT_MD_THRESHOLD_GRID (V4L2_CID_DETECT_CLASS_BASE + 3) +#define V4L2_CID_DETECT_MD_REGION_GRID (V4L2_CID_DETECT_CLASS_BASE + 4) + #endif diff -Nru v4l-utils-1.0.0+r2263/include/linux/videodev2.h v4l-utils-1.0.0+r2364/include/linux/videodev2.h --- v4l-utils-1.0.0+r2263/include/linux/videodev2.h 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/include/linux/videodev2.h 2014-08-12 09:02:18.000000000 +0000 @@ -53,13 +53,11 @@ * Hans Verkuil * et al. */ -#ifndef _UAPI__LINUX_VIDEODEV2_H -#define _UAPI__LINUX_VIDEODEV2_H +#ifndef __LINUX_VIDEODEV2_H +#define __LINUX_VIDEODEV2_H -#ifndef __KERNEL__ #include -#endif -#include + #include #include #include @@ -124,6 +122,10 @@ (field) == V4L2_FIELD_INTERLACED_BT ||\ (field) == V4L2_FIELD_SEQ_TB ||\ (field) == V4L2_FIELD_SEQ_BT) +#define V4L2_FIELD_HAS_T_OR_B(field) \ + ((field) == V4L2_FIELD_BOTTOM ||\ + (field) == V4L2_FIELD_TOP ||\ + (field) == V4L2_FIELD_ALTERNATE) enum v4l2_buf_type { V4L2_BUF_TYPE_VIDEO_CAPTURE = 1, @@ -268,6 +270,7 @@ #define V4L2_CAP_MODULATOR 0x00080000 /* has a modulator */ #define V4L2_CAP_SDR_CAPTURE 0x00100000 /* Is a SDR capture device */ +#define V4L2_CAP_EXT_PIX_FORMAT 0x00200000 /* Supports the extended pixel format */ #define V4L2_CAP_READWRITE 0x01000000 /* read/write systemcalls */ #define V4L2_CAP_ASYNCIO 0x02000000 /* async I/O */ @@ -287,6 +290,7 @@ __u32 sizeimage; __u32 colorspace; /* enum v4l2_colorspace */ __u32 priv; /* private data, depends on pixelformat */ + __u32 flags; /* format flags (V4L2_PIX_FMT_FLAG_*) */ }; /* Pixel format FOURCC depth Description */ @@ -294,7 +298,11 @@ /* RGB formats */ #define V4L2_PIX_FMT_RGB332 v4l2_fourcc('R', 'G', 'B', '1') /* 8 RGB-3-3-2 */ #define V4L2_PIX_FMT_RGB444 v4l2_fourcc('R', '4', '4', '4') /* 16 xxxxrrrr ggggbbbb */ +#define V4L2_PIX_FMT_ARGB444 v4l2_fourcc('A', 'R', '1', '2') /* 16 aaaarrrr ggggbbbb */ +#define V4L2_PIX_FMT_XRGB444 v4l2_fourcc('X', 'R', '1', '2') /* 16 xxxxrrrr ggggbbbb */ #define V4L2_PIX_FMT_RGB555 v4l2_fourcc('R', 'G', 'B', 'O') /* 16 RGB-5-5-5 */ +#define V4L2_PIX_FMT_ARGB555 v4l2_fourcc('A', 'R', '1', '5') /* 16 ARGB-1-5-5-5 */ +#define V4L2_PIX_FMT_XRGB555 v4l2_fourcc('X', 'R', '1', '5') /* 16 XRGB-1-5-5-5 */ #define V4L2_PIX_FMT_RGB565 v4l2_fourcc('R', 'G', 'B', 'P') /* 16 RGB-5-6-5 */ #define V4L2_PIX_FMT_RGB555X v4l2_fourcc('R', 'G', 'B', 'Q') /* 16 RGB-5-5-5 BE */ #define V4L2_PIX_FMT_RGB565X v4l2_fourcc('R', 'G', 'B', 'R') /* 16 RGB-5-6-5 BE */ @@ -302,7 +310,11 @@ #define V4L2_PIX_FMT_BGR24 v4l2_fourcc('B', 'G', 'R', '3') /* 24 BGR-8-8-8 */ #define V4L2_PIX_FMT_RGB24 v4l2_fourcc('R', 'G', 'B', '3') /* 24 RGB-8-8-8 */ #define V4L2_PIX_FMT_BGR32 v4l2_fourcc('B', 'G', 'R', '4') /* 32 BGR-8-8-8-8 */ +#define V4L2_PIX_FMT_ABGR32 v4l2_fourcc('A', 'R', '2', '4') /* 32 BGRA-8-8-8-8 */ +#define V4L2_PIX_FMT_XBGR32 v4l2_fourcc('X', 'R', '2', '4') /* 32 BGRX-8-8-8-8 */ #define V4L2_PIX_FMT_RGB32 v4l2_fourcc('R', 'G', 'B', '4') /* 32 RGB-8-8-8-8 */ +#define V4L2_PIX_FMT_ARGB32 v4l2_fourcc('B', 'A', '2', '4') /* 32 ARGB-8-8-8-8 */ +#define V4L2_PIX_FMT_XRGB32 v4l2_fourcc('B', 'X', '2', '4') /* 32 XRGB-8-8-8-8 */ /* Grey formats */ #define V4L2_PIX_FMT_GREY v4l2_fourcc('G', 'R', 'E', 'Y') /* 8 Greyscale */ @@ -439,6 +451,15 @@ /* SDR formats - used only for Software Defined Radio devices */ #define V4L2_SDR_FMT_CU8 v4l2_fourcc('C', 'U', '0', '8') /* IQ u8 */ #define V4L2_SDR_FMT_CU16LE v4l2_fourcc('C', 'U', '1', '6') /* IQ u16le */ +#define V4L2_SDR_FMT_CS8 v4l2_fourcc('C', 'S', '0', '8') /* complex s8 */ +#define V4L2_SDR_FMT_CS14LE v4l2_fourcc('C', 'S', '1', '4') /* complex s14le */ +#define V4L2_SDR_FMT_RU12LE v4l2_fourcc('R', 'U', '1', '2') /* real u12le */ + +/* priv field value to indicates that subsequent fields are valid. */ +#define V4L2_PIX_FMT_PRIV_MAGIC 0xfeedcafe + +/* Flags */ +#define V4L2_PIX_FMT_FLAG_PREMUL_ALPHA 0x00000001 /* * F O R M A T E N U M E R A T I O N @@ -744,7 +765,16 @@ /* FIXME: in theory we should pass something like PCI device + memory * region + offset instead of some physical address */ void *base; - struct v4l2_pix_format fmt; + struct { + __u32 width; + __u32 height; + __u32 pixelformat; + __u32 field; /* enum v4l2_field */ + __u32 bytesperline; /* for padding, zero if unused */ + __u32 sizeimage; + __u32 colorspace; /* enum v4l2_colorspace */ + __u32 priv; /* reserved field, set to 0 */ + } fmt; }; /* Flags for the 'capability' field. Read only */ #define V4L2_FBUF_CAP_EXTERNOVERLAY 0x0001 @@ -766,16 +796,16 @@ struct v4l2_clip { struct v4l2_rect c; - struct v4l2_clip __user *next; + struct v4l2_clip *next; }; struct v4l2_window { struct v4l2_rect w; __u32 field; /* enum v4l2_field */ __u32 chromakey; - struct v4l2_clip __user *clips; + struct v4l2_clip *clips; __u32 clipcount; - void __user *bitmap; + void *bitmap; __u8 global_alpha; }; @@ -1254,6 +1284,10 @@ __s32 value; __s64 value64; char *string; + __u8 *p_u8; + __u16 *p_u16; + __u32 *p_u32; + void *ptr; }; } __attribute__ ((packed)); @@ -1268,6 +1302,7 @@ #define V4L2_CTRL_ID_MASK (0x0fffffff) #define V4L2_CTRL_ID2CLASS(id) ((id) & 0x0fff0000UL) #define V4L2_CTRL_DRIVER_PRIV(id) (((id) & 0xffff) >= 0x1000) +#define V4L2_CTRL_MAX_DIMS (4) enum v4l2_ctrl_type { V4L2_CTRL_TYPE_INTEGER = 1, @@ -1278,7 +1313,13 @@ V4L2_CTRL_TYPE_CTRL_CLASS = 6, V4L2_CTRL_TYPE_STRING = 7, V4L2_CTRL_TYPE_BITMASK = 8, - V4L2_CTRL_TYPE_INTEGER_MENU = 9, + V4L2_CTRL_TYPE_INTEGER_MENU = 9, + + /* Compound types are >= 0x0100 */ + V4L2_CTRL_COMPOUND_TYPES = 0x0100, + V4L2_CTRL_TYPE_U8 = 0x0100, + V4L2_CTRL_TYPE_U16 = 0x0101, + V4L2_CTRL_TYPE_U32 = 0x0102, }; /* Used in the VIDIOC_QUERYCTRL ioctl for querying controls */ @@ -1294,6 +1335,23 @@ __u32 reserved[2]; }; +/* Used in the VIDIOC_QUERY_EXT_CTRL ioctl for querying extended controls */ +struct v4l2_query_ext_ctrl { + __u32 id; + __u32 type; + char name[32]; + __s64 minimum; + __s64 maximum; + __u64 step; + __s64 default_value; + __u32 flags; + __u32 elem_size; + __u32 elems; + __u32 nr_of_dims; + __u32 dims[V4L2_CTRL_MAX_DIMS]; + __u32 reserved[32]; +}; + /* Used in the VIDIOC_QUERYMENU ioctl for querying menu items */ struct v4l2_querymenu { __u32 id; @@ -1314,9 +1372,11 @@ #define V4L2_CTRL_FLAG_SLIDER 0x0020 #define V4L2_CTRL_FLAG_WRITE_ONLY 0x0040 #define V4L2_CTRL_FLAG_VOLATILE 0x0080 +#define V4L2_CTRL_FLAG_HAS_PAYLOAD 0x0100 -/* Query flag, to be ORed with the control ID */ +/* Query flags, to be ORed with the control ID */ #define V4L2_CTRL_FLAG_NEXT_CTRL 0x80000000 +#define V4L2_CTRL_FLAG_NEXT_COMPOUND 0x40000000 /* User-class control IDs defined by V4L2 */ #define V4L2_CID_MAX_CTRLS 1024 @@ -1582,6 +1642,12 @@ #define V4L2_VBI_UNSYNC (1 << 0) #define V4L2_VBI_INTERLACED (1 << 1) +/* ITU-R start lines for each field */ +#define V4L2_VBI_ITU_525_F1_START (1) +#define V4L2_VBI_ITU_525_F2_START (264) +#define V4L2_VBI_ITU_625_F1_START (1) +#define V4L2_VBI_ITU_625_F2_START (314) + /* Sliced VBI * * This implements is a proposal V4L2 API to allow SLICED VBI @@ -1705,6 +1771,7 @@ * @colorspace: enum v4l2_colorspace; supplemental to pixelformat * @plane_fmt: per-plane information * @num_planes: number of planes for this format + * @flags: format flags (V4L2_PIX_FMT_FLAG_*) */ struct v4l2_pix_format_mplane { __u32 width; @@ -1715,16 +1782,19 @@ struct v4l2_plane_pix_format plane_fmt[VIDEO_MAX_PLANES]; __u8 num_planes; - __u8 reserved[11]; + __u8 flags; + __u8 reserved[10]; } __attribute__ ((packed)); /** * struct v4l2_sdr_format - SDR format definition * @pixelformat: little endian four character code (fourcc) + * @buffersize: maximum size in bytes required for data */ struct v4l2_sdr_format { __u32 pixelformat; - __u8 reserved[28]; + __u32 buffersize; + __u8 reserved[24]; } __attribute__ ((packed)); /** @@ -1771,6 +1841,7 @@ #define V4L2_EVENT_CTRL 3 #define V4L2_EVENT_FRAME_SYNC 4 #define V4L2_EVENT_SOURCE_CHANGE 5 +#define V4L2_EVENT_MOTION_DET 6 #define V4L2_EVENT_PRIVATE_START 0x08000000 /* Payload for V4L2_EVENT_VSYNC */ @@ -1808,6 +1879,21 @@ __u32 changes; }; +#define V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ (1 << 0) + +/** + * struct v4l2_event_motion_det - motion detection event + * @flags: if V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ is set, then the + * frame_sequence field is valid. + * @frame_sequence: the frame sequence number associated with this event. + * @region_mask: which regions detected motion. + */ +struct v4l2_event_motion_det { + __u32 flags; + __u32 frame_sequence; + __u32 region_mask; +}; + struct v4l2_event { __u32 type; union { @@ -1815,6 +1901,7 @@ struct v4l2_event_ctrl ctrl; struct v4l2_event_frame_sync frame_sync; struct v4l2_event_src_change src_change; + struct v4l2_event_motion_det motion_det; __u8 data[64]; } u; __u32 pending; @@ -2005,9 +2092,11 @@ Never use these in applications! */ #define VIDIOC_DBG_G_CHIP_INFO _IOWR('V', 102, struct v4l2_dbg_chip_info) +#define VIDIOC_QUERY_EXT_CTRL _IOWR('V', 103, struct v4l2_query_ext_ctrl) + /* Reminder: when adding new ioctls please add support for them to drivers/media/video/v4l2-compat-ioctl32.c as well! */ #define BASE_VIDIOC_PRIVATE 192 /* 192-255 are private */ -#endif /* _UAPI__LINUX_VIDEODEV2_H */ +#endif /* __LINUX_VIDEODEV2_H */ diff -Nru v4l-utils-1.0.0+r2263/lib/include/libdvbv5/crc32.h v4l-utils-1.0.0+r2364/lib/include/libdvbv5/crc32.h --- v4l-utils-1.0.0+r2263/lib/include/libdvbv5/crc32.h 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/lib/include/libdvbv5/crc32.h 2014-08-12 09:02:18.000000000 +0000 @@ -1,6 +1,6 @@ /* * Copyright (c) 2011-2012 - Mauro Carvalho Chehab - * Copyright (c) 2012 - Andre Roth + * Copyright (c) 2012-2014 - Andre Roth * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -25,7 +25,15 @@ #include #include /* size_t */ -uint32_t crc32(uint8_t *data, size_t datalen, uint32_t crc); +#ifdef __cplusplus +extern "C" { +#endif + +uint32_t dvb_crc32(uint8_t *data, size_t datalen, uint32_t crc); + +#ifdef __cplusplus +} +#endif #endif diff -Nru v4l-utils-1.0.0+r2263/lib/include/libdvbv5/desc_extension.h v4l-utils-1.0.0+r2364/lib/include/libdvbv5/desc_extension.h --- v4l-utils-1.0.0+r2263/lib/include/libdvbv5/desc_extension.h 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/lib/include/libdvbv5/desc_extension.h 2014-08-12 09:02:18.000000000 +0000 @@ -71,10 +71,10 @@ extern "C" { #endif -int extension_descriptor_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc); -void extension_descriptor_free(struct dvb_desc *descriptor); -void extension_descriptor_print(struct dvb_v5_fe_parms *parms, - const struct dvb_desc *desc); +int dvb_extension_descriptor_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc); +void dvb_extension_descriptor_free(struct dvb_desc *descriptor); +void dvb_extension_descriptor_print(struct dvb_v5_fe_parms *parms, + const struct dvb_desc *desc); #ifdef __cplusplus } diff -Nru v4l-utils-1.0.0+r2263/lib/include/libdvbv5/descriptors.h v4l-utils-1.0.0+r2364/lib/include/libdvbv5/descriptors.h --- v4l-utils-1.0.0+r2263/lib/include/libdvbv5/descriptors.h 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/lib/include/libdvbv5/descriptors.h 2014-08-12 09:02:18.000000000 +0000 @@ -26,9 +26,9 @@ #ifndef _DESCRIPTORS_H #define _DESCRIPTORS_H -#include #include #include +#include #define DVB_MAX_PAYLOAD_PACKET_SIZE 4096 #define DVB_CRC_SIZE 4 @@ -72,9 +72,9 @@ extern "C" { #endif -uint32_t bcd(uint32_t bcd); +uint32_t dvb_bcd(uint32_t bcd); -void hexdump(struct dvb_v5_fe_parms *parms, const char *prefix, const unsigned char *buf, int len); +void dvb_hexdump(struct dvb_v5_fe_parms *parms, const char *prefix, const unsigned char *buf, int len); int dvb_desc_parse(struct dvb_v5_fe_parms *parms, const uint8_t *buf, uint16_t section_length, struct dvb_desc **head_desc); void dvb_desc_free (struct dvb_desc **list); diff -Nru v4l-utils-1.0.0+r2263/lib/include/libdvbv5/dvb-demux.h v4l-utils-1.0.0+r2364/lib/include/libdvbv5/dvb-demux.h --- v4l-utils-1.0.0+r2263/lib/include/libdvbv5/dvb-demux.h 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/lib/include/libdvbv5/dvb-demux.h 2014-08-12 09:02:18.000000000 +0000 @@ -48,7 +48,7 @@ unsigned char *mode, unsigned int flags); -int get_pmt_pid(const char *dmxdev, int sid); +int dvb_get_pmt_pid(const char *dmxdev, int sid); #ifdef __cplusplus } diff -Nru v4l-utils-1.0.0+r2263/lib/include/libdvbv5/dvb-file.h v4l-utils-1.0.0+r2364/lib/include/libdvbv5/dvb-file.h --- v4l-utils-1.0.0+r2263/lib/include/libdvbv5/dvb-file.h 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/lib/include/libdvbv5/dvb-file.h 2014-08-12 09:02:18.000000000 +0000 @@ -121,38 +121,36 @@ extern const struct parse_file channel_file_zap_format; /* From dvb-file.c */ -struct dvb_file *parse_format_oneline(const char *fname, - uint32_t delsys, - const struct parse_file *parse_file); -int write_format_oneline(const char *fname, - struct dvb_file *dvb_file, - uint32_t delsys, - const struct parse_file *parse_file); +struct dvb_file *dvb_parse_format_oneline(const char *fname, + uint32_t delsys, + const struct parse_file *parse_file); +int dvb_write_format_oneline(const char *fname, + struct dvb_file *dvb_file, + uint32_t delsys, + const struct parse_file *parse_file); +struct dvb_file *dvb_read_file(const char *fname); +int dvb_write_file(const char *fname, struct dvb_file *dvb_file); -struct dvb_file *read_dvb_file(const char *fname); - -int write_dvb_file(const char *fname, struct dvb_file *dvb_file); - -int store_entry_prop(struct dvb_entry *entry, +int dvb_store_entry_prop(struct dvb_entry *entry, uint32_t cmd, uint32_t value); -int retrieve_entry_prop(struct dvb_entry *entry, +int dvb_retrieve_entry_prop(struct dvb_entry *entry, uint32_t cmd, uint32_t *value); -int store_dvb_channel(struct dvb_file **dvb_file, +int dvb_store_channel(struct dvb_file **dvb_file, struct dvb_v5_fe_parms *parms, struct dvb_v5_descriptors *dvb_desc, int get_detected, int get_nit); -int parse_delsys(const char *name); -enum file_formats parse_format(const char *name); +int dvb_parse_delsys(const char *name); +enum file_formats dvb_parse_format(const char *name); struct dvb_file *dvb_read_file_format(const char *fname, uint32_t delsys, enum file_formats format); -int write_file_format(const char *fname, - struct dvb_file *dvb_file, - uint32_t delsys, - enum file_formats format); +int dvb_write_file_format(const char *fname, + struct dvb_file *dvb_file, + uint32_t delsys, + enum file_formats format); #ifdef __cplusplus } diff -Nru v4l-utils-1.0.0+r2263/lib/include/libdvbv5/dvb-sat.h v4l-utils-1.0.0+r2364/lib/include/libdvbv5/dvb-sat.h --- v4l-utils-1.0.0+r2263/lib/include/libdvbv5/dvb-sat.h 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/lib/include/libdvbv5/dvb-sat.h 2014-08-12 09:02:18.000000000 +0000 @@ -45,8 +45,8 @@ /* From libsat.c */ int dvb_sat_search_lnb(const char *name); -int print_lnb(int i); -void print_all_lnb(void); +int dvb_print_lnb(int i); +void dvb_print_all_lnb(void); const struct dvb_sat_lnb *dvb_sat_get_lnb(int i); int dvb_sat_set_parms(struct dvb_v5_fe_parms *parms); diff -Nru v4l-utils-1.0.0+r2263/lib/include/libdvbv5/dvb-scan.h v4l-utils-1.0.0+r2364/lib/include/libdvbv5/dvb-scan.h --- v4l-utils-1.0.0+r2263/lib/include/libdvbv5/dvb-scan.h 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/lib/include/libdvbv5/dvb-scan.h 2014-08-12 09:02:18.000000000 +0000 @@ -133,10 +133,10 @@ unsigned other_nit, unsigned timeout_multiply); -int estimate_freq_shift(struct dvb_v5_fe_parms *parms); +int dvb_estimate_freq_shift(struct dvb_v5_fe_parms *parms); -int new_freq_is_needed(struct dvb_entry *entry, struct dvb_entry *last_entry, - uint32_t freq, enum dvb_sat_polarization pol, int shift); +int dvb_new_freq_is_needed(struct dvb_entry *entry, struct dvb_entry *last_entry, + uint32_t freq, enum dvb_sat_polarization pol, int shift); struct dvb_entry *dvb_scan_add_entry(struct dvb_v5_fe_parms *parms, struct dvb_entry *first_entry, diff -Nru v4l-utils-1.0.0+r2263/lib/include/libdvbv5/nit.h v4l-utils-1.0.0+r2364/lib/include/libdvbv5/nit.h --- v4l-utils-1.0.0+r2263/lib/include/libdvbv5/nit.h 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/lib/include/libdvbv5/nit.h 2014-08-12 09:02:18.000000000 +0000 @@ -89,7 +89,8 @@ void dvb_table_nit_free(struct dvb_table_nit *nit); void dvb_table_nit_print(struct dvb_v5_fe_parms *parms, struct dvb_table_nit *nit); -void nit_descriptor_handler(struct dvb_v5_fe_parms *parms, +void dvb_table_nit_descriptor_handler( + struct dvb_v5_fe_parms *parms, struct dvb_table_nit *nit, enum descriptors descriptor, nit_handler_callback_t *call_nit, diff -Nru v4l-utils-1.0.0+r2263/lib/libdvbv5/crc32.c v4l-utils-1.0.0+r2364/lib/libdvbv5/crc32.c --- v4l-utils-1.0.0+r2263/lib/libdvbv5/crc32.c 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/lib/libdvbv5/crc32.c 2014-08-12 09:02:18.000000000 +0000 @@ -67,7 +67,7 @@ 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 }; -inline uint32_t crc32(uint8_t *data, size_t len, uint32_t crc) +inline uint32_t dvb_crc32(uint8_t *data, size_t len, uint32_t crc) { while(len--) crc = (crc << 8) ^ crctab[((crc >> 24) ^ *data++) & 0xff]; diff -Nru v4l-utils-1.0.0+r2263/lib/libdvbv5/descriptors/desc_cable_delivery.c v4l-utils-1.0.0+r2364/lib/libdvbv5/descriptors/desc_cable_delivery.c --- v4l-utils-1.0.0+r2263/lib/libdvbv5/descriptors/desc_cable_delivery.c 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/lib/libdvbv5/descriptors/desc_cable_delivery.c 2014-08-12 09:02:18.000000000 +0000 @@ -33,8 +33,8 @@ bswap32(cable->frequency); bswap16(cable->bitfield1); bswap32(cable->bitfield2); - cable->frequency = bcd(cable->frequency) * 100; - cable->symbol_rate = bcd(cable->symbol_rate) * 100; + cable->frequency = dvb_bcd(cable->frequency) * 100; + cable->symbol_rate = dvb_bcd(cable->symbol_rate) * 100; return 0; } diff -Nru v4l-utils-1.0.0+r2263/lib/libdvbv5/descriptors/desc_ca.c v4l-utils-1.0.0+r2364/lib/libdvbv5/descriptors/desc_ca.c --- v4l-utils-1.0.0+r2263/lib/libdvbv5/descriptors/desc_ca.c 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/lib/libdvbv5/descriptors/desc_ca.c 2014-08-12 09:02:18.000000000 +0000 @@ -40,7 +40,7 @@ d->privdata = NULL; d->privdata_len = 0; } - /*hexdump(parms, "desc ca ", buf, desc->length);*/ + /*dvb_hexdump(parms, "desc ca ", buf, desc->length);*/ /*dvb_desc_ca_print(parms, desc);*/ return 0; } @@ -52,7 +52,7 @@ dvb_loginfo("| ca_pid 0x%04x", d->ca_pid); dvb_loginfo("| privdata length %d", d->privdata_len); if (d->privdata) - hexdump(parms, "| privdata ", d->privdata, d->privdata_len); + dvb_hexdump(parms, "| privdata ", d->privdata, d->privdata_len); } void dvb_desc_ca_free(struct dvb_desc *desc) diff -Nru v4l-utils-1.0.0+r2263/lib/libdvbv5/descriptors/desc_event_extended.c v4l-utils-1.0.0+r2364/lib/libdvbv5/descriptors/desc_event_extended.c --- v4l-utils-1.0.0+r2263/lib/libdvbv5/descriptors/desc_event_extended.c 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/lib/libdvbv5/descriptors/desc_event_extended.c 2014-08-12 09:02:18.000000000 +0000 @@ -29,7 +29,7 @@ uint8_t len; /* the length of the string in the input data */ uint8_t len1; /* the lenght of the output strings */ - /*hexdump(parms, "event extended desc: ", buf - 2, desc->length + 2);*/ + /*dvb_hexdump(parms, "event extended desc: ", buf - 2, desc->length + 2);*/ event->ids = buf[0]; event->language[0] = buf[1]; diff -Nru v4l-utils-1.0.0+r2263/lib/libdvbv5/descriptors/desc_event_short.c v4l-utils-1.0.0+r2364/lib/libdvbv5/descriptors/desc_event_short.c --- v4l-utils-1.0.0+r2263/lib/libdvbv5/descriptors/desc_event_short.c 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/lib/libdvbv5/descriptors/desc_event_short.c 2014-08-12 09:02:18.000000000 +0000 @@ -29,7 +29,7 @@ uint8_t len; /* the length of the string in the input data */ uint8_t len1, len2; /* the lenght of the output strings */ - /*hexdump(parms, "event short desc: ", buf - 2, desc->length + 2);*/ + /*dvb_hexdump(parms, "event short desc: ", buf - 2, desc->length + 2);*/ event->language[0] = buf[0]; event->language[1] = buf[1]; diff -Nru v4l-utils-1.0.0+r2263/lib/libdvbv5/descriptors/desc_extension.c v4l-utils-1.0.0+r2364/lib/libdvbv5/descriptors/desc_extension.c --- v4l-utils-1.0.0+r2263/lib/libdvbv5/descriptors/desc_extension.c 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/lib/libdvbv5/descriptors/desc_extension.c 2014-08-12 09:02:18.000000000 +0000 @@ -116,8 +116,8 @@ }, }; -int extension_descriptor_init(struct dvb_v5_fe_parms *parms, - const uint8_t *buf, struct dvb_desc *desc) +int dvb_extension_descriptor_init(struct dvb_v5_fe_parms *parms, + const uint8_t *buf, struct dvb_desc *desc) { struct dvb_extension_descriptor *ext = (void *)desc; unsigned char *p = (unsigned char *)buf; @@ -141,7 +141,7 @@ dvb_logwarn("%sextension descriptor %s type 0x%02x, size %d", dvb_ext_descriptors[desc_type].init ? "" : "Not handled ", dvb_ext_descriptors[desc_type].name, desc_type, desc_len); - hexdump(parms, "content: ", p, desc_len); + dvb_hexdump(parms, "content: ", p, desc_len); } init = dvb_ext_descriptors[desc_type].init; @@ -161,7 +161,7 @@ return 0; } -void extension_descriptor_free(struct dvb_desc *descriptor) +void dvb_extension_descriptor_free(struct dvb_desc *descriptor) { struct dvb_extension_descriptor *ext = (void *)descriptor; uint8_t type = ext->extension_code; @@ -175,7 +175,7 @@ free(ext->descriptor); } -void extension_descriptor_print(struct dvb_v5_fe_parms *parms, +void dvb_extension_descriptor_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc) { struct dvb_extension_descriptor *ext = (void *)desc; diff -Nru v4l-utils-1.0.0+r2263/lib/libdvbv5/descriptors/desc_sat.c v4l-utils-1.0.0+r2364/lib/libdvbv5/descriptors/desc_sat.c --- v4l-utils-1.0.0+r2263/lib/libdvbv5/descriptors/desc_sat.c 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/lib/libdvbv5/descriptors/desc_sat.c 2014-08-12 09:02:18.000000000 +0000 @@ -32,9 +32,9 @@ bswap16(sat->orbit); bswap32(sat->bitfield); bswap32(sat->frequency); - sat->orbit = bcd(sat->orbit); - sat->frequency = bcd(sat->frequency) * 10; - sat->symbol_rate = bcd(sat->symbol_rate) * 100; + sat->orbit = dvb_bcd(sat->orbit); + sat->frequency = dvb_bcd(sat->frequency) * 10; + sat->symbol_rate = dvb_bcd(sat->symbol_rate) * 100; return 0; } diff -Nru v4l-utils-1.0.0+r2263/lib/libdvbv5/descriptors.c v4l-utils-1.0.0+r2364/lib/libdvbv5/descriptors.c --- v4l-utils-1.0.0+r2263/lib/libdvbv5/descriptors.c 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/lib/libdvbv5/descriptors.c 2014-08-12 09:02:18.000000000 +0000 @@ -76,7 +76,7 @@ { if (!parms) parms = dvb_fe_dummy(); - hexdump(parms, "| ", desc->data, desc->length); + dvb_hexdump(parms, "| ", desc->data, desc->length); } #define TABLE_INIT(_x) (dvb_table_init_func) _x##_init @@ -138,7 +138,7 @@ dvb_log("%sdescriptor %s type 0x%02x, size %d", dvb_descriptors[desc_type].init ? "" : "Not handled ", dvb_descriptors[desc_type].name, desc_type, desc_len); - hexdump(parms, "content: ", ptr + 2, desc_len); + dvb_hexdump(parms, "content: ", ptr + 2, desc_len); } dvb_desc_init_func init = dvb_descriptors[desc_type].init; @@ -894,9 +894,9 @@ }, [extension_descriptor] = { .name = "extension_descriptor", - .init = extension_descriptor_init, - .print = extension_descriptor_print, - .free = extension_descriptor_free, + .init = dvb_extension_descriptor_init, + .print = dvb_extension_descriptor_print, + .free = dvb_extension_descriptor_free, .size = sizeof(struct dvb_extension_descriptor), }, @@ -1311,7 +1311,7 @@ }, }; -uint32_t bcd(uint32_t bcd) +uint32_t dvb_bcd(uint32_t bcd) { uint32_t ret = 0, mult = 1; while (bcd) { @@ -1322,7 +1322,7 @@ return ret; } -int bcd_to_int(const unsigned char *bcd, int bits) +static int bcd_to_int(const unsigned char *bcd, int bits) { int nibble = 0; int ret = 0; @@ -1341,7 +1341,7 @@ return ret; } -void hexdump(struct dvb_v5_fe_parms *parms, const char *prefix, const unsigned char *data, int length) +void dvb_hexdump(struct dvb_v5_fe_parms *parms, const char *prefix, const unsigned char *data, int length) { char ascii[17]; char hex[50]; diff -Nru v4l-utils-1.0.0+r2263/lib/libdvbv5/dvb-demux.c v4l-utils-1.0.0+r2364/lib/libdvbv5/dvb-demux.c --- v4l-utils-1.0.0+r2263/lib/libdvbv5/dvb-demux.c 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/lib/libdvbv5/dvb-demux.c 2014-08-12 09:02:18.000000000 +0000 @@ -125,7 +125,7 @@ return 0; } -int get_pmt_pid(const char *dmxdev, int sid) +int dvb_get_pmt_pid(const char *dmxdev, int sid) { int patfd, count; int pmt_pid = 0; diff -Nru v4l-utils-1.0.0+r2263/lib/libdvbv5/dvb-file.c v4l-utils-1.0.0+r2364/lib/libdvbv5/dvb-file.c --- v4l-utils-1.0.0+r2263/lib/libdvbv5/dvb-file.c 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/lib/libdvbv5/dvb-file.c 2014-08-12 09:02:18.000000000 +0000 @@ -49,8 +49,8 @@ #include #include -int store_entry_prop(struct dvb_entry *entry, - uint32_t cmd, uint32_t value) +int dvb_store_entry_prop(struct dvb_entry *entry, + uint32_t cmd, uint32_t value) { int i; @@ -73,8 +73,8 @@ return 0; } -int retrieve_entry_prop(struct dvb_entry *entry, - uint32_t cmd, uint32_t *value) +int dvb_retrieve_entry_prop(struct dvb_entry *entry, + uint32_t cmd, uint32_t *value) { int i; @@ -92,13 +92,13 @@ { uint32_t delsys = SYS_UNDEFINED; - retrieve_entry_prop(entry, DTV_DELIVERY_SYSTEM, &delsys); + dvb_retrieve_entry_prop(entry, DTV_DELIVERY_SYSTEM, &delsys); switch (delsys) { case SYS_ATSC: case SYS_DVBC_ANNEX_B: { uint32_t modulation = VSB_8; - retrieve_entry_prop(entry, DTV_MODULATION, &modulation); + dvb_retrieve_entry_prop(entry, DTV_MODULATION, &modulation); switch (modulation) { case VSB_8: case VSB_16: @@ -108,7 +108,7 @@ delsys = SYS_DVBC_ANNEX_B; break; } - store_entry_prop(entry, DTV_DELIVERY_SYSTEM, delsys); + dvb_store_entry_prop(entry, DTV_DELIVERY_SYSTEM, delsys); break; } } /* switch */ @@ -118,9 +118,9 @@ * Generic parse function for all formats each channel is contained into * just one line. */ -struct dvb_file *parse_format_oneline(const char *fname, - uint32_t delsys, - const struct parse_file *parse_file) +struct dvb_file *dvb_parse_format_oneline(const char *fname, + uint32_t delsys, + const struct parse_file *parse_file) { const char *delimiter = parse_file->delimiter; const struct parse_struct *formats = parse_file->formats; @@ -309,10 +309,10 @@ } } -int write_format_oneline(const char *fname, - struct dvb_file *dvb_file, - uint32_t delsys, - const struct parse_file *parse_file) +int dvb_write_format_oneline(const char *fname, + struct dvb_file *dvb_file, + uint32_t delsys, + const struct parse_file *parse_file) { const char delimiter = parse_file->delimiter[0]; const struct parse_struct *formats = parse_file->formats; @@ -527,7 +527,7 @@ break; if (j == ARRAY_SIZE(dvb_sat_pol_name)) return -2; - store_entry_prop(entry, DTV_POLARIZATION, j); + dvb_store_entry_prop(entry, DTV_POLARIZATION, j); return 0; } else if (!strncasecmp(key,"PID_", 4)){ type = strtol(&key[4], NULL, 16); @@ -585,7 +585,7 @@ } -struct dvb_file *read_dvb_file(const char *fname) +struct dvb_file *dvb_read_file(const char *fname) { char *buf = NULL, *p, *key, *value; size_t size = 0; @@ -688,7 +688,7 @@ return NULL; }; -int write_dvb_file(const char *fname, struct dvb_file *dvb_file) +int dvb_write_file(const char *fname, struct dvb_file *dvb_file) { FILE *fp; int i; @@ -1022,12 +1022,12 @@ entry->props[j].cmd = parms->dvb_prop[j].cmd; entry->props[j].u.data = parms->dvb_prop[j].u.data; - if (!channel && entry->props[j].cmd == DTV_FREQUENCY) + if (!*channel && entry->props[j].cmd == DTV_FREQUENCY) freq = parms->dvb_prop[j].u.data; } entry->n_props = parms->n_props; - if (!channel) { + if (!*channel) { r = asprintf(&channel, "%.2fMHz#%d", freq/1000000., service_id); if (r < 0) dvb_perror("asprintf"); @@ -1062,7 +1062,7 @@ [0x80 ...0xfe] = "user defined", }; -int store_dvb_channel(struct dvb_file **dvb_file, +int dvb_store_channel(struct dvb_file **dvb_file, struct dvb_v5_fe_parms *parms, struct dvb_v5_descriptors *dvb_scan_handler, int get_detected, int get_nit) @@ -1113,8 +1113,9 @@ if (!dvb_scan_handler->sdt) { int i; - dvb_logerr("no SDT table - storing channels without their names"); + dvb_log("WARNING: no SDT table - storing channels without their names"); for (i = 0; i < dvb_scan_handler->num_program; i++) { + char *channel = NULL; unsigned service_id; if (!dvb_scan_handler->program[i].pmt) @@ -1123,7 +1124,7 @@ service_id = dvb_scan_handler->program[i].pat_pgm->service_id; rc = get_program_and_store(parms, *dvb_file, dvb_scan_handler, - service_id, NULL, NULL, + service_id, channel, NULL, get_detected, get_nit); if (rc < 0) return rc; @@ -1170,7 +1171,7 @@ return 0; } -enum file_formats parse_format(const char *name) +enum file_formats dvb_parse_format(const char *name) { if (!strcasecmp(name, "ZAP")) return FILE_ZAP; @@ -1200,7 +1201,7 @@ { SYS_DMBTH, "DMB-TH" }, }; -int parse_delsys(const char *name) +int dvb_parse_delsys(const char *name) { int i, cnt = 0; @@ -1253,17 +1254,17 @@ switch (format) { case FILE_CHANNEL: /* DVB channel/transponder old format */ - dvb_file = parse_format_oneline(fname, - SYS_UNDEFINED, - &channel_file_format); + dvb_file = dvb_parse_format_oneline(fname, + SYS_UNDEFINED, + &channel_file_format); break; case FILE_ZAP: - dvb_file = parse_format_oneline(fname, - delsys, - &channel_file_zap_format); + dvb_file = dvb_parse_format_oneline(fname, + delsys, + &channel_file_zap_format); break; case FILE_DVBV5: - dvb_file = read_dvb_file(fname); + dvb_file = dvb_read_file(fname); break; default: fprintf(stderr, "Format is not supported\n"); @@ -1273,28 +1274,28 @@ return dvb_file; } -int write_file_format(const char *fname, - struct dvb_file *dvb_file, - uint32_t delsys, - enum file_formats format) +int dvb_write_file_format(const char *fname, + struct dvb_file *dvb_file, + uint32_t delsys, + enum file_formats format) { int ret; switch (format) { case FILE_CHANNEL: /* DVB channel/transponder old format */ - ret = write_format_oneline(fname, - dvb_file, - SYS_UNDEFINED, - &channel_file_format); + ret = dvb_write_format_oneline(fname, + dvb_file, + SYS_UNDEFINED, + &channel_file_format); break; case FILE_ZAP: - ret = write_format_oneline(fname, - dvb_file, - delsys, - &channel_file_zap_format); + ret = dvb_write_format_oneline(fname, + dvb_file, + delsys, + &channel_file_zap_format); break; case FILE_DVBV5: - ret = write_dvb_file(fname, dvb_file); + ret = dvb_write_file(fname, dvb_file); break; default: return -1; diff -Nru v4l-utils-1.0.0+r2263/lib/libdvbv5/dvb-sat.c v4l-utils-1.0.0+r2364/lib/libdvbv5/dvb-sat.c --- v4l-utils-1.0.0+r2263/lib/libdvbv5/dvb-sat.c 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/lib/libdvbv5/dvb-sat.c 2014-08-12 09:02:18.000000000 +0000 @@ -44,6 +44,16 @@ .freqrange = { { 12200, 12700 } } + }, { + .name = "Astra 1E, European Universal Ku (extended)", + .alias = "EXTENDEDU", + .lowfreq = 9750, + .highfreq = 10600, + .rangeswitch = 11700, + .freqrange = { + { 10700, 11700 }, + { 11700, 12750 }, + } }, { .name = "Standard", .alias = "STANDARD", @@ -95,7 +105,7 @@ return -1; } -int print_lnb(int i) +int dvb_print_lnb(int i) { if (i < 0 || i >= ARRAY_SIZE(lnb)) return -1; @@ -122,12 +132,12 @@ return 0; } -void print_all_lnb(void) +void dvb_print_all_lnb(void) { int i; for (i = 0; i < ARRAY_SIZE(lnb); i++) { - print_lnb(i); + dvb_print_lnb(i); printf("\n"); } } diff -Nru v4l-utils-1.0.0+r2263/lib/libdvbv5/dvb-scan.c v4l-utils-1.0.0+r2364/lib/libdvbv5/dvb-scan.c --- v4l-utils-1.0.0+r2263/lib/libdvbv5/dvb-scan.c 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/lib/libdvbv5/dvb-scan.c 2014-08-12 09:02:18.000000000 +0000 @@ -300,7 +300,7 @@ break; } - crc = crc32(buf, buf_length, 0xFFFFFFFF); + crc = dvb_crc32(buf, buf_length, 0xFFFFFFFF); if (crc != 0) { dvb_logerr("%s: crc error", __func__); ret = -3; @@ -570,7 +570,7 @@ int i, rc; /* First of all, set the delivery system */ - retrieve_entry_prop(entry, DTV_DELIVERY_SYSTEM, &delsys); + dvb_retrieve_entry_prop(entry, DTV_DELIVERY_SYSTEM, &delsys); dvb_set_compat_delivery_system(parms, delsys); /* Copy data into parms */ @@ -617,7 +617,7 @@ return dvb_scan_handler; } -int estimate_freq_shift(struct dvb_v5_fe_parms *parms) +int dvb_estimate_freq_shift(struct dvb_v5_fe_parms *parms) { uint32_t shift = 0, bw = 0, symbol_rate, ro; int rolloff = 0; @@ -683,8 +683,8 @@ return shift; } -int new_freq_is_needed(struct dvb_entry *entry, struct dvb_entry *last_entry, - uint32_t freq, enum dvb_sat_polarization pol, int shift) +int dvb_new_freq_is_needed(struct dvb_entry *entry, struct dvb_entry *last_entry, + uint32_t freq, enum dvb_sat_polarization pol, int shift) { int i; uint32_t data; @@ -715,7 +715,7 @@ struct dvb_entry *new_entry; int i, n = 2; - if (!new_freq_is_needed(first_entry, NULL, freq, pol, shift)) + if (!dvb_new_freq_is_needed(first_entry, NULL, freq, pol, shift)) return NULL; /* Clone the current entry into a new entry */ @@ -788,10 +788,10 @@ } /* Set NIT props for the transponder */ - store_entry_prop(new, DTV_MODULATION, - dvbc_modulation_table[d->modulation]); - store_entry_prop(new, DTV_SYMBOL_RATE, d->symbol_rate); - store_entry_prop(new, DTV_INNER_FEC, dvbc_fec_table[d->fec_inner]); + dvb_store_entry_prop(new, DTV_MODULATION, + dvbc_modulation_table[d->modulation]); + dvb_store_entry_prop(new, DTV_SYMBOL_RATE, d->symbol_rate); + dvb_store_entry_prop(new, DTV_INNER_FEC, dvbc_fec_table[d->fec_inner]); } @@ -809,8 +809,8 @@ uint32_t mode = isdbt_mode[d->transmission_mode]; uint32_t guard = isdbt_interval[d->guard_interval]; - store_entry_prop(tr->entry, DTV_TRANSMISSION_MODE, mode); - store_entry_prop(tr->entry, DTV_GUARD_INTERVAL, guard); + dvb_store_entry_prop(tr->entry, DTV_TRANSMISSION_MODE, mode); + dvb_store_entry_prop(tr->entry, DTV_GUARD_INTERVAL, guard); return; } @@ -839,12 +839,12 @@ for (i = 0; i < len; i++) { if (tr->entry->service_id == d->partial_reception[i].service_id) { - store_entry_prop(tr->entry, - DTV_ISDBT_PARTIAL_RECEPTION, 1); + dvb_store_entry_prop(tr->entry, + DTV_ISDBT_PARTIAL_RECEPTION, 1); return; } } - store_entry_prop(tr->entry, DTV_ISDBT_PARTIAL_RECEPTION, 0); + dvb_store_entry_prop(tr->entry, DTV_ISDBT_PARTIAL_RECEPTION, 0); } static void add_update_nit_dvbt2(struct dvb_table_nit *nit, @@ -868,20 +868,20 @@ if (tr->entry->service_id != t2->system_id) return; - store_entry_prop(tr->entry, DTV_DELIVERY_SYSTEM, - SYS_DVBT2); - store_entry_prop(tr->entry, DTV_STREAM_ID, - t2->plp_id); + dvb_store_entry_prop(tr->entry, DTV_DELIVERY_SYSTEM, + SYS_DVBT2); + dvb_store_entry_prop(tr->entry, DTV_STREAM_ID, + t2->plp_id); if (d->length -1 <= 4) return; - store_entry_prop(tr->entry, DTV_BANDWIDTH_HZ, - dvbt2_bw[t2->bandwidth]); - store_entry_prop(tr->entry, DTV_GUARD_INTERVAL, - dvbt2_interval[t2->guard_interval]); - store_entry_prop(tr->entry, DTV_TRANSMISSION_MODE, - dvbt2_transmission_mode[t2->transmission_mode]); + dvb_store_entry_prop(tr->entry, DTV_BANDWIDTH_HZ, + dvbt2_bw[t2->bandwidth]); + dvb_store_entry_prop(tr->entry, DTV_GUARD_INTERVAL, + dvbt2_interval[t2->guard_interval]); + dvb_store_entry_prop(tr->entry, DTV_TRANSMISSION_MODE, + dvbt2_transmission_mode[t2->transmission_mode]); return; } @@ -896,16 +896,16 @@ if (!new) return; - store_entry_prop(new, DTV_DELIVERY_SYSTEM, - SYS_DVBT2); - store_entry_prop(new, DTV_STREAM_ID, - t2->plp_id); - store_entry_prop(new, DTV_BANDWIDTH_HZ, - dvbt2_bw[t2->bandwidth]); - store_entry_prop(new, DTV_GUARD_INTERVAL, - dvbt2_interval[t2->guard_interval]); - store_entry_prop(new, DTV_TRANSMISSION_MODE, - dvbt2_transmission_mode[t2->transmission_mode]); + dvb_store_entry_prop(new, DTV_DELIVERY_SYSTEM, + SYS_DVBT2); + dvb_store_entry_prop(new, DTV_STREAM_ID, + t2->plp_id); + dvb_store_entry_prop(new, DTV_BANDWIDTH_HZ, + dvbt2_bw[t2->bandwidth]); + dvb_store_entry_prop(new, DTV_GUARD_INTERVAL, + dvbt2_interval[t2->guard_interval]); + dvb_store_entry_prop(new, DTV_TRANSMISSION_MODE, + dvbt2_transmission_mode[t2->transmission_mode]); } } @@ -927,19 +927,19 @@ return; /* Set NIT DVB-T props for the transponder */ - store_entry_prop(new, DTV_MODULATION, + dvb_store_entry_prop(new, DTV_MODULATION, dvbt_modulation[d->constellation]); - store_entry_prop(new, DTV_BANDWIDTH_HZ, + dvb_store_entry_prop(new, DTV_BANDWIDTH_HZ, dvbt_bw[d->bandwidth]); - store_entry_prop(new, DTV_CODE_RATE_HP, + dvb_store_entry_prop(new, DTV_CODE_RATE_HP, dvbt_code_rate[d->code_rate_hp_stream]); - store_entry_prop(new, DTV_CODE_RATE_LP, + dvb_store_entry_prop(new, DTV_CODE_RATE_LP, dvbt_code_rate[d->code_rate_lp_stream]); - store_entry_prop(new, DTV_GUARD_INTERVAL, + dvb_store_entry_prop(new, DTV_GUARD_INTERVAL, dvbt_interval[d->guard_interval]); - store_entry_prop(new, DTV_TRANSMISSION_MODE, + dvb_store_entry_prop(new, DTV_TRANSMISSION_MODE, dvbt_transmission_mode[d->transmission_mode]); - store_entry_prop(new, DTV_HIERARCHY, + dvb_store_entry_prop(new, DTV_HIERARCHY, dvbt_hierarchy[d->hierarchy_information]); } @@ -968,27 +968,27 @@ /* Set NIT DVB-S props for the transponder */ - store_entry_prop(new, DTV_MODULATION, - dvbs_modulation[d->modulation_system]); - store_entry_prop(new, DTV_POLARIZATION, - dvbs_polarization[d->polarization]); - store_entry_prop(new, DTV_SYMBOL_RATE, - d->symbol_rate); - store_entry_prop(new, DTV_INNER_FEC, - dvbs_dvbc_dvbs_freq_inner[d->fec]); - store_entry_prop(new, DTV_ROLLOFF, - dvbs_rolloff[d->roll_off]); + dvb_store_entry_prop(new, DTV_MODULATION, + dvbs_modulation[d->modulation_system]); + dvb_store_entry_prop(new, DTV_POLARIZATION, + dvbs_polarization[d->polarization]); + dvb_store_entry_prop(new, DTV_SYMBOL_RATE, + d->symbol_rate); + dvb_store_entry_prop(new, DTV_INNER_FEC, + dvbs_dvbc_dvbs_freq_inner[d->fec]); + dvb_store_entry_prop(new, DTV_ROLLOFF, + dvbs_rolloff[d->roll_off]); if (d->roll_off != 0) - store_entry_prop(new, DTV_DELIVERY_SYSTEM, - SYS_DVBS2); + dvb_store_entry_prop(new, DTV_DELIVERY_SYSTEM, + SYS_DVBS2); } -void __dvb_add_update_transponders(struct dvb_v5_fe_parms *parms, - struct dvb_v5_descriptors *dvb_scan_handler, - struct dvb_entry *first_entry, - struct dvb_entry *entry, - uint32_t update) +static void __dvb_add_update_transponders(struct dvb_v5_fe_parms *parms, + struct dvb_v5_descriptors *dvb_scan_handler, + struct dvb_entry *first_entry, + struct dvb_entry *entry, + uint32_t update) { struct update_transponders tr = { .parms = parms, @@ -1002,38 +1002,43 @@ if (!dvb_scan_handler->nit) return; - tr.shift = estimate_freq_shift(parms); + tr.shift = dvb_estimate_freq_shift(parms); switch (parms->current_sys) { case SYS_DVBC_ANNEX_A: case SYS_DVBC_ANNEX_C: - nit_descriptor_handler(parms, dvb_scan_handler->nit, - cable_delivery_system_descriptor, - NULL, add_update_nit_dvbc, &tr); + dvb_table_nit_descriptor_handler( + parms, dvb_scan_handler->nit, + cable_delivery_system_descriptor, + NULL, add_update_nit_dvbc, &tr); return; case SYS_ISDBT: - nit_descriptor_handler(parms, dvb_scan_handler->nit, - partial_reception_descriptor, - NULL, add_update_nit_1seg, &tr); - nit_descriptor_handler(parms, dvb_scan_handler->nit, - ISDBT_delivery_system_descriptor, - NULL, add_update_nit_isdbt, &tr); + dvb_table_nit_descriptor_handler( + parms, dvb_scan_handler->nit, + partial_reception_descriptor, + NULL, add_update_nit_1seg, &tr); + dvb_table_nit_descriptor_handler(parms, dvb_scan_handler->nit, + ISDBT_delivery_system_descriptor, + NULL, add_update_nit_isdbt, &tr); return; case SYS_DVBT: case SYS_DVBT2: - nit_descriptor_handler(parms, dvb_scan_handler->nit, - extension_descriptor, - NULL, add_update_nit_dvbt2, &tr); - - nit_descriptor_handler(parms, dvb_scan_handler->nit, - terrestrial_delivery_system_descriptor, - NULL, add_update_nit_dvbt, &tr); + dvb_table_nit_descriptor_handler( + parms, dvb_scan_handler->nit, + extension_descriptor, + NULL, add_update_nit_dvbt2, &tr); + + dvb_table_nit_descriptor_handler( + parms, dvb_scan_handler->nit, + terrestrial_delivery_system_descriptor, + NULL, add_update_nit_dvbt, &tr); return; case SYS_DVBS: case SYS_DVBS2: - nit_descriptor_handler(parms, dvb_scan_handler->nit, - satellite_delivery_system_descriptor, - NULL, add_update_nit_dvbs, &tr); + dvb_table_nit_descriptor_handler( + parms, dvb_scan_handler->nit, + satellite_delivery_system_descriptor, + NULL, add_update_nit_dvbs, &tr); return; default: dvb_log("Transponders detection not implemented for this standard yet."); diff -Nru v4l-utils-1.0.0+r2263/lib/libdvbv5/parse_string.h v4l-utils-1.0.0+r2364/lib/libdvbv5/parse_string.h --- v4l-utils-1.0.0+r2263/lib/libdvbv5/parse_string.h 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/lib/libdvbv5/parse_string.h 2014-08-12 09:02:18.000000000 +0000 @@ -17,6 +17,10 @@ * Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ +#if HAVE_VISIBILITY +#pragma GCC visibility push(hidden) +#endif + struct dvb_v5_fe_parms; void iconv_to_charset(struct dvb_v5_fe_parms *parms, @@ -29,3 +33,7 @@ void parse_string(struct dvb_v5_fe_parms *parms, char **dest, char **emph, const unsigned char *src, size_t len, char *default_charset, char *output_charset); + +#if HAVE_VISIBILITY +#pragma GCC visibility pop +#endif diff -Nru v4l-utils-1.0.0+r2263/lib/libdvbv5/tables/eit.c v4l-utils-1.0.0+r2364/lib/libdvbv5/tables/eit.c --- v4l-utils-1.0.0+r2263/lib/libdvbv5/tables/eit.c 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/lib/libdvbv5/tables/eit.c 2014-08-12 09:02:18.000000000 +0000 @@ -86,9 +86,9 @@ event->descriptor = NULL; event->next = NULL; dvb_time(event->dvbstart, &event->start); - event->duration = bcd((uint32_t) event->dvbduration[0]) * 3600 + - bcd((uint32_t) event->dvbduration[1]) * 60 + - bcd((uint32_t) event->dvbduration[2]); + event->duration = dvb_bcd((uint32_t) event->dvbduration[0]) * 3600 + + dvb_bcd((uint32_t) event->dvbduration[1]) * 60 + + dvb_bcd((uint32_t) event->dvbduration[2]); event->service_id = eit->header.id; @@ -163,9 +163,9 @@ uint16_t mjd; mjd = *(uint16_t *) data; - hour = bcd(data[2]); - min = bcd(data[3]); - sec = bcd(data[4]); + hour = dvb_bcd(data[2]); + min = dvb_bcd(data[3]); + sec = dvb_bcd(data[4]); year = ((mjd - 15078.2) / 365.25); month = ((mjd - 14956.1 - (int) (year * 365.25)) / 30.6001); day = mjd - 14956 - (int) (year * 365.25) - (int) (month * 30.6001); diff -Nru v4l-utils-1.0.0+r2263/lib/libdvbv5/tables/nit.c v4l-utils-1.0.0+r2364/lib/libdvbv5/tables/nit.c --- v4l-utils-1.0.0+r2263/lib/libdvbv5/tables/nit.c 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/lib/libdvbv5/tables/nit.c 2014-08-12 09:02:18.000000000 +0000 @@ -158,7 +158,8 @@ dvb_loginfo("|_ %d transports", transports); } -void nit_descriptor_handler(struct dvb_v5_fe_parms *parms, +void dvb_table_nit_descriptor_handler( + struct dvb_v5_fe_parms *parms, struct dvb_table_nit *nit, enum descriptors descriptor, nit_handler_callback_t *call_nit, diff -Nru v4l-utils-1.0.0+r2263/lib/libv4l2/libv4l2.c v4l-utils-1.0.0+r2364/lib/libv4l2/libv4l2.c --- v4l-utils-1.0.0+r2263/lib/libv4l2/libv4l2.c 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/lib/libv4l2/libv4l2.c 2014-08-12 09:02:18.000000000 +0000 @@ -94,6 +94,48 @@ }; static int devices_used; +static int v4l2_ensure_convert_mmap_buf(int index) +{ + long page_size; + + if (devices[index].convert_mmap_buf != MAP_FAILED) { + return 0; + } + + page_size = sysconf(_SC_PAGESIZE); + if (page_size < 0) { + int saved_err = errno; + V4L2_LOG_ERR("unable to retrieve page size\n"); + errno = saved_err; + return -1; + } + + /* round up to full page size */ + devices[index].convert_mmap_frame_size = + (((devices[index].dest_fmt.fmt.pix.sizeimage + page_size - 1) / + page_size) * page_size); + + devices[index].convert_mmap_buf_size = + devices[index].convert_mmap_frame_size * devices[index].no_frames; + + devices[index].convert_mmap_buf = (void *)SYS_MMAP(NULL, + devices[index].convert_mmap_buf_size, + PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE, + -1, 0); + + if (devices[index].convert_mmap_buf == MAP_FAILED) { + devices[index].convert_mmap_frame_size = 0; + devices[index].convert_mmap_buf_size = 0; + + int saved_err = errno; + V4L2_LOG_ERR("allocating conversion buffer\n"); + errno = saved_err; + return -1; + } + + return 0; +} static int v4l2_request_read_buffers(int index) { @@ -158,6 +200,7 @@ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; buf.index = i; + buf.reserved = buf.reserved2 = 0; result = devices[index].dev_ops->ioctl( devices[index].dev_ops_priv, devices[index].fd, VIDIOC_QUERYBUF, &buf); @@ -317,7 +360,8 @@ &devices[index].src_fmt, &devices[index].dest_fmt, devices[index].frame_pointers[buf->index], buf->bytesused, dest ? dest : (devices[index].convert_mmap_buf + - buf->index * V4L2_FRAME_BUF_SIZE), dest_size); + buf->index * devices[index].convert_mmap_frame_size), + dest_size); if (devices[index].first_frame) { /* Always treat convert errors as EAGAIN during the first few frames, as @@ -526,7 +570,7 @@ buf->index = 0; buf->m.offset = V4L2_MMAP_OFFSET_MAGIC | buf->index; - buf->length = V4L2_FRAME_BUF_SIZE; + buf->length = devices[index].convert_mmap_frame_size; if (devices[index].frame_map_count[buf->index]) buf->flags |= V4L2_BUF_FLAG_MAPPED; else @@ -545,6 +589,7 @@ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; buf.index = i; + buf.reserved = buf.reserved2 = 0; if (devices[index].dev_ops->ioctl( devices[index].dev_ops_priv, devices[index].fd, VIDIOC_QUERYBUF, @@ -735,6 +780,8 @@ devices[index].nreadbuffers = V4L2_DEFAULT_NREADBUFFERS; devices[index].convert = convert; devices[index].convert_mmap_buf = MAP_FAILED; + devices[index].convert_mmap_buf_size = 0; + devices[index].convert_mmap_frame_size = 0; for (i = 0; i < V4L2_MAX_NO_FRAMES; i++) { devices[index].frame_pointers[i] = MAP_FAILED; devices[index].frame_map_count[i] = 0; @@ -808,9 +855,11 @@ V4L2_LOG_WARN("v4l2 mmap buffers still mapped on close()\n"); } else { SYS_MUNMAP(devices[index].convert_mmap_buf, - devices[index].no_frames * V4L2_FRAME_BUF_SIZE); + devices[index].convert_mmap_buf_size); } devices[index].convert_mmap_buf = MAP_FAILED; + devices[index].convert_mmap_buf_size = 0; + devices[index].convert_mmap_frame_size = 0; } v4lconvert_destroy(devices[index].convert); free(devices[index].readbuf); @@ -864,8 +913,10 @@ v4l2_unrequest_read_buffers may change the no_frames, so free the convert mmap buffer */ SYS_MUNMAP(devices[index].convert_mmap_buf, - devices[index].no_frames * V4L2_FRAME_BUF_SIZE); + devices[index].convert_mmap_buf_size); devices[index].convert_mmap_buf = MAP_FAILED; + devices[index].convert_mmap_buf_size = 0; + devices[index].convert_mmap_frame_size = 0; if (devices[index].flags & V4L2_STREAM_CONTROLLED_BY_READ) { V4L2_LOG("deactivating read-stream for settings change\n"); @@ -1193,7 +1244,7 @@ case VIDIOC_S_STD: case VIDIOC_S_INPUT: case VIDIOC_S_DV_TIMINGS: { - struct v4l2_format src_fmt; + struct v4l2_format src_fmt = { 0 }; result = devices[index].dev_ops->ioctl( devices[index].dev_ops_priv, @@ -1334,23 +1385,12 @@ /* An application can do a DQBUF before mmap-ing in the buffer, but we need the buffer _now_ to write our converted data to it! */ - if (devices[index].convert_mmap_buf == MAP_FAILED) { - devices[index].convert_mmap_buf = (void *)SYS_MMAP(NULL, - (size_t)(devices[index].no_frames * V4L2_FRAME_BUF_SIZE), - PROT_READ | PROT_WRITE, - MAP_ANONYMOUS | MAP_PRIVATE, - -1, 0); - if (devices[index].convert_mmap_buf == MAP_FAILED) { - saved_err = errno; - V4L2_LOG_ERR("allocating conversion buffer\n"); - errno = saved_err; - result = -1; - break; - } - } + result = v4l2_ensure_convert_mmap_buf(index); + if (result) + break; result = v4l2_dequeue_and_convert(index, buf, 0, - V4L2_FRAME_BUF_SIZE); + devices[index].convert_mmap_frame_size); if (result >= 0) { buf->bytesused = result; result = 0; @@ -1575,7 +1615,7 @@ if (index == -1 || /* Check if the mmap data matches our answer to QUERY_BUF. If it doesn't, let the kernel handle it (to allow for mmap-based non capture use) */ - start || length != V4L2_FRAME_BUF_SIZE || + start || length != devices[index].convert_mmap_frame_size || ((unsigned int)offset & ~0xFFu) != V4L2_MMAP_OFFSET_MAGIC) { if (index != -1) V4L2_LOG("Passing mmap(%p, %d, ..., %x, through to the driver\n", @@ -1600,26 +1640,16 @@ goto leave; } - if (devices[index].convert_mmap_buf == MAP_FAILED) { - devices[index].convert_mmap_buf = (void *)SYS_MMAP(NULL, - (size_t)(devices[index].no_frames * V4L2_FRAME_BUF_SIZE), - PROT_READ | PROT_WRITE, - MAP_ANONYMOUS | MAP_PRIVATE, - -1, 0); - if (devices[index].convert_mmap_buf == MAP_FAILED) { - int saved_err = errno; - - V4L2_LOG_ERR("allocating conversion buffer\n"); - errno = saved_err; - result = MAP_FAILED; - goto leave; - } + if (v4l2_ensure_convert_mmap_buf(index)) { + errno = EINVAL; + result = MAP_FAILED; + goto leave; } devices[index].frame_map_count[buffer_index]++; result = devices[index].convert_mmap_buf + - buffer_index * V4L2_FRAME_BUF_SIZE; + buffer_index * devices[index].convert_mmap_frame_size; V4L2_LOG("Fake (conversion) mmap buf %u, seen by app at: %p\n", buffer_index, result); @@ -1637,10 +1667,11 @@ unsigned char *start = _start; /* Is this memory ours? */ - if (start != MAP_FAILED && length == V4L2_FRAME_BUF_SIZE) { + if (start != MAP_FAILED) { for (index = 0; index < devices_used; index++) if (devices[index].fd != -1 && devices[index].convert_mmap_buf != MAP_FAILED && + length == devices[index].convert_mmap_frame_size && start >= devices[index].convert_mmap_buf && (start - devices[index].convert_mmap_buf) % length == 0) break; @@ -1654,6 +1685,7 @@ /* Re-do our checks now that we have the lock, things may have changed */ if (devices[index].convert_mmap_buf != MAP_FAILED && + length == devices[index].convert_mmap_frame_size && start >= devices[index].convert_mmap_buf && (start - devices[index].convert_mmap_buf) % length == 0 && buffer_index < devices[index].no_frames) { diff -Nru v4l-utils-1.0.0+r2263/lib/libv4l2/libv4l2-priv.h v4l-utils-1.0.0+r2364/lib/libv4l2/libv4l2-priv.h --- v4l-utils-1.0.0+r2263/lib/libv4l2/libv4l2-priv.h 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/lib/libv4l2/libv4l2-priv.h 2014-08-12 09:02:18.000000000 +0000 @@ -31,7 +31,6 @@ be adjusted! */ #define V4L2_MAX_NO_FRAMES 32 #define V4L2_DEFAULT_NREADBUFFERS 4 -#define V4L2_FRAME_BUF_SIZE (4096 * 4096) #define V4L2_IGNORE_FIRST_FRAME_ERRORS 3 #define V4L2_DEFAULT_FPS 30 @@ -88,6 +87,8 @@ int first_frame; struct v4lconvert_data *convert; unsigned char *convert_mmap_buf; + size_t convert_mmap_buf_size; + size_t convert_mmap_frame_size; /* Frame bookkeeping is only done when in read or mmap-conversion mode */ unsigned char *frame_pointers[V4L2_MAX_NO_FRAMES]; int frame_sizes[V4L2_MAX_NO_FRAMES]; diff -Nru v4l-utils-1.0.0+r2263/lib/libv4l2rds/libv4l2rds.c v4l-utils-1.0.0+r2364/lib/libv4l2rds/libv4l2rds.c --- v4l-utils-1.0.0+r2263/lib/libv4l2rds/libv4l2rds.c 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/lib/libv4l2rds/libv4l2rds.c 2014-08-12 09:02:18.000000000 +0000 @@ -807,28 +807,28 @@ /* bit 2 of block B contains 1 bit of the Decoder Control Information (DI) * the segment number defines the bit position - * New bits are only accepted the segments arrive in the correct order */ + * New bits are only accepted if the segments arrive in the correct order */ bool bit2 = grp->data_b_lsb & 0x04; if (segment == 0 || segment == priv_state->next_di_segment) { switch (segment) { case 0: priv_state->new_di = set_bit(priv_state->new_di, - V4L2_RDS_FLAG_STEREO, bit2); + V4L2_RDS_FLAG_DYNAMIC_PTY, bit2); priv_state->next_di_segment = 1; break; case 1: priv_state->new_di = set_bit(priv_state->new_di, - V4L2_RDS_FLAG_ARTIFICIAL_HEAD, bit2); + V4L2_RDS_FLAG_COMPRESSED, bit2); priv_state->next_di_segment = 2; break; case 2: priv_state->new_di = set_bit(priv_state->new_di, - V4L2_RDS_FLAG_COMPRESSED, bit2); + V4L2_RDS_FLAG_ARTIFICIAL_HEAD, bit2); priv_state->next_di_segment = 3; break; case 3: priv_state->new_di = set_bit(priv_state->new_di, - V4L2_RDS_FLAG_DYNAMIC_PTY, bit2); + V4L2_RDS_FLAG_STEREO, bit2); /* check if the value of DI has changed, and store * and signal DI update in case */ if (handle->di != priv_state->new_di) { diff -Nru v4l-utils-1.0.0+r2263/lib/libv4lconvert/libv4lconvert.c v4l-utils-1.0.0+r2364/lib/libv4lconvert/libv4lconvert.c --- v4l-utils-1.0.0+r2263/lib/libv4lconvert/libv4lconvert.c 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/lib/libv4lconvert/libv4lconvert.c 2014-08-12 09:02:18.000000000 +0000 @@ -86,6 +86,10 @@ { V4L2_PIX_FMT_RGB565, 16, 4, 6, 0 }, { V4L2_PIX_FMT_BGR32, 32, 4, 6, 0 }, { V4L2_PIX_FMT_RGB32, 32, 4, 6, 0 }, + { V4L2_PIX_FMT_XBGR32, 32, 4, 6, 0 }, + { V4L2_PIX_FMT_XRGB32, 32, 4, 6, 0 }, + { V4L2_PIX_FMT_ABGR32, 32, 4, 6, 0 }, + { V4L2_PIX_FMT_ARGB32, 32, 4, 6, 0 }, /* yuv 4:2:2 formats */ { V4L2_PIX_FMT_YUYV, 16, 5, 4, 0 }, { V4L2_PIX_FMT_YVYU, 16, 5, 4, 0 }, @@ -1121,11 +1125,14 @@ break; case V4L2_PIX_FMT_RGB32: + case V4L2_PIX_FMT_XRGB32: + case V4L2_PIX_FMT_ARGB32: if (src_size < (width * height * 4)) { V4LCONVERT_ERR("short rgb32 data frame\n"); errno = EPIPE; result = -1; } + src++; switch (dest_pix_fmt) { case V4L2_PIX_FMT_RGB24: v4lconvert_rgb32_to_rgb24(src, dest, width, height, 0); @@ -1143,6 +1150,8 @@ break; case V4L2_PIX_FMT_BGR32: + case V4L2_PIX_FMT_XBGR32: + case V4L2_PIX_FMT_ABGR32: if (src_size < (width * height * 4)) { V4LCONVERT_ERR("short bgr32 data frame\n"); errno = EPIPE; diff -Nru v4l-utils-1.0.0+r2263/lib/libv4l-mplane/libv4l-mplane.c v4l-utils-1.0.0+r2364/lib/libv4l-mplane/libv4l-mplane.c --- v4l-utils-1.0.0+r2263/lib/libv4l-mplane/libv4l-mplane.c 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/lib/libv4l-mplane/libv4l-mplane.c 2014-08-12 09:02:18.000000000 +0000 @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -142,6 +143,9 @@ if (cap->device_caps & V4L2_CAP_VIDEO_OUTPUT_MPLANE) cap->device_caps |= V4L2_CAP_VIDEO_OUTPUT; + cap->capabilities |= V4L2_CAP_EXT_PIX_FORMAT; + cap->device_caps |= V4L2_CAP_EXT_PIX_FORMAT; + /* * Don't report mplane caps, as this will be handled via * this plugin @@ -166,6 +170,32 @@ } } +static void sanitize_format(struct v4l2_format *fmt) +{ + unsigned int offset; + + /* + * The v4l2_pix_format structure has been extended with fields that were + * not previously required to be set to zero by applications. The priv + * field, when set to a magic value, indicates the the extended fields + * are valid. We support these extended fields since struct + * v4l2_pix_format_mplane supports those fields as well. + * + * So this function will sanitize v4l2_pix_format if priv != PRIV_MAGIC + * by setting priv to that value and zeroing the remaining fields. + */ + + if (fmt->fmt.pix.priv == V4L2_PIX_FMT_PRIV_MAGIC) + return; + + fmt->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; + + offset = offsetof(struct v4l2_pix_format, priv) + + sizeof(fmt->fmt.pix.priv); + memset(((char *)&fmt->fmt.pix) + offset, 0, + sizeof(fmt->fmt.pix) - offset); +} + static int try_set_fmt_ioctl(int fd, unsigned long int cmd, struct v4l2_format *arg) { @@ -188,12 +218,15 @@ return SYS_IOCTL(fd, cmd, arg); } + sanitize_format(org); + fmt.fmt.pix_mp.width = org->fmt.pix.width; fmt.fmt.pix_mp.height = org->fmt.pix.height; fmt.fmt.pix_mp.pixelformat = org->fmt.pix.pixelformat; fmt.fmt.pix_mp.field = org->fmt.pix.field; fmt.fmt.pix_mp.colorspace = org->fmt.pix.colorspace; fmt.fmt.pix_mp.num_planes = 1; + fmt.fmt.pix_mp.flags = org->fmt.pix.flags; fmt.fmt.pix_mp.plane_fmt[0].bytesperline = org->fmt.pix.bytesperline; fmt.fmt.pix_mp.plane_fmt[0].sizeimage = org->fmt.pix.sizeimage; @@ -208,7 +241,7 @@ org->fmt.pix.colorspace = fmt.fmt.pix_mp.colorspace; org->fmt.pix.bytesperline = fmt.fmt.pix_mp.plane_fmt[0].bytesperline; org->fmt.pix.sizeimage = fmt.fmt.pix_mp.plane_fmt[0].sizeimage; - org->fmt.pix.priv = 0; + org->fmt.pix.flags = fmt.fmt.pix_mp.flags; return 0; } @@ -239,12 +272,14 @@ cbufs.index = arg->index; cbufs.count = arg->count; cbufs.memory = arg->memory; + sanitize_format(org); fmt->fmt.pix_mp.width = org->fmt.pix.width; fmt->fmt.pix_mp.height = org->fmt.pix.height; fmt->fmt.pix_mp.pixelformat = org->fmt.pix.pixelformat; fmt->fmt.pix_mp.field = org->fmt.pix.field; fmt->fmt.pix_mp.colorspace = org->fmt.pix.colorspace; fmt->fmt.pix_mp.num_planes = 1; + fmt->fmt.pix_mp.flags = org->fmt.pix.flags; fmt->fmt.pix_mp.plane_fmt[0].bytesperline = org->fmt.pix.bytesperline; fmt->fmt.pix_mp.plane_fmt[0].sizeimage = org->fmt.pix.sizeimage; @@ -259,6 +294,7 @@ org->fmt.pix.colorspace = fmt->fmt.pix_mp.colorspace; org->fmt.pix.bytesperline = fmt->fmt.pix_mp.plane_fmt[0].bytesperline; org->fmt.pix.sizeimage = fmt->fmt.pix_mp.plane_fmt[0].sizeimage; + org->fmt.pix.flags = fmt->fmt.pix_mp.flags; return ret; } @@ -288,6 +324,7 @@ if (ret) return ret; + memset(&org->fmt.pix, 0, sizeof(org->fmt.pix)); org->fmt.pix.width = fmt.fmt.pix_mp.width; org->fmt.pix.height = fmt.fmt.pix_mp.height; org->fmt.pix.pixelformat = fmt.fmt.pix_mp.pixelformat; @@ -295,7 +332,8 @@ org->fmt.pix.colorspace = fmt.fmt.pix_mp.colorspace; org->fmt.pix.bytesperline = fmt.fmt.pix_mp.plane_fmt[0].bytesperline; org->fmt.pix.sizeimage = fmt.fmt.pix_mp.plane_fmt[0].sizeimage; - org->fmt.pix.priv = 0; + org->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; + org->fmt.pix.flags = fmt.fmt.pix_mp.flags; /* * If the device doesn't support just one plane, there's diff -Nru v4l-utils-1.0.0+r2263/utils/dvb/dvb-fe-tool.c v4l-utils-1.0.0+r2364/utils/dvb/dvb-fe-tool.c --- v4l-utils-1.0.0+r2263/utils/dvb/dvb-fe-tool.c 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/dvb/dvb-fe-tool.c 2014-08-12 09:02:18.000000000 +0000 @@ -63,7 +63,7 @@ frontend = atoi(arg); break; case 'd': - delsys = parse_delsys(arg); + delsys = dvb_parse_delsys(arg); if (delsys < 0) return ARGP_ERR_UNKNOWN; break; diff -Nru v4l-utils-1.0.0+r2263/utils/dvb/dvb-format-convert.c v4l-utils-1.0.0+r2364/utils/dvb/dvb-format-convert.c --- v4l-utils-1.0.0+r2263/utils/dvb/dvb-format-convert.c 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/dvb/dvb-format-convert.c 2014-08-12 09:02:18.000000000 +0000 @@ -58,13 +58,13 @@ struct arguments *args = state->input; switch (k) { case 'I': - args->input_format = parse_format(optarg); + args->input_format = dvb_parse_format(optarg); break; case 'O': - args->output_format = parse_format(optarg); + args->output_format = dvb_parse_format(optarg); break; case 's': - args->delsys = parse_delsys(optarg); + args->delsys = dvb_parse_delsys(optarg); break; default: return ARGP_ERR_UNKNOWN; @@ -87,8 +87,8 @@ } printf("Writing file %s\n", args->output_file); - ret = write_file_format(args->output_file, dvb_file, - args->delsys, args->output_format); + ret = dvb_write_file_format(args->output_file, dvb_file, + args->delsys, args->output_format); return ret; } diff -Nru v4l-utils-1.0.0+r2263/utils/dvb/dvbv5-scan.c v4l-utils-1.0.0+r2364/utils/dvb/dvbv5-scan.c --- v4l-utils-1.0.0+r2263/utils/dvb/dvbv5-scan.c 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/dvb/dvbv5-scan.c 2014-08-12 09:02:18.000000000 +0000 @@ -243,16 +243,16 @@ * If the channel file has duplicated frequencies, or some * entries without any frequency at all, discard. */ - if (retrieve_entry_prop(entry, DTV_FREQUENCY, &freq)) + if (dvb_retrieve_entry_prop(entry, DTV_FREQUENCY, &freq)) continue; - shift = estimate_freq_shift(parms); + shift = dvb_estimate_freq_shift(parms); - if (retrieve_entry_prop(entry, DTV_POLARIZATION, &pol)) + if (dvb_retrieve_entry_prop(entry, DTV_POLARIZATION, &pol)) pol = POLARIZATION_OFF; - if (!new_freq_is_needed(dvb_file->first_entry, entry, - freq, pol, shift)) + if (!dvb_new_freq_is_needed(dvb_file->first_entry, entry, + freq, pol, shift)) continue; count++; @@ -277,7 +277,7 @@ /* * Store the service entry */ - store_dvb_channel(&dvb_file_new, parms, dvb_scan_handler, + dvb_store_channel(&dvb_file_new, parms, dvb_scan_handler, args->get_detected, args->get_nit); /* @@ -295,8 +295,8 @@ } if (dvb_file_new) - write_file_format(args->output, dvb_file_new, - parms->current_sys, args->output_format); + dvb_write_file_format(args->output, dvb_file_new, + parms->current_sys, args->output_format); dvb_file_free(dvb_file); if (dvb_file_new) @@ -370,10 +370,10 @@ args->timeout_multiply = strtoul(optarg, NULL, 0); break; case 'I': - args->input_format = parse_format(optarg); + args->input_format = dvb_parse_format(optarg); break; case 'O': - args->output_format = parse_format(optarg); + args->output_format = dvb_parse_format(optarg); break; case 'o': args->output = optarg; @@ -437,11 +437,11 @@ lnb = dvb_sat_search_lnb(args.lnb_name); if (lnb < 0) { printf("Please select one of the LNBf's below:\n"); - print_all_lnb(); + dvb_print_all_lnb(); exit(1); } else { printf("Using LNBf "); - print_lnb(lnb); + dvb_print_lnb(lnb); } } diff -Nru v4l-utils-1.0.0+r2263/utils/dvb/dvbv5-zap.c v4l-utils-1.0.0+r2364/utils/dvb/dvbv5-zap.c --- v4l-utils-1.0.0+r2263/utils/dvb/dvbv5-zap.c 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/dvb/dvbv5-zap.c 2014-08-12 09:02:18.000000000 +0000 @@ -174,7 +174,7 @@ if (freq) { for (entry = dvb_file->first_entry; entry != NULL; entry = entry->next) { - retrieve_entry_prop(entry, DTV_FREQUENCY, &f); + dvb_retrieve_entry_prop(entry, DTV_FREQUENCY, &f); if (f == freq) break; } @@ -232,7 +232,7 @@ *sid = entry->service_id; /* First of all, set the delivery system */ - retrieve_entry_prop(entry, DTV_DELIVERY_SYSTEM, &sys); + dvb_retrieve_entry_prop(entry, DTV_DELIVERY_SYSTEM, &sys); dvb_set_compat_delivery_system(parms, sys); /* Copy data into parms */ @@ -460,7 +460,7 @@ args->timeout = strtoul(optarg, NULL, 0); break; case 'I': - args->input_format = parse_format(optarg); + args->input_format = dvb_parse_format(optarg); break; case 'o': args->filename = strdup(optarg); @@ -738,11 +738,11 @@ lnb = dvb_sat_search_lnb(args.lnb_name); if (lnb < 0) { printf("Please select one of the LNBf's below:\n"); - print_all_lnb(); + dvb_print_all_lnb(); exit(1); } else { printf("Using LNBf "); - print_lnb(lnb); + dvb_print_lnb(lnb); } } @@ -817,7 +817,7 @@ sid); goto err; } - pmtpid = get_pmt_pid(args.demux_dev, sid); + pmtpid = dvb_get_pmt_pid(args.demux_dev, sid); if (pmtpid <= 0) { fprintf(stderr, "couldn't find pmt-pid for sid %04x\n", sid); diff -Nru v4l-utils-1.0.0+r2263/utils/keytable/ir-keytable.1 v4l-utils-1.0.0+r2364/utils/keytable/ir-keytable.1 --- v4l-utils-1.0.0+r2263/utils/keytable/ir-keytable.1 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/keytable/ir-keytable.1 2014-08-12 09:02:18.000000000 +0000 @@ -78,7 +78,7 @@ .IP \fISCANKEY\fR a set of scancode1=keycode1,scancode2=keycode2.. value pairs .IP \fIPROTOCOL\fR -protocol name (nec, rc\-5, rc\-6, other) to be enabled +protocol name to be enabled (case insensitive). Supported protocols are: NEC, RC-5, RC-6, JVC, SONY, SANYO, LIRC, RC-5-SZ, SHARP, MCE-KBD, XMP, other, all. .IP \fIDELAY\fR Delay before repeating a keystroke .IP \fIPERIOD\fR diff -Nru v4l-utils-1.0.0+r2263/utils/keytable/keytable.c v4l-utils-1.0.0+r2364/utils/keytable/keytable.c --- v4l-utils-1.0.0+r2263/utils/keytable/keytable.c 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/keytable/keytable.c 2014-08-12 09:02:18.000000000 +0000 @@ -86,6 +86,9 @@ LIRC = 1 << 5, SANYO = 1 << 6, RC_5_SZ = 1 << 7, + SHARP = 1 << 8, + MCE_KBD = 1 << 9, + XMP = 1 << 10, OTHER = 1 << 31, }; @@ -110,7 +113,8 @@ " SYSDEV - the ir class as found at /sys/class/rc\n" " TABLE - a file with a set of scancode=keycode value pairs\n" " SCANKEY - a set of scancode1=keycode1,scancode2=keycode2.. value pairs\n" - " PROTOCOL - protocol name (nec, rc-5, rc-6, jvc, sony, sanyo, rc-5-sz, lirc, other) to be enabled\n" + " PROTOCOL - protocol name (nec, rc-5, rc-6, jvc, sony, sanyo, rc-5-sz, lirc,\n" + " sharp, mce_kbd, xmp, other, all) to be enabled\n" " DELAY - Delay before repeating a keystroke\n" " PERIOD - Period to repeat a keystroke\n" " CFGFILE - configuration file that associates a driver/table name with a keymap file\n" @@ -234,6 +238,12 @@ ch_proto |= SANYO; else if (!strcasecmp(p,"rc-5-sz")) ch_proto |= RC_5_SZ; + else if (!strcasecmp(p,"sharp")) + ch_proto |= SHARP; + else if (!strcasecmp(p,"mce-kbd")) + ch_proto |= MCE_KBD; + else if (!strcasecmp(p,"xmp")) + ch_proto |= XMP; else if (!strcasecmp(p,"other") || !strcasecmp(p,"unknown")) ch_proto |= OTHER; else { @@ -471,6 +481,14 @@ ch_proto |= LIRC; else if (!strcasecmp(p,"rc-5-sz")) ch_proto |= RC_5_SZ; + else if (!strcasecmp(p,"sharp")) + ch_proto |= RC_5_SZ; + else if (!strcasecmp(p,"mce-kbd")) + ch_proto |= RC_5_SZ; + else if (!strcasecmp(p,"xmp")) + ch_proto |= XMP; + else if (!strcasecmp(p,"all")) + ch_proto |= ~0; else goto err_inval; p = strtok(NULL, ",;"); @@ -744,6 +762,12 @@ proto |= SANYO; else if (!strcmp(p, "rc-5-sz")) proto |= RC_5_SZ; + else if (!strcmp(p, "sharp")) + proto |= SHARP; + else if (!strcmp(p, "mce-kbd")) + proto |= MCE_KBD; + else if (!strcmp(p, "xmp")) + proto |= XMP; else proto |= OTHER; @@ -790,6 +814,15 @@ if (rc_dev->current & RC_5_SZ) fprintf(fp, "rc-5-sz "); + if (rc_dev->current & SHARP) + fprintf(fp, "sharp "); + + if (rc_dev->current & MCE_KBD) + fprintf(fp, "mce_kbd "); + + if (rc_dev->current & XMP) + fprintf(fp, "xmp "); + if (rc_dev->current & OTHER) fprintf(fp, "unknown "); @@ -921,6 +954,12 @@ proto = LIRC; else if (!strcmp(p, "rc-5-sz")) proto = RC_5_SZ; + else if (!strcmp(p, "sharp")) + proto = SHARP; + else if (!strcmp(p, "mce-kbd")) + proto = MCE_KBD; + else if (!strcmp(p, "xmp")) + proto = XMP; else proto = OTHER; @@ -977,6 +1016,15 @@ if (rc_dev->current & RC_5_SZ) fprintf(fp, "+rc-5-sz\n"); + if (rc_dev->current & SHARP) + fprintf(fp, "+sharp\n"); + + if (rc_dev->current & MCE_KBD) + fprintf(fp, "+mce-kbd\n"); + + if (rc_dev->current & XMP) + fprintf(fp, "+xmp\n"); + if (rc_dev->current & OTHER) fprintf(fp, "+unknown\n"); @@ -1006,6 +1054,12 @@ fprintf (stderr, "LIRC "); if (proto & RC_5_SZ) fprintf (stderr, "RC-5-SZ "); + if (proto & SHARP) + fprintf (stderr, "SHARP "); + if (proto & MCE_KBD) + fprintf (stderr, "MCE_KBD "); + if (proto & XMP) + fprintf (stderr, "XMP "); if (proto & OTHER) fprintf (stderr, "other "); } @@ -1128,6 +1182,10 @@ rc_dev->supported |= SONY; if (v1_get_sw_enabled_protocol(cur->name)) rc_dev->current |= SONY; + } else if (strstr(cur->name, "/xmp_decoder")) { + rc_dev->supported |= XMP; + if (v1_get_sw_enabled_protocol(cur->name)) + rc_dev->current |= XMP; } } @@ -1138,6 +1196,12 @@ { int rc = 0; + rc_dev->current &= rc_dev->supported; + if (!rc_dev->current) { + fprintf(stderr, "Invalid protocols selected\n"); + return EINVAL; + } + if (rc_dev->version == VERSION_2) { rc = v2_set_protocols(rc_dev); return rc; @@ -1159,6 +1223,9 @@ if (rc_dev->supported & SONY) rc += v1_set_sw_enabled_protocol(rc_dev, "/sony_decoder", rc_dev->current & SONY); + if (rc_dev->supported & XMP) + rc += v1_set_sw_enabled_protocol(rc_dev, "/xmp_decoder", + rc_dev->current & XMP); } else { rc = v1_set_hw_protocols(rc_dev); } diff -Nru v4l-utils-1.0.0+r2263/utils/keytable/parse.h v4l-utils-1.0.0+r2364/utils/keytable/parse.h --- v4l-utils-1.0.0+r2263/utils/keytable/parse.h 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/keytable/parse.h 2014-08-12 09:02:18.000000000 +0000 @@ -267,7 +267,7 @@ {"KEY_VIDEO_NEXT", 241}, {"KEY_VIDEO_PREV", 242}, {"KEY_BRIGHTNESS_CYCLE", 243}, - {"KEY_BRIGHTNESS_ZERO", 244}, + {"KEY_BRIGHTNESS_AUTO", 244}, {"KEY_DISPLAY_OFF", 245}, {"KEY_WWAN", 246}, {"KEY_RFKILL", 247}, @@ -499,6 +499,15 @@ {"BTN_DPAD_LEFT", 0x222}, {"BTN_DPAD_RIGHT", 0x223}, {"KEY_ALS_TOGGLE", 0x230}, + {"KEY_BUTTONCONFIG", 0x240}, + {"KEY_TASKMANAGER", 0x241}, + {"KEY_JOURNAL", 0x242}, + {"KEY_CONTROLPANEL", 0x243}, + {"KEY_APPSELECT", 0x244}, + {"KEY_SCREENSAVER", 0x245}, + {"KEY_VOICECOMMAND", 0x246}, + {"KEY_BRIGHTNESS_MIN", 0x250}, + {"KEY_BRIGHTNESS_MAX", 0x251}, {"BTN_TRIGGER_HAPPY", 0x2c0}, {"BTN_TRIGGER_HAPPY1", 0x2c0}, {"BTN_TRIGGER_HAPPY2", 0x2c1}, diff -Nru v4l-utils-1.0.0+r2263/utils/keytable/rc_keymaps/ati_x10 v4l-utils-1.0.0+r2364/utils/keytable/rc_keymaps/ati_x10 --- v4l-utils-1.0.0+r2263/utils/keytable/rc_keymaps/ati_x10 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/keytable/rc_keymaps/ati_x10 2014-08-12 09:02:18.000000000 +0000 @@ -1,4 +1,17 @@ # table ati_x10, type: OTHER +0x00 KEY_A +0x01 KEY_B +0x02 KEY_POWER +0x03 KEY_TV +0x04 KEY_DVD +0x05 KEY_WWW +0x06 KEY_BOOKMARKS +0x07 KEY_EDIT +0x09 KEY_VOLUMEDOWN +0x08 KEY_VOLUMEUP +0x0a KEY_MUTE +0x0b KEY_CHANNELUP +0x0c KEY_CHANNELDOWN 0x0d KEY_1 0x0e KEY_2 0x0f KEY_3 @@ -8,41 +21,28 @@ 0x13 KEY_7 0x14 KEY_8 0x15 KEY_9 +0x16 KEY_MENU 0x17 KEY_0 -0x00 KEY_A -0x01 KEY_B +0x18 KEY_SETUP 0x19 KEY_C +0x1a KEY_UP 0x1b KEY_D -0x21 KEY_E -0x23 KEY_F -0x18 KEY_KPENTER -0x16 KEY_MENU -0x02 KEY_POWER -0x03 KEY_TV -0x04 KEY_DVD -0x05 KEY_WWW -0x06 KEY_BOOKMARKS -0x07 KEY_EDIT -0x1c KEY_COFFEE -0x20 KEY_FRONT +0x1c KEY_PROPS 0x1d KEY_LEFT +0x1e KEY_OK 0x1f KEY_RIGHT +0x20 KEY_SCREEN +0x21 KEY_E 0x22 KEY_DOWN -0x1a KEY_UP -0x1e KEY_OK -0x09 KEY_VOLUMEDOWN -0x08 KEY_VOLUMEUP -0x0a KEY_MUTE -0x0b KEY_CHANNELUP -0x0c KEY_CHANNELDOWN -0x27 KEY_RECORD -0x25 KEY_PLAY +0x23 KEY_F 0x24 KEY_REWIND -0x26 KEY_FORWARD -0x28 KEY_STOP +0x25 KEY_PLAY +0x26 KEY_FASTFORWARD +0x27 KEY_RECORD +0x28 KEY_STOPCD 0x29 KEY_PAUSE -0x2b KEY_PREVIOUS 0x2a KEY_NEXT +0x2b KEY_PREVIOUS 0x2d KEY_INFO 0x2e KEY_HOME 0x2f KEY_END diff -Nru v4l-utils-1.0.0+r2263/utils/keytable/rc_keymaps/behold v4l-utils-1.0.0+r2364/utils/keytable/rc_keymaps/behold --- v4l-utils-1.0.0+r2263/utils/keytable/rc_keymaps/behold 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/keytable/rc_keymaps/behold 2014-08-12 09:02:18.000000000 +0000 @@ -1,35 +1,35 @@ # table behold, type: NEC -0x6b861c KEY_TUNER -0x6b8612 KEY_POWER -0x6b8601 KEY_1 -0x6b8602 KEY_2 -0x6b8603 KEY_3 -0x6b8604 KEY_4 -0x6b8605 KEY_5 -0x6b8606 KEY_6 -0x6b8607 KEY_7 -0x6b8608 KEY_8 -0x6b8609 KEY_9 -0x6b860a KEY_AGAIN -0x6b8600 KEY_0 -0x6b8617 KEY_MODE -0x6b8614 KEY_SCREEN -0x6b8610 KEY_ZOOM -0x6b860b KEY_CHANNELUP -0x6b8618 KEY_VOLUMEDOWN -0x6b8616 KEY_OK -0x6b860c KEY_VOLUMEUP -0x6b8615 KEY_CHANNELDOWN -0x6b8611 KEY_MUTE -0x6b860d KEY_INFO -0x6b860f KEY_RECORD -0x6b861b KEY_PLAYPAUSE -0x6b861a KEY_STOP -0x6b860e KEY_TEXT -0x6b861f KEY_RED -0x6b861e KEY_VIDEO -0x6b861d KEY_SLEEP -0x6b8613 KEY_GREEN -0x6b8619 KEY_BLUE -0x6b8658 KEY_SLOW -0x6b865c KEY_CAMERA +0x866b1c KEY_TUNER +0x866b12 KEY_POWER +0x866b01 KEY_1 +0x866b02 KEY_2 +0x866b03 KEY_3 +0x866b04 KEY_4 +0x866b05 KEY_5 +0x866b06 KEY_6 +0x866b07 KEY_7 +0x866b08 KEY_8 +0x866b09 KEY_9 +0x866b0a KEY_AGAIN +0x866b00 KEY_0 +0x866b17 KEY_MODE +0x866b14 KEY_SCREEN +0x866b10 KEY_ZOOM +0x866b0b KEY_CHANNELUP +0x866b18 KEY_VOLUMEDOWN +0x866b16 KEY_OK +0x866b0c KEY_VOLUMEUP +0x866b15 KEY_CHANNELDOWN +0x866b11 KEY_MUTE +0x866b0d KEY_INFO +0x866b0f KEY_RECORD +0x866b1b KEY_PLAYPAUSE +0x866b1a KEY_STOP +0x866b0e KEY_TEXT +0x866b1f KEY_RED +0x866b1e KEY_VIDEO +0x866b1d KEY_SLEEP +0x866b13 KEY_GREEN +0x866b19 KEY_BLUE +0x866b58 KEY_SLOW +0x866b5c KEY_CAMERA diff -Nru v4l-utils-1.0.0+r2263/utils/keytable/rc_keymaps/nebula v4l-utils-1.0.0+r2364/utils/keytable/rc_keymaps/nebula --- v4l-utils-1.0.0+r2263/utils/keytable/rc_keymaps/nebula 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/keytable/rc_keymaps/nebula 2014-08-12 09:02:18.000000000 +0000 @@ -1,56 +1,56 @@ -# table nebula, type: UNKNOWN -0x00 KEY_0 -0x01 KEY_1 -0x02 KEY_2 -0x03 KEY_3 -0x04 KEY_4 -0x05 KEY_5 -0x06 KEY_6 -0x07 KEY_7 -0x08 KEY_8 -0x09 KEY_9 -0x0a KEY_TV -0x0b KEY_AUX -0x0c KEY_DVD -0x0d KEY_POWER -0x0e KEY_CAMERA -0x0f KEY_AUDIO -0x10 KEY_INFO -0x11 KEY_F13 -0x12 KEY_F14 -0x13 KEY_EPG -0x14 KEY_EXIT -0x15 KEY_MENU -0x16 KEY_UP -0x17 KEY_DOWN -0x18 KEY_LEFT -0x19 KEY_RIGHT -0x1a KEY_ENTER -0x1b KEY_CHANNELUP -0x1c KEY_CHANNELDOWN -0x1d KEY_VOLUMEUP -0x1e KEY_VOLUMEDOWN -0x1f KEY_RED -0x20 KEY_GREEN -0x21 KEY_YELLOW -0x22 KEY_BLUE -0x23 KEY_SUBTITLE -0x24 KEY_F15 -0x25 KEY_TEXT -0x26 KEY_MUTE -0x27 KEY_REWIND -0x28 KEY_STOP -0x29 KEY_PLAY -0x2a KEY_FASTFORWARD -0x2b KEY_F16 -0x2c KEY_PAUSE -0x2d KEY_PLAY -0x2e KEY_RECORD -0x2f KEY_F17 -0x30 KEY_KPPLUS -0x31 KEY_KPMINUS -0x32 KEY_F18 -0x33 KEY_F19 -0x34 KEY_EMAIL -0x35 KEY_PHONE -0x36 KEY_PC +# table nebula, type: RC5 +0x0000 KEY_0 +0x0001 KEY_1 +0x0002 KEY_2 +0x0003 KEY_3 +0x0004 KEY_4 +0x0005 KEY_5 +0x0006 KEY_6 +0x0007 KEY_7 +0x0008 KEY_8 +0x0009 KEY_9 +0x000a KEY_TV +0x000b KEY_AUX +0x000c KEY_DVD +0x000d KEY_POWER +0x000e KEY_CAMERA +0x000f KEY_AUDIO +0x0010 KEY_INFO +0x0011 KEY_F13 +0x0012 KEY_F14 +0x0013 KEY_EPG +0x0014 KEY_EXIT +0x0015 KEY_MENU +0x0016 KEY_UP +0x0017 KEY_DOWN +0x0018 KEY_LEFT +0x0019 KEY_RIGHT +0x001a KEY_ENTER +0x001b KEY_CHANNELUP +0x001c KEY_CHANNELDOWN +0x001d KEY_VOLUMEUP +0x001e KEY_VOLUMEDOWN +0x001f KEY_RED +0x0020 KEY_GREEN +0x0021 KEY_YELLOW +0x0022 KEY_BLUE +0x0023 KEY_SUBTITLE +0x0024 KEY_F15 +0x0025 KEY_TEXT +0x0026 KEY_MUTE +0x0027 KEY_REWIND +0x0028 KEY_STOP +0x0029 KEY_PLAY +0x002a KEY_FASTFORWARD +0x002b KEY_F16 +0x002c KEY_PAUSE +0x002d KEY_PLAY +0x002e KEY_RECORD +0x002f KEY_F17 +0x0030 KEY_KPPLUS +0x0031 KEY_KPMINUS +0x0032 KEY_F18 +0x0033 KEY_F19 +0x0034 KEY_EMAIL +0x0035 KEY_PHONE +0x0036 KEY_PC diff -Nru v4l-utils-1.0.0+r2263/utils/keytable/rc_maps.cfg v4l-utils-1.0.0+r2364/utils/keytable/rc_maps.cfg --- v4l-utils-1.0.0+r2263/utils/keytable/rc_maps.cfg 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/keytable/rc_maps.cfg 2014-08-12 09:02:18.000000000 +0000 @@ -30,107 +30,107 @@ # devices supported by the linux kernel #driver table file -* rc-digittrade digittrade -* rc-powercolor-real-angel powercolor_real_angel -* rc-budget-ci-old budget_ci_old -* rc-imon-pad imon_pad -* rc-eztv eztv -* rc-msi-tvanywhere-plus msi_tvanywhere_plus -* rc-pixelview-002t pixelview_002t -* rc-tbs-nec tbs_nec -* rc-delock-61959 delock_61959 -* rc-total-media-in-hand total_media_in_hand -* rc-technisat-usb2 technisat_usb2 -* rc-kworld-315u kworld_315u -* rc-avermedia-rm-ks avermedia_rm_ks +* rc-avermedia-dvbt avermedia_dvbt * rc-msi-digivox-ii msi_digivox_ii -* rc-norwood norwood -* rc-nec-terratec-cinergy-xs nec_terratec_cinergy_xs -* rc-su3000 su3000 -* rc-videomate-s350 videomate_s350 +* rc-budget-ci-old budget_ci_old +* rc-ati-tv-wonder-hd-600 ati_tv_wonder_hd_600 +* rc-winfast winfast +* rc-dntv-live-dvb-t dntv_live_dvb_t +* rc-gotview7135 gotview7135 +* rc-cinergy cinergy +* rc-kaiomy kaiomy * rc-digitalnow-tinytwin digitalnow_tinytwin -* rc-rc6-mce rc6_mce -* rc-avermedia-cardbus avermedia_cardbus -* rc-dib0700-nec dib0700_nec -* rc-nebula nebula -* rc-terratec-slim terratec_slim -* rc-videomate-k100 videomate_k100 -* rc-medion-x10-or2x medion_x10_or2x -* rc-cinergy-1400 cinergy_1400 -* rc-dm1105-nec dm1105_nec +* rc-behold behold +* rc-avertv-303 avertv_303 +* rc-it913x-v2 it913x_v2 * rc-terratec-slim-2 terratec_slim_2 -* rc-flydvb flydvb -* rc-pinnacle-pctv-hd pinnacle_pctv_hd -* rc-pctv-sedna pctv_sedna -* rc-it913x-v1 it913x_v1 -* rc-avermedia avermedia -* rc-iodata-bctv7e iodata_bctv7e -* rc-real-audio-220-32-keys real_audio_220_32_keys -* rc-asus-ps3-100 asus_ps3_100 -* rc-pv951 pv951 +* rc-fusionhdtv-mce fusionhdtv_mce +* rc-encore-enltv-fm53 encore_enltv_fm53 +* rc-streamzap streamzap +* rc-powercolor-real-angel powercolor_real_angel +* rc-genius-tvgo-a11mce genius_tvgo_a11mce +* rc-flyvideo flyvideo +* rc-adstech-dvb-t-pci adstech_dvb_t_pci +* rc-msi-digivox-iii msi_digivox_iii * rc-avermedia-m135a avermedia_m135a -* rc-reddo reddo +* rc-tevii-nec tevii_nec +* rc-dntv-live-dvbt-pro dntv_live_dvbt_pro +* rc-encore-enltv encore_enltv +* rc-terratec-slim terratec_slim +* rc-total-media-in-hand total_media_in_hand +* rc-gadmei-rm008z gadmei_rm008z +* rc-kworld-plus-tv-analog kworld_plus_tv_analog +* rc-trekstor trekstor * rc-kworld-pc150u kworld_pc150u -* rc-kaiomy kaiomy -* rc-avermedia-dvbt avermedia_dvbt -* rc-azurewave-ad-tu700 azurewave_ad_tu700 -* rc-dntv-live-dvb-t dntv_live_dvb_t -* rc-cinergy cinergy +* rc-ati-x10 ati_x10 +* rc-iodata-bctv7e iodata_bctv7e +* rc-rc6-mce rc6_mce +* rc-technisat-usb2 technisat_usb2 +* rc-hauppauge hauppauge +* rc-terratec-cinergy-xs terratec_cinergy_xs +* rc-tbs-nec tbs_nec +* rc-norwood norwood * rc-npgtech npgtech +* rc-pinnacle-color pinnacle_color +* rc-pinnacle-grey pinnacle_grey +* rc-avermedia-cardbus avermedia_cardbus +* rc-videomate-tv-pvr videomate_tv_pvr +* rc-pixelview pixelview +* rc-nebula nebula * rc-leadtek-y04g0051 leadtek_y04g0051 +* rc-avermedia-m733a-rm-k6 avermedia_m733a_rm_k6 +* rc-pixelview-new pixelview_new * rc-manli manli -* rc-streamzap streamzap +* rc-delock-61959 delock_61959 +* rc-videomate-k100 videomate_k100 * rc-winfast-usbii-deluxe winfast_usbii_deluxe -* rc-behold behold -* rc-gadmei-rm008z gadmei_rm008z -* rc-purpletv purpletv -* rc-it913x-v2 it913x_v2 -* rc-adstech-dvb-t-pci adstech_dvb_t_pci -* rc-terratec-cinergy-xs terratec_cinergy_xs -* rc-dntv-live-dvbt-pro dntv_live_dvbt_pro -* rc-flyvideo flyvideo -* rc-tivo tivo -* rc-trekstor trekstor -* rc-em-terratec em_terratec -* rc-gotview7135 gotview7135 +* rc-pctv-sedna pctv_sedna +* rc-avermedia-a16d avermedia_a16d +* rc-imon-pad imon_pad +* rc-encore-enltv2 encore_enltv2 +* rc-nec-terratec-cinergy-xs nec_terratec_cinergy_xs +* rc-it913x-v1 it913x_v1 +* rc-apac-viewcomp apac_viewcomp +* rc-eztv eztv +* rc-proteus-2309 proteus_2309 * rc-msi-tvanywhere msi_tvanywhere -* rc-alink-dtu-m alink_dtu_m -* rc-videomate-tv-pvr videomate_tv_pvr -* rc-avertv-303 avertv_303 -* rc-ati-tv-wonder-hd-600 ati_tv_wonder_hd_600 -* rc-ati-x10 ati_x10 +* rc-dib0700-nec dib0700_nec * rc-medion-x10-digitainer medion_x10_digitainer -* rc-dib0700-rc5 dib0700_rc5 -* rc-medion-x10 medion_x10 -* rc-genius-tvgo-a11mce genius_tvgo_a11mce -* rc-avermedia-a16d avermedia_a16d -* rc-behold-columbus behold_columbus -* rc-pinnacle-grey pinnacle_grey * rc-imon-mce imon_mce -* rc-snapstream-firefly snapstream_firefly -* rc-hauppauge hauppauge -* rc-asus-pc39 asus_pc39 -* rc-kworld-plus-tv-analog kworld_plus_tv_analog -* rc-fusionhdtv-mce fusionhdtv_mce -* rc-encore-enltv-fm53 encore_enltv_fm53 -* rc-evga-indtube evga_indtube +* rc-tivo tivo +* rc-medion-x10 medion_x10 +* rc-pv951 pv951 * rc-total-media-in-hand-02 total_media_in_hand_02 -* rc-msi-digivox-iii msi_digivox_iii -* rc-lme2510 lme2510 -* rc-winfast winfast +* rc-pixelview-002t pixelview_002t +* rc-reddo reddo +* rc-pinnacle-pctv-hd pinnacle_pctv_hd +* rc-purpletv purpletv +* rc-azurewave-ad-tu700 azurewave_ad_tu700 +* rc-su3000 su3000 +* rc-avermedia avermedia +* rc-evga-indtube evga_indtube +* rc-avermedia-rm-ks avermedia_rm_ks +* rc-kworld-315u kworld_315u +* rc-behold-columbus behold_columbus * rc-pixelview-mk12 pixelview_mk12 -* rc-encore-enltv encore_enltv +* rc-dib0700-rc5 dib0700_rc5 +* rc-tt-1500 tt_1500 +* rc-em-terratec em_terratec +* rc-flydvb flydvb +* rc-cinergy-1400 cinergy_1400 +* rc-videomate-s350 videomate_s350 * rc-anysee anysee -* rc-pixelview-new pixelview_new +* rc-asus-pc39 asus_pc39 +* rc-digittrade digittrade * rc-twinhan1027 twinhan_vp1027_dvbs -* rc-tevii-nec tevii_nec -* rc-apac-viewcomp apac_viewcomp -* rc-pinnacle-color pinnacle_color -* rc-encore-enltv2 encore_enltv2 -* rc-pixelview pixelview -* rc-avermedia-m733a-rm-k6 avermedia_m733a_rm_k6 -* rc-tt-1500 tt_1500 -* rc-proteus-2309 proteus_2309 +* rc-real-audio-220-32-keys real_audio_220_32_keys +* rc-medion-x10-or2x medion_x10_or2x +* rc-snapstream-firefly snapstream_firefly +* rc-lme2510 lme2510 +* rc-dm1105-nec dm1105_nec +* rc-asus-ps3-100 asus_ps3_100 +* rc-alink-dtu-m alink_dtu_m +* rc-msi-tvanywhere-plus msi_tvanywhere_plus # * * a800 # found in a800.c # * * af9005 # found in af9005-remote.c # * * cinergyt2 # found in cinergyT2-core.c diff -Nru v4l-utils-1.0.0+r2263/utils/libv4l2util/v4l2_driver.c v4l-utils-1.0.0+r2364/utils/libv4l2util/v4l2_driver.c --- v4l-utils-1.0.0+r2263/utils/libv4l2util/v4l2_driver.c 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/libv4l2util/v4l2_driver.c 2014-08-12 09:02:18.000000000 +0000 @@ -102,8 +102,16 @@ if (V4L2_CAP_VIDEO_CAPTURE & caps) strcat (s,"CAPTURE "); + if (V4L2_CAP_VIDEO_CAPTURE_MPLANE & caps) + strcat (s,"CAPTURE_MPLANE "); if (V4L2_CAP_VIDEO_OUTPUT & caps) strcat (s,"OUTPUT "); + if (V4L2_CAP_VIDEO_OUTPUT_MPLANE & caps) + strcat (s,"OUTPUT_MPLANE "); + if (V4L2_CAP_VIDEO_M2M & caps) + strcat (s,"M2M "); + if (V4L2_CAP_VIDEO_M2M_MPLANE & caps) + strcat (s,"M2M_MPLANE "); if (V4L2_CAP_VIDEO_OVERLAY & caps) strcat (s,"OVERLAY "); if (V4L2_CAP_VBI_CAPTURE & caps) @@ -116,8 +124,16 @@ strcat (s,"SLICED_VBI_OUTPUT "); if (V4L2_CAP_RDS_CAPTURE & caps) strcat (s,"RDS_CAPTURE "); + if (V4L2_CAP_RDS_OUTPUT & caps) + strcat (s,"RDS_OUTPUT "); + if (V4L2_CAP_SDR_CAPTURE & caps) + strcat (s,"SDR_CAPTURE "); if (V4L2_CAP_TUNER & caps) strcat (s,"TUNER "); + if (V4L2_CAP_HW_FREQ_SEEK & caps) + strcat (s,"HW_FREQ_SEEK "); + if (V4L2_CAP_MODULATOR & caps) + strcat (s,"MODULATOR "); if (V4L2_CAP_AUDIO & caps) strcat (s,"AUDIO "); if (V4L2_CAP_RADIO & caps) @@ -128,6 +144,10 @@ strcat (s,"ASYNCIO "); if (V4L2_CAP_STREAMING & caps) strcat (s,"STREAMING "); + if (V4L2_CAP_EXT_PIX_FORMAT & caps) + strcat (s,"EXT_PIX_FORMAT "); + if (V4L2_CAP_DEVICE_CAPS & caps) + strcat (s,"DEVICE_CAPS "); return s; } @@ -180,12 +200,14 @@ ret=xioctl(drv->fd,VIDIOC_QUERYCAP,(void *) &drv->cap); if (!ret && drv->debug) { printf ("driver=%s, card=%s, bus=%s, version=%d.%d.%d, " - "capabilities=%s\n", + "capabilities=%s, device_caps=%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)); + prt_caps(drv->cap.capabilities), + (drv->cap.capabilities & V4L2_CAP_DEVICE_CAPS) ? + prt_caps(drv->cap.device_caps) : "N/A"); } diff -Nru v4l-utils-1.0.0+r2263/utils/qv4l2/capture-win.cpp v4l-utils-1.0.0+r2364/utils/qv4l2/capture-win.cpp --- v4l-utils-1.0.0+r2263/utils/qv4l2/capture-win.cpp 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/qv4l2/capture-win.cpp 2014-08-12 09:02:18.000000000 +0000 @@ -26,6 +26,8 @@ #include #include +#include + #define MIN_WIN_SIZE_WIDTH 160 #define MIN_WIN_SIZE_HEIGHT 120 @@ -33,14 +35,25 @@ double CaptureWin::m_pixelAspectRatio = 1.0; CropMethod CaptureWin::m_cropMethod = QV4L2_CROP_NONE; -CaptureWin::CaptureWin() +CaptureWin::CaptureWin(ApplicationWindow *aw) : + m_appWin(aw) { setWindowTitle("V4L2 Capture"); m_hotkeyClose = new QShortcut(Qt::CTRL+Qt::Key_W, this); connect(m_hotkeyClose, SIGNAL(activated()), this, SLOT(close())); + connect(new QShortcut(Qt::Key_Q, this), SIGNAL(activated()), this, SLOT(close())); m_hotkeyScaleReset = new QShortcut(Qt::CTRL+Qt::Key_F, this); connect(m_hotkeyScaleReset, SIGNAL(activated()), this, SLOT(resetSize())); - m_frame.format = 0; + connect(aw->m_resetScalingAct, SIGNAL(triggered()), this, SLOT(resetSize())); + m_hotkeyExitFullscreen = new QShortcut(Qt::Key_Escape, this); + connect(m_hotkeyExitFullscreen, SIGNAL(activated()), this, SLOT(escape())); + m_hotkeyToggleFullscreen = new QShortcut(Qt::Key_F, this); + connect(m_hotkeyToggleFullscreen, SIGNAL(activated()), aw->m_makeFullScreenAct, SLOT(toggle())); + m_exitFullScreen = new QAction(QIcon(":/fullscreenexit.png"), "Exit Fullscreen", this); + connect(m_exitFullScreen, SIGNAL(triggered()), this, SLOT(escape())); + m_enterFullScreen = new QAction(QIcon(":/fullscreen.png"), "Show Fullscreen", this); + connect(m_enterFullScreen, SIGNAL(triggered()), this, SLOT(fullScreen())); + m_frame.format = 0; m_frame.size.setWidth(0); m_frame.size.setHeight(0); m_frame.planeData[0] = NULL; @@ -70,11 +83,10 @@ } void CaptureWin::setFrame(int width, int height, __u32 format, - unsigned char *data, unsigned char *data2, const QString &info) + unsigned char *data, unsigned char *data2) { m_frame.planeData[0] = data; m_frame.planeData[1] = data2; - m_frame.info = info; m_frame.updated = false; if (width != m_frame.size.width() || height != m_frame.size.height() @@ -85,7 +97,6 @@ m_frame.updated = true; updateSize(); } - m_information.setText(m_frame.info); setRenderFrame(); } @@ -93,19 +104,17 @@ void CaptureWin::buildWindow(QWidget *videoSurface) { int l, t, r, b; - QVBoxLayout *vbox = new QVBoxLayout(this); - m_information.setText("No Frame"); - vbox->addWidget(videoSurface, 2000); - vbox->addWidget(&m_information, 1, Qt::AlignBottom); - vbox->getContentsMargins(&l, &t, &r, &b); - vbox->setSpacing(b); + m_vboxLayout = new QVBoxLayout(this); + m_vboxLayout->getContentsMargins(&l, &t, &r, &b); + m_vboxLayout->setMargin(0); + m_vboxLayout->addWidget(videoSurface, 1000, Qt::AlignCenter); + + setContextMenuPolicy(Qt::CustomContextMenu); + connect(this, SIGNAL(customContextMenuRequested(QPoint)), SLOT(customMenuRequested(QPoint))); } void CaptureWin::resetSize() { - if (isMaximized()) - showNormal(); - // Force resize even if no size change QSize resetFrameSize = m_origFrameSize; m_origFrameSize.setWidth(0); @@ -114,51 +123,49 @@ setWindowSize(resetFrameSize); } -QSize CaptureWin::cropFrameSize(QSize size) +QSize CaptureWin::cropSize(QSize size) { - // Crop width - int validWidth; - - if (m_cropMethod == QV4L2_CROP_P43) - validWidth = (size.height() * 4.0 / 3.0) / m_pixelAspectRatio; - else - validWidth = size.width(); // no width crop - - if (validWidth < MIN_WIN_SIZE_WIDTH || validWidth >= size.width()) - validWidth = size.width(); // no width crop - - int deltaWidth = (size.width() - validWidth) / 2; - - // Crop height + QSize croppedSize = size; double realWidth = size.width() * m_pixelAspectRatio; - int validHeight; + double realHeight = size.height() / m_pixelAspectRatio; + double aspectRatio = 1; switch (m_cropMethod) { + case QV4L2_CROP_P43: + aspectRatio = 4.0 / 3.0; + break; case QV4L2_CROP_W149: - validHeight = realWidth / (14.0 / 9.0); + aspectRatio = 14.0 / 9.0; break; case QV4L2_CROP_W169: - validHeight = realWidth / (16.0 / 9.0); + aspectRatio = 16.0 / 9.0; break; case QV4L2_CROP_C185: - validHeight = realWidth / 1.85; + aspectRatio = 1.85; break; case QV4L2_CROP_C239: - validHeight = realWidth / 2.39; + aspectRatio = 2.39; break; case QV4L2_CROP_TB: - validHeight = size.height() - 2; + croppedSize.setHeight(size.height() - 2); break; default: - validHeight = size.height(); // No height crop + break; // No cropping } - if (validHeight < MIN_WIN_SIZE_HEIGHT || validHeight >= size.height()) - validHeight = size.height(); // No height crop + if ((m_cropMethod != QV4L2_CROP_TB) && (m_cropMethod != QV4L2_CROP_NONE)) { + if (realWidth / size.height() < aspectRatio) + croppedSize.setHeight(realWidth / aspectRatio); + else + croppedSize.setWidth(realHeight * aspectRatio); + } - int deltaHeight = (size.height() - validHeight) / 2; + if (croppedSize.width() < MIN_WIN_SIZE_WIDTH || croppedSize.width() >= size.width()) + croppedSize.setWidth(size.width()); + if (croppedSize.height() < MIN_WIN_SIZE_HEIGHT || croppedSize.height() >= size.height()) + croppedSize.setHeight(size.height()); - return QSize(deltaWidth, deltaHeight); + return croppedSize; } void CaptureWin::updateSize() @@ -166,8 +173,8 @@ m_crop.updated = false; if (m_frame.updated) { m_scaledSize = scaleFrameSize(m_windowSize, m_frame.size); - m_crop.delta = cropFrameSize(m_frame.size); - m_crop.size = m_frame.size - 2 * m_crop.delta; + m_crop.size = cropSize(m_frame.size); + m_crop.delta = (m_frame.size - m_crop.size) / 2; m_crop.updated = true; } } @@ -196,7 +203,7 @@ { int l, t, r, b; layout()->getContentsMargins(&l, &t, &r, &b); - return QSize(l + r, t + b + m_information.minimumSizeHint().height() + layout()->spacing()); + return QSize(l + r, t + b); } void CaptureWin::enableScaling(bool enable) @@ -225,8 +232,7 @@ QDesktopWidget *screen = QApplication::desktop(); QRect resolution = screen->screenGeometry(); - QSize windowSize = margins + pixelAspectFrameSize(frameSize) - - 2 * cropFrameSize(frameSize); + QSize windowSize = pixelAspectFrameSize(cropSize(frameSize)) + margins; if (windowSize.width() > resolution.width()) windowSize.setWidth(resolution.width()); @@ -247,8 +253,7 @@ QSize CaptureWin::scaleFrameSize(QSize window, QSize frame) { - QSize croppedSize = frame - 2 * cropFrameSize(frame); - QSize actualSize = pixelAspectFrameSize(croppedSize); + QSize actualSize = pixelAspectFrameSize(cropSize(frame)); if (!m_enableScaling) { window.setWidth(actualSize.width()); @@ -274,6 +279,79 @@ resetSize(); } +float CaptureWin::getHorScaleFactor() +{ + float ow, sw, wscale; + + sw = m_scaledSize.width(); + ow = m_origFrameSize.width(); + wscale = floor(100 * (sw / ow)) / 100.0; + + return wscale; +} + +float CaptureWin::getVertScaleFactor() +{ + float oh, sh, hscale; + + sh = m_scaledSize.height(); + oh = m_origFrameSize.height(); + hscale = floor(100 * (sh / oh)) / 100.0; + + return hscale; +} + +void CaptureWin::mouseDoubleClickEvent(QMouseEvent *e) +{ + m_appWin->m_makeFullScreenAct->toggle(); +} + +void CaptureWin::escape() +{ + m_appWin->m_makeFullScreenAct->setChecked(false); +} + +void CaptureWin::fullScreen() +{ + m_appWin->m_makeFullScreenAct->setChecked(true); +} + +void CaptureWin::makeFullScreen(bool enable) +{ + if (enable) { + showFullScreen(); + setStyleSheet("background-color:#000000;"); + } else { + showNormal(); + setStyleSheet("background-color:none;"); + } + QSize resetFrameSize = m_origFrameSize; + m_origFrameSize.setWidth(0); + m_origFrameSize.setHeight(0); + + setWindowSize(resetFrameSize); +} + +void CaptureWin::customMenuRequested(QPoint pos) +{ + QMenu *menu = new QMenu(this); + + if (isFullScreen()) { + menu->addAction(m_exitFullScreen); + menu->setStyleSheet("background-color:none;"); + } else { + menu->addAction(m_enterFullScreen); + } + + menu->addAction(m_appWin->m_resetScalingAct); + menu->addAction(m_appWin->m_useBlendingAct); + menu->addAction(m_appWin->m_useLinearAct); + menu->addAction(m_appWin->m_snapshotAct); + menu->addAction(m_appWin->m_showFramesAct); + + menu->popup(mapToGlobal(pos)); +} + void CaptureWin::closeEvent(QCloseEvent *event) { QWidget::closeEvent(event); diff -Nru v4l-utils-1.0.0+r2263/utils/qv4l2/capture-win-gl.cpp v4l-utils-1.0.0+r2364/utils/qv4l2/capture-win-gl.cpp --- v4l-utils-1.0.0+r2263/utils/qv4l2/capture-win-gl.cpp 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/qv4l2/capture-win-gl.cpp 2014-08-12 09:02:18.000000000 +0000 @@ -24,7 +24,8 @@ #include -CaptureWinGL::CaptureWinGL() +CaptureWinGL::CaptureWinGL(ApplicationWindow *aw) : + CaptureWin(aw) { #ifdef HAVE_QTGL CaptureWin::buildWindow(&m_videoSurface); @@ -118,6 +119,13 @@ #endif } +void CaptureWinGL::setLinearFilter(bool enable) +{ +#ifdef HAVE_QTGL + m_videoSurface.setLinearFilter(enable); +#endif +} + #ifdef HAVE_QTGL CaptureWinGLEngine::CaptureWinGLEngine() : m_frameWidth(0), @@ -125,12 +133,15 @@ m_WCrop(0), m_HCrop(0), m_colorspace(V4L2_COLORSPACE_REC709), + m_field(V4L2_FIELD_NONE), m_displayColorspace(V4L2_COLORSPACE_SRGB), m_screenTextureCount(0), m_formatChange(false), m_frameFormat(0), m_frameData(NULL), - m_blending(false) + m_blending(false), + m_mag_filter(GL_NEAREST), + m_min_filter(GL_NEAREST) { m_glfunction.initializeGLFunctions(context()); } @@ -202,6 +213,19 @@ m_formatChange = true; } +void CaptureWinGLEngine::setLinearFilter(bool enable) +{ + if (enable) { + m_mag_filter = GL_LINEAR; + m_min_filter = GL_LINEAR; + } + else { + m_mag_filter = GL_NEAREST; + m_min_filter = GL_NEAREST; + } + m_formatChange = true; +} + void CaptureWinGLEngine::clearShader() { glDeleteTextures(m_screenTextureCount, m_screenTexture); @@ -278,12 +302,18 @@ { static const __u32 supported_fmts[] = { V4L2_PIX_FMT_RGB32, + V4L2_PIX_FMT_XRGB32, + V4L2_PIX_FMT_ARGB32, V4L2_PIX_FMT_BGR32, + V4L2_PIX_FMT_XBGR32, + V4L2_PIX_FMT_ABGR32, V4L2_PIX_FMT_RGB24, V4L2_PIX_FMT_BGR24, V4L2_PIX_FMT_RGB565, V4L2_PIX_FMT_RGB565X, V4L2_PIX_FMT_RGB555, + V4L2_PIX_FMT_XRGB555, + V4L2_PIX_FMT_ARGB555, V4L2_PIX_FMT_RGB555X, V4L2_PIX_FMT_YUYV, V4L2_PIX_FMT_YVYU, @@ -336,6 +366,8 @@ break; case V4L2_PIX_FMT_RGB555: + case V4L2_PIX_FMT_XRGB555: + case V4L2_PIX_FMT_ARGB555: case V4L2_PIX_FMT_RGB555X: case V4L2_PIX_FMT_RGB565: case V4L2_PIX_FMT_RGB565X: @@ -343,6 +375,10 @@ case V4L2_PIX_FMT_BGR24: case V4L2_PIX_FMT_RGB32: case V4L2_PIX_FMT_BGR32: + case V4L2_PIX_FMT_XRGB32: + case V4L2_PIX_FMT_XBGR32: + case V4L2_PIX_FMT_ARGB32: + case V4L2_PIX_FMT_ABGR32: default: shader_RGB(); break; @@ -419,6 +455,8 @@ break; case V4L2_PIX_FMT_RGB555: + case V4L2_PIX_FMT_XRGB555: + case V4L2_PIX_FMT_ARGB555: case V4L2_PIX_FMT_RGB555X: case V4L2_PIX_FMT_RGB565: case V4L2_PIX_FMT_RGB565X: @@ -426,6 +464,10 @@ case V4L2_PIX_FMT_BGR24: case V4L2_PIX_FMT_RGB32: case V4L2_PIX_FMT_BGR32: + case V4L2_PIX_FMT_XRGB32: + case V4L2_PIX_FMT_XBGR32: + case V4L2_PIX_FMT_ARGB32: + case V4L2_PIX_FMT_ABGR32: default: render_RGB(); break; @@ -439,8 +481,8 @@ void CaptureWinGLEngine::configureTexture(size_t idx) { glBindTexture(GL_TEXTURE_2D, m_screenTexture[idx]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_min_filter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, m_mag_filter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); } @@ -927,10 +969,13 @@ GL_SRGB8_ALPHA8 : GL_RGBA8; switch (m_frameFormat) { + case V4L2_PIX_FMT_ARGB555: + hasAlpha = true; + /* fall-through */ case V4L2_PIX_FMT_RGB555: + case V4L2_PIX_FMT_XRGB555: glTexImage2D(GL_TEXTURE_2D, 0, internalFmt, m_frameWidth, m_frameHeight, 0, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, NULL); - hasAlpha = true; break; case V4L2_PIX_FMT_RGB555X: @@ -944,15 +989,21 @@ glTexImage2D(GL_TEXTURE_2D, 0, internalFmt, m_frameWidth, m_frameHeight, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL); break; + case V4L2_PIX_FMT_ARGB32: + hasAlpha = true; + /* fall-through */ case V4L2_PIX_FMT_RGB32: + case V4L2_PIX_FMT_XRGB32: glTexImage2D(GL_TEXTURE_2D, 0, internalFmt, m_frameWidth, m_frameHeight, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, NULL); - hasAlpha = true; break; + case V4L2_PIX_FMT_ABGR32: + hasAlpha = true; + /* fall-through */ case V4L2_PIX_FMT_BGR32: + case V4L2_PIX_FMT_XBGR32: glTexImage2D(GL_TEXTURE_2D, 0, internalFmt, m_frameWidth, m_frameHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, NULL); - hasAlpha = true; break; case V4L2_PIX_FMT_RGB24: case V4L2_PIX_FMT_BGR24: @@ -1018,6 +1069,8 @@ switch (m_frameFormat) { case V4L2_PIX_FMT_RGB555: + case V4L2_PIX_FMT_XRGB555: + case V4L2_PIX_FMT_ARGB555: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_frameWidth, m_frameHeight, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, m_frameData); break; @@ -1048,10 +1101,14 @@ break; case V4L2_PIX_FMT_RGB32: + case V4L2_PIX_FMT_XRGB32: + case V4L2_PIX_FMT_ARGB32: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_frameWidth, m_frameHeight, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, m_frameData); break; case V4L2_PIX_FMT_BGR32: + case V4L2_PIX_FMT_XBGR32: + case V4L2_PIX_FMT_ABGR32: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_frameWidth, m_frameHeight, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, m_frameData); break; diff -Nru v4l-utils-1.0.0+r2263/utils/qv4l2/capture-win-gl.h v4l-utils-1.0.0+r2364/utils/qv4l2/capture-win-gl.h --- v4l-utils-1.0.0+r2263/utils/qv4l2/capture-win-gl.h 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/qv4l2/capture-win-gl.h 2014-08-12 09:02:18.000000000 +0000 @@ -50,6 +50,7 @@ void setDisplayColorspace(unsigned colorspace); void setField(unsigned field); void setBlending(bool enable) { m_blending = enable; } + void setLinearFilter(bool enable); protected: void paintGL(); @@ -99,6 +100,8 @@ QGLShaderProgram m_shaderProgram; bool m_haveFramebufferSRGB; bool m_blending; + GLint m_mag_filter; + GLint m_min_filter; }; #endif @@ -106,7 +109,7 @@ class CaptureWinGL : public CaptureWin { public: - CaptureWinGL(); + CaptureWinGL(ApplicationWindow *aw); ~CaptureWinGL(); void stop(); @@ -116,6 +119,7 @@ void setField(unsigned field); void setDisplayColorspace(unsigned colorspace); void setBlending(bool enable); + void setLinearFilter(bool enable); protected: void resizeEvent(QResizeEvent *event); diff -Nru v4l-utils-1.0.0+r2263/utils/qv4l2/capture-win.h v4l-utils-1.0.0+r2364/utils/qv4l2/capture-win.h --- v4l-utils-1.0.0+r2263/utils/qv4l2/capture-win.h 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/qv4l2/capture-win.h 2014-08-12 09:02:18.000000000 +0000 @@ -25,6 +25,8 @@ #include #include #include +#include +#include enum CropMethod { // Crop Height @@ -43,7 +45,6 @@ __u32 format; QSize size; // int frameHeight; int frameWidth; unsigned char *planeData[2]; - QString info; bool updated; }; @@ -53,23 +54,30 @@ bool updated; }; +class ApplicationWindow; class CaptureWin : public QWidget { Q_OBJECT public: - CaptureWin(); + CaptureWin(ApplicationWindow *aw); ~CaptureWin(); void setWindowSize(QSize size); void enableScaling(bool enable); void setPixelAspectRatio(double ratio); + float getHorScaleFactor(); + float getVertScaleFactor(); virtual void setColorspace(unsigned colorspace) = 0; virtual void setField(unsigned field) = 0; virtual void setDisplayColorspace(unsigned colorspace) = 0; virtual void setBlending(bool enable) = 0; + virtual void setLinearFilter(bool enable) = 0; void setCropMethod(CropMethod crop); + void makeFullScreen(bool); + QAction *m_exitFullScreen; + QAction *m_enterFullScreen; /** * @brief Set a frame into the capture window. @@ -84,7 +92,7 @@ * @param info A string containing capture information. */ void setFrame(int width, int height, __u32 format, - unsigned char *data, unsigned char *data2, const QString &info); + unsigned char *data, unsigned char *data2); /** * @brief Called when the capture stream is stopped. @@ -122,19 +130,15 @@ static QSize scaleFrameSize(QSize window, QSize frame); /** - * @brief Get the number of pixels to crop. + * @brief Crop size * - * When cropping is applied this gives the number of pixels to - * remove from top and bottom. To get total multiply the return - * value by 2. + * Reduces size width or height according to m_cropMethod * - * @param size Frame size - * @return The size (no of height & width pixels) to remove when cropping + * @param size Input size + * @return Cropped size * - * @note The width and height must be original frame size - * to ensure that the cropping is done correctly. */ - static QSize cropFrameSize(QSize size); + static QSize cropSize(QSize size); /** * @brief Get the frame size when aspect ratio is applied and increases size. @@ -146,9 +150,15 @@ public slots: void resetSize(); + void customMenuRequested(QPoint pos); + +private slots: + void escape(); + void fullScreen(); protected: void closeEvent(QCloseEvent *event); + void mouseDoubleClickEvent(QMouseEvent *e); /** * @brief Get the amount of space outside the video frame. @@ -175,13 +185,6 @@ void updateSize(); /** - * @brief A label that can is used to display capture information. - * - * @note This must be set in the derived class' setFrame() function. - */ - QLabel m_information; - - /** * @brief Frame information. * * @note Set and accessed from derived render dependent classes. @@ -208,9 +211,14 @@ void close(); private: + ApplicationWindow *m_appWin; static double m_pixelAspectRatio; static CropMethod m_cropMethod; QShortcut *m_hotkeyClose; QShortcut *m_hotkeyScaleReset; + QShortcut *m_hotkeyExitFullscreen; + QShortcut *m_hotkeyToggleFullscreen; + QVBoxLayout *m_vboxLayout; + unsigned m_vboxSpacing; }; #endif diff -Nru v4l-utils-1.0.0+r2263/utils/qv4l2/capture-win-qt.cpp v4l-utils-1.0.0+r2364/utils/qv4l2/capture-win-qt.cpp --- v4l-utils-1.0.0+r2263/utils/qv4l2/capture-win-qt.cpp 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/qv4l2/capture-win-qt.cpp 2014-08-12 09:02:18.000000000 +0000 @@ -19,7 +19,8 @@ #include "capture-win-qt.h" -CaptureWinQt::CaptureWinQt() : +CaptureWinQt::CaptureWinQt(ApplicationWindow *aw) : + CaptureWin(aw), m_image(new QImage(0, 0, QImage::Format_Invalid)), m_data(NULL), m_supportedFormat(false), @@ -27,7 +28,8 @@ m_cropBytes(0), m_cropOffset(0) { - CaptureWin::buildWindow(&m_videoSurface); + m_videoSurface = new QLabel(this); + CaptureWin::buildWindow(m_videoSurface); } CaptureWinQt::~CaptureWinQt() @@ -38,7 +40,8 @@ void CaptureWinQt::resizeEvent(QResizeEvent *event) { // Get size of frame viewport. - m_windowSize = m_videoSurface.size(); + QSize margins = getMargins(); + m_windowSize = size() - margins; // Re-calculate sizes m_frame.updated = true; CaptureWin::updateSize(); @@ -57,7 +60,9 @@ if (!m_supportedFormat) dstFmt = QImage::Format_RGB888; - if (m_frame.updated || m_image->format() != dstFmt) { + if (m_frame.updated || m_image->format() != dstFmt || + m_image->width() != m_frame.size.width() || + m_image->height() != m_frame.size.height()) { delete m_image; m_image = new QImage(m_frame.size.width(), m_frame.size.height(), @@ -88,7 +93,7 @@ m_filled = true; m_image->fill(0); QPixmap img = QPixmap::fromImage(*m_image); - m_videoSurface.setPixmap(img); + m_videoSurface->setPixmap(img); } return; } @@ -106,7 +111,7 @@ // No scaling is performed by scaled() if the scaled size is equal to original size img = img.scaled(m_scaledSize.width(), m_scaledSize.height(), Qt::IgnoreAspectRatio); - m_videoSurface.setPixmap(img); + m_videoSurface->setPixmap(img); } void CaptureWinQt::stop() @@ -130,15 +135,21 @@ } supported_fmts[] = { #if Q_BYTE_ORDER == Q_BIG_ENDIAN { V4L2_PIX_FMT_RGB32, QImage::Format_RGB32 }, + { V4L2_PIX_FMT_XRGB32, QImage::Format_RGB32 }, + { V4L2_PIX_FMT_ARGB32, QImage::Format_ARGB32 }, { V4L2_PIX_FMT_RGB24, QImage::Format_RGB888 }, { V4L2_PIX_FMT_RGB565X, QImage::Format_RGB16 }, { V4L2_PIX_FMT_RGB555X, QImage::Format_RGB555 }, #else { V4L2_PIX_FMT_BGR32, QImage::Format_RGB32 }, + { V4L2_PIX_FMT_XBGR32, QImage::Format_RGB32 }, + { V4L2_PIX_FMT_ABGR32, QImage::Format_ARGB32 }, { V4L2_PIX_FMT_RGB24, QImage::Format_RGB888 }, { V4L2_PIX_FMT_RGB565, QImage::Format_RGB16 }, { V4L2_PIX_FMT_RGB555, QImage::Format_RGB555 }, + { V4L2_PIX_FMT_XRGB555, QImage::Format_RGB555 }, { V4L2_PIX_FMT_RGB444, QImage::Format_RGB444 }, + { V4L2_PIX_FMT_XRGB444, QImage::Format_RGB444 }, #endif { 0, QImage::Format_Invalid } }; diff -Nru v4l-utils-1.0.0+r2263/utils/qv4l2/capture-win-qt.h v4l-utils-1.0.0+r2364/utils/qv4l2/capture-win-qt.h --- v4l-utils-1.0.0+r2263/utils/qv4l2/capture-win-qt.h 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/qv4l2/capture-win-qt.h 2014-08-12 09:02:18.000000000 +0000 @@ -30,7 +30,7 @@ class CaptureWinQt : public CaptureWin { public: - CaptureWinQt(); + CaptureWinQt(ApplicationWindow *aw); ~CaptureWinQt(); void stop(); @@ -40,6 +40,7 @@ void setField(unsigned field) {} void setDisplayColorspace(unsigned colorspace) {} void setBlending(bool enable) {} + void setLinearFilter(bool enable) {} protected: void resizeEvent(QResizeEvent *event); @@ -51,7 +52,7 @@ QImage *m_image; unsigned char *m_data; - QLabel m_videoSurface; + QLabel *m_videoSurface; bool m_supportedFormat; bool m_filled; int m_cropBytes; diff -Nru v4l-utils-1.0.0+r2263/utils/qv4l2/ctrl-tab.cpp v4l-utils-1.0.0+r2364/utils/qv4l2/ctrl-tab.cpp --- v4l-utils-1.0.0+r2263/utils/qv4l2/ctrl-tab.cpp 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/qv4l2/ctrl-tab.cpp 2014-08-12 09:02:18.000000000 +0000 @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -59,12 +60,10 @@ void ApplicationWindow::addWidget(QGridLayout *grid, QWidget *w, Qt::Alignment align) { - if (m_col % 2) + if (m_col % 2 && !qobject_cast(w)) w->setMinimumWidth(m_minWidth); if (w->sizeHint().width() > m_maxw[m_col]) m_maxw[m_col] = w->sizeHint().width(); - if (w->sizeHint().height() > m_maxh) - m_maxh = w->sizeHint().height(); grid->addWidget(w, m_row, m_col, align | Qt::AlignVCenter); m_col++; if (m_col == m_cols) { @@ -73,61 +72,37 @@ } } -void ApplicationWindow::addTabs(int size[]) +void ApplicationWindow::addTabs(int m_winWidth) { - v4l2_queryctrl qctrl; + v4l2_query_ext_ctrl qec = { 0 }; unsigned ctrl_class; unsigned i; int id; - memset(&qctrl, 0, sizeof(qctrl)); - qctrl.id = V4L2_CTRL_FLAG_NEXT_CTRL; - while (queryctrl(qctrl)) { - if (is_valid_type(qctrl.type) && - (qctrl.flags & V4L2_CTRL_FLAG_DISABLED) == 0) { - m_ctrlMap[qctrl.id] = qctrl; - if (qctrl.type != V4L2_CTRL_TYPE_CTRL_CLASS) - m_classMap[V4L2_CTRL_ID2CLASS(qctrl.id)].push_back(qctrl.id); - } - qctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL; - } - if (qctrl.id == V4L2_CTRL_FLAG_NEXT_CTRL) { - strcpy((char *)qctrl.name, "User Controls"); - qctrl.id = V4L2_CTRL_CLASS_USER | 1; - qctrl.type = V4L2_CTRL_TYPE_CTRL_CLASS; - m_ctrlMap[qctrl.id] = qctrl; - for (id = V4L2_CID_USER_BASE; id < V4L2_CID_LASTP1; id++) { - qctrl.id = id; - if (!queryctrl(qctrl)) - continue; - if (!is_valid_type(qctrl.type)) - continue; - if (qctrl.flags & V4L2_CTRL_FLAG_DISABLED) - continue; - m_ctrlMap[qctrl.id] = qctrl; - m_classMap[V4L2_CTRL_CLASS_USER].push_back(qctrl.id); - } - for (qctrl.id = V4L2_CID_PRIVATE_BASE; - queryctrl(qctrl); qctrl.id++) { - if (!is_valid_type(qctrl.type)) - continue; - if (qctrl.flags & V4L2_CTRL_FLAG_DISABLED) - continue; - m_ctrlMap[qctrl.id] = qctrl; - m_classMap[V4L2_CTRL_CLASS_USER].push_back(qctrl.id); - } - } - - m_haveExtendedUserCtrls = false; - for (unsigned i = 0; i < m_classMap[V4L2_CTRL_CLASS_USER].size(); i++) { - unsigned id = m_classMap[V4L2_CTRL_CLASS_USER][i]; - - if (m_ctrlMap[id].type == V4L2_CTRL_TYPE_INTEGER64 || - m_ctrlMap[id].type == V4L2_CTRL_TYPE_STRING || - V4L2_CTRL_DRIVER_PRIV(id)) { - m_haveExtendedUserCtrls = true; - break; - } + while (query_ext_ctrl(qec, true) == 0) { + if (is_valid_type(qec.type) && + (qec.flags & V4L2_CTRL_FLAG_DISABLED) == 0) { + m_ctrlMap[qec.id] = qec; + if (qec.type != V4L2_CTRL_TYPE_CTRL_CLASS) + m_classMap[V4L2_CTRL_ID2CLASS(qec.id)].push_back(qec.id); + } + } + if (m_classMap.find(V4L2_CTRL_CLASS_USER) != m_classMap.end() && + m_ctrlMap.find(V4L2_CID_USER_CLASS) == m_ctrlMap.end()) { + memset(&qec, 0, sizeof(qec)); + qec.id = V4L2_CID_USER_CLASS; + strcpy(qec.name, "User Controls"); + qec.type = V4L2_CTRL_TYPE_CTRL_CLASS; + m_ctrlMap[qec.id] = qec; + } + if (m_classMap.find(V4L2_CTRL_CLASS_CAMERA) != m_classMap.end() && + m_ctrlMap.find(V4L2_CID_CAMERA_CLASS) == m_ctrlMap.end()) { + // UVC still doesn't provide this :-( + memset(&qec, 0, sizeof(qec)); + qec.id = V4L2_CID_CAMERA_CLASS; + strcpy(qec.name, "Camera Controls"); + qec.type = V4L2_CTRL_TYPE_CTRL_CLASS; + m_ctrlMap[qec.id] = qec; } for (ClassMap::iterator iter = m_classMap.begin(); iter != m_classMap.end(); ++iter) { @@ -141,7 +116,7 @@ m_maxw[j] = 0; } - const v4l2_queryctrl &qctrl = m_ctrlMap[id]; + const v4l2_query_ext_ctrl &qec = m_ctrlMap[id]; QWidget *t = new QWidget(m_tabs); QVBoxLayout *vbox = new QVBoxLayout(t); QWidget *w = new QWidget(t); @@ -149,9 +124,7 @@ vbox->addWidget(w); QGridLayout *grid = new QGridLayout(w); - QString tabName((char *)qctrl.name); - if (tabName != "User Controls" && tabName.endsWith(" Controls")) - tabName.chop(9); + QString tabName(qec.name); if (tabName.length()) { QLabel *title_tab = new QLabel(tabName, parentWidget()); @@ -183,22 +156,16 @@ fixWidth(grid); int totalw = 0; - int totalh = 0; int diff = 0; for (int i = 0; i < m_cols; i++) { totalw += m_maxw[i] + m_pxw; } - totalh = grid->rowCount() * m_maxh; - if (totalw > size[0]) - size[0] = totalw; + if (totalw > m_winWidth) + m_winWidth = totalw; else { - diff = size[0] - totalw; + diff = m_winWidth - totalw; grid->setHorizontalSpacing(diff/5); } - if (totalh > size[1]) - size[1] = totalh; - setMinimumSize(size[0], size[1]); - grid = new QGridLayout(w); finishGrid(grid, ctrl_class); } @@ -273,12 +240,12 @@ refresh(ctrl_class); } -void ApplicationWindow::addCtrl(QGridLayout *grid, const v4l2_queryctrl &qctrl) +void ApplicationWindow::addCtrl(QGridLayout *grid, const v4l2_query_ext_ctrl &qec) { QWidget *p = grid->parentWidget(); QIntValidator *val; QLineEdit *edit; - QString name((char *)qctrl.name); + QString name(qec.name); QComboBox *combo; QSpinBox *spin; QSlider *slider; @@ -286,23 +253,23 @@ QWidget *wContainer = new QWidget(); QHBoxLayout *m_boxLayout = new QHBoxLayout(wContainer); m_boxLayout->setMargin(0); - unsigned dif; + __u64 dif; - switch (qctrl.type) { + switch (qec.type) { case V4L2_CTRL_TYPE_INTEGER: addLabel(grid, name); - dif = qctrl.maximum - qctrl.minimum; - if (dif <= 0xffffU || (qctrl.flags & V4L2_CTRL_FLAG_SLIDER)) { - m_sliderMap[qctrl.id] = slider = new QSlider(Qt::Horizontal, p); + dif = qec.maximum - qec.minimum; + if (dif <= 0xffffU || (qec.flags & V4L2_CTRL_FLAG_SLIDER)) { + m_sliderMap[qec.id] = slider = new QSlider(Qt::Horizontal, p); slider->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum); - slider->setMinimum(qctrl.minimum); - slider->setMaximum(qctrl.maximum); - slider->setSingleStep(qctrl.step); - slider->setSliderPosition(qctrl.default_value); - - m_widgetMap[qctrl.id] = spin = new QSpinBox(p); - spin->setRange(qctrl.minimum, qctrl.maximum); - spin->setSingleStep(qctrl.step); + slider->setMinimum(qec.minimum); + slider->setMaximum(qec.maximum); + slider->setSingleStep(qec.step); + slider->setSliderPosition(qec.default_value); + + m_widgetMap[qec.id] = spin = new QSpinBox(p); + spin->setRange(qec.minimum, qec.maximum); + spin->setSingleStep(qec.step); m_boxLayout->addWidget(slider); m_boxLayout->addWidget(spin); @@ -311,30 +278,30 @@ connect(spin, SIGNAL(valueChanged(int)), slider, SLOT(setValue(int))); connect(slider, SIGNAL(valueChanged(int)), spin, SLOT(setValue(int))); - connect(m_widgetMap[qctrl.id], SIGNAL(valueChanged(int)), + connect(m_widgetMap[qec.id], SIGNAL(valueChanged(int)), m_sigMapper, SLOT(map())); break; } - val = new QIntValidator(qctrl.minimum, qctrl.maximum, p); + val = new QIntValidator(qec.minimum, qec.maximum, p); edit = new QLineEdit(p); edit->setValidator(val); addWidget(grid, edit); - m_widgetMap[qctrl.id] = edit; - connect(m_widgetMap[qctrl.id], SIGNAL(lostFocus()), + m_widgetMap[qec.id] = edit; + connect(m_widgetMap[qec.id], SIGNAL(lostFocus()), m_sigMapper, SLOT(map())); - connect(m_widgetMap[qctrl.id], SIGNAL(returnPressed()), + connect(m_widgetMap[qec.id], SIGNAL(returnPressed()), m_sigMapper, SLOT(map())); break; case V4L2_CTRL_TYPE_INTEGER64: addLabel(grid, name); edit = new QLineEdit(p); - m_widgetMap[qctrl.id] = edit; + m_widgetMap[qec.id] = edit; addWidget(grid, edit); - connect(m_widgetMap[qctrl.id], SIGNAL(lostFocus()), + connect(m_widgetMap[qec.id], SIGNAL(lostFocus()), m_sigMapper, SLOT(map())); - connect(m_widgetMap[qctrl.id], SIGNAL(returnPressed()), + connect(m_widgetMap[qec.id], SIGNAL(returnPressed()), m_sigMapper, SLOT(map())); break; @@ -343,38 +310,40 @@ edit = new QLineEdit(p); edit->setInputMask("HHHHHHHH"); addWidget(grid, edit); - m_widgetMap[qctrl.id] = edit; - connect(m_widgetMap[qctrl.id], SIGNAL(lostFocus()), + m_widgetMap[qec.id] = edit; + connect(m_widgetMap[qec.id], SIGNAL(lostFocus()), m_sigMapper, SLOT(map())); - connect(m_widgetMap[qctrl.id], SIGNAL(returnPressed()), + connect(m_widgetMap[qec.id], SIGNAL(returnPressed()), m_sigMapper, SLOT(map())); break; case V4L2_CTRL_TYPE_STRING: addLabel(grid, name); edit = new QLineEdit(p); - m_widgetMap[qctrl.id] = edit; - edit->setMaxLength(qctrl.maximum); + m_widgetMap[qec.id] = edit; + edit->setMaxLength(qec.maximum); addWidget(grid, edit); - connect(m_widgetMap[qctrl.id], SIGNAL(lostFocus()), + connect(m_widgetMap[qec.id], SIGNAL(lostFocus()), m_sigMapper, SLOT(map())); - connect(m_widgetMap[qctrl.id], SIGNAL(returnPressed()), + connect(m_widgetMap[qec.id], SIGNAL(returnPressed()), m_sigMapper, SLOT(map())); break; case V4L2_CTRL_TYPE_BOOLEAN: addLabel(grid, name); - m_widgetMap[qctrl.id] = new QCheckBox(p); - addWidget(grid, m_widgetMap[qctrl.id]); - connect(m_widgetMap[qctrl.id], SIGNAL(clicked()), + m_widgetMap[qec.id] = new QCheckBox(p); + addWidget(grid, m_widgetMap[qec.id]); + connect(m_widgetMap[qec.id], SIGNAL(clicked()), m_sigMapper, SLOT(map())); break; case V4L2_CTRL_TYPE_BUTTON: - addLabel(grid, ""); - m_widgetMap[qctrl.id] = new QPushButton((char *)qctrl.name, p); - addWidget(grid, m_widgetMap[qctrl.id]); - connect(m_widgetMap[qctrl.id], SIGNAL(clicked()), + addLabel(grid, (char *)qec.name); + QToolButton *button; + m_widgetMap[qec.id] = button = new QToolButton(p); + button->setIcon(QIcon(":/enterbutt.png")); + addWidget(grid, m_widgetMap[qec.id]); + connect(m_widgetMap[qec.id], SIGNAL(clicked()), m_sigMapper, SLOT(map())); break; @@ -382,36 +351,34 @@ case V4L2_CTRL_TYPE_INTEGER_MENU: addLabel(grid, name); combo = new QComboBox(p); - m_widgetMap[qctrl.id] = combo; - for (int i = qctrl.minimum; i <= qctrl.maximum; i++) { - qmenu.id = qctrl.id; + m_widgetMap[qec.id] = combo; + for (int i = (int)qec.minimum; i <= (int)qec.maximum; i++) { + qmenu.id = qec.id; qmenu.index = i; - if (!querymenu(qmenu)) + if (querymenu(qmenu)) continue; - if (qctrl.type == V4L2_CTRL_TYPE_MENU) + if (qec.type == V4L2_CTRL_TYPE_MENU) combo->addItem((char *)qmenu.name); else combo->addItem(QString("%1").arg(qmenu.value)); } - addWidget(grid, m_widgetMap[qctrl.id]); - connect(m_widgetMap[qctrl.id], SIGNAL(activated(int)), + addWidget(grid, m_widgetMap[qec.id]); + connect(m_widgetMap[qec.id], SIGNAL(activated(int)), m_sigMapper, SLOT(map())); break; default: return; } - struct v4l2_event_subscription sub; - memset(&sub, 0, sizeof(sub)); - sub.type = V4L2_EVENT_CTRL; - sub.id = qctrl.id; - subscribe_event(sub); - - m_sigMapper->setMapping(m_widgetMap[qctrl.id], qctrl.id); - if (qctrl.flags & CTRL_FLAG_DISABLED) { - m_widgetMap[qctrl.id]->setDisabled(true); - if (m_sliderMap.find(qctrl.id) != m_sliderMap.end()) - m_sliderMap[qctrl.id]->setDisabled(true); + + m_sigMapper->setMapping(m_widgetMap[qec.id], qec.id); + if (qec.flags & CTRL_FLAG_DISABLED) { + if (qobject_cast(m_widgetMap[qec.id])) + static_cast(m_widgetMap[qec.id])->setReadOnly(true); + else + m_widgetMap[qec.id]->setDisabled(true); + if (m_sliderMap.find(qec.id) != m_sliderMap.end()) + m_sliderMap[qec.id]->setDisabled(true); } } @@ -435,16 +402,6 @@ } if (!update && !all && m_ctrlMap[id].type != V4L2_CTRL_TYPE_BUTTON) return; - if (!m_haveExtendedUserCtrls && ctrl_class == V4L2_CTRL_CLASS_USER) { - if (!all) { - updateCtrl(id); - return; - } - for (unsigned i = 0; i < m_classMap[ctrl_class].size(); i++) { - updateCtrl(m_classMap[ctrl_class][i]); - } - return; - } if (!all) { updateCtrl(id); return; @@ -476,7 +433,7 @@ ctrls.count = idx; ctrls.ctrl_class = ctrl_class; ctrls.controls = c; - if (ioctl(VIDIOC_S_EXT_CTRLS, &ctrls)) { + if (s_ext_ctrls(ctrls)) { if (ctrls.error_idx >= ctrls.count) { error(errno); } @@ -494,17 +451,17 @@ QString ApplicationWindow::getString(unsigned id) { - const v4l2_queryctrl &qctrl = m_ctrlMap[id]; - QWidget *w = m_widgetMap[qctrl.id]; + const v4l2_query_ext_ctrl &qec = m_ctrlMap[id]; + QWidget *w = m_widgetMap[qec.id]; QString v; int mod; - switch (qctrl.type) { + switch (qec.type) { case V4L2_CTRL_TYPE_STRING: v = static_cast(w)->text(); - mod = v.length() % qctrl.step; + mod = v.length() % qec.step; if (mod) - v += QString(qctrl.step - mod, ' '); + v += QString(qec.step - mod, ' '); break; default: break; @@ -515,11 +472,11 @@ long long ApplicationWindow::getVal64(unsigned id) { - const v4l2_queryctrl &qctrl = m_ctrlMap[id]; - QWidget *w = m_widgetMap[qctrl.id]; + const v4l2_query_ext_ctrl &qec = m_ctrlMap[id]; + QWidget *w = m_widgetMap[qec.id]; long long v = 0; - switch (qctrl.type) { + switch (qec.type) { case V4L2_CTRL_TYPE_INTEGER64: v = static_cast(w)->text().toLongLong(); break; @@ -532,17 +489,17 @@ int ApplicationWindow::getVal(unsigned id) { - const v4l2_queryctrl &qctrl = m_ctrlMap[id]; - QWidget *w = m_widgetMap[qctrl.id]; + const v4l2_query_ext_ctrl &qec = m_ctrlMap[id]; + QWidget *w = m_widgetMap[qec.id]; v4l2_querymenu qmenu; int i, idx; int v = 0; unsigned dif; - switch (qctrl.type) { + switch (qec.type) { case V4L2_CTRL_TYPE_INTEGER: - dif = qctrl.maximum - qctrl.minimum; - if (dif <= 0xffffU || (qctrl.flags & V4L2_CTRL_FLAG_SLIDER)) { + dif = qec.maximum - qec.minimum; + if (dif <= 0xffffU || (qec.flags & V4L2_CTRL_FLAG_SLIDER)) { v = static_cast(w)->value(); break; } @@ -559,10 +516,10 @@ case V4L2_CTRL_TYPE_MENU: case V4L2_CTRL_TYPE_INTEGER_MENU: idx = static_cast(w)->currentIndex(); - for (i = qctrl.minimum; i <= qctrl.maximum; i++) { - qmenu.id = qctrl.id; + for (i = qec.minimum; i <= qec.maximum; i++) { + qmenu.id = qec.id; qmenu.index = i; - if (!querymenu(qmenu)) + if (querymenu(qmenu)) continue; if (idx-- == 0) break; @@ -586,18 +543,6 @@ if (m_ctrlMap[id].flags & CTRL_FLAG_DISABLED) return; - if (!m_haveExtendedUserCtrls && ctrl_class == V4L2_CTRL_CLASS_USER) { - struct v4l2_control c; - - c.id = id; - c.value = getVal(id); - if (ioctl(VIDIOC_S_CTRL, &c)) { - errorCtrl(id, errno, c.value); - } - else if (m_ctrlMap[id].flags & V4L2_CTRL_FLAG_UPDATE) - refresh(ctrl_class); - return; - } struct v4l2_ext_control c; struct v4l2_ext_controls ctrls; @@ -616,7 +561,7 @@ ctrls.count = 1; ctrls.ctrl_class = ctrl_class; ctrls.controls = &c; - if (ioctl(VIDIOC_S_EXT_CTRLS, &ctrls)) { + if (s_ext_ctrls(ctrls)) { errorCtrl(id, errno, c.value); } else if (m_ctrlMap[id].flags & V4L2_CTRL_FLAG_UPDATE) @@ -633,65 +578,60 @@ } } -void ApplicationWindow::updateCtrlRange(unsigned id) +void ApplicationWindow::updateCtrlRange(unsigned id, __s32 new_val) { - const v4l2_queryctrl &qctrl = m_ctrlMap[id]; + const v4l2_query_ext_ctrl &qec = m_ctrlMap[id]; QLineEdit *edit; QIntValidator *val; unsigned dif; - switch (qctrl.type) { + switch (qec.type) { case V4L2_CTRL_TYPE_INTEGER: - dif = qctrl.maximum - qctrl.minimum; - if (dif <= 0xffffU || (qctrl.flags & V4L2_CTRL_FLAG_SLIDER)) { + dif = qec.maximum - qec.minimum; + if (dif <= 0xffffU || (qec.flags & V4L2_CTRL_FLAG_SLIDER)) { QSlider *slider = static_cast(m_sliderMap[id]); - slider->setMinimum(qctrl.minimum); - slider->setMaximum(qctrl.maximum); - slider->setSingleStep(qctrl.step); - slider->setSliderPosition(qctrl.default_value); + slider->setMinimum(qec.minimum); + slider->setMaximum(qec.maximum); + slider->setSingleStep(qec.step); + slider->setSliderPosition(new_val); QSpinBox *spin = static_cast(m_widgetMap[id]); - spin->setRange(qctrl.minimum, qctrl.maximum); - spin->setSingleStep(qctrl.step); + spin->setRange(qec.minimum, qec.maximum); + spin->setSingleStep(qec.step); + spin->setValue(new_val); break; } edit = static_cast(m_widgetMap[id]); - val = new QIntValidator(qctrl.minimum, qctrl.maximum, edit->parent()); + val = new QIntValidator(qec.minimum, qec.maximum, edit->parent()); // FIXME: will this delete the old validator? edit->setValidator(val); break; case V4L2_CTRL_TYPE_STRING: QLineEdit *edit = static_cast(m_widgetMap[id]); - edit->setMaxLength(qctrl.maximum); + edit->setMaxLength(qec.maximum); break; } } -void ApplicationWindow::refresh(unsigned ctrl_class) +void ApplicationWindow::subscribeCtrlEvents() { - if (!m_haveExtendedUserCtrls && ctrl_class == V4L2_CTRL_CLASS_USER) { - for (unsigned i = 0; i < m_classMap[ctrl_class].size(); i++) { - unsigned id = m_classMap[ctrl_class][i]; - v4l2_control c; - - queryctrl(m_ctrlMap[id]); - if (m_ctrlMap[id].type == V4L2_CTRL_TYPE_BUTTON) - continue; - if (m_ctrlMap[id].flags & V4L2_CTRL_FLAG_WRITE_ONLY) - continue; - c.id = id; - if (ioctl(VIDIOC_G_CTRL, &c)) { - errorCtrl(id, errno); - } - setVal(id, c.value); - m_widgetMap[id]->setDisabled(m_ctrlMap[id].flags & CTRL_FLAG_DISABLED); - if (m_sliderMap.find(id) != m_sliderMap.end()) - m_sliderMap[id]->setDisabled(m_ctrlMap[id].flags & CTRL_FLAG_DISABLED); + for (ClassMap::iterator iter = m_classMap.begin(); iter != m_classMap.end(); ++iter) { + for (unsigned i = 0; i < m_classMap[iter->first].size(); i++) { + unsigned id = m_classMap[iter->first][i]; + struct v4l2_event_subscription sub; + + memset(&sub, 0, sizeof(sub)); + sub.type = V4L2_EVENT_CTRL; + sub.id = id; + subscribe_event(sub); } - return; } +} + +void ApplicationWindow::refresh(unsigned ctrl_class) +{ unsigned count = m_classMap[ctrl_class].size(); unsigned cnt = 0; struct v4l2_ext_control *c = new v4l2_ext_control[count]; @@ -700,6 +640,8 @@ for (unsigned i = 0; i < count; i++) { unsigned id = c[cnt].id = m_classMap[ctrl_class][i]; + c[cnt].size = 0; + c[cnt].reserved2[0] = 0; if (m_ctrlMap[id].type == V4L2_CTRL_TYPE_BUTTON) continue; if (m_ctrlMap[id].flags & V4L2_CTRL_FLAG_WRITE_ONLY) @@ -714,7 +656,7 @@ ctrls.count = cnt; ctrls.ctrl_class = ctrl_class; ctrls.controls = c; - if (ioctl(VIDIOC_G_EXT_CTRLS, &ctrls)) { + if (g_ext_ctrls(ctrls)) { if (ctrls.error_idx >= ctrls.count) { error(errno); } @@ -726,7 +668,7 @@ for (unsigned i = 0; i < ctrls.count; i++) { unsigned id = c[i].id; - queryctrl(m_ctrlMap[id]); + query_ext_ctrl(m_ctrlMap[id]); if (m_ctrlMap[id].type == V4L2_CTRL_TYPE_INTEGER64) setVal64(id, c[i].value64); else if (m_ctrlMap[id].type == V4L2_CTRL_TYPE_STRING) { @@ -735,9 +677,15 @@ } else setVal(id, c[i].value); - m_widgetMap[id]->setDisabled(m_ctrlMap[id].flags & CTRL_FLAG_DISABLED); + + bool disabled = m_ctrlMap[id].flags & CTRL_FLAG_DISABLED; + + if (qobject_cast(m_widgetMap[id])) + static_cast(m_widgetMap[id])->setReadOnly(disabled); + else + m_widgetMap[id]->setDisabled(disabled); if (m_sliderMap.find(id) != m_sliderMap.end()) - m_sliderMap[id]->setDisabled(m_ctrlMap[id].flags & CTRL_FLAG_DISABLED); + m_sliderMap[id]->setDisabled(disabled); } } delete [] c; @@ -751,18 +699,18 @@ void ApplicationWindow::setWhat(QWidget *w, unsigned id, const QString &v) { - const v4l2_queryctrl &qctrl = m_ctrlMap[id]; + const v4l2_query_ext_ctrl &qec = m_ctrlMap[id]; QString what; - QString flags = getCtrlFlags(qctrl.flags); + QString flags = getCtrlFlags(qec.flags); - switch (qctrl.type) { + switch (qec.type) { case V4L2_CTRL_TYPE_STRING: w->setWhatsThis(QString("Type: String\n" "Minimum: %1\n" "Maximum: %2\n" "Step: %3\n" "Current: %4") - .arg(qctrl.minimum).arg(qctrl.maximum).arg(qctrl.step).arg(v) + flags); + .arg(qec.minimum).arg(qec.maximum).arg(qec.step).arg(v) + flags); w->setStatusTip(w->whatsThis()); break; default: @@ -772,11 +720,11 @@ void ApplicationWindow::setWhat(QWidget *w, unsigned id, long long v) { - const v4l2_queryctrl &qctrl = m_ctrlMap[id]; + const v4l2_query_ext_ctrl &qec = m_ctrlMap[id]; QString what; - QString flags = getCtrlFlags(qctrl.flags); + QString flags = getCtrlFlags(qec.flags); - switch (qctrl.type) { + switch (qec.type) { case V4L2_CTRL_TYPE_INTEGER: w->setWhatsThis(QString("Type: Integer\n" "Minimum: %1\n" @@ -784,13 +732,18 @@ "Step: %3\n" "Current: %4\n" "Default: %5") - .arg(qctrl.minimum).arg(qctrl.maximum).arg(qctrl.step).arg(v).arg(qctrl.default_value) + flags); + .arg(qec.minimum).arg(qec.maximum).arg(qec.step).arg(v).arg(qec.default_value) + flags); w->setStatusTip(w->whatsThis()); break; case V4L2_CTRL_TYPE_INTEGER64: w->setWhatsThis(QString("Type: Integer64\n" - "Current: %1").arg(v) + flags); + "Minimum: %1\n" + "Maximum: %2\n" + "Step: %3\n" + "Current: %4\n" + "Default: %5") + .arg(qec.minimum).arg(qec.maximum).arg(qec.step).arg(v).arg(qec.default_value) + flags); w->setStatusTip(w->whatsThis()); break; @@ -799,8 +752,8 @@ "Maximum: %1\n" "Current: %2\n" "Default: %3") - .arg((unsigned)qctrl.maximum, 0, 16).arg((unsigned)v, 0, 16) - .arg((unsigned)qctrl.default_value, 0, 16) + flags); + .arg((unsigned)qec.maximum, 0, 16).arg((unsigned)v, 0, 16) + .arg((unsigned)qec.default_value, 0, 16) + flags); w->setStatusTip(w->whatsThis()); break; @@ -813,7 +766,7 @@ w->setWhatsThis(QString("Type: Boolean\n" "Current: %1\n" "Default: %2") - .arg(v).arg(qctrl.default_value) + flags); + .arg(v).arg(qec.default_value) + flags); w->setStatusTip(w->whatsThis()); break; @@ -823,7 +776,7 @@ "Maximum: %2\n" "Current: %3\n" "Default: %4") - .arg(qctrl.minimum).arg(qctrl.maximum).arg(v).arg(qctrl.default_value) + flags); + .arg(qec.minimum).arg(qec.maximum).arg(v).arg(qec.default_value) + flags); w->setStatusTip(w->whatsThis()); break; @@ -833,7 +786,7 @@ "Maximum: %2\n" "Current: %3\n" "Default: %4") - .arg(qctrl.minimum).arg(qctrl.maximum).arg(v).arg(qctrl.default_value) + flags); + .arg(qec.minimum).arg(qec.maximum).arg(v).arg(qec.default_value) + flags); w->setStatusTip(w->whatsThis()); break; default: @@ -843,16 +796,16 @@ void ApplicationWindow::setVal(unsigned id, int v) { - const v4l2_queryctrl &qctrl = m_ctrlMap[id]; + const v4l2_query_ext_ctrl &qec = m_ctrlMap[id]; v4l2_querymenu qmenu; - QWidget *w = m_widgetMap[qctrl.id]; + QWidget *w = m_widgetMap[qec.id]; int i, idx; unsigned dif; - switch (qctrl.type) { + switch (qec.type) { case V4L2_CTRL_TYPE_INTEGER: - dif = qctrl.maximum - qctrl.minimum; - if (dif <= 0xffffU || (qctrl.flags & V4L2_CTRL_FLAG_SLIDER)) + dif = qec.maximum - qec.minimum; + if (dif <= 0xffffU || (qec.flags & V4L2_CTRL_FLAG_SLIDER)) static_cast(w)->setValue(v); else static_cast(w)->setText(QString::number(v)); @@ -869,10 +822,10 @@ case V4L2_CTRL_TYPE_MENU: case V4L2_CTRL_TYPE_INTEGER_MENU: idx = 0; - for (i = qctrl.minimum; i <= v; i++) { + for (i = qec.minimum; i <= v; i++) { qmenu.id = id; qmenu.index = i; - if (!querymenu(qmenu)) + if (querymenu(qmenu)) continue; idx++; } @@ -886,10 +839,10 @@ void ApplicationWindow::setVal64(unsigned id, long long v) { - const v4l2_queryctrl &qctrl = m_ctrlMap[id]; - QWidget *w = m_widgetMap[qctrl.id]; + const v4l2_query_ext_ctrl &qec = m_ctrlMap[id]; + QWidget *w = m_widgetMap[qec.id]; - switch (qctrl.type) { + switch (qec.type) { case V4L2_CTRL_TYPE_INTEGER64: static_cast(w)->setText(QString::number(v)); break; @@ -901,10 +854,10 @@ void ApplicationWindow::setString(unsigned id, const QString &v) { - const v4l2_queryctrl &qctrl = m_ctrlMap[id]; - QWidget *w = m_widgetMap[qctrl.id]; + const v4l2_query_ext_ctrl &qec = m_ctrlMap[id]; + QWidget *w = m_widgetMap[qec.id]; - switch (qctrl.type) { + switch (qec.type) { case V4L2_CTRL_TYPE_STRING: static_cast(w)->setText(v); break; Binary files /tmp/hFHZnN35Bj/v4l-utils-1.0.0+r2263/utils/qv4l2/enterbutt.png and /tmp/LK0ZygNQ7o/v4l-utils-1.0.0+r2364/utils/qv4l2/enterbutt.png differ Binary files /tmp/hFHZnN35Bj/v4l-utils-1.0.0+r2263/utils/qv4l2/fullscreenexit.png and /tmp/LK0ZygNQ7o/v4l-utils-1.0.0+r2364/utils/qv4l2/fullscreenexit.png differ Binary files /tmp/hFHZnN35Bj/v4l-utils-1.0.0+r2263/utils/qv4l2/fullscreen.png and /tmp/LK0ZygNQ7o/v4l-utils-1.0.0+r2364/utils/qv4l2/fullscreen.png differ diff -Nru v4l-utils-1.0.0+r2263/utils/qv4l2/general-tab.cpp v4l-utils-1.0.0+r2364/utils/qv4l2/general-tab.cpp --- v4l-utils-1.0.0+r2263/utils/qv4l2/general-tab.cpp 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/qv4l2/general-tab.cpp 2014-08-12 09:02:18.000000000 +0000 @@ -24,8 +24,8 @@ #include #include #include -#include #include +#include #include #include @@ -43,9 +43,20 @@ AUDIO_ADD_READWRITE }; -GeneralTab::GeneralTab(const QString &device, v4l2 &fd, int n, QWidget *parent) : +static QString pixfmt2s(unsigned id) +{ + QString pixfmt; + + pixfmt += (char)(id & 0xff); + pixfmt += (char)((id >> 8) & 0xff); + pixfmt += (char)((id >> 16) & 0xff); + pixfmt += (char)((id >> 24) & 0xff); + return pixfmt; +} + +GeneralTab::GeneralTab(const QString &device, cv4l_fd *fd, int n, QWidget *parent) : QGridLayout(parent), - v4l2(fd), + m_fd(fd), m_row(0), m_col(0), m_cols(n), @@ -53,7 +64,6 @@ m_pxw(25.0), m_vMargin(10), m_hMargin(20), - m_maxh(0), m_isRadio(false), m_isSDR(false), m_isVbi(false), @@ -106,26 +116,26 @@ { m_device.append(device); setSizeConstraint(QLayout::SetMinimumSize); + for (int i = 0; i < n; i++) { m_maxw[i] = 0; } + querycap(m_querycap); - if (querycap(m_querycap)) { - addTitle("General Information"); + addTitle("General Information"); - addLabel("Device"); - addLabel(device + (useWrapper() ? " (wrapped)" : "")); + addLabel("Device"); + addLabel(device + (m_fd->g_direct() ? "" : " (wrapped)")); - addLabel("Driver"); - addLabel((char *)m_querycap.driver); + addLabel("Driver"); + addLabel((char *)m_querycap.driver); - addLabel("Card"); - addLabel((char *)m_querycap.card); + addLabel("Card"); + addLabel((char *)m_querycap.card); - addLabel("Bus"); - addLabel((char *)m_querycap.bus_info); - } + addLabel("Bus"); + addLabel((char *)m_querycap.bus_info); g_tuner(m_tuner); g_tuner(m_tuner_rf, 1); @@ -136,8 +146,6 @@ v4l2_audio vaudio; v4l2_audioout vaudout; v4l2_fmtdesc fmt; - bool needsStd = false; - bool needsTimings = false; if (m_tuner.capability && (m_tuner.capability & (V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_1HZ))) @@ -146,40 +154,32 @@ (m_modulator.capability & (V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_1HZ))) m_isRadio = true; if (m_querycap.capabilities & V4L2_CAP_DEVICE_CAPS) { - m_isVbi = caps() & (V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE); - m_isSDR = caps() & V4L2_CAP_SDR_CAPTURE; + m_isVbi = g_caps() & (V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE | + V4L2_CAP_VBI_OUTPUT | V4L2_CAP_SLICED_VBI_OUTPUT); + m_isSDR = g_caps() & V4L2_CAP_SDR_CAPTURE; if (m_isSDR) m_isRadio = true; - if (caps() & (V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_MPLANE)) + if (g_caps() & (V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_MPLANE | + V4L2_CAP_VBI_OUTPUT | V4L2_CAP_SLICED_VBI_OUTPUT)) m_isOutput = true; } if (m_querycap.capabilities & (V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_VIDEO_OUTPUT_MPLANE)) m_isPlanar = true; - if (isSlicedVbi()) - m_buftype = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; - else if (isVbi()) - m_buftype = V4L2_BUF_TYPE_VBI_CAPTURE; - else if (m_isOutput) - m_buftype = isPlanar() ? V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE : - V4L2_BUF_TYPE_VIDEO_OUTPUT; - else - m_buftype = isPlanar() ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : - V4L2_BUF_TYPE_VIDEO_CAPTURE; - m_stackedStandards = new QStackedWidget; - m_stackedFrameSettings = new QStackedWidget; - m_stackedFrequency = new QStackedWidget; + m_stackedStandards = new QStackedWidget(parent); + m_stackedFrameSettings = new QStackedWidget(parent); + m_stackedFrequency = new QStackedWidget(parent); - if (enum_input(vin, true) || m_tuner.capability) { + if (!enum_input(vin, true) || m_tuner.capability) { addTitle("Input Settings"); - inputSection(needsStd, needsTimings, vin); + inputSection(vin); } - if (m_tuner_rf.capability || m_modulator.capability || (!isRadio() && enum_output(vout, true))) { + if (m_modulator.capability || (!isRadio() && !enum_output(vout, true))) { addTitle("Output Settings"); - outputSection(vout, fmt); + outputSection(vout); } if (hasAlsaAudio()) { @@ -187,8 +187,8 @@ m_audioOutDevice = new QComboBox(parent); } - if (!isVbi() && (createAudioDeviceList() || (!isRadio() && enum_audio(vaudio, true)) || - (!isSDR() && m_tuner.capability) || (!isRadio() && enum_audout(vaudout, true)))) { + if (!isVbi() && (createAudioDeviceList() || (!isRadio() && !enum_audio(vaudio, true)) || + (!isSDR() && m_tuner.capability) || (!isRadio() && !enum_audout(vaudout, true)))) { addTitle("Audio Settings"); audioSection(vaudio, vaudout); } @@ -201,77 +201,106 @@ m_audioOutDevice = NULL; } - if (isRadio()) + if (!isSDR() && isRadio()) goto done; addTitle("Format Settings"); if (isVbi()) { - addLabel("VBI Capture Method"); - m_vbiMethods = new QComboBox(parent); - if (caps() & V4L2_CAP_VBI_CAPTURE) + addLabel("VBI Streaming Method"); + m_vbiMethods = new QComboBox(parentWidget()); + if (has_raw_vbi_cap() || has_raw_vbi_out()) m_vbiMethods->addItem("Raw"); - if (caps() & V4L2_CAP_SLICED_VBI_CAPTURE) + if (has_sliced_vbi_cap() || has_sliced_vbi_out()) m_vbiMethods->addItem("Sliced"); addWidget(m_vbiMethods); connect(m_vbiMethods, SIGNAL(activated(int)), SLOT(vbiMethodsChanged(int))); - updateVideoInput(); - goto capture_method; + vbiMethodsChanged(0); + if (m_isOutput) + updateVideoOutput(); + else + updateVideoInput(); + } else if (!isSDR()) { + formatSection(fmt); } - formatSection(fmt); -capture_method: - addLabel("Capture Method"); + addLabel("Streaming Method"); m_capMethods = new QComboBox(parent); - if (caps() & V4L2_CAP_STREAMING) { - v4l2_requestbuffers reqbuf; + if (has_streaming()) { + cv4l_queue q; - // Yuck. The videobuf framework does not accept a count of 0. + // Yuck. The videobuf framework does not accept a reqbufs count of 0. // This is out-of-spec, but it means that the only way to test which - // method is supported is to give it a non-zero count. But non-videobuf - // drivers like uvc do not allow e.g. S_FMT calls after a REQBUFS call - // with non-zero counts unless there is a REQBUFS call with count == 0 - // in between. This is actual proper behavior, although somewhat - // unexpected. So the only way at the moment to do this that works - // everywhere is to call REQBUFS with a count of 1, and then again with - // a count of 0. - if (reqbufs_user(reqbuf, 1)) { + // method is supported is to give it a non-zero count. But after that + // we have to reopen the device to clear the fact that there were + // buffers allocated. This is the only really portable way as long + // as there are still drivers around that do not support reqbufs(0). + q.init(g_type(), V4L2_MEMORY_USERPTR); + if (q.reqbufs(m_fd, 1) == 0) { m_capMethods->addItem("User pointer I/O", QVariant(methodUser)); - reqbufs_user(reqbuf, 0); + m_fd->reopen(true); } - if (reqbufs_mmap(reqbuf, 1)) { + q.init(g_type(), V4L2_MEMORY_MMAP); + if (q.reqbufs(m_fd, 1) == 0) { m_capMethods->addItem("Memory mapped I/O", QVariant(methodMmap)); - reqbufs_mmap(reqbuf, 0); + m_fd->reopen(true); } } - if (caps() & V4L2_CAP_READWRITE) { - m_capMethods->addItem("read()", QVariant(methodRead)); + if (has_rw()) { + if (v4l_type_is_output(g_type())) + m_capMethods->addItem("write()", QVariant(methodRead)); + else + m_capMethods->addItem("read()", QVariant(methodRead)); } addWidget(m_capMethods); + addLabel("Use Record Priority"); + m_recordPrio = new QCheckBox(parentWidget()); + addWidget(m_recordPrio); - - if (!isRadio() && !isVbi() && !m_isOutput && (has_crop() || has_compose())) { + if (!isRadio() && !isVbi() && (has_crop() || has_compose())) { addTitle("Cropping & Compose Settings"); cropSection(); } - updateVideoInput(); - updateVideoOutput(); - updateVidFormat(); + if (!isSDR()) { + if (m_isOutput) + updateVideoOutput(); + else + updateVideoInput(); + updateVidFormat(); + } done: QGridLayout::addWidget(new QWidget(parent), rowCount(), 0, 1, n); setRowStretch(rowCount() - 1, 1); if (m_videoInput) - updateGUI(m_videoInput->currentIndex()); - else - updateGUI(0); + updateGUIInput(m_videoInput->currentIndex()); + else if (m_videoOutput) + updateGUIOutput(m_videoOutput->currentIndex()); fixWidth(); } -void GeneralTab::inputSection(bool needsStd, bool needsTimings, v4l2_input vin) +void GeneralTab::sourceChangeSubscribe() { - if (!isRadio() && enum_input(vin, true)) { + v4l2_input vin; + + if (!enum_input(vin, true)) { + do { + struct v4l2_event_subscription sub = { + V4L2_EVENT_SOURCE_CHANGE, vin.index + }; + + subscribe_event(sub); + } while (!enum_input(vin)); + } +} + +void GeneralTab::inputSection(v4l2_input vin) +{ + bool needsStd = false; + bool needsTimings = false; + + if (!isRadio() && !enum_input(vin, true)) { addLabel("Input"); m_videoInput = new QComboBox(parentWidget()); do { @@ -280,13 +309,7 @@ needsStd = true; if (vin.capabilities & V4L2_IN_CAP_DV_TIMINGS) needsTimings = true; - - struct v4l2_event_subscription sub = { - V4L2_EVENT_SOURCE_CHANGE, vin.index - }; - - subscribe_event(sub); - } while (enum_input(vin)); + } while (!enum_input(vin)); addWidget(m_videoInput); connect(m_videoInput, SIGNAL(activated(int)), SLOT(inputChanged(int))); m_row++; @@ -305,9 +328,10 @@ m_stdRow->addWidget(m_tvStandard, 0, 1, Qt::AlignLeft); connect(m_tvStandard, SIGNAL(activated(int)), SLOT(standardChanged(int))); refreshStandards(); - if (ioctl_exists(VIDIOC_QUERYSTD, &tmp)) { - m_qryStandard = new QPushButton("Query Standard", parentWidget()); - m_stdRow->addWidget(new QLabel("", parentWidget()), 0, 2, Qt::AlignLeft); + if (query_std(tmp) != ENOTTY) { + m_qryStandard = new QToolButton(parentWidget()); + m_qryStandard->setIcon(QIcon(":/enterbutt.png")); + m_stdRow->addWidget(new QLabel("Query Standard", parentWidget()), 0, 2, Qt::AlignLeft); m_stdRow->addWidget(m_qryStandard, 0, 3, Qt::AlignLeft); connect(m_qryStandard, SIGNAL(clicked()), SLOT(qryStdClicked())); } @@ -323,8 +347,9 @@ m_timRow->addWidget(m_videoTimings, 0, 1, Qt::AlignLeft); connect(m_videoTimings, SIGNAL(activated(int)), SLOT(timingsChanged(int))); refreshTimings(); - m_qryTimings = new QPushButton("Query Timings", parentWidget()); - m_timRow->addWidget(new QLabel("", parentWidget()), 0, 2, Qt::AlignLeft); + m_qryTimings = new QToolButton(parentWidget()); + m_qryTimings->setIcon(QIcon(":/enterbutt.png")); + m_timRow->addWidget(new QLabel("Query Timings", parentWidget()), 0, 2, Qt::AlignLeft); m_timRow->addWidget(m_qryTimings, 0, 3, Qt::AlignLeft); connect(m_qryTimings, SIGNAL(clicked()), SLOT(qryTimingsClicked())); } @@ -341,6 +366,7 @@ if (m_tuner.capability) { const char *unit = (m_tuner.capability & V4L2_TUNER_CAP_LOW) ? " kHz" : (m_tuner.capability & V4L2_TUNER_CAP_1HZ ? " Hz" : " MHz"); + const char *name = m_isSDR ? "ADC Frequency" : "Frequency"; m_freqFac = (m_tuner.capability & V4L2_TUNER_CAP_1HZ) ? 1 : 16; m_freq = new QDoubleSpinBox(parentWidget()); @@ -349,22 +375,51 @@ m_freq->setSingleStep(1.0 / m_freqFac); m_freq->setSuffix(unit); m_freq->setDecimals((m_tuner.capability & V4L2_TUNER_CAP_1HZ) ? 0 : 4); - m_freq->setWhatsThis(QString("Frequency\nLow: %1 %3\nHigh: %2 %3") + m_freq->setWhatsThis(QString("%1\nLow: %2 %4\nHigh: %3 %4") + .arg(name) .arg((double)m_tuner.rangelow / m_freqFac, 0, 'f', 2) .arg((double)m_tuner.rangehigh / m_freqFac, 0, 'f', 2) .arg(unit)); m_freq->setStatusTip(m_freq->whatsThis()); connect(m_freq, SIGNAL(valueChanged(double)), SLOT(freqChanged(double))); updateFreq(); - m_freqRows->addWidget(new QLabel("Frequency", parentWidget()), 0, 0, Qt::AlignLeft); + m_freqRows->addWidget(new QLabel(name, parentWidget()), 0, 0, Qt::AlignLeft); m_freqRows->addWidget(m_freq, 0, 1, Qt::AlignLeft); } - if (m_tuner.capability && !isSDR()) { - m_subchannels = new QLabel("", parentWidget()); - m_detectSubchans = new QPushButton("Refresh Tuner Status", parentWidget()); - m_freqRows->addWidget(m_subchannels, 0, 2, Qt::AlignLeft); - m_freqRows->addWidget(m_detectSubchans, 0, 3, Qt::AlignLeft); + if (m_tuner_rf.capability) { + const char *unit = (m_tuner_rf.capability & V4L2_TUNER_CAP_LOW) ? " kHz" : + (m_tuner_rf.capability & V4L2_TUNER_CAP_1HZ ? " Hz" : " MHz"); + + m_freqRfFac = (m_tuner_rf.capability & V4L2_TUNER_CAP_1HZ) ? 1 : 16; + m_freqRf = new QDoubleSpinBox(parentWidget()); + m_freqRf->setMinimum(m_tuner_rf.rangelow / m_freqRfFac); + m_freqRf->setMaximum(m_tuner_rf.rangehigh / m_freqRfFac); + m_freqRf->setSingleStep(1.0 / m_freqRfFac); + m_freqRf->setSuffix(unit); + m_freqRf->setDecimals((m_tuner_rf.capability & V4L2_TUNER_CAP_1HZ) ? 0 : 4); + m_freqRf->setWhatsThis(QString("RF Frequency\nLow: %1 %3\nHigh: %2 %3") + .arg((double)m_tuner_rf.rangelow / m_freqRfFac, 0, 'f', 2) + .arg((double)m_tuner_rf.rangehigh / m_freqRfFac, 0, 'f', 2) + .arg(unit)); + m_freqRf->setStatusTip(m_freqRf->whatsThis()); + connect(m_freqRf, SIGNAL(valueChanged(double)), SLOT(freqRfChanged(double))); + updateFreqRf(); + m_freqRows->addWidget(new QLabel("RF Frequency", parentWidget()), 0, 2, Qt::AlignLeft); + m_freqRows->addWidget(m_freqRf, 0, 3, Qt::AlignLeft); + } else if (!isSDR()) { + QLabel *l = new QLabel("Refresh Tuner Status", parentWidget()); + QWidget *w = new QWidget(parentWidget()); + QHBoxLayout *box = new QHBoxLayout(w); + + box->setMargin(0); + m_detectSubchans = new QToolButton(w); + m_detectSubchans->setIcon(QIcon(":/enterbutt.png")); + m_subchannels = new QLabel("", w); + box->addWidget(m_detectSubchans, 0, Qt::AlignLeft); + box->addWidget(m_subchannels, 0, Qt::AlignLeft); + m_freqRows->addWidget(l, 0, 2, Qt::AlignLeft); + m_freqRows->addWidget(w, 0, 3, Qt::AlignLeft); connect(m_detectSubchans, SIGNAL(clicked()), SLOT(detectSubchansClicked())); detectSubchansClicked(); } @@ -389,6 +444,9 @@ QGridLayout::addWidget(m_stackedFrequency, m_row, 0, 2, m_cols, Qt::AlignVCenter); m_row += 2; + if (isRadio() || isVbi()) + return; + QWidget *wFrameWH = new QWidget(); QWidget *wFrameSR = new QWidget(); QGridLayout *m_wh = new QGridLayout(wFrameWH); @@ -423,56 +481,57 @@ m_row++; } -void GeneralTab::outputSection(v4l2_output vout, v4l2_fmtdesc fmt) +void GeneralTab::outputSection(v4l2_output vout) { - if (!isRadio() && enum_output(vout, true)) { + bool needsStd = false; + bool needsTimings = false; + + if (!isRadio() && !enum_output(vout, true)) { addLabel("Output"); m_videoOutput = new QComboBox(parentWidget()); do { m_videoOutput->addItem((char *)vout.name); - } while (enum_output(vout)); + if (vout.capabilities & V4L2_OUT_CAP_STD) + needsStd = true; + if (vout.capabilities & V4L2_OUT_CAP_DV_TIMINGS) + needsTimings = true; + } while (!enum_output(vout)); addWidget(m_videoOutput); connect(m_videoOutput, SIGNAL(activated(int)), SLOT(outputChanged(int))); updateVideoOutput(); + m_row++; + m_col = 0; } - if (m_isOutput) { - addLabel("Output Image Formats"); - m_vidOutFormats = new QComboBox(parentWidget()); - m_vidOutFormats->setMinimumContentsLength(20); - if (enum_fmt(fmt, m_buftype, true)) { - do { - m_vidOutFormats->addItem(pixfmt2s(fmt.pixelformat) + - " - " + (const char *)fmt.description); - } while (enum_fmt(fmt, m_buftype)); - } - addWidget(m_vidOutFormats); - connect(m_vidOutFormats, SIGNAL(activated(int)), SLOT(vidOutFormatChanged(int))); - } + QWidget *wStd = new QWidget(); + QGridLayout *m_stdRow = new QGridLayout(wStd); + m_grids.append(m_stdRow); + if (needsStd) { + m_tvStandard = new QComboBox(parentWidget()); + m_stdRow->addWidget(new QLabel("TV Standard", parentWidget()), 0, 0, Qt::AlignLeft); + m_stdRow->addWidget(m_tvStandard, 0, 1, Qt::AlignLeft); + connect(m_tvStandard, SIGNAL(activated(int)), SLOT(standardChanged(int))); + refreshStandards(); + } - if (m_tuner_rf.capability) { - const char *unit = (m_tuner_rf.capability & V4L2_TUNER_CAP_LOW) ? " kHz" : - (m_tuner_rf.capability & V4L2_TUNER_CAP_1HZ ? " Hz" : " MHz"); + QWidget *wTim = new QWidget(); + QGridLayout *m_timRow = new QGridLayout(wTim); + m_grids.append(m_timRow); - m_freqRfFac = (m_tuner_rf.capability & V4L2_TUNER_CAP_1HZ) ? 1 : 16; - m_freqRf = new QDoubleSpinBox(parentWidget()); - m_freqRf->setMinimum(m_tuner_rf.rangelow / m_freqRfFac); - m_freqRf->setMaximum(m_tuner_rf.rangehigh / m_freqRfFac); - m_freqRf->setSingleStep(1.0 / m_freqRfFac); - m_freqRf->setSuffix(unit); - m_freqRf->setDecimals((m_tuner_rf.capability & V4L2_TUNER_CAP_1HZ) ? 0 : 4); - m_freqRf->setWhatsThis(QString("RF Frequency\nLow: %1 %3\nHigh: %2 %3") - .arg((double)m_tuner_rf.rangelow / m_freqRfFac, 0, 'f', 2) - .arg((double)m_tuner_rf.rangehigh / m_freqRfFac, 0, 'f', 2) - .arg(unit)); - m_freqRf->setStatusTip(m_freqRf->whatsThis()); - connect(m_freqRf, SIGNAL(valueChanged(double)), SLOT(freqRfChanged(double))); - updateFreqRf(); - addLabel("RF Frequency"); - addWidget(m_freqRf); + if (needsTimings) { + m_videoTimings = new QComboBox(parentWidget()); + m_timRow->addWidget(new QLabel("Video Timings", parentWidget()), 0, 0, Qt::AlignLeft); + m_timRow->addWidget(m_videoTimings, 0, 1, Qt::AlignLeft); + connect(m_videoTimings, SIGNAL(activated(int)), SLOT(timingsChanged(int))); + refreshTimings(); } + m_stackedStandards->addWidget(wStd); + m_stackedStandards->addWidget(wTim); + QGridLayout::addWidget(m_stackedStandards, m_row, 0, 1, m_cols, Qt::AlignVCenter); + m_row++; + if (m_modulator.capability) { const char *unit = (m_modulator.capability & V4L2_TUNER_CAP_LOW) ? " kHz" : (m_modulator.capability & V4L2_TUNER_CAP_1HZ ? " Hz" : " MHz"); @@ -493,8 +552,7 @@ updateFreq(); addLabel("Frequency"); addWidget(m_freq); - } - if (m_modulator.capability && !isSDR()) { + if (m_modulator.capability & V4L2_TUNER_CAP_STEREO) { addLabel("Stereo"); m_stereoMode = new QCheckBox(parentWidget()); @@ -512,6 +570,28 @@ connect(m_rdsMode, SIGNAL(clicked()), SLOT(rdsModeChanged())); } } + + if (isRadio()) + return; + + QWidget *wFrameWH = new QWidget(); + QGridLayout *m_wh = new QGridLayout(wFrameWH); + m_grids.append(m_wh); + + m_wh->addWidget(new QLabel("Frame Width", parentWidget()), 0, 0, Qt::AlignLeft); + m_frameWidth = new QSpinBox(parentWidget()); + m_wh->addWidget(m_frameWidth, 0, 1, Qt::AlignLeft); + connect(m_frameWidth, SIGNAL(editingFinished()), SLOT(frameWidthChanged())); + + m_wh->addWidget(new QLabel("Frame Height", parentWidget()), 0, 2, Qt::AlignLeft); + m_frameHeight = new QSpinBox(parentWidget()); + m_wh->addWidget(m_frameHeight, 0, 3, Qt::AlignLeft); + connect(m_frameHeight, SIGNAL(editingFinished()), SLOT(frameHeightChanged())); + + m_stackedFrameSettings->addWidget(wFrameWH); + + QGridLayout::addWidget(m_stackedFrameSettings, m_row, 0, 1, m_cols, Qt::AlignVCenter); + m_row++; } void GeneralTab::audioSection(v4l2_audio vaudio, v4l2_audioout vaudout) @@ -530,7 +610,7 @@ setAudioDeviceBufferSize(75); } else { v4l2_fract fract; - if (!v4l2::get_interval(m_buftype, fract)) { + if (m_fd->get_interval(fract)) { // Default values are for 30 FPS fract.numerator = 33; fract.denominator = 1000; @@ -546,13 +626,13 @@ } } - if (!isRadio() && enum_audio(vaudio, true)) { + if (!isRadio() && !enum_audio(vaudio, true)) { addLabel("Input Audio"); m_audioInput = new QComboBox(parentWidget()); m_audioInput->setMinimumContentsLength(10); do { m_audioInput->addItem((char *)vaudio.name); - } while (enum_audio(vaudio)); + } while (!enum_audio(vaudio)); addWidget(m_audioInput); connect(m_audioInput, SIGNAL(activated(int)), SLOT(inputAudioChanged(int))); updateAudioInput(); @@ -589,13 +669,13 @@ connect(m_audioMode, SIGNAL(activated(int)), SLOT(audioModeChanged(int))); } - if (!isRadio() && enum_audout(vaudout, true)) { + if (!isRadio() && !enum_audout(vaudout, true)) { addLabel("Output Audio"); m_audioOutput = new QComboBox(parentWidget()); m_audioOutput->setMinimumContentsLength(10); do { m_audioOutput->addItem((char *)vaudout.name); - } while (enum_audout(vaudout)); + } while (!enum_audout(vaudout)); addWidget(m_audioOutput); connect(m_audioOutput, SIGNAL(activated(int)), SLOT(outputAudioChanged(int))); updateAudioOutput(); @@ -604,11 +684,23 @@ void GeneralTab::formatSection(v4l2_fmtdesc fmt) { - if (!m_isOutput) { + if (m_isOutput) { + addLabel("Output Image Formats"); + m_vidOutFormats = new QComboBox(parentWidget()); + m_vidOutFormats->setMinimumContentsLength(20); + if (!enum_fmt(fmt, true)) { + do { + m_vidOutFormats->addItem(pixfmt2s(fmt.pixelformat) + + " (" + (const char *)fmt.description + ")"); + } while (!enum_fmt(fmt)); + } + addWidget(m_vidOutFormats); + connect(m_vidOutFormats, SIGNAL(activated(int)), SLOT(vidOutFormatChanged(int))); + } else { addLabel("Capture Image Formats"); m_vidCapFormats = new QComboBox(parentWidget()); m_vidCapFormats->setMinimumContentsLength(20); - if (enum_fmt(fmt, m_buftype, true)) { + if (!enum_fmt(fmt, true)) { do { QString s(pixfmt2s(fmt.pixelformat) + " ("); @@ -616,7 +708,7 @@ m_vidCapFormats->addItem(s + "Emulated)"); else m_vidCapFormats->addItem(s + (const char *)fmt.description + ")"); - } while (enum_fmt(fmt, m_buftype)); + } while (!enum_fmt(fmt)); } addWidget(m_vidCapFormats); connect(m_vidCapFormats, SIGNAL(activated(int)), SLOT(vidCapFormatChanged(int))); @@ -628,6 +720,9 @@ addWidget(m_vidFields); connect(m_vidFields, SIGNAL(activated(int)), SLOT(vidFieldChanged(int))); + if (m_isOutput) + return; + m_cropping = new QComboBox(parentWidget()); m_cropping->addItem("Source Width and Height"); m_cropping->addItem("Crop Top and Bottom Line"); @@ -764,6 +859,11 @@ QList list = parentWidget()->findChildren(); QList::iterator it; for (it = list.begin(); it != list.end(); ++it) { + if (!qobject_cast(*it) && + !qobject_cast(*it) && + !qobject_cast(*it)) + continue; + if (((*it)->sizeHint().width()) > m_minWidth) { m_increment = (int) ceil(((*it)->sizeHint().width() - m_minWidth) / m_pxw); (*it)->setMinimumWidth(m_minWidth + m_increment * m_pxw); // for stepsize expansion of widgets @@ -779,10 +879,12 @@ if ((*i)->itemAt(n)->widget()->sizeHint().width() > m_maxw[n % 4]) { m_maxw[n % 4] = (*i)->itemAt(n)->widget()->sizeHint().width(); } - if (n % 2) - (*i)->itemAt(n)->widget()->setMinimumWidth(m_minWidth); - else + if (n % 2) { + if (!qobject_cast((*i)->itemAt(n)->widget())) + (*i)->itemAt(n)->widget()->setMinimumWidth(m_minWidth); + } else { (*i)->itemAt(n)->widget()->setMinimumWidth(m_maxw[n % 4]); + } } for (int j = 0; j < m_cols; j++) { if (j % 2) @@ -870,65 +972,10 @@ m_vbiMethods->setDisabled(haveBuffers); } -void GeneralTab::showAllAudioDevices(bool use) +bool GeneralTab::filterAudioDevice(QString &deviceName) { - QString oldIn(m_audioInDevice->currentText()); - QString oldOut(m_audioOutDevice->currentText()); - - m_fullAudioName = use; - if (oldIn == NULL || oldOut == NULL || !createAudioDeviceList()) - return; - - // Select a similar device as before the listings method change - // check by comparing old selection with any matching in the new list - bool setIn = false, setOut = false; - int listSize = std::max(m_audioInDevice->count(), m_audioOutDevice->count()); - - for (int i = 0; i < listSize; i++) { - QString oldInCmp(oldIn.left(std::min(m_audioInDevice->itemText(i).length(), oldIn.length()))); - QString oldOutCmp(oldOut.left(std::min(m_audioOutDevice->itemText(i).length(), oldOut.length()))); - - if (!setIn && i < m_audioInDevice->count() - && m_audioInDevice->itemText(i).startsWith(oldInCmp)) { - setIn = true; - m_audioInDevice->setCurrentIndex(i); - } - - if (!setOut && i < m_audioOutDevice->count() - && m_audioOutDevice->itemText(i).startsWith(oldOutCmp)) { - setOut = true; - m_audioOutDevice->setCurrentIndex(i); - } - } -} - -bool GeneralTab::filterAudioInDevice(QString &deviceName) -{ - // Removes S/PDIF, front speakers and surround from input devices - // as they are output devices, not input - if (deviceName.contains("surround") - || deviceName.contains("front") - || deviceName.contains("iec958")) - return false; - - // Removes sysdefault too if not full audio mode listings - if (!m_fullAudioName && deviceName.contains("sysdefault")) - return false; - - return true; -} - -bool GeneralTab::filterAudioOutDevice(QString &deviceName) -{ - // Removes advanced options if not full audio mode listings - if (!m_fullAudioName && (deviceName.contains("surround") - || deviceName.contains("front") - || deviceName.contains("iec958") - || deviceName.contains("sysdefault"))) { - return false; - } - - return true; + // Only show hw devices + return deviceName.contains("hw") && !deviceName.contains("plughw"); } int GeneralTab::addAudioDevice(void *hint, int deviceNum) @@ -973,13 +1020,13 @@ listName.append(QString(" %1").arg(devNo)); } - if ((iotype == NULL || strncmp(iotype, "Input", 5) == 0) && filterAudioInDevice(deviceName)) { + if ((iotype == NULL || strncmp(iotype, "Input", 5) == 0) && filterAudioDevice(deviceName)) { m_audioInDevice->addItem(listName); m_audioInDeviceMap[listName] = snd_device_name_get_hint(hint, "NAME"); added += AUDIO_ADD_READ; } - if ((iotype == NULL || strncmp(iotype, "Output", 6) == 0) && filterAudioOutDevice(deviceName)) { + if ((iotype == NULL || strncmp(iotype, "Output", 6) == 0) && filterAudioDevice(deviceName)) { m_audioOutDevice->addItem(listName); m_audioOutDeviceMap[listName] = snd_device_name_get_hint(hint, "NAME"); added += AUDIO_ADD_WRITE; @@ -1046,12 +1093,10 @@ void GeneralTab::addWidget(QWidget *w, Qt::Alignment align) { - if (m_col % 2) + if (m_col % 2 && !qobject_cast(w)) w->setMinimumWidth(m_minWidth); if (w->sizeHint().width() > m_maxw[m_col]) m_maxw[m_col] = w->sizeHint().width(); - if (w->sizeHint().height() > m_maxh) - m_maxh = w->sizeHint().height(); QGridLayout::addWidget(w, m_row, m_col, align | Qt::AlignVCenter); m_col++; if (m_col == m_cols) { @@ -1089,11 +1134,6 @@ return total; } -int GeneralTab::getHeight() -{ - return rowCount() * m_maxh; -} - bool GeneralTab::isSlicedVbi() const { return m_vbiMethods && m_vbiMethods->currentText() == "Sliced"; @@ -1104,16 +1144,16 @@ return (CapMethod)m_capMethods->itemData(m_capMethods->currentIndex()).toInt(); } -void GeneralTab::updateGUI(int input) +void GeneralTab::updateGUIInput(__u32 input) { v4l2_input in; enum_input(in, true, input); - if (!g_input(input) || m_isRadio) { + if (g_input(input) || m_isRadio) { m_stackedFrameSettings->hide(); return; } - if (in.capabilities & V4L2_IN_CAP_STD && in.type == V4L2_INPUT_TYPE_TUNER) { + if ((in.capabilities & V4L2_IN_CAP_STD) && in.type == V4L2_INPUT_TYPE_TUNER) { m_stackedFrameSettings->setCurrentIndex(0); m_stackedFrameSettings->show(); m_stackedStandards->setCurrentIndex(0); @@ -1144,34 +1184,72 @@ } } +void GeneralTab::updateGUIOutput(__u32 output) +{ + v4l2_output out; + enum_output(out, true, output); + if (g_output(output) || m_isRadio) { + m_stackedFrameSettings->hide(); + return; + } + + if (out.capabilities & V4L2_OUT_CAP_STD) { + m_stackedFrameSettings->setCurrentIndex(0); + m_stackedFrameSettings->show(); + m_stackedStandards->setCurrentIndex(0); + m_stackedStandards->show(); + m_stackedFrequency->hide(); + } else if (out.capabilities & V4L2_OUT_CAP_DV_TIMINGS) { + m_stackedFrameSettings->setCurrentIndex(0); + m_stackedFrameSettings->show(); + m_stackedStandards->setCurrentIndex(1); + m_stackedStandards->show(); + m_stackedFrequency->hide(); + } else { + m_stackedFrameSettings->setCurrentIndex(1); + m_stackedFrameSettings->show(); + m_stackedStandards->hide(); + m_stackedFrequency->hide(); + } + + if (isVbi()) { + m_stackedFrameSettings->hide(); + } +} + void GeneralTab::inputChanged(int input) { - s_input(input); + s_input((__u32)input); if (m_audioInput) updateAudioInput(); updateVideoInput(); updateVidCapFormat(); - updateGUI(input); + updateGUIInput(input); } void GeneralTab::outputChanged(int output) { - s_output(output); + s_output((__u32)output); + + if (m_audioOutput) + updateAudioOutput(); + updateVideoOutput(); updateVidOutFormat(); + updateGUIOutput(output); } void GeneralTab::inputAudioChanged(int input) { - s_audio(input); + s_audio((__u32)input); updateAudioInput(); } void GeneralTab::outputAudioChanged(int output) { - s_audout(output); + s_audout((__u32)output); updateAudioOutput(); } @@ -1289,16 +1367,13 @@ { v4l2_fmtdesc desc; - enum_fmt(desc, m_buftype, true, idx); + enum_fmt(desc, true, idx); - v4l2_format fmt; + cv4l_fmt fmt; - g_fmt(m_buftype, fmt); - if (isPlanar()) - fmt.fmt.pix_mp.pixelformat = desc.pixelformat; - else - fmt.fmt.pix.pixelformat = desc.pixelformat; - if (try_fmt(fmt)) + g_fmt(fmt); + fmt.s_pixelformat(desc.pixelformat); + if (try_fmt(fmt) == 0) s_fmt(fmt); updateVidCapFormat(); @@ -1334,15 +1409,12 @@ void GeneralTab::vidFieldChanged(int idx) { - v4l2_format fmt; + cv4l_fmt fmt; - g_fmt(m_buftype, fmt); + g_fmt(fmt); for (__u32 f = V4L2_FIELD_NONE; f <= V4L2_FIELD_INTERLACED_BT; f++) { if (m_vidFields->currentText() == QString(field2s(f))) { - if (isPlanar()) - fmt.fmt.pix_mp.field = f; - else - fmt.fmt.pix.field = f; + fmt.s_field(f); s_fmt(fmt); break; } @@ -1352,16 +1424,16 @@ void GeneralTab::frameWidthChanged() { - v4l2_format fmt; + cv4l_fmt fmt; int val = m_frameWidth->value(); if (m_frameWidth->isEnabled()) { - g_fmt(m_buftype, fmt); - if (isPlanar()) - fmt.fmt.pix_mp.width = val; - else - fmt.fmt.pix.width = val; - if (try_fmt(fmt)) + g_fmt(fmt); + fmt.s_width(val); + // Force the driver to recalculate bytesperline. + for (unsigned p = 0; p < fmt.g_num_planes(); p++) + fmt.s_bytesperline(0, p); + if (try_fmt(fmt) == 0) s_fmt(fmt); } @@ -1370,16 +1442,13 @@ void GeneralTab::frameHeightChanged() { - v4l2_format fmt; + cv4l_fmt fmt; int val = m_frameHeight->value(); if (m_frameHeight->isEnabled()) { - g_fmt(m_buftype, fmt); - if (isPlanar()) - fmt.fmt.pix_mp.height = val; - else - fmt.fmt.pix.height = val; - if (try_fmt(fmt)) + g_fmt(fmt); + fmt.s_height(val); + if (try_fmt(fmt) == 0) s_fmt(fmt); } @@ -1388,20 +1457,18 @@ void GeneralTab::frameSizeChanged(int idx) { - v4l2_frmsizeenum frmsize; + v4l2_frmsizeenum frmsize = { 0 }; - if (enum_framesizes(frmsize, m_pixelformat, idx)) { - v4l2_format fmt; + if (!enum_framesizes(frmsize, m_pixelformat, idx)) { + cv4l_fmt fmt; - g_fmt(m_buftype, fmt); - if (isPlanar()) { - fmt.fmt.pix_mp.width = frmsize.discrete.width; - fmt.fmt.pix_mp.height = frmsize.discrete.height; - } else { - fmt.fmt.pix.width = frmsize.discrete.width; - fmt.fmt.pix.height = frmsize.discrete.height; - } - if (try_fmt(fmt)) + g_fmt(fmt); + fmt.s_width(frmsize.discrete.width); + fmt.s_height(frmsize.discrete.height); + // Force the driver to recalculate bytesperline. + for (unsigned p = 0; p < fmt.g_num_planes(); p++) + fmt.s_bytesperline(0, p); + if (try_fmt(fmt) == 0) s_fmt(fmt); } updateVidFormat(); @@ -1409,11 +1476,11 @@ void GeneralTab::frameIntervalChanged(int idx) { - v4l2_frmivalenum frmival; + v4l2_frmivalenum frmival = { 0 }; - if (enum_frameintervals(frmival, m_pixelformat, m_width, m_height, idx) + if (!enum_frameintervals(frmival, m_pixelformat, m_width, m_height, idx) && frmival.type == V4L2_FRMIVAL_TYPE_DISCRETE) { - if (set_interval(m_buftype, frmival.discrete)) + if (!set_interval(frmival.discrete)) m_interval = frmival.discrete; } } @@ -1422,62 +1489,71 @@ { v4l2_fmtdesc desc; - enum_fmt(desc, m_buftype, true, idx); + enum_fmt(desc, true, idx); - v4l2_format fmt; + cv4l_fmt fmt; - g_fmt(m_buftype, fmt); - fmt.fmt.pix.pixelformat = desc.pixelformat; - if (try_fmt(fmt)) + g_fmt(fmt); + fmt.s_pixelformat(desc.pixelformat); + if (try_fmt(fmt) == 0) s_fmt(fmt); updateVidOutFormat(); } void GeneralTab::vbiMethodsChanged(int idx) { - m_buftype = isSlicedVbi() ? V4L2_BUF_TYPE_SLICED_VBI_CAPTURE : - V4L2_BUF_TYPE_VBI_CAPTURE; + if (isSlicedVbi()) + s_type(m_isOutput ? V4L2_BUF_TYPE_SLICED_VBI_OUTPUT : + V4L2_BUF_TYPE_SLICED_VBI_CAPTURE); + else + s_type(m_isOutput ? V4L2_BUF_TYPE_VBI_OUTPUT : + V4L2_BUF_TYPE_VBI_CAPTURE); + cv4l_fmt fmt; + + g_fmt(fmt); + s_fmt(fmt); } void GeneralTab::cropChanged() { - v4l2_crop crop; + v4l2_selection sel = { 0 }; - if (!m_cropWidth->isEnabled()) + if (!m_cropWidth->isEnabled() || !cur_io_has_crop()) return; - crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - crop.c.width = m_cropWidth->value(); - crop.c.left = m_cropLeft->value(); - crop.c.height = m_cropHeight->value(); - crop.c.top = m_cropTop->value(); - ioctl("Set Crop Rectangle", VIDIOC_S_CROP, &crop); - updateVidCapFormat(); + sel.type = g_selection_type(); + sel.target = V4L2_SEL_TGT_CROP; + sel.r.width = m_cropWidth->value(); + sel.r.left = m_cropLeft->value(); + sel.r.height = m_cropHeight->value(); + sel.r.top = m_cropTop->value(); + s_selection(sel); + updateVidFormat(); } void GeneralTab::composeChanged() { - v4l2_selection sel; + v4l2_selection sel = { 0 }; - if (!m_composeWidth->isEnabled() || !input_has_compose()) + if (!m_composeWidth->isEnabled() || !cur_io_has_compose()) return; - sel.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + sel.type = g_selection_type(); sel.target = V4L2_SEL_TGT_COMPOSE; sel.r.width = m_composeWidth->value(); sel.r.left = m_composeLeft->value(); sel.r.height = m_composeHeight->value(); sel.r.top = m_composeTop->value(); - ioctl("Set Compose Rectangle", VIDIOC_S_SELECTION, &sel); - updateVidCapFormat(); + s_selection(sel); + updateVidFormat(); } void GeneralTab::updateVideoInput() { - int input; + __u32 input; v4l2_input in; - if (!g_input(input)) + if (g_input(input)) return; enum_input(in, true, input); m_videoInput->setCurrentIndex(input); @@ -1514,7 +1590,7 @@ if (m_audioInput) m_audioInput->setEnabled(in.audioset); if (m_cropWidth) { - bool has_crop = input_has_crop(); + bool has_crop = cur_io_has_crop(); m_cropWidth->setEnabled(has_crop); m_cropLeft->setEnabled(has_crop); @@ -1522,7 +1598,7 @@ m_cropTop->setEnabled(has_crop); } if (m_composeWidth) { - bool has_compose = input_has_compose(); + bool has_compose = cur_io_has_compose(); m_composeWidth->setEnabled(has_compose); m_composeLeft->setEnabled(has_compose); @@ -1533,10 +1609,10 @@ void GeneralTab::updateVideoOutput() { - int output; + __u32 output; v4l2_output out; - if (!g_output(output)) + if (g_output(output)) return; enum_output(out, true, output); m_videoOutput->setCurrentIndex(output); @@ -1552,6 +1628,25 @@ updateTimings(); m_videoTimings->setEnabled(out.capabilities & V4L2_OUT_CAP_DV_TIMINGS); } + if (m_audioOutput) + m_audioOutput->setEnabled(out.audioset); + if (m_cropWidth) { + bool has_crop = cur_io_has_crop(); + + m_cropWidth->setEnabled(has_crop); + m_cropLeft->setEnabled(has_crop); + m_cropHeight->setEnabled(has_crop); + m_cropTop->setEnabled(has_crop); + } + if (m_composeWidth) { + bool has_compose = cur_io_has_compose(); + + m_composeWidth->setEnabled(has_compose); + m_composeLeft->setEnabled(has_compose); + m_composeHeight->setEnabled(has_compose); + m_composeTop->setEnabled(has_compose); + } + g_mw->updateLimRGBRange(); } void GeneralTab::updateAudioInput() @@ -1585,10 +1680,10 @@ { v4l2_standard vs; m_tvStandard->clear(); - if (enum_std(vs, true)) { + if (!enum_std(vs, true)) { do { m_tvStandard->addItem((char *)vs.name); - } while (enum_std(vs)); + } while (!enum_std(vs)); } } @@ -1598,19 +1693,20 @@ v4l2_standard vs; QString what; - g_std(std); - if (enum_std(vs, true)) { - do { - if (vs.id == std) - break; - } while (enum_std(vs)); - } + if (g_std(std)) + return; + if (enum_std(vs, true)) + return; + do { + if (vs.id == std) + break; + } while (!enum_std(vs)); if (vs.id != std) { - if (enum_std(vs, true)) { + if (!enum_std(vs, true)) { do { if (vs.id & std) break; - } while (enum_std(vs)); + } while (!enum_std(vs)); } } if ((vs.id & std) == 0) @@ -1625,7 +1721,7 @@ m_tvStandard->setStatusTip(what); m_tvStandard->setWhatsThis(what); updateVidFormat(); - if (!isVbi()) + if (!isVbi() && !m_isOutput) changePixelAspectRatio(); } @@ -1633,7 +1729,7 @@ { v4l2_std_id std; - if (!query_std(std)) + if (query_std(std)) return; if (std == V4L2_STD_UNKNOWN) { @@ -1648,7 +1744,7 @@ { v4l2_enum_dv_timings timings; m_videoTimings->clear(); - if (enum_dv_timings(timings, true)) { + if (!enum_dv_timings(timings, true)) { do { v4l2_bt_timings &bt = timings.timings.bt; double tot_height = bt.height + @@ -1665,7 +1761,7 @@ sprintf(buf, "%dx%dp%.2f", bt.width, bt.height, (double)bt.pixelclock / (tot_width * tot_height)); m_videoTimings->addItem(buf); - } while (enum_dv_timings(timings)); + } while (!enum_dv_timings(timings)); } } @@ -1675,13 +1771,14 @@ v4l2_enum_dv_timings p; QString what; - g_dv_timings(timings); - if (enum_dv_timings(p, true)) { - do { - if (!memcmp(&timings, &p.timings, sizeof(timings))) - break; - } while (enum_dv_timings(p)); - } + if (g_dv_timings(timings)) + return; + if (enum_dv_timings(p, true)) + return; + do { + if (!memcmp(&timings, &p.timings, sizeof(timings))) + break; + } while (!enum_dv_timings(p)); if (memcmp(&timings, &p.timings, sizeof(timings))) return; m_videoTimings->setCurrentIndex(p.index); @@ -1691,15 +1788,31 @@ m_videoTimings->setStatusTip(what); m_videoTimings->setWhatsThis(what); updateVidFormat(); + g_mw->updateLimRGBRange(); } void GeneralTab::qryTimingsClicked() { v4l2_dv_timings timings; + int err = query_dv_timings(timings); - if (query_dv_timings(timings)) { + switch (err) { + case ENOLINK: + info("No signal found\n"); + break; + case ENOLCK: + info("Could not lock to signal\n"); + break; + case ERANGE: + info("Frequency out of range\n"); + break; + case 0: s_dv_timings(timings); updateTimings(); + break; + default: + error(err); + break; } } @@ -1748,40 +1861,24 @@ void GeneralTab::updateVidCapFormat() { v4l2_fmtdesc desc; - v4l2_format fmt; + cv4l_fmt fmt; if (isVbi()) return; - g_fmt(m_buftype, fmt); - if (isPlanar()) { - m_pixelformat = fmt.fmt.pix_mp.pixelformat; - m_width = fmt.fmt.pix_mp.width; - m_height = fmt.fmt.pix_mp.height; - } else { - m_pixelformat = fmt.fmt.pix.pixelformat; - m_width = fmt.fmt.pix.width; - m_height = fmt.fmt.pix.height; - } + g_fmt(fmt); + m_pixelformat = fmt.g_pixelformat(); + m_width = fmt.g_width(); + m_height = fmt.g_height(); updateFrameSize(); updateFrameInterval(); - if (enum_fmt(desc, m_buftype, true)) { + if (!enum_fmt(desc, true)) { do { - if (isPlanar()) { - if (desc.pixelformat == fmt.fmt.pix_mp.pixelformat) - break; - } else { - if (desc.pixelformat == fmt.fmt.pix.pixelformat) - break; - } - } while (enum_fmt(desc, m_buftype)); - } - if (isPlanar()) { - if (desc.pixelformat != fmt.fmt.pix_mp.pixelformat) - return; - } else { - if (desc.pixelformat != fmt.fmt.pix.pixelformat) - return; + if (desc.pixelformat == m_pixelformat) + break; + } while (!enum_fmt(desc)); } + if (desc.pixelformat != m_pixelformat) + return; m_vidCapFormats->setCurrentIndex(desc.index); updateVidFields(); updateCrop(); @@ -1791,75 +1888,49 @@ void GeneralTab::updateVidOutFormat() { v4l2_fmtdesc desc; - v4l2_format fmt; + cv4l_fmt fmt; - g_fmt(m_buftype, fmt); - if (isPlanar()) { - m_pixelformat = fmt.fmt.pix_mp.pixelformat; - m_width = fmt.fmt.pix_mp.width; - m_height = fmt.fmt.pix_mp.height; - } else { - m_pixelformat = fmt.fmt.pix.pixelformat; - m_width = fmt.fmt.pix.width; - m_height = fmt.fmt.pix.height; - } + if (isVbi()) + return; + g_fmt(fmt); + m_pixelformat = fmt.g_pixelformat(); + m_width = fmt.g_width(); + m_height = fmt.g_height(); updateFrameSize(); - updateFrameInterval(); - if (enum_fmt(desc, m_buftype, true)) { + if (!enum_fmt(desc, true)) { do { - if (isPlanar()) { - if (desc.pixelformat == fmt.fmt.pix_mp.pixelformat) - break; - } else { - if (desc.pixelformat == fmt.fmt.pix.pixelformat) - break; - } - } while (enum_fmt(desc, m_buftype)); - } - if (isPlanar()) { - if (desc.pixelformat != fmt.fmt.pix_mp.pixelformat) - return; - } else { - if (desc.pixelformat != fmt.fmt.pix.pixelformat) - return; + if (desc.pixelformat == m_pixelformat) + break; + } while (!enum_fmt(desc)); } + if (desc.pixelformat != m_pixelformat) + return; m_vidOutFormats->setCurrentIndex(desc.index); updateVidFields(); + updateCrop(); + updateCompose(); } void GeneralTab::updateVidFields() { - v4l2_format fmt; - v4l2_format tmp; + cv4l_fmt fmt; + cv4l_fmt tmp; bool first = true; - g_fmt(m_buftype, fmt); + g_fmt(fmt); for (__u32 f = V4L2_FIELD_NONE; f <= V4L2_FIELD_INTERLACED_BT; f++) { tmp = fmt; - if (isPlanar()) { - tmp.fmt.pix_mp.field = f; - if (!try_fmt(tmp) || tmp.fmt.pix_mp.field != f) - continue; - if (first) { - m_vidFields->clear(); - first = false; - } - m_vidFields->addItem(field2s(f)); - if (fmt.fmt.pix_mp.field == f) - m_vidFields->setCurrentIndex(m_vidFields->count() - 1); - } else { - tmp.fmt.pix.field = f; - if (!try_fmt(tmp) || tmp.fmt.pix.field != f) - continue; - if (first) { - m_vidFields->clear(); - first = false; - } - m_vidFields->addItem(field2s(f)); - if (fmt.fmt.pix.field == f) - m_vidFields->setCurrentIndex(m_vidFields->count() - 1); - } + tmp.s_field(f); + if (try_fmt(tmp) || tmp.g_field() != f) + continue; + if (first) { + m_vidFields->clear(); + first = false; + } + m_vidFields->addItem(field2s(f)); + if (fmt.g_field() == f) + m_vidFields->setCurrentIndex(m_vidFields->count() - 1); } } @@ -1868,14 +1939,19 @@ if (m_cropWidth == NULL || !m_cropWidth->isEnabled()) return; - v4l2_cropcap cropcap; - v4l2_rect &b = cropcap.bounds; - v4l2_crop crop; - v4l2_rect &c = crop.c; - - cropcap.type = crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (ioctl(VIDIOC_CROPCAP, &cropcap) || - ioctl(VIDIOC_G_CROP, &crop)) + v4l2_selection sel = { 0 }; + v4l2_rect &r = sel.r; + v4l2_rect b = { 0, 0, m_width, m_height }; + + sel.type = g_selection_type(); + if (sel.type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + sel.target = V4L2_SEL_TGT_CROP_BOUNDS; + if (g_selection(sel)) + return; + b = sel.r; + } + sel.target = V4L2_SEL_TGT_CROP; + if (g_selection(sel)) return; m_cropWidth->blockSignals(true); @@ -1884,16 +1960,16 @@ m_cropTop->blockSignals(true); m_cropWidth->setRange(8, b.width); - m_cropWidth->setSliderPosition(c.width); - if (b.width != c.width) { - m_cropLeft->setRange(b.left, b.left + b.width - c.width); - m_cropLeft->setSliderPosition(c.left); + m_cropWidth->setSliderPosition(r.width); + if (b.width != r.width) { + m_cropLeft->setRange(b.left, b.left + b.width - r.width); + m_cropLeft->setSliderPosition(r.left); } m_cropHeight->setRange(8, b.height); - m_cropHeight->setSliderPosition(c.height); - if (b.height != c.height) { - m_cropTop->setRange(b.top, b.top + b.height - c.height); - m_cropTop->setSliderPosition(c.top); + m_cropHeight->setSliderPosition(r.height); + if (b.height != r.height) { + m_cropTop->setRange(b.top, b.top + b.height - r.height); + m_cropTop->setSliderPosition(r.top); } m_cropWidth->blockSignals(false); @@ -1907,12 +1983,19 @@ if (m_composeWidth == NULL || !m_composeWidth->isEnabled()) return; - v4l2_selection sel; + v4l2_selection sel = { 0 }; v4l2_rect &r = sel.r; + v4l2_rect b = { 0, 0, m_width, m_height }; - sel.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + sel.type = g_selection_type(); + if (sel.type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { + sel.target = V4L2_SEL_TGT_COMPOSE_BOUNDS; + if (g_selection(sel)) + return; + b = sel.r; + } sel.target = V4L2_SEL_TGT_COMPOSE; - if (ioctl(VIDIOC_G_SELECTION, &sel)) + if (g_selection(sel)) return; m_composeWidth->blockSignals(true); @@ -1920,16 +2003,16 @@ m_composeHeight->blockSignals(true); m_composeTop->blockSignals(true); - m_composeWidth->setRange(8, m_width); + m_composeWidth->setRange(8, b.width); m_composeWidth->setSliderPosition(r.width); - if (m_width != r.width) { - m_composeLeft->setRange(0, m_width - r.width); + if (b.width != r.width) { + m_composeLeft->setRange(b.left, b.left + b.width - r.width); m_composeLeft->setSliderPosition(r.left); } - m_composeHeight->setRange(8, m_height); + m_composeHeight->setRange(8, b.height); m_composeHeight->setSliderPosition(r.height); - if (m_height != r.height) { - m_composeTop->setRange(0, m_height - r.height); + if (b.height != r.height) { + m_composeTop->setRange(b.top, b.top + b.height - r.height); m_composeTop->setSliderPosition(r.top); } @@ -1945,9 +2028,10 @@ v4l2_frmsizeenum frmsize; bool ok = false; - m_frameSize->clear(); + if (m_frameSize) + m_frameSize->clear(); - ok = enum_framesizes(frmsize, m_pixelformat); + ok = !enum_framesizes(frmsize, m_pixelformat); if (ok && frmsize.type == V4L2_FRMSIZE_TYPE_DISCRETE) { do { m_frameSize->addItem(QString("%1x%2") @@ -1955,7 +2039,7 @@ if (frmsize.discrete.width == m_width && frmsize.discrete.height == m_height) m_frameSize->setCurrentIndex(frmsize.index); - } while (enum_framesizes(frmsize)); + } while (!enum_framesizes(frmsize)); m_discreteSizes = true; m_frameWidth->setEnabled(false); @@ -1984,7 +2068,8 @@ frmsize.stepwise.step_height = 1; } m_discreteSizes = false; - m_frameSize->setEnabled(false); + if (m_frameSize) + m_frameSize->setEnabled(false); m_frameWidth->setEnabled(!m_haveBuffers); m_frameWidth->blockSignals(true); m_frameWidth->setMinimum(frmsize.stepwise.min_width); @@ -2036,7 +2121,7 @@ v4l2_fract ratio = { 1, 1 }; unsigned w = 0, h = 0; - ratio = g_pixel_aspect(m_buftype, w, h); + ratio = g_pixel_aspect(w, h); switch (m_pixelAspectRatio->currentIndex()) { // override ratio if hardcoded, but keep w and h case 1: @@ -2052,12 +2137,12 @@ ratio.denominator = 40; break; case 4: - ratio.numerator = 11; - ratio.denominator = 12; + ratio.numerator = 54; + ratio.denominator = 59; break; case 5: - ratio.numerator = 11; - ratio.denominator = 16; + ratio.numerator = 81; + ratio.denominator = 118; break; default: break; @@ -2067,21 +2152,15 @@ .arg(ratio.numerator).arg(ratio.denominator)); m_pixelAspectRatio->setStatusTip(m_pixelAspectRatio->whatsThis()); - v4l2_format fmt; + cv4l_fmt fmt; unsigned cur_width, cur_height; unsigned cur_field; - g_fmt(m_buftype, fmt); + g_fmt(fmt); - if (isPlanar()) { - cur_width = fmt.fmt.pix_mp.width; - cur_height = fmt.fmt.pix_mp.height; - cur_field = fmt.fmt.pix_mp.field; - } else { - cur_width = fmt.fmt.pix.width; - cur_height = fmt.fmt.pix.height; - cur_field = fmt.fmt.pix.field; - } + cur_width = fmt.g_width(); + cur_height = fmt.g_height(); + cur_field = fmt.g_field(); if (w == 0) w = cur_width; if (cur_field == V4L2_FIELD_TOP || @@ -2107,18 +2186,21 @@ void GeneralTab::updateFrameInterval() { - v4l2_frmivalenum frmival; - v4l2_fract curr; + v4l2_frmivalenum frmival = { 0 }; + v4l2_fract curr = { 1, 1 }; bool curr_ok, ok; + if (m_frameInterval == NULL) + return; + m_frameInterval->clear(); - ok = enum_frameintervals(frmival, m_pixelformat, m_width, m_height); + ok = !enum_frameintervals(frmival, m_pixelformat, m_width, m_height); m_has_interval = ok && frmival.type == V4L2_FRMIVAL_TYPE_DISCRETE; m_frameInterval->setEnabled(m_has_interval); if (m_has_interval) { m_interval = frmival.discrete; - curr_ok = v4l2::get_interval(m_buftype, curr); + curr_ok = !m_fd->get_interval(curr); do { m_frameInterval->addItem(QString("%1 fps") .arg((double)frmival.discrete.denominator / frmival.discrete.numerator)); @@ -2128,7 +2210,7 @@ m_frameInterval->setCurrentIndex(frmival.index); m_interval = frmival.discrete; } - } while (enum_frameintervals(frmival)); + } while (!enum_frameintervals(frmival)); } } @@ -2167,11 +2249,12 @@ } #ifdef HAVE_ALSA -int GeneralTab::checkMatchAudioDevice(void *md, const char *vid, const enum device_type type) +int GeneralTab::checkMatchAudioDevice(void *md, const char *vid, enum device_type type) { const char *devname = NULL; + enum device_type dtype = isRadio() ? MEDIA_V4L_RADIO : MEDIA_V4L_VIDEO; - while ((devname = get_associated_device(md, devname, type, vid, MEDIA_V4L_VIDEO)) != NULL) { + while ((devname = get_associated_device(md, devname, type, vid, dtype)) != NULL) { if (type == MEDIA_SND_CAP) { QStringList devAddr = QString(devname).split(QRegExp("[:,]")); return devAddr.value(1).toInt(); @@ -2184,19 +2267,13 @@ { QStringList devPath = m_device.split("/"); QString curDev = devPath.value(devPath.count() - 1); - void *media; - const char *video = NULL; int match; media = discover_media_devices(); - while ((video = get_associated_device(media, video, MEDIA_V4L_VIDEO, NULL, NONE)) != NULL) - if (curDev.compare(video) == 0) - for (int i = 0; i <= MEDIA_SND_HW; i++) - if ((match = checkMatchAudioDevice(media, video, static_cast(i))) != -1) - return match; - + if ((match = checkMatchAudioDevice(media, curDev.toAscii(), MEDIA_SND_CAP)) != -1) + return match; return -1; } #endif diff -Nru v4l-utils-1.0.0+r2263/utils/qv4l2/general-tab.h v4l-utils-1.0.0+r2364/utils/qv4l2/general-tab.h --- v4l-utils-1.0.0+r2263/utils/qv4l2/general-tab.h 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/qv4l2/general-tab.h 2014-08-12 09:02:18.000000000 +0000 @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -31,7 +32,6 @@ #include #include "qv4l2.h" -#include "v4l2-api.h" #include "capture-win.h" #ifdef HAVE_ALSA @@ -45,15 +45,15 @@ class QComboBox; class QCheckBox; class QSpinBox; -class QPushButton; +class QToolButton; class QSlider; -class GeneralTab: public QGridLayout, public v4l2 +class GeneralTab: public QGridLayout { Q_OBJECT public: - GeneralTab(const QString &device, v4l2 &fd, int n, QWidget *parent = 0); + GeneralTab(const QString &device, cv4l_fd *fd, int n, QWidget *parent = 0); virtual ~GeneralTab() {} CapMethod capMethod(); @@ -72,24 +72,17 @@ bool isVbi() const { return m_isVbi; } bool isSlicedVbi() const; bool isPlanar() const { return m_isPlanar; } - __u32 bufType() const { return m_buftype; } - inline bool reqbufs_mmap(v4l2_requestbuffers &reqbuf, int count = 0) { - return v4l2::reqbufs_mmap(reqbuf, m_buftype, count); - } - inline bool reqbufs_user(v4l2_requestbuffers &reqbuf, int count = 0) { - return v4l2::reqbufs_user(reqbuf, m_buftype, count); + __u32 usePrio() const + { + return m_recordPrio->isChecked() ? + V4L2_PRIORITY_RECORD : V4L2_PRIORITY_DEFAULT; } - inline bool streamon() { return v4l2::streamon(m_buftype); } - inline bool streamoff() { return v4l2::streamoff(m_buftype); } void setHaveBuffers(bool haveBuffers); void sourceChange(const v4l2_event &ev); + void sourceChangeSubscribe(); unsigned getDisplayColorspace() const; unsigned getColorspace() const; int getWidth(); - int getHeight(); - -public slots: - void showAllAudioDevices(bool use); signals: void audioDeviceChanged(); @@ -130,13 +123,14 @@ void composeChanged(); private: - void inputSection(bool needsStd, bool needsTimings, v4l2_input vin); - void outputSection(v4l2_output vout, v4l2_fmtdesc fmt); + void inputSection(v4l2_input vin); + void outputSection(v4l2_output vout); void audioSection(v4l2_audio vaudio, v4l2_audioout vaudout); void formatSection(v4l2_fmtdesc fmt); void cropSection(); void fixWidth(); - void updateGUI(int); + void updateGUIInput(__u32); + void updateGUIOutput(__u32); void updateVideoInput(); void updateVideoOutput(); void updateAudioInput(); @@ -163,12 +157,11 @@ updateVidCapFormat(); } int addAudioDevice(void *hint, int deviceNum); - bool filterAudioInDevice(QString &deviceName); - bool filterAudioOutDevice(QString &deviceName); + bool filterAudioDevice(QString &deviceName); bool createAudioDeviceList(); #ifdef HAVE_ALSA int matchAudioDevice(); - int checkMatchAudioDevice(void *md, const char *vid, const enum device_type type); + int checkMatchAudioDevice(void *md, const char *vid, enum device_type type); #endif void addWidget(QWidget *w, Qt::Alignment align = Qt::AlignLeft); @@ -185,7 +178,105 @@ { g_mw->error(error); } + virtual void error(int error) + { + g_mw->error(error); + } + v4l_fd *g_v4l_fd() { return m_fd->g_v4l_fd(); } + + __u32 g_type() const { return m_fd->g_type(); } + void s_type(__u32 type) { m_fd->s_type(type); } + __u32 g_selection_type() const { return m_fd->g_selection_type(); } + __u32 g_caps() const { return m_fd->g_caps(); } + + bool has_vid_cap() const { return m_fd->has_vid_cap(); } + bool has_vid_out() const { return m_fd->has_vid_out(); } + bool has_vid_m2m() const { return m_fd->has_vid_m2m(); } + bool has_vid_mplane() const { return m_fd->has_vid_mplane(); } + bool has_overlay_cap() const { return m_fd->has_overlay_cap(); } + bool has_overlay_out() const { return m_fd->has_overlay_out(); } + bool has_raw_vbi_cap() const { return m_fd->has_raw_vbi_cap(); } + bool has_sliced_vbi_cap() const { return m_fd->has_sliced_vbi_cap(); } + bool has_vbi_cap() const { return m_fd->has_vbi_cap(); } + bool has_raw_vbi_out() const { return m_fd->has_raw_vbi_out(); } + bool has_sliced_vbi_out() const { return m_fd->has_sliced_vbi_out(); } + bool has_vbi_out() const { return m_fd->has_vbi_out(); } + bool has_vbi() const { return m_fd->has_vbi(); } + bool has_radio_rx() const { return m_fd->has_radio_rx(); } + bool has_radio_tx() const { return m_fd->has_radio_tx(); } + bool has_rds_cap() const { return m_fd->has_rds_cap(); } + bool has_rds_out() const { return m_fd->has_rds_out(); } + bool has_sdr_cap() const { return m_fd->has_sdr_cap(); } + bool has_hwseek() const { return m_fd->has_hwseek(); } + bool has_rw() const { return m_fd->has_rw(); } + bool has_streaming() const { return m_fd->has_streaming(); } + bool has_ext_pix_format() const { return m_fd->has_ext_pix_format(); } + + bool g_direct() const { return m_fd->g_direct(); } + void s_direct(bool direct) { m_fd->s_direct(direct); } + void querycap(v4l2_capability &cap) { return m_fd->querycap(cap); } + int queryctrl(v4l2_queryctrl &qc) { return m_fd->queryctrl(qc); } + int querymenu(v4l2_querymenu &qm) { return m_fd->querymenu(qm); } + int g_fmt(v4l2_format &fmt, unsigned type = 0) { return m_fd->g_fmt(fmt); } + int try_fmt(v4l2_format &fmt) { return m_fd->try_fmt(fmt); } + int s_fmt(v4l2_format &fmt) { return m_fd->s_fmt(fmt); } + int g_selection(v4l2_selection &sel) { return m_fd->g_selection(sel); } + int s_selection(v4l2_selection &sel) { return m_fd->s_selection(sel); } + int g_tuner(v4l2_tuner &tuner, unsigned index = 0) { return m_fd->g_tuner(tuner, index); } + int s_tuner(v4l2_tuner &tuner) { return m_fd->g_tuner(tuner); } + int g_modulator(v4l2_modulator &modulator) { return m_fd->g_modulator(modulator); } + int s_modulator(v4l2_modulator &modulator) { return m_fd->s_modulator(modulator); } + int enum_input(v4l2_input &in, bool init = false, int index = 0) { return m_fd->enum_input(in, init, index); } + int enum_output(v4l2_output &out, bool init = false, int index = 0) { return m_fd->enum_output(out, init, index); } + int enum_audio(v4l2_audio &audio, bool init = false, int index = 0) { return m_fd->enum_audio(audio, init, index); } + int enum_audout(v4l2_audioout &audout, bool init = false, int index = 0) { return m_fd->enum_audout(audout, init, index); } + int subscribe_event(v4l2_event_subscription &sub) { return m_fd->subscribe_event(sub); } + int dqevent(v4l2_event &ev) { return m_fd->dqevent(ev); } + int g_input(__u32 &input) { return m_fd->g_input(input); } + int s_input(__u32 input) { return m_fd->s_input(input); } + int g_output(__u32 &output) { return m_fd->g_output(output); } + int s_output(__u32 output) { return m_fd->s_output(output); } + int g_audio(v4l2_audio &audio) { return m_fd->g_audio(audio); } + int s_audio(__u32 input) { return m_fd->s_audio(input); } + int g_audout(v4l2_audioout &audout) { return m_fd->g_audout(audout); } + int s_audout(__u32 output) { return m_fd->s_audout(output); } + int g_std(v4l2_std_id &std) { return m_fd->g_std(std); } + int s_std(v4l2_std_id std) { return m_fd->s_std(std); } + int query_std(v4l2_std_id &std) { return m_fd->query_std(std); } + int g_dv_timings(v4l2_dv_timings &timings) { return m_fd->g_dv_timings(timings); } + int s_dv_timings(v4l2_dv_timings &timings) { return m_fd->s_dv_timings(timings); } + int query_dv_timings(v4l2_dv_timings &timings) { return m_fd->query_dv_timings(timings); } + int g_frequency(v4l2_frequency &freq, unsigned index = 0) { return m_fd->g_frequency(freq, index); } + int s_frequency(v4l2_frequency &freq) { return m_fd->s_frequency(freq); } + int g_priority(__u32 &prio) { return m_fd->g_priority(prio); } + int s_priority(__u32 prio = V4L2_PRIORITY_DEFAULT) { return m_fd->s_priority(prio); } + int streamon(__u32 type = 0) { return m_fd->streamon(type); } + int streamoff(__u32 type = 0) { return m_fd->streamoff(type); } + int querybuf(v4l_buffer &buf, unsigned index) { return m_fd->querybuf(buf, index); } + int dqbuf(v4l_buffer &buf) { return m_fd->dqbuf(buf); } + int qbuf(v4l_buffer &buf) { return m_fd->qbuf(buf); } + int prepare_buf(v4l_buffer &buf) { return m_fd->prepare_buf(buf); } + int enum_std(v4l2_standard &std, bool init = false, int index = 0) { return m_fd->enum_std(std, init, index); } + int enum_dv_timings(v4l2_enum_dv_timings &timings, bool init = false, int index = 0) { return m_fd->enum_dv_timings(timings, init, index); } + int enum_fmt(v4l2_fmtdesc &fmt, bool init = false, int index = 0, unsigned type = 0) { return m_fd->enum_fmt(fmt, init, index, type); } + int enum_framesizes(v4l2_frmsizeenum &frm, __u32 init_pixfmt = 0, int index = 0) { return m_fd->enum_framesizes(frm, init_pixfmt, index); } + int enum_frameintervals(v4l2_frmivalenum &frm, __u32 init_pixfmt = 0, __u32 w = 0, __u32 h = 0, int index = 0) { return m_fd->enum_frameintervals(frm, init_pixfmt, w, h, index); } + int set_interval(v4l2_fract interval, unsigned type = 0) { return m_fd->set_interval(interval, type); } + v4l2_fract g_pixel_aspect(unsigned &width, unsigned &height, unsigned type = 0) + { + return m_fd->g_pixel_aspect(width, height, type); + } + bool has_crop() { return m_fd->has_crop(); } + bool has_compose() { return m_fd->has_compose(); } + bool cur_io_has_crop() { return m_fd->cur_io_has_crop(); } + bool cur_io_has_compose() { return m_fd->cur_io_has_compose(); } + bool ioctl_exists(int ret) + { + return ret == 0 || errno != ENOTTY; + } + + cv4l_fd *m_fd; int m_row; int m_col; int m_cols; @@ -205,7 +296,6 @@ bool m_isPlanar; bool m_haveBuffers; bool m_discreteSizes; - __u32 m_buftype; __u32 m_audioModes[5]; QString m_device; struct v4l2_tuner m_tuner; @@ -231,13 +321,13 @@ QComboBox *m_audioInput; QComboBox *m_audioOutput; QComboBox *m_tvStandard; - QPushButton *m_qryStandard; + QToolButton *m_qryStandard; QComboBox *m_videoTimings; QComboBox *m_pixelAspectRatio; QComboBox *m_colorspace; QComboBox *m_displayColorspace; QComboBox *m_cropping; - QPushButton *m_qryTimings; + QToolButton *m_qryTimings; QDoubleSpinBox *m_freq; QComboBox *m_freqTable; QComboBox *m_freqChannel; @@ -246,7 +336,7 @@ QDoubleSpinBox *m_freqRf; QCheckBox *m_stereoMode; QCheckBox *m_rdsMode; - QPushButton *m_detectSubchans; + QToolButton *m_detectSubchans; QComboBox *m_vidCapFormats; QComboBox *m_vidFields; QComboBox *m_frameSize; @@ -255,6 +345,7 @@ QComboBox *m_frameInterval; QComboBox *m_vidOutFormats; QComboBox *m_capMethods; + QCheckBox *m_recordPrio; QComboBox *m_vbiMethods; QComboBox *m_audioInDevice; QComboBox *m_audioOutDevice; diff -Nru v4l-utils-1.0.0+r2263/utils/qv4l2/Makefile.am v4l-utils-1.0.0+r2364/utils/qv4l2/Makefile.am --- v4l-utils-1.0.0+r2263/utils/qv4l2/Makefile.am 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/qv4l2/Makefile.am 2014-08-12 09:02:18.000000000 +0000 @@ -1,27 +1,29 @@ bin_PROGRAMS = qv4l2 man_MANS = qv4l2.1 -qv4l2_SOURCES = qv4l2.cpp general-tab.cpp ctrl-tab.cpp vbi-tab.cpp v4l2-api.cpp capture-win.cpp \ +qv4l2_SOURCES = qv4l2.cpp general-tab.cpp ctrl-tab.cpp vbi-tab.cpp capture-win.cpp tpg-tab.cpp \ capture-win-qt.cpp capture-win-qt.h capture-win-gl.cpp capture-win-gl.h alsa_stream.c alsa_stream.h \ - raw2sliced.cpp qv4l2.h capture-win.h general-tab.h vbi-tab.h v4l2-api.h raw2sliced.h + raw2sliced.cpp qv4l2.h capture-win.h general-tab.h vbi-tab.h raw2sliced.h \ + ../v4l2-ctl/vivid-tpg.c ../v4l2-ctl/vivid-tpg.h ../v4l2-ctl/vivid-tpg-colors.c ../v4l2-ctl/vivid-tpg-colors.h nodist_qv4l2_SOURCES = moc_qv4l2.cpp moc_general-tab.cpp moc_capture-win.cpp moc_vbi-tab.cpp qrc_qv4l2.cpp qv4l2_LDADD = ../../lib/libv4l2/libv4l2.la ../../lib/libv4lconvert/libv4lconvert.la ../libv4l2util/libv4l2util.la \ ../libmedia_dev/libmedia_dev.la +qv4l2_CPPFLAGS = -I../v4l2-compliance -I../v4l2-ctl if WITH_QTGL -qv4l2_CPPFLAGS = $(QTGL_CFLAGS) +qv4l2_CPPFLAGS += $(QTGL_CFLAGS) qv4l2_LDFLAGS = $(QTGL_LIBS) else -qv4l2_CPPFLAGS = $(QT_CFLAGS) +qv4l2_CPPFLAGS += $(QT_CFLAGS) qv4l2_LDFLAGS = $(QT_LIBS) endif qv4l2_CPPFLAGS += $(ALSA_CFLAGS) qv4l2_LDFLAGS += $(ALSA_LIBS) -pthread -EXTRA_DIST = exit.png fileopen.png qv4l2_24x24.png qv4l2_64x64.png qv4l2.png qv4l2.svg snapshot.png \ - video-television.png fileclose.png qv4l2_16x16.png qv4l2_32x32.png qv4l2.desktop qv4l2.qrc record.png \ - saveraw.png qv4l2.pro qv4l2.1 +EXTRA_DIST = enterbutt.png exit.png fileopen.png qv4l2_24x24.png qv4l2_64x64.png qv4l2.png qv4l2.svg \ + snapshot.png video-television.png fileclose.png qv4l2_16x16.png qv4l2_32x32.png qv4l2.desktop \ + qv4l2.qrc record.png saveraw.png qv4l2.pro qv4l2.1 fullscreenexit.png fullscreen.png clean-local: -rm -vf moc_*.cpp qrc_*.cpp qrc_*.o ui_*.h @@ -49,4 +51,4 @@ $(INSTALL_DATA) -D -p "$(srcdir)/qv4l2_24x24.png" "$(DESTDIR)$(datadir)/icons/hicolor/24x24/apps/qv4l2.png" $(INSTALL_DATA) -D -p "$(srcdir)/qv4l2_32x32.png" "$(DESTDIR)$(datadir)/icons/hicolor/32x32/apps/qv4l2.png" $(INSTALL_DATA) -D -p "$(srcdir)/qv4l2_64x64.png" "$(DESTDIR)$(datadir)/icons/hicolor/64x64/apps/qv4l2.png" - $(INSTALL_DATA) -D -p "$(srcdir)/qv4l2.svg" "$(DESTDIR)$(datadir)/icons/hicolor/scalable/apps/qv4l2.svg" \ No newline at end of file + $(INSTALL_DATA) -D -p "$(srcdir)/qv4l2.svg" "$(DESTDIR)$(datadir)/icons/hicolor/scalable/apps/qv4l2.svg" diff -Nru v4l-utils-1.0.0+r2263/utils/qv4l2/qv4l2.cpp v4l-utils-1.0.0+r2364/utils/qv4l2/qv4l2.cpp --- v4l-utils-1.0.0+r2263/utils/qv4l2/qv4l2.cpp 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/qv4l2/qv4l2.cpp 2014-08-12 09:02:18.000000000 +0000 @@ -17,13 +17,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "qv4l2.h" -#include "general-tab.h" -#include "vbi-tab.h" -#include "capture-win.h" -#include "capture-win-qt.h" -#include "capture-win-gl.h" - #ifdef ENABLE_ASLA extern "C" { #include "alsa_stream.h" @@ -57,8 +50,20 @@ #include #include #include +#include #include -#include + +#include "qv4l2.h" +#include "general-tab.h" +#include "vbi-tab.h" +#include "capture-win.h" +#include "capture-win-qt.h" +#include "capture-win-gl.h" + +#include + +#define SDR_WIDTH 1024 +#define SDR_HEIGHT 512 ApplicationWindow::ApplicationWindow() : m_capture(NULL), @@ -66,19 +71,21 @@ m_minWidth(175), m_vMargin(15), m_hMargin(5), - m_maxh(0), m_genTab(NULL), m_sigMapper(NULL) { setAttribute(Qt::WA_DeleteOnClose, true); m_capNotifier = NULL; + m_outNotifier = NULL; m_ctrlNotifier = NULL; m_capImage = NULL; m_frameData = NULL; m_nbuffers = 0; - m_buffers = NULL; m_makeSnapshot = false; + m_tpgLimRGBRange = NULL; + for (unsigned b = 0; b < sizeof(m_clear); b++) + m_clear[b] = false; QAction *openAct = new QAction(QIcon(":/fileopen.png"), "&Open Device", this); openAct->setStatusTip("Open a v4l device, use libv4l2 wrapper if possible"); @@ -118,6 +125,11 @@ closeAct->setShortcut(Qt::CTRL+Qt::Key_W); connect(closeAct, SIGNAL(triggered()), this, SLOT(closeDevice())); + QAction *traceAct = new QAction("&Trace IOCTLs", this); + traceAct->setStatusTip("All V4L2 IOCTLs are traced on the console"); + traceAct->setCheckable(true); + connect(traceAct, SIGNAL(toggled(bool)), this, SLOT(traceIoctls(bool))); + QAction *quitAct = new QAction(QIcon(":/exit.png"), "&Quit", this); quitAct->setStatusTip("Exit the application"); quitAct->setShortcut(Qt::CTRL+Qt::Key_Q); @@ -130,6 +142,8 @@ fileMenu->addAction(m_snapshotAct); fileMenu->addAction(m_saveRawAct); fileMenu->addSeparator(); + fileMenu->addAction(traceAct); + fileMenu->addSeparator(); fileMenu->addAction(quitAct); QToolBar *toolBar = addToolBar("File"); @@ -144,6 +158,7 @@ m_scalingAct->setCheckable(true); m_scalingAct->setChecked(true); connect(m_scalingAct, SIGNAL(toggled(bool)), this, SLOT(enableScaling(bool))); + m_resetScalingAct = new QAction("Resize to &Frame Size", this); m_resetScalingAct->setStatusTip("Resizes the capture window to match frame size"); m_resetScalingAct->setShortcut(Qt::CTRL+Qt::Key_F); @@ -152,7 +167,6 @@ captureMenu->addAction(m_capStartAct); captureMenu->addAction(m_showFramesAct); captureMenu->addAction(m_scalingAct); - captureMenu->addAction(m_resetScalingAct); if (CaptureWinGL::isSupported()) { m_renderMethod = QV4L2_RENDER_GL; @@ -161,28 +175,38 @@ m_useGLAct->setStatusTip("Use GPU with OpenGL for video capture if set."); m_useGLAct->setCheckable(true); m_useGLAct->setChecked(true); - connect(m_useGLAct, SIGNAL(triggered()), this, SLOT(setRenderMethod())); + connect(m_useGLAct, SIGNAL(toggled(bool)), this, SLOT(setRenderMethod(bool))); captureMenu->addAction(m_useGLAct); m_useBlendingAct = new QAction("Enable &Blending", this); m_useBlendingAct->setStatusTip("Enable blending to test the alpha component in the image"); m_useBlendingAct->setCheckable(true); m_useBlendingAct->setChecked(false); - connect(m_useBlendingAct, SIGNAL(triggered()), this, SLOT(setBlending())); + connect(m_useBlendingAct, SIGNAL(toggled(bool)), this, SLOT(setBlending(bool))); captureMenu->addAction(m_useBlendingAct); + + m_useLinearAct = new QAction("Enable &Linear filter", this); + m_useLinearAct->setStatusTip("Enable linear scaling filter"); + m_useLinearAct->setCheckable(true); + m_useLinearAct->setChecked(false); + connect(m_useLinearAct, SIGNAL(toggled(bool)), this, SLOT(setLinearFilter(bool))); + captureMenu->addAction(m_useLinearAct); + } else { m_renderMethod = QV4L2_RENDER_QT; } + captureMenu->addAction(m_resetScalingAct); + + m_makeFullScreenAct = new QAction(QIcon(":/fullscreen.png"), "Show Fullscreen", this); + m_makeFullScreenAct->setStatusTip("Capture in fullscreen mode"); + m_makeFullScreenAct->setCheckable(true); + connect(m_makeFullScreenAct, SIGNAL(toggled(bool)), this, SLOT(makeFullScreen(bool))); + captureMenu->addAction(m_makeFullScreenAct); + toolBar->addAction(m_makeFullScreenAct); #ifdef HAVE_ALSA captureMenu->addSeparator(); - m_showAllAudioAct = new QAction("Show All Audio &Devices", this); - m_showAllAudioAct->setStatusTip("Show all audio input and output devices if set"); - m_showAllAudioAct->setCheckable(true); - m_showAllAudioAct->setChecked(false); - captureMenu->addAction(m_showAllAudioAct); - m_audioBufferAct = new QAction("Set Audio &Buffer Capacity...", this); m_audioBufferAct->setStatusTip("Set audio buffer capacity in amount of ms than can be stored"); connect(m_audioBufferAct, SIGNAL(triggered()), this, SLOT(setAudioBufferSize())); @@ -208,16 +232,16 @@ closeDevice(); } - void ApplicationWindow::setDevice(const QString &device, bool rawOpen) { closeDevice(); m_sigMapper = new QSignalMapper(this); connect(m_sigMapper, SIGNAL(mapped(int)), this, SLOT(ctrlAction(int))); - if (!open(device, !rawOpen)) { + s_direct(rawOpen); + + if (open(device.toLatin1(), true) < 0) { #ifdef HAVE_ALSA - m_showAllAudioAct->setEnabled(false); m_audioBufferAct->setEnabled(false); #endif return; @@ -226,20 +250,14 @@ newCaptureWin(); QWidget *w = new QWidget(m_tabs); - m_genTab = new GeneralTab(device, *this, 4, w); - int size[2]; - size[0] = m_genTab->getWidth(); - size[1] = m_genTab->getHeight(); - setMinimumSize(size[0], size[1]); + m_genTab = new GeneralTab(device, this, 4, w); + int m_winWidth = m_genTab->getWidth(); #ifdef HAVE_ALSA if (m_genTab->hasAlsaAudio()) { - connect(m_showAllAudioAct, SIGNAL(toggled(bool)), m_genTab, SLOT(showAllAudioDevices(bool))); connect(m_genTab, SIGNAL(audioDeviceChanged()), this, SLOT(changeAudioDevice())); - m_showAllAudioAct->setEnabled(true); m_audioBufferAct->setEnabled(true); } else { - m_showAllAudioAct->setEnabled(false); m_audioBufferAct->setEnabled(false); } #endif @@ -249,8 +267,16 @@ connect(m_genTab, SIGNAL(displayColorspaceChanged()), this, SLOT(updateDisplayColorspace())); connect(m_genTab, SIGNAL(clearBuffers()), this, SLOT(clearBuffers())); m_tabs->addTab(w, "General Settings"); - addTabs(size); - if (caps() & (V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE)) { + + if (has_vid_out()) { + addTpgTab(m_minWidth); + tpg_init(&m_tpg, 640, 360); + updateLimRGBRange(); + } + + addTabs(m_winWidth); + m_vbiTab = NULL; + if (has_vbi_cap()) { w = new QWidget(m_tabs); m_vbiTab = new VbiTab(w); m_tabs->addTab(w, "VBI"); @@ -261,13 +287,18 @@ statusBar()->clearMessage(); m_tabs->show(); m_tabs->setFocus(); - m_convertData = v4lconvert_create(fd()); - m_capStartAct->setEnabled(fd() >= 0); - m_saveRawAct->setEnabled(fd() >= 0); + m_convertData = v4lconvert_create(g_fd()); + bool canStream = g_fd() >= 0 && (v4l_type_is_capture(g_type()) || has_vid_out()) && + !has_radio_tx(); + m_capStartAct->setEnabled(canStream); + m_saveRawAct->setEnabled(canStream); + m_snapshotAct->setEnabled(canStream && has_vid_cap()); #ifdef HAVE_QTGL m_useGLAct->setEnabled(CaptureWinGL::isSupported()); #endif - m_ctrlNotifier = new QSocketNotifier(fd(), QSocketNotifier::Exception, m_tabs); + m_genTab->sourceChangeSubscribe(); + subscribeCtrlEvents(); + m_ctrlNotifier = new QSocketNotifier(g_fd(), QSocketNotifier::Exception, m_tabs); connect(m_ctrlNotifier, SIGNAL(activated(int)), this, SLOT(ctrlEvent())); } @@ -291,27 +322,29 @@ setDevice(d.selectedFiles().first(), true); } -void ApplicationWindow::setRenderMethod() +void ApplicationWindow::setRenderMethod(bool checked) { if (m_capStartAct->isChecked()) { m_useGLAct->setChecked(m_renderMethod == QV4L2_RENDER_GL); return; } - if (m_useGLAct->isChecked()) { - m_renderMethod = QV4L2_RENDER_GL; - } else { - m_renderMethod = QV4L2_RENDER_QT; - } + m_renderMethod = checked ? QV4L2_RENDER_GL : QV4L2_RENDER_QT; m_useBlendingAct->setEnabled(m_renderMethod == QV4L2_RENDER_GL); newCaptureWin(); } -void ApplicationWindow::setBlending() +void ApplicationWindow::setBlending(bool checked) +{ + if (m_capture) + m_capture->setBlending(checked); +} + +void ApplicationWindow::setLinearFilter(bool checked) { if (m_capture) - m_capture->setBlending(m_useBlendingAct->isChecked()); + m_capture->setLinearFilter(checked); } void ApplicationWindow::setAudioBufferSize() @@ -331,7 +364,7 @@ { v4l2_event ev; - while (dqevent(ev)) { + while (dqevent(ev) == 0) { if (ev.type == V4L2_EVENT_SOURCE_CHANGE) { m_genTab->sourceChange(ev); continue; @@ -343,11 +376,17 @@ m_ctrlMap[ev.id].maximum = ev.u.ctrl.maximum; m_ctrlMap[ev.id].step = ev.u.ctrl.step; m_ctrlMap[ev.id].default_value = ev.u.ctrl.default_value; - m_widgetMap[ev.id]->setDisabled(m_ctrlMap[ev.id].flags & CTRL_FLAG_DISABLED); + + bool disabled = m_ctrlMap[ev.id].flags & CTRL_FLAG_DISABLED; + + if (qobject_cast(m_widgetMap[ev.id])) + static_cast(m_widgetMap[ev.id])->setReadOnly(disabled); + else + m_widgetMap[ev.id]->setDisabled(disabled); if (m_sliderMap.find(ev.id) != m_sliderMap.end()) - m_sliderMap[ev.id]->setDisabled(m_ctrlMap[ev.id].flags & CTRL_FLAG_DISABLED); + m_sliderMap[ev.id]->setDisabled(disabled); if (ev.u.ctrl.changes & V4L2_EVENT_CTRL_CH_RANGE) - updateCtrlRange(ev.id); + updateCtrlRange(ev.id, ev.u.ctrl.value); switch (m_ctrlMap[ev.id].type) { case V4L2_CTRL_TYPE_INTEGER: case V4L2_CTRL_TYPE_INTEGER_MENU: @@ -364,7 +403,7 @@ } if (m_ctrlMap[ev.id].type != V4L2_CTRL_TYPE_STRING) continue; - queryctrl(m_ctrlMap[ev.id]); + query_ext_ctrl(m_ctrlMap[ev.id]); struct v4l2_ext_control c; struct v4l2_ext_controls ctrls; @@ -376,7 +415,7 @@ ctrls.count = 1; ctrls.ctrl_class = 0; ctrls.controls = &c; - if (!ioctl(VIDIOC_G_EXT_CTRLS, &ctrls)) + if (!g_ext_ctrls(ctrls)) setString(ev.id, c.string); free(c.string); } @@ -391,26 +430,109 @@ switch (m_renderMethod) { case QV4L2_RENDER_GL: - m_capture = new CaptureWinGL; + m_capture = new CaptureWinGL(this); break; default: - m_capture = new CaptureWinQt; + m_capture = new CaptureWinQt(this); break; } m_capture->setPixelAspectRatio(1.0); m_capture->enableScaling(m_scalingAct->isChecked()); connect(m_capture, SIGNAL(close()), this, SLOT(closeCaptureWin())); - connect(m_resetScalingAct, SIGNAL(triggered()), m_capture, SLOT(resetSize())); +} + +bool ApplicationWindow::startStreaming() +{ + startAudio(); + + if (!m_genTab->isSDR() && m_genTab->isRadio()) { + s_priority(m_genTab->usePrio()); + return true; + } + + m_queue.init(g_type(), m_capMethod); + +#ifdef HAVE_QTGL + m_useGLAct->setEnabled(false); +#endif + + switch (m_capMethod) { + case methodRead: + m_snapshotAct->setEnabled(true); + m_genTab->setHaveBuffers(true); + s_priority(m_genTab->usePrio()); + /* Nothing to do. */ + return true; + + case methodMmap: + case methodUser: + if (m_queue.reqbufs(this, 4)) { + error("Cannot capture"); + break; + } + + if (m_queue.g_buffers() < 2) { + error("Too few buffers"); + break; + } + + if (m_queue.obtain_bufs(this)) { + error("Get buffers"); + break; + } + + if (v4l_type_is_capture(g_type())) { + for (unsigned i = 0; i < m_queue.g_buffers(); i++) { + cv4l_buffer buf; + + m_queue.buffer_init(buf, i); + qbuf(buf); + } + } else { + for (unsigned i = 0; i < m_queue.g_buffers(); i++) { + cv4l_buffer buf; + + m_queue.buffer_init(buf, i); + buf.s_field(m_tpgField); + tpg_s_field(&m_tpg, m_tpgField); + if (m_tpgField == V4L2_FIELD_TOP) + m_tpgField = V4L2_FIELD_BOTTOM; + else if (m_tpgField == V4L2_FIELD_BOTTOM) + m_tpgField = V4L2_FIELD_TOP; + for (unsigned p = 0; p < m_queue.g_num_planes(); p++) + tpg_fillbuffer(&m_tpg, m_tpgStd, p, (u8 *)m_queue.g_dataptr(i, p)); + qbuf(buf); + tpg_update_mv_count(&m_tpg, V4L2_FIELD_HAS_T_OR_B(m_tpgField)); + } + } + + if (streamon()) { + perror("VIDIOC_STREAMON"); + break; + } + m_snapshotAct->setEnabled(true); + m_genTab->setHaveBuffers(true); + s_priority(m_genTab->usePrio()); + return true; + } + + m_queue.free(this); + reopen(true); + m_genTab->sourceChangeSubscribe(); + subscribeCtrlEvents(); + m_capStartAct->setChecked(false); +#ifdef HAVE_QTGL + m_useGLAct->setEnabled(CaptureWinGL::isSupported()); +#endif + return false; } void ApplicationWindow::capVbiFrame() { - __u32 buftype = m_genTab->bufType(); - v4l2_buffer buf; + cv4l_buffer buf(m_queue); __u8 *data = NULL; int s = 0; - bool again; switch (m_capMethod) { case methodRead: @@ -426,43 +548,28 @@ break; case methodMmap: - if (!dqbuf_mmap(buf, buftype, again)) { - error("dqbuf"); - m_capStartAct->setChecked(false); - return; - } - if (again) - return; - if (buf.flags & V4L2_BUF_FLAG_ERROR) { - qbuf(buf); - return; - } - data = (__u8 *)m_buffers[buf.index].start[0]; - s = buf.bytesused; - break; - case methodUser: - if (!dqbuf_user(buf, buftype, again)) { + if (dqbuf(buf)) { + if (errno == EAGAIN) + return; error("dqbuf"); m_capStartAct->setChecked(false); return; } - if (again) - return; - if (buf.flags & V4L2_BUF_FLAG_ERROR) { + if (buf.g_flags() & V4L2_BUF_FLAG_ERROR) { qbuf(buf); return; } - data = (__u8 *)buf.m.userptr; - s = buf.bytesused; + data = (__u8 *)m_queue.g_dataptr(buf.g_index(), 0); + s = buf.g_bytesused(); break; } - if (buftype == V4L2_BUF_TYPE_VBI_CAPTURE && s != m_vbiSize) { + if (g_type() == V4L2_BUF_TYPE_VBI_CAPTURE && s != m_vbiSize) { error("incorrect vbi size"); m_capStartAct->setChecked(false); return; } - if (showFrames() && buftype == V4L2_BUF_TYPE_VBI_CAPTURE) { + if (showFrames() && g_type() == V4L2_BUF_TYPE_VBI_CAPTURE) { for (unsigned y = 0; y < m_vbiHeight; y++) { __u8 *p = data + y * m_vbiWidth; __u8 *q = m_capImage->bits() + y * m_capImage->bytesPerLine(); @@ -479,7 +586,7 @@ struct v4l2_sliced_vbi_data sdata[m_vbiHandle.count[0] + m_vbiHandle.count[1]]; struct v4l2_sliced_vbi_data *p; - if (buftype == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) { + if (g_type() == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) { p = (struct v4l2_sliced_vbi_data *)data; } else { vbi_parse(&m_vbiHandle, data, &sfmt, sdata); @@ -506,9 +613,9 @@ m_tv = tv; } status = QString("Frame: %1 Fps: %2").arg(++m_frame).arg(m_fps); - if (showFrames() && buftype == V4L2_BUF_TYPE_VBI_CAPTURE) + if (showFrames() && g_type() == V4L2_BUF_TYPE_VBI_CAPTURE) m_capture->setFrame(m_capImage->width(), m_capImage->height(), - m_capDestFormat.fmt.pix.pixelformat, m_capImage->bits(), NULL, status); + m_capDestFormat.fmt.pix.pixelformat, m_capImage->bits(), NULL); curStatus = statusBar()->currentMessage(); if (curStatus.isEmpty() || curStatus.startsWith("Frame: ")) @@ -517,28 +624,15 @@ refresh(); } -void ApplicationWindow::capFrame() +void ApplicationWindow::capSdrFrame() { - __u32 buftype = m_genTab->bufType(); - v4l2_plane planes[VIDEO_MAX_PLANES]; - v4l2_buffer buf; + cv4l_buffer buf(m_queue); + __u8 *data = NULL; int s = 0; - int err = 0; - bool again; -#ifdef HAVE_ALSA - struct timeval tv_alsa; -#endif - - unsigned char *displaybuf = NULL; - unsigned char *displaybuf2 = NULL; switch (m_capMethod) { case methodRead: - s = read(m_frameData, m_capSrcFormat.fmt.pix.sizeimage); -#ifdef HAVE_ALSA - alsa_thread_timestamp(&tv_alsa); -#endif - + s = read(m_frameData, m_sdrSize); if (s < 0) { if (errno != EAGAIN) { error("read"); @@ -546,110 +640,246 @@ } return; } - if (m_makeSnapshot) - makeSnapshot((unsigned char *)m_frameData, s); - if (m_saveRaw.openMode()) - m_saveRaw.write((const char *)m_frameData, s); - - if (!showFrames()) - break; - if (m_mustConvert) - err = v4lconvert_convert(m_convertData, &m_capSrcFormat, &m_capDestFormat, - m_frameData, s, - m_capImage->bits(), m_capDestFormat.fmt.pix.sizeimage); - if (m_mustConvert && err != -1) - displaybuf = m_capImage->bits(); - if (!m_mustConvert) - displaybuf = m_frameData; + data = m_frameData; break; case methodMmap: - memset(planes, 0, sizeof(planes)); - buf.length = VIDEO_MAX_PLANES; - buf.m.planes = planes; - if (!dqbuf_mmap(buf, buftype, again)) { + case methodUser: + if (dqbuf(buf)) { + if (errno == EAGAIN) + return; error("dqbuf"); m_capStartAct->setChecked(false); return; } + if (buf.g_flags() & V4L2_BUF_FLAG_ERROR) { + qbuf(buf); + return; + } + data = (__u8 *)m_queue.g_dataptr(buf.g_index(), 0); + s = buf.g_bytesused(); + break; + } + if (s != m_sdrSize) { + error("incorrect sdr size"); + m_capStartAct->setChecked(false); + return; + } + if (showFrames()) { + unsigned width = m_sdrSize / 2 - 1; + + if (SDR_WIDTH < width) + width = SDR_WIDTH; + + m_capImage->fill(0); + /* + * Draw two waveforms, each consisting of the first 'width + 1' samples + * of the buffer, the top is for the I, the bottom is for the Q values. + */ + for (unsigned i = 0; i < 2; i++) { + unsigned start = 255 - data[i]; + + for (unsigned x = 0; x < width; x++) { + unsigned next = 255 - data[2 + 2 * x + i]; + unsigned low = start < next ? start : next; + unsigned high = start > next ? start : next; + __u8 *q = m_capImage->bits() + x * 3 + + (i * 256 + low) * m_capImage->bytesPerLine(); + + while (low++ <= high) { + q[0] = 255; + q[1] = 255; + q[2] = 255; + q += m_capImage->bytesPerLine(); + } + start = next; + } + } + } + + if (m_capMethod != methodRead) + qbuf(buf); + + QString status, curStatus; + struct timeval tv, res; + + if (m_frame == 0) + gettimeofday(&m_tv, NULL); + gettimeofday(&tv, NULL); + timersub(&tv, &m_tv, &res); + if (res.tv_sec) { + m_fps = (100 * (m_frame - m_lastFrame)) / + (res.tv_sec * 100 + res.tv_usec / 10000); + m_lastFrame = m_frame; + m_tv = tv; + } + status = QString("Frame: %1 Fps: %2").arg(++m_frame).arg(m_fps); + if (showFrames()) + m_capture->setFrame(m_capImage->width(), m_capImage->height(), + m_capDestFormat.fmt.pix.pixelformat, m_capImage->bits(), NULL); + + curStatus = statusBar()->currentMessage(); + if (curStatus.isEmpty() || curStatus.startsWith("Frame: ")) + statusBar()->showMessage(status); + if (m_frame == 1) + refresh(); +} + +void ApplicationWindow::outFrame() +{ + cv4l_buffer buf(m_queue); + int s = 0; + + switch (m_capMethod) { + case methodRead: + tpg_fillbuffer(&m_tpg, m_tpgStd, 0, (u8 *)m_frameData); + s = write(m_frameData, m_tpgSizeImage); + tpg_update_mv_count(&m_tpg, V4L2_FIELD_HAS_T_OR_B(m_tpgField)); - if (again) + if (s < 0) { + if (errno != EAGAIN) { + error("write"); + m_capStartAct->setChecked(false); + } return; - if (buf.flags & V4L2_BUF_FLAG_ERROR) { - qbuf(buf); + } + break; + + case methodMmap: + case methodUser: + if (dqbuf(buf)) { + if (errno == EAGAIN) + return; + error("dqbuf"); + m_capStartAct->setChecked(false); return; } + m_queue.buffer_init(buf, buf.g_index()); + buf.s_field(m_tpgField); + tpg_s_field(&m_tpg, m_tpgField); + if (m_tpgField == V4L2_FIELD_TOP) + m_tpgField = V4L2_FIELD_BOTTOM; + else if (m_tpgField == V4L2_FIELD_BOTTOM) + m_tpgField = V4L2_FIELD_TOP; + for (unsigned p = 0; p < m_queue.g_num_planes(); p++) + tpg_fillbuffer(&m_tpg, m_tpgStd, p, (u8 *)m_queue.g_dataptr(buf.g_index(), p)); + tpg_update_mv_count(&m_tpg, V4L2_FIELD_HAS_T_OR_B(m_tpgField)); + break; + } + QString status, curStatus; + struct timeval tv, res; + + if (m_frame == 0) + gettimeofday(&m_tv, NULL); + gettimeofday(&tv, NULL); + timersub(&tv, &m_tv, &res); + if (res.tv_sec) { + m_fps = (100 * (m_frame - m_lastFrame)) / + (res.tv_sec * 100 + res.tv_usec / 10000); + m_lastFrame = m_frame; + m_tv = tv; + } + + status = QString("Frame: %1 Fps: %2").arg(++m_frame).arg(m_fps); + + if (m_capMethod == methodMmap || m_capMethod == methodUser) { + if (m_clear[buf.g_index()]) { + for (unsigned p = 0; p < m_queue.g_num_planes(); p++) + memset(m_queue.g_dataptr(buf.g_index(), p), 0, buf.g_length(p)); + m_clear[buf.g_index()] = false; + } + + qbuf(buf); + } + + curStatus = statusBar()->currentMessage(); + if (curStatus.isEmpty() || curStatus.startsWith("Frame: ")) + statusBar()->showMessage(status); + if (m_frame == 1) + refresh(); +} + +void ApplicationWindow::capFrame() +{ + cv4l_buffer buf(m_queue); + unsigned char *plane[2]; + unsigned bytesused[2]; + int s = 0; + int err = 0; +#ifdef HAVE_ALSA + struct timeval tv_alsa; +#endif + + plane[0] = plane[1] = NULL; + switch (m_capMethod) { + case methodRead: + s = read(m_frameData, m_capSrcFormat.g_sizeimage(0)); #ifdef HAVE_ALSA alsa_thread_timestamp(&tv_alsa); #endif - if (showFrames()) { - if (m_mustConvert) - err = v4lconvert_convert(m_convertData, &m_capSrcFormat, &m_capDestFormat, - (unsigned char *)m_buffers[buf.index].start[0], buf.bytesused, - m_capImage->bits(), m_capDestFormat.fmt.pix.sizeimage); - if (m_mustConvert && err != -1) - displaybuf = m_capImage->bits(); - if (!m_mustConvert) { - displaybuf = (unsigned char *)m_buffers[buf.index].start[0]; - displaybuf2 = (unsigned char *)m_buffers[buf.index].start[1]; - if (V4L2_TYPE_IS_MULTIPLANAR(buf.type)) { - displaybuf += planes[0].data_offset; - displaybuf2 += planes[1].data_offset; - } + if (s < 0) { + if (errno != EAGAIN) { + error("read"); + m_capStartAct->setChecked(false); } + return; } if (m_makeSnapshot) - makeSnapshot((unsigned char *)m_buffers[buf.index].start[0], buf.bytesused); + makeSnapshot((unsigned char *)m_frameData, s); if (m_saveRaw.openMode()) - m_saveRaw.write((const char *)m_buffers[buf.index].start[0], buf.bytesused); + m_saveRaw.write((const char *)m_frameData, s); + plane[0] = m_frameData; + if (showFrames() && m_mustConvert) { + err = v4lconvert_convert(m_convertData, &m_capSrcFormat, &m_capDestFormat, + m_frameData, s, + m_capImage->bits(), m_capDestFormat.fmt.pix.sizeimage); + if (err != -1) + plane[0] = m_capImage->bits(); + } break; + case methodMmap: case methodUser: - memset(planes, 0, sizeof(planes)); - buf.length = VIDEO_MAX_PLANES; - buf.m.planes = planes; - if (!dqbuf_user(buf, buftype, again)) { - error("dqbuf1"); + if (dqbuf(buf)) { + if (errno == EAGAIN) + return; + error("dqbuf"); m_capStartAct->setChecked(false); return; } - if (again) - return; - if (buf.flags & V4L2_BUF_FLAG_ERROR) { + if (buf.g_flags() & V4L2_BUF_FLAG_ERROR) { qbuf(buf); return; } + #ifdef HAVE_ALSA alsa_thread_timestamp(&tv_alsa); #endif - if (buf.flags & V4L2_BUF_FLAG_ERROR) { - qbuf(buf); - return; - } - if (showFrames()) { - if (m_mustConvert) - err = v4lconvert_convert(m_convertData, &m_capSrcFormat, &m_capDestFormat, - (unsigned char *)buf.m.userptr, buf.bytesused, - m_capImage->bits(), m_capDestFormat.fmt.pix.sizeimage); - if (m_mustConvert && err != -1) - displaybuf = m_capImage->bits(); - if (!m_mustConvert) { - displaybuf = (unsigned char *)m_buffers[buf.index].start[0]; - displaybuf2 = (unsigned char *)m_buffers[buf.index].start[1]; - if (V4L2_TYPE_IS_MULTIPLANAR(buf.type)) { - displaybuf += planes[0].data_offset; - displaybuf2 += planes[1].data_offset; - } + plane[0] = (__u8 *)m_queue.g_dataptr(buf.g_index(), 0); + plane[1] = (__u8 *)m_queue.g_dataptr(buf.g_index(), 1); + plane[0] += buf.g_data_offset(0); + bytesused[0] = buf.g_bytesused(0) - buf.g_data_offset(0); + if (plane[1]) { + plane[1] += buf.g_data_offset(1); + bytesused[1] = buf.g_bytesused(1) - buf.g_data_offset(1); + } + if (showFrames() && m_mustConvert) { + err = v4lconvert_convert(m_convertData, &m_capSrcFormat, &m_capDestFormat, + plane[0], bytesused[0], m_capImage->bits(), + m_capDestFormat.fmt.pix.sizeimage); + if (err != -1) { + plane[0] = m_capImage->bits(); + bytesused[0] = m_capDestFormat.fmt.pix.sizeimage; } } if (m_makeSnapshot) - makeSnapshot((unsigned char *)buf.m.userptr, buf.bytesused); + makeSnapshot(plane[0], bytesused[0]); if (m_saveRaw.openMode()) - m_saveRaw.write((const char *)buf.m.userptr, buf.bytesused); + m_saveRaw.write((const char *)plane[0], bytesused[0]); break; } @@ -670,31 +900,32 @@ m_tv = tv; } - - status = QString("Frame: %1 Fps: %2").arg(++m_frame).arg(m_fps); + float wscale = m_capture->getHorScaleFactor(); + float hscale = m_capture->getVertScaleFactor(); + status = QString("Frame: %1 Fps: %2 Scale Factors: %3x%4").arg(++m_frame).arg(m_fps).arg(wscale).arg(hscale); #ifdef HAVE_ALSA if (alsa_thread_is_running()) { if (tv_alsa.tv_sec || tv_alsa.tv_usec) { - m_totalAudioLatency.tv_sec += buf.timestamp.tv_sec - tv_alsa.tv_sec; - m_totalAudioLatency.tv_usec += buf.timestamp.tv_usec - tv_alsa.tv_usec; + m_totalAudioLatency.tv_sec += buf.g_timestamp().tv_sec - tv_alsa.tv_sec; + m_totalAudioLatency.tv_usec += buf.g_timestamp().tv_usec - tv_alsa.tv_usec; } status.append(QString(" Average A-V: %3 ms") .arg((m_totalAudioLatency.tv_sec * 1000 + m_totalAudioLatency.tv_usec / 1000) / m_frame)); } #endif - if (displaybuf == NULL && showFrames()) + if (plane[0] == NULL && showFrames()) status.append(" Error: Unsupported format."); if (showFrames()) m_capture->setFrame(m_capImage->width(), m_capImage->height(), - m_capDestFormat.fmt.pix.pixelformat, displaybuf, displaybuf2, status); + m_capDestFormat.g_pixelformat(), plane[0], plane[1]); if (m_capMethod == methodMmap || m_capMethod == methodUser) { - if (m_buffers[buf.index].clear) { - memset(m_buffers[buf.index].start[0], 0, m_buffers[buf.index].length[0]); - if (V4L2_TYPE_IS_MULTIPLANAR(buf.type)) - memset(m_buffers[buf.index].start[1], 0, m_buffers[buf.index].length[1]); - m_buffers[buf.index].clear = false; + if (m_clear[buf.g_index()]) { + memset(m_queue.g_dataptr(buf.g_index(), 0), 0, buf.g_length()); + if (V4L2_TYPE_IS_MULTIPLANAR(buf.g_type())) + memset(m_queue.g_dataptr(buf.g_index(), 1), 0, buf.g_length(1)); + m_clear[buf.g_index()] = false; } qbuf(buf); @@ -707,229 +938,41 @@ refresh(); } -bool ApplicationWindow::startCapture(unsigned buffer_size) +void ApplicationWindow::stopStreaming() { - startAudio(); - - if (m_genTab->isRadio()) - return true; - - __u32 buftype = m_genTab->bufType(); - v4l2_requestbuffers req; - unsigned int i; - - memset(&req, 0, sizeof(req)); - - m_useGLAct->setEnabled(false); - - switch (m_capMethod) { - case methodRead: - m_snapshotAct->setEnabled(true); - m_genTab->setHaveBuffers(true); - /* Nothing to do. */ - return true; - - case methodMmap: - if (!reqbufs_mmap(req, buftype, 3)) { - error("Cannot capture"); - break; - } - - if (req.count < 2) { - error("Too few buffers"); - reqbufs_mmap(req, buftype); - break; - } - - m_buffers = (buffer *)calloc(req.count, sizeof(*m_buffers)); - - if (!m_buffers) { - error("Out of memory"); - reqbufs_mmap(req, buftype); - break; - } - - for (m_nbuffers = 0; m_nbuffers < req.count; ++m_nbuffers) { - v4l2_plane planes[VIDEO_MAX_PLANES]; - v4l2_buffer buf; - - memset(&buf, 0, sizeof(buf)); - - buf.type = buftype; - buf.memory = V4L2_MEMORY_MMAP; - buf.index = m_nbuffers; - buf.length = VIDEO_MAX_PLANES; - buf.m.planes = planes; - - if (-1 == ioctl(VIDIOC_QUERYBUF, &buf)) { - perror("VIDIOC_QUERYBUF"); - goto error; - } - - if (V4L2_TYPE_IS_MULTIPLANAR(buftype)) { - m_buffers[m_nbuffers].planes = buf.length; - for (unsigned p = 0; p < buf.length; p++) { - m_buffers[m_nbuffers].length[p] = planes[p].length; - m_buffers[m_nbuffers].start[p] = mmap(planes[p].length, planes[p].m.mem_offset); - if (MAP_FAILED == m_buffers[m_nbuffers].start[p]) { - perror("mmap"); - goto error; - } - memset(m_buffers[m_nbuffers].start[p], 0, - m_buffers[m_nbuffers].length[p]); - } - } else { - m_buffers[m_nbuffers].planes = 1; - m_buffers[m_nbuffers].length[0] = buf.length; - m_buffers[m_nbuffers].start[0] = mmap(buf.length, buf.m.offset); - if (MAP_FAILED == m_buffers[m_nbuffers].start[0]) { - perror("mmap"); - goto error; - } - memset(m_buffers[m_nbuffers].start[0], 0, - m_buffers[m_nbuffers].length[0]); - } - } - for (i = 0; i < m_nbuffers; ++i) { - if (!qbuf_mmap(i, buftype)) { - perror("VIDIOC_QBUF"); - goto error; - } - } - if (!streamon(buftype)) { - perror("VIDIOC_STREAMON"); - goto error; - } - m_snapshotAct->setEnabled(true); - m_genTab->setHaveBuffers(true); - return true; - - case methodUser: - if (!reqbufs_user(req, buftype, 3)) { - error("Cannot capture"); - break; - } - - if (req.count < 2) { - error("Too few buffers"); - reqbufs_user(req, buftype); - break; - } - - m_buffers = (buffer *)calloc(req.count, sizeof(*m_buffers)); - - if (!m_buffers) { - error("Out of memory"); - break; - } - - for (m_nbuffers = 0; m_nbuffers < req.count; ++m_nbuffers) { - v4l2_plane planes[VIDEO_MAX_PLANES]; - v4l2_buffer buf; - - memset(&buf, 0, sizeof(buf)); - - buf.type = buftype; - buf.memory = V4L2_MEMORY_USERPTR; - buf.index = m_nbuffers; - buf.length = VIDEO_MAX_PLANES; - buf.m.planes = planes; - - if (-1 == ioctl(VIDIOC_QUERYBUF, &buf)) { - perror("VIDIOC_QUERYBUF"); - goto error; - } - - if (V4L2_TYPE_IS_MULTIPLANAR(buftype)) { - m_buffers[m_nbuffers].planes = buf.length; - for (unsigned p = 0; p < buf.length; p++) { - m_buffers[m_nbuffers].length[p] = planes[p].length; - m_buffers[m_nbuffers].start[p] = calloc(1, planes[p].length); - if (m_buffers[m_nbuffers].start[p] == NULL) { - error("Out of memory"); - goto error; - } - } - } else { - m_buffers[m_nbuffers].planes = 1; - m_buffers[m_nbuffers].length[0] = buffer_size; - m_buffers[m_nbuffers].start[0] = calloc(1, buffer_size); - - if (!m_buffers[m_nbuffers].start[0]) { - error("Out of memory"); - goto error; - } - } - } - for (i = 0; i < m_nbuffers; ++i) - if (!qbuf_user(i, buftype, m_buffers[i].start, m_buffers[i].length)) { - perror("VIDIOC_QBUF"); - goto error; - } - if (!streamon(buftype)) { - perror("VIDIOC_STREAMON"); - goto error; - } - m_snapshotAct->setEnabled(true); - m_genTab->setHaveBuffers(true); - return true; - } - -error: - m_capStartAct->setChecked(false); - m_useGLAct->setEnabled(CaptureWinGL::isSupported()); - return false; -} + v4l2_encoder_cmd cmd; -void ApplicationWindow::stopCapture() -{ stopAudio(); - if (m_genTab->isRadio()) + s_priority(V4L2_PRIORITY_DEFAULT); + + if (!m_genTab->isSDR() && m_genTab->isRadio()) return; - __u32 buftype = m_genTab->bufType(); - v4l2_requestbuffers reqbufs; - v4l2_encoder_cmd cmd; - unsigned i; + if (v4l_type_is_capture(g_type())) + m_capture->stop(); - m_capture->stop(); m_snapshotAct->setDisabled(true); +#ifdef HAVE_QTGL m_useGLAct->setEnabled(CaptureWinGL::isSupported()); +#endif switch (m_capMethod) { case methodRead: - memset(&cmd, 0, sizeof(cmd)); - cmd.cmd = V4L2_ENC_CMD_STOP; - ioctl(VIDIOC_ENCODER_CMD, &cmd); + if (v4l_type_is_capture(g_type())) { + memset(&cmd, 0, sizeof(cmd)); + cmd.cmd = V4L2_ENC_CMD_STOP; + encoder_cmd(cmd); + } break; case methodMmap: - if (m_buffers == NULL) - break; - if (!streamoff(buftype)) - perror("VIDIOC_STREAMOFF"); - for (i = 0; i < m_nbuffers; ++i) - for (unsigned p = 0; p < m_buffers[i].planes; p++) - if (-1 == munmap(m_buffers[i].start[p], m_buffers[i].length[p])) - perror("munmap"); - // Free all buffers. - reqbufs_mmap(reqbufs, buftype, 1); // videobuf workaround - reqbufs_mmap(reqbufs, buftype, 0); - break; - case methodUser: - if (!streamoff(buftype)) - perror("VIDIOC_STREAMOFF"); - // Free all buffers. - reqbufs_user(reqbufs, buftype, 1); // videobuf workaround - reqbufs_user(reqbufs, buftype, 0); - for (i = 0; i < m_nbuffers; ++i) - for (unsigned p = 0; p < m_buffers[i].planes; p++) - free(m_buffers[i].start[p]); + m_queue.free(this); break; } - free(m_buffers); - m_buffers = NULL; + reopen(true); + m_genTab->sourceChangeSubscribe(); + subscribeCtrlEvents(); m_genTab->setHaveBuffers(false); refresh(); } @@ -945,12 +988,9 @@ return m_showFramesAct->isChecked(); } -void ApplicationWindow::startOutput(unsigned) -{ -} - -void ApplicationWindow::stopOutput() +void ApplicationWindow::traceIoctls(bool enable) { + s_trace(enable); } void ApplicationWindow::enableScaling(bool enable) @@ -979,13 +1019,13 @@ unsigned colorspace = m_genTab->getColorspace(); if (colorspace == 0) { - v4l2_format fmt; + cv4l_fmt fmt; - g_fmt(m_genTab->bufType(), fmt); - if (m_genTab->isPlanar()) - colorspace = fmt.fmt.pix_mp.colorspace; - else - colorspace = fmt.fmt.pix.colorspace; + g_fmt(fmt); + // don't use the wrapped ioctl since it doesn't + // update colorspace correctly. + ::ioctl(g_fd(), VIDIOC_G_FMT, &fmt); + colorspace = fmt.g_colorspace(); } m_capture->setColorspace(colorspace); } @@ -998,9 +1038,9 @@ void ApplicationWindow::clearBuffers() { - if (m_capture && m_buffers) - for (unsigned b = 0; b < m_nbuffers; b++) - m_buffers[b].clear = true; + if (m_capture) + for (unsigned b = 0; b < sizeof(m_clear); b++) + m_clear[b] = true; } void ApplicationWindow::startAudio() @@ -1044,30 +1084,106 @@ m_capStartAct->setChecked(false); } +void ApplicationWindow::outStart(bool start) +{ + if (start) { + cv4l_fmt fmt; + v4l2_output out; + v4l2_control ctrl = { V4L2_CID_DV_TX_RGB_RANGE }; + int factor = 1; + + g_output(out.index); + enum_output(out, true, out.index); + m_frame = m_lastFrame = m_fps = 0; + m_capMethod = m_genTab->capMethod(); + g_fmt(fmt); + if (out.capabilities & V4L2_OUT_CAP_STD) + g_std(m_tpgStd); + else + m_tpgStd = 0; + m_tpgField = fmt.g_first_field(m_tpgStd); + m_tpgSizeImage = fmt.g_sizeimage(0); + tpg_alloc(&m_tpg, fmt.g_width()); + m_useTpg = tpg_s_fourcc(&m_tpg, fmt.g_pixelformat()); + if (V4L2_FIELD_HAS_T_OR_B(fmt.g_field())) + factor = 2; + tpg_reset_source(&m_tpg, fmt.g_width(), fmt.g_height() * factor, fmt.g_field()); + tpg_init_mv_count(&m_tpg); + if (g_ctrl(ctrl)) + tpg_s_rgb_range(&m_tpg, V4L2_DV_RGB_RANGE_AUTO); + else + tpg_s_rgb_range(&m_tpg, ctrl.value); + if (m_tpgColorspace == 0) + fmt.s_colorspace(defaultColorspace(false)); + else + fmt.s_colorspace(m_tpgColorspace); + s_fmt(fmt); + + if (out.capabilities & V4L2_OUT_CAP_STD) { + tpg_s_pixel_aspect(&m_tpg, (m_tpgStd & V4L2_STD_525_60) ? + TPG_PIXEL_ASPECT_NTSC : TPG_PIXEL_ASPECT_PAL); + } else if (out.capabilities & V4L2_OUT_CAP_DV_TIMINGS) { + v4l2_dv_timings timings; + + g_dv_timings(timings); + if (timings.bt.width == 720 && timings.bt.height <= 576) + tpg_s_pixel_aspect(&m_tpg, timings.bt.height == 480 ? + TPG_PIXEL_ASPECT_NTSC : TPG_PIXEL_ASPECT_PAL); + else + tpg_s_pixel_aspect(&m_tpg, TPG_PIXEL_ASPECT_SQUARE); + } else { + tpg_s_pixel_aspect(&m_tpg, TPG_PIXEL_ASPECT_SQUARE); + } + + tpg_s_colorspace(&m_tpg, m_tpgColorspace ? m_tpgColorspace : fmt.g_colorspace()); + tpg_s_bytesperline(&m_tpg, 0, fmt.g_bytesperline(0)); + tpg_s_bytesperline(&m_tpg, 1, fmt.g_bytesperline(1)); + if (m_capMethod == methodRead) + m_frameData = new unsigned char[fmt.g_sizeimage(0)]; + if (startStreaming()) { + m_outNotifier = new QSocketNotifier(g_fd(), QSocketNotifier::Write, m_tabs); + connect(m_outNotifier, SIGNAL(activated(int)), this, SLOT(outFrame())); + } + } else { + stopStreaming(); + tpg_free(&m_tpg); + delete m_frameData; + m_frameData = NULL; + delete m_outNotifier; + m_outNotifier = NULL; + } +} + void ApplicationWindow::capStart(bool start) { - if (m_genTab->isRadio()) { + if (m_genTab->isRadio() && !m_genTab->isSDR()) { if (start) - startCapture(0); + startAudio(); else - stopCapture(); + stopAudio(); + return; + } + if (has_vid_out()) { + outStart(start); + return; + } + + if (!m_genTab->isSDR() && m_genTab->isRadio()) { + if (start) + startStreaming(); + else + stopStreaming(); return; } QImage::Format dstFmt = QImage::Format_RGB888; struct v4l2_fract interval; - v4l2_pix_format &srcPix = m_capSrcFormat.fmt.pix; - v4l2_pix_format &dstPix = m_capDestFormat.fmt.pix; - v4l2_pix_format_mplane &srcMPix = m_capSrcFormat.fmt.pix_mp; - v4l2_pix_format_mplane &dstMPix = m_capDestFormat.fmt.pix_mp; - __u32 buftype = m_genTab->bufType(); - bool isPlanar = m_genTab->isPlanar(); __u32 width, height, pixfmt; unsigned colorspace, field; if (!start) { - stopCapture(); + stopStreaming(); delete m_capNotifier; m_capNotifier = NULL; delete m_capImage; @@ -1078,34 +1194,42 @@ m_capMethod = m_genTab->capMethod(); if (m_genTab->isSlicedVbi()) { - v4l2_format fmt; + cv4l_fmt fmt; v4l2_std_id std; - g_fmt_sliced_vbi(fmt); - g_std(std); - fmt.fmt.sliced.service_set = (std & V4L2_STD_625_50) ? - V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525; + s_type(V4L2_BUF_TYPE_SLICED_VBI_CAPTURE); + if (g_std(std)) { + error("this input isn't suitable for VBI\n"); + return; + } + if (g_fmt(fmt)) { + error("could not obtain an VBI format\n"); + return; + } + fmt.fmt.sliced.service_set = (std & V4L2_STD_525_60) ? + V4L2_SLICED_VBI_525 : V4L2_SLICED_VBI_625; s_fmt(fmt); memset(&m_vbiHandle, 0, sizeof(m_vbiHandle)); m_vbiTab->slicedFormat(fmt.fmt.sliced); m_vbiSize = fmt.fmt.sliced.io_size; m_frameData = new unsigned char[m_vbiSize]; - if (startCapture(m_vbiSize)) { - m_capNotifier = new QSocketNotifier(fd(), QSocketNotifier::Read, m_tabs); + if (startStreaming()) { + m_capNotifier = new QSocketNotifier(g_fd(), QSocketNotifier::Read, m_tabs); connect(m_capNotifier, SIGNAL(activated(int)), this, SLOT(capVbiFrame())); } return; } if (m_genTab->isVbi()) { - v4l2_format fmt; + cv4l_fmt fmt; v4l2_std_id std; - if (!g_std(std)) { + s_type(V4L2_BUF_TYPE_VBI_CAPTURE); + if (g_std(std)) { error("this input isn't suitable for VBI\n"); return; } - if (!g_fmt_vbi(fmt)) { - error("could not obtain a VBI format\n"); + if (g_fmt(fmt)) { + error("could not obtain an VBI format\n"); return; } if (fmt.fmt.vbi.sample_format != V4L2_PIX_FMT_GREY) { @@ -1113,7 +1237,6 @@ return; } s_fmt(fmt); - g_std(std); if (!vbi_prepare(&m_vbiHandle, &fmt.fmt.vbi, std)) { error("no services possible\n"); return; @@ -1127,68 +1250,101 @@ m_capImage->fill(0); m_capture->setWindowSize(QSize(m_vbiWidth, m_vbiHeight)); m_capture->setFrame(m_capImage->width(), m_capImage->height(), - m_capDestFormat.fmt.pix.pixelformat, m_capImage->bits(), NULL, "No frame"); + m_capDestFormat.fmt.pix.pixelformat, m_capImage->bits(), NULL); if (showFrames()) m_capture->show(); statusBar()->showMessage("No frame"); - if (startCapture(m_vbiSize)) { - m_capNotifier = new QSocketNotifier(fd(), QSocketNotifier::Read, m_tabs); + if (startStreaming()) { + m_capNotifier = new QSocketNotifier(g_fd(), QSocketNotifier::Read, m_tabs); connect(m_capNotifier, SIGNAL(activated(int)), this, SLOT(capVbiFrame())); } return; } - g_fmt(buftype, m_capSrcFormat); + if (m_genTab->isSDR()) { + cv4l_fmt fmt; + + if (g_fmt(fmt)) { + error("could not obtain an VBI format\n"); + return; + } + if (fmt.fmt.sdr.pixelformat != V4L2_SDR_FMT_CU8) { + error("only CU8 is supported for SDR\n"); + return; + } + m_sdrSize = fmt.fmt.sdr.buffersize; + m_frameData = new unsigned char[m_sdrSize]; + m_capImage = new QImage(SDR_WIDTH, SDR_HEIGHT, dstFmt); + m_capImage->fill(0); + m_capture->setWindowSize(QSize(SDR_WIDTH, SDR_HEIGHT)); + m_capture->setFrame(m_capImage->width(), m_capImage->height(), + m_capDestFormat.fmt.pix.pixelformat, m_capImage->bits(), NULL); + if (showFrames()) + m_capture->show(); + + statusBar()->showMessage("No frame"); + if (startStreaming()) { + m_capNotifier = new QSocketNotifier(g_fd(), QSocketNotifier::Read, m_tabs); + connect(m_capNotifier, SIGNAL(activated(int)), this, SLOT(capSdrFrame())); + } + return; + } + + m_capSrcFormat.s_type(g_type()); + if (g_fmt(m_capSrcFormat)) { + error("could not obtain a source format\n"); + return; + } s_fmt(m_capSrcFormat); if (m_genTab->get_interval(interval)) - set_interval(buftype, interval); + set_interval(interval); - if (!isPlanar) - m_frameData = new unsigned char[srcPix.sizeimage]; - else - m_frameData = new unsigned char[srcMPix.plane_fmt[0].sizeimage + srcMPix.plane_fmt[1].sizeimage]; + m_frameData = new unsigned char[m_capSrcFormat.g_sizeimage(0) + + m_capSrcFormat.g_sizeimage(1)]; m_capDestFormat = m_capSrcFormat; - if (isPlanar) { - dstMPix.pixelformat = srcMPix.pixelformat; - width = srcMPix.width; - height = srcMPix.height; - pixfmt = srcMPix.pixelformat; - colorspace = srcMPix.colorspace; - field = srcMPix.field; - m_mustConvert = false; - } else if (m_capture->hasNativeFormat(srcPix.pixelformat)) { - dstPix.pixelformat = srcPix.pixelformat; - width = srcPix.width; - height = srcPix.height; - pixfmt = srcPix.pixelformat; - colorspace = srcPix.colorspace; - field = srcPix.field; + if (m_capture->hasNativeFormat(m_capSrcFormat.g_pixelformat())) { + width = m_capSrcFormat.g_width(); + height = m_capSrcFormat.g_height(); + pixfmt = m_capSrcFormat.g_pixelformat(); + colorspace = m_capSrcFormat.g_colorspace(); + field = m_capSrcFormat.g_field(); m_mustConvert = false; } else { m_mustConvert = true; - dstPix.pixelformat = V4L2_PIX_FMT_RGB24; + m_capDestFormat.s_pixelformat(V4L2_PIX_FMT_RGB24); // Make sure sizeimage is large enough. This is necessary if the mplane // plugin is in use since v4lconvert_try_format() bypasses the plugin. - dstPix.sizeimage = dstPix.width * dstPix.height * 3; - v4l2_format copy = m_capSrcFormat; + m_capDestFormat.s_sizeimage(m_capDestFormat.g_width() * + m_capDestFormat.g_height() * 3); + cv4l_fmt copy = m_capSrcFormat; v4lconvert_try_format(m_convertData, &m_capDestFormat, &m_capSrcFormat); // v4lconvert_try_format sometimes modifies the source format if it thinks // that there is a better format available. Restore our selected source // format since we do not want that happening. m_capSrcFormat = copy; - width = dstPix.width; - height = dstPix.height; - pixfmt = dstPix.pixelformat; - colorspace = dstPix.colorspace; - field = dstPix.field; + width = m_capDestFormat.g_width(); + height = m_capDestFormat.g_height(); + pixfmt = m_capDestFormat.g_pixelformat(); + colorspace = m_capDestFormat.g_colorspace(); + field = m_capDestFormat.g_field(); } // Ensure that the initial image is large enough for native 32 bit per pixel formats - if (pixfmt == V4L2_PIX_FMT_RGB32 || pixfmt == V4L2_PIX_FMT_BGR32) + switch (pixfmt) { + case V4L2_PIX_FMT_RGB32: + case V4L2_PIX_FMT_BGR32: + case V4L2_PIX_FMT_XRGB32: + case V4L2_PIX_FMT_XBGR32: + dstFmt = QImage::Format_RGB32; + break; + case V4L2_PIX_FMT_ARGB32: + case V4L2_PIX_FMT_ABGR32: dstFmt = QImage::Format_ARGB32; + break; + } m_capImage = new QImage(width, height, dstFmt); m_capImage->fill(0); @@ -1201,17 +1357,24 @@ m_capture->setWindowSize(QSize(width, height)); m_capture->setFrame(m_capImage->width(), m_capImage->height(), - pixfmt, m_capImage->bits(), NULL, "No frame"); + pixfmt, m_capImage->bits(), NULL); + m_capture->makeFullScreen(m_makeFullScreenAct->isChecked()); if (showFrames()) m_capture->show(); statusBar()->showMessage("No frame"); - if (startCapture(srcPix.sizeimage)) { - m_capNotifier = new QSocketNotifier(fd(), QSocketNotifier::Read, m_tabs); + if (startStreaming()) { + m_capNotifier = new QSocketNotifier(g_fd(), QSocketNotifier::Read, m_tabs); connect(m_capNotifier, SIGNAL(activated(int)), this, SLOT(capFrame())); } } +void ApplicationWindow::makeFullScreen(bool checked) +{ + if (m_capture && m_capStartAct->isChecked()) + m_capture->makeFullScreen(checked); +} + void ApplicationWindow::closeDevice() { stopAudio(); @@ -1220,21 +1383,25 @@ m_capStartAct->setEnabled(false); m_capStartAct->setChecked(false); m_saveRawAct->setEnabled(false); - if (fd() >= 0) { + if (g_fd() >= 0) { if (m_capNotifier) { delete m_capNotifier; delete m_capImage; m_capNotifier = NULL; m_capImage = NULL; } + if (m_outNotifier) { + delete m_outNotifier; + m_outNotifier = NULL; + } if (m_ctrlNotifier) { delete m_ctrlNotifier; m_ctrlNotifier = NULL; } - delete m_frameData; + delete [] m_frameData; m_frameData = NULL; v4lconvert_destroy(m_convertData); - v4l2::close(); + cv4l_fd::close(); delete m_capture; m_capture = NULL; } @@ -1242,10 +1409,12 @@ m_tabs->removeTab(0); delete page; } + m_genTab = NULL; m_ctrlMap.clear(); m_widgetMap.clear(); m_sliderMap.clear(); m_classMap.clear(); + m_tpgLimRGBRange = NULL; } bool SaveDialog::setBuffer(unsigned char *buf, unsigned size) @@ -1421,6 +1590,42 @@ return ok ? QString("%1%2").arg(dev).arg(name) : name; } +static bool processShortOption(const QStringList &args, int &i, QString &dev) +{ + if (args[i].length() < 2) + return false; + if (args[i].length() == 2) { + if (i + 1 >= args.size()) { + usageError(args[i].toAscii()); + return false; + } + dev = args[++i]; + return true; + } + dev = args[i].mid(2); + return true; +} + +static bool processLongOption(const QStringList &args, int &i, QString &dev) +{ + int index = args[i].indexOf('='); + + if (index >= 0) { + dev = args[i].mid(index + 1); + if (dev.length() == 0) { + usageError("--device"); + return false; + } + return true; + } + if (i + 1 >= args.size()) { + usageError(args[i].toAscii()); + return false; + } + dev = args[++i]; + return true; +} + int main(int argc, char **argv) { QApplication a(argc, argv); @@ -1437,94 +1642,36 @@ QStringList args = a.arguments(); for (int i = 1; i < args.size(); i++) { - if (args[i] == "-d" || args[i] == "--device") { - ++i; - if (i >= args.size()) { - usageError("-d"); + if (args[i].startsWith("-d")) { + if (!processShortOption(args, i, video_device)) return 0; - } - - video_device = args[i]; - if (video_device.startsWith("-")) { - usageError("-d"); - return 0; - } - } else if (args[i] == "-V" || args[i] == "--vbi-device") { - ++i; - if (i >= args.size()) { - usageError("-V"); - return 0; - } - - vbi_device = args[i]; - if (vbi_device.startsWith("-")) { - usageError("-V"); - return 0; - } - } else if (args[i] == "-r" || args[i] == "--radio-device") { - ++i; - if (i >= args.size()) { - usageError("-r"); - return 0; - } - - radio_device = args[i]; - if (radio_device.startsWith("-")) { - usageError("-r"); - return 0; - } - } else if (args[i] == "-S" || args[i] == "--sdr-device") { - ++i; - if (i >= args.size()) { - usageError("-S"); - return 0; - } - - sdr_device = args[i]; - if (sdr_device.startsWith("-")) { - usageError("-S"); - return 0; - } } else if (args[i].startsWith("--device")) { - QStringList param = args[i].split("="); - if (param.size() == 2) { - video_device = param[1]; - } else { - usageError("--device"); + if (!processLongOption(args, i, video_device)) + return 0; + } else if (args[i].startsWith("-V")) { + if (!processShortOption(args, i, vbi_device)) return 0; - } } else if (args[i].startsWith("--vbi-device")) { - QStringList param = args[i].split("="); - if (param.size() == 2) { - vbi_device = param[1]; - } else { - usageError("--vbi-device"); + if (!processLongOption(args, i, vbi_device)) + return 0; + } else if (args[i].startsWith("-r")) { + if (!processShortOption(args, i, radio_device)) return 0; - } } else if (args[i].startsWith("--radio-device")) { - QStringList param = args[i].split("="); - if (param.size() == 2) { - radio_device = param[1]; - } else { - usageError("--radio-device"); + if (!processLongOption(args, i, radio_device)) + return 0; + } else if (args[i].startsWith("-S")) { + if (!processShortOption(args, i, sdr_device)) return 0; - } } else if (args[i].startsWith("--sdr-device")) { - QStringList param = args[i].split("="); - if (param.size() == 2) { - sdr_device = param[1]; - } else { - usageError("--sdr-device"); + if (!processLongOption(args, i, sdr_device)) return 0; - } } else if (args[i] == "-h" || args[i] == "--help") { usage(); return 0; } else if (args[i] == "-R" || args[i] == "--raw") { raw = true; - - } else { printf("Invalid argument %s\n", args[i].toAscii().data()); return 0; diff -Nru v4l-utils-1.0.0+r2263/utils/qv4l2/qv4l2.h v4l-utils-1.0.0+r2364/utils/qv4l2/qv4l2.h --- v4l-utils-1.0.0+r2263/utils/qv4l2/qv4l2.h 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/qv4l2/qv4l2.h 2014-08-12 09:02:18.000000000 +0000 @@ -33,12 +33,19 @@ #include #include -#include "v4l2-api.h" +// Must come before cv4l-helpers.h +#include + +extern "C" { +#include +} +#include "cv4l-helpers.h" #include "raw2sliced.h" #include "capture-win.h" class QComboBox; class QSpinBox; +class QCheckBox; class GeneralTab; class VbiTab; class QCloseEvent; @@ -46,7 +53,7 @@ typedef std::vector ClassIDVec; typedef std::map ClassMap; -typedef std::map CtrlMap; +typedef std::map CtrlMap; typedef std::map WidgetMap; enum { @@ -78,10 +85,13 @@ V4L2_CTRL_FLAG_INACTIVE | \ V4L2_CTRL_FLAG_GRABBED) -class ApplicationWindow: public QMainWindow, public v4l2 +class CaptureWin; + +class ApplicationWindow: public QMainWindow, cv4l_fd { Q_OBJECT + friend class CaptureWin; public: ApplicationWindow(); virtual ~ApplicationWindow(); @@ -97,17 +107,18 @@ private: CaptureWin *m_capture; - bool startCapture(unsigned buffer_size); - void stopCapture(); - void startOutput(unsigned buffer_size); - void stopOutput(); + bool startStreaming(); + void stopStreaming(); void newCaptureWin(); void startAudio(); void stopAudio(); + bool startOutput(); + void stopOutput(); + __u32 defaultColorspace(bool capture); - struct buffer *m_buffers; - struct v4l2_format m_capSrcFormat; - struct v4l2_format m_capDestFormat; + bool m_clear[64]; + cv4l_fmt m_capSrcFormat; + cv4l_fmt m_capDestFormat; unsigned char *m_frameData; unsigned m_nbuffers; struct v4lconvert_data *m_convertData; @@ -118,13 +129,19 @@ private slots: void capStart(bool); + void outStart(bool); + void makeFullScreen(bool); void capFrame(); + void outFrame(); void ctrlEvent(); void snapshot(); void capVbiFrame(); + void capSdrFrame(); void saveRaw(bool); - void setRenderMethod(); - void setBlending(); + void setRenderMethod(bool); + void setBlending(bool); + void setLinearFilter(bool); + void traceIoctls(bool); void changeAudioDevice(); // gui @@ -141,9 +158,24 @@ void updateColorspace(); void updateDisplayColorspace(); void clearBuffers(); - void about(); + // tpg +private slots: + void testPatternChanged(int val); + void horMovementChanged(int val); + void vertMovementChanged(int val); + void showBorderChanged(int val); + void showSquareChanged(int val); + void insSAVChanged(int val); + void insEAVChanged(int val); + void videoAspectRatioChanged(int val); + void colorspaceChanged(int val); + void limRGBRangeChanged(int val); + void fillPercentageChanged(int val); + void alphaComponentChanged(int val); + void applyToRedChanged(int val); + public: virtual void error(const QString &text); void error(int err); @@ -152,6 +184,12 @@ void errorCtrl(unsigned id, int err, const QString &v); void info(const QString &info); virtual void closeEvent(QCloseEvent *event); + void updateLimRGBRange(); + QAction *m_resetScalingAct; + QAction *m_useBlendingAct; + QAction *m_useLinearAct; + QAction *m_snapshotAct; + QAction *m_showFramesAct; private: void addWidget(QGridLayout *grid, QWidget *w, Qt::Alignment align = Qt::AlignLeft); @@ -160,11 +198,13 @@ addWidget(grid, new QLabel(text, parentWidget()), align); } void fixWidth(QGridLayout *grid); - void addTabs(int size[]); + void addTabs(int m_winWidth); + void addTpgTab(int m_winWidth); void finishGrid(QGridLayout *grid, unsigned ctrl_class); - void addCtrl(QGridLayout *grid, const struct v4l2_queryctrl &qctrl); + void addCtrl(QGridLayout *grid, const struct v4l2_query_ext_ctrl &qec); void updateCtrl(unsigned id); - void updateCtrlRange(unsigned id); + void updateCtrlRange(unsigned id, __s32 val); + void subscribeCtrlEvents(); void refresh(unsigned ctrl_class); void refresh(); void makeSnapshot(unsigned char *buf, unsigned size); @@ -187,29 +227,35 @@ void updateFreqChannel(); bool showFrames(); + struct tpg_data m_tpg; + v4l2_std_id m_tpgStd; + unsigned m_tpgField; + unsigned m_tpgSizeImage; + unsigned m_tpgColorspace; + bool m_useTpg; + QCheckBox *m_tpgLimRGBRange; + + cv4l_queue m_queue; + const double m_pxw; const int m_minWidth; const int m_vMargin; const int m_hMargin; int m_maxw[4]; - int m_maxh; int m_increment; GeneralTab *m_genTab; VbiTab *m_vbiTab; QAction *m_capStartAct; - QAction *m_snapshotAct; QAction *m_saveRawAct; - QAction *m_showFramesAct; QAction *m_useGLAct; - QAction *m_useBlendingAct; - QAction *m_showAllAudioAct; QAction *m_audioBufferAct; QAction *m_scalingAct; - QAction *m_resetScalingAct; + QAction *m_makeFullScreenAct; QString m_filename; QSignalMapper *m_sigMapper; QTabWidget *m_tabs; QSocketNotifier *m_capNotifier; + QSocketNotifier *m_outNotifier; QSocketNotifier *m_ctrlNotifier; QImage *m_capImage; int m_row, m_col, m_cols; @@ -217,11 +263,11 @@ WidgetMap m_widgetMap; WidgetMap m_sliderMap; ClassMap m_classMap; - bool m_haveExtendedUserCtrls; int m_vbiSize; unsigned m_vbiWidth; unsigned m_vbiHeight; struct vbi_handle m_vbiHandle; + int m_sdrSize; unsigned m_frame; unsigned m_lastFrame; unsigned m_fps; diff -Nru v4l-utils-1.0.0+r2263/utils/qv4l2/qv4l2.pro v4l-utils-1.0.0+r2364/utils/qv4l2/qv4l2.pro --- v4l-utils-1.0.0+r2263/utils/qv4l2/qv4l2.pro 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/qv4l2/qv4l2.pro 2014-08-12 09:02:18.000000000 +0000 @@ -7,8 +7,8 @@ CONFIG += debug # Input -HEADERS += qv4l2.h general-tab.h v4l2-api.h capture-win.h -SOURCES += qv4l2.cpp general-tab.cpp ctrl-tab.cpp v4l2-api.cpp capture-win.cpp +HEADERS += qv4l2.h general-tab.h capture-win.h +SOURCES += qv4l2.cpp general-tab.cpp ctrl-tab.cpp capture-win.cpp LIBS += -L../../lib/libv4l2 -lv4l2 -L../../lib/libv4lconvert -lv4lconvert -lrt -L../libv4l2util -lv4l2util -ldl -ljpeg RESOURCES += qv4l2.qrc diff -Nru v4l-utils-1.0.0+r2263/utils/qv4l2/qv4l2.qrc v4l-utils-1.0.0+r2364/utils/qv4l2/qv4l2.qrc --- v4l-utils-1.0.0+r2263/utils/qv4l2/qv4l2.qrc 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/qv4l2/qv4l2.qrc 2014-08-12 09:02:18.000000000 +0000 @@ -8,5 +8,8 @@ saveraw.png video-television.png qv4l2.png + enterbutt.png + fullscreen.png + fullscreenexit.png diff -Nru v4l-utils-1.0.0+r2263/utils/qv4l2/tpg-tab.cpp v4l-utils-1.0.0+r2364/utils/qv4l2/tpg-tab.cpp --- v4l-utils-1.0.0+r2263/utils/qv4l2/tpg-tab.cpp 1970-01-01 00:00:00.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/qv4l2/tpg-tab.cpp 2014-08-12 09:02:18.000000000 +0000 @@ -0,0 +1,363 @@ +/* + * qv4l2 - Test Pattern Generator Tab + * + * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "qv4l2.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +void ApplicationWindow::addTpgTab(int m_winWidth) +{ + QWidget *t = new QWidget(m_tabs); + QVBoxLayout *vbox = new QVBoxLayout(t); + QWidget *w = new QWidget(t); + QCheckBox *check; + QComboBox *combo; + QSpinBox *spin; + + m_col = m_row = 0; + m_cols = 4; + for (int j = 0; j < m_cols; j++) { + m_maxw[j] = 0; + } + + vbox->addWidget(w); + + QGridLayout *grid = new QGridLayout(w); + QLabel *title_tab = new QLabel("Test Pattern Generator", parentWidget()); + QFont f = title_tab->font(); + f.setBold(true); + title_tab->setFont(f); + grid->addWidget(title_tab, m_row, m_col, 1, m_cols, Qt::AlignLeft); + grid->setRowMinimumHeight(m_row, 25); + m_row++; + + QFrame *m_line = new QFrame(grid->parentWidget()); + m_line->setFrameShape(QFrame::HLine); + m_line->setFrameShadow(QFrame::Sunken); + grid->addWidget(m_line, m_row, m_col, 1, m_cols, Qt::AlignVCenter); + m_row++; + + m_tabs->addTab(t, "Test Pattern Generator"); + grid->addWidget(new QWidget(w), grid->rowCount(), 0, 1, m_cols); + + addLabel(grid, "Test Pattern"); + combo = new QComboBox(w); + for (int i = 0; tpg_pattern_strings[i]; i++) + combo->addItem(tpg_pattern_strings[i]); + addWidget(grid, combo); + connect(combo, SIGNAL(activated(int)), SLOT(testPatternChanged(int))); + + m_row++; + m_col = 0; + + addLabel(grid, "Horizontal Movement"); + combo = new QComboBox(w); + combo->addItem("Move Left Fast"); + combo->addItem("Move Left"); + combo->addItem("Move Left Slow"); + combo->addItem("No Movement"); + combo->addItem("Move Right Slow"); + combo->addItem("Move Right"); + combo->addItem("Move Right Fast"); + combo->setCurrentIndex(3); + addWidget(grid, combo); + connect(combo, SIGNAL(activated(int)), SLOT(horMovementChanged(int))); + + addLabel(grid, "Video Aspect Ratio"); + combo = new QComboBox(w); + combo->addItem("Source Width x Height"); + combo->addItem("4x3"); + combo->addItem("14x9"); + combo->addItem("16x9"); + combo->addItem("16x9 Anamorphic"); + addWidget(grid, combo); + connect(combo, SIGNAL(activated(int)), SLOT(videoAspectRatioChanged(int))); + + addLabel(grid, "Vertical Movement"); + combo = new QComboBox(w); + combo->addItem("Move Up Fast"); + combo->addItem("Move Up"); + combo->addItem("Move Up Slow"); + combo->addItem("No Movement"); + combo->addItem("Move Down Slow"); + combo->addItem("Move Down"); + combo->addItem("Move Down Fast"); + combo->setCurrentIndex(3); + addWidget(grid, combo); + connect(combo, SIGNAL(activated(int)), SLOT(vertMovementChanged(int))); + + m_tpgColorspace = 0; + addLabel(grid, "Colorspace"); + combo = new QComboBox(w); + combo->addItem("Autodetect"); + combo->addItem("SMPTE 170M"); + combo->addItem("SMPTE 240M"); + combo->addItem("REC 709"); + combo->addItem("470 System M"); + combo->addItem("470 System BG"); + combo->addItem("sRGB"); + addWidget(grid, combo); + connect(combo, SIGNAL(activated(int)), SLOT(colorspaceChanged(int))); + + addLabel(grid, "Show Border"); + check = new QCheckBox(w); + addWidget(grid, check); + connect(check, SIGNAL(stateChanged(int)), SLOT(showBorderChanged(int))); + + addLabel(grid, "Insert SAV Code in Image"); + check = new QCheckBox(w); + addWidget(grid, check); + connect(check, SIGNAL(stateChanged(int)), SLOT(insSAVChanged(int))); + + addLabel(grid, "Show Square"); + check = new QCheckBox(w); + addWidget(grid, check); + connect(check, SIGNAL(stateChanged(int)), SLOT(showSquareChanged(int))); + + addLabel(grid, "Insert EAV Code in Image"); + check = new QCheckBox(w); + addWidget(grid, check); + connect(check, SIGNAL(stateChanged(int)), SLOT(insEAVChanged(int))); + + addLabel(grid, "Fill Percentage of Frame"); + spin = new QSpinBox(w); + spin->setRange(0, 100); + spin->setValue(100); + addWidget(grid, spin); + connect(spin, SIGNAL(valueChanged(int)), SLOT(fillPercentageChanged(int))); + + addLabel(grid, "Limited RGB Range (16-235)"); + m_tpgLimRGBRange = new QCheckBox(w); + addWidget(grid, m_tpgLimRGBRange); + connect(m_tpgLimRGBRange, SIGNAL(stateChanged(int)), SLOT(limRGBRangeChanged(int))); + + addLabel(grid, "Alpha Component"); + spin = new QSpinBox(w); + spin->setRange(0, 255); + spin->setValue(0); + addWidget(grid, spin); + connect(spin, SIGNAL(valueChanged(int)), SLOT(alphaComponentChanged(int))); + + addLabel(grid, "Apply Alpha To Red Only"); + check = new QCheckBox(w); + addWidget(grid, check); + connect(check, SIGNAL(stateChanged(int)), SLOT(applyToRedChanged(int))); + + m_row++; + m_col = 0; + addWidget(grid, new QWidget(w)); + grid->setRowStretch(grid->rowCount() - 1, 1); + w = new QWidget(t); + vbox->addWidget(w); + fixWidth(grid); + + int totalw = 0; + int diff = 0; + for (int i = 0; i < m_cols; i++) { + totalw += m_maxw[i] + m_pxw; + } + if (totalw > m_winWidth) + m_winWidth = totalw; + else { + diff = m_winWidth - totalw; + grid->setHorizontalSpacing(diff/5); + } +} + +void ApplicationWindow::testPatternChanged(int val) +{ + tpg_s_pattern(&m_tpg, (tpg_pattern)val); +} + +void ApplicationWindow::horMovementChanged(int val) +{ + tpg_s_mv_hor_mode(&m_tpg, (tpg_move_mode)val); +} + +void ApplicationWindow::vertMovementChanged(int val) +{ + tpg_s_mv_vert_mode(&m_tpg, (tpg_move_mode)val); +} + +void ApplicationWindow::showBorderChanged(int val) +{ + tpg_s_show_border(&m_tpg, val); +} + +void ApplicationWindow::showSquareChanged(int val) +{ + tpg_s_show_square(&m_tpg, val); +} + +void ApplicationWindow::insSAVChanged(int val) +{ + tpg_s_insert_sav(&m_tpg, val); +} + +void ApplicationWindow::insEAVChanged(int val) +{ + tpg_s_insert_eav(&m_tpg, val); +} + +void ApplicationWindow::videoAspectRatioChanged(int val) +{ + tpg_s_video_aspect(&m_tpg, (tpg_video_aspect)val); +} + +void ApplicationWindow::updateLimRGBRange() +{ + if (m_tpgLimRGBRange == NULL) + return; + + v4l2_output out; + + g_output(out.index); + enum_output(out, true, out.index); + + if (out.capabilities & V4L2_OUT_CAP_STD) { + m_tpgLimRGBRange->setChecked(false); + } else if (out.capabilities & V4L2_OUT_CAP_DV_TIMINGS) { + v4l2_dv_timings timings; + + g_dv_timings(timings); + if (timings.bt.standards & V4L2_DV_BT_STD_CEA861) + m_tpgLimRGBRange->setChecked(true); + else + m_tpgLimRGBRange->setChecked(false); + } else { + m_tpgLimRGBRange->setChecked(false); + } +} + +__u32 ApplicationWindow::defaultColorspace(bool capture) +{ + v4l2_dv_timings timings = { 0 }; + v4l2_output out; + v4l2_input in; + __u32 io_caps; + bool dvi_d = false; + + if (capture) { + g_input(in.index); + enum_input(in, true, in.index); + io_caps = in.capabilities; + } else { + g_output(out.index); + enum_output(out, true, out.index); + io_caps = out.capabilities; + v4l2_control ctrl = { V4L2_CID_DV_TX_MODE }; + + if (!g_ctrl(ctrl)) + dvi_d = ctrl.value == V4L2_DV_TX_MODE_DVI_D; + } + + if (io_caps & V4L2_OUT_CAP_STD) + return V4L2_COLORSPACE_SMPTE170M; + if (!(io_caps & V4L2_OUT_CAP_DV_TIMINGS)) + return V4L2_COLORSPACE_SRGB; + + g_dv_timings(timings); + + if (!(timings.bt.standards & V4L2_DV_BT_STD_CEA861) || dvi_d) + return V4L2_COLORSPACE_SRGB; + if (timings.bt.width == 720 && timings.bt.height <= 576) + return V4L2_COLORSPACE_SMPTE170M; + return V4L2_COLORSPACE_REC709; +} + +void ApplicationWindow::colorspaceChanged(int val) +{ + switch (val) { + case 0: + m_tpgColorspace = 0; + break; + case 1: + m_tpgColorspace = V4L2_COLORSPACE_SMPTE170M; + break; + case 2: + m_tpgColorspace = V4L2_COLORSPACE_SMPTE240M; + break; + case 3: + m_tpgColorspace = V4L2_COLORSPACE_REC709; + break; + case 4: + m_tpgColorspace = V4L2_COLORSPACE_470_SYSTEM_M; + break; + case 5: + m_tpgColorspace = V4L2_COLORSPACE_470_SYSTEM_BG; + break; + case 6: + default: + m_tpgColorspace = V4L2_COLORSPACE_SRGB; + break; + } + + cv4l_fmt fmt; + v4l2_output out; + + g_output(out.index); + enum_output(out, true, out.index); + + g_fmt(fmt); + if (m_tpgColorspace == 0) + fmt.s_colorspace(defaultColorspace(false)); + else + fmt.s_colorspace(m_tpgColorspace); + s_fmt(fmt); + tpg_s_colorspace(&m_tpg, m_tpgColorspace ? m_tpgColorspace : fmt.g_colorspace()); +} + +void ApplicationWindow::limRGBRangeChanged(int val) +{ + tpg_s_real_rgb_range(&m_tpg, val ? V4L2_DV_RGB_RANGE_LIMITED : V4L2_DV_RGB_RANGE_FULL); +} + +void ApplicationWindow::fillPercentageChanged(int val) +{ + tpg_s_perc_fill(&m_tpg, val); +} + +void ApplicationWindow::alphaComponentChanged(int val) +{ + tpg_s_alpha_component(&m_tpg, val); +} + +void ApplicationWindow::applyToRedChanged(int val) +{ + tpg_s_alpha_mode(&m_tpg, val); +} diff -Nru v4l-utils-1.0.0+r2263/utils/qv4l2/v4l2-api.cpp v4l-utils-1.0.0+r2364/utils/qv4l2/v4l2-api.cpp --- v4l-utils-1.0.0+r2263/utils/qv4l2/v4l2-api.cpp 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/qv4l2/v4l2-api.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,656 +0,0 @@ -/* v4l2-api: low-level wrapper around v4l2 devices - * - * Copyright (C) 2009 Hans Verkuil - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include -#include -#include -#include -#include -#include -#include "v4l2-api.h" - -bool v4l2::open(const QString &device, bool useWrapper) -{ - m_device = device; - m_useWrapper = useWrapper; - m_fd = ::open(device.toAscii(), O_RDWR | O_NONBLOCK); - if (m_fd < 0) { - error("Cannot open " + device); - return false; - } - if (!querycap(m_capability)) { - ::close(m_fd); - m_fd = -1; - error(device + " is not a V4L2 device"); - return false; - } - - if (m_useWrapper) { - int fd = ::v4l2_fd_open(m_fd, V4L2_ENABLE_ENUM_FMT_EMULATION); - - if (fd < 0) { - m_useWrapper = false; - error("Cannot use libv4l2 wrapper for " + device); - } - } - return true; -} - -void v4l2::close() -{ - if (useWrapper()) - ::v4l2_close(m_fd); - else - ::close(m_fd); - m_fd = -1; -} - -int v4l2::ioctl(unsigned cmd, void *arg) -{ - if (useWrapper()) - return v4l2_ioctl(m_fd, cmd, arg); - return ::ioctl(m_fd, cmd, arg); -} - -bool v4l2::ioctl(const QString &descr, unsigned cmd, void *arg) -{ - clear(); - int err = ioctl(cmd, arg); - - if (err < 0) { - QString s = strerror(errno); - error(descr + ": " + s); - } - return err >= 0; -} - -bool v4l2::ioctl_exists(unsigned cmd, void *arg) -{ - int err; - - if (useWrapper()) - err = v4l2_ioctl(m_fd, cmd, arg); - else - err = ::ioctl(m_fd, cmd, arg); - return !err || errno != ENOTTY; -} - -int v4l2::read(unsigned char *p, int size) -{ - if (useWrapper()) - return v4l2_read(m_fd, p, size); - return ::read(m_fd, p, size); -} - -void *v4l2::mmap(size_t length, int64_t offset) -{ - if (useWrapper()) - return v4l2_mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, m_fd, offset); - return ::mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, m_fd, offset); -} - -int v4l2::munmap(void *start, size_t length) -{ - if (useWrapper()) - return v4l2_munmap(start, length); - return ::munmap(start, length); -} - -void v4l2::error(const QString &error) -{ - if (!error.isEmpty()) - fprintf(stderr, "%s\n", error.toAscii().data()); -} - -QString v4l2::pixfmt2s(unsigned id) -{ - QString pixfmt; - - pixfmt += (char)(id & 0xff); - pixfmt += (char)((id >> 8) & 0xff); - pixfmt += (char)((id >> 16) & 0xff); - pixfmt += (char)((id >> 24) & 0xff); - return pixfmt; -} - -bool v4l2::querycap(v4l2_capability &cap) -{ - memset(&cap, 0, sizeof(cap)); - return ioctl(VIDIOC_QUERYCAP, &cap) >= 0; -} - -bool v4l2::queryctrl(v4l2_queryctrl &qc) -{ - return ioctl(VIDIOC_QUERYCTRL, &qc) >= 0; -} - -bool v4l2::querymenu(v4l2_querymenu &qm) -{ - return ioctl(VIDIOC_QUERYMENU, &qm) >= 0; -} - -bool v4l2::g_tuner(v4l2_tuner &tuner, unsigned index) -{ - memset(&tuner, 0, sizeof(tuner)); - tuner.index = index; - if (ioctl(VIDIOC_G_TUNER, &tuner) < 0) - return false; - if (tuner.rangehigh > INT_MAX) - tuner.rangehigh = INT_MAX; - return true; -} - -bool v4l2::s_tuner(v4l2_tuner &tuner) -{ - return ioctl("Set Tuner", VIDIOC_S_TUNER, &tuner); -} - -bool v4l2::g_modulator(v4l2_modulator &modulator) -{ - memset(&modulator, 0, sizeof(modulator)); - return ioctl(VIDIOC_G_MODULATOR, &modulator) >= 0; -} - -bool v4l2::s_modulator(v4l2_modulator &modulator) -{ - return ioctl("Set Modulator", VIDIOC_S_MODULATOR, &modulator); -} - -bool v4l2::g_input(int &input) -{ - return ioctl(VIDIOC_G_INPUT, &input) >= 0; -} - -bool v4l2::s_input(int input) -{ - return ioctl("Set Input", VIDIOC_S_INPUT, &input); -} - -bool v4l2::g_output(int &output) -{ - return ioctl(VIDIOC_G_OUTPUT, &output) >= 0; -} - -bool v4l2::s_output(int output) -{ - return ioctl("Set Output", VIDIOC_S_OUTPUT, &output); -} - -bool v4l2::g_audio(v4l2_audio &audio) -{ - memset(&audio, 0, sizeof(audio)); - return ioctl(VIDIOC_G_AUDIO, &audio) >= 0; -} - -bool v4l2::s_audio(int input) -{ - v4l2_audio audio; - - memset(&audio, 0, sizeof(audio)); - audio.index = input; - return ioctl("Set Audio Input", VIDIOC_S_AUDIO, &audio); -} - -bool v4l2::g_audout(v4l2_audioout &audout) -{ - memset(&audout, 0, sizeof(audout)); - return ioctl(VIDIOC_G_AUDOUT, &audout) >= 0; -} - -bool v4l2::s_audout(int output) -{ - v4l2_audioout audout; - - memset(&audout, 0, sizeof(audout)); - audout.index = output; - return ioctl("Set Audio Output", VIDIOC_S_AUDOUT, &audout); -} - -bool v4l2::g_std(v4l2_std_id &std) -{ - return ioctl(VIDIOC_G_STD, &std) >= 0; -} - -bool v4l2::s_std(v4l2_std_id std) -{ - return ioctl("Set TV Standard", VIDIOC_S_STD, &std); -} - -bool v4l2::query_std(v4l2_std_id &std) -{ - return ioctl("Query TV Standard", VIDIOC_QUERYSTD, &std); -} - -bool v4l2::g_dv_timings(v4l2_dv_timings &timings) -{ - int err = ioctl(VIDIOC_G_DV_TIMINGS, &timings); - return err >= 0; -} - -bool v4l2::s_dv_timings(v4l2_dv_timings &timings) -{ - return ioctl("Set Timings", VIDIOC_S_DV_TIMINGS, &timings); -} - -bool v4l2::query_dv_timings(v4l2_dv_timings &timings) -{ - return ioctl("Query Timings", VIDIOC_QUERY_DV_TIMINGS, &timings); -} - - -bool v4l2::g_frequency(v4l2_frequency &freq, unsigned index) -{ - memset(&freq, 0, sizeof(freq)); - freq.tuner = index; - freq.type = V4L2_TUNER_ANALOG_TV; - return ioctl(VIDIOC_G_FREQUENCY, &freq) >= 0; -} - -bool v4l2::s_frequency(v4l2_frequency &freq) -{ - return ioctl("Set Frequency", VIDIOC_S_FREQUENCY, &freq); -} - -bool v4l2::s_frequency(int val, bool low) -{ - v4l2_frequency f; - - memset(&f, 0, sizeof(f)); - f.type = low ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; - f.frequency = val; - return s_frequency(f); -} - -bool v4l2::g_fmt(unsigned type, v4l2_format &fmt) -{ - memset(&fmt, 0, sizeof(fmt)); - fmt.type = type; - return ioctl(VIDIOC_G_FMT, &fmt) >= 0; -} - -bool v4l2::g_fmt_vbi(v4l2_format &fmt) -{ - memset(&fmt, 0, sizeof(fmt)); - fmt.type = V4L2_BUF_TYPE_VBI_CAPTURE; - return ioctl(VIDIOC_G_FMT, &fmt) >= 0; -} - -bool v4l2::g_fmt_sliced_vbi(v4l2_format &fmt) -{ - memset(&fmt, 0, sizeof(fmt)); - fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; - return ioctl(VIDIOC_G_FMT, &fmt) >= 0; -} - -bool v4l2::try_fmt(v4l2_format &fmt) -{ - if (V4L2_TYPE_IS_MULTIPLANAR(fmt.type)) { - fmt.fmt.pix_mp.plane_fmt[0].bytesperline = 0; - fmt.fmt.pix_mp.plane_fmt[1].bytesperline = 0; - } else { - fmt.fmt.pix.bytesperline = 0; - } - return ioctl("Try Capture Format", VIDIOC_TRY_FMT, &fmt); -} - -bool v4l2::s_fmt(v4l2_format &fmt) -{ - if (V4L2_TYPE_IS_MULTIPLANAR(fmt.type)) { - fmt.fmt.pix_mp.plane_fmt[0].bytesperline = 0; - fmt.fmt.pix_mp.plane_fmt[1].bytesperline = 0; - } else { - fmt.fmt.pix.bytesperline = 0; - } - return ioctl("Set Capture Format", VIDIOC_S_FMT, &fmt); -} - -bool v4l2::enum_input(v4l2_input &in, bool init, int index) -{ - if (init) { - memset(&in, 0, sizeof(in)); - in.index = index; - } else { - in.index++; - } - return ioctl(VIDIOC_ENUMINPUT, &in) >= 0; -} - -bool v4l2::enum_output(v4l2_output &out, bool init, int index) -{ - if (init) { - memset(&out, 0, sizeof(out)); - out.index = index; - } else { - out.index++; - } - return ioctl(VIDIOC_ENUMOUTPUT, &out) >= 0; -} - -bool v4l2::enum_audio(v4l2_audio &audio, bool init) -{ - if (init) - memset(&audio, 0, sizeof(audio)); - else - audio.index++; - return ioctl(VIDIOC_ENUMAUDIO, &audio) >= 0; -} - -bool v4l2::enum_audout(v4l2_audioout &audout, bool init) -{ - if (init) - memset(&audout, 0, sizeof(audout)); - else - audout.index++; - return ioctl(VIDIOC_ENUMAUDOUT, &audout) >= 0; -} - -bool v4l2::enum_std(v4l2_standard &std, bool init, int index) -{ - if (init) { - memset(&std, 0, sizeof(std)); - std.index = index; - } else { - std.index++; - } - return ioctl(VIDIOC_ENUMSTD, &std) >= 0; -} - -bool v4l2::enum_dv_timings(v4l2_enum_dv_timings &timings, bool init, int index) -{ - if (init) { - memset(&timings, 0, sizeof(timings)); - timings.index = index; - } else { - timings.index++; - } - return ioctl(VIDIOC_ENUM_DV_TIMINGS, &timings) >= 0; -} - -bool v4l2::enum_fmt(v4l2_fmtdesc &fmt, unsigned type, bool init, int index) -{ - if (init) { - memset(&fmt, 0, sizeof(fmt)); - fmt.index = index; - } else { - fmt.index++; - } - fmt.type = type; - return ioctl(VIDIOC_ENUM_FMT, &fmt) >= 0; -} - -bool v4l2::enum_framesizes(v4l2_frmsizeenum &frm, __u32 init_pixfmt, int index) -{ - if (init_pixfmt) { - memset(&frm, 0, sizeof(frm)); - frm.pixel_format = init_pixfmt; - frm.index = index; - } else { - frm.index++; - } - return ioctl(VIDIOC_ENUM_FRAMESIZES, &frm) >= 0; -} - -bool v4l2::enum_frameintervals(v4l2_frmivalenum &frm, __u32 init_pixfmt, __u32 w, __u32 h, int index) -{ - if (init_pixfmt) { - memset(&frm, 0, sizeof(frm)); - frm.pixel_format = init_pixfmt; - frm.width = w; - frm.height = h; - frm.index = index; - } else { - frm.index++; - } - return ioctl(VIDIOC_ENUM_FRAMEINTERVALS, &frm) >= 0; -} - -bool v4l2::reqbufs_user(v4l2_requestbuffers &reqbuf, __u32 buftype, int count) -{ - memset(&reqbuf, 0, sizeof (reqbuf)); - reqbuf.type = buftype; - reqbuf.memory = V4L2_MEMORY_USERPTR; - reqbuf.count = count; - - return ioctl(VIDIOC_REQBUFS, &reqbuf) >= 0; -} - -bool v4l2::reqbufs_mmap(v4l2_requestbuffers &reqbuf, __u32 buftype, int count) -{ - memset(&reqbuf, 0, sizeof (reqbuf)); - reqbuf.type = buftype; - reqbuf.memory = V4L2_MEMORY_MMAP; - reqbuf.count = count; - - return ioctl(VIDIOC_REQBUFS, &reqbuf) >= 0; -} - -bool v4l2::dqbuf_mmap(v4l2_buffer &buf, __u32 buftype, bool &again) -{ - v4l2_plane *planes = buf.m.planes; - unsigned length = buf.length; - int res; - - memset(&buf, 0, sizeof(buf)); - buf.length = length; - buf.m.planes = planes; - buf.type = buftype; - buf.memory = V4L2_MEMORY_MMAP; - res = ioctl(VIDIOC_DQBUF, &buf); - again = res < 0 && errno == EAGAIN; - return res >= 0 || again; -} - -bool v4l2::dqbuf_user(v4l2_buffer &buf, __u32 buftype, bool &again) -{ - v4l2_plane *planes = buf.m.planes; - unsigned length = buf.length; - int res; - - memset(&buf, 0, sizeof(buf)); - buf.length = length; - buf.m.planes = planes; - buf.type = buftype; - buf.memory = V4L2_MEMORY_USERPTR; - res = ioctl(VIDIOC_DQBUF, &buf); - again = res < 0 && errno == EAGAIN; - return res >= 0 || again; -} - -bool v4l2::qbuf(v4l2_buffer &buf) -{ - return ioctl(VIDIOC_QBUF, &buf) >= 0; -} - -bool v4l2::qbuf_mmap(int index, __u32 buftype) -{ - v4l2_plane planes[VIDEO_MAX_PLANES]; - v4l2_buffer buf; - - memset(&buf, 0, sizeof(buf)); - buf.type = buftype; - buf.memory = V4L2_MEMORY_MMAP; - buf.index = index; - buf.length = 2; - buf.m.planes = planes; - return qbuf(buf); -} - -bool v4l2::qbuf_user(int index, __u32 buftype, void *ptr[], size_t length[]) -{ - v4l2_plane planes[VIDEO_MAX_PLANES]; - v4l2_buffer buf; - - memset(&buf, 0, sizeof(buf)); - buf.type = buftype; - buf.memory = V4L2_MEMORY_USERPTR; - if (V4L2_TYPE_IS_MULTIPLANAR(buftype)) { - buf.length = 2; - buf.m.planes = planes; - planes[0].length = length[0]; - planes[0].m.userptr = (unsigned long)ptr[0]; - planes[1].length = length[1]; - planes[1].m.userptr = (unsigned long)ptr[1]; - } else { - buf.m.userptr = (unsigned long)ptr[0]; - buf.length = length[0]; - } - buf.index = index; - return qbuf(buf); -} - -bool v4l2::streamon(__u32 buftype) -{ - return ioctl("Start Streaming", VIDIOC_STREAMON, &buftype); -} - -bool v4l2::streamoff(__u32 buftype) -{ - return ioctl("Stop Streaming", VIDIOC_STREAMOFF, &buftype); -} - -bool v4l2::subscribe_event(v4l2_event_subscription &sub) -{ - return ioctl(VIDIOC_SUBSCRIBE_EVENT, &sub); -} - -bool v4l2::dqevent(v4l2_event &ev) -{ - return ioctl(VIDIOC_DQEVENT, &ev) >= 0; -} - -bool v4l2::set_interval(unsigned type, v4l2_fract interval) -{ - v4l2_streamparm parm; - - parm.type = type; - if (ioctl(VIDIOC_G_PARM, &parm) < 0) - return false; - - if (!(parm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME)) - return false; - - parm.parm.capture.timeperframe = interval; - - return ioctl("Set FPS", VIDIOC_S_PARM, &parm); -} - -bool v4l2::get_interval(unsigned type, v4l2_fract &interval) -{ - v4l2_streamparm parm; - - parm.type = type; - if (ioctl(VIDIOC_G_PARM, &parm) >= 0 && - (parm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME)) { - interval = parm.parm.capture.timeperframe; - return true; - } - - return false; -} - -v4l2_fract v4l2::g_pixel_aspect(unsigned type, unsigned &width, unsigned &height) -{ - v4l2_cropcap ratio; - v4l2_dv_timings timings; - v4l2_std_id std; - static const v4l2_fract square = { 1, 1 }; - static const v4l2_fract hz50 = { 11, 12 }; - static const v4l2_fract hz60 = { 11, 10 }; - - ratio.type = type; - if (ioctl(VIDIOC_CROPCAP, &ratio) == 0) { - width = ratio.defrect.width; - height = ratio.defrect.height; - if (ratio.pixelaspect.numerator && ratio.pixelaspect.denominator) - return ratio.pixelaspect; - } - - width = 720; - height = 480; - if (g_std(std)) { - if (std & V4L2_STD_525_60) - return hz60; - if (std & V4L2_STD_625_50) { - height = 576; - return hz50; - } - } - - if (g_dv_timings(timings)) { - width = timings.bt.width; - height = timings.bt.height; - if (width == 720 && height == 480) - return hz60; - if (width == 720 && height == 576) { - height = 576; - return hz50; - } - return square; - } - width = 0; - height = 0; - return square; -} - -bool v4l2::has_crop() -{ - v4l2_crop crop; - v4l2_cropcap cropcap; - - crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - return ioctl_exists(VIDIOC_G_CROP, &crop) && - ioctl_exists(VIDIOC_S_CROP, &crop) && - ioctl_exists(VIDIOC_CROPCAP, &cropcap); -} - -bool v4l2::input_has_crop() -{ - v4l2_crop crop; - v4l2_cropcap cropcap; - - crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - return ioctl(VIDIOC_G_CROP, &crop) == 0 && - ioctl(VIDIOC_S_CROP, &crop) == 0 && - ioctl(VIDIOC_CROPCAP, &cropcap) == 0 && - cropcap.bounds.width && cropcap.bounds.height; -} - -bool v4l2::has_compose() -{ - v4l2_selection sel; - - memset(&sel, 0, sizeof(sel)); - sel.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - sel.target = V4L2_SEL_TGT_COMPOSE; - return ioctl_exists(VIDIOC_G_SELECTION, &sel) && - ioctl_exists(VIDIOC_S_SELECTION, &sel); -} - -bool v4l2::input_has_compose() -{ - v4l2_selection sel; - - memset(&sel, 0, sizeof(sel)); - sel.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - sel.target = V4L2_SEL_TGT_COMPOSE; - return ioctl(VIDIOC_G_SELECTION, &sel) == 0 && - ioctl(VIDIOC_S_SELECTION, &sel) == 0; -} diff -Nru v4l-utils-1.0.0+r2263/utils/qv4l2/v4l2-api.h v4l-utils-1.0.0+r2364/utils/qv4l2/v4l2-api.h --- v4l-utils-1.0.0+r2263/utils/qv4l2/v4l2-api.h 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/qv4l2/v4l2-api.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,128 +0,0 @@ -/* v4l2-api: low-level wrapper around v4l2 devices - * - * Copyright (C) 2009 Hans Verkuil - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef V4L2_API_H -#define V4L2_API_H - -#include -#include -#include - -class v4l2 -{ -public: - v4l2() : m_fd(-1) {} - v4l2(v4l2 &old) : - m_fd(old.m_fd), - m_device(old.m_device), - m_useWrapper(old.m_useWrapper), - m_capability(old.m_capability) - {} - - bool open(const QString &device, bool useWrapper = true); - void close(); - int read(unsigned char *p, int size); - int ioctl(unsigned cmd, void *arg); - bool ioctl(const QString &descr, unsigned cmd, void *arg); - bool ioctl_exists(unsigned cmd, void *arg); - void *mmap(size_t length, int64_t offset); - int munmap(void *_start, size_t length); - - inline int fd() const { return m_fd; } - inline bool useWrapper() const { return m_useWrapper; } - inline __u32 caps() const { - if (m_capability.capabilities & V4L2_CAP_DEVICE_CAPS) - return m_capability.device_caps; - return m_capability.capabilities; - } - inline const QString &device() const { return m_device; } - static QString pixfmt2s(unsigned pixelformat); - - virtual void error(const QString &text); - - bool querycap(v4l2_capability &cap); - bool queryctrl(v4l2_queryctrl &qc); - bool querymenu(v4l2_querymenu &qm); - bool g_tuner(v4l2_tuner &tuner, unsigned index = 0); - bool s_tuner(v4l2_tuner &tuner); - bool g_modulator(v4l2_modulator &modulator); - bool s_modulator(v4l2_modulator &modulator); - bool g_input(int &input); - bool s_input(int input); - bool g_output(int &output); - bool s_output(int output); - bool g_audio(v4l2_audio &audio); - bool s_audio(int input); - bool g_audout(v4l2_audioout &audout); - bool s_audout(int output); - bool s_std(v4l2_std_id std); - bool g_std(v4l2_std_id &std); - bool query_std(v4l2_std_id &std); - bool s_dv_timings(v4l2_dv_timings &timings); - bool g_dv_timings(v4l2_dv_timings &timings); - bool query_dv_timings(v4l2_dv_timings &timings); - bool g_frequency(v4l2_frequency &freq, unsigned index = 0); - bool s_frequency(v4l2_frequency &freq); - bool s_frequency(int freq, bool low = false); - bool g_fmt(unsigned type, v4l2_format &fmt); - bool g_fmt_vbi(v4l2_format &fmt); - bool g_fmt_sliced_vbi(v4l2_format &fmt); - bool try_fmt(v4l2_format &fmt); - bool s_fmt(v4l2_format &fmt); - bool enum_input(v4l2_input &in, bool init = false, int index = 0); - bool enum_output(v4l2_output &out, bool init = false, int index = 0); - bool enum_audio(v4l2_audio &audio, bool init = false); - bool enum_audout(v4l2_audioout &audout, bool init = false); - bool enum_std(v4l2_standard &std, bool init = false, int index = 0); - bool enum_dv_timings(v4l2_enum_dv_timings &timings, bool init = false, int index = 0); - bool enum_fmt(v4l2_fmtdesc &std, unsigned type, bool init = false, int index = 0); - bool enum_framesizes(v4l2_frmsizeenum &frm, __u32 init_pixfmt = 0, int index = 0); - bool enum_frameintervals(v4l2_frmivalenum &frm, __u32 init_pixfmt = 0, __u32 w = 0, __u32 h = 0, int index = 0); - - bool reqbufs_mmap(v4l2_requestbuffers &reqbuf, __u32 buftype, int count = 0); - bool reqbufs_user(v4l2_requestbuffers &reqbuf, __u32 buftype, int count = 0); - bool dqbuf_mmap(v4l2_buffer &buf, __u32 buftype, bool &again); - bool dqbuf_user(v4l2_buffer &buf, __u32 buftype, bool &again); - bool qbuf(v4l2_buffer &buf); - bool qbuf_mmap(int index, __u32 buftype); - bool qbuf_user(int index, __u32 buftype, void *ptr[], size_t length[]); - bool streamon(__u32 buftype); - bool streamoff(__u32 buftype); - v4l2_fract g_pixel_aspect(unsigned type, unsigned &width, unsigned &height); - bool has_crop(); - bool input_has_crop(); - bool has_compose(); - bool input_has_compose(); - - bool subscribe_event(v4l2_event_subscription &sub); - bool dqevent(v4l2_event &ev); - - bool set_interval(unsigned type, v4l2_fract interval); - bool get_interval(unsigned type, v4l2_fract &interval); -private: - void clear() { error(QString()); } - -private: - int m_fd; - QString m_device; - bool m_useWrapper; // true if using the libv4l2 wrappers - v4l2_capability m_capability; -}; - -#endif diff -Nru v4l-utils-1.0.0+r2263/utils/qv4l2/vbi-tab.h v4l-utils-1.0.0+r2364/utils/qv4l2/vbi-tab.h --- v4l-utils-1.0.0+r2263/utils/qv4l2/vbi-tab.h 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/qv4l2/vbi-tab.h 2014-08-12 09:02:18.000000000 +0000 @@ -22,7 +22,6 @@ #define VBI_TAB_H #include "qv4l2.h" -#include "v4l2-api.h" class QTableWidget; diff -Nru v4l-utils-1.0.0+r2263/utils/rds-ctl/rds-ctl.cpp v4l-utils-1.0.0+r2364/utils/rds-ctl/rds-ctl.cpp --- v4l-utils-1.0.0+r2263/utils/rds-ctl/rds-ctl.cpp 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/rds-ctl/rds-ctl.cpp 2014-08-12 09:02:18.000000000 +0000 @@ -299,14 +299,10 @@ s += "\t\tTuner\n"; if (cap & V4L2_CAP_MODULATOR) s += "\t\tModulator\n"; - if (cap & V4L2_CAP_AUDIO) - s += "\t\tAudio\n"; if (cap & V4L2_CAP_RADIO) s += "\t\tRadio\n"; if (cap & V4L2_CAP_READWRITE) s += "\t\tRead/Write\n"; - if (cap & V4L2_CAP_ASYNCIO) - s += "\t\tAsync I/O\n"; if (cap & V4L2_CAP_STREAMING) s += "\t\tStreaming\n"; if (cap & V4L2_CAP_DEVICE_CAPS) @@ -665,7 +661,7 @@ } if (updated_fields & V4L2_RDS_PTY && handle->valid_fields & V4L2_RDS_PTY) - printf("\nPTY: %0u -> %s",handle->pty, v4l2_rds_get_pty_str(handle)); + printf("\nPTY: %0u -> %s", handle->pty, v4l2_rds_get_pty_str(handle)); if (updated_fields & V4L2_RDS_PTYN && handle->valid_fields & V4L2_RDS_PTYN) { printf("\nPTYN: %s", handle->ptyn); @@ -678,11 +674,12 @@ printf("\nRT: %s", handle->rt); } - if (updated_fields & V4L2_RDS_TP && handle->valid_fields & V4L2_RDS_TP) - printf("\nTP: %s TA: %s", (handle->tp)? "yes":"no", - handle->ta? "yes":"no"); + if ((updated_fields & (V4L2_RDS_TP | V4L2_RDS_TA)) && + (handle->valid_fields & (V4L2_RDS_TP | V4L2_RDS_TA))) + printf("\nTP: %s TA: %s", (handle->tp) ? "yes" : "no", + handle->ta ? "yes" : "no"); if (updated_fields & V4L2_RDS_MS && handle->valid_fields & V4L2_RDS_MS) - printf("\nMS Flag: %s", (handle->ms)? "Music" : "Speech"); + printf("\nMS Flag: %s", (handle->ms) ? "Music" : "Speech"); if (updated_fields & V4L2_RDS_ECC && handle->valid_fields & V4L2_RDS_ECC) printf("\nECC: %X%x, Country: %u -> %s", handle->ecc >> 4, handle->ecc & 0x0f, handle->pi >> 12, @@ -695,7 +692,7 @@ if (updated_fields & V4L2_RDS_ODA && handle->decode_information & V4L2_RDS_ODA) { for (int i = 0; i < handle->rds_oda.size; ++i) - printf("\nODA Group: %02u%c, AID: %08x",handle->rds_oda.oda[i].group_id, + printf("\nODA Group: %02u%c, AID: %08x", handle->rds_oda.oda[i].group_id, handle->rds_oda.oda[i].group_version, handle->rds_oda.oda[i].aid); } if (updated_fields & V4L2_RDS_AF && handle->valid_fields & V4L2_RDS_AF) diff -Nru v4l-utils-1.0.0+r2263/utils/v4l2-compliance/cv4l-helpers.h v4l-utils-1.0.0+r2364/utils/v4l2-compliance/cv4l-helpers.h --- v4l-utils-1.0.0+r2263/utils/v4l2-compliance/cv4l-helpers.h 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/v4l2-compliance/cv4l-helpers.h 2014-08-12 09:02:18.000000000 +0000 @@ -1,139 +1,577 @@ #ifndef _CV4L_HELPERS_H_ #define _CV4L_HELPERS_H_ +#include #include -class cv4l_fmt : public v4l2_format { +#define cv4l_ioctl(cmd, arg) v4l_named_ioctl(g_v4l_fd(), #cmd, cmd, arg) + +class cv4l_fd : v4l_fd { public: - cv4l_fmt() + cv4l_fd() + { + v4l_fd_init(this); + } + cv4l_fd(cv4l_fd *fd) + { + *this = *fd; + } + + __u32 g_type() const { return type; } + void s_type(__u32 type) { v4l_s_type(this, type); } + __u32 g_selection_type() const { return v4l_g_selection_type(this); } + __u32 g_caps() const { return caps; } + int g_fd() const { return fd; } + v4l_fd *g_v4l_fd() { return this; } + bool g_direct() const { return v4l_fd_g_direct(this); } + void s_direct(bool direct) { v4l_fd_s_direct(this, direct); } + bool g_trace() const { return v4l_fd_g_trace(this); } + void s_trace(bool trace) { v4l_fd_s_trace(this, trace); } + + int open(const char *devname, bool non_blocking = false) { return v4l_open(this, devname, non_blocking); } + int close() { return v4l_close(this); } + int reopen(bool non_blocking = false) { return v4l_reopen(this, non_blocking); } + ssize_t read(void *buffer, size_t n) { return v4l_read(this, buffer, n); } + ssize_t write(const void *buffer, size_t n) { return v4l_write(this, buffer, n); } + void *mmap(size_t length, off_t offset) { return v4l_mmap(this, length, offset); } + int munmap(void *start, size_t length) { return v4l_munmap(this, start, length); } + + bool has_vid_cap() const { return v4l_has_vid_cap(this); } + bool has_vid_out() const { return v4l_has_vid_out(this); } + bool has_vid_m2m() const { return v4l_has_vid_m2m(this); } + bool has_vid_mplane() const { return v4l_has_vid_mplane(this); } + bool has_overlay_cap() const { return v4l_has_overlay_cap(this); } + bool has_overlay_out() const { return v4l_has_overlay_out(this); } + bool has_raw_vbi_cap() const { return v4l_has_raw_vbi_cap(this); } + bool has_sliced_vbi_cap() const { return v4l_has_sliced_vbi_cap(this); } + bool has_vbi_cap() const { return v4l_has_vbi_cap(this); } + bool has_raw_vbi_out() const { return v4l_has_raw_vbi_out(this); } + bool has_sliced_vbi_out() const { return v4l_has_sliced_vbi_out(this); } + bool has_vbi_out() const { return v4l_has_vbi_out(this); } + bool has_vbi() const { return v4l_has_vbi(this); } + bool has_radio_rx() const { return v4l_has_radio_rx(this); } + bool has_radio_tx() const { return v4l_has_radio_tx(this); } + bool has_rds_cap() const { return v4l_has_rds_cap(this); } + bool has_rds_out() const { return v4l_has_rds_out(this); } + bool has_sdr_cap() const { return v4l_has_sdr_cap(this); } + bool has_hwseek() const { return v4l_has_hwseek(this); } + bool has_rw() const { return v4l_has_rw(this); } + bool has_streaming() const { return v4l_has_streaming(this); } + bool has_ext_pix_format() const { return v4l_has_ext_pix_format(this); } + + void querycap(v4l2_capability &cap) + { + cap = this->cap; + } + + int queryctrl(v4l2_queryctrl &qc) + { + return cv4l_ioctl(VIDIOC_QUERYCTRL, &qc); + } + + int querymenu(v4l2_querymenu &qm) + { + return cv4l_ioctl(VIDIOC_QUERYMENU, &qm); + } + + int query_ext_ctrl(v4l2_query_ext_ctrl &qec, bool next_ctrl = false, bool next_compound = false) + { + return v4l_query_ext_ctrl(this, &qec, next_ctrl, next_compound); + } + + int g_ctrl(v4l2_control &ctrl) + { + return cv4l_ioctl(VIDIOC_G_CTRL, &ctrl); + } + + int s_ctrl(v4l2_control &ctrl) + { + return cv4l_ioctl(VIDIOC_S_CTRL, &ctrl); + } + + int g_ext_ctrls(v4l2_ext_controls &ec) + { + return v4l_g_ext_ctrls(this, &ec); + } + + int try_ext_ctrls(v4l2_ext_controls &ec) + { + return v4l_try_ext_ctrls(this, &ec); + } + + int s_ext_ctrls(v4l2_ext_controls &ec) + { + return v4l_s_ext_ctrls(this, &ec); + } + + int g_fmt(v4l2_format &fmt, unsigned type = 0) + { + return v4l_g_fmt(this, &fmt, type); + } + + int try_fmt(v4l2_format &fmt) + { + return v4l_try_fmt(this, &fmt); + } + + int s_fmt(v4l2_format &fmt) + { + return v4l_s_fmt(this, &fmt); + } + + int g_selection(v4l2_selection &sel) + { + return v4l_g_selection(this, &sel); + } + + int s_selection(v4l2_selection &sel) + { + return v4l_s_selection(this, &sel); + } + + int g_tuner(v4l2_tuner &tuner, unsigned index = 0) + { + memset(&tuner, 0, sizeof(tuner)); + tuner.index = index; + int ret = cv4l_ioctl(VIDIOC_G_TUNER, &tuner); + if (ret == 0 && tuner.rangehigh > INT_MAX) + tuner.rangehigh = INT_MAX; + return ret; + } + + int s_tuner(v4l2_tuner &tuner) + { + return cv4l_ioctl(VIDIOC_S_TUNER, &tuner); + } + + int g_modulator(v4l2_modulator &modulator) + { + memset(&modulator, 0, sizeof(modulator)); + return cv4l_ioctl(VIDIOC_G_MODULATOR, &modulator); + } + + int s_modulator(v4l2_modulator &modulator) + { + return cv4l_ioctl(VIDIOC_S_MODULATOR, &modulator); + } + + int enum_input(v4l2_input &in, bool init = false, int index = 0) + { + if (init) { + memset(&in, 0, sizeof(in)); + in.index = index; + } else { + in.index++; + } + return cv4l_ioctl(VIDIOC_ENUMINPUT, &in); + } + + int enum_output(v4l2_output &out, bool init = false, int index = 0) + { + if (init) { + memset(&out, 0, sizeof(out)); + out.index = index; + } else { + out.index++; + } + return cv4l_ioctl(VIDIOC_ENUMOUTPUT, &out); + } + + int enum_audio(v4l2_audio &audio, bool init = false, int index = 0) + { + if (init) { + memset(&audio, 0, sizeof(audio)); + audio.index = index; + } else { + audio.index++; + } + return cv4l_ioctl(VIDIOC_ENUMAUDIO, &audio); + } + + int enum_audout(v4l2_audioout &audout, bool init = false, int index = 0) + { + if (init) { + memset(&audout, 0, sizeof(audout)); + audout.index = index; + } else { + audout.index++; + } + return cv4l_ioctl(VIDIOC_ENUMAUDOUT, &audout); + } + + bool has_crop() + { + v4l2_selection sel; + + memset(&sel, 0, sizeof(sel)); + sel.type = g_selection_type(); + sel.target = V4L2_SEL_TGT_CROP; + return g_selection(sel) != ENOTTY; + } + + bool has_compose() + { + v4l2_selection sel; + + memset(&sel, 0, sizeof(sel)); + sel.type = g_selection_type(); + sel.target = V4L2_SEL_TGT_COMPOSE; + return g_selection(sel) != ENOTTY; + } + + bool cur_io_has_crop() + { + v4l2_selection sel; + + memset(&sel, 0, sizeof(sel)); + sel.type = g_selection_type(); + sel.target = V4L2_SEL_TGT_CROP; + return g_selection(sel) == 0; + } + + bool cur_io_has_compose() + { + v4l2_selection sel; + + memset(&sel, 0, sizeof(sel)); + sel.type = g_selection_type(); + sel.target = V4L2_SEL_TGT_COMPOSE; + return g_selection(sel) == 0; + } + + int subscribe_event(v4l2_event_subscription &sub) + { + return cv4l_ioctl(VIDIOC_SUBSCRIBE_EVENT, &sub); + } + + int dqevent(v4l2_event &ev) + { + return cv4l_ioctl(VIDIOC_DQEVENT, &ev); + } + + int g_input(__u32 &input) + { + return cv4l_ioctl(VIDIOC_G_INPUT, &input); + } + + int s_input(__u32 input) + { + return cv4l_ioctl(VIDIOC_S_INPUT, &input); + } + + int g_output(__u32 &output) + { + return cv4l_ioctl(VIDIOC_G_OUTPUT, &output); + } + + int s_output(__u32 output) + { + return cv4l_ioctl(VIDIOC_S_OUTPUT, &output); + } + + int g_audio(v4l2_audio &audio) + { + memset(&audio, 0, sizeof(audio)); + return cv4l_ioctl(VIDIOC_G_AUDIO, &audio); + } + + int s_audio(__u32 input) + { + v4l2_audio audio; + + memset(&audio, 0, sizeof(audio)); + audio.index = input; + return cv4l_ioctl(VIDIOC_S_AUDIO, &audio); + } + + int g_audout(v4l2_audioout &audout) { - fd = NULL; - type = 0; - memset(&fmt, 0, sizeof(fmt)); + memset(&audout, 0, sizeof(audout)); + return cv4l_ioctl(VIDIOC_G_AUDOUT, &audout); } - cv4l_fmt(v4l_fd *_fd, unsigned _type = 0) + + int s_audout(__u32 output) { - fd = _fd; - memset(&fmt, 0, sizeof(fmt)); - if (_type == 0) - type = v4l_buf_type_g_vid_cap(fd); - else - type = _type; + v4l2_audioout audout; + + memset(&audout, 0, sizeof(audout)); + audout.index = output; + return cv4l_ioctl(VIDIOC_S_AUDOUT, &audout); } - cv4l_fmt(v4l_fd *_fd, const v4l2_format &_fmt) + + int g_std(v4l2_std_id &std) { - fd = _fd; - type = _fmt.type; - fmt = _fmt.fmt; + return cv4l_ioctl(VIDIOC_G_STD, &std); } - cv4l_fmt(const cv4l_fmt &_fmt) + + int s_std(v4l2_std_id std) { - fd = _fmt.fd; - type = _fmt.type; - fmt = _fmt.fmt; + return cv4l_ioctl(VIDIOC_S_STD, &std); } - void init(v4l_fd *_fd, unsigned _type = 0) + + int query_std(v4l2_std_id &std) { - fd = _fd; - memset(&fmt, 0, sizeof(fmt)); - if (_type == 0) - type = v4l_buf_type_g_vid_cap(fd); - else - type = _type; + return cv4l_ioctl(VIDIOC_QUERYSTD, &std); } - void init(v4l_fd *_fd, const v4l2_format &_fmt) + + int g_dv_timings(v4l2_dv_timings &timings) { - fd = _fd; - type = _fmt.type; - fmt = _fmt.fmt; + return cv4l_ioctl(VIDIOC_G_DV_TIMINGS, &timings); } - int g_fmt(unsigned _type = 0) + + int s_dv_timings(v4l2_dv_timings &timings) { - return v4l_g_fmt(fd, this, _type ? _type : type); + return cv4l_ioctl(VIDIOC_S_DV_TIMINGS, &timings); } - int try_fmt() + + int query_dv_timings(v4l2_dv_timings &timings) { - return v4l_try_fmt(fd, this); + return cv4l_ioctl(VIDIOC_QUERY_DV_TIMINGS, &timings); } - int s_fmt() + + int g_frequency(v4l2_frequency &freq, unsigned index = 0) { - return v4l_s_fmt(fd, this); + memset(&freq, 0, sizeof(freq)); + freq.tuner = index; + freq.type = V4L2_TUNER_ANALOG_TV; + return cv4l_ioctl(VIDIOC_G_FREQUENCY, &freq); } - void s_width(__u32 width) + + int s_frequency(v4l2_frequency &freq) { - v4l_format_s_width(this, width); + return cv4l_ioctl(VIDIOC_S_FREQUENCY, &freq); } - __u32 g_width() + + int g_priority(__u32 &prio) { - return v4l_format_g_width(this); + return cv4l_ioctl(VIDIOC_G_PRIORITY, &prio); } - void s_height(__u32 height) + + int s_priority(__u32 prio = V4L2_PRIORITY_DEFAULT) { - v4l_format_s_height(this, height); + return cv4l_ioctl(VIDIOC_S_PRIORITY, &prio); } - __u32 g_height() + + int streamon(__u32 type = 0) { - return v4l_format_g_height(this); + if (type == 0) + type = g_type(); + return cv4l_ioctl(VIDIOC_STREAMON, &type); } - void s_pixelformat(__u32 pixelformat) + + int streamoff(__u32 type = 0) { - v4l_format_s_pixelformat(this, pixelformat); + if (type == 0) + type = g_type(); + return cv4l_ioctl(VIDIOC_STREAMOFF, &type); } - __u32 g_pixelformat() + + int querybuf(v4l_buffer &buf, unsigned index) { - return v4l_format_g_pixelformat(this); + return v4l_buffer_querybuf(this, &buf, index); } - void s_field(unsigned field) + + int dqbuf(v4l_buffer &buf) { - v4l_format_s_field(this, field); + return v4l_buffer_dqbuf(this, &buf); } - unsigned g_field() + + int qbuf(v4l_buffer &buf) { - return v4l_format_g_field(this); + return v4l_buffer_qbuf(this, &buf); } - unsigned g_first_field(v4l2_std_id std) + + int prepare_buf(v4l_buffer &buf) { - return v4l_format_g_first_field(this, std); + return v4l_buffer_prepare_buf(this, &buf); } - unsigned g_flds_per_frm() + + int enum_std(v4l2_standard &std, bool init = false, int index = 0) { - return v4l_format_g_flds_per_frm(this); + if (init) { + memset(&std, 0, sizeof(std)); + std.index = index; + } else { + std.index++; + } + return cv4l_ioctl(VIDIOC_ENUMSTD, &std); } - void s_colorspace(unsigned colorspace) + + int enum_dv_timings(v4l2_enum_dv_timings &timings, bool init = false, int index = 0) { - v4l_format_s_colorspace(this, colorspace); + if (init) { + memset(&timings, 0, sizeof(timings)); + timings.index = index; + } else { + timings.index++; + } + return cv4l_ioctl(VIDIOC_ENUM_DV_TIMINGS, &timings); } - unsigned g_colorspace() + + int enum_fmt(v4l2_fmtdesc &fmt, bool init = false, int index = 0, unsigned type = 0) { - return v4l_format_g_colorspace(this); + if (init) { + memset(&fmt, 0, sizeof(fmt)); + fmt.index = index; + } else { + fmt.index++; + } + fmt.type = type ? type : g_type(); + return cv4l_ioctl(VIDIOC_ENUM_FMT, &fmt); } - void s_num_planes(__u8 num_planes) + + int enum_framesizes(v4l2_frmsizeenum &frm, __u32 init_pixfmt = 0, int index = 0) { - v4l_format_s_num_planes(this, num_planes); + if (init_pixfmt) { + memset(&frm, 0, sizeof(frm)); + frm.pixel_format = init_pixfmt; + frm.index = index; + } else { + frm.index++; + } + return cv4l_ioctl(VIDIOC_ENUM_FRAMESIZES, &frm); } - __u8 g_num_planes() + + int enum_frameintervals(v4l2_frmivalenum &frm, __u32 init_pixfmt = 0, __u32 w = 0, __u32 h = 0, int index = 0) { - return v4l_format_g_num_planes(this); + if (init_pixfmt) { + memset(&frm, 0, sizeof(frm)); + frm.pixel_format = init_pixfmt; + frm.width = w; + frm.height = h; + frm.index = index; + } else { + frm.index++; + } + return cv4l_ioctl(VIDIOC_ENUM_FRAMEINTERVALS, &frm); } - void s_bytesperline(unsigned plane, __u32 bytesperline) + + int set_interval(v4l2_fract interval, unsigned type = 0) { - v4l_format_s_bytesperline(this, plane, bytesperline); + v4l2_streamparm parm; + + parm.type = type ? type : g_type(); + memset(parm.parm.capture.reserved, 0, sizeof(parm.parm.capture.reserved)); + if (cv4l_ioctl(VIDIOC_G_PARM, &parm) || + !(parm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME)) + return -1; + + parm.parm.capture.timeperframe = interval; + + return cv4l_ioctl(VIDIOC_S_PARM, &parm); + } + + int get_interval(v4l2_fract &interval, unsigned type = 0) + { + v4l2_streamparm parm; + + parm.type = type ? type : g_type(); + memset(parm.parm.capture.reserved, 0, sizeof(parm.parm.capture.reserved)); + if (cv4l_ioctl(VIDIOC_G_PARM, &parm) == 0 && + (parm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME)) { + interval = parm.parm.capture.timeperframe; + return 0; + } + + return -1; + } + + int encoder_cmd(v4l2_encoder_cmd &cmd) + { + return cv4l_ioctl(VIDIOC_ENCODER_CMD, &cmd); + } + + int try_encoder_cmd(v4l2_encoder_cmd &cmd) + { + return cv4l_ioctl(VIDIOC_TRY_ENCODER_CMD, &cmd); + } + + int decoder_cmd(v4l2_decoder_cmd &cmd) + { + return cv4l_ioctl(VIDIOC_DECODER_CMD, &cmd); } - __u32 g_bytesperline(unsigned plane) + + int try_decoder_cmd(v4l2_decoder_cmd &cmd) { - return v4l_format_g_bytesperline(this, plane); + return cv4l_ioctl(VIDIOC_TRY_DECODER_CMD, &cmd); + } + + v4l2_fract g_pixel_aspect(unsigned &width, unsigned &height, unsigned type = 0) + { + v4l2_cropcap ratio; + v4l2_dv_timings timings; + v4l2_std_id std; + static const v4l2_fract square = { 1, 1 }; + static const v4l2_fract hz50 = { 11, 12 }; + static const v4l2_fract hz60 = { 11, 10 }; + + ratio.type = type ? type : g_selection_type(); + if (cv4l_ioctl(VIDIOC_CROPCAP, &ratio) == 0) { + width = ratio.defrect.width; + height = ratio.defrect.height; + if (ratio.pixelaspect.numerator && ratio.pixelaspect.denominator) + return ratio.pixelaspect; + } + + width = 720; + height = 480; + if (!g_std(std)) { + if (std & V4L2_STD_525_60) + return hz60; + if (std & V4L2_STD_625_50) { + height = 576; + return hz50; + } + } + + if (!g_dv_timings(timings)) { + width = timings.bt.width; + height = timings.bt.height; + if (width == 720 && height == 480) + return hz60; + if (width == 720 && height == 576) { + height = 576; + return hz50; + } + return square; + } + width = 0; + height = 0; + return square; } - void s_sizeimage(unsigned plane, __u32 sizeimage) +}; + +class cv4l_fmt : public v4l2_format { +public: + cv4l_fmt(unsigned _type = 0) { - v4l_format_s_sizeimage(this, plane, sizeimage); + v4l_format_init(this, _type); } - __u32 g_sizeimage(unsigned plane) + cv4l_fmt(const v4l2_format &_fmt) { - return v4l_format_g_sizeimage(this, plane); + *this = _fmt; } -protected: - v4l_fd *fd; + __u32 g_type() { return type; } + void s_type(unsigned type) { v4l_format_init(this, type); } + __u32 g_width() { return v4l_format_g_width(this); } + void s_width(__u32 width) { v4l_format_s_width(this, width); } + __u32 g_height() { return v4l_format_g_height(this); } + void s_height(__u32 height) { v4l_format_s_height(this, height); } + __u32 g_pixelformat() { return v4l_format_g_pixelformat(this); } + void s_pixelformat(__u32 pixelformat) { v4l_format_s_pixelformat(this, pixelformat); } + unsigned g_colorspace() { return v4l_format_g_colorspace(this); } + void s_colorspace(unsigned colorspace) { v4l_format_s_colorspace(this, colorspace); } + __u8 g_num_planes() { return v4l_format_g_num_planes(this); } + void s_num_planes(__u8 num_planes) { v4l_format_s_num_planes(this, num_planes); } + __u32 g_bytesperline(unsigned plane = 0) { return v4l_format_g_bytesperline(this, plane); } + void s_bytesperline(__u32 bytesperline, unsigned plane = 0) { v4l_format_s_bytesperline(this, bytesperline, plane); } + __u32 g_sizeimage(unsigned plane = 0) { return v4l_format_g_sizeimage(this, plane); } + void s_sizeimage(__u32 sizeimage, unsigned plane = 0) { v4l_format_s_sizeimage(this, sizeimage, plane); } + unsigned g_field() { return v4l_format_g_field(this); } + void s_field(unsigned field) { v4l_format_s_field(this, field); } + unsigned g_first_field(v4l2_std_id std) { return v4l_format_g_first_field(this, std); } + unsigned g_flds_per_frm() { return v4l_format_g_flds_per_frm(this); } }; class cv4l_buffer; @@ -141,99 +579,86 @@ class cv4l_queue : v4l_queue { friend class cv4l_buffer; public: - cv4l_queue(v4l_fd *_fd, unsigned type = V4L2_BUF_TYPE_VIDEO_CAPTURE, - unsigned memory = V4L2_MEMORY_MMAP) + cv4l_queue(unsigned type = V4L2_BUF_TYPE_VIDEO_CAPTURE, + unsigned memory = V4L2_MEMORY_MMAP) { - fd = _fd; v4l_queue_init(this, type, memory); } - virtual ~cv4l_queue() - { - if (fd->fd != -1) - v4l_queue_free(fd, this); - } - void init(unsigned type, unsigned memory) { - if (fd->fd != -1) - v4l_queue_free(fd, this); v4l_queue_init(this, type, memory); } unsigned g_type() const { return v4l_queue_g_type(this); } unsigned g_memory() const { return v4l_queue_g_memory(this); } - bool is_planar() const { return v4l_queue_is_planar(this); } - bool is_output() const { return v4l_queue_is_output(this); } - bool is_capture() const { return v4l_queue_is_capture(this); } - bool is_video() const { return v4l_queue_is_video(this); } - bool is_vbi() const { return v4l_queue_is_vbi(this); } - bool is_sliced_vbi() const { return v4l_queue_is_sliced_vbi(this); } - bool is_sdr() const { return v4l_queue_is_sdr(this); } unsigned g_buffers() const { return v4l_queue_g_buffers(this); } unsigned g_num_planes() const { return v4l_queue_g_num_planes(this); } unsigned g_length(unsigned plane) const { return v4l_queue_g_length(this, plane); } unsigned g_mem_offset(unsigned index, unsigned plane) const { return v4l_queue_g_mem_offset(this, index, plane); } - void s_mmapping(unsigned index, unsigned plane, void *m) { v4l_queue_s_mmapping(this, index, plane, m); } void *g_mmapping(unsigned index, unsigned plane) const { return v4l_queue_g_mmapping(this, index, plane); } - void s_userptr(unsigned index, unsigned plane, void *m) { v4l_queue_s_userptr(this, index, plane, m); } + void s_mmapping(unsigned index, unsigned plane, void *m) { v4l_queue_s_mmapping(this, index, plane, m); } void *g_userptr(unsigned index, unsigned plane) const { return v4l_queue_g_userptr(this, index, plane); } - void s_fd(unsigned index, unsigned plane, int fd) { v4l_queue_s_fd(this, index, plane, fd); } + void s_userptr(unsigned index, unsigned plane, void *m) { v4l_queue_s_userptr(this, index, plane, m); } + void *g_dataptr(unsigned index, unsigned plane) const { return v4l_queue_g_dataptr(this, index, plane); } int g_fd(unsigned index, unsigned plane) const { return v4l_queue_g_fd(this, index, plane); } + void s_fd(unsigned index, unsigned plane, int fd) { v4l_queue_s_fd(this, index, plane, fd); } - int reqbufs(unsigned count = 0) + int reqbufs(cv4l_fd *fd, unsigned count = 0) { - return v4l_queue_reqbufs(fd, this, count); + return v4l_queue_reqbufs(fd->g_v4l_fd(), this, count); } - bool has_create_bufs() const + bool has_create_bufs(cv4l_fd *fd) const { - return v4l_queue_has_create_bufs(fd, this); + return v4l_queue_has_create_bufs(fd->g_v4l_fd(), this); } - int create_bufs(unsigned count, const v4l2_format *fmt = NULL) + int create_bufs(cv4l_fd *fd, unsigned count, const v4l2_format *fmt = NULL) { - return v4l_queue_create_bufs(fd, this, count, fmt); + return v4l_queue_create_bufs(fd->g_v4l_fd(), this, count, fmt); } - int streamon() + int mmap_bufs(cv4l_fd *fd, unsigned from = 0) { - return v4l_queue_streamon(fd, this); + return v4l_queue_mmap_bufs(fd->g_v4l_fd(), this, from); } - int streamoff() + int munmap_bufs(cv4l_fd *fd) { - return v4l_queue_streamoff(fd, this); + return v4l_queue_munmap_bufs(fd->g_v4l_fd(), this); } - int mmap_bufs(unsigned from = 0) + int alloc_bufs(cv4l_fd *fd, unsigned from = 0) { - return v4l_queue_mmap_bufs(fd, this, from); + return v4l_queue_alloc_bufs(fd->g_v4l_fd(), this, from); } - int munmap_bufs() + int free_bufs() { - return v4l_queue_munmap_bufs(fd, this); + return v4l_queue_free_bufs(this); } - int alloc_bufs(unsigned from = 0) + int obtain_bufs(cv4l_fd *fd, unsigned from = 0) { - return v4l_queue_alloc_bufs(fd, this, from); + return v4l_queue_obtain_bufs(fd->g_v4l_fd(), this, from); } - int free_bufs() + int release_bufs(cv4l_fd *fd) { - return v4l_queue_free_bufs(this); + return v4l_queue_release_bufs(fd->g_v4l_fd(), this); } - bool has_expbuf() + bool has_expbuf(cv4l_fd *fd) { - return v4l_queue_has_expbuf(fd); + return v4l_queue_has_expbuf(fd->g_v4l_fd()); } - int export_bufs() + int export_bufs(cv4l_fd *fd) { - return v4l_queue_export_bufs(fd, this); + return v4l_queue_export_bufs(fd->g_v4l_fd(), this); } void close_exported_fds() { v4l_queue_close_exported_fds(this); } - void buffer_init(struct v4l_buffer *buf, unsigned index) const + void free(cv4l_fd *fd) { - v4l_queue_buffer_init(this, buf, index); + v4l_queue_free(fd->g_v4l_fd(), this); } - -protected: - v4l_fd *fd; + void buffer_init(v4l_buffer &buf, unsigned index) const + { + v4l_queue_buffer_init(this, &buf, index); + } + int queue_all(cv4l_fd *fd); }; class cv4l_buffer : public v4l_buffer { @@ -251,20 +676,22 @@ init(b); } virtual ~cv4l_buffer() {} + void init(unsigned type = 0, unsigned memory = 0, unsigned index = 0) { v4l_buffer_init(this, type, memory, index); } void init(const cv4l_queue &q, unsigned index = 0) { - q.buffer_init(this, index); + q.buffer_init(*this, index); } void init(const cv4l_buffer &b) { *this = b; - if (is_planar()) + if (v4l_type_is_planar(g_type())) buf.m.planes = planes; } + __u32 g_index() const { return v4l_buffer_g_index(this); } void s_index(unsigned index) { v4l_buffer_s_index(this, index); } unsigned g_type() const { return v4l_buffer_g_type(this); } @@ -274,6 +701,20 @@ void or_flags(__u32 flags) { v4l_buffer_or_flags(this, flags); } unsigned g_field() const { return v4l_buffer_g_field(this); } void s_field(unsigned field) { v4l_buffer_s_field(this, field); } + + unsigned g_num_planes() const { return v4l_buffer_g_num_planes(this); } + __u32 g_mem_offset(unsigned plane = 0) const { return v4l_buffer_g_mem_offset(this, plane); } + void *g_userptr(unsigned plane = 0) const { return v4l_buffer_g_userptr(this, plane); } + void s_userptr(void *userptr, unsigned plane = 0) { v4l_buffer_s_userptr(this, plane, userptr); } + int g_fd(unsigned plane = 0) const { return v4l_buffer_g_fd(this, plane); } + void s_fd(int fd, unsigned plane = 0) { v4l_buffer_s_fd(this, plane, fd); } + __u32 g_bytesused(unsigned plane = 0) const { return v4l_buffer_g_bytesused(this, plane); } + void s_bytesused(__u32 bytesused, unsigned plane = 0) { v4l_buffer_s_bytesused(this, plane, bytesused); } + __u32 g_data_offset(unsigned plane = 0) const { return v4l_buffer_g_data_offset(this, plane); } + void s_data_offset(__u32 data_offset, unsigned plane = 0) { v4l_buffer_s_data_offset(this, plane, data_offset); } + __u32 g_length(unsigned plane = 0) const { return v4l_buffer_g_length(this, plane); } + void s_length(unsigned length, unsigned plane = 0) { return v4l_buffer_s_length(this, plane, length); } + __u32 g_sequence() const { return v4l_buffer_g_sequence(this); } __u32 g_timestamp_type() const { return v4l_buffer_g_timestamp_type(this); } __u32 g_timestamp_src() const { return v4l_buffer_g_timestamp_src(this); } @@ -285,90 +726,19 @@ void s_timestamp_clock() { v4l_buffer_s_timestamp_clock(this); } const v4l2_timecode &g_timecode() const { return *v4l_buffer_g_timecode(this); } void s_timecode(const v4l2_timecode &tc) { v4l_buffer_s_timecode(this, &tc); } - __u32 g_mem_offset(unsigned plane = 0) const - { - return v4l_buffer_g_mem_offset(this, plane); - } - void *g_userptr(unsigned plane = 0) const - { - return v4l_buffer_g_userptr(this, plane); - } - int g_fd(unsigned plane = 0) const - { - return v4l_buffer_g_fd(this, plane); - } - __u32 g_bytesused(unsigned plane = 0) const - { - return v4l_buffer_g_bytesused(this, plane); - } - __u32 g_length(unsigned plane = 0) const - { - return v4l_buffer_g_length(this, plane); - } - __u32 g_data_offset(unsigned plane = 0) const - { - return v4l_buffer_g_data_offset(this, plane); - } - void s_userptr(void *userptr, unsigned plane = 0) - { - v4l_buffer_s_userptr(this, plane, userptr); - } - void s_fd(int fd, unsigned plane = 0) - { - v4l_buffer_s_fd(this, plane, fd); - } - void s_bytesused(__u32 bytesused, unsigned plane = 0) - { - v4l_buffer_s_bytesused(this, plane, bytesused); - } - void s_data_offset(__u32 data_offset, unsigned plane = 0) - { - v4l_buffer_s_data_offset(this, plane, data_offset); - } - bool is_planar() const { return v4l_buffer_is_planar(this); } - bool is_output() const { return v4l_buffer_is_output(this); } - bool is_capture() const { return v4l_buffer_is_capture(this); } - bool is_video() const { return v4l_buffer_is_video(this); } - bool is_vbi() const { return v4l_buffer_is_vbi(this); } - bool is_sliced_vbi() const { return v4l_buffer_is_sliced_vbi(this); } - bool is_sdr() const { return v4l_buffer_is_sdr(this); } - unsigned g_num_planes() const - { - return v4l_buffer_g_num_planes(this); - } +}; - int querybuf(v4l_fd *fd, unsigned index) - { - return v4l_buffer_querybuf(fd, this, index); - } - int querybuf(const cv4l_queue &q, unsigned index) - { - return querybuf(q.fd, index); - } - int dqbuf(v4l_fd *fd) - { - return v4l_buffer_dqbuf(fd, this); - } - int dqbuf(const cv4l_queue &q) - { - return dqbuf(q.fd); - } - int qbuf(v4l_fd *fd) - { - return v4l_buffer_qbuf(fd, this); +inline int cv4l_queue::queue_all(cv4l_fd *fd) +{ + cv4l_buffer buf; + + for (unsigned i = 0; i < g_buffers(); i++) { + buf.init(*this, i); + int ret = fd->qbuf(buf); + if (ret) + return ret; } - int qbuf(const cv4l_queue &q) - { - return qbuf(q.fd); - } - int prepare_buf(v4l_fd *fd) - { - return v4l_buffer_prepare_buf(fd, this); - } - int prepare_buf(const cv4l_queue &q) - { - return prepare_buf(q.fd); - } -}; + return 0; +} #endif diff -Nru v4l-utils-1.0.0+r2263/utils/v4l2-compliance/v4l2-compliance.cpp v4l-utils-1.0.0+r2364/utils/v4l2-compliance/v4l2-compliance.cpp --- v4l-utils-1.0.0+r2263/utils/v4l2-compliance/v4l2-compliance.cpp 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/v4l2-compliance/v4l2-compliance.cpp 2014-08-12 09:02:18.000000000 +0000 @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -69,7 +68,6 @@ // Globals bool show_info; bool show_warnings = true; -bool wrapper; int kernel_version; unsigned warnings; @@ -129,38 +127,6 @@ exit(0); } -static void v4l_fd_test_init(struct v4l_fd *f, int fd) -{ - struct v4l2_capability cap; - - f->fd = fd; - f->ioctl = test_ioctl; - f->mmap = test_mmap; - f->munmap = test_munmap; - f->trace = options[OptTrace]; - f->caps = v4l_querycap(f, &cap) ? 0 : v4l_capability_g_caps(&cap); -} - -int doioctl_name(struct node *node, unsigned long int request, void *parm, - const char *name) -{ - int retval; - int e; - - errno = 0; - retval = test_ioctl(node->vfd.fd, request, parm); - e = errno; - if (options[OptTrace]) - printf("\t\t%s returned %d (%s)\n", name, retval, strerror(e)); - if (retval == 0) - return 0; - if (retval != -1) { - fail("%s returned %d instead of 0 or -1\n", name, retval); - return -1; - } - return e; -} - std::string cap2s(unsigned cap) { std::string s; @@ -197,6 +163,8 @@ s += "\t\tSDR Capture\n"; if (cap & V4L2_CAP_TUNER) s += "\t\tTuner\n"; + if (cap & V4L2_CAP_HW_FREQ_SEEK) + s += "\t\tHW Frequency Seek\n"; if (cap & V4L2_CAP_MODULATOR) s += "\t\tModulator\n"; if (cap & V4L2_CAP_AUDIO) @@ -209,6 +177,8 @@ s += "\t\tAsync I/O\n"; if (cap & V4L2_CAP_STREAMING) s += "\t\tStreaming\n"; + if (cap & V4L2_CAP_EXT_PIX_FORMAT) + s += "\t\tExtended Pix Format\n"; if (cap & V4L2_CAP_DEVICE_CAPS) s += "\t\tDevice Capabilities\n"; return s; @@ -345,6 +315,10 @@ fail_on_test(dcaps & V4L2_CAP_DEVICE_CAPS); fail_on_test(dcaps & ~caps); fail_on_test(!(dcaps & caps)); + // set by the core, so this really should always be there + // for a modern driver for both caps and dcaps + fail_on_test(!(caps & V4L2_CAP_EXT_PIX_FORMAT)); + //fail_on_test(!(dcaps & V4L2_CAP_EXT_PIX_FORMAT)); fail_on_test(node->is_video && !(dcaps & video_caps)); fail_on_test(node->is_radio && !(dcaps & radio_caps)); // V4L2_CAP_AUDIO is invalid for radio and sdr @@ -438,7 +412,7 @@ struct v4l2_frequency f = { 0 }; unsigned freq_caps; - if (node->caps & V4L2_CAP_MODULATOR) { + if (node->g_caps() & V4L2_CAP_MODULATOR) { struct v4l2_modulator m = { 0 }; doioctl(node, VIDIOC_G_MODULATOR, &m); @@ -491,16 +465,16 @@ int main(int argc, char **argv) { int i; - struct node node = { -1 }; - struct node video_node = { -1 }; - struct node video_node2 = { -1 }; - struct node vbi_node = { -1 }; - struct node vbi_node2 = { -1 }; - struct node radio_node = { -1 }; - struct node radio_node2 = { -1 }; - struct node sdr_node = { -1 }; - struct node sdr_node2 = { -1 }; - struct node expbuf_node = { -1 }; + struct node node; + struct node video_node; + struct node video_node2; + struct node vbi_node; + struct node vbi_node2; + struct node radio_node; + struct node radio_node2; + struct node sdr_node; + struct node sdr_node2; + struct node expbuf_node; /* command args */ int ch; @@ -624,7 +598,7 @@ usage(); return 1; } - wrapper = options[OptUseWrapper]; + bool direct = !options[OptUseWrapper]; struct utsname uts; int v1, v2, v3; @@ -639,105 +613,99 @@ video_device = "/dev/video0"; if (video_device) { - fd = test_open(video_device, O_RDWR); + video_node.s_trace(options[OptTrace]); + video_node.s_direct(direct); + fd = video_node.open(video_device, false); if (fd < 0) { fprintf(stderr, "Failed to open %s: %s\n", video_device, strerror(errno)); exit(1); } - v4l_fd_test_init(&video_node.vfd, fd); } if (vbi_device) { - fd = test_open(vbi_device, O_RDWR); + vbi_node.s_trace(options[OptTrace]); + vbi_node.s_direct(direct); + fd = vbi_node.open(vbi_device, false); if (fd < 0) { fprintf(stderr, "Failed to open %s: %s\n", vbi_device, strerror(errno)); exit(1); } - v4l_fd_test_init(&vbi_node.vfd, fd); } if (radio_device) { - fd = test_open(radio_device, O_RDWR); + radio_node.s_trace(options[OptTrace]); + radio_node.s_direct(direct); + fd = radio_node.open(radio_device, false); if (fd < 0) { fprintf(stderr, "Failed to open %s: %s\n", radio_device, strerror(errno)); exit(1); } - v4l_fd_test_init(&radio_node.vfd, fd); } if (sdr_device) { - fd = test_open(sdr_device, O_RDWR); + sdr_node.s_trace(options[OptTrace]); + sdr_node.s_direct(direct); + fd = sdr_node.open(sdr_device, false); if (fd < 0) { fprintf(stderr, "Failed to open %s: %s\n", sdr_device, strerror(errno)); exit(1); } - v4l_fd_test_init(&sdr_node.vfd, fd); } if (expbuf_device) { - fd = open(expbuf_device, O_RDWR); + expbuf_node.s_trace(options[OptTrace]); + expbuf_node.s_direct(true); + fd = expbuf_node.open(expbuf_device, false); if (fd < 0) { fprintf(stderr, "Failed to open %s: %s\n", expbuf_device, strerror(errno)); exit(1); } - v4l_fd_init(&expbuf_node.vfd, fd); } - if (video_node.vfd.fd >= 0) { - node.vfd = video_node.vfd; + if (video_node.g_fd() >= 0) { + node = video_node; device = video_device; node.is_video = true; - } else if (vbi_node.vfd.fd >= 0) { - node.vfd = vbi_node.vfd; + } else if (vbi_node.g_fd() >= 0) { + node = vbi_node; device = vbi_device; node.is_vbi = true; - } else if (radio_node.vfd.fd >= 0) { - node.vfd = radio_node.vfd; + } else if (radio_node.g_fd() >= 0) { + node = radio_node; device = radio_device; node.is_radio = true; - } else if (sdr_node.vfd.fd >= 0) { - node.vfd = sdr_node.vfd; + } else if (sdr_node.g_fd() >= 0) { + node = sdr_node; device = sdr_device; node.is_sdr = true; } node.device = device; doioctl(&node, VIDIOC_QUERYCAP, &vcap); - if (vcap.capabilities & V4L2_CAP_DEVICE_CAPS) - node.caps = vcap.device_caps; - else - node.caps = vcap.capabilities; - if (node.caps & (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE | + if (node.g_caps() & (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_SLICED_VBI_CAPTURE)) node.has_inputs = true; - if (node.caps & (V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VBI_OUTPUT | + if (node.g_caps() & (V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VBI_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_SLICED_VBI_OUTPUT)) node.has_outputs = true; - if (node.caps & (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE | + if (node.g_caps() & (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_VIDEO_M2M | V4L2_CAP_SLICED_VBI_CAPTURE | V4L2_CAP_RDS_CAPTURE | V4L2_CAP_SDR_CAPTURE)) node.can_capture = true; - if (node.caps & (V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VBI_OUTPUT | + if (node.g_caps() & (V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VBI_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_VIDEO_M2M | V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_RDS_OUTPUT)) node.can_output = true; - if (node.caps & (V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_VIDEO_OUTPUT_MPLANE | + if (node.g_caps() & (V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_VIDEO_M2M_MPLANE)) node.is_planar = true; - if (expbuf_device) { - doioctl(&expbuf_node, VIDIOC_QUERYCAP, &vcap); - if (vcap.capabilities & V4L2_CAP_DEVICE_CAPS) - expbuf_node.caps = vcap.device_caps; - else - expbuf_node.caps = vcap.capabilities; - } /* Information Opts */ @@ -760,7 +728,7 @@ } printf("\nCompliance test for device %s (%susing libv4l2):\n\n", - device, wrapper ? "" : "not "); + device, direct ? "not " : ""); /* Required ioctls */ @@ -774,8 +742,8 @@ if (video_device) { video_node2 = node; printf("\ttest second video open: %s\n", - ok((video_node2.vfd.fd = test_open(video_device, O_RDWR)) < 0)); - if (video_node2.vfd.fd >= 0) { + ok(video_node2.open(video_device, false) >= 0 ? 0 : errno)); + if (video_node2.g_fd() >= 0) { printf("\ttest VIDIOC_QUERYCAP: %s\n", ok(testCap(&video_node2))); printf("\ttest VIDIOC_G/S_PRIORITY: %s\n", ok(testPrio(&node, &video_node2))); @@ -785,8 +753,8 @@ if (vbi_device) { vbi_node2 = node; printf("\ttest second vbi open: %s\n", - ok((vbi_node2.vfd.fd = test_open(vbi_device, O_RDWR)) < 0)); - if (vbi_node2.vfd.fd >= 0) { + ok(vbi_node2.open(vbi_device, false) >= 0 ? 0 : errno)); + if (vbi_node2.g_fd() >= 0) { printf("\ttest VIDIOC_QUERYCAP: %s\n", ok(testCap(&vbi_node2))); printf("\ttest VIDIOC_G/S_PRIORITY: %s\n", ok(testPrio(&node, &vbi_node2))); @@ -796,8 +764,8 @@ if (radio_device) { radio_node2 = node; printf("\ttest second radio open: %s\n", - ok((radio_node2.vfd.fd = test_open(radio_device, O_RDWR)) < 0)); - if (radio_node2.vfd.fd >= 0) { + ok(radio_node2.open(radio_device, false) >= 0 ? 0 : errno)); + if (radio_node2.g_fd() >= 0) { printf("\ttest VIDIOC_QUERYCAP: %s\n", ok(testCap(&radio_node2))); printf("\ttest VIDIOC_G/S_PRIORITY: %s\n", ok(testPrio(&node, &radio_node2))); @@ -807,8 +775,8 @@ if (sdr_device) { sdr_node2 = node; printf("\ttest second sdr open: %s\n", - ok((sdr_node2.vfd.fd = test_open(sdr_device, O_RDWR)) < 0)); - if (sdr_node2.vfd.fd >= 0) { + ok(sdr_node2.open(sdr_device, false) >= 0 ? 0 : errno)); + if (sdr_node2.g_fd() >= 0) { printf("\ttest VIDIOC_QUERYCAP: %s\n", ok(testCap(&sdr_node2))); printf("\ttest VIDIOC_G/S_PRIORITY: %s\n", ok(testPrio(&node, &sdr_node2))); @@ -861,6 +829,7 @@ unsigned max_io = node.inputs > node.outputs ? node.inputs : node.outputs; for (unsigned io = 0; io < (max_io ? max_io : 1); io++) { + node.std_controls = node.priv_controls = 0; node.controls.clear(); for (unsigned idx = 0; idx < V4L2_BUF_TYPE_SDR_CAPTURE + 1; idx++) node.buftype_pixfmts[idx].clear(); @@ -932,17 +901,17 @@ printf("\ttest read/write: %s\n", ok(testReadWrite(&node))); // Reopen after each streaming test to reset the streaming state // in case of any errors in the preceeding test. - reopen(&node); + node.reopen(); printf("\ttest MMAP: %s\n", ok(testMmap(&node, frame_count))); - reopen(&node); + node.reopen(); printf("\ttest USERPTR: %s\n", ok(testUserPtr(&node, frame_count))); - reopen(&node); + node.reopen(); if (options[OptSetExpBufDevice] || !(node.valid_memorytype & (1 << V4L2_MEMORY_DMABUF))) printf("\ttest DMABUF: %s\n", ok(testDmaBuf(&expbuf_node, &node, frame_count))); else if (!options[OptSetExpBufDevice]) printf("\ttest DMABUF: Cannot test, specify --expbuf-device\n"); - reopen(&node); + node.reopen(); } printf("\n"); @@ -954,11 +923,11 @@ /* Final test report */ - test_close(node.vfd.fd); + node.close(); if (node.node2) - test_close(node.node2->vfd.fd); + node.node2->close(); if (expbuf_device) - close(expbuf_node.vfd.fd); + expbuf_node.close(); printf("Total: %d, Succeeded: %d, Failed: %d, Warnings: %d\n", tests_total, tests_ok, tests_total - tests_ok, warnings); exit(app_result); diff -Nru v4l-utils-1.0.0+r2263/utils/v4l2-compliance/v4l2-compliance.h v4l-utils-1.0.0+r2364/utils/v4l2-compliance/v4l2-compliance.h --- v4l-utils-1.0.0+r2263/utils/v4l2-compliance/v4l2-compliance.h 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/v4l2-compliance/v4l2-compliance.h 2014-08-12 09:02:18.000000000 +0000 @@ -30,14 +30,6 @@ #ifndef NO_LIBV4L2 #include -#else -#define v4l2_open(file, oflag, ...) (-1) -#define v4l2_close(fd) (-1) -#define v4l2_read(fd, buffer, n) (-1) -#define v4l2_write(fd, buffer, n) (-1) -#define v4l2_ioctl(fd, request, ...) (-1) -#define v4l2_mmap(start, length, prot, flags, fd, offset) (MAP_FAILED) -#define v4l2_munmap(_start, length) (-1) #endif #include @@ -48,7 +40,6 @@ extern bool show_info; extern bool show_warnings; -extern bool wrapper; extern int kernel_version; extern unsigned warnings; @@ -59,10 +50,9 @@ typedef std::list qctrl_list; typedef std::set<__u32> pixfmt_set; -struct node; +struct base_node; -struct node { - struct v4l_fd vfd; +struct base_node { bool is_video; bool is_radio; bool is_vbi; @@ -72,7 +62,6 @@ bool can_capture; bool can_output; const char *device; - unsigned caps; struct node *node2; /* second open filehandle */ bool has_outputs; bool has_inputs; @@ -85,14 +74,19 @@ unsigned cur_io_caps; unsigned std_controls; unsigned priv_controls; - qctrl_list controls; __u32 fbuf_caps; - pixfmt_set buftype_pixfmts[V4L2_BUF_TYPE_SDR_CAPTURE + 1]; __u32 valid_buftypes; __u32 valid_buftype; __u32 valid_memorytype; }; +struct node : public base_node, public cv4l_fd { + node() : base_node() {} + + qctrl_list controls; + pixfmt_set buftype_pixfmts[V4L2_BUF_TYPE_SDR_CAPTURE + 1]; +}; + #define info(fmt, args...) \ do { \ if (show_info) \ @@ -118,59 +112,6 @@ return fail("%s\n", #test); \ } while (0) -static inline int test_open(const char *file, int oflag) -{ - return wrapper ? v4l2_open(file, oflag) : open(file, oflag); -} - -static inline int test_close(int fd) -{ - return wrapper ? v4l2_close(fd) : close(fd); -} - -static inline void reopen(struct node *node) -{ - test_close(node->vfd.fd); - if ((node->vfd.fd = test_open(node->device, O_RDWR)) < 0) { - fprintf(stderr, "Failed to open %s: %s\n", node->device, - strerror(errno)); - exit(1); - } -} - -static inline ssize_t test_read(int fd, void *buffer, size_t n) -{ - return wrapper ? v4l2_read(fd, buffer, n) : read(fd, buffer, n); -} - -static inline ssize_t test_write(int fd, const void *buffer, size_t n) -{ - return wrapper ? v4l2_write(fd, buffer, n) : write(fd, buffer, n); -} - -static inline int test_ioctl(int fd, unsigned long cmd, ...) -{ - void *arg; - va_list ap; - - va_start(ap, cmd); - arg = va_arg(ap, void *); - va_end(ap); - return wrapper ? v4l2_ioctl(fd, cmd, arg) : ioctl(fd, cmd, arg); -} - -static inline void *test_mmap(void *start, size_t length, int prot, int flags, - int fd, int64_t offset) -{ - return wrapper ? v4l2_mmap(start, length, prot, flags, fd, offset) : - mmap(start, length, prot, flags, fd, offset); -} - -static inline int test_munmap(void *start, size_t length) -{ - return wrapper ? v4l2_munmap(start, length) : munmap(start, length); -} - static inline int check_fract(const struct v4l2_fract *f) { if (f->numerator && f->denominator) @@ -183,9 +124,7 @@ return (double)f->numerator / (double)f->denominator; } -int doioctl_name(struct node *node, unsigned long int request, void *parm, - const char *name); -#define doioctl(n, r, p) doioctl_name(n, r, p, #r) +#define doioctl(n, r, p) v4l_named_ioctl((n)->g_v4l_fd(), #r, r, p) std::string cap2s(unsigned cap); std::string buftype2s(int type); diff -Nru v4l-utils-1.0.0+r2263/utils/v4l2-compliance/v4l2-test-buffers.cpp v4l-utils-1.0.0+r2364/utils/v4l2-compliance/v4l2-test-buffers.cpp --- v4l-utils-1.0.0+r2263/utils/v4l2-compliance/v4l2-test-buffers.cpp 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/v4l2-compliance/v4l2-test-buffers.cpp 2014-08-12 09:02:18.000000000 +0000 @@ -106,20 +106,8 @@ } } -class queue : public cv4l_queue { -public: - queue(node *node, unsigned type = V4L2_BUF_TYPE_VIDEO_CAPTURE, - unsigned memory = V4L2_MEMORY_MMAP) : - cv4l_queue(&node->vfd, type, memory) {} -}; - class buffer : public cv4l_buffer { public: - using cv4l_buffer::querybuf; - using cv4l_buffer::prepare_buf; - using cv4l_buffer::qbuf; - using cv4l_buffer::dqbuf; - buffer(unsigned type = 0, unsigned memory = 0, unsigned index = 0) : cv4l_buffer(type, memory, index) {} buffer(const cv4l_queue &q, unsigned index = 0) : @@ -128,39 +116,28 @@ int querybuf(node *node, unsigned index) { - return querybuf(&node->vfd, index); + return node->querybuf(*this, index); } int prepare_buf(node *node) { - return prepare_buf(&node->vfd); + return node->prepare_buf(*this); } int dqbuf(node *node) { - return dqbuf(&node->vfd); + return node->dqbuf(*this); } int qbuf(node *node, bool fill_bytesused = true) { int err; - if (is_output()) - fill_output_buf(fill_bytesused); - err = qbuf(&node->vfd); - if (err == 0 && is_output()) - buffer_info[g_timestamp()] = buf; - return err; - } - int qbuf(const queue &q, bool fill_bytesused = true) - { - int err; - - if (is_output()) + if (v4l_type_is_output(g_type())) fill_output_buf(fill_bytesused); - err = cv4l_buffer::qbuf(q); - if (err == 0 && is_output()) + err = node->qbuf(*this); + if (err == 0 && v4l_type_is_output(g_type())) buffer_info[g_timestamp()] = buf; return err; } - int check(const queue &q, enum QueryBufMode mode) + int check(const cv4l_queue &q, enum QueryBufMode mode) { int ret = check(q.g_type(), q.g_memory(), g_index(), mode, last_seq); @@ -168,7 +145,7 @@ ret = check_planes(q, mode); return ret; } - int check(const queue &q, enum QueryBufMode mode, __u32 index) + int check(const cv4l_queue &q, enum QueryBufMode mode, __u32 index) { int ret = check(q.g_type(), q.g_memory(), index, mode, last_seq); @@ -176,7 +153,7 @@ ret = check_planes(q, mode); return ret; } - int check(const queue &q, buf_seq &seq) + int check(const cv4l_queue &q, buf_seq &seq) { int ret = check(q.g_type(), q.g_memory(), g_index(), Dequeued, seq); @@ -196,7 +173,7 @@ private: int check(unsigned type, unsigned memory, unsigned index, enum QueryBufMode mode, struct buf_seq &seq); - int check_planes(const queue &q, enum QueryBufMode mode); + int check_planes(const cv4l_queue &q, enum QueryBufMode mode); void fill_output_buf(bool fill_bytesused = true) { timespec ts; @@ -229,7 +206,7 @@ } }; -int buffer::check_planes(const queue &q, enum QueryBufMode mode) +int buffer::check_planes(const cv4l_queue &q, enum QueryBufMode mode) { if (mode == Dequeued || mode == Prepared) { for (unsigned p = 0; p < g_num_planes(); p++) { @@ -261,7 +238,7 @@ timestamp != V4L2_BUF_FLAG_TIMESTAMP_COPY); fail_on_test(timestamp_src != V4L2_BUF_FLAG_TSTAMP_SRC_SOE && timestamp_src != V4L2_BUF_FLAG_TSTAMP_SRC_EOF); - fail_on_test(!ts_copy && is_output() && + fail_on_test(!ts_copy && v4l_type_is_output(g_type()) && timestamp_src == V4L2_BUF_FLAG_TSTAMP_SRC_SOE); if (g_flags() & V4L2_BUF_FLAG_KEYFRAME) frame_types++; @@ -282,7 +259,7 @@ buf_states++; fail_on_test(buf_states > 1); fail_on_test(buf.length == 0); - if (is_planar()) { + if (v4l_type_is_planar(g_type())) { fail_on_test(buf.length > VIDEO_MAX_PLANES); for (unsigned p = 0; p < buf.length; p++) { struct v4l2_plane *vp = buf.m.planes + p; @@ -292,7 +269,7 @@ } } - if (is_capture() && !ts_copy && + if (v4l_type_is_capture(g_type()) && !ts_copy && (g_flags() & V4L2_BUF_FLAG_TIMECODE)) warn("V4L2_BUF_FLAG_TIMECODE was used!\n"); @@ -304,7 +281,7 @@ } fail_on_test(!g_timestamp().tv_sec && !g_timestamp().tv_usec); fail_on_test(!(g_flags() & (V4L2_BUF_FLAG_DONE | V4L2_BUF_FLAG_ERROR))); - if (is_video()) { + if (v4l_type_is_video(g_type())) { fail_on_test(g_field() == V4L2_FIELD_ALTERNATE); fail_on_test(g_field() == V4L2_FIELD_ANY); if (cur_fmt.g_field() == V4L2_FIELD_ALTERNATE) { @@ -327,12 +304,12 @@ seq.last_field = g_field(); } else { fail_on_test(g_sequence()); - if (mode == Queued && ts_copy && is_output()) { + if (mode == Queued && ts_copy && v4l_type_is_output(g_type())) { fail_on_test(!g_timestamp().tv_sec && !g_timestamp().tv_usec); } else { fail_on_test(g_timestamp().tv_sec || g_timestamp().tv_usec); } - if (!is_output() || mode == Unqueued) + if (!v4l_type_is_output(g_type()) || mode == Unqueued) fail_on_test(frame_types); if (mode == Unqueued) fail_on_test(g_flags() & (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_PREPARED | @@ -355,7 +332,7 @@ for (i = 0; i < count; i++) { fail_on_test(buf.querybuf(node, i)); - if (buf.is_planar()) + if (v4l_type_is_planar(buf.g_type())) fail_on_test(buf.buf.m.planes != buf.planes); fail_on_test(buf.check(Unqueued, i)); } @@ -366,34 +343,35 @@ static int testSetupVbi(struct node *node, int type) { - if (!v4l_buf_type_is_vbi(type)) + if (!v4l_type_is_vbi(type)) return 0; if (!(node->cur_io_caps & V4L2_IN_CAP_STD)) return -1; - cv4l_fmt vbi_fmt(&node->vfd, type); + node->s_type(type); + cv4l_fmt vbi_fmt; - if (!vbi_fmt.g_fmt()) - vbi_fmt.s_fmt(); + if (!node->g_fmt(vbi_fmt)) + node->s_fmt(vbi_fmt); return 0; } int testReqBufs(struct node *node) { - bool can_stream = node->caps & V4L2_CAP_STREAMING; - bool can_rw = node->caps & V4L2_CAP_READWRITE; + bool can_stream = node->g_caps() & V4L2_CAP_STREAMING; + bool can_rw = node->g_caps() & V4L2_CAP_READWRITE; bool mmap_valid; bool userptr_valid; bool dmabuf_valid; int ret; unsigned i, m; - reopen(node); + node->reopen(); - queue q(node, 0, 0); + cv4l_queue q(0, 0); - ret = q.reqbufs(0); + ret = q.reqbufs(node, 0); if (ret == ENOTTY) { fail_on_test(can_stream); return ret; @@ -401,7 +379,7 @@ fail_on_test(ret != EINVAL); fail_on_test(node->node2 == NULL); for (i = 1; i <= V4L2_BUF_TYPE_SDR_CAPTURE; i++) { - bool is_overlay = v4l_buf_type_is_overlay(i); + bool is_overlay = v4l_type_is_overlay(i); if (!(node->valid_buftypes & (1 << i))) continue; @@ -414,19 +392,19 @@ node->valid_buftype = i; q.init(0, 0); - fail_on_test(q.reqbufs(i) != EINVAL); + fail_on_test(q.reqbufs(node, i) != EINVAL); q.init(i, V4L2_MEMORY_MMAP); - ret = q.reqbufs(0); + ret = q.reqbufs(node, 0); fail_on_test(ret && ret != EINVAL); mmap_valid = !ret; q.init(i, V4L2_MEMORY_USERPTR); - ret = q.reqbufs(0); + ret = q.reqbufs(node, 0); fail_on_test(ret && ret != EINVAL); userptr_valid = !ret; q.init(i, V4L2_MEMORY_DMABUF); - ret = q.reqbufs(0); + ret = q.reqbufs(node, 0); fail_on_test(ret && ret != EINVAL); dmabuf_valid = !ret; fail_on_test((can_stream && !is_overlay) && !mmap_valid && !userptr_valid && !dmabuf_valid); @@ -436,33 +414,33 @@ if (mmap_valid) { q.init(i, V4L2_MEMORY_MMAP); - fail_on_test(q.reqbufs(1)); + fail_on_test(q.reqbufs(node, 1)); fail_on_test(q.g_buffers() == 0); fail_on_test(q.g_memory() != V4L2_MEMORY_MMAP); fail_on_test(q.g_type() != i); - fail_on_test(q.reqbufs(1)); + fail_on_test(q.reqbufs(node, 1)); fail_on_test(testQueryBuf(node, i, q.g_buffers())); node->valid_memorytype |= 1 << V4L2_MEMORY_MMAP; } if (userptr_valid) { q.init(i, V4L2_MEMORY_USERPTR); - fail_on_test(q.reqbufs(1)); + fail_on_test(q.reqbufs(node, 1)); fail_on_test(q.g_buffers() == 0); fail_on_test(q.g_memory() != V4L2_MEMORY_USERPTR); fail_on_test(q.g_type() != i); - fail_on_test(q.reqbufs(1)); + fail_on_test(q.reqbufs(node, 1)); fail_on_test(testQueryBuf(node, i, q.g_buffers())); node->valid_memorytype |= 1 << V4L2_MEMORY_USERPTR; } if (dmabuf_valid) { q.init(i, V4L2_MEMORY_DMABUF); - fail_on_test(q.reqbufs(1)); + fail_on_test(q.reqbufs(node, 1)); fail_on_test(q.g_buffers() == 0); fail_on_test(q.g_memory() != V4L2_MEMORY_DMABUF); fail_on_test(q.g_type() != i); - fail_on_test(q.reqbufs(1)); + fail_on_test(q.reqbufs(node, 1)); fail_on_test(testQueryBuf(node, i, q.g_buffers())); node->valid_memorytype |= 1 << V4L2_MEMORY_DMABUF; } @@ -471,30 +449,30 @@ char buf = 0; if (node->can_capture) - ret = test_read(node->vfd.fd, &buf, 1); + ret = node->read(&buf, 1); else - ret = test_write(node->vfd.fd, &buf, 1); + ret = node->write(&buf, 1); if (ret != -1) return fail("Expected -1, got %d\n", ret); if (errno != EBUSY) return fail("Expected EBUSY, got %d\n", errno); } - fail_on_test(q.reqbufs(0)); + fail_on_test(q.reqbufs(node, 0)); for (m = V4L2_MEMORY_MMAP; m <= V4L2_MEMORY_DMABUF; m++) { if (!(node->valid_memorytype & (1 << m))) continue; - queue q2(node->node2, i, m); - fail_on_test(q.reqbufs(1)); + cv4l_queue q2(i, m); + fail_on_test(q.reqbufs(node, 1)); if (!node->is_m2m) { - fail_on_test(q2.reqbufs(1) != EBUSY); - fail_on_test(q2.reqbufs() != EBUSY); - fail_on_test(q.reqbufs()); - fail_on_test(q2.reqbufs(1)); - fail_on_test(q2.reqbufs()); + fail_on_test(q2.reqbufs(node->node2, 1) != EBUSY); + fail_on_test(q2.reqbufs(node->node2) != EBUSY); + fail_on_test(q.reqbufs(node)); + fail_on_test(q2.reqbufs(node->node2, 1)); + fail_on_test(q2.reqbufs(node->node2)); } - fail_on_test(q.reqbufs()); - ret = q.create_bufs(1); + fail_on_test(q.reqbufs(node)); + ret = q.create_bufs(node, 1); if (ret == ENOTTY) { warn("VIDIOC_CREATE_BUFS not supported\n"); break; @@ -503,12 +481,12 @@ fail_on_test(q.g_buffers() == 0); fail_on_test(q.g_type() != i); fail_on_test(testQueryBuf(node, i, q.g_buffers())); - fail_on_test(q.create_bufs(1)); + fail_on_test(q.create_bufs(node, 1)); fail_on_test(testQueryBuf(node, i, q.g_buffers())); if (!node->is_m2m) - fail_on_test(q2.create_bufs(1) != EBUSY); + fail_on_test(q2.create_bufs(node->node2, 1) != EBUSY); } - fail_on_test(q.reqbufs()); + fail_on_test(q.reqbufs(node)); } return 0; } @@ -519,53 +497,53 @@ int type; if (!(node->valid_memorytype & (1 << V4L2_MEMORY_MMAP))) { - queue q(node); + cv4l_queue q; - fail_on_test(q.has_expbuf()); + fail_on_test(q.has_expbuf(node)); return ENOTTY; } for (type = 0; type <= V4L2_BUF_TYPE_SDR_CAPTURE; type++) { if (!(node->valid_buftypes & (1 << type))) continue; - if (v4l_buf_type_is_overlay(type)) + if (v4l_type_is_overlay(type)) continue; if (testSetupVbi(node, type)) continue; - queue q(node, type, V4L2_MEMORY_MMAP); + cv4l_queue q(type, V4L2_MEMORY_MMAP); - fail_on_test(q.reqbufs(1)); - if (q.has_expbuf()) { - fail_on_test(q.export_bufs()); + fail_on_test(q.reqbufs(node, 1)); + if (q.has_expbuf(node)) { + fail_on_test(q.export_bufs(node)); have_expbuf = true; } else { - fail_on_test(!q.export_bufs()); + fail_on_test(!q.export_bufs(node)); } q.close_exported_fds(); - fail_on_test(q.reqbufs()); + fail_on_test(q.reqbufs(node)); } return have_expbuf ? 0 : ENOTTY; } int testReadWrite(struct node *node) { - bool can_rw = node->caps & V4L2_CAP_READWRITE; - int fd_flags = fcntl(node->vfd.fd, F_GETFL); + bool can_rw = node->g_caps() & V4L2_CAP_READWRITE; + int fd_flags = fcntl(node->g_fd(), F_GETFL); char buf = 0; int ret; - if (v4l_has_vbi(&node->vfd) && + if (v4l_has_vbi(node->g_v4l_fd()) && !(node->cur_io_caps & V4L2_IN_CAP_STD)) { return 0; } - fcntl(node->vfd.fd, F_SETFL, fd_flags | O_NONBLOCK); + fcntl(node->g_fd(), F_SETFL, fd_flags | O_NONBLOCK); if (node->can_capture) - ret = read(node->vfd.fd, &buf, 1); + ret = node->read(&buf, 1); else - ret = write(node->vfd.fd, &buf, 1); + ret = node->write(&buf, 1); // Note: RDS can only return multiples of 3, so we accept // both 0 and 1 as return code. // EBUSY can be returned when attempting to read/write to a @@ -577,22 +555,22 @@ if (!can_rw) return ENOTTY; - reopen(node); - fcntl(node->vfd.fd, F_SETFL, fd_flags | O_NONBLOCK); + node->reopen(); + fcntl(node->g_fd(), F_SETFL, fd_flags | O_NONBLOCK); /* check that the close cleared the busy flag */ if (node->can_capture) - ret = read(node->vfd.fd, &buf, 1); + ret = node->read(&buf, 1); else - ret = write(node->vfd.fd, &buf, 1); + ret = node->write(&buf, 1); fail_on_test((ret < 0 && errno != EAGAIN && errno != EBUSY) || ret > 1); return 0; } -static int captureBufs(struct node *node, const queue &q, - const queue &m2m_q, unsigned frame_count, bool use_poll) +static int captureBufs(struct node *node, const cv4l_queue &q, + const cv4l_queue &m2m_q, unsigned frame_count, bool use_poll) { - int fd_flags = fcntl(node->vfd.fd, F_GETFL); + int fd_flags = fcntl(node->g_fd(), F_GETFL); buffer buf(q); unsigned count = frame_count; int ret; @@ -604,7 +582,7 @@ } if (use_poll) - fcntl(node->vfd.fd, F_SETFL, fd_flags | O_NONBLOCK); + fcntl(node->g_fd(), F_SETFL, fd_flags | O_NONBLOCK); for (;;) { buf.init(q); @@ -613,18 +591,18 @@ fd_set fds; FD_ZERO(&fds); - FD_SET(node->vfd.fd, &fds); + FD_SET(node->g_fd(), &fds); if (node->is_m2m) - ret = select(node->vfd.fd + 1, &fds, &fds, NULL, &tv); - else if (q.is_output()) - ret = select(node->vfd.fd + 1, NULL, &fds, NULL, &tv); + ret = select(node->g_fd() + 1, &fds, &fds, NULL, &tv); + else if (v4l_type_is_output(q.g_type())) + ret = select(node->g_fd() + 1, NULL, &fds, NULL, &tv); else - ret = select(node->vfd.fd + 1, &fds, NULL, NULL, &tv); + ret = select(node->g_fd() + 1, &fds, NULL, NULL, &tv); fail_on_test(ret <= 0); - fail_on_test(!FD_ISSET(node->vfd.fd, &fds)); + fail_on_test(!FD_ISSET(node->g_fd(), &fds)); } - ret = buf.dqbuf(q); + ret = buf.dqbuf(node); if (ret != EAGAIN) { fail_on_test(ret); if (show_info) @@ -636,11 +614,11 @@ printf("\r\t%s: Frame #%03d%s", buftype2s(q.g_type()).c_str(), frame_count - count, use_poll ? " (polling)" : ""); - if (node->vfd.trace) + if (node->g_trace()) printf("\n"); fflush(stdout); } - if (buf.is_capture() && node->is_m2m && buf.ts_is_copy()) { + if (v4l_type_is_capture(buf.g_type()) && node->is_m2m && buf.ts_is_copy()) { fail_on_test(buffer_info.find(buf.g_timestamp()) == buffer_info.end()); struct v4l2_buffer &orig_buf = buffer_info[buf.g_timestamp()]; fail_on_test(buf.g_field() != orig_buf.field); @@ -650,7 +628,7 @@ fail_on_test(memcmp(&buf.g_timecode(), &orig_buf.timecode, sizeof(orig_buf.timecode))); } - fail_on_test(buf.qbuf(q)); + fail_on_test(buf.qbuf(node)); if (--count == 0) break; } @@ -658,7 +636,7 @@ continue; buf.init(m2m_q); - ret = buf.dqbuf(m2m_q); + ret = buf.dqbuf(node); if (ret == EAGAIN) continue; if (show_info) @@ -667,7 +645,7 @@ buf.g_timestamp().tv_sec, buf.g_timestamp().tv_usec); fail_on_test(ret); fail_on_test(buf.check(m2m_q, last_m2m_seq)); - if (buf.is_capture() && buf.ts_is_copy()) { + if (v4l_type_is_capture(buf.g_type()) && buf.ts_is_copy()) { fail_on_test(buffer_info.find(buf.g_timestamp()) == buffer_info.end()); struct v4l2_buffer &orig_buf = buffer_info[buf.g_timestamp()]; fail_on_test(buf.g_field() != orig_buf.field); @@ -677,10 +655,10 @@ fail_on_test(memcmp(&buf.g_timecode(), &orig_buf.timecode, sizeof(orig_buf.timecode))); } - fail_on_test(buf.qbuf(m2m_q)); + fail_on_test(buf.qbuf(node)); } if (use_poll) - fcntl(node->vfd.fd, F_SETFL, fd_flags); + fcntl(node->g_fd(), F_SETFL, fd_flags); if (!show_info) { printf("\r\t \r"); fflush(stdout); @@ -690,33 +668,33 @@ static unsigned invert_buf_type(unsigned type) { - if (v4l_buf_type_is_planar(type)) - return v4l_buf_type_is_output(type) ? + if (v4l_type_is_planar(type)) + return v4l_type_is_output(type) ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; - return v4l_buf_type_is_output(type) ? + return v4l_type_is_output(type) ? V4L2_BUF_TYPE_VIDEO_CAPTURE : V4L2_BUF_TYPE_VIDEO_OUTPUT; } -static int setupM2M(struct node *node, queue &q) +static int setupM2M(struct node *node, cv4l_queue &q) { last_m2m_seq.init(); - fail_on_test(q.reqbufs(1)); + fail_on_test(q.reqbufs(node, 1)); for (unsigned i = 0; i < q.g_buffers(); i++) { buffer buf(q); - fail_on_test(buf.querybuf(q, i)); - fail_on_test(buf.qbuf(q)); + fail_on_test(buf.querybuf(node, i)); + fail_on_test(buf.qbuf(node)); } - if (q.is_video()) { - cv4l_fmt fmt(&node->vfd, q.g_type()); + if (v4l_type_is_video(q.g_type())) { + cv4l_fmt fmt(q.g_type()); - fmt.g_fmt(); + node->g_fmt(fmt); last_m2m_seq.last_field = fmt.g_field(); } - fail_on_test(q.streamon()); + fail_on_test(node->streamon(q.g_type())); return 0; } @@ -735,7 +713,7 @@ have_prepare = ret != ENOTTY; fail_on_test(buf.qbuf(node, false) != EINVAL); - if (buf.is_planar()) { + if (v4l_type_is_planar(buf.g_type())) { for (unsigned p = 0; p < buf.g_num_planes(); p++) { buf.s_bytesused(buf.g_length(p) / 2, p); buf.s_data_offset(buf.g_bytesused(p), p); @@ -766,56 +744,56 @@ return 0; } -static int setupMmap(struct node *node, queue &q) +static int setupMmap(struct node *node, cv4l_queue &q) { for (unsigned i = 0; i < q.g_buffers(); i++) { buffer buf(q); int ret; - fail_on_test(buf.querybuf(q, i)); + fail_on_test(buf.querybuf(node, i)); fail_on_test(buf.check(q, Unqueued, i)); for (unsigned p = 0; p < buf.g_num_planes(); p++) { // Try a random offset - fail_on_test(test_mmap(NULL, buf.g_length(p), PROT_READ | PROT_WRITE, - MAP_SHARED, node->vfd.fd, buf.g_mem_offset(p) + 0xdeadbeef) != MAP_FAILED); + fail_on_test(node->mmap(buf.g_length(p), + buf.g_mem_offset(p) + 0xdeadbeef) != MAP_FAILED); } - fail_on_test(!buf.dqbuf(q)); - if (buf.is_output() && i == 0) { + fail_on_test(!buf.dqbuf(node)); + if (v4l_type_is_output(buf.g_type()) && i == 0) { fail_on_test(bufferOutputErrorTest(node, buf)); - fail_on_test(buf.querybuf(q, i)); + fail_on_test(buf.querybuf(node, i)); fail_on_test(buf.check(q, Queued, i)); } else { - ret = buf.prepare_buf(q); + ret = buf.prepare_buf(node); fail_on_test(ret && ret != ENOTTY); if (ret == 0) { - fail_on_test(buf.querybuf(q, i)); + fail_on_test(buf.querybuf(node, i)); fail_on_test(buf.check(q, Prepared, i)); - fail_on_test(!buf.prepare_buf(q)); + fail_on_test(!buf.prepare_buf(node)); } - fail_on_test(buf.qbuf(q)); - fail_on_test(!buf.qbuf(q)); - fail_on_test(!buf.prepare_buf(q)); + fail_on_test(buf.qbuf(node)); + fail_on_test(!buf.qbuf(node)); + fail_on_test(!buf.prepare_buf(node)); // Test with invalid buffer index buf.s_index(buf.g_index() + VIDEO_MAX_FRAME); - fail_on_test(!buf.prepare_buf(q)); - fail_on_test(!buf.qbuf(q)); - fail_on_test(!buf.querybuf(q, buf.g_index())); + fail_on_test(!buf.prepare_buf(node)); + fail_on_test(!buf.qbuf(node)); + fail_on_test(!buf.querybuf(node, buf.g_index())); buf.s_index(buf.g_index() - VIDEO_MAX_FRAME); fail_on_test(buf.g_index() != i); } - fail_on_test(buf.querybuf(q, i)); + fail_on_test(buf.querybuf(node, i)); fail_on_test(buf.check(q, Queued, i)); - fail_on_test(!buf.dqbuf(q)); + fail_on_test(!buf.dqbuf(node)); } - fail_on_test(q.mmap_bufs()); + fail_on_test(q.mmap_bufs(node)); return 0; } int testMmap(struct node *node, unsigned frame_count) { - bool can_stream = node->caps & V4L2_CAP_STREAMING; + bool can_stream = node->g_caps() & V4L2_CAP_STREAMING; bool have_createbufs = true; int type; int ret; @@ -827,55 +805,55 @@ for (type = 0; type <= V4L2_BUF_TYPE_SDR_CAPTURE; type++) { if (!(node->valid_buftypes & (1 << type))) continue; - if (v4l_buf_type_is_overlay(type)) + if (v4l_type_is_overlay(type)) continue; - queue q(node, type, V4L2_MEMORY_MMAP); - queue m2m_q(node, invert_buf_type(type)); + cv4l_queue q(type, V4L2_MEMORY_MMAP); + cv4l_queue m2m_q(invert_buf_type(type)); if (testSetupVbi(node, type)) continue; - ret = q.reqbufs(0); + ret = q.reqbufs(node, 0); if (ret) { fail_on_test(can_stream); return ret; } fail_on_test(!can_stream); - fail_on_test(q.streamon() != EINVAL); - fail_on_test(q.streamoff()); + fail_on_test(node->streamon(q.g_type()) != EINVAL); + fail_on_test(node->streamoff(q.g_type())); q.init(type, V4L2_MEMORY_MMAP); - fail_on_test(q.reqbufs(1)); - fail_on_test(q.streamoff()); + fail_on_test(q.reqbufs(node, 1)); + fail_on_test(node->streamoff(q.g_type())); last_seq.init(); // Test queuing buffers... for (unsigned i = 0; i < q.g_buffers(); i++) { buffer buf(q); - fail_on_test(buf.querybuf(q, i)); - fail_on_test(buf.qbuf(q)); + fail_on_test(buf.querybuf(node, i)); + fail_on_test(buf.qbuf(node)); } // calling STREAMOFF... - fail_on_test(q.streamoff()); + fail_on_test(node->streamoff(q.g_type())); // and now we should be able to queue those buffers again since // STREAMOFF should return them back to the dequeued state. for (unsigned i = 0; i < q.g_buffers(); i++) { buffer buf(q); - fail_on_test(buf.querybuf(q, i)); - fail_on_test(buf.qbuf(q)); + fail_on_test(buf.querybuf(node, i)); + fail_on_test(buf.qbuf(node)); } // Now request buffers again, freeing the old buffers. // Good check for whether all the internal vb2 calls are in // balance. - fail_on_test(q.reqbufs(q.g_buffers())); - cur_fmt.init(&node->vfd, q.g_type()); - cur_fmt.g_fmt(); + fail_on_test(q.reqbufs(node, q.g_buffers())); + cur_fmt.s_type(q.g_type()); + node->g_fmt(cur_fmt); - ret = q.create_bufs(0); + ret = q.create_bufs(node, 0); fail_on_test(ret != ENOTTY && ret != 0); if (ret == ENOTTY) have_createbufs = false; @@ -886,47 +864,48 @@ last_seq.last_field = cur_fmt.g_field(); fmt.s_height(fmt.g_height() / 2); for (unsigned p = 0; p < fmt.g_num_planes(); p++) - fmt.s_sizeimage(p, fmt.g_sizeimage(p) / 2); - ret = q.create_bufs(1, &fmt); + fmt.s_sizeimage(fmt.g_sizeimage(p) / 2, p); + ret = q.create_bufs(node, 1, &fmt); fail_on_test(ret != EINVAL); fail_on_test(testQueryBuf(node, cur_fmt.type, q.g_buffers())); fmt = cur_fmt; for (unsigned p = 0; p < fmt.g_num_planes(); p++) - fmt.s_sizeimage(p, fmt.g_sizeimage(p) * 2); + fmt.s_sizeimage(fmt.g_sizeimage(p) * 2, p); } - fail_on_test(q.create_bufs(1, &fmt)); + fail_on_test(q.create_bufs(node, 1, &fmt)); } fail_on_test(setupMmap(node, q)); - fail_on_test(q.streamon()); - fail_on_test(q.streamon()); + fail_on_test(node->streamon(q.g_type())); + fail_on_test(node->streamon(q.g_type())); if (node->is_m2m) fail_on_test(setupM2M(node, m2m_q)); else fail_on_test(captureBufs(node, q, m2m_q, frame_count, false)); fail_on_test(captureBufs(node, q, m2m_q, frame_count, true)); - fail_on_test(q.streamoff()); - fail_on_test(q.streamoff()); + fail_on_test(node->streamoff(q.g_type())); + fail_on_test(node->streamoff(q.g_type())); + q.munmap_bufs(node); + fail_on_test(q.reqbufs(node, 0)); } return 0; } -static int setupUserPtr(struct node *node, queue &q) +static int setupUserPtr(struct node *node, cv4l_queue &q) { - fail_on_test(q.alloc_bufs()); + fail_on_test(q.alloc_bufs(node)); for (unsigned i = 0; i < q.g_buffers(); i++) { buffer buf(q); int ret; - fail_on_test(buf.querybuf(q, i)); + fail_on_test(buf.querybuf(node, i)); fail_on_test(buf.check(q, Unqueued, i)); for (unsigned p = 0; p < buf.g_num_planes(); p++) { // This should not work! - fail_on_test(test_mmap(NULL, buf.g_length(p), PROT_READ | PROT_WRITE, - MAP_SHARED, node->vfd.fd, 0) != MAP_FAILED); + fail_on_test(node->mmap(buf.g_length(p), 0) != MAP_FAILED); } ret = ENOTTY; @@ -934,39 +913,39 @@ if ((i & 1) == 0) { for (unsigned p = 0; p < buf.g_num_planes(); p++) buf.s_userptr(0UL, p); - ret = buf.prepare_buf(q); + ret = buf.prepare_buf(node); fail_on_test(!ret); for (unsigned p = 0; p < buf.g_num_planes(); p++) buf.s_userptr((char *)q.g_userptr(i, p) + 0xdeadbeef, p); - ret = buf.prepare_buf(q); + ret = buf.prepare_buf(node); fail_on_test(!ret); for (unsigned p = 0; p < buf.g_num_planes(); p++) buf.s_userptr(q.g_userptr(i, p), p); - ret = buf.prepare_buf(q); + ret = buf.prepare_buf(node); fail_on_test(ret && ret != ENOTTY); if (ret == 0) { - fail_on_test(buf.querybuf(q, i)); + fail_on_test(buf.querybuf(node, i)); fail_on_test(buf.check(q, Prepared, i)); } } if (ret == ENOTTY) { for (unsigned p = 0; p < buf.g_num_planes(); p++) buf.s_userptr(0UL, p); - ret = buf.qbuf(q); + ret = buf.qbuf(node); fail_on_test(!ret); for (unsigned p = 0; p < buf.g_num_planes(); p++) buf.s_userptr((char *)q.g_userptr(i, p) + 0xdeadbeef, p); - ret = buf.qbuf(q); + ret = buf.qbuf(node); fail_on_test(!ret); for (unsigned p = 0; p < buf.g_num_planes(); p++) buf.s_userptr(q.g_userptr(i, p), p); } - fail_on_test(buf.qbuf(q)); - fail_on_test(buf.querybuf(q, i)); + fail_on_test(buf.qbuf(node)); + fail_on_test(buf.querybuf(node, i)); fail_on_test(buf.check(q, Queued, i)); } return 0; @@ -974,7 +953,7 @@ int testUserPtr(struct node *node, unsigned frame_count) { - bool can_stream = node->caps & V4L2_CAP_STREAMING; + bool can_stream = node->g_caps() & V4L2_CAP_STREAMING; int type; int ret; @@ -985,16 +964,16 @@ for (type = 0; type <= V4L2_BUF_TYPE_SDR_CAPTURE; type++) { if (!(node->valid_buftypes & (1 << type))) continue; - if (v4l_buf_type_is_overlay(type)) + if (v4l_type_is_overlay(type)) continue; - queue q(node, type, V4L2_MEMORY_USERPTR); - queue m2m_q(node, invert_buf_type(type)); + cv4l_queue q(type, V4L2_MEMORY_USERPTR); + cv4l_queue m2m_q(invert_buf_type(type)); if (testSetupVbi(node, type)) continue; - ret = q.reqbufs(0); + ret = q.reqbufs(node, 0); if (ret) { fail_on_test(ret != EINVAL); return ENOTTY; @@ -1002,76 +981,75 @@ fail_on_test(!can_stream); q.init(type, V4L2_MEMORY_USERPTR); - fail_on_test(q.reqbufs(1)); - fail_on_test(q.streamoff()); + fail_on_test(q.reqbufs(node, 1)); + fail_on_test(node->streamoff(q.g_type())); last_seq.init(); if (node->is_video) last_seq.last_field = cur_fmt.g_field(); fail_on_test(setupUserPtr(node, q)); - fail_on_test(q.streamon()); - fail_on_test(q.streamon()); + fail_on_test(node->streamon(q.g_type())); + fail_on_test(node->streamon(q.g_type())); if (node->is_m2m) fail_on_test(setupM2M(node, m2m_q)); else fail_on_test(captureBufs(node, q, m2m_q, frame_count, false)); fail_on_test(captureBufs(node, q, m2m_q, frame_count, true)); - fail_on_test(q.streamoff()); - fail_on_test(q.streamoff()); + fail_on_test(node->streamoff(q.g_type())); + fail_on_test(node->streamoff(q.g_type())); } return 0; } static int setupDmaBuf(struct node *expbuf_node, struct node *node, - queue &q, queue &exp_q) + cv4l_queue &q, cv4l_queue &exp_q) { - fail_on_test(exp_q.reqbufs(q.g_buffers())); + fail_on_test(exp_q.reqbufs(expbuf_node, q.g_buffers())); fail_on_test(exp_q.g_buffers() < q.g_buffers()); - fail_on_test(exp_q.export_bufs()); + fail_on_test(exp_q.export_bufs(expbuf_node)); for (unsigned i = 0; i < q.g_buffers(); i++) { buffer buf(q); int ret; - fail_on_test(buf.querybuf(q, i)); + fail_on_test(buf.querybuf(node, i)); fail_on_test(buf.check(q, Unqueued, i)); fail_on_test(exp_q.g_num_planes() < buf.g_num_planes()); for (unsigned p = 0; p < buf.g_num_planes(); p++) { fail_on_test(exp_q.g_length(p) < buf.g_length(p)); // This should not work! - fail_on_test(test_mmap(NULL, buf.g_length(p), PROT_READ | PROT_WRITE, - MAP_SHARED, node->vfd.fd, 0) != MAP_FAILED); + fail_on_test(node->mmap(buf.g_length(p), 0) != MAP_FAILED); q.s_fd(i, p, exp_q.g_fd(i, p)); } for (unsigned p = 0; p < buf.g_num_planes(); p++) buf.s_fd(0xdeadbeef + q.g_fd(i, p), p); - ret = buf.prepare_buf(q); + ret = buf.prepare_buf(node); fail_on_test(!ret); if (ret != ENOTTY) { buf.init(q, i); - ret = buf.prepare_buf(q); + ret = buf.prepare_buf(node); fail_on_test(ret); - fail_on_test(buf.querybuf(q, i)); + fail_on_test(buf.querybuf(node, i)); fail_on_test(buf.check(q, Prepared, i)); } else { - fail_on_test(!buf.qbuf(q)); + fail_on_test(!buf.qbuf(node)); buf.init(q, i); } - fail_on_test(buf.qbuf(q)); - fail_on_test(buf.querybuf(q, i)); + fail_on_test(buf.qbuf(node)); + fail_on_test(buf.querybuf(node, i)); fail_on_test(buf.check(q, Queued, i)); } - fail_on_test(q.mmap_bufs()); + fail_on_test(q.mmap_bufs(node)); return 0; } int testDmaBuf(struct node *expbuf_node, struct node *node, unsigned frame_count) { - bool can_stream = node->caps & V4L2_CAP_STREAMING; + bool can_stream = node->g_caps() & V4L2_CAP_STREAMING; int expbuf_type, type; int ret; @@ -1082,52 +1060,52 @@ for (type = 0; type <= V4L2_BUF_TYPE_SDR_CAPTURE; type++) { if (!(node->valid_buftypes & (1 << type))) continue; - if (v4l_buf_type_is_sdr(type)) + if (v4l_type_is_sdr(type)) continue; - if (v4l_buf_type_is_overlay(type)) + if (v4l_type_is_overlay(type)) continue; - if (expbuf_node->caps & V4L2_CAP_VIDEO_CAPTURE_MPLANE) + if (expbuf_node->g_caps() & V4L2_CAP_VIDEO_CAPTURE_MPLANE) expbuf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - else if (expbuf_node->caps & V4L2_CAP_VIDEO_CAPTURE) + else if (expbuf_node->g_caps() & V4L2_CAP_VIDEO_CAPTURE) expbuf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - else if (expbuf_node->caps & V4L2_CAP_VIDEO_OUTPUT_MPLANE) + else if (expbuf_node->g_caps() & V4L2_CAP_VIDEO_OUTPUT_MPLANE) expbuf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; else expbuf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT; - queue q(node, type, V4L2_MEMORY_DMABUF); - queue m2m_q(node, invert_buf_type(type)); - queue exp_q(expbuf_node, expbuf_type, V4L2_MEMORY_MMAP); + cv4l_queue q(type, V4L2_MEMORY_DMABUF); + cv4l_queue m2m_q(invert_buf_type(type)); + cv4l_queue exp_q(expbuf_type, V4L2_MEMORY_MMAP); if (testSetupVbi(node, type)) continue; - ret = q.reqbufs(0); + ret = q.reqbufs(node, 0); if (ret) { fail_on_test(ret != EINVAL); return ENOTTY; } fail_on_test(!can_stream); - fail_on_test(q.reqbufs(1)); - fail_on_test(q.streamoff()); + fail_on_test(q.reqbufs(node, 1)); + fail_on_test(node->streamoff(q.g_type())); last_seq.init(); if (node->is_video) last_seq.last_field = cur_fmt.g_field(); fail_on_test(setupDmaBuf(expbuf_node, node, q, exp_q)); - fail_on_test(q.streamon()); - fail_on_test(q.streamon()); + fail_on_test(node->streamon(q.g_type())); + fail_on_test(node->streamon(q.g_type())); if (node->is_m2m) fail_on_test(setupM2M(node, m2m_q)); else fail_on_test(captureBufs(node, q, m2m_q, frame_count, false)); fail_on_test(captureBufs(node, q, m2m_q, frame_count, true)); - fail_on_test(q.streamoff()); - fail_on_test(q.streamoff()); + fail_on_test(node->streamoff(q.g_type())); + fail_on_test(node->streamoff(q.g_type())); } return 0; } diff -Nru v4l-utils-1.0.0+r2263/utils/v4l2-compliance/v4l2-test-controls.cpp v4l-utils-1.0.0+r2364/utils/v4l2-compliance/v4l2-test-controls.cpp --- v4l-utils-1.0.0+r2263/utils/v4l2-compliance/v4l2-test-controls.cpp 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/v4l2-compliance/v4l2-test-controls.cpp 2014-08-12 09:02:18.000000000 +0000 @@ -379,7 +379,7 @@ ctrl.id = iter->id; ctrl.value = iter->minimum - 1; ret = doioctl(node, VIDIOC_S_CTRL, &ctrl); - if (ret && ret != ERANGE) + if (ret && ret != EIO && ret != ERANGE) return fail("invalid minimum range check\n"); if (!ret && checkSimpleCtrl(ctrl, *iter)) return fail("invalid control %08x\n", iter->id); @@ -389,7 +389,7 @@ ctrl.id = iter->id; ctrl.value = iter->maximum + 1; ret = doioctl(node, VIDIOC_S_CTRL, &ctrl); - if (ret && ret != ERANGE) + if (ret && ret != EIO && ret != ERANGE) return fail("invalid maximum range check\n"); if (!ret && checkSimpleCtrl(ctrl, *iter)) return fail("invalid control %08x\n", iter->id); @@ -402,7 +402,7 @@ if (ret == ERANGE) warn("%s: returns ERANGE for in-range, but non-step-multiple value\n", iter->name); - else if (ret) + else if (ret && ret != EIO) return fail("returns error for in-range, but non-step-multiple value\n"); } @@ -432,15 +432,15 @@ ctrl.id = iter->id; ctrl.value = iter->minimum; ret = doioctl(node, VIDIOC_S_CTRL, &ctrl); - if (ret) + if (ret && ret != EIO) return fail("could not set minimum value\n"); ctrl.value = iter->maximum; ret = doioctl(node, VIDIOC_S_CTRL, &ctrl); - if (ret) + if (ret && ret != EIO) return fail("could not set maximum value\n"); ctrl.value = iter->default_value; ret = doioctl(node, VIDIOC_S_CTRL, &ctrl); - if (ret) + if (ret && ret != EIO) return fail("could not set default value\n"); } } @@ -721,8 +721,8 @@ return fail("subscribe event for control '%s' failed\n", iter->name); //if (iter->type == V4L2_CTRL_TYPE_CTRL_CLASS) FD_ZERO(&set); - FD_SET(node->vfd.fd, &set); - ret = select(node->vfd.fd + 1, NULL, NULL, &set, &timeout); + FD_SET(node->g_fd(), &set); + ret = select(node->g_fd() + 1, NULL, NULL, &set, &timeout); if (ret == 0) { if (iter->type != V4L2_CTRL_TYPE_CTRL_CLASS) return fail("failed to find event for control '%s'\n", iter->name); diff -Nru v4l-utils-1.0.0+r2263/utils/v4l2-compliance/v4l2-test-formats.cpp v4l-utils-1.0.0+r2364/utils/v4l2-compliance/v4l2-test-formats.cpp --- v4l-utils-1.0.0+r2263/utils/v4l2-compliance/v4l2-test-formats.cpp 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/v4l2-compliance/v4l2-test-formats.cpp 2014-08-12 09:02:18.000000000 +0000 @@ -165,7 +165,7 @@ frmsize.discrete.width + 1, frmsize.discrete.height, 0); if (ret && ret != ENOTTY) return ret; - if (ret == 0 && !(node->caps & (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_CAPTURE_MPLANE))) + if (ret == 0 && !(node->g_caps() & (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_CAPTURE_MPLANE))) return fail("found discrete framesizes when no video capture is supported\n"); break; case V4L2_FRMSIZE_TYPE_CONTINUOUS: @@ -243,7 +243,7 @@ return fail("fmtdesc.description not set\n"); if (!fmtdesc.pixelformat) return fail("fmtdesc.pixelformat not set\n"); - if (!wrapper && (fmtdesc.flags & V4L2_FMT_FLAG_EMULATED)) + if (node->g_direct() && (fmtdesc.flags & V4L2_FMT_FLAG_EMULATED)) return fail("drivers must never set the emulated flag\n"); if (fmtdesc.flags & ~(V4L2_FMT_FLAG_COMPRESSED | V4L2_FMT_FLAG_EMULATED)) return fail("unknown flag %08x returned\n", fmtdesc.flags); @@ -282,10 +282,10 @@ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: case V4L2_BUF_TYPE_SDR_CAPTURE: - if (ret && (node->caps & buftype2cap[type])) + if (ret && (node->g_caps() & buftype2cap[type])) return fail("%s cap set, but no %s formats defined\n", buftype2s(type).c_str(), buftype2s(type).c_str()); - if (!ret && !(node->caps & buftype2cap[type])) + if (!ret && !(node->g_caps() & buftype2cap[type])) return fail("%s cap not set, but %s formats defined\n", buftype2s(type).c_str(), buftype2s(type).c_str()); break; @@ -323,7 +323,6 @@ int testFBuf(struct node *node) { struct v4l2_framebuffer fbuf; - struct v4l2_pix_format &fmt = fbuf.fmt; __u32 caps; __u32 flags; int ret; @@ -331,15 +330,15 @@ memset(&fbuf, 0xff, sizeof(fbuf)); fbuf.fmt.priv = 0; ret = doioctl(node, VIDIOC_G_FBUF, &fbuf); - fail_on_test(ret == 0 && !(node->caps & (V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_VIDEO_OUTPUT_OVERLAY))); - fail_on_test(ret == ENOTTY && (node->caps & (V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_VIDEO_OUTPUT_OVERLAY))); + fail_on_test(ret == 0 && !(node->g_caps() & (V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_VIDEO_OUTPUT_OVERLAY))); + fail_on_test(ret == ENOTTY && (node->g_caps() & (V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_VIDEO_OUTPUT_OVERLAY))); if (ret == ENOTTY) return ret; if (ret && ret != EINVAL) return fail("expected EINVAL, but got %d when getting framebuffer format\n", ret); node->fbuf_caps = caps = fbuf.capability; flags = fbuf.flags; - if (node->caps & V4L2_CAP_VIDEO_OUTPUT_OVERLAY) + if (node->g_caps() & V4L2_CAP_VIDEO_OUTPUT_OVERLAY) fail_on_test(!fbuf.base); if (flags & V4L2_FBUF_FLAG_CHROMAKEY) fail_on_test(!(caps & V4L2_FBUF_CAP_CHROMAKEY)); @@ -351,18 +350,18 @@ fail_on_test(!(caps & V4L2_FBUF_CAP_LOCAL_INV_ALPHA)); if (flags & V4L2_FBUF_FLAG_SRC_CHROMAKEY) fail_on_test(!(caps & V4L2_FBUF_CAP_SRC_CHROMAKEY)); - fail_on_test(!fmt.width || !fmt.height); - if (fmt.priv) + fail_on_test(!fbuf.fmt.width || !fbuf.fmt.height); + if (fbuf.fmt.priv) warn("fbuf.fmt.priv is non-zero\n"); /* Not yet: unclear what EXTERNOVERLAY means in a output overlay context if (caps & V4L2_FBUF_CAP_EXTERNOVERLAY) { - fail_on_test(fmt.bytesperline); - fail_on_test(fmt.sizeimage); + fail_on_test(fbuf.fmt.bytesperline); + fail_on_test(fbuf.fmt.sizeimage); fail_on_test(fbuf.base); }*/ - fail_on_test(fmt.bytesperline && fmt.bytesperline < fmt.width); - fail_on_test(fmt.sizeimage && fmt.sizeimage < fmt.bytesperline * fmt.height); - fail_on_test(testColorspace(fmt.pixelformat, fmt.colorspace)); + fail_on_test(fbuf.fmt.bytesperline && fbuf.fmt.bytesperline < fbuf.fmt.width); + fail_on_test(fbuf.fmt.sizeimage && fbuf.fmt.sizeimage < fbuf.fmt.bytesperline * fbuf.fmt.height); + fail_on_test(testColorspace(fbuf.fmt.pixelformat, fbuf.fmt.colorspace)); return 0; } @@ -417,8 +416,8 @@ fail_on_test(!pix.sizeimage); fail_on_test(testColorspace(pix.pixelformat, pix.colorspace)); fail_on_test(pix.field == V4L2_FIELD_ANY); - if (pix.priv) - return fail("priv is non-zero!\n"); + if (pix.priv && pix.priv != V4L2_PIX_FMT_PRIV_MAGIC) + return fail("priv is non-zero and non-magic!\n"); break; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: @@ -518,6 +517,7 @@ if (set.find(sdr.pixelformat) == set.end()) return fail("unknown pixelformat %08x for buftype %d\n", pix.pixelformat, type); + fail_on_test(sdr.buffersize == 0); fail_on_test(check_0(sdr.reserved, sizeof(sdr.reserved))); break; case V4L2_BUF_TYPE_PRIVATE: @@ -552,10 +552,10 @@ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: case V4L2_BUF_TYPE_SDR_CAPTURE: - if (ret && (node->caps & buftype2cap[type])) + if (ret && (node->g_caps() & buftype2cap[type])) return fail("%s cap set, but no %s formats defined\n", buftype2s(type).c_str(), buftype2s(type).c_str()); - if (!ret && !(node->caps & buftype2cap[type])) + if (!ret && !(node->g_caps() & buftype2cap[type])) return fail("%s cap not set, but %s formats defined\n", buftype2s(type).c_str(), buftype2s(type).c_str()); break; @@ -585,10 +585,10 @@ case V4L2_BUF_TYPE_VIDEO_OUTPUT: if (!memcmp(&f1.fmt.pix, &f2.fmt.pix, sizeof(f1.fmt.pix))) return true; - printf("\t\tG_FMT: %dx%d, %x, %d, %d, %d, %d, %d\n", + printf("\t\tG_FMT: %dx%d, %x, %d, %d, %d, %d, %x\n", pix1.width, pix1.height, pix1.pixelformat, pix1.field, pix1.bytesperline, pix1.sizeimage, pix1.colorspace, pix1.priv); - printf("\t\tTRY/S_FMT: %dx%d, %x, %d, %d, %d, %d, %d\n", + printf("\t\tTRY/S_FMT: %dx%d, %x, %d, %d, %d, %d, %x\n", pix2.width, pix2.height, pix2.pixelformat, pix2.field, pix2.bytesperline, pix2.sizeimage, pix2.colorspace, pix2.priv); return false; @@ -774,7 +774,7 @@ // test is pointless. // This test will also never succeed if we are using the libv4l2 // wrapper. - if (wrapper || (pixfmt1 == pixfmt2 && w1 == w2 && h1 == h2)) + if (!node->g_direct() || (pixfmt1 == pixfmt2 && w1 == w2 && h1 == h2)) return 0; if (type == V4L2_BUF_TYPE_SDR_CAPTURE) { @@ -994,13 +994,13 @@ ret = doioctl(node, VIDIOC_G_SLICED_VBI_CAP, &cap); if (ret == ENOTTY || ret == EINVAL) { if (node->cur_io_caps & V4L2_IN_CAP_STD) - fail_on_test(sliced_type && (node->caps & buftype2cap[type])); + fail_on_test(sliced_type && (node->g_caps() & buftype2cap[type])); return ret == ENOTTY ? ret : 0; } fail_on_test(ret); fail_on_test(check_0(cap.reserved, sizeof(cap.reserved))); fail_on_test(cap.type != type); - fail_on_test(!sliced_type || !(node->caps & buftype2cap[type])); + fail_on_test(!sliced_type || !(node->g_caps() & buftype2cap[type])); for (int f = 0; f < 2; f++) for (int i = 0; i < 24; i++) @@ -1036,9 +1036,9 @@ if (ret) return fail("reserved not zeroed\n"); fail_on_test(cap->readbuffers > VIDEO_MAX_FRAME); - if (!(node->caps & V4L2_CAP_READWRITE)) + if (!(node->g_caps() & V4L2_CAP_READWRITE)) fail_on_test(cap->readbuffers); - else if (node->caps & V4L2_CAP_STREAMING) + else if (node->g_caps() & V4L2_CAP_STREAMING) fail_on_test(!cap->readbuffers); fail_on_test(cap->capability & ~V4L2_CAP_TIMEPERFRAME); fail_on_test(cap->capturemode & ~V4L2_MODE_HIGHQUALITY); @@ -1054,9 +1054,9 @@ if (ret) return fail("reserved not zeroed\n"); fail_on_test(out->writebuffers > VIDEO_MAX_FRAME); - if (!(node->caps & V4L2_CAP_READWRITE)) + if (!(node->g_caps() & V4L2_CAP_READWRITE)) fail_on_test(out->writebuffers); - else if (node->caps & V4L2_CAP_STREAMING) + else if (node->g_caps() & V4L2_CAP_STREAMING) fail_on_test(!out->writebuffers); fail_on_test(out->capability & ~V4L2_CAP_TIMEPERFRAME); fail_on_test(out->outputmode); @@ -1118,7 +1118,7 @@ type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && type != V4L2_BUF_TYPE_VIDEO_OUTPUT) return fail("G/S_PARM is only allowed for video capture/output\n"); - if (!(node->caps & buftype2cap[type])) + if (!(node->g_caps() & buftype2cap[type])) return fail("%s cap not set, but G/S_PARM worked\n", buftype2s(type).c_str()); } diff -Nru v4l-utils-1.0.0+r2263/utils/v4l2-compliance/v4l2-test-input-output.cpp v4l-utils-1.0.0+r2364/utils/v4l2-compliance/v4l2-test-input-output.cpp --- v4l-utils-1.0.0+r2263/utils/v4l2-compliance/v4l2-test-input-output.cpp 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/v4l2-compliance/v4l2-test-input-output.cpp 2014-08-12 09:02:18.000000000 +0000 @@ -110,8 +110,8 @@ if (node->is_sdr) fail_on_test(!(V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_1HZ)); fail_on_test(!(tuner.capability & V4L2_TUNER_CAP_FREQ_BANDS)); - fail_on_test(!(node->caps & V4L2_CAP_HW_FREQ_SEEK) && hwseek_caps); - fail_on_test((node->caps & V4L2_CAP_HW_FREQ_SEEK) && + fail_on_test(!(node->g_caps() & V4L2_CAP_HW_FREQ_SEEK) && hwseek_caps); + fail_on_test((node->g_caps() & V4L2_CAP_HW_FREQ_SEEK) && !(tuner.capability & (V4L2_TUNER_CAP_HWSEEK_BOUNDED | V4L2_TUNER_CAP_HWSEEK_WRAP))); if (tuner.rangelow > tuner.rangehigh) return fail("rangelow > rangehigh\n"); @@ -136,10 +136,10 @@ return fail("V4L2_TUNER_CAP_RDS is set, but not V4L2_TUNER_CAP_RDS_* or vice versa\n"); fail_on_test(node->is_sdr && have_rds); if ((tuner.capability & V4L2_TUNER_CAP_RDS_BLOCK_IO) && - !(node->caps & V4L2_CAP_READWRITE)) + !(node->g_caps() & V4L2_CAP_READWRITE)) return fail("V4L2_TUNER_CAP_RDS_BLOCK_IO is set, but not V4L2_CAP_READWRITE\n"); if (node->is_radio && !(tuner.capability & V4L2_TUNER_CAP_RDS_BLOCK_IO) && - (node->caps & V4L2_CAP_READWRITE)) + (node->g_caps() & V4L2_CAP_READWRITE)) return fail("V4L2_TUNER_CAP_RDS_BLOCK_IO is not set, but V4L2_CAP_READWRITE is\n"); if (std == V4L2_STD_NTSC_M && (tuner.rxsubchans & V4L2_TUNER_SUB_LANG1)) return fail("LANG1 subchan, but NTSC-M standard\n"); @@ -208,13 +208,13 @@ tuner.index = t; if (doioctl(node, VIDIOC_S_TUNER, &tuner) != EINVAL) return fail("could set invalid tuner %d\n", t); - if (node->tuners && !(node->caps & V4L2_CAP_TUNER)) + if (node->tuners && !(node->g_caps() & V4L2_CAP_TUNER)) return fail("tuners found, but no tuner capability set\n"); - if (!node->tuners && (node->caps & V4L2_CAP_TUNER)) + if (!node->tuners && (node->g_caps() & V4L2_CAP_TUNER)) return fail("no tuners found, but tuner capability set\n"); - if (has_rds && !(node->caps & V4L2_CAP_RDS_CAPTURE)) + if (has_rds && !(node->g_caps() & V4L2_CAP_RDS_CAPTURE)) return fail("RDS tuner capability, but no RDS capture capability?\n"); - if (!has_rds && (node->caps & V4L2_CAP_RDS_CAPTURE)) + if (!has_rds && (node->g_caps() & V4L2_CAP_RDS_CAPTURE)) return fail("No RDS tuner capability, but RDS capture capability?\n"); return 0; } @@ -244,10 +244,10 @@ if (freq.type != V4L2_TUNER_RADIO && freq.type != V4L2_TUNER_ANALOG_TV && freq.type != V4L2_TUNER_ADC && freq.type != V4L2_TUNER_RF) return fail("returned invalid tuner type %d\n", freq.type); - if (freq.type == V4L2_TUNER_RADIO && !(node->caps & V4L2_CAP_RADIO)) + if (freq.type == V4L2_TUNER_RADIO && !(node->g_caps() & V4L2_CAP_RADIO)) return fail("radio tuner found but no radio capability set\n"); if ((freq.type == V4L2_TUNER_ADC || freq.type == V4L2_TUNER_RF) && - !(node->caps & V4L2_CAP_SDR_CAPTURE)) + !(node->g_caps() & V4L2_CAP_SDR_CAPTURE)) return fail("sdr tuner found but no sdr capture capability set\n"); if (freq.type != tuner.type) return fail("frequency tuner type and tuner type mismatch\n"); @@ -292,7 +292,7 @@ } /* If this is a modulator device, then skip the remaining tests */ - if (node->caps & V4L2_CAP_MODULATOR) + if (node->g_caps() & V4L2_CAP_MODULATOR) return 0; freq.tuner = t; @@ -327,11 +327,11 @@ seek.tuner = t; seek.type = V4L2_TUNER_RADIO; ret = doioctl(node, VIDIOC_S_HW_FREQ_SEEK, &seek); - if (!(node->caps & V4L2_CAP_HW_FREQ_SEEK) && ret != ENOTTY) + if (!(node->g_caps() & V4L2_CAP_HW_FREQ_SEEK) && ret != ENOTTY) return fail("hw seek supported but capability not set\n"); if (!node->is_radio && ret != ENOTTY) return fail("hw seek supported on a non-radio node?!\n"); - if (!node->is_radio || !(node->caps & V4L2_CAP_HW_FREQ_SEEK)) + if (!node->is_radio || !(node->g_caps() & V4L2_CAP_HW_FREQ_SEEK)) return ENOTTY; seek.type = V4L2_TUNER_ANALOG_TV; ret = doioctl(node, VIDIOC_S_HW_FREQ_SEEK, &seek); @@ -490,7 +490,7 @@ node->audio_inputs++; i++; } - if (node->audio_inputs && !(node->caps & V4L2_CAP_AUDIO)) + if (node->audio_inputs && !(node->g_caps() & V4L2_CAP_AUDIO)) return fail("audio inputs reported, but no CAP_AUDIO set\n"); return 0; } @@ -592,10 +592,10 @@ if (have_rds ^ have_rds_method) return fail("V4L2_TUNER_CAP_RDS is set, but not V4L2_TUNER_CAP_RDS_* or vice versa\n"); if ((mod.capability & V4L2_TUNER_CAP_RDS_BLOCK_IO) && - !(node->caps & V4L2_CAP_READWRITE)) + !(node->g_caps() & V4L2_CAP_READWRITE)) return fail("V4L2_TUNER_CAP_RDS_BLOCK_IO is set, but not V4L2_CAP_READWRITE\n"); if (!(mod.capability & V4L2_TUNER_CAP_RDS_BLOCK_IO) && - (node->caps & V4L2_CAP_READWRITE)) + (node->g_caps() & V4L2_CAP_READWRITE)) return fail("V4L2_TUNER_CAP_RDS_BLOCK_IO is not set, but V4L2_CAP_READWRITE is\n"); return checkEnumFreqBands(node, mod.index, V4L2_TUNER_RADIO, mod.capability, mod.rangelow, mod.rangehigh); @@ -632,13 +632,13 @@ mod.index = m; if (doioctl(node, VIDIOC_S_MODULATOR, &mod) != EINVAL) return fail("could set invalid modulator %d\n", m); - if (node->modulators && !(node->caps & V4L2_CAP_MODULATOR)) + if (node->modulators && !(node->g_caps() & V4L2_CAP_MODULATOR)) return fail("modulators found, but no modulator capability set\n"); - if (!node->modulators && (node->caps & V4L2_CAP_MODULATOR)) + if (!node->modulators && (node->g_caps() & V4L2_CAP_MODULATOR)) return fail("no modulators found, but modulator capability set\n"); - if (has_rds && !(node->caps & V4L2_CAP_RDS_OUTPUT)) + if (has_rds && !(node->g_caps() & V4L2_CAP_RDS_OUTPUT)) return fail("RDS modulator capability, but no RDS output capability?\n"); - if (!has_rds && (node->caps & V4L2_CAP_RDS_OUTPUT)) + if (!has_rds && (node->g_caps() & V4L2_CAP_RDS_OUTPUT)) return fail("No RDS modulator capability, but RDS output capability?\n"); return 0; } @@ -699,7 +699,7 @@ } /* If this is a tuner device, then skip the remaining tests */ - if (node->caps & V4L2_CAP_TUNER) + if (node->g_caps() & V4L2_CAP_TUNER) return 0; freq.tuner = m; @@ -833,7 +833,7 @@ o++; } - if (node->audio_outputs && !(node->caps & V4L2_CAP_AUDIO)) + if (node->audio_outputs && !(node->g_caps() & V4L2_CAP_AUDIO)) return fail("audio outputs reported, but no CAP_AUDIO set\n"); return 0; } @@ -893,7 +893,7 @@ return fail("invalid audioset for output %d\n", o); } - if (node->audio_outputs == 0 && node->audio_inputs == 0 && (node->caps & V4L2_CAP_AUDIO)) + if (node->audio_outputs == 0 && node->audio_inputs == 0 && (node->g_caps() & V4L2_CAP_AUDIO)) return fail("no audio inputs or outputs reported, but CAP_AUDIO set\n"); return node->audio_outputs ? 0 : ENOTTY; } diff -Nru v4l-utils-1.0.0+r2263/utils/v4l2-compliance/v4l2-test-io-config.cpp v4l-utils-1.0.0+r2364/utils/v4l2-compliance/v4l2-test-io-config.cpp --- v4l-utils-1.0.0+r2263/utils/v4l2-compliance/v4l2-test-io-config.cpp 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/v4l2-compliance/v4l2-test-io-config.cpp 2014-08-12 09:02:18.000000000 +0000 @@ -155,7 +155,7 @@ struct v4l2_enum_dv_timings enumtimings; struct v4l2_dv_timings timings; struct v4l2_format fmt; - bool is_mplane = node->caps & (V4L2_CAP_VIDEO_CAPTURE_MPLANE | + bool is_mplane = node->g_caps() & (V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_VIDEO_M2M_MPLANE); unsigned type; @@ -372,6 +372,12 @@ fail_on_test(!is_input); fail_on_test(ret); fail_on_test(check_0(edid.reserved, sizeof(edid.reserved))); + if (blocks == 256) + return 0; + edid.blocks = 256; + ret = doioctl(node, VIDIOC_S_EDID, &edid); + fail_on_test(ret != E2BIG); + fail_on_test(edid.blocks == 0 || edid.blocks >= 256); return 0; } diff -Nru v4l-utils-1.0.0+r2263/utils/v4l2-compliance/v4l-helpers.h v4l-utils-1.0.0+r2364/utils/v4l2-compliance/v4l-helpers.h --- v4l-utils-1.0.0+r2263/utils/v4l2-compliance/v4l-helpers.h 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/v4l2-compliance/v4l-helpers.h 2014-08-12 09:02:18.000000000 +0000 @@ -2,54 +2,220 @@ #define _V4L_HELPERS_H_ #include +#include +#include +#include +#include +#include +#include #include +#include #include #include +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + struct v4l_fd { int fd; + struct v4l2_capability cap; + char devname[128]; + __u32 type; __u32 caps; bool trace; - int (*ioctl)(int fd, unsigned long cmd, ...); + bool direct; + bool have_query_ext_ctrl; + bool have_ext_ctrls; + bool have_next_ctrl; + bool have_selection; + + int (*open)(struct v4l_fd *f, const char *file, int oflag, ...); + int (*close)(struct v4l_fd *f); + int (*ioctl)(struct v4l_fd *f, unsigned long cmd, ...); + ssize_t (*read)(struct v4l_fd *f, void *buffer, size_t n); + ssize_t (*write)(struct v4l_fd *f, const void *buffer, size_t n); void *(*mmap)(void *addr, size_t length, int prot, int flags, - int fd, int64_t offset); - int (*munmap)(void *addr, size_t length); + struct v4l_fd *f, off_t offset); + int (*munmap)(struct v4l_fd *f, void *addr, size_t length); }; -static inline int v4l_named_ioctl(struct v4l_fd *f, const char *cmd_name, - unsigned long cmd, void *arg) +#ifdef __LIBV4L2_H + +static inline int v4l_wrap_open(struct v4l_fd *f, const char *file, int oflag, ...) +{ + return f->direct ? open(file, oflag) : v4l2_open(file, oflag); +} + +static inline int v4l_wrap_close(struct v4l_fd *f) +{ + return f->direct ? close(f->fd) : v4l2_close(f->fd); +} + +static inline ssize_t v4l_wrap_read(struct v4l_fd *f, void *buffer, size_t n) +{ + return f->direct ? read(f->fd, buffer, n) : v4l2_read(f->fd, buffer, n); +} + +static inline ssize_t v4l_wrap_write(struct v4l_fd *f, const void *buffer, size_t n) +{ + return f->direct ? write(f->fd, buffer, n) : v4l2_write(f->fd, buffer, n); +} + +static inline int v4l_wrap_ioctl(struct v4l_fd *f, unsigned long cmd, ...) +{ + void *arg; + va_list ap; + + va_start(ap, cmd); + arg = va_arg(ap, void *); + va_end(ap); + return f->direct ? ioctl(f->fd, cmd, arg) : v4l2_ioctl(f->fd, cmd, arg); +} + +static inline void *v4l_wrap_mmap(void *start, size_t length, int prot, int flags, + struct v4l_fd *f, off_t offset) +{ + return f->direct ? mmap(start, length, prot, flags, f->fd, offset) : + v4l2_mmap(start, length, prot, flags, f->fd, offset); +} + +static inline int v4l_wrap_munmap(struct v4l_fd *f, void *start, size_t length) +{ + return f->direct ? munmap(start, length) : v4l2_munmap(start, length); +} + +static inline bool v4l_fd_g_direct(const struct v4l_fd *f) +{ + return f->direct; +} + +static inline void v4l_fd_s_direct(struct v4l_fd *f, bool direct) +{ + f->direct = direct; +} + +#else + +static inline int v4l_wrap_open(struct v4l_fd *f, const char *file, int oflag, ...) +{ + return open(file, oflag); +} + +static inline int v4l_wrap_close(struct v4l_fd *f) +{ + return close(f->fd); +} + +static inline ssize_t v4l_wrap_read(struct v4l_fd *f, void *buffer, size_t n) +{ + return read(f->fd, buffer, n); +} + +static inline ssize_t v4l_wrap_write(struct v4l_fd *f, const void *buffer, size_t n) +{ + return write(f->fd, buffer, n); +} + +static inline int v4l_wrap_ioctl(struct v4l_fd *f, unsigned long cmd, ...) +{ + void *arg; + va_list ap; + + va_start(ap, cmd); + arg = va_arg(ap, void *); + va_end(ap); + return ioctl(f->fd, cmd, arg); +} + +static inline void *v4l_wrap_mmap(void *start, size_t length, int prot, int flags, + struct v4l_fd *f, off_t offset) +{ + return mmap(start, length, prot, flags, f->fd, offset); +} + +static inline int v4l_wrap_munmap(struct v4l_fd *f, void *start, size_t length) +{ + return munmap(start, length); +} + +static inline bool v4l_fd_g_direct(const struct v4l_fd *f) +{ + return true; +} + +static inline void v4l_fd_s_direct(struct v4l_fd *f, bool direct) +{ +} + +#endif + +static inline void v4l_fd_init(struct v4l_fd *f) +{ + memset(f, 0, sizeof(*f)); + f->fd = -1; + f->open = v4l_wrap_open; + f->close = v4l_wrap_close; + f->ioctl = v4l_wrap_ioctl; + f->read = v4l_wrap_read; + f->write = v4l_wrap_write; + f->mmap = v4l_wrap_mmap; + f->munmap = v4l_wrap_munmap; +} + +static inline bool v4l_fd_g_trace(const struct v4l_fd *f) +{ + return f->trace; +} + +static inline void v4l_fd_s_trace(struct v4l_fd *f, bool trace) +{ + f->trace = trace; +} + +static inline int v4l_named_ioctl(struct v4l_fd *f, + const char *cmd_name, unsigned long cmd, void *arg) { int retval; int e; - errno = 0; - retval = f->ioctl(f->fd, cmd, arg); - e = errno; + retval = f->ioctl(f, cmd, arg); + e = retval == 0 ? 0 : errno; if (f->trace) - fprintf(stderr, "\t\t%s returned %d (%s)\n", cmd_name, retval, strerror(e)); - return retval ? e : 0; + fprintf(stderr, "\t\t%s returned %d (%s)\n", + cmd_name, retval, strerror(e)); + return retval == -1 ? e : (retval ? -1 : 0); } #define v4l_ioctl(f, cmd, arg) v4l_named_ioctl(f, #cmd, cmd, arg) -/* - * mmap has a different prototype compared to v4l2_mmap. Because of - * this we have to make a wrapper for it. - */ -static inline void *v4l_fd_mmap(void *addr, size_t length, int prot, int flags, - int fd, int64_t offset) +static inline void *v4l_mmap(struct v4l_fd *f, size_t length, off_t offset) { - return mmap(addr, length, prot, flags, fd, offset); + return f->mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, f, offset); } -static inline void *v4l_mmap(struct v4l_fd *f, size_t length, off_t offset) +static inline int v4l_munmap(struct v4l_fd *f, void *start, size_t length) { - return f->mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, f->fd, offset); + return f->munmap(f, start, length); } -static inline int v4l_munmap(struct v4l_fd *f, void *start, size_t length) +static inline ssize_t v4l_read(struct v4l_fd *f, void *buffer, size_t n) { - return f->munmap(start, length) ? errno : 0; + return f->read(f, buffer, n); +} + +static inline ssize_t v4l_write(struct v4l_fd *f, const void *buffer, size_t n) +{ + return f->write(f, buffer, n); +} + +static inline int v4l_close(struct v4l_fd *f) +{ + int res = f->close(f); + + f->caps = f->type = 0; + f->fd = -1; + return res; } static inline int v4l_querycap(struct v4l_fd *f, struct v4l2_capability *cap) @@ -63,162 +229,144 @@ cap->device_caps : cap->capabilities; } -static inline __u32 v4l_g_caps(struct v4l_fd *f) +static inline __u32 v4l_g_type(const struct v4l_fd *f) +{ + return f->type; +} + +static inline void v4l_s_type(struct v4l_fd *f, __u32 type) +{ + f->type = type; +} + +static inline __u32 v4l_g_selection_type(const struct v4l_fd *f) +{ + if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) + return V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) + return V4L2_BUF_TYPE_VIDEO_OUTPUT; + return f->type; +} + +static inline __u32 v4l_g_caps(const struct v4l_fd *f) { return f->caps; } -static inline bool v4l_has_vid_cap(struct v4l_fd *f) +static inline bool v4l_has_vid_cap(const struct v4l_fd *f) { return v4l_g_caps(f) & (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_CAPTURE_MPLANE); } -static inline bool v4l_has_vid_out(struct v4l_fd *f) +static inline bool v4l_has_vid_out(const struct v4l_fd *f) { return v4l_g_caps(f) & (V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_MPLANE); } -static inline bool v4l_has_vid_m2m(struct v4l_fd *f) +static inline bool v4l_has_vid_m2m(const struct v4l_fd *f) { return v4l_g_caps(f) & (V4L2_CAP_VIDEO_M2M | V4L2_CAP_VIDEO_M2M_MPLANE); } -static inline bool v4l_has_vid_mplane(struct v4l_fd *f) +static inline bool v4l_has_vid_mplane(const struct v4l_fd *f) { return v4l_g_caps(f) & (V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_VIDEO_M2M_MPLANE); } -static inline bool v4l_has_overlay_cap(struct v4l_fd *f) +static inline bool v4l_has_overlay_cap(const struct v4l_fd *f) { return v4l_g_caps(f) & V4L2_CAP_VIDEO_OVERLAY; } -static inline bool v4l_has_overlay_out(struct v4l_fd *f) +static inline bool v4l_has_overlay_out(const struct v4l_fd *f) { return v4l_g_caps(f) & V4L2_CAP_VIDEO_OUTPUT_OVERLAY; } -static inline bool v4l_has_raw_vbi_cap(struct v4l_fd *f) +static inline bool v4l_has_raw_vbi_cap(const struct v4l_fd *f) { return v4l_g_caps(f) & V4L2_CAP_VBI_CAPTURE; } -static inline bool v4l_has_sliced_vbi_cap(struct v4l_fd *f) +static inline bool v4l_has_sliced_vbi_cap(const struct v4l_fd *f) { return v4l_g_caps(f) & V4L2_CAP_SLICED_VBI_CAPTURE; } -static inline bool v4l_has_vbi_cap(struct v4l_fd *f) +static inline bool v4l_has_vbi_cap(const struct v4l_fd *f) { return v4l_has_raw_vbi_cap(f) || v4l_has_sliced_vbi_cap(f); } -static inline bool v4l_has_raw_vbi_out(struct v4l_fd *f) +static inline bool v4l_has_raw_vbi_out(const struct v4l_fd *f) { return v4l_g_caps(f) & V4L2_CAP_VBI_OUTPUT; } -static inline bool v4l_has_sliced_vbi_out(struct v4l_fd *f) +static inline bool v4l_has_sliced_vbi_out(const struct v4l_fd *f) { return v4l_g_caps(f) & V4L2_CAP_SLICED_VBI_OUTPUT; } -static inline bool v4l_has_vbi_out(struct v4l_fd *f) +static inline bool v4l_has_vbi_out(const struct v4l_fd *f) { return v4l_has_raw_vbi_out(f) || v4l_has_sliced_vbi_out(f); } -static inline bool v4l_has_vbi(struct v4l_fd *f) +static inline bool v4l_has_vbi(const struct v4l_fd *f) { return v4l_has_vbi_cap(f) || v4l_has_vbi_out(f); } -static inline bool v4l_has_radio_rx(struct v4l_fd *f) +static inline bool v4l_has_radio_rx(const struct v4l_fd *f) { return (v4l_g_caps(f) & V4L2_CAP_RADIO) && (v4l_g_caps(f) & V4L2_CAP_TUNER); } -static inline bool v4l_has_radio_tx(struct v4l_fd *f) +static inline bool v4l_has_radio_tx(const struct v4l_fd *f) { - return (v4l_g_caps(f) & V4L2_CAP_RADIO) && - (v4l_g_caps(f) & V4L2_CAP_MODULATOR); + return v4l_g_caps(f) & V4L2_CAP_MODULATOR; } -static inline bool v4l_has_rds_cap(struct v4l_fd *f) +static inline bool v4l_has_rds_cap(const struct v4l_fd *f) { return v4l_g_caps(f) & V4L2_CAP_RDS_CAPTURE; } -static inline bool v4l_has_rds_out(struct v4l_fd *f) +static inline bool v4l_has_rds_out(const struct v4l_fd *f) { return v4l_g_caps(f) & V4L2_CAP_RDS_OUTPUT; } -static inline bool v4l_has_sdr_cap(struct v4l_fd *f) +static inline bool v4l_has_sdr_cap(const struct v4l_fd *f) { return v4l_g_caps(f) & V4L2_CAP_SDR_CAPTURE; } -static inline bool v4l_has_hwseek(struct v4l_fd *f) +static inline bool v4l_has_hwseek(const struct v4l_fd *f) { return v4l_g_caps(f) & V4L2_CAP_HW_FREQ_SEEK; } -static inline bool v4l_has_rw(struct v4l_fd *f) +static inline bool v4l_has_rw(const struct v4l_fd *f) { return v4l_g_caps(f) & V4L2_CAP_READWRITE; } -static inline bool v4l_has_streaming(struct v4l_fd *f) +static inline bool v4l_has_streaming(const struct v4l_fd *f) { return v4l_g_caps(f) & V4L2_CAP_STREAMING; } -static inline void v4l_fd_init(struct v4l_fd *f, int fd) +static inline bool v4l_has_ext_pix_format(const struct v4l_fd *f) { - struct v4l2_capability cap; - - f->fd = fd; - f->ioctl = ioctl; - f->mmap = v4l_fd_mmap; - f->munmap = munmap; - f->caps = v4l_querycap(f, &cap) ? 0 : v4l_capability_g_caps(&cap); -} - -#define v4l_fd_libv4l2_init(f, fd) \ - do { \ - struct v4l2_capability cap; \ - \ - (f)->fd = fd; \ - (f)->ioctl = v4l2_ioctl; \ - (f)->mmap = v4l2_mmap; \ - (f)->munmap = v4l2_munmap; \ - (f)->caps = v4l_querycap(f, &cap) ? 0 : \ - v4l_capability_g_caps(&cap); \ - } while (0) - -static inline __u32 v4l_buf_type_g_vid_cap(struct v4l_fd *f) -{ - if (v4l_g_caps(f) & (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_M2M)) - return V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (v4l_g_caps(f) & (V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_VIDEO_M2M_MPLANE)) - return V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - return 0; + return v4l_g_caps(f) & V4L2_CAP_EXT_PIX_FORMAT; } -static inline __u32 v4l_buf_type_g_vid_out(struct v4l_fd *f) -{ - if (f->caps & (V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_M2M)) - return V4L2_BUF_TYPE_VIDEO_OUTPUT; - if (f->caps & (V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_VIDEO_M2M_MPLANE)) - return V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; - return 0; -} - -static inline __u32 v4l_g_buf_type(struct v4l_fd *f) +static inline __u32 v4l_determine_type(const struct v4l_fd *f) { if (v4l_has_vid_mplane(f)) return v4l_has_vid_cap(f) ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : @@ -240,83 +388,52 @@ return 0; } - -static inline bool v4l_buf_type_is_planar(unsigned type) +static inline int v4l_open(struct v4l_fd *f, const char *devname, bool non_blocking) { - return V4L2_TYPE_IS_MULTIPLANAR(type); -} + struct v4l2_query_ext_ctrl qec = { V4L2_CTRL_FLAG_NEXT_CTRL }; + struct v4l2_ext_controls ec = { 0, 0 }; + struct v4l2_queryctrl qc = { V4L2_CTRL_FLAG_NEXT_CTRL }; + struct v4l2_selection sel = { 0 }; -static inline bool v4l_buf_type_is_output(unsigned type) -{ - return V4L2_TYPE_IS_OUTPUT(type); -} + f->fd = f->open(f, devname, O_RDWR | (non_blocking ? O_NONBLOCK : 0)); -static inline bool v4l_buf_type_is_capture(unsigned type) -{ - return !v4l_buf_type_is_output(type); -} - -static inline bool v4l_buf_type_is_video(unsigned type) -{ - switch (type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: - case V4L2_BUF_TYPE_VIDEO_OUTPUT: - case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: - return true; - default: - return false; + if (f->fd < 0) + return f->fd; + if (f->devname != devname) { + strncpy(f->devname, devname, sizeof(f->devname)); + f->devname[sizeof(f->devname) - 1] = '\0'; } -} - -static inline bool v4l_buf_type_is_raw_vbi(unsigned type) -{ - return type == V4L2_BUF_TYPE_VBI_CAPTURE || - type == V4L2_BUF_TYPE_VBI_OUTPUT; -} - -static inline bool v4l_buf_type_is_sliced_vbi(unsigned type) -{ - return type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE || - type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT; -} - -static inline bool v4l_buf_type_is_vbi(unsigned type) -{ - return v4l_buf_type_is_raw_vbi(type) || v4l_buf_type_is_sliced_vbi(type); -} - -static inline bool v4l_buf_type_is_overlay(unsigned type) -{ - return type == V4L2_BUF_TYPE_VIDEO_OVERLAY || - type == V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY; -} - -static inline bool v4l_buf_type_is_sdr(unsigned type) -{ - return type == V4L2_BUF_TYPE_SDR_CAPTURE; -} + if (v4l_querycap(f, &f->cap)) { + v4l_close(f); + return -1; + } + f->caps = v4l_capability_g_caps(&f->cap); + f->type = v4l_determine_type(f); -static inline int v4l_g_fmt(struct v4l_fd *f, struct v4l2_format *fmt, unsigned type) -{ - fmt->type = type; - return v4l_ioctl(f, VIDIOC_G_FMT, fmt); -} + f->have_query_ext_ctrl = v4l_ioctl(f, VIDIOC_QUERY_EXT_CTRL, &qec) != ENOTTY; + f->have_ext_ctrls = v4l_ioctl(f, VIDIOC_TRY_EXT_CTRLS, &ec) != ENOTTY; + f->have_next_ctrl = v4l_ioctl(f, VIDIOC_QUERYCTRL, &qc) != ENOTTY; + sel.type = v4l_g_selection_type(f); + sel.target = sel.type == V4L2_BUF_TYPE_VIDEO_CAPTURE ? + V4L2_SEL_TGT_CROP : V4L2_SEL_TGT_COMPOSE; + f->have_selection = v4l_ioctl(f, VIDIOC_G_SELECTION, &sel) != ENOTTY; -static inline int v4l_try_fmt(struct v4l_fd *f, struct v4l2_format *fmt) -{ - return v4l_ioctl(f, VIDIOC_TRY_FMT, fmt); + return f->fd; } -static inline int v4l_s_fmt(struct v4l_fd *f, struct v4l2_format *fmt) +static inline int v4l_reopen(struct v4l_fd *f, bool non_blocking) { - return v4l_ioctl(f, VIDIOC_S_FMT, fmt); + f->close(f); + return v4l_open(f, f->devname, non_blocking); } static inline void v4l_format_init(struct v4l2_format *fmt, unsigned type) { memset(fmt, 0, sizeof(*fmt)); fmt->type = type; + if (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE || + fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) + fmt->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; } static inline void v4l_format_s_width(struct v4l2_format *fmt, __u32 width) @@ -539,17 +656,24 @@ } static inline void v4l_format_s_bytesperline(struct v4l2_format *fmt, - unsigned plane, __u32 bytesperline) + __u32 bytesperline, unsigned plane) { switch (fmt->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: case V4L2_BUF_TYPE_VIDEO_OUTPUT: - fmt->fmt.pix.bytesperline = bytesperline; + if (plane == 0) + fmt->fmt.pix.bytesperline = bytesperline; break; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: fmt->fmt.pix_mp.plane_fmt[plane].bytesperline = bytesperline; break; + case V4L2_BUF_TYPE_VBI_CAPTURE: + case V4L2_BUF_TYPE_VBI_OUTPUT: + /* This assumes V4L2_PIX_FMT_GREY which is always the case */ + if (plane == 0) + fmt->fmt.vbi.samples_per_line = bytesperline; + break; } } @@ -559,22 +683,27 @@ switch (fmt->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: case V4L2_BUF_TYPE_VIDEO_OUTPUT: - return fmt->fmt.pix.bytesperline; + return plane ? 0 : fmt->fmt.pix.bytesperline; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: return fmt->fmt.pix_mp.plane_fmt[plane].bytesperline; + case V4L2_BUF_TYPE_VBI_CAPTURE: + case V4L2_BUF_TYPE_VBI_OUTPUT: + /* This assumes V4L2_PIX_FMT_GREY which is always the case */ + return plane ? 0 : fmt->fmt.vbi.samples_per_line; default: return 0; } } static inline void v4l_format_s_sizeimage(struct v4l2_format *fmt, - unsigned plane, __u32 sizeimage) + __u32 sizeimage, unsigned plane) { switch (fmt->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: case V4L2_BUF_TYPE_VIDEO_OUTPUT: - fmt->fmt.pix.sizeimage = sizeimage; + if (plane == 0) + fmt->fmt.pix.sizeimage = sizeimage; break; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: @@ -589,15 +718,41 @@ switch (fmt->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: case V4L2_BUF_TYPE_VIDEO_OUTPUT: - return fmt->fmt.pix.sizeimage; + return plane ? 0 : fmt->fmt.pix.sizeimage; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: return fmt->fmt.pix_mp.plane_fmt[plane].sizeimage; + case V4L2_BUF_TYPE_VBI_CAPTURE: + case V4L2_BUF_TYPE_VBI_OUTPUT: + /* This assumes V4L2_PIX_FMT_GREY which is always the case */ + return plane ? 0 : fmt->fmt.vbi.samples_per_line * + (fmt->fmt.vbi.count[0] + fmt->fmt.vbi.count[1]); + case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: + case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: + return plane ? 0 : fmt->fmt.sliced.io_size; + case V4L2_BUF_TYPE_SDR_CAPTURE: + return plane ? 0 : fmt->fmt.sdr.buffersize; default: return 0; } } +static inline int v4l_g_fmt(struct v4l_fd *f, struct v4l2_format *fmt, unsigned type) +{ + v4l_format_init(fmt, type ? type : f->type); + return v4l_ioctl(f, VIDIOC_G_FMT, fmt); +} + +static inline int v4l_try_fmt(struct v4l_fd *f, struct v4l2_format *fmt) +{ + return v4l_ioctl(f, VIDIOC_TRY_FMT, fmt); +} + +static inline int v4l_s_fmt(struct v4l_fd *f, struct v4l2_format *fmt) +{ + return v4l_ioctl(f, VIDIOC_S_FMT, fmt); +} + struct v4l_buffer { struct v4l2_plane planes[VIDEO_MAX_PLANES]; struct v4l2_buffer buf; @@ -616,44 +771,65 @@ } } -static inline bool v4l_buffer_is_planar(const struct v4l_buffer *buf) +static inline bool v4l_type_is_planar(unsigned type) +{ + return V4L2_TYPE_IS_MULTIPLANAR(type); +} + +static inline bool v4l_type_is_output(unsigned type) +{ + return V4L2_TYPE_IS_OUTPUT(type); +} + +static inline bool v4l_type_is_capture(unsigned type) { - return v4l_buf_type_is_planar(buf->buf.type); + return !v4l_type_is_output(type); } -static inline bool v4l_buffer_is_output(const struct v4l_buffer *buf) +static inline bool v4l_type_is_video(unsigned type) { - return v4l_buf_type_is_output(buf->buf.type); + switch (type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + return true; + default: + return false; + } } -static inline bool v4l_buffer_is_capture(const struct v4l_buffer *buf) +static inline bool v4l_type_is_raw_vbi(unsigned type) { - return v4l_buf_type_is_capture(buf->buf.type); + return type == V4L2_BUF_TYPE_VBI_CAPTURE || + type == V4L2_BUF_TYPE_VBI_OUTPUT; } -static inline bool v4l_buffer_is_video(const struct v4l_buffer *buf) +static inline bool v4l_type_is_sliced_vbi(unsigned type) { - return v4l_buf_type_is_video(buf->buf.type); + return type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE || + type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT; } -static inline bool v4l_buffer_is_vbi(const struct v4l_buffer *buf) +static inline bool v4l_type_is_vbi(unsigned type) { - return v4l_buf_type_is_vbi(buf->buf.type); + return v4l_type_is_raw_vbi(type) || v4l_type_is_sliced_vbi(type); } -static inline bool v4l_buffer_is_sliced_vbi(const struct v4l_buffer *buf) +static inline bool v4l_type_is_overlay(unsigned type) { - return v4l_buf_type_is_sliced_vbi(buf->buf.type); + return type == V4L2_BUF_TYPE_VIDEO_OVERLAY || + type == V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY; } -static inline bool v4l_buffer_is_sdr(const struct v4l_buffer *buf) +static inline bool v4l_type_is_sdr(unsigned type) { - return v4l_buf_type_is_sdr(buf->buf.type); + return type == V4L2_BUF_TYPE_SDR_CAPTURE; } static inline unsigned v4l_buffer_g_num_planes(const struct v4l_buffer *buf) { - if (v4l_buffer_is_planar(buf)) + if (v4l_type_is_planar(buf->buf.type)) return buf->buf.length; return 1; } @@ -765,74 +941,82 @@ static inline unsigned v4l_buffer_g_length(const struct v4l_buffer *buf, unsigned plane) { - if (v4l_buffer_is_planar(buf)) + if (v4l_type_is_planar(buf->buf.type)) return buf->planes[plane].length; - return buf->buf.length; + return plane ? 0 : buf->buf.length; +} + +static inline void v4l_buffer_s_length(struct v4l_buffer *buf, unsigned plane, unsigned length) +{ + if (v4l_type_is_planar(buf->buf.type)) + buf->planes[plane].length = length; + else if (plane == 0) + buf->buf.length = length; } static inline unsigned v4l_buffer_g_bytesused(const struct v4l_buffer *buf, unsigned plane) { - if (v4l_buffer_is_planar(buf)) + if (v4l_type_is_planar(buf->buf.type)) return buf->planes[plane].bytesused; - return buf->buf.bytesused; + return plane ? 0 : buf->buf.bytesused; } static inline void v4l_buffer_s_bytesused(struct v4l_buffer *buf, unsigned plane, __u32 bytesused) { - if (v4l_buffer_is_planar(buf)) + if (v4l_type_is_planar(buf->buf.type)) buf->planes[plane].bytesused = bytesused; - else + else if (plane == 0) buf->buf.bytesused = bytesused; } static inline unsigned v4l_buffer_g_data_offset(const struct v4l_buffer *buf, unsigned plane) { - if (v4l_buffer_is_planar(buf)) + if (v4l_type_is_planar(buf->buf.type)) return buf->planes[plane].data_offset; return 0; } static inline void v4l_buffer_s_data_offset(struct v4l_buffer *buf, unsigned plane, __u32 data_offset) { - if (v4l_buffer_is_planar(buf)) + if (v4l_type_is_planar(buf->buf.type)) buf->planes[plane].data_offset = data_offset; } static inline __u32 v4l_buffer_g_mem_offset(const struct v4l_buffer *buf, unsigned plane) { - if (v4l_buffer_is_planar(buf)) + if (v4l_type_is_planar(buf->buf.type)) return buf->planes[plane].m.mem_offset; - return buf->buf.m.offset; + return plane ? 0 : buf->buf.m.offset; } static inline void v4l_buffer_s_userptr(struct v4l_buffer *buf, unsigned plane, void *userptr) { - if (v4l_buffer_is_planar(buf)) + if (v4l_type_is_planar(buf->buf.type)) buf->planes[plane].m.userptr = (unsigned long)userptr; - else + else if (plane == 0) buf->buf.m.userptr = (unsigned long)userptr; } static inline void *v4l_buffer_g_userptr(const struct v4l_buffer *buf, unsigned plane) { - if (v4l_buffer_is_planar(buf)) + if (v4l_type_is_planar(buf->buf.type)) return (void *)buf->planes[plane].m.userptr; - return (void *)buf->buf.m.userptr; + return plane ? NULL : (void *)buf->buf.m.userptr; } static inline void v4l_buffer_s_fd(struct v4l_buffer *buf, unsigned plane, int fd) { - if (v4l_buffer_is_planar(buf)) + if (v4l_type_is_planar(buf->buf.type)) buf->planes[plane].m.fd = fd; - else + else if (plane == 0) buf->buf.m.fd = fd; } static inline int v4l_buffer_g_fd(const struct v4l_buffer *buf, unsigned plane) { - if (v4l_buffer_is_planar(buf)) + if (v4l_type_is_planar(buf->buf.type)) return buf->planes[plane].m.fd; - return buf->buf.m.fd; + return plane ? -1 : buf->buf.m.fd; } static inline int v4l_buffer_prepare_buf(struct v4l_fd *f, struct v4l_buffer *buf) @@ -882,60 +1066,10 @@ q->fds[i][p] = -1; } -static inline unsigned v4l_queue_g_type(const struct v4l_queue *q) -{ - return q->type; -} - -static inline unsigned v4l_queue_g_memory(const struct v4l_queue *q) -{ - return q->memory; -} - -static inline bool v4l_queue_is_planar(const struct v4l_queue *q) -{ - return v4l_buf_type_is_planar(q->type); -} - -static inline bool v4l_queue_is_output(const struct v4l_queue *q) -{ - return v4l_buf_type_is_output(q->type); -} - -static inline bool v4l_queue_is_capture(const struct v4l_queue *q) -{ - return v4l_buf_type_is_capture(q->type); -} - -static inline bool v4l_queue_is_video(const struct v4l_queue *q) -{ - return v4l_buf_type_is_video(q->type); -} - -static inline bool v4l_queue_is_vbi(const struct v4l_queue *q) -{ - return v4l_buf_type_is_vbi(q->type); -} - -static inline bool v4l_queue_is_sliced_vbi(const struct v4l_queue *q) -{ - return v4l_buf_type_is_sliced_vbi(q->type); -} - -static inline bool v4l_queue_is_sdr(const struct v4l_queue *q) -{ - return v4l_buf_type_is_sdr(q->type); -} - -static inline unsigned v4l_queue_g_buffers(const struct v4l_queue *q) -{ - return q->buffers; -} - -static inline unsigned v4l_queue_g_num_planes(const struct v4l_queue *q) -{ - return q->num_planes; -} +static inline unsigned v4l_queue_g_type(const struct v4l_queue *q) { return q->type; } +static inline unsigned v4l_queue_g_memory(const struct v4l_queue *q) { return q->memory; } +static inline unsigned v4l_queue_g_buffers(const struct v4l_queue *q) { return q->buffers; } +static inline unsigned v4l_queue_g_num_planes(const struct v4l_queue *q) { return q->num_planes; } static inline __u32 v4l_queue_g_length(const struct v4l_queue *q, unsigned plane) { @@ -954,6 +1088,8 @@ static inline void *v4l_queue_g_mmapping(const struct v4l_queue *q, unsigned index, unsigned plane) { + if (index >= v4l_queue_g_buffers(q) || plane >= v4l_queue_g_num_planes(q)) + return NULL; return q->mmappings[index][plane]; } @@ -964,6 +1100,8 @@ static inline void *v4l_queue_g_userptr(const struct v4l_queue *q, unsigned index, unsigned plane) { + if (index >= v4l_queue_g_buffers(q) || plane >= v4l_queue_g_num_planes(q)) + return NULL; return (void *)q->userptrs[index][plane]; } @@ -977,6 +1115,13 @@ return q->fds[index][plane]; } +static inline void *v4l_queue_g_dataptr(const struct v4l_queue *q, unsigned index, unsigned plane) +{ + if (q->memory == V4L2_MEMORY_USERPTR) + return v4l_queue_g_userptr(q, index, plane); + return v4l_queue_g_mmapping(q, index, plane); +} + static inline int v4l_queue_querybufs(struct v4l_fd *f, struct v4l_queue *q, unsigned from) { unsigned b, p; @@ -1056,16 +1201,6 @@ return v4l_queue_querybufs(f, q, q->buffers - createbufs.count); } -static inline int v4l_queue_streamon(struct v4l_fd *f, struct v4l_queue *q) -{ - return v4l_ioctl(f, VIDIOC_STREAMON, &q->type); -} - -static inline int v4l_queue_streamoff(struct v4l_fd *f, struct v4l_queue *q) -{ - return v4l_ioctl(f, VIDIOC_STREAMOFF, &q->type); -} - static inline int v4l_queue_mmap_bufs(struct v4l_fd *f, struct v4l_queue *q, unsigned from) { @@ -1146,13 +1281,28 @@ return 0; for (b = 0; b < v4l_queue_g_buffers(q); b++) { for (p = 0; p < v4l_queue_g_num_planes(q); p++) { - free(v4l_queue_g_mmapping(q, b, p)); - v4l_queue_s_mmapping(q, b, p, NULL); + free(v4l_queue_g_userptr(q, b, p)); + v4l_queue_s_userptr(q, b, p, NULL); } } return 0; } +static inline int v4l_queue_obtain_bufs(struct v4l_fd *f, + struct v4l_queue *q, unsigned from) +{ + if (q->memory == V4L2_MEMORY_USERPTR) + return v4l_queue_alloc_bufs(f, q, from); + return v4l_queue_mmap_bufs(f, q, from); +} + +static inline int v4l_queue_release_bufs(struct v4l_fd *f, struct v4l_queue *q) +{ + if (q->memory == V4L2_MEMORY_USERPTR) + return v4l_queue_free_bufs(q); + return v4l_queue_munmap_bufs(f, q); +} + static inline bool v4l_queue_has_expbuf(struct v4l_fd *f) { @@ -1205,9 +1355,8 @@ static inline void v4l_queue_free(struct v4l_fd *f, struct v4l_queue *q) { - v4l_queue_streamoff(f, q); - v4l_queue_free_bufs(q); - v4l_queue_munmap_bufs(f, q); + v4l_ioctl(f, VIDIOC_STREAMOFF, &q->type); + v4l_queue_release_bufs(f, q); v4l_queue_close_exported_fds(q); v4l_queue_reqbufs(f, q, 0); } @@ -1217,14 +1366,16 @@ unsigned p; v4l_buffer_init(buf, v4l_queue_g_type(q), v4l_queue_g_memory(q), index); - if (v4l_queue_is_planar(q)) { + if (v4l_type_is_planar(q->type)) { buf->buf.length = v4l_queue_g_num_planes(q); buf->buf.m.planes = buf->planes; } switch (q->memory) { case V4L2_MEMORY_USERPTR: - for (p = 0; p < v4l_queue_g_num_planes(q); p++) + for (p = 0; p < v4l_queue_g_num_planes(q); p++) { v4l_buffer_s_userptr(buf, p, v4l_queue_g_userptr(q, index, p)); + v4l_buffer_s_length(buf, p, v4l_queue_g_length(q, p)); + } break; case V4L2_MEMORY_DMABUF: for (p = 0; p < v4l_queue_g_num_planes(q); p++) @@ -1235,4 +1386,206 @@ } } +static inline int v4l_query_ext_ctrl(v4l_fd *f, struct v4l2_query_ext_ctrl *qec, + bool next_ctrl, bool next_compound) +{ + struct v4l2_queryctrl qc; + int ret; + + if (next_compound && !f->have_query_ext_ctrl) { + if (!next_ctrl) + return -EINVAL; + next_compound = false; + } + if (next_compound) + qec->id |= V4L2_CTRL_FLAG_NEXT_COMPOUND; + if (next_ctrl) { + if (f->have_next_ctrl) + qec->id |= V4L2_CTRL_FLAG_NEXT_CTRL; + else + qec->id = qec->id ? qec->id + 1 : V4L2_CID_BASE; + } + if (f->have_query_ext_ctrl) + return v4l_ioctl(f, VIDIOC_QUERY_EXT_CTRL, qec); + + for (;;) { + if (qec->id == V4L2_CID_LASTP1 && next_ctrl) + qec->id = V4L2_CID_PRIVATE_BASE; + qc.id = qec->id; + ret = v4l_ioctl(f, VIDIOC_QUERYCTRL, &qc); + if (!ret) + break; + if (ret != EINVAL) + return ret; + if (!next_ctrl || f->have_next_ctrl) + return ret; + if (qec->id >= V4L2_CID_PRIVATE_BASE) + return ret; + qec->id++; + } + qec->id = qc.id; + qec->type = qc.type; + memcpy(qec->name, qc.name, sizeof(qec->name)); + qec->minimum = qc.minimum; + qec->maximum = qc.maximum; + qec->step = qc.step; + qec->default_value = qc.default_value; + qec->flags = qc.flags; + qec->elems = 1; + qec->nr_of_dims = 0; + memset(qec->dims, 0, sizeof(qec->dims)); + switch (qec->type) { + case V4L2_CTRL_TYPE_INTEGER64: + qec->elem_size = sizeof(__s64); + qec->minimum = 0x8000000000000000ULL; + qec->maximum = 0x7fffffffffffffffULL; + qec->step = 1; + break; + case V4L2_CTRL_TYPE_STRING: + qec->elem_size = qc.maximum + 1; + break; + default: + qec->elem_size = sizeof(__s32); + break; + } + memset(qec->reserved, 0, sizeof(qec->reserved)); + return 0; +} + +static inline int v4l_g_ext_ctrls(v4l_fd *f, struct v4l2_ext_controls *ec) +{ + unsigned i; + + if (f->have_ext_ctrls) + return v4l_ioctl(f, VIDIOC_G_EXT_CTRLS, ec); + if (ec->count == 0) + return 0; + for (i = 0; i < ec->count; i++) { + struct v4l2_control c = { ec->controls[i].id }; + int ret = v4l_ioctl(f, VIDIOC_G_CTRL, &c); + + if (ret) { + ec->error_idx = i; + return ret; + } + ec->controls[i].value = c.value; + } + return 0; +} + +static inline int v4l_s_ext_ctrls(v4l_fd *f, struct v4l2_ext_controls *ec) +{ + unsigned i; + + if (f->have_ext_ctrls) + return v4l_ioctl(f, VIDIOC_S_EXT_CTRLS, ec); + if (ec->count == 0) + return 0; + for (i = 0; i < ec->count; i++) { + struct v4l2_control c = { ec->controls[i].id, ec->controls[i].value }; + int ret = v4l_ioctl(f, VIDIOC_S_CTRL, &c); + + if (ret) { + ec->error_idx = i; + return ret; + } + } + return 0; +} + +static inline int v4l_try_ext_ctrls(v4l_fd *f, struct v4l2_ext_controls *ec) +{ + unsigned i; + + if (f->have_ext_ctrls) + return v4l_ioctl(f, VIDIOC_TRY_EXT_CTRLS, ec); + if (ec->count == 0) + return 0; + for (i = 0; i < ec->count; i++) { + struct v4l2_queryctrl qc = { ec->controls[i].id }; + int ret = v4l_ioctl(f, VIDIOC_QUERYCTRL, &qc); + + if (ret || qc.type == V4L2_CTRL_TYPE_STRING || + qc.type == V4L2_CTRL_TYPE_INTEGER64) { + ec->error_idx = i; + return ret ? ret : EINVAL; + } + } + return 0; +} + +static inline int v4l_g_selection(v4l_fd *f, struct v4l2_selection *sel) +{ + struct v4l2_cropcap cc; + struct v4l2_crop crop; + int ret; + + if (f->have_selection) + return v4l_ioctl(f, VIDIOC_G_SELECTION, sel); + crop.type = sel->type; + cc.type = sel->type; + ret = v4l_ioctl(f, VIDIOC_CROPCAP, &cc); + if (ret) + return ret; + ret = v4l_ioctl(f, VIDIOC_G_CROP, &crop); + if (ret) + return ret; + if (sel->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + switch (sel->target) { + case V4L2_SEL_TGT_CROP: + sel->r = crop.c; + return 0; + case V4L2_SEL_TGT_CROP_DEFAULT: + sel->r = cc.defrect; + return 0; + case V4L2_SEL_TGT_CROP_BOUNDS: + sel->r = cc.bounds; + return 0; + default: + return EINVAL; + } + } + switch (sel->target) { + case V4L2_SEL_TGT_COMPOSE: + sel->r = crop.c; + return 0; + case V4L2_SEL_TGT_COMPOSE_DEFAULT: + sel->r = cc.defrect; + return 0; + case V4L2_SEL_TGT_COMPOSE_BOUNDS: + sel->r = cc.bounds; + return 0; + default: + return EINVAL; + } +} + +static inline int v4l_s_selection(v4l_fd *f, struct v4l2_selection *sel) +{ + struct v4l2_crop crop; + int ret; + + if (f->have_selection) + return v4l_ioctl(f, VIDIOC_S_SELECTION, sel); + crop.type = sel->type; + ret = v4l_ioctl(f, VIDIOC_G_CROP, &crop); + if (ret) + return ret; + if (sel->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && + sel->target == V4L2_SEL_TGT_CROP) { + crop.c = sel->r; + return v4l_ioctl(f, VIDIOC_S_CROP, &crop); + } + if (sel->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && + sel->target == V4L2_SEL_TGT_COMPOSE) { + crop.c = sel->r; + return v4l_ioctl(f, VIDIOC_S_CROP, &crop); + } + return EINVAL; +} + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + #endif diff -Nru v4l-utils-1.0.0+r2263/utils/v4l2-ctl/Android.mk v4l-utils-1.0.0+r2364/utils/v4l2-ctl/Android.mk --- v4l-utils-1.0.0+r2263/utils/v4l2-ctl/Android.mk 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/v4l2-ctl/Android.mk 2014-08-12 09:02:18.000000000 +0000 @@ -20,6 +20,6 @@ v4l2-ctl-io.cpp v4l2-ctl-stds.cpp v4l2-ctl-vidcap.cpp v4l2-ctl-vidout.cpp \ v4l2-ctl-overlay.cpp v4l2-ctl-vbi.cpp v4l2-ctl-selection.cpp v4l2-ctl-misc.cpp \ v4l2-ctl-streaming.cpp v4l2-ctl-test-patterns.cpp v4l2-ctl-sdr.cpp \ - v4l2-ctl-edid.cpp + v4l2-ctl-edid.cpp vivid-tpg-colors.c vivid-tpg.c include $(BUILD_EXECUTABLE) diff -Nru v4l-utils-1.0.0+r2263/utils/v4l2-ctl/Makefile.am v4l-utils-1.0.0+r2364/utils/v4l2-ctl/Makefile.am --- v4l-utils-1.0.0+r2263/utils/v4l2-ctl/Makefile.am 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/v4l2-ctl/Makefile.am 2014-08-12 09:02:18.000000000 +0000 @@ -8,7 +8,7 @@ v4l2_ctl_SOURCES = v4l2-ctl.cpp v4l2-ctl.h v4l2-ctl-common.cpp v4l2-ctl-tuner.cpp \ v4l2-ctl-io.cpp v4l2-ctl-stds.cpp v4l2-ctl-vidcap.cpp v4l2-ctl-vidout.cpp \ v4l2-ctl-overlay.cpp v4l2-ctl-vbi.cpp v4l2-ctl-selection.cpp v4l2-ctl-misc.cpp \ - v4l2-ctl-streaming.cpp v4l2-ctl-sdr.cpp v4l2-ctl-edid.cpp vivi-colors.c vivi-tpg.c + v4l2-ctl-streaming.cpp v4l2-ctl-sdr.cpp v4l2-ctl-edid.cpp vivid-tpg-colors.c vivid-tpg.c v4l2_ctl_LDADD = ../../lib/libv4l2/libv4l2.la ../../lib/libv4lconvert/libv4lconvert.la EXTRA_DIST = Android.mk diff -Nru v4l-utils-1.0.0+r2263/utils/v4l2-ctl/v4l2-ctl-common.cpp v4l-utils-1.0.0+r2364/utils/v4l2-ctl/v4l2-ctl-common.cpp --- v4l-utils-1.0.0+r2263/utils/v4l2-ctl/v4l2-ctl-common.cpp 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/v4l2-ctl/v4l2-ctl-common.cpp 2014-08-12 09:02:18.000000000 +0000 @@ -25,13 +25,21 @@ #include #include +struct ctrl_subset { + unsigned offset[V4L2_CTRL_MAX_DIMS]; + unsigned size[V4L2_CTRL_MAX_DIMS]; +}; + typedef std::map > class2ctrls_map; -typedef std::map ctrl_qmap; +typedef std::map ctrl_qmap; static ctrl_qmap ctrl_str2q; typedef std::map ctrl_idmap; static ctrl_idmap ctrl_id2str; +typedef std::map ctrl_subset_map; +static ctrl_subset_map ctrl_subsets; + typedef std::list ctrl_get_list; static ctrl_get_list get_ctrls; @@ -75,6 +83,9 @@ " -l, --list-ctrls display all controls and their values [VIDIOC_QUERYCTRL]\n" " -L, --list-ctrls-menus\n" " display all controls and their menus [VIDIOC_QUERYMENU]\n" + " -r, --subset=[,,]+\n" + " the subset of the N-dimensional array to get/set for control ,\n" + " for every dimension an (, ) tuple is given.\n" #ifndef NO_LIBV4L2 " -w, --wrapper use the libv4l2 wrapper library.\n" #endif @@ -194,7 +205,7 @@ } } -static std::string name2var(unsigned char *name) +static std::string name2var(char *name) { std::string s; int add_underscore = 0; @@ -260,63 +271,105 @@ { V4L2_CTRL_FLAG_SLIDER, "slider" }, { V4L2_CTRL_FLAG_WRITE_ONLY, "write-only" }, { V4L2_CTRL_FLAG_VOLATILE, "volatile" }, + { V4L2_CTRL_FLAG_HAS_PAYLOAD,"has-payload" }, { 0, NULL } }; return flags2s(flags, def); } -static void print_qctrl(int fd, struct v4l2_queryctrl *queryctrl, +static void print_qctrl(int fd, struct v4l2_query_ext_ctrl *queryctrl, struct v4l2_ext_control *ctrl, int show_menus) { struct v4l2_querymenu qmenu; std::string s = name2var(queryctrl->name); - int i; + unsigned i; memset(&qmenu, 0, sizeof(qmenu)); qmenu.id = queryctrl->id; switch (queryctrl->type) { case V4L2_CTRL_TYPE_INTEGER: - printf("%31s (int) : min=%d max=%d step=%d default=%d value=%d", + printf("%31s (int) : min=%lld max=%lld step=%lld default=%lld", s.c_str(), queryctrl->minimum, queryctrl->maximum, - queryctrl->step, queryctrl->default_value, - ctrl->value); + queryctrl->step, queryctrl->default_value); break; case V4L2_CTRL_TYPE_INTEGER64: - printf("%31s (int64) : value=%lld", s.c_str(), ctrl->value64); + printf("%31s (int64) : min=%lld max=%lld step=%lld default=%lld", + s.c_str(), + queryctrl->minimum, queryctrl->maximum, + queryctrl->step, queryctrl->default_value); break; case V4L2_CTRL_TYPE_STRING: - printf("%31s (str) : min=%d max=%d step=%d value='%s'", + printf("%31s (str) : min=%lld max=%lld step=%lld", s.c_str(), queryctrl->minimum, queryctrl->maximum, - queryctrl->step, safename(ctrl->string).c_str()); + queryctrl->step); break; case V4L2_CTRL_TYPE_BOOLEAN: - printf("%31s (bool) : default=%d value=%d", - s.c_str(), - queryctrl->default_value, ctrl->value); + printf("%31s (bool) : default=%lld", + s.c_str(), queryctrl->default_value); break; case V4L2_CTRL_TYPE_MENU: - printf("%31s (menu) : min=%d max=%d default=%d value=%d", + printf("%31s (menu) : min=%lld max=%lld default=%lld", s.c_str(), queryctrl->minimum, queryctrl->maximum, - queryctrl->default_value, ctrl->value); + queryctrl->default_value); break; case V4L2_CTRL_TYPE_INTEGER_MENU: - printf("%31s (intmenu): min=%d max=%d default=%d value=%d", + printf("%31s (intmenu): min=%lld max=%lld default=%lld", s.c_str(), queryctrl->minimum, queryctrl->maximum, - queryctrl->default_value, ctrl->value); + queryctrl->default_value); break; case V4L2_CTRL_TYPE_BUTTON: printf("%31s (button) :", s.c_str()); break; case V4L2_CTRL_TYPE_BITMASK: - printf("%31s (bitmask): max=0x%08x default=0x%08x value=0x%08x", + printf("%31s (bitmask): max=0x%08llx default=0x%08llx", s.c_str(), queryctrl->maximum, - queryctrl->default_value, ctrl->value); + queryctrl->default_value); + break; + case V4L2_CTRL_TYPE_U8: + printf("%31s (u8) : min=%lld max=%lld step=%lld default=%lld", + s.c_str(), + queryctrl->minimum, queryctrl->maximum, + queryctrl->step, queryctrl->default_value); + break; + case V4L2_CTRL_TYPE_U16: + printf("%31s (u16) : min=%lld max=%lld step=%lld default=%lld", + s.c_str(), + queryctrl->minimum, queryctrl->maximum, + queryctrl->step, queryctrl->default_value); + break; + default: + printf("%31s (unknown): type=%x", s.c_str(), queryctrl->type); break; - default: break; + } + if (queryctrl->nr_of_dims == 0) { + switch (queryctrl->type) { + case V4L2_CTRL_TYPE_INTEGER: + case V4L2_CTRL_TYPE_BOOLEAN: + case V4L2_CTRL_TYPE_MENU: + case V4L2_CTRL_TYPE_INTEGER_MENU: + printf(" value=%d", ctrl->value); + break; + case V4L2_CTRL_TYPE_BITMASK: + printf(" value=0x%08x", ctrl->value); + break; + case V4L2_CTRL_TYPE_INTEGER64: + printf(" value=%lld", ctrl->value64); + break; + case V4L2_CTRL_TYPE_STRING: + printf(" value='%s'", safename(ctrl->string).c_str()); + break; + default: + break; + } + } + if (queryctrl->nr_of_dims) { + printf(" "); + for (i = 0; i < queryctrl->nr_of_dims; i++) + printf("[%u]", queryctrl->dims[i]); } if (queryctrl->flags) printf(" flags=%s", ctrlflags2s(queryctrl->flags).c_str()); @@ -335,7 +388,7 @@ } } -static int print_control(int fd, struct v4l2_queryctrl &qctrl, int show_menus) +static int print_control(int fd, struct v4l2_query_ext_ctrl &qctrl, int show_menus) { struct v4l2_control ctrl; struct v4l2_ext_control ext_ctrl; @@ -356,6 +409,10 @@ print_qctrl(fd, &qctrl, &ext_ctrl, show_menus); return 1; } + if (qctrl.type >= V4L2_CTRL_COMPOUND_TYPES) { + print_qctrl(fd, &qctrl, NULL, show_menus); + return 1; + } ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(qctrl.id); ctrls.count = 1; ctrls.controls = &ext_ctrl; @@ -389,57 +446,97 @@ return 1; } +static int query_ext_ctrl_ioctl(int fd, struct v4l2_query_ext_ctrl &qctrl) +{ + struct v4l2_queryctrl qc; + int rc; + + rc = test_ioctl(fd, VIDIOC_QUERY_EXT_CTRL, &qctrl); + if (errno != ENOTTY) + return rc; + qc.id = qctrl.id; + rc = test_ioctl(fd, VIDIOC_QUERYCTRL, &qc); + if (rc == 0) { + qctrl.type = qc.type; + memcpy(qctrl.name, qc.name, sizeof(qctrl.name)); + qctrl.minimum = qc.minimum; + qctrl.maximum = qc.maximum; + qctrl.step = qc.step; + qctrl.default_value = qc.default_value; + qctrl.flags = qc.flags; + qctrl.elems = 1; + qctrl.nr_of_dims = 0; + memset(qctrl.dims, 0, sizeof(qctrl.dims)); + switch (qctrl.type) { + case V4L2_CTRL_TYPE_INTEGER64: + qctrl.elem_size = sizeof(__s64); + break; + case V4L2_CTRL_TYPE_STRING: + qctrl.elem_size = qc.maximum + 1; + break; + default: + qctrl.elem_size = sizeof(__s32); + break; + } + memset(qctrl.reserved, 0, sizeof(qctrl.reserved)); + } + qctrl.id = qc.id; + return rc; +} + static void list_controls(int fd, int show_menus) { - struct v4l2_queryctrl qctrl; + const unsigned next_fl = V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND; + struct v4l2_query_ext_ctrl qctrl; int id; memset(&qctrl, 0, sizeof(qctrl)); - qctrl.id = V4L2_CTRL_FLAG_NEXT_CTRL; - while (test_ioctl(fd, VIDIOC_QUERYCTRL, &qctrl) == 0) { - print_control(fd, qctrl, show_menus); - qctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL; + qctrl.id = next_fl; + while (query_ext_ctrl_ioctl(fd, qctrl) == 0) { + print_control(fd, qctrl, show_menus); + qctrl.id |= next_fl; } - if (qctrl.id != V4L2_CTRL_FLAG_NEXT_CTRL) + if (!(qctrl.id & next_fl)) return; for (id = V4L2_CID_USER_BASE; id < V4L2_CID_LASTP1; id++) { qctrl.id = id; - if (test_ioctl(fd, VIDIOC_QUERYCTRL, &qctrl) == 0) + if (query_ext_ctrl_ioctl(fd, qctrl) == 0) print_control(fd, qctrl, show_menus); } for (qctrl.id = V4L2_CID_PRIVATE_BASE; - test_ioctl(fd, VIDIOC_QUERYCTRL, &qctrl) == 0; qctrl.id++) { + query_ext_ctrl_ioctl(fd, qctrl) == 0; qctrl.id++) { print_control(fd, qctrl, show_menus); } } static void find_controls(int fd) { - struct v4l2_queryctrl qctrl; + const unsigned next_fl = V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND; + struct v4l2_query_ext_ctrl qctrl; int id; memset(&qctrl, 0, sizeof(qctrl)); - qctrl.id = V4L2_CTRL_FLAG_NEXT_CTRL; - while (test_ioctl(fd, VIDIOC_QUERYCTRL, &qctrl) == 0) { + qctrl.id = next_fl; + while (query_ext_ctrl_ioctl(fd, qctrl) == 0) { if (qctrl.type != V4L2_CTRL_TYPE_CTRL_CLASS && !(qctrl.flags & V4L2_CTRL_FLAG_DISABLED)) { ctrl_str2q[name2var(qctrl.name)] = qctrl; ctrl_id2str[qctrl.id] = name2var(qctrl.name); } - qctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL; + qctrl.id |= next_fl; } - if (qctrl.id != V4L2_CTRL_FLAG_NEXT_CTRL) + if (!(qctrl.id & next_fl)) return; for (id = V4L2_CID_USER_BASE; id < V4L2_CID_LASTP1; id++) { qctrl.id = id; - if (test_ioctl(fd, VIDIOC_QUERYCTRL, &qctrl) == 0 && + if (query_ext_ctrl_ioctl(fd, qctrl) == 0 && !(qctrl.flags & V4L2_CTRL_FLAG_DISABLED)) { ctrl_str2q[name2var(qctrl.name)] = qctrl; ctrl_id2str[qctrl.id] = name2var(qctrl.name); } } for (qctrl.id = V4L2_CID_PRIVATE_BASE; - test_ioctl(fd, VIDIOC_QUERYCTRL, &qctrl) == 0; qctrl.id++) { + query_ext_ctrl_ioctl(fd, qctrl) == 0; qctrl.id++) { if (!(qctrl.flags & V4L2_CTRL_FLAG_DISABLED)) { ctrl_str2q[name2var(qctrl.name)] = qctrl; ctrl_id2str[qctrl.id] = name2var(qctrl.name); @@ -490,6 +587,57 @@ ctrl->minimum, ctrl->maximum, ctrl->step, ctrl->default_value); } +static bool parse_subset(char *optarg) +{ + struct ctrl_subset subset; + std::string ctrl_name; + unsigned idx = 0; + char *p; + + memset(&subset, 0, sizeof(subset)); + while (*optarg) { + p = strchr(optarg, ','); + if (p) + *p = 0; + if (optarg[0] == 0) { + fprintf(stderr, "empty string\n"); + return true; + } + if (idx == 0) { + ctrl_name = optarg; + } else { + if (idx > V4L2_CTRL_MAX_DIMS * 2) { + fprintf(stderr, "too many dimensions\n"); + return true; + } + if (idx & 1) + subset.offset[idx / 2] = strtoul(optarg, 0, 0); + else { + subset.size[idx / 2 - 1] = strtoul(optarg, 0, 0); + if (subset.size[idx / 2 - 1] == 0) { + fprintf(stderr, " cannot be 0\n"); + return true; + } + } + } + idx++; + if (p == NULL) + break; + optarg = p + 1; + } + if (idx == 1) { + fprintf(stderr, "no , tuples given\n"); + return true; + } + if ((idx & 1) == 0) { + fprintf(stderr, " without \n"); + return true; + } + ctrl_subsets[ctrl_name] = subset; + + return false; +} + static bool parse_next_subopt(char **subs, char **value) { static char *const subopts[] = { @@ -542,6 +690,12 @@ } } break; + case OptSubset: + if (parse_subset(optarg)) { + common_usage(); + exit(1); + } + break; case OptSetPriority: prio = (enum v4l2_priority)strtoul(optarg, 0L, 0); break; @@ -551,6 +705,50 @@ } } +static bool fill_subset(const struct v4l2_query_ext_ctrl &qc, ctrl_subset &subset) +{ + unsigned d; + + if (qc.nr_of_dims == 0) + return false; + + for (d = 0; d < qc.nr_of_dims; d++) { + subset.offset[d] = 0; + subset.size[d] = qc.dims[d]; + } + + if (ctrl_subsets.find(qc.name) != ctrl_subsets.end()) { + unsigned ss_dims; + + subset = ctrl_subsets[qc.name]; + for (ss_dims = 0; ss_dims < V4L2_CTRL_MAX_DIMS && subset.size[ss_dims]; ss_dims++) ; + if (ss_dims != qc.nr_of_dims) { + fprintf(stderr, "expected %d dimensions but --subset specified %d\n", + qc.nr_of_dims, ss_dims); + return true; + } + for (d = 0; d < qc.nr_of_dims; d++) { + if (subset.offset[d] + subset.size[d] > qc.dims[d]) { + fprintf(stderr, "the subset offset+size for dimension %d is out of range\n", d); + return true; + } + } + } + return false; +} + +static bool idx_in_subset(const struct v4l2_query_ext_ctrl &qc, const ctrl_subset &subset, + const unsigned *divide, unsigned idx) +{ + for (unsigned d = 0; d < qc.nr_of_dims; d++) { + unsigned i = (idx / divide[d]) % qc.dims[d]; + + if (i < subset.offset[d] || i >= subset.offset[d] + subset.size[d]) + return false; + } + return true; +} + void common_set(int fd) { if (options[OptSetPriority]) { @@ -568,24 +766,57 @@ for (ctrl_set_map::iterator iter = set_ctrls.begin(); iter != set_ctrls.end(); ++iter) { struct v4l2_ext_control ctrl; + struct v4l2_query_ext_ctrl &qc = ctrl_str2q[iter->first]; memset(&ctrl, 0, sizeof(ctrl)); - ctrl.id = ctrl_str2q[iter->first].id; - if (ctrl_str2q[iter->first].type == V4L2_CTRL_TYPE_INTEGER64) + ctrl.id = qc.id; + if (qc.type == V4L2_CTRL_TYPE_INTEGER64) use_ext_ctrls = true; - if (ctrl_str2q[iter->first].type == V4L2_CTRL_TYPE_STRING) { - unsigned len = iter->second.length(); - unsigned maxlen = ctrl_str2q[iter->first].maximum; + if (qc.flags & V4L2_CTRL_FLAG_HAS_PAYLOAD) { + struct v4l2_ext_controls ctrls = { 0, 1 }; + unsigned divide[V4L2_CTRL_MAX_DIMS] = { 0 }; + ctrl_subset subset; + long long v; + unsigned d, i; use_ext_ctrls = true; - ctrl.size = maxlen + 1; - ctrl.string = (char *)malloc(ctrl.size); - if (len > maxlen) { - memcpy(ctrl.string, iter->second.c_str(), maxlen); - ctrl.string[maxlen] = 0; + ctrl.size = qc.elems * qc.elem_size; + ctrl.ptr = malloc(ctrl.size); + + ctrls.controls = &ctrl; + ioctl(fd, VIDIOC_G_EXT_CTRLS, &ctrls); + + if (fill_subset(qc, subset)) + return; + + for (d = 0; d < qc.nr_of_dims; d++) { + divide[d] = qc.dims[d]; + for (i = 0; i < d; i++) + divide[i] *= divide[d]; } - else { - strcpy(ctrl.string, iter->second.c_str()); + + + switch (qc.type) { + case V4L2_CTRL_TYPE_U8: + v = strtoul(iter->second.c_str(), NULL, 0); + for (i = 0; i < qc.elems; i++) + if (idx_in_subset(qc, subset, divide, i)) + ctrl.p_u8[i] = v; + break; + case V4L2_CTRL_TYPE_U16: + v = strtoul(iter->second.c_str(), NULL, 0); + for (i = 0; i < qc.elems; i++) + if (idx_in_subset(qc, subset, divide, i)) + ctrl.p_u16[i] = v; + break; + case V4L2_CTRL_TYPE_STRING: + strncpy(ctrl.string, iter->second.c_str(), qc.maximum); + ctrl.string[qc.maximum] = 0; + break; + default: + fprintf(stderr, "%s: unsupported payload type\n", + qc.name); + break; } } else { if (V4L2_CTRL_DRIVER_PRIV(ctrl.id)) @@ -618,7 +849,7 @@ ctrls.controls = &iter->second[0]; if (doioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls)) { if (ctrls.error_idx >= ctrls.count) { - fprintf(stderr, "Error setting MPEG controls: %s\n", + fprintf(stderr, "Error setting controls: %s\n", strerror(errno)); } else { @@ -632,6 +863,60 @@ } } +static void print_array(const struct v4l2_query_ext_ctrl &qc, void *p) +{ + ctrl_subset subset; + unsigned divide[V4L2_CTRL_MAX_DIMS] = { 0 }; + unsigned from, to; + unsigned d, i; + + if (fill_subset(qc, subset)) + return; + + for (d = 0; d < qc.nr_of_dims; d++) { + divide[d] = qc.dims[d]; + for (i = 0; i < d; i++) + divide[i] *= divide[d]; + } + + from = subset.offset[qc.nr_of_dims - 1]; + to = subset.offset[qc.nr_of_dims - 1] + subset.size[qc.nr_of_dims - 1] - 1; + + for (unsigned idx = 0; idx < qc.elems / qc.dims[qc.nr_of_dims - 1]; idx++) { + for (d = 0; d < qc.nr_of_dims - 1; d++) { + unsigned i = (idx / divide[d]) % qc.dims[d]; + + if (i < subset.offset[d] || i >= subset.offset[d] + subset.size[d]) + break; + } + if (d < qc.nr_of_dims - 1) + continue; + + printf("%s", qc.name); + for (d = 0; d < qc.nr_of_dims - 1; d++) + printf("[%u]", (idx / divide[d]) % qc.dims[d]); + printf(": "); + switch (qc.type) { + case V4L2_CTRL_TYPE_U8: + for (i = from; i <= to; i++) { + printf("%4d", ((__u8 *)p)[idx + i]); + if (i < to) + printf(", "); + } + printf("\n"); + break; + case V4L2_CTRL_TYPE_U16: + for (i = from; i <= to; i++) { + printf("%6d", ((__u16 *)p)[idx + i]); + if (i < to) + printf(", "); + } + printf("\n"); + break; + } + } +} + void common_get(int fd) { if (options[OptGetCtrl] && !get_ctrls.empty()) { @@ -643,16 +928,16 @@ for (ctrl_get_list::iterator iter = get_ctrls.begin(); iter != get_ctrls.end(); ++iter) { struct v4l2_ext_control ctrl; + struct v4l2_query_ext_ctrl &qc = ctrl_str2q[*iter]; memset(&ctrl, 0, sizeof(ctrl)); - ctrl.id = ctrl_str2q[*iter].id; - if (ctrl_str2q[*iter].type == V4L2_CTRL_TYPE_INTEGER64) + ctrl.id = qc.id; + if (qc.type == V4L2_CTRL_TYPE_INTEGER64) use_ext_ctrls = true; - if (ctrl_str2q[*iter].type == V4L2_CTRL_TYPE_STRING) { + if (qc.flags & V4L2_CTRL_FLAG_HAS_PAYLOAD) { use_ext_ctrls = true; - ctrl.size = ctrl_str2q[*iter].maximum + 1; - ctrl.string = (char *)malloc(ctrl.size); - ctrl.string[0] = 0; + ctrl.size = qc.elems * qc.elem_size; + ctrl.ptr = calloc(1, ctrl.size); } if (V4L2_CTRL_DRIVER_PRIV(ctrl.id)) use_ext_ctrls = true; @@ -679,12 +964,26 @@ doioctl(fd, VIDIOC_G_EXT_CTRLS, &ctrls); for (unsigned i = 0; i < iter->second.size(); i++) { struct v4l2_ext_control ctrl = iter->second[i]; + std::string &name = ctrl_id2str[ctrl.id]; + struct v4l2_query_ext_ctrl &qc = ctrl_str2q[name]; - if (ctrl_str2q[ctrl_id2str[ctrl.id]].type == V4L2_CTRL_TYPE_STRING) - printf("%s: '%s'\n", ctrl_id2str[ctrl.id].c_str(), - safename(ctrl.string).c_str()); - else - printf("%s: %d\n", ctrl_id2str[ctrl.id].c_str(), ctrl.value); + if (qc.flags & V4L2_CTRL_FLAG_HAS_PAYLOAD) { + switch (qc.type) { + case V4L2_CTRL_TYPE_U8: + case V4L2_CTRL_TYPE_U16: + print_array(qc, ctrl.ptr); + break; + case V4L2_CTRL_TYPE_STRING: + printf("%s: '%s'\n", name.c_str(), + safename(ctrl.string).c_str()); + break; + default: + fprintf(stderr, "%s: unsupported payload type\n", + qc.name); + break; + } + } else + printf("%s: %d\n", name.c_str(), ctrl.value); } } } diff -Nru v4l-utils-1.0.0+r2263/utils/v4l2-ctl/v4l2-ctl.cpp v4l-utils-1.0.0+r2364/utils/v4l2-ctl/v4l2-ctl.cpp --- v4l-utils-1.0.0+r2263/utils/v4l2-ctl/v4l2-ctl.cpp 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/v4l2-ctl/v4l2-ctl.cpp 2014-08-12 09:02:18.000000000 +0000 @@ -54,6 +54,8 @@ unsigned capabilities; unsigned out_capabilities; +unsigned priv_magic; +unsigned out_priv_magic; bool is_multiplanar; __u32 vidcap_buftype; __u32 vidout_buftype; @@ -115,6 +117,7 @@ {"add-clip", required_argument, 0, OptAddClip}, {"add-bitmap", required_argument, 0, OptAddBitmap}, {"find-fb", no_argument, 0, OptFindFb}, + {"subset", required_argument, 0, OptSubset}, {"get-standard", no_argument, 0, OptGetStandard}, {"set-standard", required_argument, 0, OptSetStandard}, {"get-detected-standard", no_argument, 0, OptQueryStandard}, @@ -402,6 +405,16 @@ } +static const flag_def pixflags_def[] = { + { V4L2_PIX_FMT_FLAG_PREMUL_ALPHA, "premultiplied-alpha" }, + { 0, NULL } +}; + +std::string pixflags2s(unsigned flags) +{ + return flags2s(flags, pixflags_def); +} + static const flag_def service_def[] = { { V4L2_SLICED_TELETEXT_B, "teletext" }, { V4L2_SLICED_VPS, "vps" }, @@ -433,8 +446,8 @@ printf("\tBytes per Line: %u\n", vfmt.fmt.pix.bytesperline); printf("\tSize Image : %u\n", vfmt.fmt.pix.sizeimage); printf("\tColorspace : %s\n", colorspace2s(vfmt.fmt.pix.colorspace).c_str()); - if (vfmt.fmt.pix.priv) - printf("\tCustom Info : %08x\n", vfmt.fmt.pix.priv); + if (vfmt.fmt.pix.priv == V4L2_PIX_FMT_PRIV_MAGIC) + printf("\tFlags : %s\n", pixflags2s(vfmt.fmt.pix.flags).c_str()); break; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: @@ -442,6 +455,7 @@ printf("\tPixel Format : '%s'\n", fcc2s(vfmt.fmt.pix_mp.pixelformat).c_str()); printf("\tField : %s\n", field2s(vfmt.fmt.pix_mp.field).c_str()); printf("\tNumber of planes : %u\n", vfmt.fmt.pix_mp.num_planes); + printf("\tFlags : %s\n", pixflags2s(vfmt.fmt.pix_mp.flags).c_str()); printf("\tColorspace : %s\n", colorspace2s(vfmt.fmt.pix_mp.colorspace).c_str()); for (int i = 0; i < vfmt.fmt.pix_mp.num_planes && i < VIDEO_MAX_PLANES; i++) { printf("\tPlane %d :\n", i); @@ -508,6 +522,7 @@ break; case V4L2_BUF_TYPE_SDR_CAPTURE: printf("\tSample Format : %s\n", fcc2s(vfmt.fmt.sdr.pixelformat).c_str()); + printf("\tBuffer Size : %u\n", vfmt.fmt.sdr.buffersize); break; } } @@ -570,14 +585,16 @@ s += "\t\tSliced VBI Capture\n"; if (cap & V4L2_CAP_SLICED_VBI_OUTPUT) s += "\t\tSliced VBI Output\n"; - if (cap & V4L2_CAP_SDR_CAPTURE) - s += "\t\tSDR Capture\n"; if (cap & V4L2_CAP_RDS_CAPTURE) s += "\t\tRDS Capture\n"; if (cap & V4L2_CAP_RDS_OUTPUT) s += "\t\tRDS Output\n"; + if (cap & V4L2_CAP_SDR_CAPTURE) + s += "\t\tSDR Capture\n"; if (cap & V4L2_CAP_TUNER) s += "\t\tTuner\n"; + if (cap & V4L2_CAP_HW_FREQ_SEEK) + s += "\t\tHW Frequency Seek\n"; if (cap & V4L2_CAP_MODULATOR) s += "\t\tModulator\n"; if (cap & V4L2_CAP_AUDIO) @@ -590,6 +607,8 @@ s += "\t\tAsync I/O\n"; if (cap & V4L2_CAP_STREAMING) s += "\t\tStreaming\n"; + if (cap & V4L2_CAP_EXT_PIX_FORMAT) + s += "\t\tExtended Pix Format\n"; if (cap & V4L2_CAP_DEVICE_CAPS) s += "\t\tDevice Capabilities\n"; return s; @@ -799,6 +818,14 @@ case V4L2_EVENT_SOURCE_CHANGE: printf("source_change: pad/input=%d changes: %x\n", ev->id, ev->u.src_change.changes); break; + case V4L2_EVENT_MOTION_DET: + if (ev->u.motion_det.flags & V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ) + printf("motion_det frame %d, regions 0x%x\n", + ev->u.motion_det.frame_sequence, + ev->u.motion_det.region_mask); + else + printf("motion_det regions 0x%x\n", ev->u.motion_det.region_mask); + break; default: if (ev->type >= V4L2_EVENT_PRIVATE_START) printf("unknown private event (%08x)\n", ev->type); @@ -821,6 +848,8 @@ event = V4L2_EVENT_VSYNC; else if (!strcmp(e, "frame_sync")) event = V4L2_EVENT_FRAME_SYNC; + else if (!strcmp(e, "motion_det")) + event = V4L2_EVENT_MOTION_DET; else if (!strncmp(e, "ctrl=", 5)) { event = V4L2_EVENT_CTRL; *name = e + 5; @@ -1026,6 +1055,8 @@ if (capabilities & V4L2_CAP_DEVICE_CAPS) capabilities = vcap.device_caps; + priv_magic = (capabilities & V4L2_CAP_EXT_PIX_FORMAT) ? + V4L2_PIX_FMT_PRIV_MAGIC : 0; is_multiplanar = capabilities & (V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_VIDEO_OUTPUT_MPLANE); @@ -1048,6 +1079,8 @@ out_capabilities = vcap.capabilities; if (out_capabilities & V4L2_CAP_DEVICE_CAPS) out_capabilities = vcap.device_caps; + out_priv_magic = (out_capabilities & V4L2_CAP_EXT_PIX_FORMAT) ? + V4L2_PIX_FMT_PRIV_MAGIC : 0; } common_process_controls(fd); diff -Nru v4l-utils-1.0.0+r2263/utils/v4l2-ctl/v4l2-ctl.h v4l-utils-1.0.0+r2364/utils/v4l2-ctl/v4l2-ctl.h --- v4l-utils-1.0.0+r2263/utils/v4l2-ctl/v4l2-ctl.h 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/v4l2-ctl/v4l2-ctl.h 2014-08-12 09:02:18.000000000 +0000 @@ -50,6 +50,7 @@ OptSetOutput = 'o', OptGetParm = 'P', OptSetParm = 'p', + OptSubset = 'r', OptGetStandard = 'S', OptSetStandard = 's', OptGetTuner = 'T', @@ -204,6 +205,8 @@ extern char options[OptLast]; extern unsigned capabilities; extern unsigned out_capabilities; +extern unsigned priv_magic; +extern unsigned out_priv_magic; extern bool is_multiplanar; extern __u32 vidcap_buftype; extern __u32 vidout_buftype; diff -Nru v4l-utils-1.0.0+r2263/utils/v4l2-ctl/v4l2-ctl-misc.cpp v4l-utils-1.0.0+r2364/utils/v4l2-ctl/v4l2-ctl-misc.cpp --- v4l-utils-1.0.0+r2263/utils/v4l2-ctl/v4l2-ctl-misc.cpp 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/v4l2-ctl/v4l2-ctl-misc.cpp 2014-08-12 09:02:18.000000000 +0000 @@ -29,7 +29,8 @@ " --wait-for-event=\n" " wait for an event [VIDIOC_DQEVENT]\n" " is the event number or one of:\n" - " eos, vsync, ctrl=, frame_sync, source_change=\n" + " eos, vsync, ctrl=, frame_sync, source_change=,\n" + " motion_det\n" " where is the name of the control\n" " and where is the index of the pad or input\n" " --poll-for-event=\n" diff -Nru v4l-utils-1.0.0+r2263/utils/v4l2-ctl/v4l2-ctl-overlay.cpp v4l-utils-1.0.0+r2364/utils/v4l2-ctl/v4l2-ctl-overlay.cpp --- v4l-utils-1.0.0+r2263/utils/v4l2-ctl/v4l2-ctl-overlay.cpp 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/v4l2-ctl/v4l2-ctl-overlay.cpp 2014-08-12 09:02:18.000000000 +0000 @@ -183,14 +183,14 @@ }; static const struct bitfield2fmt fb_formats[] = { - { 10, 5, 5, 5, 0, 5, 15, 1, V4L2_PIX_FMT_RGB555 }, + { 10, 5, 5, 5, 0, 5, 15, 1, V4L2_PIX_FMT_ARGB555 }, { 11, 5, 5, 6, 0, 5, 0, 0, V4L2_PIX_FMT_RGB565 }, { 1, 5, 6, 5, 11, 5, 0, 1, V4L2_PIX_FMT_RGB555X }, { 0, 5, 5, 6, 11, 5, 0, 0, V4L2_PIX_FMT_RGB565X }, { 16, 8, 8, 8, 0, 8, 0, 0, V4L2_PIX_FMT_BGR24 }, { 0, 8, 8, 8, 16, 8, 0, 0, V4L2_PIX_FMT_RGB24 }, - { 16, 8, 8, 8, 0, 8, 24, 8, V4L2_PIX_FMT_BGR32 }, - { 8, 8, 16, 8, 24, 8, 0, 8, V4L2_PIX_FMT_RGB32 }, + { 16, 8, 8, 8, 0, 8, 24, 8, V4L2_PIX_FMT_ABGR32 }, + { 8, 8, 16, 8, 24, 8, 0, 8, V4L2_PIX_FMT_ARGB32 }, { } }; @@ -514,7 +514,8 @@ void overlay_set(int fd) { if ((options[OptSetOverlayFormat] || options[OptTryOverlayFormat]) && - (set_overlay_fmt || bitmap_rects.size() || clips.size())) { + (set_overlay_fmt || options[OptClearClips] || options[OptClearBitmap] || + bitmap_rects.size() || clips.size())) { struct v4l2_format fmt; memset(&fmt, 0, sizeof(fmt)); diff -Nru v4l-utils-1.0.0+r2263/utils/v4l2-ctl/v4l2-ctl-streaming.cpp v4l-utils-1.0.0+r2364/utils/v4l2-ctl/v4l2-ctl-streaming.cpp --- v4l-utils-1.0.0+r2263/utils/v4l2-ctl/v4l2-ctl-streaming.cpp 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/v4l2-ctl/v4l2-ctl-streaming.cpp 2014-08-12 09:02:18.000000000 +0000 @@ -18,7 +18,7 @@ #include "v4l2-ctl.h" extern "C" { -#include "vivi-tpg.h" +#include "vivid-tpg.h" } static unsigned stream_count; @@ -97,7 +97,7 @@ " can be one of: square, ntsc, pal\n" " --stream-out-video-aspect= can be one of: 4x3, 16x9, anamorphic\n" + " can be one of: 4x3, 14x9, 16x9, anamorphic\n" " --stream-out-alpha=\n" " value to use for the alpha component, range 0-255. The default is 0.\n" " --stream-out-alpha-red-only\n" @@ -318,6 +318,8 @@ case OptStreamOutVideoAspect: if (!strcmp(optarg, "4x3")) stream_out_video_aspect = TPG_VIDEO_ASPECT_4X3; + else if (!strcmp(optarg, "14x9")) + stream_out_video_aspect = TPG_VIDEO_ASPECT_14X9_CENTRE; else if (!strcmp(optarg, "16x9")) stream_out_video_aspect = TPG_VIDEO_ASPECT_16X9_CENTRE; else if (!strcmp(optarg, "anamorphic")) @@ -595,6 +597,7 @@ bool can_fill; memset(&fmt, 0, sizeof(fmt)); + fmt.fmt.pix.priv = out_priv_magic; fmt.type = b.type; doioctl(fd, VIDIOC_G_FMT, &fmt); if (test_ioctl(fd, VIDIOC_G_STD, &stream_out_std)) { @@ -675,12 +678,6 @@ struct v4l2_plane planes[VIDEO_MAX_PLANES]; struct v4l2_buffer buf; - tpg_s_field(&tpg, field); - if (field == V4L2_FIELD_TOP) - field = V4L2_FIELD_BOTTOM; - else if (field == V4L2_FIELD_BOTTOM) - field = V4L2_FIELD_TOP; - memset(&buf, 0, sizeof(buf)); memset(planes, 0, sizeof(planes)); buf.type = b.type; @@ -694,6 +691,12 @@ return -1; buf.field = field; + tpg_s_field(&tpg, field); + if (field == V4L2_FIELD_TOP) + field = V4L2_FIELD_BOTTOM; + else if (field == V4L2_FIELD_BOTTOM) + field = V4L2_FIELD_TOP; + if (b.is_mplane) { for (unsigned j = 0; j < b.num_planes; j++) { struct v4l2_plane &p = b.planes[i][j]; @@ -724,7 +727,7 @@ planes[j].m.userptr = (unsigned long)b.bufs[i][j]; } if (can_fill) - tpg_fillbuffer(&tpg, NULL, stream_out_std, j, (u8 *)b.bufs[i][j]); + tpg_fillbuffer(&tpg, stream_out_std, j, (u8 *)b.bufs[i][j]); } if (fin) fill_buffer_from_file(b, buf.index, fin); @@ -756,7 +759,7 @@ } if (!fin || !fill_buffer_from_file(b, buf.index, fin)) if (can_fill) - tpg_fillbuffer(&tpg, NULL, stream_out_std, 0, (u8 *)b.bufs[i][0]); + tpg_fillbuffer(&tpg, stream_out_std, 0, (u8 *)b.bufs[i][0]); } if (qbuf) { if (V4L2_TYPE_IS_OUTPUT(buf.type)) @@ -965,9 +968,9 @@ if (!fin && stream_out_refresh) { if (b.is_mplane) { for (unsigned j = 0; j < b.num_planes; j++) - tpg_fillbuffer(&tpg, NULL, stream_out_std, j, (u8 *)b.bufs[buf.index][j]); + tpg_fillbuffer(&tpg, stream_out_std, j, (u8 *)b.bufs[buf.index][j]); } else { - tpg_fillbuffer(&tpg, NULL, stream_out_std, 0, (u8 *)b.bufs[buf.index][0]); + tpg_fillbuffer(&tpg, stream_out_std, 0, (u8 *)b.bufs[buf.index][0]); } } @@ -1564,6 +1567,7 @@ if (out_fd < 0) { out_fd = fd; out_capabilities = capabilities; + out_priv_magic = priv_magic; } if (do_cap > 1) { diff -Nru v4l-utils-1.0.0+r2263/utils/v4l2-ctl/v4l2-ctl-vidcap.cpp v4l-utils-1.0.0+r2364/utils/v4l2-ctl/v4l2-ctl-vidcap.cpp --- v4l-utils-1.0.0+r2263/utils/v4l2-ctl/v4l2-ctl-vidcap.cpp 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/v4l2-ctl/v4l2-ctl-vidcap.cpp 2014-08-12 09:02:18.000000000 +0000 @@ -162,6 +162,8 @@ struct v4l2_format fmt; struct v4l2_format tmp; + memset(&fmt, 0, sizeof(fmt)); + fmt.fmt.pix.priv = priv_magic; fmt.type = vidcap_buftype; if (test_ioctl(fd, VIDIOC_G_FMT, &fmt) < 0) return; @@ -248,6 +250,8 @@ if (options[OptSetVideoFormat] || options[OptTryVideoFormat]) { struct v4l2_format vfmt; + memset(&vfmt, 0, sizeof(vfmt)); + vfmt.fmt.pix.priv = priv_magic; vfmt.type = vidcap_buftype; if (doioctl(fd, VIDIOC_G_FMT, &vfmt) == 0) { @@ -317,6 +321,8 @@ if (options[OptGetVideoFormat]) { struct v4l2_format vfmt; + memset(&vfmt, 0, sizeof(vfmt)); + vfmt.fmt.pix.priv = priv_magic; vfmt.type = vidcap_buftype; if (doioctl(fd, VIDIOC_G_FMT, &vfmt) == 0) printfmt(vfmt); diff -Nru v4l-utils-1.0.0+r2263/utils/v4l2-ctl/v4l2-ctl-vidout.cpp v4l-utils-1.0.0+r2364/utils/v4l2-ctl/v4l2-ctl-vidout.cpp --- v4l-utils-1.0.0+r2263/utils/v4l2-ctl/v4l2-ctl-vidout.cpp 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/v4l2-ctl/v4l2-ctl-vidout.cpp 2014-08-12 09:02:18.000000000 +0000 @@ -46,6 +46,8 @@ struct v4l2_format fmt; struct v4l2_format tmp; + memset(&fmt, 0, sizeof(fmt)); + fmt.fmt.pix.priv = priv_magic; fmt.type = vidout_buftype; if (test_ioctl(fd, VIDIOC_G_FMT, &fmt) < 0) return; @@ -91,6 +93,8 @@ if (options[OptSetVideoOutFormat] || options[OptTryVideoOutFormat]) { struct v4l2_format vfmt; + memset(&vfmt, 0, sizeof(vfmt)); + vfmt.fmt.pix.priv = priv_magic; vfmt.type = vidout_buftype; if (doioctl(fd, VIDIOC_G_FMT, &vfmt) == 0) { if (is_multiplanar) { @@ -163,6 +167,8 @@ if (options[OptGetVideoOutFormat]) { struct v4l2_format vfmt; + memset(&vfmt, 0, sizeof(vfmt)); + vfmt.fmt.pix.priv = priv_magic; vfmt.type = vidout_buftype; if (doioctl(fd, VIDIOC_G_FMT, &vfmt) == 0) printfmt(vfmt); diff -Nru v4l-utils-1.0.0+r2263/utils/v4l2-ctl/vivi-colors.c v4l-utils-1.0.0+r2364/utils/v4l2-ctl/vivi-colors.c --- v4l-utils-1.0.0+r2263/utils/v4l2-ctl/vivi-colors.c 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/v4l2-ctl/vivi-colors.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,273 +0,0 @@ -#include - -#include "vivi-colors.h" - -/* sRGB colors with range [0-255] */ -const struct color tpg_colors[TPG_COLOR_MAX] = { - /* - * Colors to test colorspace conversion: converting these colors - * to other colorspaces will never lead to out-of-gamut colors. - */ - { 191, 191, 191 }, /* TPG_COLOR_CSC_WHITE */ - { 191, 191, 50 }, /* TPG_COLOR_CSC_YELLOW */ - { 50, 191, 191 }, /* TPG_COLOR_CSC_CYAN */ - { 50, 191, 50 }, /* TPG_COLOR_CSC_GREEN */ - { 191, 50, 191 }, /* TPG_COLOR_CSC_MAGENTA */ - { 191, 50, 50 }, /* TPG_COLOR_CSC_RED */ - { 50, 50, 191 }, /* TPG_COLOR_CSC_BLUE */ - { 50, 50, 50 }, /* TPG_COLOR_CSC_BLACK */ - - /* 75% colors */ - { 191, 191, 0 }, /* TPG_COLOR_75_YELLOW */ - { 0, 191, 191 }, /* TPG_COLOR_75_CYAN */ - { 0, 191, 0 }, /* TPG_COLOR_75_GREEN */ - { 191, 0, 191 }, /* TPG_COLOR_75_MAGENTA */ - { 191, 0, 0 }, /* TPG_COLOR_75_RED */ - { 0, 0, 191 }, /* TPG_COLOR_75_BLUE */ - - /* 100% colors */ - { 255, 255, 255 }, /* TPG_COLOR_100_WHITE */ - { 255, 255, 0 }, /* TPG_COLOR_100_YELLOW */ - { 0, 255, 255 }, /* TPG_COLOR_100_CYAN */ - { 0, 255, 0 }, /* TPG_COLOR_100_GREEN */ - { 255, 0, 255 }, /* TPG_COLOR_100_MAGENTA */ - { 255, 0, 0 }, /* TPG_COLOR_100_RED */ - { 0, 0, 255 }, /* TPG_COLOR_100_BLUE */ - { 0, 0, 0 }, /* TPG_COLOR_100_BLACK */ - - { 0, 0, 0 }, /* TPG_COLOR_RANDOM placeholder */ -}; - -#ifndef COMPILE_APP - -/* Generated table */ -const struct color16 tpg_csc_colors[V4L2_COLORSPACE_SRGB + 1][TPG_COLOR_CSC_BLACK + 1] = { - [V4L2_COLORSPACE_SMPTE170M][0] = { 2953, 2939, 2939 }, - [V4L2_COLORSPACE_SMPTE170M][1] = { 2954, 2963, 585 }, - [V4L2_COLORSPACE_SMPTE170M][2] = { 84, 2967, 2937 }, - [V4L2_COLORSPACE_SMPTE170M][3] = { 93, 2990, 575 }, - [V4L2_COLORSPACE_SMPTE170M][4] = { 3030, 259, 2933 }, - [V4L2_COLORSPACE_SMPTE170M][5] = { 3031, 406, 557 }, - [V4L2_COLORSPACE_SMPTE170M][6] = { 544, 428, 2931 }, - [V4L2_COLORSPACE_SMPTE170M][7] = { 551, 547, 547 }, - [V4L2_COLORSPACE_SMPTE240M][0] = { 2926, 2926, 2926 }, - [V4L2_COLORSPACE_SMPTE240M][1] = { 2926, 2926, 857 }, - [V4L2_COLORSPACE_SMPTE240M][2] = { 1594, 2901, 2901 }, - [V4L2_COLORSPACE_SMPTE240M][3] = { 1594, 2901, 774 }, - [V4L2_COLORSPACE_SMPTE240M][4] = { 2484, 618, 2858 }, - [V4L2_COLORSPACE_SMPTE240M][5] = { 2484, 618, 617 }, - [V4L2_COLORSPACE_SMPTE240M][6] = { 507, 507, 2832 }, - [V4L2_COLORSPACE_SMPTE240M][7] = { 507, 507, 507 }, - [V4L2_COLORSPACE_REC709][0] = { 2939, 2939, 2939 }, - [V4L2_COLORSPACE_REC709][1] = { 2939, 2939, 547 }, - [V4L2_COLORSPACE_REC709][2] = { 547, 2939, 2939 }, - [V4L2_COLORSPACE_REC709][3] = { 547, 2939, 547 }, - [V4L2_COLORSPACE_REC709][4] = { 2939, 547, 2939 }, - [V4L2_COLORSPACE_REC709][5] = { 2939, 547, 547 }, - [V4L2_COLORSPACE_REC709][6] = { 547, 547, 2939 }, - [V4L2_COLORSPACE_REC709][7] = { 547, 547, 547 }, - [V4L2_COLORSPACE_470_SYSTEM_M][0] = { 2894, 2988, 2808 }, - [V4L2_COLORSPACE_470_SYSTEM_M][1] = { 2847, 3070, 843 }, - [V4L2_COLORSPACE_470_SYSTEM_M][2] = { 1656, 2962, 2783 }, - [V4L2_COLORSPACE_470_SYSTEM_M][3] = { 1572, 3045, 763 }, - [V4L2_COLORSPACE_470_SYSTEM_M][4] = { 2477, 229, 2743 }, - [V4L2_COLORSPACE_470_SYSTEM_M][5] = { 2422, 672, 614 }, - [V4L2_COLORSPACE_470_SYSTEM_M][6] = { 725, 63, 2718 }, - [V4L2_COLORSPACE_470_SYSTEM_M][7] = { 534, 561, 509 }, - [V4L2_COLORSPACE_470_SYSTEM_BG][0] = { 2939, 2939, 2939 }, - [V4L2_COLORSPACE_470_SYSTEM_BG][1] = { 2939, 2939, 621 }, - [V4L2_COLORSPACE_470_SYSTEM_BG][2] = { 786, 2939, 2939 }, - [V4L2_COLORSPACE_470_SYSTEM_BG][3] = { 786, 2939, 621 }, - [V4L2_COLORSPACE_470_SYSTEM_BG][4] = { 2879, 547, 2923 }, - [V4L2_COLORSPACE_470_SYSTEM_BG][5] = { 2879, 547, 547 }, - [V4L2_COLORSPACE_470_SYSTEM_BG][6] = { 547, 547, 2923 }, - [V4L2_COLORSPACE_470_SYSTEM_BG][7] = { 547, 547, 547 }, - [V4L2_COLORSPACE_SRGB][0] = { 3056, 3056, 3056 }, - [V4L2_COLORSPACE_SRGB][1] = { 3056, 3056, 800 }, - [V4L2_COLORSPACE_SRGB][2] = { 800, 3056, 3056 }, - [V4L2_COLORSPACE_SRGB][3] = { 800, 3056, 800 }, - [V4L2_COLORSPACE_SRGB][4] = { 3056, 800, 3056 }, - [V4L2_COLORSPACE_SRGB][5] = { 3056, 800, 800 }, - [V4L2_COLORSPACE_SRGB][6] = { 800, 800, 3056 }, - [V4L2_COLORSPACE_SRGB][7] = { 800, 800, 800 }, -}; - -#else - -/* This code generates the table above */ - -#include -#include -#include - -static const double rec709_to_ntsc1953[3][3] = { - { 0.6698, 0.2678, 0.0323 }, - { 0.0185, 1.0742, -0.0603 }, - { 0.0162, 0.0432, 0.8551 } -}; - -static const double rec709_to_ebu[3][3] = { - { 0.9578, 0.0422, 0 }, - { 0 , 1 , 0 }, - { 0 , 0.0118, 0.9882 } -}; - -static const double rec709_to_170m[3][3] = { - { 1.0654, -0.0554, -0.0010 }, - { -0.0196, 1.0364, -0.0167 }, - { 0.0016, 0.0044, 0.9940 } -}; - -static const double rec709_to_240m[3][3] = { - { 0.7151, 0.2849, 0 }, - { 0.0179, 0.9821, 0 }, - { 0.0177, 0.0472, 0.9350 } -}; - - -static void mult_matrix(double *r, double *g, double *b, const double m[3][3]) -{ - double ir, ig, ib; - - ir = m[0][0] * (*r) + m[0][1] * (*g) + m[0][2] * (*b); - ig = m[1][0] * (*r) + m[1][1] * (*g) + m[1][2] * (*b); - ib = m[2][0] * (*r) + m[2][1] * (*g) + m[2][2] * (*b); - *r = ir; - *g = ig; - *b = ib; -} - -static double transfer_srgb_to_rgb(double v) -{ - return (v <= 0.03928) ? v / 12.92 : pow((v + 0.055) / 1.055, 2.4); -} - -static double transfer_rgb_to_smpte240m(double v) -{ - return (v <= 0.0228) ? v * 4.0 : 1.1115 * pow(v, 0.45) - 0.1115; -} - -static double transfer_rgb_to_rec709(double v) -{ - return (v < 0.018) ? v * 4.5 : 1.099 * pow(v, 0.45) - 0.099; -} - -static double transfer_srgb_to_rec709(double v) -{ - return transfer_rgb_to_rec709(transfer_srgb_to_rgb(v)); -} - -static void csc(enum v4l2_colorspace colorspace, double *r, double *g, double *b) -{ - /* Convert the primaries of Rec. 709 Linear RGB */ - switch (colorspace) { - case V4L2_COLORSPACE_SMPTE240M: - *r = transfer_srgb_to_rgb(*r); - *g = transfer_srgb_to_rgb(*g); - *b = transfer_srgb_to_rgb(*b); - mult_matrix(r, g, b, rec709_to_240m); - break; - case V4L2_COLORSPACE_SMPTE170M: - *r = transfer_srgb_to_rgb(*r); - *g = transfer_srgb_to_rgb(*g); - *b = transfer_srgb_to_rgb(*b); - mult_matrix(r, g, b, rec709_to_170m); - break; - case V4L2_COLORSPACE_470_SYSTEM_BG: - *r = transfer_srgb_to_rgb(*r); - *g = transfer_srgb_to_rgb(*g); - *b = transfer_srgb_to_rgb(*b); - mult_matrix(r, g, b, rec709_to_ebu); - break; - case V4L2_COLORSPACE_470_SYSTEM_M: - *r = transfer_srgb_to_rgb(*r); - *g = transfer_srgb_to_rgb(*g); - *b = transfer_srgb_to_rgb(*b); - mult_matrix(r, g, b, rec709_to_ntsc1953); - break; - case V4L2_COLORSPACE_SRGB: - case V4L2_COLORSPACE_REC709: - default: - break; - } - - *r = ((*r) < 0) ? 0 : (((*r) > 1) ? 1 : (*r)); - *g = ((*g) < 0) ? 0 : (((*g) > 1) ? 1 : (*g)); - *b = ((*b) < 0) ? 0 : (((*b) > 1) ? 1 : (*b)); - - /* Encode to gamma corrected colorspace */ - switch (colorspace) { - case V4L2_COLORSPACE_SMPTE240M: - *r = transfer_rgb_to_smpte240m(*r); - *g = transfer_rgb_to_smpte240m(*g); - *b = transfer_rgb_to_smpte240m(*b); - break; - case V4L2_COLORSPACE_SMPTE170M: - case V4L2_COLORSPACE_470_SYSTEM_M: - case V4L2_COLORSPACE_470_SYSTEM_BG: - *r = transfer_rgb_to_rec709(*r); - *g = transfer_rgb_to_rec709(*g); - *b = transfer_rgb_to_rec709(*b); - break; - case V4L2_COLORSPACE_SRGB: - break; - case V4L2_COLORSPACE_REC709: - default: - *r = transfer_srgb_to_rec709(*r); - *g = transfer_srgb_to_rec709(*g); - *b = transfer_srgb_to_rec709(*b); - break; - } -} - -int main(int argc, char **argv) -{ - static const unsigned colorspaces[] = { - 0, - V4L2_COLORSPACE_SMPTE170M, - V4L2_COLORSPACE_SMPTE240M, - V4L2_COLORSPACE_REC709, - 0, - V4L2_COLORSPACE_470_SYSTEM_M, - V4L2_COLORSPACE_470_SYSTEM_BG, - 0, - V4L2_COLORSPACE_SRGB, - }; - static const char * const colorspace_names[] = { - "", - "V4L2_COLORSPACE_SMPTE170M", - "V4L2_COLORSPACE_SMPTE240M", - "V4L2_COLORSPACE_REC709", - "", - "V4L2_COLORSPACE_470_SYSTEM_M", - "V4L2_COLORSPACE_470_SYSTEM_BG", - "", - "V4L2_COLORSPACE_SRGB", - }; - int i; - int c; - - printf("/* Generated table */\n"); - printf("const struct color16 tpg_csc_colors[V4L2_COLORSPACE_SRGB + 1][TPG_COLOR_CSC_BLACK + 1] = {\n"); - for (c = 0; c <= V4L2_COLORSPACE_SRGB; c++) { - for (i = 0; i <= TPG_COLOR_CSC_BLACK; i++) { - double r, g, b; - - if (colorspaces[c] == 0) - continue; - - r = tpg_colors[i].r / 255.0; - g = tpg_colors[i].g / 255.0; - b = tpg_colors[i].b / 255.0; - - csc(c, &r, &g, &b); - - printf("\t[%s][%d] = { %d, %d, %d },\n", colorspace_names[c], i, - (int)(r * 4080), (int)(g * 4080), (int)(b * 4080)); - } - } - printf("};\n\n"); - return 0; -} - -#endif diff -Nru v4l-utils-1.0.0+r2263/utils/v4l2-ctl/vivi-colors.h v4l-utils-1.0.0+r2364/utils/v4l2-ctl/vivi-colors.h --- v4l-utils-1.0.0+r2263/utils/v4l2-ctl/vivi-colors.h 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/v4l2-ctl/vivi-colors.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -#ifndef _VIVI_COLORS_H_ -#define _VIVI_COLORS_H_ - -struct color { - unsigned char r, g, b; -}; - -struct color16 { - int r, g, b; -}; - -enum tpg_color { - TPG_COLOR_CSC_WHITE, - TPG_COLOR_CSC_YELLOW, - TPG_COLOR_CSC_CYAN, - TPG_COLOR_CSC_GREEN, - TPG_COLOR_CSC_MAGENTA, - TPG_COLOR_CSC_RED, - TPG_COLOR_CSC_BLUE, - TPG_COLOR_CSC_BLACK, - TPG_COLOR_75_YELLOW, - TPG_COLOR_75_CYAN, - TPG_COLOR_75_GREEN, - TPG_COLOR_75_MAGENTA, - TPG_COLOR_75_RED, - TPG_COLOR_75_BLUE, - TPG_COLOR_100_WHITE, - TPG_COLOR_100_YELLOW, - TPG_COLOR_100_CYAN, - TPG_COLOR_100_GREEN, - TPG_COLOR_100_MAGENTA, - TPG_COLOR_100_RED, - TPG_COLOR_100_BLUE, - TPG_COLOR_100_BLACK, - TPG_COLOR_TEXTFG, - TPG_COLOR_TEXTBG, - TPG_COLOR_RANDOM, - TPG_COLOR_RAMP, - TPG_COLOR_MAX = TPG_COLOR_RAMP + 256 -}; - -extern const struct color tpg_colors[TPG_COLOR_MAX]; -extern const struct color16 tpg_csc_colors[V4L2_COLORSPACE_SRGB + 1][TPG_COLOR_CSC_BLACK + 1]; - -#endif diff -Nru v4l-utils-1.0.0+r2263/utils/v4l2-ctl/vivid-tpg.c v4l-utils-1.0.0+r2364/utils/v4l2-ctl/vivid-tpg.c --- v4l-utils-1.0.0+r2263/utils/v4l2-ctl/vivid-tpg.c 1970-01-01 00:00:00.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/v4l2-ctl/vivid-tpg.c 2014-08-12 09:02:18.000000000 +0000 @@ -0,0 +1,1439 @@ +/* + * vivid-tpg.c - Test Pattern Generator + * + * Note: gen_twopix and tpg_gen_text are based on code from vivi.c. See the + * vivi.c source for the copyright information of those functions. + * + * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "vivid-tpg.h" + +/* Must remain in sync with enum tpg_pattern */ +const char * const tpg_pattern_strings[] = { + "75% Colorbar", + "100% Colorbar", + "CSC Colorbar", + "Horizontal 100% Colorbar", + "100% Color Squares", + "100% Black", + "100% White", + "100% Red", + "100% Green", + "100% Blue", + "16x16 Checkers", + "1x1 Checkers", + "Alternating Hor Lines", + "Alternating Vert Lines", + "One Pixel Wide Cross", + "Two Pixels Wide Cross", + "Ten Pixels Wide Cross", + "Gray Ramp", + "Noise", + NULL +}; + +/* Must remain in sync with enum tpg_aspect */ +const char * const tpg_aspect_strings[] = { + "Source Width x Height", + "4x3", + "14x9", + "16x9", + "16x9 Anamorphic", + NULL +}; + +/* + * Sinus table: sin[0] = 127 * sin(-180 degrees) + * sin[128] = 127 * sin(0 degrees) + * sin[256] = 127 * sin(180 degrees) + */ +static const s8 sin[257] = { + 0, -4, -7, -11, -13, -18, -20, -22, -26, -29, -33, -35, -37, -41, -43, -48, + -50, -52, -56, -58, -62, -63, -65, -69, -71, -75, -76, -78, -82, -83, -87, -88, + -90, -93, -94, -97, -99, -101, -103, -104, -107, -108, -110, -111, -112, -114, -115, -117, + -118, -119, -120, -121, -122, -123, -123, -124, -125, -125, -126, -126, -127, -127, -127, -127, + -127, -127, -127, -127, -126, -126, -125, -125, -124, -124, -123, -122, -121, -120, -119, -118, + -117, -116, -114, -113, -111, -110, -109, -107, -105, -103, -101, -100, -97, -96, -93, -91, + -90, -87, -85, -82, -80, -76, -75, -73, -69, -67, -63, -62, -60, -56, -54, -50, + -48, -46, -41, -39, -35, -33, -31, -26, -24, -20, -18, -15, -11, -9, -4, -2, + 0, 2, 4, 9, 11, 15, 18, 20, 24, 26, 31, 33, 35, 39, 41, 46, + 48, 50, 54, 56, 60, 62, 64, 67, 69, 73, 75, 76, 80, 82, 85, 87, + 90, 91, 93, 96, 97, 100, 101, 103, 105, 107, 109, 110, 111, 113, 114, 116, + 117, 118, 119, 120, 121, 122, 123, 124, 124, 125, 125, 126, 126, 127, 127, 127, + 127, 127, 127, 127, 127, 126, 126, 125, 125, 124, 123, 123, 122, 121, 120, 119, + 118, 117, 115, 114, 112, 111, 110, 108, 107, 104, 103, 101, 99, 97, 94, 93, + 90, 88, 87, 83, 82, 78, 76, 75, 71, 69, 65, 64, 62, 58, 56, 52, + 50, 48, 43, 41, 37, 35, 33, 29, 26, 22, 20, 18, 13, 11, 7, 4, + 0, +}; + +#define cos(idx) sin[((idx) + 64) % sizeof(sin)] + +/* Global font descriptor */ +static const u8 *font8x16; + +void tpg_set_font(const u8 *f) +{ + font8x16 = f; +} + +void tpg_init(struct tpg_data *tpg, unsigned w, unsigned h) +{ + memset(tpg, 0, sizeof(*tpg)); + tpg->scaled_width = tpg->src_width = w; + tpg->src_height = tpg->buf_height = h; + tpg->crop.width = tpg->compose.width = w; + tpg->crop.height = tpg->compose.height = h; + tpg->recalc_colors = true; + tpg->recalc_square_border = true; + tpg->brightness = 128; + tpg->contrast = 128; + tpg->saturation = 128; + tpg->hue = 0; + tpg->mv_hor_mode = TPG_MOVE_NONE; + tpg->mv_vert_mode = TPG_MOVE_NONE; + tpg->field = V4L2_FIELD_NONE; + tpg_s_fourcc(tpg, V4L2_PIX_FMT_RGB24); + tpg->colorspace = V4L2_COLORSPACE_SRGB; + tpg->perc_fill = 100; +} + +int tpg_alloc(struct tpg_data *tpg, unsigned max_w) +{ + unsigned pat; + unsigned plane; + + tpg->max_line_width = max_w; + for (pat = 0; pat < TPG_MAX_PAT_LINES; pat++) { + for (plane = 0; plane < TPG_MAX_PLANES; plane++) { + unsigned pixelsz = plane ? 1 : 4; + + tpg->lines[pat][plane] = vzalloc(max_w * 2 * pixelsz); + if (!tpg->lines[pat][plane]) + return -ENOMEM; + } + } + for (plane = 0; plane < TPG_MAX_PLANES; plane++) { + unsigned pixelsz = plane ? 1 : 4; + + tpg->contrast_line[plane] = vzalloc(max_w * pixelsz); + if (!tpg->contrast_line[plane]) + return -ENOMEM; + tpg->black_line[plane] = vzalloc(max_w * pixelsz); + if (!tpg->black_line[plane]) + return -ENOMEM; + tpg->random_line[plane] = vzalloc(max_w * pixelsz); + if (!tpg->random_line[plane]) + return -ENOMEM; + } + return 0; +} + +void tpg_free(struct tpg_data *tpg) +{ + unsigned pat; + unsigned plane; + + for (pat = 0; pat < TPG_MAX_PAT_LINES; pat++) + for (plane = 0; plane < TPG_MAX_PLANES; plane++) { + vfree(tpg->lines[pat][plane]); + tpg->lines[pat][plane] = NULL; + } + for (plane = 0; plane < TPG_MAX_PLANES; plane++) { + vfree(tpg->contrast_line[plane]); + vfree(tpg->black_line[plane]); + vfree(tpg->random_line[plane]); + tpg->contrast_line[plane] = NULL; + tpg->black_line[plane] = NULL; + tpg->random_line[plane] = NULL; + } +} + +bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc) +{ + tpg->fourcc = fourcc; + tpg->planes = 1; + tpg->recalc_colors = true; + switch (fourcc) { + case V4L2_PIX_FMT_RGB565: + case V4L2_PIX_FMT_RGB565X: + case V4L2_PIX_FMT_RGB555: + case V4L2_PIX_FMT_XRGB555: + case V4L2_PIX_FMT_ARGB555: + case V4L2_PIX_FMT_RGB555X: + case V4L2_PIX_FMT_RGB24: + case V4L2_PIX_FMT_BGR24: + case V4L2_PIX_FMT_RGB32: + case V4L2_PIX_FMT_BGR32: + case V4L2_PIX_FMT_XRGB32: + case V4L2_PIX_FMT_XBGR32: + case V4L2_PIX_FMT_ARGB32: + case V4L2_PIX_FMT_ABGR32: + tpg->is_yuv = 0; + break; + case V4L2_PIX_FMT_NV16M: + case V4L2_PIX_FMT_NV61M: + tpg->planes = 2; + /* fall-through */ + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_YVYU: + case V4L2_PIX_FMT_VYUY: + tpg->is_yuv = 1; + break; + default: + return false; + } + + switch (fourcc) { + case V4L2_PIX_FMT_RGB565: + case V4L2_PIX_FMT_RGB565X: + case V4L2_PIX_FMT_RGB555: + case V4L2_PIX_FMT_XRGB555: + case V4L2_PIX_FMT_ARGB555: + case V4L2_PIX_FMT_RGB555X: + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_YVYU: + case V4L2_PIX_FMT_VYUY: + tpg->twopixelsize[0] = 2 * 2; + break; + case V4L2_PIX_FMT_RGB24: + case V4L2_PIX_FMT_BGR24: + tpg->twopixelsize[0] = 2 * 3; + break; + case V4L2_PIX_FMT_RGB32: + case V4L2_PIX_FMT_BGR32: + case V4L2_PIX_FMT_XRGB32: + case V4L2_PIX_FMT_XBGR32: + case V4L2_PIX_FMT_ARGB32: + case V4L2_PIX_FMT_ABGR32: + tpg->twopixelsize[0] = 2 * 4; + break; + case V4L2_PIX_FMT_NV16M: + case V4L2_PIX_FMT_NV61M: + tpg->twopixelsize[0] = 2; + tpg->twopixelsize[1] = 2; + break; + } + return true; +} + +void tpg_s_crop_compose(struct tpg_data *tpg, const struct v4l2_rect *crop, + const struct v4l2_rect *compose) +{ + tpg->crop = *crop; + tpg->compose = *compose; + tpg->scaled_width = (tpg->src_width * tpg->compose.width + + tpg->crop.width - 1) / tpg->crop.width; + tpg->scaled_width &= ~1; + if (tpg->scaled_width > tpg->max_line_width) + tpg->scaled_width = tpg->max_line_width; + if (tpg->scaled_width < 2) + tpg->scaled_width = 2; + tpg->recalc_lines = true; +} + +void tpg_reset_source(struct tpg_data *tpg, unsigned width, unsigned height, + enum v4l2_field field) +{ + unsigned p; + + tpg->src_width = width; + tpg->src_height = height; + tpg->field = field; + tpg->buf_height = height; + if (V4L2_FIELD_HAS_T_OR_B(field)) + tpg->buf_height /= 2; + tpg->scaled_width = width; + tpg->crop.top = tpg->crop.left = 0; + tpg->crop.width = width; + tpg->crop.height = height; + tpg->compose.top = tpg->compose.left = 0; + tpg->compose.width = width; + tpg->compose.height = tpg->buf_height; + for (p = 0; p < tpg->planes; p++) + tpg->bytesperline[p] = width * tpg->twopixelsize[p] / 2; + tpg->recalc_square_border = true; +} + +static enum tpg_color tpg_get_textbg_color(struct tpg_data *tpg) +{ + switch (tpg->pattern) { + case TPG_PAT_BLACK: + return TPG_COLOR_100_WHITE; + case TPG_PAT_CSC_COLORBAR: + return TPG_COLOR_CSC_BLACK; + default: + return TPG_COLOR_100_BLACK; + } +} + +static enum tpg_color tpg_get_textfg_color(struct tpg_data *tpg) +{ + switch (tpg->pattern) { + case TPG_PAT_75_COLORBAR: + case TPG_PAT_CSC_COLORBAR: + return TPG_COLOR_CSC_WHITE; + case TPG_PAT_BLACK: + return TPG_COLOR_100_BLACK; + default: + return TPG_COLOR_100_WHITE; + } +} + +static u16 color_to_y(struct tpg_data *tpg, int r, int g, int b) +{ + switch (tpg->colorspace) { + case V4L2_COLORSPACE_SMPTE170M: + case V4L2_COLORSPACE_470_SYSTEM_M: + case V4L2_COLORSPACE_470_SYSTEM_BG: + return ((16829 * r + 33039 * g + 6416 * b + 16 * 32768) >> 16) + (16 << 4); + case V4L2_COLORSPACE_SMPTE240M: + return ((11932 * r + 39455 * g + 4897 * b + 16 * 32768) >> 16) + (16 << 4); + case V4L2_COLORSPACE_REC709: + case V4L2_COLORSPACE_SRGB: + default: + return ((11966 * r + 40254 * g + 4064 * b + 16 * 32768) >> 16) + (16 << 4); + } +} + +static u16 color_to_cb(struct tpg_data *tpg, int r, int g, int b) +{ + switch (tpg->colorspace) { + case V4L2_COLORSPACE_SMPTE170M: + case V4L2_COLORSPACE_470_SYSTEM_M: + case V4L2_COLORSPACE_470_SYSTEM_BG: + return ((-9714 * r - 19070 * g + 28784 * b + 16 * 32768) >> 16) + (128 << 4); + case V4L2_COLORSPACE_SMPTE240M: + return ((-6684 * r - 22100 * g + 28784 * b + 16 * 32768) >> 16) + (128 << 4); + case V4L2_COLORSPACE_REC709: + case V4L2_COLORSPACE_SRGB: + default: + return ((-6596 * r - 22189 * g + 28784 * b + 16 * 32768) >> 16) + (128 << 4); + } +} + +static u16 color_to_cr(struct tpg_data *tpg, int r, int g, int b) +{ + switch (tpg->colorspace) { + case V4L2_COLORSPACE_SMPTE170M: + case V4L2_COLORSPACE_470_SYSTEM_M: + case V4L2_COLORSPACE_470_SYSTEM_BG: + return ((28784 * r - 24103 * g - 4681 * b + 16 * 32768) >> 16) + (128 << 4); + case V4L2_COLORSPACE_SMPTE240M: + return ((28784 * r - 25606 * g - 3178 * b + 16 * 32768) >> 16) + (128 << 4); + case V4L2_COLORSPACE_REC709: + case V4L2_COLORSPACE_SRGB: + default: + return ((28784 * r - 26145 * g - 2639 * b + 16 * 32768) >> 16) + (128 << 4); + } +} + +static u16 ycbcr_to_r(struct tpg_data *tpg, int y, int cb, int cr) +{ + int r; + + y -= 16 << 4; + cb -= 128 << 4; + cr -= 128 << 4; + switch (tpg->colorspace) { + case V4L2_COLORSPACE_SMPTE170M: + case V4L2_COLORSPACE_470_SYSTEM_M: + case V4L2_COLORSPACE_470_SYSTEM_BG: + r = 4769 * y + 6537 * cr; + break; + case V4L2_COLORSPACE_SMPTE240M: + r = 4769 * y + 7376 * cr; + break; + case V4L2_COLORSPACE_REC709: + case V4L2_COLORSPACE_SRGB: + default: + r = 4769 * y + 7343 * cr; + break; + } + return clamp(r >> 12, 0, 0xff0); +} + +static u16 ycbcr_to_g(struct tpg_data *tpg, int y, int cb, int cr) +{ + int g; + + y -= 16 << 4; + cb -= 128 << 4; + cr -= 128 << 4; + switch (tpg->colorspace) { + case V4L2_COLORSPACE_SMPTE170M: + case V4L2_COLORSPACE_470_SYSTEM_M: + case V4L2_COLORSPACE_470_SYSTEM_BG: + g = 4769 * y - 1605 * cb - 3330 * cr; + break; + case V4L2_COLORSPACE_SMPTE240M: + g = 4769 * y - 1055 * cb - 2341 * cr; + break; + case V4L2_COLORSPACE_REC709: + case V4L2_COLORSPACE_SRGB: + default: + g = 4769 * y - 873 * cb - 2183 * cr; + break; + } + return clamp(g >> 12, 0, 0xff0); +} + +static u16 ycbcr_to_b(struct tpg_data *tpg, int y, int cb, int cr) +{ + int b; + + y -= 16 << 4; + cb -= 128 << 4; + cr -= 128 << 4; + switch (tpg->colorspace) { + case V4L2_COLORSPACE_SMPTE170M: + case V4L2_COLORSPACE_470_SYSTEM_M: + case V4L2_COLORSPACE_470_SYSTEM_BG: + b = 4769 * y + 7343 * cb; + break; + case V4L2_COLORSPACE_SMPTE240M: + b = 4769 * y + 8552 * cb; + break; + case V4L2_COLORSPACE_REC709: + case V4L2_COLORSPACE_SRGB: + default: + b = 4769 * y + 8652 * cb; + break; + } + return clamp(b >> 12, 0, 0xff0); +} + +/* precalculate color bar values to speed up rendering */ +static void precalculate_color(struct tpg_data *tpg, int k) +{ + int col = k; + int r = tpg_colors[col].r; + int g = tpg_colors[col].g; + int b = tpg_colors[col].b; + + if (k == TPG_COLOR_TEXTBG) { + col = tpg_get_textbg_color(tpg); + + r = tpg_colors[col].r; + g = tpg_colors[col].g; + b = tpg_colors[col].b; + } else if (k == TPG_COLOR_TEXTFG) { + col = tpg_get_textfg_color(tpg); + + r = tpg_colors[col].r; + g = tpg_colors[col].g; + b = tpg_colors[col].b; + } else if (tpg->pattern == TPG_PAT_NOISE) { + r = g = b = prandom_u32_max(256); + } else if (k == TPG_COLOR_RANDOM) { + r = g = b = tpg->qual_offset + prandom_u32_max(196); + } else if (k >= TPG_COLOR_RAMP) { + r = g = b = k - TPG_COLOR_RAMP; + } + + if (tpg->pattern == TPG_PAT_CSC_COLORBAR && col <= TPG_COLOR_CSC_BLACK) { + r = tpg_csc_colors[tpg->colorspace][col].r; + g = tpg_csc_colors[tpg->colorspace][col].g; + b = tpg_csc_colors[tpg->colorspace][col].b; + } else { + r <<= 4; + g <<= 4; + b <<= 4; + } + if (tpg->qual == TPG_QUAL_GRAY) + r = g = b = color_to_y(tpg, r, g, b); + + /* + * The assumption is that the RGB output is always full range, + * so only if the rgb_range overrides the 'real' rgb range do + * we need to convert the RGB values. + * + * Currently there is no way of signalling to userspace if you + * are actually giving it limited range RGB (or full range + * YUV for that matter). + * + * Remember that r, g and b are still in the 0 - 0xff0 range. + */ + if (tpg->real_rgb_range == V4L2_DV_RGB_RANGE_LIMITED && + tpg->rgb_range == V4L2_DV_RGB_RANGE_FULL) { + /* + * Convert from full range (which is what r, g and b are) + * to limited range (which is the 'real' RGB range), which + * is then interpreted as full range. + */ + r = (r * 219) / 255 + (16 << 4); + g = (g * 219) / 255 + (16 << 4); + b = (b * 219) / 255 + (16 << 4); + } else if (tpg->real_rgb_range != V4L2_DV_RGB_RANGE_LIMITED && + tpg->rgb_range == V4L2_DV_RGB_RANGE_LIMITED) { + /* + * Clamp r, g and b to the limited range and convert to full + * range since that's what we deliver. + */ + r = clamp(r, 16 << 4, 235 << 4); + g = clamp(g, 16 << 4, 235 << 4); + b = clamp(b, 16 << 4, 235 << 4); + r = (r - (16 << 4)) * 255 / 219; + g = (g - (16 << 4)) * 255 / 219; + b = (b - (16 << 4)) * 255 / 219; + } + + if (tpg->brightness != 128 || tpg->contrast != 128 || + tpg->saturation != 128 || tpg->hue) { + /* Implement these operations */ + + /* First convert to YCbCr */ + int y = color_to_y(tpg, r, g, b); /* Luma */ + int cb = color_to_cb(tpg, r, g, b); /* Cb */ + int cr = color_to_cr(tpg, r, g, b); /* Cr */ + int tmp_cb, tmp_cr; + + y = (16 << 4) + ((y - (16 << 4)) * tpg->contrast) / 128; + y += (tpg->brightness << 4) - (128 << 4); + + cb -= 128 << 4; + cr -= 128 << 4; + tmp_cb = (cb * cos(128 + tpg->hue)) / 127 + (cr * sin[128 + tpg->hue]) / 127; + tmp_cr = (cr * cos(128 + tpg->hue)) / 127 - (cb * sin[128 + tpg->hue]) / 127; + + cb = (128 << 4) + (tmp_cb * tpg->contrast * tpg->saturation) / (128 * 128); + cr = (128 << 4) + (tmp_cr * tpg->contrast * tpg->saturation) / (128 * 128); + if (tpg->is_yuv) { + tpg->colors[k][0] = clamp(y >> 4, 1, 254); + tpg->colors[k][1] = clamp(cb >> 4, 1, 254); + tpg->colors[k][2] = clamp(cr >> 4, 1, 254); + return; + } + r = ycbcr_to_r(tpg, y, cb, cr); + g = ycbcr_to_g(tpg, y, cb, cr); + b = ycbcr_to_b(tpg, y, cb, cr); + } + + if (tpg->is_yuv) { + /* Convert to YCbCr */ + u16 y = color_to_y(tpg, r, g, b); /* Luma */ + u16 cb = color_to_cb(tpg, r, g, b); /* Cb */ + u16 cr = color_to_cr(tpg, r, g, b); /* Cr */ + + tpg->colors[k][0] = clamp(y >> 4, 1, 254); + tpg->colors[k][1] = clamp(cb >> 4, 1, 254); + tpg->colors[k][2] = clamp(cr >> 4, 1, 254); + } else { + switch (tpg->fourcc) { + case V4L2_PIX_FMT_RGB565: + case V4L2_PIX_FMT_RGB565X: + r >>= 7; + g >>= 6; + b >>= 7; + break; + case V4L2_PIX_FMT_RGB555: + case V4L2_PIX_FMT_XRGB555: + case V4L2_PIX_FMT_ARGB555: + case V4L2_PIX_FMT_RGB555X: + r >>= 7; + g >>= 7; + b >>= 7; + break; + default: + r >>= 4; + g >>= 4; + b >>= 4; + break; + } + + tpg->colors[k][0] = r; + tpg->colors[k][1] = g; + tpg->colors[k][2] = b; + } +} + +static void tpg_precalculate_colors(struct tpg_data *tpg) +{ + int k; + + for (k = 0; k < TPG_COLOR_MAX; k++) + precalculate_color(tpg, k); +} + +/* 'odd' is true for pixels 1, 3, 5, etc. and false for pixels 0, 2, 4, etc. */ +static void gen_twopix(struct tpg_data *tpg, + u8 buf[TPG_MAX_PLANES][8], int color, bool odd) +{ + unsigned offset = odd * tpg->twopixelsize[0] / 2; + u8 alpha = tpg->alpha_component; + u8 r_y, g_u, b_v; + + if (tpg->alpha_red_only && color != TPG_COLOR_CSC_RED && + color != TPG_COLOR_100_RED && + color != TPG_COLOR_75_RED) + alpha = 0; + if (color == TPG_COLOR_RANDOM) + precalculate_color(tpg, color); + r_y = tpg->colors[color][0]; /* R or precalculated Y */ + g_u = tpg->colors[color][1]; /* G or precalculated U */ + b_v = tpg->colors[color][2]; /* B or precalculated V */ + + switch (tpg->fourcc) { + case V4L2_PIX_FMT_NV16M: + buf[0][offset] = r_y; + buf[1][offset] = odd ? b_v : g_u; + break; + case V4L2_PIX_FMT_NV61M: + buf[0][offset] = r_y; + buf[1][offset] = odd ? g_u : b_v; + break; + + case V4L2_PIX_FMT_YUYV: + buf[0][offset] = r_y; + buf[0][offset + 1] = odd ? b_v : g_u; + break; + case V4L2_PIX_FMT_UYVY: + buf[0][offset] = odd ? b_v : g_u; + buf[0][offset + 1] = r_y; + break; + case V4L2_PIX_FMT_YVYU: + buf[0][offset] = r_y; + buf[0][offset + 1] = odd ? g_u : b_v; + break; + case V4L2_PIX_FMT_VYUY: + buf[0][offset] = odd ? g_u : b_v; + buf[0][offset + 1] = r_y; + break; + case V4L2_PIX_FMT_RGB565: + buf[0][offset] = (g_u << 5) | b_v; + buf[0][offset + 1] = (r_y << 3) | (g_u >> 3); + break; + case V4L2_PIX_FMT_RGB565X: + buf[0][offset] = (r_y << 3) | (g_u >> 3); + buf[0][offset + 1] = (g_u << 5) | b_v; + break; + case V4L2_PIX_FMT_RGB555: + case V4L2_PIX_FMT_XRGB555: + alpha = 0; + /* fall through */ + case V4L2_PIX_FMT_ARGB555: + buf[0][offset] = (g_u << 5) | b_v; + buf[0][offset + 1] = (alpha & 0x80) | (r_y << 2) | (g_u >> 3); + break; + case V4L2_PIX_FMT_RGB555X: + buf[0][offset] = (alpha & 0x80) | (r_y << 2) | (g_u >> 3); + buf[0][offset + 1] = (g_u << 5) | b_v; + break; + case V4L2_PIX_FMT_RGB24: + buf[0][offset] = r_y; + buf[0][offset + 1] = g_u; + buf[0][offset + 2] = b_v; + break; + case V4L2_PIX_FMT_BGR24: + buf[0][offset] = b_v; + buf[0][offset + 1] = g_u; + buf[0][offset + 2] = r_y; + break; + case V4L2_PIX_FMT_RGB32: + case V4L2_PIX_FMT_XRGB32: + alpha = 0; + /* fall through */ + case V4L2_PIX_FMT_ARGB32: + buf[0][offset] = alpha; + buf[0][offset + 1] = r_y; + buf[0][offset + 2] = g_u; + buf[0][offset + 3] = b_v; + break; + case V4L2_PIX_FMT_BGR32: + case V4L2_PIX_FMT_XBGR32: + alpha = 0; + /* fall through */ + case V4L2_PIX_FMT_ABGR32: + buf[0][offset] = b_v; + buf[0][offset + 1] = g_u; + buf[0][offset + 2] = r_y; + buf[0][offset + 3] = alpha; + break; + } +} + +/* Return how many pattern lines are used by the current pattern. */ +static unsigned tpg_get_pat_lines(struct tpg_data *tpg) +{ + switch (tpg->pattern) { + case TPG_PAT_CHECKERS_16X16: + case TPG_PAT_CHECKERS_1X1: + case TPG_PAT_ALTERNATING_HLINES: + case TPG_PAT_CROSS_1_PIXEL: + case TPG_PAT_CROSS_2_PIXELS: + case TPG_PAT_CROSS_10_PIXELS: + return 2; + case TPG_PAT_100_COLORSQUARES: + case TPG_PAT_100_HCOLORBAR: + return 8; + default: + return 1; + } +} + +/* Which pattern line should be used for the given frame line. */ +static unsigned tpg_get_pat_line(struct tpg_data *tpg, unsigned line) +{ + switch (tpg->pattern) { + case TPG_PAT_CHECKERS_16X16: + return (line >> 4) & 1; + case TPG_PAT_CHECKERS_1X1: + case TPG_PAT_ALTERNATING_HLINES: + return line & 1; + case TPG_PAT_100_COLORSQUARES: + case TPG_PAT_100_HCOLORBAR: + return (line * 8) / tpg->src_height; + case TPG_PAT_CROSS_1_PIXEL: + return line == tpg->src_height / 2; + case TPG_PAT_CROSS_2_PIXELS: + return (line + 1) / 2 == tpg->src_height / 4; + case TPG_PAT_CROSS_10_PIXELS: + return (line + 10) / 20 == tpg->src_height / 40; + default: + return 0; + } +} + +/* + * Which color should be used for the given pattern line and X coordinate. + * Note: x is in the range 0 to 2 * tpg->src_width. + */ +static enum tpg_color tpg_get_color(struct tpg_data *tpg, unsigned pat_line, unsigned x) +{ + /* Maximum number of bars are TPG_COLOR_MAX - otherwise, the input print code + should be modified */ + static const enum tpg_color bars[3][8] = { + /* Standard ITU-R 75% color bar sequence */ + { TPG_COLOR_CSC_WHITE, TPG_COLOR_75_YELLOW, + TPG_COLOR_75_CYAN, TPG_COLOR_75_GREEN, + TPG_COLOR_75_MAGENTA, TPG_COLOR_75_RED, + TPG_COLOR_75_BLUE, TPG_COLOR_100_BLACK, }, + /* Standard ITU-R 100% color bar sequence */ + { TPG_COLOR_100_WHITE, TPG_COLOR_100_YELLOW, + TPG_COLOR_100_CYAN, TPG_COLOR_100_GREEN, + TPG_COLOR_100_MAGENTA, TPG_COLOR_100_RED, + TPG_COLOR_100_BLUE, TPG_COLOR_100_BLACK, }, + /* Color bar sequence suitable to test CSC */ + { TPG_COLOR_CSC_WHITE, TPG_COLOR_CSC_YELLOW, + TPG_COLOR_CSC_CYAN, TPG_COLOR_CSC_GREEN, + TPG_COLOR_CSC_MAGENTA, TPG_COLOR_CSC_RED, + TPG_COLOR_CSC_BLUE, TPG_COLOR_CSC_BLACK, }, + }; + + switch (tpg->pattern) { + case TPG_PAT_75_COLORBAR: + case TPG_PAT_100_COLORBAR: + case TPG_PAT_CSC_COLORBAR: + return bars[tpg->pattern][((x * 8) / tpg->src_width) % 8]; + case TPG_PAT_100_COLORSQUARES: + return bars[1][(pat_line + (x * 8) / tpg->src_width) % 8]; + case TPG_PAT_100_HCOLORBAR: + return bars[1][pat_line]; + case TPG_PAT_BLACK: + return TPG_COLOR_100_BLACK; + case TPG_PAT_WHITE: + return TPG_COLOR_100_WHITE; + case TPG_PAT_RED: + return TPG_COLOR_100_RED; + case TPG_PAT_GREEN: + return TPG_COLOR_100_GREEN; + case TPG_PAT_BLUE: + return TPG_COLOR_100_BLUE; + case TPG_PAT_CHECKERS_16X16: + return (((x >> 4) & 1) ^ (pat_line & 1)) ? + TPG_COLOR_100_BLACK : TPG_COLOR_100_WHITE; + case TPG_PAT_CHECKERS_1X1: + return ((x & 1) ^ (pat_line & 1)) ? + TPG_COLOR_100_WHITE : TPG_COLOR_100_BLACK; + case TPG_PAT_ALTERNATING_HLINES: + return pat_line ? TPG_COLOR_100_WHITE : TPG_COLOR_100_BLACK; + case TPG_PAT_ALTERNATING_VLINES: + return (x & 1) ? TPG_COLOR_100_WHITE : TPG_COLOR_100_BLACK; + case TPG_PAT_CROSS_1_PIXEL: + if (pat_line || (x % tpg->src_width) == tpg->src_width / 2) + return TPG_COLOR_100_BLACK; + return TPG_COLOR_100_WHITE; + case TPG_PAT_CROSS_2_PIXELS: + if (pat_line || ((x % tpg->src_width) + 1) / 2 == tpg->src_width / 4) + return TPG_COLOR_100_BLACK; + return TPG_COLOR_100_WHITE; + case TPG_PAT_CROSS_10_PIXELS: + if (pat_line || ((x % tpg->src_width) + 10) / 20 == tpg->src_width / 40) + return TPG_COLOR_100_BLACK; + return TPG_COLOR_100_WHITE; + case TPG_PAT_GRAY_RAMP: + return TPG_COLOR_RAMP + ((x % tpg->src_width) * 256) / tpg->src_width; + default: + return TPG_COLOR_100_RED; + } +} + +/* + * Given the pixel aspect ratio and video aspect ratio calculate the + * coordinates of a centered square and the coordinates of the border of + * the active video area. The coordinates are relative to the source + * frame rectangle. + */ +static void tpg_calculate_square_border(struct tpg_data *tpg) +{ + unsigned w = tpg->src_width; + unsigned h = tpg->src_height; + unsigned sq_w, sq_h; + + sq_w = (w * 2 / 5) & ~1; + if (((w - sq_w) / 2) & 1) + sq_w += 2; + sq_h = sq_w; + tpg->square.width = sq_w; + if (tpg->vid_aspect == TPG_VIDEO_ASPECT_16X9_ANAMORPHIC) { + unsigned ana_sq_w = (sq_w / 4) * 3; + + if (((w - ana_sq_w) / 2) & 1) + ana_sq_w += 2; + tpg->square.width = ana_sq_w; + } + tpg->square.left = (w - tpg->square.width) / 2; + if (tpg->pix_aspect == TPG_PIXEL_ASPECT_NTSC) + sq_h = sq_w * 10 / 11; + else if (tpg->pix_aspect == TPG_PIXEL_ASPECT_PAL) + sq_h = sq_w * 59 / 54; + tpg->square.height = sq_h; + tpg->square.top = (h - sq_h) / 2; + tpg->border.left = 0; + tpg->border.width = w; + tpg->border.top = 0; + tpg->border.height = h; + switch (tpg->vid_aspect) { + case TPG_VIDEO_ASPECT_4X3: + if (tpg->pix_aspect) + return; + if (3 * w >= 4 * h) { + tpg->border.width = ((4 * h) / 3) & ~1; + if (((w - tpg->border.width) / 2) & ~1) + tpg->border.width -= 2; + tpg->border.left = (w - tpg->border.width) / 2; + break; + } + tpg->border.height = ((3 * w) / 4) & ~1; + tpg->border.top = (h - tpg->border.height) / 2; + break; + case TPG_VIDEO_ASPECT_14X9_CENTRE: + if (tpg->pix_aspect) { + tpg->border.height = tpg->pix_aspect == TPG_PIXEL_ASPECT_NTSC ? 420 : 506; + tpg->border.top = (h - tpg->border.height) / 2; + break; + } + if (9 * w >= 14 * h) { + tpg->border.width = ((14 * h) / 9) & ~1; + if (((w - tpg->border.width) / 2) & ~1) + tpg->border.width -= 2; + tpg->border.left = (w - tpg->border.width) / 2; + break; + } + tpg->border.height = ((9 * w) / 14) & ~1; + tpg->border.top = (h - tpg->border.height) / 2; + break; + case TPG_VIDEO_ASPECT_16X9_CENTRE: + if (tpg->pix_aspect) { + tpg->border.height = tpg->pix_aspect == TPG_PIXEL_ASPECT_NTSC ? 368 : 442; + tpg->border.top = (h - tpg->border.height) / 2; + break; + } + if (9 * w >= 16 * h) { + tpg->border.width = ((16 * h) / 9) & ~1; + if (((w - tpg->border.width) / 2) & ~1) + tpg->border.width -= 2; + tpg->border.left = (w - tpg->border.width) / 2; + break; + } + tpg->border.height = ((9 * w) / 16) & ~1; + tpg->border.top = (h - tpg->border.height) / 2; + break; + default: + break; + } +} + +static void tpg_precalculate_line(struct tpg_data *tpg) +{ + enum tpg_color contrast; + unsigned pat; + unsigned p; + unsigned x; + + switch (tpg->pattern) { + case TPG_PAT_GREEN: + contrast = TPG_COLOR_100_RED; + break; + case TPG_PAT_CSC_COLORBAR: + contrast = TPG_COLOR_CSC_GREEN; + break; + default: + contrast = TPG_COLOR_100_GREEN; + break; + } + + for (pat = 0; pat < tpg_get_pat_lines(tpg); pat++) { + /* Coarse scaling with Bresenham */ + unsigned int_part = tpg->src_width / tpg->scaled_width; + unsigned fract_part = tpg->src_width % tpg->scaled_width; + unsigned src_x = 0; + unsigned error = 0; + + for (x = 0; x < tpg->scaled_width * 2; x += 2) { + unsigned real_x = src_x; + enum tpg_color color1, color2; + u8 pix[TPG_MAX_PLANES][8]; + + real_x = tpg->hflip ? tpg->src_width * 2 - real_x - 2 : real_x; + color1 = tpg_get_color(tpg, pat, real_x); + + src_x += int_part; + error += fract_part; + if (error >= tpg->scaled_width) { + error -= tpg->scaled_width; + src_x++; + } + + real_x = src_x; + real_x = tpg->hflip ? tpg->src_width * 2 - real_x - 2 : real_x; + color2 = tpg_get_color(tpg, pat, real_x); + + src_x += int_part; + error += fract_part; + if (error >= tpg->scaled_width) { + error -= tpg->scaled_width; + src_x++; + } + + gen_twopix(tpg, pix, tpg->hflip ? color2 : color1, 0); + gen_twopix(tpg, pix, tpg->hflip ? color1 : color2, 1); + for (p = 0; p < tpg->planes; p++) { + unsigned twopixsize = tpg->twopixelsize[p]; + u8 *pos = tpg->lines[pat][p] + x * twopixsize / 2; + + memcpy(pos, pix[p], twopixsize); + } + } + } + for (x = 0; x < tpg->scaled_width; x += 2) { + u8 pix[TPG_MAX_PLANES][8]; + + gen_twopix(tpg, pix, contrast, 0); + gen_twopix(tpg, pix, contrast, 1); + for (p = 0; p < tpg->planes; p++) { + unsigned twopixsize = tpg->twopixelsize[p]; + u8 *pos = tpg->contrast_line[p] + x * twopixsize / 2; + + memcpy(pos, pix[p], twopixsize); + } + } + for (x = 0; x < tpg->scaled_width; x += 2) { + u8 pix[TPG_MAX_PLANES][8]; + + gen_twopix(tpg, pix, TPG_COLOR_100_BLACK, 0); + gen_twopix(tpg, pix, TPG_COLOR_100_BLACK, 1); + for (p = 0; p < tpg->planes; p++) { + unsigned twopixsize = tpg->twopixelsize[p]; + u8 *pos = tpg->black_line[p] + x * twopixsize / 2; + + memcpy(pos, pix[p], twopixsize); + } + } + for (x = 0; x < tpg->scaled_width * 2; x += 2) { + u8 pix[TPG_MAX_PLANES][8]; + + gen_twopix(tpg, pix, TPG_COLOR_RANDOM, 0); + gen_twopix(tpg, pix, TPG_COLOR_RANDOM, 1); + for (p = 0; p < tpg->planes; p++) { + unsigned twopixsize = tpg->twopixelsize[p]; + u8 *pos = tpg->random_line[p] + x * twopixsize / 2; + + memcpy(pos, pix[p], twopixsize); + } + } + gen_twopix(tpg, tpg->textbg, TPG_COLOR_TEXTBG, 0); + gen_twopix(tpg, tpg->textbg, TPG_COLOR_TEXTBG, 1); + gen_twopix(tpg, tpg->textfg, TPG_COLOR_TEXTFG, 0); + gen_twopix(tpg, tpg->textfg, TPG_COLOR_TEXTFG, 1); +} + +/* need this to do rgb24 rendering */ +typedef struct { u16 __; u8 _; } __packed x24; + +void tpg_gen_text(struct tpg_data *tpg, u8 *basep[TPG_MAX_PLANES][2], + int y, int x, char *text) +{ + int line; + unsigned step = V4L2_FIELD_HAS_T_OR_B(tpg->field) ? 2 : 1; + unsigned div = step; + unsigned first = 0; + unsigned len = strlen(text); + unsigned p; + + if (font8x16 == NULL || basep == NULL) + return; + + /* Checks if it is possible to show string */ + if (y + 16 >= tpg->compose.height || x + 8 >= tpg->compose.width) + return; + + if (len > (tpg->compose.width - x) / 8) + len = (tpg->compose.width - x) / 8; + if (tpg->vflip) + y = tpg->compose.height - y - 16; + if (tpg->hflip) + x = tpg->compose.width - x - 8; + y += tpg->compose.top; + x += tpg->compose.left; + if (tpg->field == V4L2_FIELD_BOTTOM) + first = 1; + else if (tpg->field == V4L2_FIELD_SEQ_TB || tpg->field == V4L2_FIELD_SEQ_BT) + div = 2; + + for (p = 0; p < tpg->planes; p++) { + /* Print stream time */ +#define PRINTSTR(PIXTYPE) do { \ + PIXTYPE fg; \ + PIXTYPE bg; \ + memcpy(&fg, tpg->textfg[p], sizeof(PIXTYPE)); \ + memcpy(&bg, tpg->textbg[p], sizeof(PIXTYPE)); \ + \ + for (line = first; line < 16; line += step) { \ + int l = tpg->vflip ? 15 - line : line; \ + PIXTYPE *pos = (PIXTYPE *)(basep[p][line & 1] + \ + ((y * step + l) / div) * tpg->bytesperline[p] + \ + x * sizeof(PIXTYPE)); \ + unsigned s; \ + \ + for (s = 0; s < len; s++) { \ + u8 chr = font8x16[text[s] * 16 + line]; \ + \ + if (tpg->hflip) { \ + pos[7] = (chr & (0x01 << 7) ? fg : bg); \ + pos[6] = (chr & (0x01 << 6) ? fg : bg); \ + pos[5] = (chr & (0x01 << 5) ? fg : bg); \ + pos[4] = (chr & (0x01 << 4) ? fg : bg); \ + pos[3] = (chr & (0x01 << 3) ? fg : bg); \ + pos[2] = (chr & (0x01 << 2) ? fg : bg); \ + pos[1] = (chr & (0x01 << 1) ? fg : bg); \ + pos[0] = (chr & (0x01 << 0) ? fg : bg); \ + } else { \ + pos[0] = (chr & (0x01 << 7) ? fg : bg); \ + pos[1] = (chr & (0x01 << 6) ? fg : bg); \ + pos[2] = (chr & (0x01 << 5) ? fg : bg); \ + pos[3] = (chr & (0x01 << 4) ? fg : bg); \ + pos[4] = (chr & (0x01 << 3) ? fg : bg); \ + pos[5] = (chr & (0x01 << 2) ? fg : bg); \ + pos[6] = (chr & (0x01 << 1) ? fg : bg); \ + pos[7] = (chr & (0x01 << 0) ? fg : bg); \ + } \ + \ + pos += tpg->hflip ? -8 : 8; \ + } \ + } \ +} while (0) + + switch (tpg->twopixelsize[p]) { + case 2: + PRINTSTR(u8); break; + case 4: + PRINTSTR(u16); break; + case 6: + PRINTSTR(x24); break; + case 8: + PRINTSTR(u32); break; + } + } +} + +void tpg_update_mv_step(struct tpg_data *tpg) +{ + int factor = tpg->mv_hor_mode > TPG_MOVE_NONE ? -1 : 1; + + if (tpg->hflip) + factor = -factor; + switch (tpg->mv_hor_mode) { + case TPG_MOVE_NEG_FAST: + case TPG_MOVE_POS_FAST: + tpg->mv_hor_step = ((tpg->src_width + 319) / 320) * 4; + break; + case TPG_MOVE_NEG: + case TPG_MOVE_POS: + tpg->mv_hor_step = ((tpg->src_width + 639) / 640) * 4; + break; + case TPG_MOVE_NEG_SLOW: + case TPG_MOVE_POS_SLOW: + tpg->mv_hor_step = 2; + break; + case TPG_MOVE_NONE: + tpg->mv_hor_step = 0; + break; + } + if (factor < 0) + tpg->mv_hor_step = tpg->src_width - tpg->mv_hor_step; + + factor = tpg->mv_vert_mode > TPG_MOVE_NONE ? -1 : 1; + switch (tpg->mv_vert_mode) { + case TPG_MOVE_NEG_FAST: + case TPG_MOVE_POS_FAST: + tpg->mv_vert_step = ((tpg->src_width + 319) / 320) * 4; + break; + case TPG_MOVE_NEG: + case TPG_MOVE_POS: + tpg->mv_vert_step = ((tpg->src_width + 639) / 640) * 4; + break; + case TPG_MOVE_NEG_SLOW: + case TPG_MOVE_POS_SLOW: + tpg->mv_vert_step = 1; + break; + case TPG_MOVE_NONE: + tpg->mv_vert_step = 0; + break; + } + if (factor < 0) + tpg->mv_vert_step = tpg->src_height - tpg->mv_vert_step; +} + +/* Map the line number relative to the crop rectangle to a frame line number */ +static unsigned tpg_calc_frameline(struct tpg_data *tpg, unsigned src_y, + unsigned field) +{ + switch (field) { + case V4L2_FIELD_TOP: + return tpg->crop.top + src_y * 2; + case V4L2_FIELD_BOTTOM: + return tpg->crop.top + src_y * 2 + 1; + default: + return src_y + tpg->crop.top; + } +} + +/* + * Map the line number relative to the compose rectangle to a destination + * buffer line number. + */ +static unsigned tpg_calc_buffer_line(struct tpg_data *tpg, unsigned y, + unsigned field) +{ + y += tpg->compose.top; + switch (field) { + case V4L2_FIELD_SEQ_TB: + if (y & 1) + return tpg->buf_height / 2 + y / 2; + return y / 2; + case V4L2_FIELD_SEQ_BT: + if (y & 1) + return y / 2; + return tpg->buf_height / 2 + y / 2; + default: + return y; + } +} + +static void tpg_recalc(struct tpg_data *tpg) +{ + if (tpg->recalc_colors) { + tpg->recalc_colors = false; + tpg->recalc_lines = true; + tpg_precalculate_colors(tpg); + } + if (tpg->recalc_square_border) { + tpg->recalc_square_border = false; + tpg_calculate_square_border(tpg); + } + if (tpg->recalc_lines) { + tpg->recalc_lines = false; + tpg_precalculate_line(tpg); + } +} + +void tpg_calc_text_basep(struct tpg_data *tpg, + u8 *basep[TPG_MAX_PLANES][2], unsigned p, u8 *vbuf) +{ + unsigned stride = tpg->bytesperline[p]; + + tpg_recalc(tpg); + + basep[p][0] = vbuf; + basep[p][1] = vbuf; + if (tpg->field == V4L2_FIELD_SEQ_TB) + basep[p][1] += tpg->buf_height * stride / 2; + else if (tpg->field == V4L2_FIELD_SEQ_BT) + basep[p][0] += tpg->buf_height * stride / 2; +} + +void tpg_fillbuffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8 *vbuf) +{ + bool is_tv = std; + bool is_60hz = is_tv && (std & V4L2_STD_525_60); + unsigned mv_hor_old = tpg->mv_hor_count % tpg->src_width; + unsigned mv_hor_new = (tpg->mv_hor_count + tpg->mv_hor_step) % tpg->src_width; + unsigned mv_vert_old = tpg->mv_vert_count % tpg->src_height; + unsigned mv_vert_new = (tpg->mv_vert_count + tpg->mv_vert_step) % tpg->src_height; + unsigned wss_width; + unsigned f; + int hmax = (tpg->compose.height * tpg->perc_fill) / 100; + int h; + unsigned twopixsize = tpg->twopixelsize[p]; + unsigned img_width = tpg->compose.width * twopixsize / 2; + unsigned line_offset; + unsigned left_pillar_width = 0; + unsigned right_pillar_start = img_width; + unsigned stride = tpg->bytesperline[p]; + unsigned factor = V4L2_FIELD_HAS_T_OR_B(tpg->field) ? 2 : 1; + u8 *orig_vbuf = vbuf; + + /* Coarse scaling with Bresenham */ + unsigned int_part = (tpg->crop.height / factor) / tpg->compose.height; + unsigned fract_part = (tpg->crop.height / factor) % tpg->compose.height; + unsigned src_y = 0; + unsigned error = 0; + + tpg_recalc(tpg); + + mv_hor_old = (mv_hor_old * tpg->scaled_width / tpg->src_width) & ~1; + mv_hor_new = (mv_hor_new * tpg->scaled_width / tpg->src_width) & ~1; + wss_width = tpg->crop.left < tpg->src_width / 2 ? + tpg->src_width / 2 - tpg->crop.left : 0; + if (wss_width > tpg->crop.width) + wss_width = tpg->crop.width; + wss_width = wss_width * tpg->scaled_width / tpg->src_width; + + vbuf += tpg->compose.left * twopixsize / 2; + line_offset = tpg->crop.left * tpg->scaled_width / tpg->src_width; + line_offset = (line_offset & ~1) * twopixsize / 2; + if (tpg->crop.left < tpg->border.left) { + left_pillar_width = tpg->border.left - tpg->crop.left; + if (left_pillar_width > tpg->crop.width) + left_pillar_width = tpg->crop.width; + left_pillar_width = (left_pillar_width * tpg->scaled_width) / tpg->src_width; + left_pillar_width = (left_pillar_width & ~1) * twopixsize / 2; + } + if (tpg->crop.left + tpg->crop.width > tpg->border.left + tpg->border.width) { + right_pillar_start = tpg->border.left + tpg->border.width - tpg->crop.left; + right_pillar_start = (right_pillar_start * tpg->scaled_width) / tpg->src_width; + right_pillar_start = (right_pillar_start & ~1) * twopixsize / 2; + if (right_pillar_start > img_width) + right_pillar_start = img_width; + } + + f = tpg->field == (is_60hz ? V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM); + + for (h = 0; h < tpg->compose.height; h++) { + bool even; + bool fill_blank = false; + unsigned frame_line; + unsigned buf_line; + unsigned pat_line_old; + unsigned pat_line_new; + u8 *linestart_older; + u8 *linestart_newer; + u8 *linestart_top; + u8 *linestart_bottom; + + frame_line = tpg_calc_frameline(tpg, src_y, tpg->field); + even = !(frame_line & 1); + buf_line = tpg_calc_buffer_line(tpg, h, tpg->field); + src_y += int_part; + error += fract_part; + if (error >= tpg->compose.height) { + error -= tpg->compose.height; + src_y++; + } + + if (h >= hmax) { + if (hmax == tpg->compose.height) + continue; + if (!tpg->perc_fill_blank) + continue; + fill_blank = true; + } + + if (tpg->vflip) + frame_line = tpg->src_height - frame_line - 1; + + if (fill_blank) { + linestart_older = tpg->contrast_line[p]; + linestart_newer = tpg->contrast_line[p]; + } else if (tpg->qual != TPG_QUAL_NOISE && + (frame_line < tpg->border.top || + frame_line >= tpg->border.top + tpg->border.height)) { + linestart_older = tpg->black_line[p]; + linestart_newer = tpg->black_line[p]; + } else if (tpg->pattern == TPG_PAT_NOISE || tpg->qual == TPG_QUAL_NOISE) { + linestart_older = tpg->random_line[p] + + twopixsize * prandom_u32_max(tpg->src_width / 2); + linestart_newer = tpg->random_line[p] + + twopixsize * prandom_u32_max(tpg->src_width / 2); + } else { + pat_line_old = tpg_get_pat_line(tpg, + (frame_line + mv_vert_old) % tpg->src_height); + pat_line_new = tpg_get_pat_line(tpg, + (frame_line + mv_vert_new) % tpg->src_height); + linestart_older = tpg->lines[pat_line_old][p] + + mv_hor_old * twopixsize / 2; + linestart_newer = tpg->lines[pat_line_new][p] + + mv_hor_new * twopixsize / 2; + linestart_older += line_offset; + linestart_newer += line_offset; + } + if (is_60hz) { + linestart_top = linestart_newer; + linestart_bottom = linestart_older; + } else { + linestart_top = linestart_older; + linestart_bottom = linestart_newer; + } + + switch (tpg->field) { + case V4L2_FIELD_INTERLACED: + case V4L2_FIELD_INTERLACED_TB: + case V4L2_FIELD_SEQ_TB: + case V4L2_FIELD_SEQ_BT: + if (even) + memcpy(vbuf + buf_line * stride, linestart_top, img_width); + else + memcpy(vbuf + buf_line * stride, linestart_bottom, img_width); + break; + case V4L2_FIELD_INTERLACED_BT: + if (even) + memcpy(vbuf + buf_line * stride, linestart_bottom, img_width); + else + memcpy(vbuf + buf_line * stride, linestart_top, img_width); + break; + case V4L2_FIELD_TOP: + memcpy(vbuf + buf_line * stride, linestart_top, img_width); + break; + case V4L2_FIELD_BOTTOM: + memcpy(vbuf + buf_line * stride, linestart_bottom, img_width); + break; + case V4L2_FIELD_NONE: + default: + memcpy(vbuf + buf_line * stride, linestart_older, img_width); + break; + } + + if (is_tv && !is_60hz && frame_line == 0 && wss_width) { + /* + * Replace the first half of the top line of a 50 Hz frame + * with random data to simulate a WSS signal. + */ + u8 *wss = tpg->random_line[p] + + twopixsize * prandom_u32_max(tpg->src_width / 2); + + memcpy(vbuf + buf_line * stride, wss, wss_width * twopixsize / 2); + } + } + + vbuf = orig_vbuf; + vbuf += tpg->compose.left * twopixsize / 2; + src_y = 0; + error = 0; + for (h = 0; h < tpg->compose.height; h++) { + unsigned frame_line = tpg_calc_frameline(tpg, src_y, tpg->field); + unsigned buf_line = tpg_calc_buffer_line(tpg, h, tpg->field); + const struct v4l2_rect *sq = &tpg->square; + const struct v4l2_rect *b = &tpg->border; + const struct v4l2_rect *c = &tpg->crop; + + src_y += int_part; + error += fract_part; + if (error >= tpg->compose.height) { + error -= tpg->compose.height; + src_y++; + } + + if (tpg->show_border && frame_line >= b->top && + frame_line < b->top + b->height) { + unsigned bottom = b->top + b->height - 1; + unsigned left = left_pillar_width; + unsigned right = right_pillar_start; + + if (frame_line == b->top || frame_line == b->top + 1 || + frame_line == bottom || frame_line == bottom - 1) { + memcpy(vbuf + buf_line * stride + left, tpg->contrast_line[p], + right - left); + } else { + if (b->left >= c->left && + b->left < c->left + c->width) + memcpy(vbuf + buf_line * stride + left, + tpg->contrast_line[p], twopixsize); + if (b->left + b->width > c->left && + b->left + b->width <= c->left + c->width) + memcpy(vbuf + buf_line * stride + right - twopixsize, + tpg->contrast_line[p], twopixsize); + } + } + if (tpg->qual != TPG_QUAL_NOISE && frame_line >= b->top && + frame_line < b->top + b->height) { + memcpy(vbuf + buf_line * stride, tpg->black_line[p], left_pillar_width); + memcpy(vbuf + buf_line * stride + right_pillar_start, tpg->black_line[p], + img_width - right_pillar_start); + } + if (tpg->show_square && frame_line >= sq->top && + frame_line < sq->top + sq->height && + sq->left < c->left + c->width && + sq->left + sq->width >= c->left) { + unsigned left = sq->left; + unsigned width = sq->width; + + if (c->left > left) { + width -= c->left - left; + left = c->left; + } + if (c->left + c->width < left + width) + width -= left + width - c->left - c->width; + left -= c->left; + left = (left * tpg->scaled_width) / tpg->src_width; + left = (left & ~1) * twopixsize / 2; + width = (width * tpg->scaled_width) / tpg->src_width; + width = (width & ~1) * twopixsize / 2; + memcpy(vbuf + buf_line * stride + left, tpg->contrast_line[p], width); + } + if (tpg->insert_sav) { + unsigned offset = (tpg->compose.width / 6) * twopixsize; + u8 *p = vbuf + buf_line * stride + offset; + unsigned vact = 0, hact = 0; + + p[0] = 0xff; + p[1] = 0; + p[2] = 0; + p[3] = 0x80 | (f << 6) | (vact << 5) | (hact << 4) | + ((hact ^ vact) << 3) | + ((hact ^ f) << 2) | + ((f ^ vact) << 1) | + (hact ^ vact ^ f); + } + if (tpg->insert_eav) { + unsigned offset = (tpg->compose.width / 6) * 2 * twopixsize; + u8 *p = vbuf + buf_line * stride + offset; + unsigned vact = 0, hact = 1; + + p[0] = 0xff; + p[1] = 0; + p[2] = 0; + p[3] = 0x80 | (f << 6) | (vact << 5) | (hact << 4) | + ((hact ^ vact) << 3) | + ((hact ^ f) << 2) | + ((f ^ vact) << 1) | + (hact ^ vact ^ f); + } + } +} diff -Nru v4l-utils-1.0.0+r2263/utils/v4l2-ctl/vivid-tpg-colors.c v4l-utils-1.0.0+r2364/utils/v4l2-ctl/vivid-tpg-colors.c --- v4l-utils-1.0.0+r2263/utils/v4l2-ctl/vivid-tpg-colors.c 1970-01-01 00:00:00.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/v4l2-ctl/vivid-tpg-colors.c 2014-08-12 09:02:18.000000000 +0000 @@ -0,0 +1,310 @@ +/* + * vivid-color.c - A table that converts colors to various colorspaces + * + * The test pattern generator uses the tpg_colors for its test patterns. + * For testing colorspaces the first 8 colors of that table need to be + * converted to their equivalent in the target colorspace. + * + * The tpg_csc_colors[] table is the result of that conversion and since + * it is precalculated the colorspace conversion is just a simple table + * lookup. + * + * This source also contains the code used to generate the tpg_csc_colors + * table. Run the following command to compile it: + * + * gcc vivid-colors.c -DCOMPILE_APP -o gen-colors -lm + * + * and run the utility. + * + * Note that the converted colors are in the range 0x000-0xff0 (so times 16) + * in order to preserve precision. + * + * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include + +#include "vivid-tpg-colors.h" + +/* sRGB colors with range [0-255] */ +const struct color tpg_colors[TPG_COLOR_MAX] = { + /* + * Colors to test colorspace conversion: converting these colors + * to other colorspaces will never lead to out-of-gamut colors. + */ + { 191, 191, 191 }, /* TPG_COLOR_CSC_WHITE */ + { 191, 191, 50 }, /* TPG_COLOR_CSC_YELLOW */ + { 50, 191, 191 }, /* TPG_COLOR_CSC_CYAN */ + { 50, 191, 50 }, /* TPG_COLOR_CSC_GREEN */ + { 191, 50, 191 }, /* TPG_COLOR_CSC_MAGENTA */ + { 191, 50, 50 }, /* TPG_COLOR_CSC_RED */ + { 50, 50, 191 }, /* TPG_COLOR_CSC_BLUE */ + { 50, 50, 50 }, /* TPG_COLOR_CSC_BLACK */ + + /* 75% colors */ + { 191, 191, 0 }, /* TPG_COLOR_75_YELLOW */ + { 0, 191, 191 }, /* TPG_COLOR_75_CYAN */ + { 0, 191, 0 }, /* TPG_COLOR_75_GREEN */ + { 191, 0, 191 }, /* TPG_COLOR_75_MAGENTA */ + { 191, 0, 0 }, /* TPG_COLOR_75_RED */ + { 0, 0, 191 }, /* TPG_COLOR_75_BLUE */ + + /* 100% colors */ + { 255, 255, 255 }, /* TPG_COLOR_100_WHITE */ + { 255, 255, 0 }, /* TPG_COLOR_100_YELLOW */ + { 0, 255, 255 }, /* TPG_COLOR_100_CYAN */ + { 0, 255, 0 }, /* TPG_COLOR_100_GREEN */ + { 255, 0, 255 }, /* TPG_COLOR_100_MAGENTA */ + { 255, 0, 0 }, /* TPG_COLOR_100_RED */ + { 0, 0, 255 }, /* TPG_COLOR_100_BLUE */ + { 0, 0, 0 }, /* TPG_COLOR_100_BLACK */ + + { 0, 0, 0 }, /* TPG_COLOR_RANDOM placeholder */ +}; + +#ifndef COMPILE_APP + +/* Generated table */ +const struct color16 tpg_csc_colors[V4L2_COLORSPACE_SRGB + 1][TPG_COLOR_CSC_BLACK + 1] = { + [V4L2_COLORSPACE_SMPTE170M][0] = { 2953, 2939, 2939 }, + [V4L2_COLORSPACE_SMPTE170M][1] = { 2954, 2963, 585 }, + [V4L2_COLORSPACE_SMPTE170M][2] = { 84, 2967, 2937 }, + [V4L2_COLORSPACE_SMPTE170M][3] = { 93, 2990, 575 }, + [V4L2_COLORSPACE_SMPTE170M][4] = { 3030, 259, 2933 }, + [V4L2_COLORSPACE_SMPTE170M][5] = { 3031, 406, 557 }, + [V4L2_COLORSPACE_SMPTE170M][6] = { 544, 428, 2931 }, + [V4L2_COLORSPACE_SMPTE170M][7] = { 551, 547, 547 }, + [V4L2_COLORSPACE_SMPTE240M][0] = { 2926, 2926, 2926 }, + [V4L2_COLORSPACE_SMPTE240M][1] = { 2926, 2926, 857 }, + [V4L2_COLORSPACE_SMPTE240M][2] = { 1594, 2901, 2901 }, + [V4L2_COLORSPACE_SMPTE240M][3] = { 1594, 2901, 774 }, + [V4L2_COLORSPACE_SMPTE240M][4] = { 2484, 618, 2858 }, + [V4L2_COLORSPACE_SMPTE240M][5] = { 2484, 618, 617 }, + [V4L2_COLORSPACE_SMPTE240M][6] = { 507, 507, 2832 }, + [V4L2_COLORSPACE_SMPTE240M][7] = { 507, 507, 507 }, + [V4L2_COLORSPACE_REC709][0] = { 2939, 2939, 2939 }, + [V4L2_COLORSPACE_REC709][1] = { 2939, 2939, 547 }, + [V4L2_COLORSPACE_REC709][2] = { 547, 2939, 2939 }, + [V4L2_COLORSPACE_REC709][3] = { 547, 2939, 547 }, + [V4L2_COLORSPACE_REC709][4] = { 2939, 547, 2939 }, + [V4L2_COLORSPACE_REC709][5] = { 2939, 547, 547 }, + [V4L2_COLORSPACE_REC709][6] = { 547, 547, 2939 }, + [V4L2_COLORSPACE_REC709][7] = { 547, 547, 547 }, + [V4L2_COLORSPACE_470_SYSTEM_M][0] = { 2894, 2988, 2808 }, + [V4L2_COLORSPACE_470_SYSTEM_M][1] = { 2847, 3070, 843 }, + [V4L2_COLORSPACE_470_SYSTEM_M][2] = { 1656, 2962, 2783 }, + [V4L2_COLORSPACE_470_SYSTEM_M][3] = { 1572, 3045, 763 }, + [V4L2_COLORSPACE_470_SYSTEM_M][4] = { 2477, 229, 2743 }, + [V4L2_COLORSPACE_470_SYSTEM_M][5] = { 2422, 672, 614 }, + [V4L2_COLORSPACE_470_SYSTEM_M][6] = { 725, 63, 2718 }, + [V4L2_COLORSPACE_470_SYSTEM_M][7] = { 534, 561, 509 }, + [V4L2_COLORSPACE_470_SYSTEM_BG][0] = { 2939, 2939, 2939 }, + [V4L2_COLORSPACE_470_SYSTEM_BG][1] = { 2939, 2939, 621 }, + [V4L2_COLORSPACE_470_SYSTEM_BG][2] = { 786, 2939, 2939 }, + [V4L2_COLORSPACE_470_SYSTEM_BG][3] = { 786, 2939, 621 }, + [V4L2_COLORSPACE_470_SYSTEM_BG][4] = { 2879, 547, 2923 }, + [V4L2_COLORSPACE_470_SYSTEM_BG][5] = { 2879, 547, 547 }, + [V4L2_COLORSPACE_470_SYSTEM_BG][6] = { 547, 547, 2923 }, + [V4L2_COLORSPACE_470_SYSTEM_BG][7] = { 547, 547, 547 }, + [V4L2_COLORSPACE_SRGB][0] = { 3056, 3056, 3056 }, + [V4L2_COLORSPACE_SRGB][1] = { 3056, 3056, 800 }, + [V4L2_COLORSPACE_SRGB][2] = { 800, 3056, 3056 }, + [V4L2_COLORSPACE_SRGB][3] = { 800, 3056, 800 }, + [V4L2_COLORSPACE_SRGB][4] = { 3056, 800, 3056 }, + [V4L2_COLORSPACE_SRGB][5] = { 3056, 800, 800 }, + [V4L2_COLORSPACE_SRGB][6] = { 800, 800, 3056 }, + [V4L2_COLORSPACE_SRGB][7] = { 800, 800, 800 }, +}; + +#else + +/* This code generates the table above */ + +#include +#include +#include + +static const double rec709_to_ntsc1953[3][3] = { + { 0.6698, 0.2678, 0.0323 }, + { 0.0185, 1.0742, -0.0603 }, + { 0.0162, 0.0432, 0.8551 } +}; + +static const double rec709_to_ebu[3][3] = { + { 0.9578, 0.0422, 0 }, + { 0 , 1 , 0 }, + { 0 , 0.0118, 0.9882 } +}; + +static const double rec709_to_170m[3][3] = { + { 1.0654, -0.0554, -0.0010 }, + { -0.0196, 1.0364, -0.0167 }, + { 0.0016, 0.0044, 0.9940 } +}; + +static const double rec709_to_240m[3][3] = { + { 0.7151, 0.2849, 0 }, + { 0.0179, 0.9821, 0 }, + { 0.0177, 0.0472, 0.9350 } +}; + + +static void mult_matrix(double *r, double *g, double *b, const double m[3][3]) +{ + double ir, ig, ib; + + ir = m[0][0] * (*r) + m[0][1] * (*g) + m[0][2] * (*b); + ig = m[1][0] * (*r) + m[1][1] * (*g) + m[1][2] * (*b); + ib = m[2][0] * (*r) + m[2][1] * (*g) + m[2][2] * (*b); + *r = ir; + *g = ig; + *b = ib; +} + +static double transfer_srgb_to_rgb(double v) +{ + return (v <= 0.03928) ? v / 12.92 : pow((v + 0.055) / 1.055, 2.4); +} + +static double transfer_rgb_to_smpte240m(double v) +{ + return (v <= 0.0228) ? v * 4.0 : 1.1115 * pow(v, 0.45) - 0.1115; +} + +static double transfer_rgb_to_rec709(double v) +{ + return (v < 0.018) ? v * 4.5 : 1.099 * pow(v, 0.45) - 0.099; +} + +static double transfer_srgb_to_rec709(double v) +{ + return transfer_rgb_to_rec709(transfer_srgb_to_rgb(v)); +} + +static void csc(enum v4l2_colorspace colorspace, double *r, double *g, double *b) +{ + /* Convert the primaries of Rec. 709 Linear RGB */ + switch (colorspace) { + case V4L2_COLORSPACE_SMPTE240M: + *r = transfer_srgb_to_rgb(*r); + *g = transfer_srgb_to_rgb(*g); + *b = transfer_srgb_to_rgb(*b); + mult_matrix(r, g, b, rec709_to_240m); + break; + case V4L2_COLORSPACE_SMPTE170M: + *r = transfer_srgb_to_rgb(*r); + *g = transfer_srgb_to_rgb(*g); + *b = transfer_srgb_to_rgb(*b); + mult_matrix(r, g, b, rec709_to_170m); + break; + case V4L2_COLORSPACE_470_SYSTEM_BG: + *r = transfer_srgb_to_rgb(*r); + *g = transfer_srgb_to_rgb(*g); + *b = transfer_srgb_to_rgb(*b); + mult_matrix(r, g, b, rec709_to_ebu); + break; + case V4L2_COLORSPACE_470_SYSTEM_M: + *r = transfer_srgb_to_rgb(*r); + *g = transfer_srgb_to_rgb(*g); + *b = transfer_srgb_to_rgb(*b); + mult_matrix(r, g, b, rec709_to_ntsc1953); + break; + case V4L2_COLORSPACE_SRGB: + case V4L2_COLORSPACE_REC709: + default: + break; + } + + *r = ((*r) < 0) ? 0 : (((*r) > 1) ? 1 : (*r)); + *g = ((*g) < 0) ? 0 : (((*g) > 1) ? 1 : (*g)); + *b = ((*b) < 0) ? 0 : (((*b) > 1) ? 1 : (*b)); + + /* Encode to gamma corrected colorspace */ + switch (colorspace) { + case V4L2_COLORSPACE_SMPTE240M: + *r = transfer_rgb_to_smpte240m(*r); + *g = transfer_rgb_to_smpte240m(*g); + *b = transfer_rgb_to_smpte240m(*b); + break; + case V4L2_COLORSPACE_SMPTE170M: + case V4L2_COLORSPACE_470_SYSTEM_M: + case V4L2_COLORSPACE_470_SYSTEM_BG: + *r = transfer_rgb_to_rec709(*r); + *g = transfer_rgb_to_rec709(*g); + *b = transfer_rgb_to_rec709(*b); + break; + case V4L2_COLORSPACE_SRGB: + break; + case V4L2_COLORSPACE_REC709: + default: + *r = transfer_srgb_to_rec709(*r); + *g = transfer_srgb_to_rec709(*g); + *b = transfer_srgb_to_rec709(*b); + break; + } +} + +int main(int argc, char **argv) +{ + static const unsigned colorspaces[] = { + 0, + V4L2_COLORSPACE_SMPTE170M, + V4L2_COLORSPACE_SMPTE240M, + V4L2_COLORSPACE_REC709, + 0, + V4L2_COLORSPACE_470_SYSTEM_M, + V4L2_COLORSPACE_470_SYSTEM_BG, + 0, + V4L2_COLORSPACE_SRGB, + }; + static const char * const colorspace_names[] = { + "", + "V4L2_COLORSPACE_SMPTE170M", + "V4L2_COLORSPACE_SMPTE240M", + "V4L2_COLORSPACE_REC709", + "", + "V4L2_COLORSPACE_470_SYSTEM_M", + "V4L2_COLORSPACE_470_SYSTEM_BG", + "", + "V4L2_COLORSPACE_SRGB", + }; + int i; + int c; + + printf("/* Generated table */\n"); + printf("const struct color16 tpg_csc_colors[V4L2_COLORSPACE_SRGB + 1][TPG_COLOR_CSC_BLACK + 1] = {\n"); + for (c = 0; c <= V4L2_COLORSPACE_SRGB; c++) { + for (i = 0; i <= TPG_COLOR_CSC_BLACK; i++) { + double r, g, b; + + if (colorspaces[c] == 0) + continue; + + r = tpg_colors[i].r / 255.0; + g = tpg_colors[i].g / 255.0; + b = tpg_colors[i].b / 255.0; + + csc(c, &r, &g, &b); + + printf("\t[%s][%d] = { %d, %d, %d },\n", colorspace_names[c], i, + (int)(r * 4080), (int)(g * 4080), (int)(b * 4080)); + } + } + printf("};\n\n"); + return 0; +} + +#endif diff -Nru v4l-utils-1.0.0+r2263/utils/v4l2-ctl/vivid-tpg-colors.h v4l-utils-1.0.0+r2364/utils/v4l2-ctl/vivid-tpg-colors.h --- v4l-utils-1.0.0+r2263/utils/v4l2-ctl/vivid-tpg-colors.h 1970-01-01 00:00:00.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/v4l2-ctl/vivid-tpg-colors.h 2014-08-12 09:02:18.000000000 +0000 @@ -0,0 +1,64 @@ +/* + * vivid-color.h - Color definitions for the test pattern generator + * + * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef _VIVID_COLORS_H_ +#define _VIVID_COLORS_H_ + +struct color { + unsigned char r, g, b; +}; + +struct color16 { + int r, g, b; +}; + +enum tpg_color { + TPG_COLOR_CSC_WHITE, + TPG_COLOR_CSC_YELLOW, + TPG_COLOR_CSC_CYAN, + TPG_COLOR_CSC_GREEN, + TPG_COLOR_CSC_MAGENTA, + TPG_COLOR_CSC_RED, + TPG_COLOR_CSC_BLUE, + TPG_COLOR_CSC_BLACK, + TPG_COLOR_75_YELLOW, + TPG_COLOR_75_CYAN, + TPG_COLOR_75_GREEN, + TPG_COLOR_75_MAGENTA, + TPG_COLOR_75_RED, + TPG_COLOR_75_BLUE, + TPG_COLOR_100_WHITE, + TPG_COLOR_100_YELLOW, + TPG_COLOR_100_CYAN, + TPG_COLOR_100_GREEN, + TPG_COLOR_100_MAGENTA, + TPG_COLOR_100_RED, + TPG_COLOR_100_BLUE, + TPG_COLOR_100_BLACK, + TPG_COLOR_TEXTFG, + TPG_COLOR_TEXTBG, + TPG_COLOR_RANDOM, + TPG_COLOR_RAMP, + TPG_COLOR_MAX = TPG_COLOR_RAMP + 256 +}; + +extern const struct color tpg_colors[TPG_COLOR_MAX]; +extern const struct color16 tpg_csc_colors[V4L2_COLORSPACE_SRGB + 1][TPG_COLOR_CSC_BLACK + 1]; + +#endif diff -Nru v4l-utils-1.0.0+r2263/utils/v4l2-ctl/vivid-tpg.h v4l-utils-1.0.0+r2364/utils/v4l2-ctl/vivid-tpg.h --- v4l-utils-1.0.0+r2263/utils/v4l2-ctl/vivid-tpg.h 1970-01-01 00:00:00.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/v4l2-ctl/vivid-tpg.h 2014-08-12 09:02:18.000000000 +0000 @@ -0,0 +1,471 @@ +/* + * vivid-tpg.h - Test Pattern Generator + * + * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef _VIVID_TPG_H_ +#define _VIVID_TPG_H_ + +#include +#include + +#include +#include +#include +#include + +typedef __u32 u32; +typedef __u16 u16; +typedef __s16 s16; +typedef __u8 u8; +typedef __s8 s8; + +#define __packed __attribute__((packed)) + +static inline void vfree(void *p) +{ + free(p); +} + +static inline void *vzalloc(unsigned long size) +{ + return calloc(1, size); +} + +#define clamp(val, min, max) ({ \ + typeof(val) __val = (val); \ + typeof(min) __min = (min); \ + typeof(max) __max = (max); \ + (void) (&__val == &__min); \ + (void) (&__val == &__max); \ + __val = __val < __min ? __min: __val; \ + __val > __max ? __max: __val; }) + +#include "vivid-tpg-colors.h" + +enum tpg_pattern { + TPG_PAT_75_COLORBAR, + TPG_PAT_100_COLORBAR, + TPG_PAT_CSC_COLORBAR, + TPG_PAT_100_HCOLORBAR, + TPG_PAT_100_COLORSQUARES, + TPG_PAT_BLACK, + TPG_PAT_WHITE, + TPG_PAT_RED, + TPG_PAT_GREEN, + TPG_PAT_BLUE, + TPG_PAT_CHECKERS_16X16, + TPG_PAT_CHECKERS_1X1, + TPG_PAT_ALTERNATING_HLINES, + TPG_PAT_ALTERNATING_VLINES, + TPG_PAT_CROSS_1_PIXEL, + TPG_PAT_CROSS_2_PIXELS, + TPG_PAT_CROSS_10_PIXELS, + TPG_PAT_GRAY_RAMP, + + /* Must be the last pattern */ + TPG_PAT_NOISE, +}; + +extern const char * const tpg_pattern_strings[]; + +enum tpg_quality { + TPG_QUAL_COLOR, + TPG_QUAL_GRAY, + TPG_QUAL_NOISE +}; + +enum tpg_video_aspect { + TPG_VIDEO_ASPECT_IMAGE, + TPG_VIDEO_ASPECT_4X3, + TPG_VIDEO_ASPECT_14X9_CENTRE, + TPG_VIDEO_ASPECT_16X9_CENTRE, + TPG_VIDEO_ASPECT_16X9_ANAMORPHIC, +}; + +enum tpg_pixel_aspect { + TPG_PIXEL_ASPECT_SQUARE, + TPG_PIXEL_ASPECT_NTSC, + TPG_PIXEL_ASPECT_PAL, +}; + +enum tpg_move_mode { + TPG_MOVE_NEG_FAST, + TPG_MOVE_NEG, + TPG_MOVE_NEG_SLOW, + TPG_MOVE_NONE, + TPG_MOVE_POS_SLOW, + TPG_MOVE_POS, + TPG_MOVE_POS_FAST, +}; + +extern const char * const tpg_aspect_strings[]; + +#define TPG_MAX_PLANES 2 +#define TPG_MAX_PAT_LINES 8 + +struct tpg_data { + /* Source frame size */ + unsigned src_width, src_height; + /* Buffer height */ + unsigned buf_height; + /* Scaled output frame size */ + unsigned scaled_width; + u32 field; + /* crop coordinates are frame-based */ + struct v4l2_rect crop; + /* compose coordinates are format-based */ + struct v4l2_rect compose; + /* border and square coordinates are frame-based */ + struct v4l2_rect border; + struct v4l2_rect square; + + /* Color-related fields */ + enum tpg_quality qual; + unsigned qual_offset; + u8 alpha_component; + bool alpha_red_only; + u8 brightness; + u8 contrast; + u8 saturation; + s16 hue; + u32 fourcc; + bool is_yuv; + u32 colorspace; + enum tpg_video_aspect vid_aspect; + enum tpg_pixel_aspect pix_aspect; + unsigned rgb_range; + unsigned real_rgb_range; + unsigned planes; + /* Used to store the colors in native format, either RGB or YUV */ + u8 colors[TPG_COLOR_MAX][3]; + u8 textfg[TPG_MAX_PLANES][8], textbg[TPG_MAX_PLANES][8]; + /* size in bytes for two pixels in each plane */ + unsigned twopixelsize[TPG_MAX_PLANES]; + unsigned bytesperline[TPG_MAX_PLANES]; + + /* Configuration */ + enum tpg_pattern pattern; + bool hflip; + bool vflip; + unsigned perc_fill; + bool perc_fill_blank; + bool show_border; + bool show_square; + bool insert_sav; + bool insert_eav; + + /* Test pattern movement */ + enum tpg_move_mode mv_hor_mode; + int mv_hor_count; + int mv_hor_step; + enum tpg_move_mode mv_vert_mode; + int mv_vert_count; + int mv_vert_step; + + bool recalc_colors; + bool recalc_lines; + bool recalc_square_border; + + /* Used to store TPG_MAX_PAT_LINES lines, each with up to two planes */ + unsigned max_line_width; + u8 *lines[TPG_MAX_PAT_LINES][TPG_MAX_PLANES]; + u8 *random_line[TPG_MAX_PLANES]; + u8 *contrast_line[TPG_MAX_PLANES]; + u8 *black_line[TPG_MAX_PLANES]; +}; + +void tpg_init(struct tpg_data *tpg, unsigned w, unsigned h); +int tpg_alloc(struct tpg_data *tpg, unsigned max_w); +void tpg_free(struct tpg_data *tpg); +void tpg_reset_source(struct tpg_data *tpg, unsigned width, unsigned height, + u32 field); + +void tpg_set_font(const u8 *f); +void tpg_gen_text(struct tpg_data *tpg, + u8 *basep[TPG_MAX_PLANES][2], int y, int x, char *text); +void tpg_calc_text_basep(struct tpg_data *tpg, + u8 *basep[TPG_MAX_PLANES][2], unsigned p, u8 *vbuf); +void tpg_fillbuffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8 *vbuf); +bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc); +void tpg_s_crop_compose(struct tpg_data *tpg, const struct v4l2_rect *crop, + const struct v4l2_rect *compose); + +static inline void tpg_s_pattern(struct tpg_data *tpg, enum tpg_pattern pattern) +{ + if (tpg->pattern == pattern) + return; + tpg->pattern = pattern; + tpg->recalc_colors = true; +} + +static inline void tpg_s_quality(struct tpg_data *tpg, + enum tpg_quality qual, unsigned qual_offset) +{ + if (tpg->qual == qual && tpg->qual_offset == qual_offset) + return; + tpg->qual = qual; + tpg->qual_offset = qual_offset; + tpg->recalc_colors = true; +} + +static inline enum tpg_quality tpg_g_quality(const struct tpg_data *tpg) +{ + return tpg->qual; +} + +static inline void tpg_s_alpha_component(struct tpg_data *tpg, + u8 alpha_component) +{ + if (tpg->alpha_component == alpha_component) + return; + tpg->alpha_component = alpha_component; + tpg->recalc_colors = true; +} + +static inline void tpg_s_alpha_mode(struct tpg_data *tpg, + bool red_only) +{ + if (tpg->alpha_red_only == red_only) + return; + tpg->alpha_red_only = red_only; + tpg->recalc_colors = true; +} + +static inline void tpg_s_brightness(struct tpg_data *tpg, + u8 brightness) +{ + if (tpg->brightness == brightness) + return; + tpg->brightness = brightness; + tpg->recalc_colors = true; +} + +static inline void tpg_s_contrast(struct tpg_data *tpg, + u8 contrast) +{ + if (tpg->contrast == contrast) + return; + tpg->contrast = contrast; + tpg->recalc_colors = true; +} + +static inline void tpg_s_saturation(struct tpg_data *tpg, + u8 saturation) +{ + if (tpg->saturation == saturation) + return; + tpg->saturation = saturation; + tpg->recalc_colors = true; +} + +static inline void tpg_s_hue(struct tpg_data *tpg, + s16 hue) +{ + if (tpg->hue == hue) + return; + tpg->hue = hue; + tpg->recalc_colors = true; +} + +static inline void tpg_s_rgb_range(struct tpg_data *tpg, + unsigned rgb_range) +{ + if (tpg->rgb_range == rgb_range) + return; + tpg->rgb_range = rgb_range; + tpg->recalc_colors = true; +} + +static inline void tpg_s_real_rgb_range(struct tpg_data *tpg, + unsigned rgb_range) +{ + if (tpg->real_rgb_range == rgb_range) + return; + tpg->real_rgb_range = rgb_range; + tpg->recalc_colors = true; +} + +static inline void tpg_s_colorspace(struct tpg_data *tpg, u32 colorspace) +{ + if (tpg->colorspace == colorspace) + return; + tpg->colorspace = colorspace; + tpg->recalc_colors = true; +} + +static inline u32 tpg_g_colorspace(const struct tpg_data *tpg) +{ + return tpg->colorspace; +} + +static inline unsigned tpg_g_planes(const struct tpg_data *tpg) +{ + return tpg->planes; +} + +static inline unsigned tpg_g_twopixelsize(const struct tpg_data *tpg, unsigned plane) +{ + return tpg->twopixelsize[plane]; +} + +static inline unsigned tpg_g_bytesperline(const struct tpg_data *tpg, unsigned plane) +{ + return tpg->bytesperline[plane]; +} + +static inline void tpg_s_bytesperline(struct tpg_data *tpg, unsigned plane, unsigned bpl) +{ + tpg->bytesperline[plane] = bpl; +} + +static inline void tpg_s_buf_height(struct tpg_data *tpg, unsigned h) +{ + tpg->buf_height = h; +} + +static inline void tpg_s_field(struct tpg_data *tpg, unsigned field) +{ + tpg->field = field; +} + +static inline void tpg_s_perc_fill(struct tpg_data *tpg, + unsigned perc_fill) +{ + tpg->perc_fill = perc_fill; +} + +static inline unsigned tpg_g_perc_fill(const struct tpg_data *tpg) +{ + return tpg->perc_fill; +} + +static inline void tpg_s_perc_fill_blank(struct tpg_data *tpg, + bool perc_fill_blank) +{ + tpg->perc_fill_blank = perc_fill_blank; +} + +static inline void tpg_s_video_aspect(struct tpg_data *tpg, + enum tpg_video_aspect vid_aspect) +{ + if (tpg->vid_aspect == vid_aspect) + return; + tpg->vid_aspect = vid_aspect; + tpg->recalc_square_border = true; +} + +static inline enum tpg_video_aspect tpg_g_video_aspect(const struct tpg_data *tpg) +{ + return tpg->vid_aspect; +} + +static inline void tpg_s_pixel_aspect(struct tpg_data *tpg, + enum tpg_pixel_aspect pix_aspect) +{ + if (tpg->pix_aspect == pix_aspect) + return; + tpg->pix_aspect = pix_aspect; + tpg->recalc_square_border = true; +} + +static inline void tpg_s_show_border(struct tpg_data *tpg, + bool show_border) +{ + tpg->show_border = show_border; +} + +static inline void tpg_s_show_square(struct tpg_data *tpg, + bool show_square) +{ + tpg->show_square = show_square; +} + +static inline void tpg_s_insert_sav(struct tpg_data *tpg, bool insert_sav) +{ + tpg->insert_sav = insert_sav; +} + +static inline void tpg_s_insert_eav(struct tpg_data *tpg, bool insert_eav) +{ + tpg->insert_eav = insert_eav; +} + +void tpg_update_mv_step(struct tpg_data *tpg); + +static inline void tpg_s_mv_hor_mode(struct tpg_data *tpg, + enum tpg_move_mode mv_hor_mode) +{ + tpg->mv_hor_mode = mv_hor_mode; + tpg_update_mv_step(tpg); +} + +static inline void tpg_s_mv_vert_mode(struct tpg_data *tpg, + enum tpg_move_mode mv_vert_mode) +{ + tpg->mv_vert_mode = mv_vert_mode; + tpg_update_mv_step(tpg); +} + +static inline void tpg_init_mv_count(struct tpg_data *tpg) +{ + tpg->mv_hor_count = tpg->mv_vert_count = 0; +} + +static inline void tpg_update_mv_count(struct tpg_data *tpg, bool frame_is_field) +{ + tpg->mv_hor_count += tpg->mv_hor_step * (frame_is_field ? 1 : 2); + tpg->mv_vert_count += tpg->mv_vert_step * (frame_is_field ? 1 : 2); +} + +static inline void tpg_s_hflip(struct tpg_data *tpg, bool hflip) +{ + if (tpg->hflip == hflip) + return; + tpg->hflip = hflip; + tpg_update_mv_step(tpg); + tpg->recalc_lines = true; +} + +static inline bool tpg_g_hflip(const struct tpg_data *tpg) +{ + return tpg->hflip; +} + +static inline void tpg_s_vflip(struct tpg_data *tpg, bool vflip) +{ + tpg->vflip = vflip; +} + +static inline bool tpg_g_vflip(const struct tpg_data *tpg) +{ + return tpg->vflip; +} + +static inline bool tpg_pattern_is_static(const struct tpg_data *tpg) +{ + return tpg->pattern != TPG_PAT_NOISE && + tpg->mv_hor_mode == TPG_MOVE_NONE && + tpg->mv_vert_mode == TPG_MOVE_NONE; +} + +static inline u32 prandom_u32_max(u32 ep_ro) +{ + return rand() % ep_ro; +} + +#endif diff -Nru v4l-utils-1.0.0+r2263/utils/v4l2-ctl/vivi-tpg.c v4l-utils-1.0.0+r2364/utils/v4l2-ctl/vivi-tpg.c --- v4l-utils-1.0.0+r2263/utils/v4l2-ctl/vivi-tpg.c 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/v4l2-ctl/vivi-tpg.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,1369 +0,0 @@ -#include "vivi-tpg.h" - -/* Must remain in sync with enum tpg_pattern */ -const char * const tpg_pattern_strings[] = { - "75% Colorbar", - "100% Colorbar", - "CSC Colorbar", - "Horizontal 100% Colorbar", - "100% Color Squares", - "100% Black", - "100% White", - "100% Red", - "100% Green", - "100% Blue", - "16x16 Checkers", - "1x1 Checkers", - "Alternating Hor Lines", - "Alternating Vert Lines", - "One Pixel Wide Cross", - "Two Pixels Wide Cross", - "Ten Pixels Wide Cross", - "Gray Ramp", - "Noise", - NULL -}; - -/* Must remain in sync with enum tpg_aspect */ -const char * const tpg_aspect_strings[] = { - "Source Width x Height", - "4x3", - "16x9", - "16x9 Anamorphic", - NULL -}; - -/* - * Sinus table: sin[0] = 127 * sin(-180 degrees) - * sin[128] = 127 * sin(0 degrees) - * sin[256] = 127 * sin(180 degrees) - */ -static const s8 sin[257] = { - 0, -4, -7, -11, -13, -18, -20, -22, -26, -29, -33, -35, -37, -41, -43, -48, - -50, -52, -56, -58, -62, -63, -65, -69, -71, -75, -76, -78, -82, -83, -87, -88, - -90, -93, -94, -97, -99, -101, -103, -104, -107, -108, -110, -111, -112, -114, -115, -117, - -118, -119, -120, -121, -122, -123, -123, -124, -125, -125, -126, -126, -127, -127, -127, -127, - -127, -127, -127, -127, -126, -126, -125, -125, -124, -124, -123, -122, -121, -120, -119, -118, - -117, -116, -114, -113, -111, -110, -109, -107, -105, -103, -101, -100, -97, -96, -93, -91, - -90, -87, -85, -82, -80, -76, -75, -73, -69, -67, -63, -62, -60, -56, -54, -50, - -48, -46, -41, -39, -35, -33, -31, -26, -24, -20, -18, -15, -11, -9, -4, -2, - 0, 2, 4, 9, 11, 15, 18, 20, 24, 26, 31, 33, 35, 39, 41, 46, - 48, 50, 54, 56, 60, 62, 64, 67, 69, 73, 75, 76, 80, 82, 85, 87, - 90, 91, 93, 96, 97, 100, 101, 103, 105, 107, 109, 110, 111, 113, 114, 116, - 117, 118, 119, 120, 121, 122, 123, 124, 124, 125, 125, 126, 126, 127, 127, 127, - 127, 127, 127, 127, 127, 126, 126, 125, 125, 124, 123, 123, 122, 121, 120, 119, - 118, 117, 115, 114, 112, 111, 110, 108, 107, 104, 103, 101, 99, 97, 94, 93, - 90, 88, 87, 83, 82, 78, 76, 75, 71, 69, 65, 64, 62, 58, 56, 52, - 50, 48, 43, 41, 37, 35, 33, 29, 26, 22, 20, 18, 13, 11, 7, 4, - 0, -}; - -/* - * Cosinus table: cos[0] = 127 * cos(-180 degrees) - * cos[128] = 127 * cos(0 degrees) - * cos[256] = 127 * cos(180 degrees) - */ -static const s8 cos[257] = { - -127, -127, -127, -127, -126, -126, -125, -125, -124, -124, -123, -122, -121, -120, -119, -118, - -117, -116, -114, -113, -111, -110, -109, -107, -105, -103, -101, -100, -97, -96, -93, -91, - -90, -87, -85, -82, -80, -76, -75, -73, -69, -67, -63, -62, -60, -56, -54, -50, - -48, -46, -41, -39, -35, -33, -31, -26, -24, -20, -18, -15, -11, -9, -4, -2, - 0, 4, 7, 11, 13, 18, 20, 22, 26, 29, 33, 35, 37, 41, 43, 48, - 50, 52, 56, 58, 62, 64, 65, 69, 71, 75, 76, 78, 82, 83, 87, 88, - 90, 93, 94, 97, 99, 101, 103, 104, 107, 108, 110, 111, 112, 114, 115, 117, - 118, 119, 120, 121, 122, 123, 123, 124, 125, 125, 126, 126, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 126, 126, 125, 125, 124, 123, 123, 122, 121, 120, 119, - 118, 117, 115, 114, 112, 111, 110, 108, 107, 104, 103, 101, 99, 97, 94, 93, - 90, 88, 87, 83, 82, 78, 76, 75, 71, 69, 65, 64, 62, 58, 56, 52, - 50, 48, 43, 41, 37, 35, 33, 29, 26, 22, 20, 18, 13, 11, 7, 4, - 0, -2, -4, -9, -11, -15, -18, -20, -24, -26, -31, -33, -35, -39, -41, -46, - -48, -50, -54, -56, -60, -62, -63, -67, -69, -73, -75, -76, -80, -82, -85, -87, - -90, -91, -93, -96, -97, -100, -101, -103, -105, -107, -109, -110, -111, -113, -114, -116, - -117, -118, -119, -120, -121, -122, -123, -124, -124, -125, -125, -126, -126, -127, -127, -127, - -127, -}; - -/* Global font descriptor */ -static const u8 *font8x16; - -void tpg_set_font(const u8 *f) -{ - font8x16 = f; -} - -void tpg_init(struct tpg_data *tpg, unsigned w, unsigned h) -{ - memset(tpg, 0, sizeof(*tpg)); - tpg->scaled_width = tpg->src_width = w; - tpg->src_height = tpg->buf_height = h; - tpg->crop.width = tpg->compose.width = w; - tpg->crop.height = tpg->compose.height = h; - tpg->recalc_colors = true; - tpg->recalc_square_border = true; - tpg->brightness = 128; - tpg->contrast = 128; - tpg->saturation = 128; - tpg->hue = 0; - tpg->field = V4L2_FIELD_NONE; - tpg_s_fourcc(tpg, V4L2_PIX_FMT_RGB24); - tpg->colorspace = V4L2_COLORSPACE_SRGB; - tpg->perc_fill = 100; -} - -int tpg_alloc(struct tpg_data *tpg, unsigned max_w) -{ - unsigned pat; - unsigned plane; - - tpg->max_line_width = max_w; - for (pat = 0; pat < TPG_MAX_PAT_LINES; pat++) { - for (plane = 0; plane < TPG_MAX_PLANES; plane++) { - unsigned pixelsz = plane ? 1 : 4; - - tpg->lines[pat][plane] = vzalloc(max_w * 2 * pixelsz); - if (!tpg->lines[pat][plane]) - return -ENOMEM; - } - } - for (plane = 0; plane < TPG_MAX_PLANES; plane++) { - unsigned pixelsz = plane ? 1 : 4; - - tpg->contrast_line[plane] = vzalloc(max_w * pixelsz); - if (!tpg->contrast_line[plane]) - return -ENOMEM; - tpg->black_line[plane] = vzalloc(max_w * pixelsz); - if (!tpg->black_line[plane]) - return -ENOMEM; - tpg->random_line[plane] = vzalloc(max_w * pixelsz); - if (!tpg->random_line[plane]) - return -ENOMEM; - } - return 0; -} - -void tpg_free(struct tpg_data *tpg) -{ - unsigned pat; - unsigned plane; - - for (pat = 0; pat < TPG_MAX_PAT_LINES; pat++) - for (plane = 0; plane < TPG_MAX_PLANES; plane++) { - vfree(tpg->lines[pat][plane]); - tpg->lines[pat][plane] = NULL; - } - for (plane = 0; plane < TPG_MAX_PLANES; plane++) { - vfree(tpg->contrast_line[plane]); - vfree(tpg->black_line[plane]); - vfree(tpg->random_line[plane]); - tpg->contrast_line[plane] = NULL; - tpg->black_line[plane] = NULL; - tpg->random_line[plane] = NULL; - } -} - -bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc) -{ - tpg->fourcc = fourcc; - tpg->planes = 1; - tpg->recalc_colors = true; - switch (fourcc) { - case V4L2_PIX_FMT_RGB565: - case V4L2_PIX_FMT_RGB565X: - case V4L2_PIX_FMT_RGB555: - case V4L2_PIX_FMT_RGB555X: - case V4L2_PIX_FMT_RGB24: - case V4L2_PIX_FMT_BGR24: - case V4L2_PIX_FMT_RGB32: - case V4L2_PIX_FMT_BGR32: - tpg->is_yuv = 0; - break; - case V4L2_PIX_FMT_NV16M: - case V4L2_PIX_FMT_NV61M: - tpg->planes = 2; - /* fall-through */ - case V4L2_PIX_FMT_YUYV: - case V4L2_PIX_FMT_UYVY: - case V4L2_PIX_FMT_YVYU: - case V4L2_PIX_FMT_VYUY: - tpg->is_yuv = 1; - break; - default: - return false; - } - - switch (fourcc) { - case V4L2_PIX_FMT_RGB565: - case V4L2_PIX_FMT_RGB565X: - case V4L2_PIX_FMT_RGB555: - case V4L2_PIX_FMT_RGB555X: - case V4L2_PIX_FMT_YUYV: - case V4L2_PIX_FMT_UYVY: - case V4L2_PIX_FMT_YVYU: - case V4L2_PIX_FMT_VYUY: - tpg->twopixelsize[0] = 2 * 2; - break; - case V4L2_PIX_FMT_RGB24: - case V4L2_PIX_FMT_BGR24: - tpg->twopixelsize[0] = 2 * 3; - break; - case V4L2_PIX_FMT_RGB32: - case V4L2_PIX_FMT_BGR32: - tpg->twopixelsize[0] = 2 * 4; - break; - case V4L2_PIX_FMT_NV16M: - case V4L2_PIX_FMT_NV61M: - tpg->twopixelsize[0] = 2; - tpg->twopixelsize[1] = 2; - break; - } - return true; -} - -void tpg_s_crop_compose(struct tpg_data *tpg) -{ - tpg->scaled_width = (tpg->src_width * tpg->compose.width + - tpg->crop.width - 1) / tpg->crop.width; - tpg->scaled_width &= ~1; - if (tpg->scaled_width > tpg->max_line_width) - tpg->scaled_width = tpg->max_line_width; - if (tpg->scaled_width < 2) - tpg->scaled_width = 2; - tpg->recalc_lines = true; -} - -void tpg_reset_source(struct tpg_data *tpg, unsigned width, unsigned height, - enum v4l2_field field) -{ - unsigned p; - - tpg->src_width = width; - tpg->src_height = height; - tpg->field = field; - tpg->buf_height = height; - if (V4L2_FIELD_HAS_T_OR_B(field)) - tpg->buf_height /= 2; - tpg->scaled_width = width; - tpg->crop.top = tpg->crop.left = 0; - tpg->crop.width = width; - tpg->crop.height = height; - tpg->compose.top = tpg->compose.left = 0; - tpg->compose.width = width; - tpg->compose.height = tpg->buf_height; - for (p = 0; p < tpg->planes; p++) - tpg->bytesperline[p] = width * tpg->twopixelsize[p] / 2; - tpg->recalc_square_border = true; -} - -static enum tpg_color tpg_get_textbg_color(struct tpg_data *tpg) -{ - switch (tpg->pattern) { - case TPG_PAT_BLACK: - return TPG_COLOR_100_WHITE; - case TPG_PAT_CSC_COLORBAR: - return TPG_COLOR_CSC_BLACK; - default: - return TPG_COLOR_100_BLACK; - } -} - -static enum tpg_color tpg_get_textfg_color(struct tpg_data *tpg) -{ - switch (tpg->pattern) { - case TPG_PAT_75_COLORBAR: - case TPG_PAT_CSC_COLORBAR: - return TPG_COLOR_CSC_WHITE; - case TPG_PAT_BLACK: - return TPG_COLOR_100_BLACK; - default: - return TPG_COLOR_100_WHITE; - } -} - -static u16 color_to_y(struct tpg_data *tpg, int r, int g, int b) -{ - switch (tpg->colorspace) { - case V4L2_COLORSPACE_SMPTE170M: - case V4L2_COLORSPACE_470_SYSTEM_M: - case V4L2_COLORSPACE_470_SYSTEM_BG: - return ((16829 * r + 33039 * g + 6416 * b + 16 * 32768) >> 16) + (16 << 4); - case V4L2_COLORSPACE_SMPTE240M: - return ((11932 * r + 39455 * g + 4897 * b + 16 * 32768) >> 16) + (16 << 4); - case V4L2_COLORSPACE_REC709: - case V4L2_COLORSPACE_SRGB: - default: - return ((11966 * r + 40254 * g + 4064 * b + 16 * 32768) >> 16) + (16 << 4); - } -} - -static u16 color_to_cb(struct tpg_data *tpg, int r, int g, int b) -{ - switch (tpg->colorspace) { - case V4L2_COLORSPACE_SMPTE170M: - case V4L2_COLORSPACE_470_SYSTEM_M: - case V4L2_COLORSPACE_470_SYSTEM_BG: - return ((-9714 * r - 19070 * g + 28784 * b + 16 * 32768) >> 16) + (128 << 4); - case V4L2_COLORSPACE_SMPTE240M: - return ((-6684 * r - 22100 * g + 28784 * b + 16 * 32768) >> 16) + (128 << 4); - case V4L2_COLORSPACE_REC709: - case V4L2_COLORSPACE_SRGB: - default: - return ((-6596 * r - 22189 * g + 28784 * b + 16 * 32768) >> 16) + (128 << 4); - } -} - -static u16 color_to_cr(struct tpg_data *tpg, int r, int g, int b) -{ - switch (tpg->colorspace) { - case V4L2_COLORSPACE_SMPTE170M: - case V4L2_COLORSPACE_470_SYSTEM_M: - case V4L2_COLORSPACE_470_SYSTEM_BG: - return ((28784 * r - 24103 * g - 4681 * b + 16 * 32768) >> 16) + (128 << 4); - case V4L2_COLORSPACE_SMPTE240M: - return ((28784 * r - 25606 * g - 3178 * b + 16 * 32768) >> 16) + (128 << 4); - case V4L2_COLORSPACE_REC709: - case V4L2_COLORSPACE_SRGB: - default: - return ((28784 * r - 26145 * g - 2639 * b + 16 * 32768) >> 16) + (128 << 4); - } -} - -static u16 ycbcr_to_r(struct tpg_data *tpg, int y, int cb, int cr) -{ - int r; - - y -= 16 << 4; - cb -= 128 << 4; - cr -= 128 << 4; - switch (tpg->colorspace) { - case V4L2_COLORSPACE_SMPTE170M: - case V4L2_COLORSPACE_470_SYSTEM_M: - case V4L2_COLORSPACE_470_SYSTEM_BG: - r = 4769 * y + 6537 * cr; - break; - case V4L2_COLORSPACE_SMPTE240M: - r = 4769 * y + 7376 * cr; - break; - case V4L2_COLORSPACE_REC709: - case V4L2_COLORSPACE_SRGB: - default: - r = 4769 * y + 7343 * cr; - break; - } - return clamp(r >> 12, 0, 0xff0); -} - -static u16 ycbcr_to_g(struct tpg_data *tpg, int y, int cb, int cr) -{ - int g; - - y -= 16 << 4; - cb -= 128 << 4; - cr -= 128 << 4; - switch (tpg->colorspace) { - case V4L2_COLORSPACE_SMPTE170M: - case V4L2_COLORSPACE_470_SYSTEM_M: - case V4L2_COLORSPACE_470_SYSTEM_BG: - g = 4769 * y - 1605 * cb - 3330 * cr; - break; - case V4L2_COLORSPACE_SMPTE240M: - g = 4769 * y - 1055 * cb - 2341 * cr; - break; - case V4L2_COLORSPACE_REC709: - case V4L2_COLORSPACE_SRGB: - default: - g = 4769 * y - 873 * cb - 2183 * cr; - break; - } - return clamp(g >> 12, 0, 0xff0); -} - -static u16 ycbcr_to_b(struct tpg_data *tpg, int y, int cb, int cr) -{ - int b; - - y -= 16 << 4; - cb -= 128 << 4; - cr -= 128 << 4; - switch (tpg->colorspace) { - case V4L2_COLORSPACE_SMPTE170M: - case V4L2_COLORSPACE_470_SYSTEM_M: - case V4L2_COLORSPACE_470_SYSTEM_BG: - b = 4769 * y + 7343 * cb; - break; - case V4L2_COLORSPACE_SMPTE240M: - b = 4769 * y + 8552 * cb; - break; - case V4L2_COLORSPACE_REC709: - case V4L2_COLORSPACE_SRGB: - default: - b = 4769 * y + 8652 * cb; - break; - } - return clamp(b >> 12, 0, 0xff0); -} - -/* precalculate color bar values to speed up rendering */ -static void precalculate_color(struct tpg_data *tpg, int k) -{ - int col = k; - int r = tpg_colors[col].r; - int g = tpg_colors[col].g; - int b = tpg_colors[col].b; - - if (k == TPG_COLOR_TEXTBG) { - col = tpg_get_textbg_color(tpg); - - r = tpg_colors[col].r; - g = tpg_colors[col].g; - b = tpg_colors[col].b; - } else if (k == TPG_COLOR_TEXTFG) { - col = tpg_get_textfg_color(tpg); - - r = tpg_colors[col].r; - g = tpg_colors[col].g; - b = tpg_colors[col].b; - } else if (tpg->pattern == TPG_PAT_NOISE) { - r = g = b = prandom_u32_max(256); - } else if (k == TPG_COLOR_RANDOM) { - r = g = b = tpg->qual_offset + prandom_u32_max(196); - } else if (k >= TPG_COLOR_RAMP) { - r = g = b = k - TPG_COLOR_RAMP; - } - - if (tpg->pattern == TPG_PAT_CSC_COLORBAR) { - r = tpg_csc_colors[tpg->colorspace][col].r; - g = tpg_csc_colors[tpg->colorspace][col].g; - b = tpg_csc_colors[tpg->colorspace][col].b; - } else { - r <<= 4; - g <<= 4; - b <<= 4; - } - if (tpg->qual == TPG_QUAL_GRAY) - r = g = b = color_to_y(tpg, r, g, b); - - /* - * The assumption is that the RGB output is always full range, - * so only if the rgb_range overrides the 'real' rgb range do - * we need to convert the RGB values. - * - * Currently there is no way of signalling to userspace if you - * are actually giving it limited range RGB (or full range - * YUV for that matter). - * - * Remember that r, g and b are still in the 0 - 0xff0 range. - */ - if (tpg->real_rgb_range == V4L2_DV_RGB_RANGE_LIMITED && - tpg->rgb_range == V4L2_DV_RGB_RANGE_FULL) { - /* - * Convert from full range (which is what r, g and b are) - * to limited range (which is the 'real' RGB range), which - * is then interpreted as full range. - */ - r = (r * 219) / 255 + (16 << 4); - g = (g * 219) / 255 + (16 << 4); - b = (b * 219) / 255 + (16 << 4); - } else if (tpg->real_rgb_range != V4L2_DV_RGB_RANGE_LIMITED && - tpg->rgb_range == V4L2_DV_RGB_RANGE_LIMITED) { - /* - * Clamp r, g and b to the limited range and convert to full - * range since that's what we deliver. - */ - r = clamp(r, 16 << 4, 235 << 4); - g = clamp(g, 16 << 4, 235 << 4); - b = clamp(b, 16 << 4, 235 << 4); - r = (r - (16 << 4)) * 255 / 219; - g = (g - (16 << 4)) * 255 / 219; - b = (b - (16 << 4)) * 255 / 219; - } - - if (tpg->brightness != 128 || tpg->contrast != 128 || - tpg->saturation != 128 || tpg->hue) { - /* Implement these operations */ - - /* First convert to YCbCr */ - int y = color_to_y(tpg, r, g, b); /* Luma */ - int cb = color_to_cb(tpg, r, g, b); /* Cb */ - int cr = color_to_cr(tpg, r, g, b); /* Cr */ - int tmp_cb, tmp_cr; - - y = (16 << 4) + ((y - (16 << 4)) * tpg->contrast) / 128; - y += (tpg->brightness << 4) - (128 << 4); - - cb -= 128 << 4; - cr -= 128 << 4; - tmp_cb = (cb * cos[128 + tpg->hue]) / 127 + (cr * sin[128 + tpg->hue]) / 127; - tmp_cr = (cr * cos[128 + tpg->hue]) / 127 - (cb * sin[128 + tpg->hue]) / 127; - - cb = (128 << 4) + (tmp_cb * tpg->contrast * tpg->saturation) / (128 * 128); - cr = (128 << 4) + (tmp_cr * tpg->contrast * tpg->saturation) / (128 * 128); - if (tpg->is_yuv) { - tpg->colors[k][0] = clamp(y >> 4, 1, 254); - tpg->colors[k][1] = clamp(cb >> 4, 1, 254); - tpg->colors[k][2] = clamp(cr >> 4, 1, 254); - return; - } - r = ycbcr_to_r(tpg, y, cb, cr); - g = ycbcr_to_g(tpg, y, cb, cr); - b = ycbcr_to_b(tpg, y, cb, cr); - } - - if (tpg->is_yuv) { - /* Convert to YCbCr */ - u16 y = color_to_y(tpg, r, g, b); /* Luma */ - u16 cb = color_to_cb(tpg, r, g, b); /* Cb */ - u16 cr = color_to_cr(tpg, r, g, b); /* Cr */ - - tpg->colors[k][0] = clamp(y >> 4, 1, 254); - tpg->colors[k][1] = clamp(cb >> 4, 1, 254); - tpg->colors[k][2] = clamp(cr >> 4, 1, 254); - } else { - switch (tpg->fourcc) { - case V4L2_PIX_FMT_RGB565: - case V4L2_PIX_FMT_RGB565X: - r >>= 7; - g >>= 6; - b >>= 7; - break; - case V4L2_PIX_FMT_RGB555: - case V4L2_PIX_FMT_RGB555X: - r >>= 7; - g >>= 7; - b >>= 7; - break; - default: - r >>= 4; - g >>= 4; - b >>= 4; - break; - } - - tpg->colors[k][0] = r; - tpg->colors[k][1] = g; - tpg->colors[k][2] = b; - } -} - -static void tpg_precalculate_colors(struct tpg_data *tpg) -{ - int k; - - for (k = 0; k < TPG_COLOR_MAX; k++) - precalculate_color(tpg, k); -} - -/* 'odd' is true for pixels 1, 3, 5, etc. and false for pixels 0, 2, 4, etc. */ -static void gen_twopix(struct tpg_data *tpg, - u8 buf[TPG_MAX_PLANES][8], int color, bool odd) -{ - unsigned offset = odd * tpg->twopixelsize[0] / 2; - u8 alpha = tpg->alpha_component; - u8 r_y, g_u, b_v; - - if (tpg->alpha_red_only && color != TPG_COLOR_CSC_RED && - color != TPG_COLOR_100_RED && - color != TPG_COLOR_75_RED) - alpha = 0; - if (color == TPG_COLOR_RANDOM) - precalculate_color(tpg, color); - r_y = tpg->colors[color][0]; /* R or precalculated Y */ - g_u = tpg->colors[color][1]; /* G or precalculated U */ - b_v = tpg->colors[color][2]; /* B or precalculated V */ - - switch (tpg->fourcc) { - case V4L2_PIX_FMT_NV16M: - buf[0][offset] = r_y; - buf[1][offset] = odd ? b_v : g_u; - break; - case V4L2_PIX_FMT_NV61M: - buf[0][offset] = r_y; - buf[1][offset] = odd ? g_u : b_v; - break; - - case V4L2_PIX_FMT_YUYV: - buf[0][offset] = r_y; - buf[0][offset + 1] = odd ? b_v : g_u; - break; - case V4L2_PIX_FMT_UYVY: - buf[0][offset] = odd ? b_v : g_u; - buf[0][offset + 1] = r_y; - break; - case V4L2_PIX_FMT_YVYU: - buf[0][offset] = r_y; - buf[0][offset + 1] = odd ? g_u : b_v; - break; - case V4L2_PIX_FMT_VYUY: - buf[0][offset] = odd ? g_u : b_v; - buf[0][offset + 1] = r_y; - break; - case V4L2_PIX_FMT_RGB565: - buf[0][offset] = (g_u << 5) | b_v; - buf[0][offset + 1] = (r_y << 3) | (g_u >> 3); - break; - case V4L2_PIX_FMT_RGB565X: - buf[0][offset] = (r_y << 3) | (g_u >> 3); - buf[0][offset + 1] = (g_u << 5) | b_v; - break; - case V4L2_PIX_FMT_RGB555: - buf[0][offset] = (g_u << 5) | b_v; - buf[0][offset + 1] = (alpha & 0x80) | (r_y << 2) | (g_u >> 3); - break; - case V4L2_PIX_FMT_RGB555X: - buf[0][offset] = (alpha & 0x80) | (r_y << 2) | (g_u >> 3); - buf[0][offset + 1] = (g_u << 5) | b_v; - break; - case V4L2_PIX_FMT_RGB24: - buf[0][offset] = r_y; - buf[0][offset + 1] = g_u; - buf[0][offset + 2] = b_v; - break; - case V4L2_PIX_FMT_BGR24: - buf[0][offset] = b_v; - buf[0][offset + 1] = g_u; - buf[0][offset + 2] = r_y; - break; - case V4L2_PIX_FMT_RGB32: - buf[0][offset] = alpha; - buf[0][offset + 1] = r_y; - buf[0][offset + 2] = g_u; - buf[0][offset + 3] = b_v; - break; - case V4L2_PIX_FMT_BGR32: - buf[0][offset] = b_v; - buf[0][offset + 1] = g_u; - buf[0][offset + 2] = r_y; - buf[0][offset + 3] = alpha; - break; - } -} - -/* Return how many pattern lines are used by the current pattern. */ -static unsigned tpg_get_pat_lines(struct tpg_data *tpg) -{ - switch (tpg->pattern) { - case TPG_PAT_CHECKERS_16X16: - case TPG_PAT_CHECKERS_1X1: - case TPG_PAT_ALTERNATING_HLINES: - case TPG_PAT_CROSS_1_PIXEL: - case TPG_PAT_CROSS_2_PIXELS: - case TPG_PAT_CROSS_10_PIXELS: - return 2; - case TPG_PAT_100_COLORSQUARES: - case TPG_PAT_100_HCOLORBAR: - return 8; - default: - return 1; - } -} - -/* Which pattern line should be used for the given frame line. */ -static unsigned tpg_get_pat_line(struct tpg_data *tpg, unsigned line) -{ - switch (tpg->pattern) { - case TPG_PAT_CHECKERS_16X16: - return (line >> 4) & 1; - case TPG_PAT_CHECKERS_1X1: - case TPG_PAT_ALTERNATING_HLINES: - return line & 1; - case TPG_PAT_100_COLORSQUARES: - case TPG_PAT_100_HCOLORBAR: - return (line * 8) / tpg->src_height; - case TPG_PAT_CROSS_1_PIXEL: - return line == tpg->src_height / 2; - case TPG_PAT_CROSS_2_PIXELS: - return (line + 1) / 2 == tpg->src_height / 4; - case TPG_PAT_CROSS_10_PIXELS: - return (line + 10) / 20 == tpg->src_height / 40; - default: - return 0; - } -} - -/* - * Which color should be used for the given pattern line and X coordinate. - * Note: x is in the range 0 to 2 * tpg->src_width. - */ -static enum tpg_color tpg_get_color(struct tpg_data *tpg, unsigned pat_line, unsigned x) -{ - /* Maximum number of bars are TPG_COLOR_MAX - otherwise, the input print code - should be modified */ - static const enum tpg_color bars[3][8] = { - /* Standard ITU-R 75% color bar sequence */ - { TPG_COLOR_CSC_WHITE, TPG_COLOR_75_YELLOW, - TPG_COLOR_75_CYAN, TPG_COLOR_75_GREEN, - TPG_COLOR_75_MAGENTA, TPG_COLOR_75_RED, - TPG_COLOR_75_BLUE, TPG_COLOR_100_BLACK, }, - /* Standard ITU-R 100% color bar sequence */ - { TPG_COLOR_100_WHITE, TPG_COLOR_100_YELLOW, - TPG_COLOR_100_CYAN, TPG_COLOR_100_GREEN, - TPG_COLOR_100_MAGENTA, TPG_COLOR_100_RED, - TPG_COLOR_100_BLUE, TPG_COLOR_100_BLACK, }, - /* Color bar sequence suitable to test CSC */ - { TPG_COLOR_CSC_WHITE, TPG_COLOR_CSC_YELLOW, - TPG_COLOR_CSC_CYAN, TPG_COLOR_CSC_GREEN, - TPG_COLOR_CSC_MAGENTA, TPG_COLOR_CSC_RED, - TPG_COLOR_CSC_BLUE, TPG_COLOR_CSC_BLACK, }, - }; - - switch (tpg->pattern) { - case TPG_PAT_75_COLORBAR: - case TPG_PAT_100_COLORBAR: - case TPG_PAT_CSC_COLORBAR: - return bars[tpg->pattern][((x * 8) / tpg->src_width) % 8]; - case TPG_PAT_100_COLORSQUARES: - return bars[1][(pat_line + (x * 8) / tpg->src_width) % 8]; - case TPG_PAT_100_HCOLORBAR: - return bars[1][pat_line]; - case TPG_PAT_BLACK: - return TPG_COLOR_100_BLACK; - case TPG_PAT_WHITE: - return TPG_COLOR_100_WHITE; - case TPG_PAT_RED: - return TPG_COLOR_100_RED; - case TPG_PAT_GREEN: - return TPG_COLOR_100_GREEN; - case TPG_PAT_BLUE: - return TPG_COLOR_100_BLUE; - case TPG_PAT_CHECKERS_16X16: - return (((x >> 4) & 1) ^ (pat_line & 1)) ? - TPG_COLOR_100_BLACK : TPG_COLOR_100_WHITE; - case TPG_PAT_CHECKERS_1X1: - return ((x & 1) ^ (pat_line & 1)) ? - TPG_COLOR_100_WHITE : TPG_COLOR_100_BLACK; - case TPG_PAT_ALTERNATING_HLINES: - return pat_line ? TPG_COLOR_100_WHITE : TPG_COLOR_100_BLACK; - case TPG_PAT_ALTERNATING_VLINES: - return (x & 1) ? TPG_COLOR_100_WHITE : TPG_COLOR_100_BLACK; - case TPG_PAT_CROSS_1_PIXEL: - if (pat_line || (x % tpg->src_width) == tpg->src_width / 2) - return TPG_COLOR_100_BLACK; - return TPG_COLOR_100_WHITE; - case TPG_PAT_CROSS_2_PIXELS: - if (pat_line || ((x % tpg->src_width) + 1) / 2 == tpg->src_width / 4) - return TPG_COLOR_100_BLACK; - return TPG_COLOR_100_WHITE; - case TPG_PAT_CROSS_10_PIXELS: - if (pat_line || ((x % tpg->src_width) + 10) / 20 == tpg->src_width / 40) - return TPG_COLOR_100_BLACK; - return TPG_COLOR_100_WHITE; - case TPG_PAT_GRAY_RAMP: - return TPG_COLOR_RAMP + ((x % tpg->src_width) * 256) / tpg->src_width; - default: - return TPG_COLOR_100_RED; - } -} - -/* - * Given the pixel aspect ratio and video aspect ratio calculate the - * coordinates of a centered square and the coordinates of the border of - * the active video area. The coordinates are relative to the source - * frame rectangle. - */ -static void tpg_calculate_square_border(struct tpg_data *tpg) -{ - unsigned w = tpg->src_width; - unsigned h = tpg->src_height; - unsigned sq_w, sq_h; - - sq_w = (w * 2 / 5) & ~1; - if (((w - sq_w) / 2) & 1) - sq_w += 2; - sq_h = sq_w; - tpg->square.width = sq_w; - if (tpg->vid_aspect == TPG_VIDEO_ASPECT_16X9_ANAMORPHIC) { - unsigned ana_sq_w = (sq_w / 4) * 3; - - if (((w - ana_sq_w) / 2) & 1) - ana_sq_w += 2; - tpg->square.width = ana_sq_w; - } - tpg->square.left = (w - tpg->square.width) / 2; - if (tpg->pix_aspect == TPG_PIXEL_ASPECT_NTSC) - sq_h = sq_w * 10 / 11; - else if (tpg->pix_aspect == TPG_PIXEL_ASPECT_PAL) - sq_h = sq_w * 59 / 54; - tpg->square.height = sq_h; - tpg->square.top = (h - sq_h) / 2; - tpg->border.left = 0; - tpg->border.width = w; - tpg->border.top = 0; - tpg->border.height = h; - switch (tpg->vid_aspect) { - case TPG_VIDEO_ASPECT_4X3: - if (tpg->pix_aspect) - return; - if (3 * w >= 4 * h) { - tpg->border.width = ((4 * h) / 3) & ~1; - if (((w - tpg->border.width) / 2) & ~1) - tpg->border.width -= 2; - tpg->border.left = (w - tpg->border.width) / 2; - break; - } - tpg->border.height = ((3 * w) / 4) & ~1; - tpg->border.top = (h - tpg->border.height) / 2; - break; - case TPG_VIDEO_ASPECT_16X9_CENTRE: - if (tpg->pix_aspect) { - tpg->border.height = tpg->pix_aspect == TPG_PIXEL_ASPECT_NTSC ? 400 : 430; - tpg->border.top = (h - tpg->border.height) / 2; - break; - } - if (9 * w >= 16 * h) { - tpg->border.width = ((16 * h) / 9) & ~1; - if (((w - tpg->border.width) / 2) & ~1) - tpg->border.width -= 2; - tpg->border.left = (w - tpg->border.width) / 2; - break; - } - tpg->border.height = ((9 * w) / 16) & ~1; - tpg->border.top = (h - tpg->border.height) / 2; - break; - default: - break; - } -} - -static void tpg_precalculate_line(struct tpg_data *tpg) -{ - enum tpg_color contrast = tpg->pattern == TPG_PAT_GREEN ? - TPG_COLOR_100_RED : TPG_COLOR_100_GREEN; - unsigned pat; - unsigned p; - unsigned x; - - for (pat = 0; pat < tpg_get_pat_lines(tpg); pat++) { - /* Coarse scaling with Bresenham */ - unsigned int_part = tpg->src_width / tpg->scaled_width; - unsigned fract_part = tpg->src_width % tpg->scaled_width; - unsigned src_x = 0; - unsigned error = 0; - - for (x = 0; x < tpg->scaled_width * 2; x += 2) { - unsigned real_x = src_x; - enum tpg_color color1, color2; - u8 pix[TPG_MAX_PLANES][8]; - - real_x = tpg->hflip ? tpg->src_width * 2 - real_x - 2 : real_x; - color1 = tpg_get_color(tpg, pat, real_x); - - src_x += int_part; - error += fract_part; - if (error >= tpg->scaled_width) { - error -= tpg->scaled_width; - src_x++; - } - - real_x = src_x; - real_x = tpg->hflip ? tpg->src_width * 2 - real_x - 2 : real_x; - color2 = tpg_get_color(tpg, pat, real_x); - - src_x += int_part; - error += fract_part; - if (error >= tpg->scaled_width) { - error -= tpg->scaled_width; - src_x++; - } - - gen_twopix(tpg, pix, tpg->hflip ? color2 : color1, 0); - gen_twopix(tpg, pix, tpg->hflip ? color1 : color2, 1); - for (p = 0; p < tpg->planes; p++) { - unsigned twopixsize = tpg->twopixelsize[p]; - u8 *pos = tpg->lines[pat][p] + x * twopixsize / 2; - - memcpy(pos, pix[p], twopixsize); - } - } - } - for (x = 0; x < tpg->scaled_width; x += 2) { - u8 pix[TPG_MAX_PLANES][8]; - - gen_twopix(tpg, pix, contrast, 0); - gen_twopix(tpg, pix, contrast, 1); - for (p = 0; p < tpg->planes; p++) { - unsigned twopixsize = tpg->twopixelsize[p]; - u8 *pos = tpg->contrast_line[p] + x * twopixsize / 2; - - memcpy(pos, pix[p], twopixsize); - } - } - for (x = 0; x < tpg->scaled_width; x += 2) { - u8 pix[TPG_MAX_PLANES][8]; - - gen_twopix(tpg, pix, TPG_COLOR_100_BLACK, 0); - gen_twopix(tpg, pix, TPG_COLOR_100_BLACK, 1); - for (p = 0; p < tpg->planes; p++) { - unsigned twopixsize = tpg->twopixelsize[p]; - u8 *pos = tpg->black_line[p] + x * twopixsize / 2; - - memcpy(pos, pix[p], twopixsize); - } - } - for (x = 0; x < tpg->scaled_width * 2; x += 2) { - u8 pix[TPG_MAX_PLANES][8]; - - gen_twopix(tpg, pix, TPG_COLOR_RANDOM, 0); - gen_twopix(tpg, pix, TPG_COLOR_RANDOM, 1); - for (p = 0; p < tpg->planes; p++) { - unsigned twopixsize = tpg->twopixelsize[p]; - u8 *pos = tpg->random_line[p] + x * twopixsize / 2; - - memcpy(pos, pix[p], twopixsize); - } - } - gen_twopix(tpg, tpg->textbg, TPG_COLOR_TEXTBG, 0); - gen_twopix(tpg, tpg->textbg, TPG_COLOR_TEXTBG, 1); - gen_twopix(tpg, tpg->textfg, TPG_COLOR_TEXTFG, 0); - gen_twopix(tpg, tpg->textfg, TPG_COLOR_TEXTFG, 1); -} - -/* need this to do rgb24 rendering */ -typedef struct { u16 __; u8 _; } __packed x24; - -void tpg_gen_text(struct tpg_data *tpg, u8 *basep[TPG_MAX_PLANES][2], - int y, int x, char *text) -{ - int line; - unsigned step = V4L2_FIELD_HAS_T_OR_B(tpg->field) ? 2 : 1; - unsigned div = step; - unsigned first = 0; - unsigned len = strlen(text); - unsigned p; - - if (font8x16 == NULL || basep == NULL) - return; - - /* Checks if it is possible to show string */ - if (y + 16 >= tpg->compose.height || x + 8 >= tpg->compose.width) - return; - - if (len > (tpg->compose.width - x) / 8) - len = (tpg->compose.width - x) / 8; - if (tpg->vflip) - y = tpg->compose.height - y - 16; - if (tpg->hflip) - x = tpg->compose.width - x - 8; - y += tpg->compose.top; - x += tpg->compose.left; - if (tpg->field == V4L2_FIELD_BOTTOM) - first = 1; - else if (tpg->field == V4L2_FIELD_SEQ_TB || tpg->field == V4L2_FIELD_SEQ_BT) - div = 2; - - for (p = 0; p < tpg->planes; p++) { - /* Print stream time */ -#define PRINTSTR(PIXTYPE) do { \ - PIXTYPE fg; \ - PIXTYPE bg; \ - memcpy(&fg, tpg->textfg[p], sizeof(PIXTYPE)); \ - memcpy(&bg, tpg->textbg[p], sizeof(PIXTYPE)); \ - \ - for (line = first; line < 16; line += step) { \ - int l = tpg->vflip ? 15 - line : line; \ - PIXTYPE *pos = (PIXTYPE *)(basep[p][line & 1] + \ - ((y * step + l) / div) * tpg->bytesperline[p] + \ - x * sizeof(PIXTYPE)); \ - unsigned s; \ - \ - for (s = 0; s < len; s++) { \ - u8 chr = font8x16[text[s] * 16 + line]; \ - \ - if (tpg->hflip) { \ - pos[7] = (chr & (0x01 << 7) ? fg : bg); \ - pos[6] = (chr & (0x01 << 6) ? fg : bg); \ - pos[5] = (chr & (0x01 << 5) ? fg : bg); \ - pos[4] = (chr & (0x01 << 4) ? fg : bg); \ - pos[3] = (chr & (0x01 << 3) ? fg : bg); \ - pos[2] = (chr & (0x01 << 2) ? fg : bg); \ - pos[1] = (chr & (0x01 << 1) ? fg : bg); \ - pos[0] = (chr & (0x01 << 0) ? fg : bg); \ - } else { \ - pos[0] = (chr & (0x01 << 7) ? fg : bg); \ - pos[1] = (chr & (0x01 << 6) ? fg : bg); \ - pos[2] = (chr & (0x01 << 5) ? fg : bg); \ - pos[3] = (chr & (0x01 << 4) ? fg : bg); \ - pos[4] = (chr & (0x01 << 3) ? fg : bg); \ - pos[5] = (chr & (0x01 << 2) ? fg : bg); \ - pos[6] = (chr & (0x01 << 1) ? fg : bg); \ - pos[7] = (chr & (0x01 << 0) ? fg : bg); \ - } \ - \ - pos += tpg->hflip ? -8 : 8; \ - } \ - } \ -} while (0) - - switch (tpg->twopixelsize[p]) { - case 2: - PRINTSTR(u8); break; - case 4: - PRINTSTR(u16); break; - case 6: - PRINTSTR(x24); break; - case 8: - PRINTSTR(u32); break; - } - } -} - -void tpg_update_mv_step(struct tpg_data *tpg) -{ - int factor = tpg->mv_hor_mode > TPG_MOVE_NONE ? -1 : 1; - - if (tpg->hflip) - factor = -factor; - switch (tpg->mv_hor_mode) { - case TPG_MOVE_NEG_FAST: - case TPG_MOVE_POS_FAST: - tpg->mv_hor_step = ((tpg->src_width + 319) / 320) * 4; - break; - case TPG_MOVE_NEG: - case TPG_MOVE_POS: - tpg->mv_hor_step = ((tpg->src_width + 639) / 640) * 4; - break; - case TPG_MOVE_NEG_SLOW: - case TPG_MOVE_POS_SLOW: - tpg->mv_hor_step = 2; - break; - case TPG_MOVE_NONE: - tpg->mv_hor_step = 0; - break; - } - tpg->mv_hor_step *= factor; - - factor = tpg->mv_vert_mode > TPG_MOVE_NONE ? -1 : 1; - switch (tpg->mv_vert_mode) { - case TPG_MOVE_NEG_FAST: - case TPG_MOVE_POS_FAST: - tpg->mv_vert_step = ((tpg->src_width + 319) / 320) * 4; - break; - case TPG_MOVE_NEG: - case TPG_MOVE_POS: - tpg->mv_vert_step = ((tpg->src_width + 639) / 640) * 4; - break; - case TPG_MOVE_NEG_SLOW: - case TPG_MOVE_POS_SLOW: - tpg->mv_vert_step = 1; - break; - case TPG_MOVE_NONE: - tpg->mv_vert_step = 0; - break; - } - tpg->mv_vert_step *= factor; -} - -/* Map the line number relative to the crop rectangle to a frame line number */ -static unsigned tpg_calc_frameline(struct tpg_data *tpg, unsigned src_y, - unsigned field) -{ - switch (field) { - case V4L2_FIELD_TOP: - return tpg->crop.top + src_y * 2; - case V4L2_FIELD_BOTTOM: - return tpg->crop.top + src_y * 2 + 1; - default: - return src_y + tpg->crop.top; - } -} - -/* - * Map the line number relative to the compose rectangle to a destination - * buffer line number. - */ -static unsigned tpg_calc_buffer_line(struct tpg_data *tpg, unsigned y, - unsigned field) -{ - y += tpg->compose.top; - switch (field) { - case V4L2_FIELD_SEQ_TB: - if (y & 1) - return tpg->buf_height / 2 + y / 2; - return y / 2; - case V4L2_FIELD_SEQ_BT: - if (y & 1) - return y / 2; - return tpg->buf_height / 2 + y / 2; - default: - return y; - } -} - -void tpg_fillbuffer(struct tpg_data *tpg, u8 *basep[TPG_MAX_PLANES][2], - v4l2_std_id std, unsigned p, u8 *vbuf) -{ - bool is_tv = std; - bool is_60hz = is_tv && (std & V4L2_STD_525_60); - unsigned mv_hor_old = tpg->mv_hor_count % tpg->src_width; - unsigned mv_hor_new = (tpg->mv_hor_count + tpg->mv_hor_step) % tpg->src_width; - unsigned mv_vert_old = tpg->mv_vert_count % tpg->src_height; - unsigned mv_vert_new = (tpg->mv_vert_count + tpg->mv_vert_step) % tpg->src_height; - unsigned wss_width; - unsigned f; - int hmax = (tpg->compose.height * tpg->perc_fill) / 100; - int h; - unsigned twopixsize = tpg->twopixelsize[p]; - unsigned img_width = tpg->compose.width * twopixsize / 2; - unsigned line_offset; - unsigned left_pillar_width = 0; - unsigned right_pillar_start = img_width; - unsigned stride = tpg->bytesperline[p]; - unsigned factor = V4L2_FIELD_HAS_T_OR_B(tpg->field) ? 2 : 1; - u8 *orig_vbuf = vbuf; - - /* Coarse scaling with Bresenham */ - unsigned int_part = (tpg->crop.height / factor) / tpg->compose.height; - unsigned fract_part = (tpg->crop.height / factor) % tpg->compose.height; - unsigned src_y = 0; - unsigned error = 0; - - if (tpg->recalc_colors) { - tpg->recalc_colors = false; - tpg->recalc_lines = true; - tpg_precalculate_colors(tpg); - } - if (tpg->recalc_square_border) { - tpg->recalc_square_border = false; - tpg_calculate_square_border(tpg); - } - if (tpg->recalc_lines) { - tpg->recalc_lines = false; - tpg_precalculate_line(tpg); - } - - mv_hor_old = (mv_hor_old * tpg->scaled_width / tpg->src_width) & ~1; - mv_hor_new = (mv_hor_new * tpg->scaled_width / tpg->src_width) & ~1; - wss_width = tpg->crop.left < tpg->src_width / 2 ? - tpg->src_width / 2 - tpg->crop.left : 0; - if (wss_width > tpg->crop.width) - wss_width = tpg->crop.width; - wss_width = wss_width * tpg->scaled_width / tpg->src_width; - - if (basep) { - basep[p][0] = vbuf; - basep[p][1] = vbuf; - if (tpg->field == V4L2_FIELD_SEQ_TB) - basep[p][1] += tpg->buf_height * stride / 2; - else if (tpg->field == V4L2_FIELD_SEQ_BT) - basep[p][0] += tpg->buf_height * stride / 2; - } - - vbuf += tpg->compose.left * twopixsize / 2; - line_offset = tpg->crop.left * tpg->scaled_width / tpg->src_width; - line_offset = (line_offset & ~1) * twopixsize / 2; - if (tpg->crop.left < tpg->border.left) { - left_pillar_width = tpg->border.left - tpg->crop.left; - if (left_pillar_width > tpg->crop.width) - left_pillar_width = tpg->crop.width; - left_pillar_width = (left_pillar_width * tpg->scaled_width) / tpg->src_width; - left_pillar_width = (left_pillar_width & ~1) * twopixsize / 2; - } - if (tpg->crop.left + tpg->crop.width > tpg->border.left + tpg->border.width) { - right_pillar_start = tpg->border.left + tpg->border.width - tpg->crop.left; - right_pillar_start = (right_pillar_start * tpg->scaled_width) / tpg->src_width; - right_pillar_start = (right_pillar_start & ~1) * twopixsize / 2; - if (right_pillar_start > img_width) - right_pillar_start = img_width; - } - - f = tpg->field == (is_60hz ? V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM); - - for (h = 0; h < tpg->compose.height; h++) { - bool even; - bool fill_blank = false; - unsigned frame_line; - unsigned buf_line; - unsigned pat_line_old; - unsigned pat_line_new; - u8 *linestart_older; - u8 *linestart_newer; - u8 *linestart_top; - u8 *linestart_bottom; - - frame_line = tpg_calc_frameline(tpg, src_y, tpg->field); - even = !(frame_line & 1); - buf_line = tpg_calc_buffer_line(tpg, h, tpg->field); - src_y += int_part; - error += fract_part; - if (error >= tpg->compose.height) { - error -= tpg->compose.height; - src_y++; - } - - if (h >= hmax) { - if (hmax == tpg->compose.height) - continue; - if (!tpg->perc_fill_blank) - continue; - fill_blank = true; - } - - if (tpg->vflip) - frame_line = tpg->src_height - frame_line - 1; - - if (fill_blank) { - linestart_older = tpg->contrast_line[p]; - linestart_newer = tpg->contrast_line[p]; - } else if (tpg->qual != TPG_QUAL_NOISE && - (frame_line < tpg->border.top || - frame_line >= tpg->border.top + tpg->border.height)) { - linestart_older = tpg->black_line[p]; - linestart_newer = tpg->black_line[p]; - } else if (tpg->pattern == TPG_PAT_NOISE || tpg->qual == TPG_QUAL_NOISE) { - linestart_older = tpg->random_line[p] + - twopixsize * prandom_u32_max(tpg->src_width / 2); - linestart_newer = tpg->random_line[p] + - twopixsize * prandom_u32_max(tpg->src_width / 2); - } else { - pat_line_old = tpg_get_pat_line(tpg, - (frame_line + mv_vert_old) % tpg->src_height); - pat_line_new = tpg_get_pat_line(tpg, - (frame_line + mv_vert_new) % tpg->src_height); - linestart_older = tpg->lines[pat_line_old][p] + - mv_hor_old * twopixsize / 2; - linestart_newer = tpg->lines[pat_line_new][p] + - mv_hor_new * twopixsize / 2; - linestart_older += line_offset; - linestart_newer += line_offset; - } - if (is_60hz) { - linestart_top = linestart_newer; - linestart_bottom = linestart_older; - } else { - linestart_top = linestart_older; - linestart_bottom = linestart_newer; - } - - switch (tpg->field) { - case V4L2_FIELD_INTERLACED: - case V4L2_FIELD_INTERLACED_TB: - case V4L2_FIELD_SEQ_TB: - case V4L2_FIELD_SEQ_BT: - if (even) - memcpy(vbuf + buf_line * stride, linestart_top, img_width); - else - memcpy(vbuf + buf_line * stride, linestart_bottom, img_width); - break; - case V4L2_FIELD_INTERLACED_BT: - if (even) - memcpy(vbuf + buf_line * stride, linestart_bottom, img_width); - else - memcpy(vbuf + buf_line * stride, linestart_top, img_width); - break; - case V4L2_FIELD_TOP: - memcpy(vbuf + buf_line * stride, linestart_top, img_width); - break; - case V4L2_FIELD_BOTTOM: - memcpy(vbuf + buf_line * stride, linestart_bottom, img_width); - break; - case V4L2_FIELD_NONE: - default: - memcpy(vbuf + buf_line * stride, linestart_older, img_width); - break; - } - - if (is_tv && !is_60hz && frame_line == 0 && wss_width) { - /* - * Replace the first half of the top line of a 50 Hz frame - * with random data to simulate a WSS signal. - */ - u8 *wss = tpg->random_line[p] + - twopixsize * prandom_u32_max(tpg->src_width / 2); - - memcpy(vbuf + buf_line * stride, wss, wss_width * twopixsize / 2); - } - } - - vbuf = orig_vbuf; - vbuf += tpg->compose.left * twopixsize / 2; - src_y = 0; - error = 0; - for (h = 0; h < tpg->compose.height; h++) { - unsigned frame_line = tpg_calc_frameline(tpg, src_y, tpg->field); - unsigned buf_line = tpg_calc_buffer_line(tpg, h, tpg->field); - const struct v4l2_rect *sq = &tpg->square; - const struct v4l2_rect *b = &tpg->border; - const struct v4l2_rect *c = &tpg->crop; - - src_y += int_part; - error += fract_part; - if (error >= tpg->compose.height) { - error -= tpg->compose.height; - src_y++; - } - - if (tpg->show_border && frame_line >= b->top && - frame_line < b->top + b->height) { - unsigned bottom = b->top + b->height - 1; - unsigned left = left_pillar_width; - unsigned right = right_pillar_start; - - if (frame_line == b->top || frame_line == b->top + 1 || - frame_line == bottom || frame_line == bottom - 1) { - memcpy(vbuf + buf_line * stride + left, tpg->contrast_line[p], - right - left); - } else { - if (b->left >= c->left && - b->left < c->left + c->width) - memcpy(vbuf + buf_line * stride + left, - tpg->contrast_line[p], twopixsize); - if (b->left + b->width > c->left && - b->left + b->width <= c->left + c->width) - memcpy(vbuf + buf_line * stride + right - twopixsize, - tpg->contrast_line[p], twopixsize); - } - } - if (tpg->qual != TPG_QUAL_NOISE && frame_line >= b->top && - frame_line < b->top + b->height) { - memcpy(vbuf + buf_line * stride, tpg->black_line[p], left_pillar_width); - memcpy(vbuf + buf_line * stride + right_pillar_start, tpg->black_line[p], - img_width - right_pillar_start); - } - if (tpg->show_square && frame_line >= sq->top && - frame_line < sq->top + sq->height && - sq->left < c->left + c->width && - sq->left + sq->width >= c->left) { - unsigned left = sq->left; - unsigned width = sq->width; - - if (c->left > left) { - width -= c->left - left; - left = c->left; - } - if (c->left + c->width < left + width) - width -= left + width - c->left - c->width; - left -= c->left; - left = (left * tpg->scaled_width) / tpg->src_width; - left = (left & ~1) * twopixsize / 2; - width = (width * tpg->scaled_width) / tpg->src_width; - width = (width & ~1) * twopixsize / 2; - memcpy(vbuf + buf_line * stride + left, tpg->contrast_line[p], width); - } - if (tpg->insert_sav) { - unsigned offset = (tpg->compose.width / 6) * twopixsize; - u8 *p = vbuf + buf_line * stride + offset; - unsigned vact = 0, hact = 0; - - p[0] = 0xff; - p[1] = 0; - p[2] = 0; - p[3] = 0x80 | (f << 6) | (vact << 5) | (hact << 4) | - ((hact ^ vact) << 3) | - ((hact ^ f) << 2) | - ((f ^ vact) << 1) | - (hact ^ vact ^ f); - } - if (tpg->insert_eav) { - unsigned offset = (tpg->compose.width / 6) * 2 * twopixsize; - u8 *p = vbuf + buf_line * stride + offset; - unsigned vact = 0, hact = 1; - - p[0] = 0xff; - p[1] = 0; - p[2] = 0; - p[3] = 0x80 | (f << 6) | (vact << 5) | (hact << 4) | - ((hact ^ vact) << 3) | - ((hact ^ f) << 2) | - ((f ^ vact) << 1) | - (hact ^ vact ^ f); - } - } -} diff -Nru v4l-utils-1.0.0+r2263/utils/v4l2-ctl/vivi-tpg.h v4l-utils-1.0.0+r2364/utils/v4l2-ctl/vivi-tpg.h --- v4l-utils-1.0.0+r2263/utils/v4l2-ctl/vivi-tpg.h 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/v4l2-ctl/vivi-tpg.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,459 +0,0 @@ -#ifndef _VIVI_TPG_H_ -#define _VIVI_TPG_H_ - -#include -#include - -#include -#include -#include -#include - -typedef __u32 u32; -typedef __u16 u16; -typedef __s16 s16; -typedef __u8 u8; -typedef __s8 s8; - -#define __packed __attribute__((packed)) - -static inline void vfree(void *p) -{ - free(p); -} - -static inline void *vzalloc(unsigned long size) -{ - return calloc(1, size); -} - -#define clamp(val, min, max) ({ \ - typeof(val) __val = (val); \ - typeof(min) __min = (min); \ - typeof(max) __max = (max); \ - (void) (&__val == &__min); \ - (void) (&__val == &__max); \ - __val = __val < __min ? __min: __val; \ - __val > __max ? __max: __val; }) - -#include "vivi-colors.h" - -enum tpg_pattern { - TPG_PAT_75_COLORBAR, - TPG_PAT_100_COLORBAR, - TPG_PAT_CSC_COLORBAR, - TPG_PAT_100_HCOLORBAR, - TPG_PAT_100_COLORSQUARES, - TPG_PAT_BLACK, - TPG_PAT_WHITE, - TPG_PAT_RED, - TPG_PAT_GREEN, - TPG_PAT_BLUE, - TPG_PAT_CHECKERS_16X16, - TPG_PAT_CHECKERS_1X1, - TPG_PAT_ALTERNATING_HLINES, - TPG_PAT_ALTERNATING_VLINES, - TPG_PAT_CROSS_1_PIXEL, - TPG_PAT_CROSS_2_PIXELS, - TPG_PAT_CROSS_10_PIXELS, - TPG_PAT_GRAY_RAMP, - - /* Must be the last pattern */ - TPG_PAT_NOISE, -}; - -extern const char * const tpg_pattern_strings[]; - -enum tpg_quality { - TPG_QUAL_COLOR, - TPG_QUAL_GRAY, - TPG_QUAL_NOISE -}; - -enum tpg_video_aspect { - TPG_VIDEO_ASPECT_IMAGE, - TPG_VIDEO_ASPECT_4X3, - TPG_VIDEO_ASPECT_16X9_CENTRE, - TPG_VIDEO_ASPECT_16X9_ANAMORPHIC, -}; - -enum tpg_pixel_aspect { - TPG_PIXEL_ASPECT_SQUARE, - TPG_PIXEL_ASPECT_NTSC, - TPG_PIXEL_ASPECT_PAL, -}; - -enum tpg_move_mode { - TPG_MOVE_NEG_FAST, - TPG_MOVE_NEG, - TPG_MOVE_NEG_SLOW, - TPG_MOVE_NONE, - TPG_MOVE_POS_SLOW, - TPG_MOVE_POS, - TPG_MOVE_POS_FAST, -}; - -extern const char * const tpg_aspect_strings[]; - -#define TPG_MAX_PLANES 2 -#define TPG_MAX_PAT_LINES 8 - -#define V4L2_FIELD_HAS_T_OR_B(f) \ - ((f) == V4L2_FIELD_BOTTOM || \ - (f) == V4L2_FIELD_TOP || \ - (f) == V4L2_FIELD_ALTERNATE) - -struct tpg_data { - /* Source frame size */ - unsigned src_width, src_height; - /* Buffer height */ - unsigned buf_height; - /* Scaled output frame size */ - unsigned scaled_width; - u32 field; - /* crop coordinates are frame-based */ - struct v4l2_rect crop; - /* compose coordinates are format-based */ - struct v4l2_rect compose; - /* border and square coordinates are frame-based */ - struct v4l2_rect border; - struct v4l2_rect square; - - /* Color-related fields */ - enum tpg_quality qual; - unsigned qual_offset; - u8 alpha_component; - bool alpha_red_only; - u8 brightness; - u8 contrast; - u8 saturation; - s16 hue; - u32 fourcc; - bool is_yuv; - u32 colorspace; - enum tpg_video_aspect vid_aspect; - enum tpg_pixel_aspect pix_aspect; - unsigned rgb_range; - unsigned real_rgb_range; - unsigned planes; - /* Used to store the colors in native format, either RGB or YUV */ - u8 colors[TPG_COLOR_MAX][3]; - u8 textfg[TPG_MAX_PLANES][8], textbg[TPG_MAX_PLANES][8]; - /* size in bytes for two pixels in each plane */ - unsigned twopixelsize[TPG_MAX_PLANES]; - unsigned bytesperline[TPG_MAX_PLANES]; - - /* Configuration */ - enum tpg_pattern pattern; - bool hflip; - bool vflip; - unsigned perc_fill; - bool perc_fill_blank; - bool show_border; - bool show_square; - bool insert_sav; - bool insert_eav; - - /* Test pattern movement */ - enum tpg_move_mode mv_hor_mode; - int mv_hor_count; - int mv_hor_step; - enum tpg_move_mode mv_vert_mode; - int mv_vert_count; - int mv_vert_step; - - bool recalc_colors; - bool recalc_lines; - bool recalc_square_border; - - /* Used to store TPG_MAX_PAT_LINES lines, each with up to two planes */ - unsigned max_line_width; - u8 *lines[TPG_MAX_PAT_LINES][TPG_MAX_PLANES]; - u8 *random_line[TPG_MAX_PLANES]; - u8 *contrast_line[TPG_MAX_PLANES]; - u8 *black_line[TPG_MAX_PLANES]; -}; - -void tpg_init(struct tpg_data *tpg, unsigned w, unsigned h); -int tpg_alloc(struct tpg_data *tpg, unsigned max_w); -void tpg_free(struct tpg_data *tpg); -void tpg_reset_source(struct tpg_data *tpg, unsigned width, unsigned height, - u32 field); - -void tpg_set_font(const u8 *f); -void tpg_gen_text(struct tpg_data *tpg, u8 *basep[TPG_MAX_PLANES][2], - int y, int x, char *text); -void tpg_fillbuffer(struct tpg_data *tpg, u8 *basep[TPG_MAX_PLANES][2], - v4l2_std_id std, unsigned p, u8 *vbuf); -bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc); -void tpg_s_crop_compose(struct tpg_data *tpg); - -static inline void tpg_s_pattern(struct tpg_data *tpg, enum tpg_pattern pattern) -{ - if (tpg->pattern == pattern) - return; - tpg->pattern = pattern; - tpg->recalc_colors = true; -} - -static inline void tpg_s_quality(struct tpg_data *tpg, - enum tpg_quality qual, unsigned qual_offset) -{ - if (tpg->qual == qual && tpg->qual_offset == qual_offset) - return; - tpg->qual = qual; - tpg->qual_offset = qual_offset; - tpg->recalc_colors = true; -} - -static inline enum tpg_quality tpg_g_quality(const struct tpg_data *tpg) -{ - return tpg->qual; -} - -static inline void tpg_s_alpha_component(struct tpg_data *tpg, - u8 alpha_component) -{ - if (tpg->alpha_component == alpha_component) - return; - tpg->alpha_component = alpha_component; - tpg->recalc_colors = true; -} - -static inline void tpg_s_alpha_mode(struct tpg_data *tpg, - bool red_only) -{ - if (tpg->alpha_red_only == red_only) - return; - tpg->alpha_red_only = red_only; - tpg->recalc_colors = true; -} - -static inline void tpg_s_brightness(struct tpg_data *tpg, - u8 brightness) -{ - if (tpg->brightness == brightness) - return; - tpg->brightness = brightness; - tpg->recalc_colors = true; -} - -static inline void tpg_s_contrast(struct tpg_data *tpg, - u8 contrast) -{ - if (tpg->contrast == contrast) - return; - tpg->contrast = contrast; - tpg->recalc_colors = true; -} - -static inline void tpg_s_saturation(struct tpg_data *tpg, - u8 saturation) -{ - if (tpg->saturation == saturation) - return; - tpg->saturation = saturation; - tpg->recalc_colors = true; -} - -static inline void tpg_s_hue(struct tpg_data *tpg, - s16 hue) -{ - if (tpg->hue == hue) - return; - tpg->hue = hue; - tpg->recalc_colors = true; -} - -static inline void tpg_s_rgb_range(struct tpg_data *tpg, - unsigned rgb_range) -{ - if (tpg->rgb_range == rgb_range) - return; - tpg->rgb_range = rgb_range; - tpg->recalc_colors = true; -} - -static inline void tpg_s_real_rgb_range(struct tpg_data *tpg, - unsigned rgb_range) -{ - if (tpg->real_rgb_range == rgb_range) - return; - tpg->real_rgb_range = rgb_range; - tpg->recalc_colors = true; -} - -static inline void tpg_s_colorspace(struct tpg_data *tpg, u32 colorspace) -{ - if (tpg->colorspace == colorspace) - return; - tpg->colorspace = colorspace; - tpg->recalc_colors = true; -} - -static inline u32 tpg_g_colorspace(const struct tpg_data *tpg) -{ - return tpg->colorspace; -} - -static inline unsigned tpg_g_planes(const struct tpg_data *tpg) -{ - return tpg->planes; -} - -static inline unsigned tpg_g_twopixelsize(const struct tpg_data *tpg, unsigned plane) -{ - return tpg->twopixelsize[plane]; -} - -static inline unsigned tpg_g_bytesperline(const struct tpg_data *tpg, unsigned plane) -{ - return tpg->bytesperline[plane]; -} - -static inline void tpg_s_bytesperline(struct tpg_data *tpg, unsigned plane, unsigned bpl) -{ - tpg->bytesperline[plane] = bpl; -} - -static inline void tpg_s_buf_height(struct tpg_data *tpg, unsigned h) -{ - tpg->buf_height = h; -} - -static inline struct v4l2_rect *tpg_g_crop(struct tpg_data *tpg) -{ - return &tpg->crop; -} - -static inline struct v4l2_rect *tpg_g_compose(struct tpg_data *tpg) -{ - return &tpg->compose; -} - -static inline void tpg_s_field(struct tpg_data *tpg, unsigned field) -{ - tpg->field = field; -} - -static inline void tpg_s_perc_fill(struct tpg_data *tpg, - unsigned perc_fill) -{ - tpg->perc_fill = perc_fill; -} - -static inline unsigned tpg_g_perc_fill(const struct tpg_data *tpg) -{ - return tpg->perc_fill; -} - -static inline void tpg_s_perc_fill_blank(struct tpg_data *tpg, - bool perc_fill_blank) -{ - tpg->perc_fill_blank = perc_fill_blank; -} - -static inline void tpg_s_video_aspect(struct tpg_data *tpg, - enum tpg_video_aspect vid_aspect) -{ - if (tpg->vid_aspect == vid_aspect) - return; - tpg->vid_aspect = vid_aspect; - tpg->recalc_square_border = true; -} - -static inline void tpg_s_pixel_aspect(struct tpg_data *tpg, - enum tpg_pixel_aspect pix_aspect) -{ - if (tpg->pix_aspect == pix_aspect) - return; - tpg->pix_aspect = pix_aspect; - tpg->recalc_square_border = true; -} - -static inline void tpg_s_show_border(struct tpg_data *tpg, - bool show_border) -{ - tpg->show_border = show_border; -} - -static inline void tpg_s_show_square(struct tpg_data *tpg, - bool show_square) -{ - tpg->show_square = show_square; -} - -static inline void tpg_s_insert_sav(struct tpg_data *tpg, bool insert_sav) -{ - tpg->insert_sav = insert_sav; -} - -static inline void tpg_s_insert_eav(struct tpg_data *tpg, bool insert_eav) -{ - tpg->insert_eav = insert_eav; -} - -void tpg_update_mv_step(struct tpg_data *tpg); - -static inline void tpg_s_mv_hor_mode(struct tpg_data *tpg, - enum tpg_move_mode mv_hor_mode) -{ - tpg->mv_hor_mode = mv_hor_mode; - tpg_update_mv_step(tpg); -} - -static inline void tpg_s_mv_vert_mode(struct tpg_data *tpg, - enum tpg_move_mode mv_vert_mode) -{ - tpg->mv_vert_mode = mv_vert_mode; - tpg_update_mv_step(tpg); -} - -static inline void tpg_init_mv_count(struct tpg_data *tpg) -{ - tpg->mv_hor_count = tpg->mv_vert_count = 0; -} - -static inline void tpg_update_mv_count(struct tpg_data *tpg, bool frame_is_field) -{ - tpg->mv_hor_count += tpg->mv_hor_step * (frame_is_field ? 1 : 2); - tpg->mv_vert_count += tpg->mv_vert_step * (frame_is_field ? 1 : 2); -} - -static inline void tpg_s_hflip(struct tpg_data *tpg, bool hflip) -{ - if (tpg->hflip == hflip) - return; - tpg->hflip = hflip; - tpg_update_mv_step(tpg); - tpg->recalc_lines = true; -} - -static inline bool tpg_g_hflip(const struct tpg_data *tpg) -{ - return tpg->hflip; -} - -static inline void tpg_s_vflip(struct tpg_data *tpg, bool vflip) -{ - tpg->vflip = vflip; -} - -static inline bool tpg_g_vflip(const struct tpg_data *tpg) -{ - return tpg->vflip; -} - -static inline bool tpg_pattern_is_static(const struct tpg_data *tpg) -{ - return tpg->pattern != TPG_PAT_NOISE && - tpg->mv_hor_mode == TPG_MOVE_NONE && - tpg->mv_vert_mode == TPG_MOVE_NONE; -} - -static inline u32 prandom_u32_max(u32 ep_ro) -{ - return rand() % ep_ro; -} - -#endif diff -Nru v4l-utils-1.0.0+r2263/utils/v4l2-dbg/v4l2-dbg.cpp v4l-utils-1.0.0+r2364/utils/v4l2-dbg/v4l2-dbg.cpp --- v4l-utils-1.0.0+r2263/utils/v4l2-dbg/v4l2-dbg.cpp 2014-07-17 01:36:32.000000000 +0000 +++ v4l-utils-1.0.0+r2364/utils/v4l2-dbg/v4l2-dbg.cpp 2014-08-12 09:02:18.000000000 +0000 @@ -196,8 +196,16 @@ if (cap & V4L2_CAP_VIDEO_CAPTURE) s += "\t\tVideo Capture\n"; + if (cap & V4L2_CAP_VIDEO_CAPTURE_MPLANE) + s += "\t\tVideo Capture Multiplanar\n"; if (cap & V4L2_CAP_VIDEO_OUTPUT) s += "\t\tVideo Output\n"; + if (cap & V4L2_CAP_VIDEO_OUTPUT_MPLANE) + s += "\t\tVideo Output Multiplanar\n"; + if (cap & V4L2_CAP_VIDEO_M2M) + s += "\t\tVideo Memory-to-Memory\n"; + if (cap & V4L2_CAP_VIDEO_M2M_MPLANE) + s += "\t\tVideo Memory-to-Memory Multiplanar\n"; if (cap & V4L2_CAP_VIDEO_OVERLAY) s += "\t\tVideo Overlay\n"; if (cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY) @@ -212,8 +220,16 @@ s += "\t\tSliced VBI Output\n"; if (cap & V4L2_CAP_RDS_CAPTURE) s += "\t\tRDS Capture\n"; + if (cap & V4L2_CAP_RDS_OUTPUT) + s += "\t\tRDS Output\n"; + if (cap & V4L2_CAP_SDR_CAPTURE) + s += "\t\tSDR Capture\n"; if (cap & V4L2_CAP_TUNER) s += "\t\tTuner\n"; + if (cap & V4L2_CAP_HW_FREQ_SEEK) + s += "\t\tHW Frequency Seek\n"; + if (cap & V4L2_CAP_MODULATOR) + s += "\t\tModulator\n"; if (cap & V4L2_CAP_AUDIO) s += "\t\tAudio\n"; if (cap & V4L2_CAP_RADIO) @@ -224,6 +240,10 @@ s += "\t\tAsync I/O\n"; if (cap & V4L2_CAP_STREAMING) s += "\t\tStreaming\n"; + if (cap & V4L2_CAP_EXT_PIX_FORMAT) + s += "\t\tExtended Pix Format\n"; + if (cap & V4L2_CAP_DEVICE_CAPS) + s += "\t\tDevice Capabilities\n"; return s; }