Hi,
I've added the ioctls VIDIOC_ENUM_FRAMESIZES and VIDIOC_ENUM_FRAMEINTERVALS
to the pwc driver.
I'm unsure if I've done the FRAMESIZES ioctl correct for the raw mode.
The FRAMEINTERVALS is completely missing for raw mode.
This patch is only tested with a PCVC680K. So please try it out and
report back.
The patch is against svn://svn.saillard.org/pwc/branches/v4l2.
I've attached a simple testprogram. If you use kernel headers older
than 2.6.19, you need to get the uvc_compat.h header from the uvc
driver.
Thanks,
Gregor
This patch add support for the VIDIOC_ENUM_FRAMESIZES and
VIDIOC_ENUM_FRAMEINTERVALS ioctl.
Todo:
* check if the maximum native framesize for raw mode is correct
* raw mode framerates for all three chipset types
Signed-off-by: Gregor Jasny <[EMAIL PROTECTED]>
---
Index: pwc.h
===================================================================
--- pwc.h (revision 142)
+++ pwc.h (working copy)
@@ -299,6 +299,7 @@
/** Functions in pwc-ctrl.c */
/* Request a certain video mode. Returns < 0 if not possible */
extern int pwc_set_video_mode(struct pwc_device *pdev, int width, int height,
int frames, int compression, int snapshot);
+extern unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index,
unsigned int size);
/* Calculate the number of bytes per image (not frame) */
extern int pwc_mpt_reset(struct pwc_device *pdev, int flags);
extern int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt);
Index: pwc-timon.c
===================================================================
--- pwc-timon.c (revision 142)
+++ pwc-timon.c (working copy)
@@ -40,7 +40,9 @@
#include "pwc-timon.h"
-const struct Timon_table_entry Timon_table[PSZ_MAX][6][4] =
+const unsigned int Timon_fps_vector[PWC_FPS_MAX_TIMON] = { 5, 10, 15, 20, 25,
30 };
+
+const struct Timon_table_entry Timon_table[PSZ_MAX][PWC_FPS_MAX_TIMON][4] =
{
/* SQCIF */
{
Index: pwc-kiara.c
===================================================================
--- pwc-kiara.c (revision 142)
+++ pwc-kiara.c (working copy)
@@ -42,6 +42,8 @@
#include "pwc-kiara.h"
#include "pwc-uncompress.h"
+const unsigned int Kiara_fps_vector[PWC_FPS_MAX_KIARA] = { 5, 10, 15, 20, 25,
30 };
+
const struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4] =
{
/* SQCIF */
Index: pwc-timon.h
===================================================================
--- pwc-timon.h (revision 142)
+++ pwc-timon.h (working copy)
@@ -44,6 +44,8 @@
#include "pwc-ioctl.h" /* for PSZ_MAX */
+#define PWC_FPS_MAX_TIMON 6
+
struct Timon_table_entry
{
char alternate; /* USB alternate interface */
@@ -52,10 +54,10 @@
unsigned char mode[13]; /* precomputed mode settings for cam */
};
-extern const struct Timon_table_entry Timon_table[PSZ_MAX][6][4];
+extern const struct Timon_table_entry
Timon_table[PSZ_MAX][PWC_FPS_MAX_TIMON][4];
extern const unsigned int TimonRomTable [16][2][16][8];
+extern const unsigned int Timon_fps_vector[PWC_FPS_MAX_TIMON];
-
#endif
Index: pwc-kiara.h
===================================================================
--- pwc-kiara.h (revision 142)
+++ pwc-kiara.h (working copy)
@@ -29,6 +29,8 @@
#include "pwc-ioctl.h"
+#define PWC_FPS_MAX_KIARA 6
+
struct Kiara_table_entry
{
char alternate; /* USB alternate interface */
@@ -37,8 +39,9 @@
unsigned char mode[12]; /* precomputed mode settings for cam */
};
-extern const struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4];
+extern const struct Kiara_table_entry
Kiara_table[PSZ_MAX][PWC_FPS_MAX_KIARA][4];
extern const unsigned int KiaraRomTable[8][2][16][8];
+extern const unsigned int Kiara_fps_vector[PWC_FPS_MAX_KIARA];
#endif
Index: pwc-ctrl.c
===================================================================
--- pwc-ctrl.c (revision 142)
+++ pwc-ctrl.c (working copy)
@@ -141,6 +141,8 @@
An alternate value of 0 means this mode is not available at all.
*/
+#define PWC_FPS_MAX_NALA 8
+
struct Nala_table_entry {
char alternate; /* USB alternate setting */
int compressed; /* Compressed yes/no */
@@ -148,7 +150,9 @@
unsigned char mode[3]; /* precomputed mode table */
};
-static struct Nala_table_entry Nala_table[PSZ_MAX][8] =
+static unsigned int Nala_fps_vector[PWC_FPS_MAX_NALA] = { 4, 5, 7, 10, 12, 15,
20, 24 };
+
+static struct Nala_table_entry Nala_table[PSZ_MAX][PWC_FPS_MAX_NALA] =
{
#include "pwc-nala.h"
};
@@ -424,6 +428,59 @@
return 0;
}
+static unsigned int pwc_get_fps_Nala(struct pwc_device *pdev, unsigned int
index, unsigned int size)
+{
+ unsigned int i;
+
+ for (i = 0; i < PWC_FPS_MAX_NALA; i++) {
+ if (Nala_table[size][i].alternate) {
+ if (index--==0) return Nala_fps_vector[i];
+ }
+ }
+ return 0;
+}
+
+static unsigned int pwc_get_fps_Kiara(struct pwc_device *pdev, unsigned int
index, unsigned int size)
+{
+ unsigned int i;
+
+ for (i = 0; i < PWC_FPS_MAX_KIARA; i++) {
+ if (Kiara_table[size][i][3].alternate) {
+ if (index--==0) return Kiara_fps_vector[i];
+ }
+ }
+ return 0;
+}
+
+static unsigned int pwc_get_fps_Timon(struct pwc_device *pdev, unsigned int
index, unsigned int size)
+{
+ unsigned int i;
+
+ for (i=0; i < PWC_FPS_MAX_TIMON; i++) {
+ if (Timon_table[size][i][3].alternate) {
+ if (index--==0) return Timon_fps_vector[i];
+ }
+ }
+ return 0;
+}
+
+unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned
int size)
+{
+ unsigned int ret;
+
+ if (DEVICE_USE_CODEC1(pdev->type)) {
+ ret = pwc_get_fps_Nala(pdev, index, size);
+
+ } else if (DEVICE_USE_CODEC3(pdev->type)) {
+ ret = pwc_get_fps_Kiara(pdev, index, size);
+
+ } else {
+ ret = pwc_get_fps_Timon(pdev, index, size);
+ }
+
+ return ret;
+}
+
#define BLACK_Y 0
#define BLACK_U 128
#define BLACK_V 128
Index: pwc-v4l.c
===================================================================
--- pwc-v4l.c (revision 142)
+++ pwc-v4l.c (working copy)
@@ -1224,7 +1224,65 @@
pwc_isoc_cleanup(pdev);
return 0;
}
-
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
+ case VIDIOC_ENUM_FRAMESIZES:
+ {
+ struct v4l2_frmsizeenum *fsize = arg;
+ unsigned int i = 0, index = fsize->index;
+
+ if (fsize->pixel_format == V4L2_PIX_FMT_YUV420) {
+ for (i = 0; i < PSZ_MAX; i++) {
+ if (pdev->image_mask & (1 << i)) {
+ if (!index--) {
+ fsize->type =
V4L2_FRMSIZE_TYPE_DISCRETE;
+ fsize->discrete.width =
pwc_image_sizes[i].x;
+ fsize->discrete.height
= pwc_image_sizes[i].y;
+ return 0;
+ }
+ }
+ }
+ } else if (fsize->index == 0 &&
+ ((fsize->pixel_format == V4L2_PIX_FMT_PWC1
&& DEVICE_USE_CODEC1(pdev->type)) ||
+ (fsize->pixel_format == V4L2_PIX_FMT_PWC2
&& DEVICE_USE_CODEC23(pdev->type)))) {
+
+ fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+ fsize->discrete.width = pdev->abs_max.x;
+ fsize->discrete.height = pdev->abs_max.y;
+ return 0;
+ }
+ return -EINVAL;
+ }
+
+ case VIDIOC_ENUM_FRAMEINTERVALS:
+ {
+ struct v4l2_frmivalenum *fival = arg;
+ int size = -1;
+ unsigned int i;
+
+ for (i = 0; i < PSZ_MAX; i++) {
+ if (pwc_image_sizes[i].x == fival->width &&
+ pwc_image_sizes[i].y == fival->height) {
+ size = i;
+ break;
+ }
+ }
+
+ // TODO: Support raw format
+ if (size < 0 || fival->pixel_format !=
V4L2_PIX_FMT_YUV420) {
+ return -EINVAL;
+ }
+
+ i = pwc_get_fps(pdev, fival->index, size);
+ if (!i) return -EINVAL;
+
+ fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
+ fival->discrete.numerator = 1;
+ fival->discrete.denominator = i;
+
+ return 0;
+ }
+#endif // >= 2.6.19
+
default:
return pwc_ioctl(pdev, cmd, arg);
} /* ..switch */
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/kernel.h>
#include <asm/types.h>
#include <linux/ioctl.h>
#include <linux/videodev2.h>
#include "uvc_compat.h"
static int xioctl( int fd, int request, void *arg )
{
int r;
do r = ioctl (fd, request, arg);
while (r == -1 && errno == EINTR);
return r;
};
int main( int argc, char *argv[] )
{
int fd;
if (argc < 2) return -1;
// open device
if ((fd = open (argv[1], O_RDWR)) < 0) {
fd = 0;
fprintf (stderr, "open (): %s\n", strerror(errno));
return -1;
}
fcntl (fd, F_SETFD, FD_CLOEXEC);
int index = 0, ret, ret2;
struct v4l2_frmsizeenum fsize;
memset (&fsize, 0, sizeof(fsize));
fsize.pixel_format = V4L2_PIX_FMT_YUV420;
fsize.index = 0;
struct v4l2_frmivalenum fival;
memset (&fival, 0, sizeof(fival));
do {
ret = xioctl (fd, VIDIOC_ENUM_FRAMESIZES, &fsize);
if (ret == 0 && fsize.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
printf ("%i: %ix%i: ", fsize.index, fsize.discrete.width, fsize.discrete.height);
fival.pixel_format = fsize.pixel_format;
fival.width = fsize.discrete.width;
fival.height = fsize.discrete.height;
fival.index = 0;
do {
ret2 = xioctl (fd, VIDIOC_ENUM_FRAMEINTERVALS, &fival);
if (ret2 == 0 && fival.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
printf ("%u/%u ", fival.discrete.numerator, fival.discrete.denominator);
}
fival.index++;
} while (ret2 == 0);
printf ("\n");
}
fsize.index++;
} while (ret==0);
close (fd);
return 0;
}
_______________________________________________
pwc mailing list
[email protected]
http://lists.saillard.org/mailman/listinfo/pwc