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 <hverk...@xs4all.nl>
Cc: Hans de Goede <hdego...@redhat.com>
Cc: Andy Walls <awa...@md.metrocast.net>
Signed-off-by: Antti Palosaari <cr...@iki.fi>
---
 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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to