[PATCH RFC 1/6] libv4lconvert: SDR conversion from U8 to FLOAT

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Convert unsigned 8 to float 32 [-1 to +1], which is commonly
used format for baseband signals by SDR applications.

Some implementation changes done as suggested by Hans Verkuil,
Hans de Goede and Andy Walls.

Cc: Hans Verkuil <hverkuil@xxxxxxxxx>
Cc: Hans de Goede <hdegoede@xxxxxxxxxx>
Cc: Andy Walls <awalls@xxxxxxxxxxxxxxxx>
Signed-off-by: Antti Palosaari <crope@xxxxxx>
---
 contrib/freebsd/include/linux/videodev2.h |  4 ++
 include/linux/videodev2.h                 |  4 ++
 lib/libv4lconvert/libv4lconvert.c         | 77 +++++++++++++++++++++++++++++++
 3 files changed, 85 insertions(+)

diff --git a/contrib/freebsd/include/linux/videodev2.h b/contrib/freebsd/include/linux/videodev2.h
index 1fcfaeb..05cc19b 100644
--- a/contrib/freebsd/include/linux/videodev2.h
+++ b/contrib/freebsd/include/linux/videodev2.h
@@ -465,6 +465,10 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_SE401      v4l2_fourcc('S', '4', '0', '1') /* se401 janggu compressed rgb */
 #define V4L2_PIX_FMT_S5C_UYVY_JPG v4l2_fourcc('S', '5', 'C', 'I') /* S5C73M3 interleaved UYVY/JPEG */
 
+/* SDR */
+#define V4L2_PIX_FMT_SDR_FLOAT  v4l2_fourcc('D', 'F', '3', '2') /* float 32-bit */
+#define V4L2_PIX_FMT_SDR_U8     v4l2_fourcc('D', 'U', '0', '8') /* unsigned 8-bit */
+
 /*
  *	F O R M A T   E N U M E R A T I O N
  */
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 437f1b0..ba2a173 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -431,6 +431,10 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_SE401      v4l2_fourcc('S', '4', '0', '1') /* se401 janggu compressed rgb */
 #define V4L2_PIX_FMT_S5C_UYVY_JPG v4l2_fourcc('S', '5', 'C', 'I') /* S5C73M3 interleaved UYVY/JPEG */
 
+/* SDR */
+#define V4L2_PIX_FMT_SDR_FLOAT  v4l2_fourcc('D', 'F', '3', '2') /* float 32-bit */
+#define V4L2_PIX_FMT_SDR_U8     v4l2_fourcc('D', 'U', '0', '8') /* unsigned 8-bit */
+
 /*
  *	F O R M A T   E N U M E R A T I O N
  */
diff --git a/lib/libv4lconvert/libv4lconvert.c b/lib/libv4lconvert/libv4lconvert.c
index e2afc27..b7cc0e1 100644
--- a/lib/libv4lconvert/libv4lconvert.c
+++ b/lib/libv4lconvert/libv4lconvert.c
@@ -266,6 +266,10 @@ int v4lconvert_supported_dst_format(unsigned int pixelformat)
 {
 	int i;
 
+	/* only supported SDR destination format */
+	if (pixelformat == V4L2_PIX_FMT_SDR_FLOAT)
+		return 1;
+
 	for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++)
 		if (supported_dst_pixfmts[i].fmt == pixelformat)
 			break;
@@ -435,6 +439,32 @@ static int v4lconvert_do_try_format_uvc(struct v4lconvert_data *data,
 	return 0;
 }
 
+static int v4lconvert_do_try_format_sdr(struct v4lconvert_data *data,
+		struct v4l2_format *dest_fmt, struct v4l2_format *src_fmt)
+{
+	int i;
+	struct v4l2_format try_fmt;
+	static const unsigned int supported_src_pixfmts_sdr[] = {
+		V4L2_PIX_FMT_SDR_FLOAT,
+		V4L2_PIX_FMT_SDR_U8,
+	};
+
+	for (i = 0; i < ARRAY_SIZE(supported_src_pixfmts_sdr); i++) {
+		try_fmt = *dest_fmt;
+		try_fmt.fmt.pix.pixelformat = supported_src_pixfmts_sdr[i];
+		if (data->dev_ops->ioctl(data->dev_ops_priv, data->fd,
+				VIDIOC_TRY_FMT, &try_fmt))
+			continue;
+
+		if (try_fmt.fmt.pix.pixelformat != supported_src_pixfmts_sdr[i])
+			continue;
+	}
+
+	*src_fmt = try_fmt;
+
+	return 0;
+}
+
 static int v4lconvert_do_try_format(struct v4lconvert_data *data,
 		struct v4l2_format *dest_fmt, struct v4l2_format *src_fmt)
 {
@@ -445,6 +475,8 @@ static int v4lconvert_do_try_format(struct v4lconvert_data *data,
 
 	if (data->flags & V4LCONVERT_IS_UVC)
 		return v4lconvert_do_try_format_uvc(data, dest_fmt, src_fmt);
+	else if (dest_fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_SDR_FLOAT)
+		return v4lconvert_do_try_format_sdr(data, dest_fmt, src_fmt);
 
 	for (i = 0; i < ARRAY_SIZE(supported_src_pixfmts); i++) {
 		/* is this format supported? */
@@ -1293,6 +1325,43 @@ static int v4lconvert_convert_pixfmt(struct v4lconvert_data *data,
 	return result;
 }
 
+/* SDR format conversions */
+static int v4lconvert_convert_sdr(struct v4lconvert_data *data,
+		unsigned char *src, int src_size,
+		unsigned char *dest, int dest_size,
+		struct v4l2_format *fmt, unsigned int dest_pix_fmt)
+{
+	int i, dest_needed;
+	unsigned int src_pix_fmt = fmt->fmt.pix.pixelformat;
+	float *fptr = (float *) dest;
+
+	switch (src_pix_fmt) {
+	case V4L2_PIX_FMT_SDR_U8:
+		/* 8-bit unsigned to 32-bit float */
+		dest_needed = src_size * sizeof(float);
+		if (dest_size < dest_needed)
+			goto err_buf_too_small;
+
+		for (i = 0; i < src_size; i++)
+			*fptr++ = (*src++ - 127.5f) / 127.5f;
+		break;
+	default:
+		V4LCONVERT_ERR("Unknown src format in conversion\n");
+		errno = EINVAL;
+		return -1;
+	}
+
+	fmt->fmt.pix.pixelformat = dest_pix_fmt;
+
+	return dest_needed;
+
+err_buf_too_small:
+	V4LCONVERT_ERR("destination buffer too small (%d < %d)\n",
+			dest_size, dest_needed);
+	errno = EFAULT;
+	return -1;
+}
+
 int v4lconvert_convert(struct v4lconvert_data *data,
 		const struct v4l2_format *src_fmt,  /* in */
 		const struct v4l2_format *dest_fmt, /* in */
@@ -1310,6 +1379,14 @@ int v4lconvert_convert(struct v4lconvert_data *data,
 	struct v4l2_format my_src_fmt = *src_fmt;
 	struct v4l2_format my_dest_fmt = *dest_fmt;
 
+	/* SDR */
+	switch (my_dest_fmt.fmt.pix.pixelformat) {
+	case V4L2_PIX_FMT_SDR_FLOAT:
+		return v4lconvert_convert_sdr(data, src, src_size,
+				convert2_dest, convert2_dest_size,
+				&my_src_fmt, my_dest_fmt.fmt.pix.pixelformat);
+	}
+
 	processing = v4lprocessing_pre_processing(data->processing);
 	rotate90 = data->control_flags & V4LCONTROL_ROTATED_90_JPEG;
 	hflip = v4lcontrol_get_ctrl(data->control, V4LCONTROL_HFLIP);
-- 
1.8.4.2

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux