summaryrefslogtreecommitdiff
path: root/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c
diff options
context:
space:
mode:
Diffstat (limited to 'v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c')
-rw-r--r--v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c72
1 files changed, 69 insertions, 3 deletions
diff --git a/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c b/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c
index ade797cd9..9b13a6b78 100644
--- a/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c
+++ b/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c
@@ -78,6 +78,8 @@ struct v4lconvert_data *v4lconvert_create(int fd)
for (j = 0; j < ARRAY_SIZE(supported_src_pixfmts); j++)
if (fmt.pixelformat == supported_src_pixfmts[j]) {
data->supported_src_formats |= 1 << j;
+ if (fmt.flags & V4L2_FMT_FLAG_UPSIDEDOWN)
+ data->format_needs_flip |= 1 << j;
break;
}
}
@@ -214,17 +216,55 @@ int v4lconvert_try_format(struct v4lconvert_data *data,
return 0;
}
+static int v4lconvert_needs_flip(struct v4lconvert_data *data,
+ const struct v4l2_format *src_fmt)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(supported_src_pixfmts); i++)
+ if (src_fmt->fmt.pix.pixelformat == supported_src_pixfmts[i] &&
+ (data->format_needs_flip & (1 << i)))
+ return 1;
+
+ return 0;
+}
+
+/* Is conversion necessary ? */
+int v4lconvert_needs_conversion(struct v4lconvert_data *data,
+ const struct v4l2_format *src_fmt, /* in */
+ const struct v4l2_format *dest_fmt) /* in */
+{
+ int i;
+
+ if(memcmp(src_fmt, dest_fmt, sizeof(*src_fmt)))
+ return 1; /* Formats differ */
+
+ if (!v4lconvert_needs_flip(data, src_fmt))
+ return 0; /* Formats identical and we don't need flip */
+
+ /* Formats are identical, but we need flip, do we support the dest_fmt? */
+ for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++)
+ if (supported_dst_pixfmts[i] == dest_fmt->fmt.pix.pixelformat)
+ break;
+
+ if (i == ARRAY_SIZE(supported_dst_pixfmts))
+ return 0; /* Needs flip but we cannot do it :( */
+ else
+ return 1; /* Needs flip and thus conversion */
+}
+
int v4lconvert_convert(struct v4lconvert_data *data,
const struct v4l2_format *src_fmt, /* in */
const struct v4l2_format *dest_fmt, /* in */
- unsigned char *src, int src_size, unsigned char *dest, int dest_size)
+ unsigned char *src, int src_size, unsigned char *_dest, int dest_size)
{
unsigned int header_width, header_height;
- int result, needed;
+ int result, needed, needs_flip = 0;
unsigned char *components[3];
+ unsigned char *dest = _dest;
/* Special case when no conversion is needed */
- if(!memcmp(src_fmt, dest_fmt, sizeof(*src_fmt))) {
+ if (!v4lconvert_needs_conversion(data, src_fmt, dest_fmt)) {
int to_copy = MIN(dest_size, src_size);
memcpy(dest, src, to_copy);
return to_copy;
@@ -251,6 +291,11 @@ int v4lconvert_convert(struct v4lconvert_data *data,
return -1;
}
+ if (v4lconvert_needs_flip(data, src_fmt)) {
+ needs_flip = 1;
+ dest = alloca(needed);
+ }
+
switch (src_fmt->fmt.pix.pixelformat) {
case V4L2_PIX_FMT_MJPEG:
case V4L2_PIX_FMT_JPEG:
@@ -455,6 +500,27 @@ int v4lconvert_convert(struct v4lconvert_data *data,
return -1;
}
+ if (needs_flip) {
+ /* Note dest is our temporary buffer to which our conversion was done and
+ _dest is the real dest! */
+
+ /* If the formats are identical no conversion has been done! */
+ if (dest_fmt->fmt.pix.pixelformat == src_fmt->fmt.pix.pixelformat)
+ dest = src;
+
+ switch (dest_fmt->fmt.pix.pixelformat) {
+ case V4L2_PIX_FMT_RGB24:
+ case V4L2_PIX_FMT_BGR24:
+ v4lconvert_flip_rgbbgr24(dest, _dest, dest_fmt->fmt.pix.width,
+ dest_fmt->fmt.pix.height);
+ break;
+ case V4L2_PIX_FMT_YUV420:
+ v4lconvert_flip_yuv420(dest, _dest, dest_fmt->fmt.pix.width,
+ dest_fmt->fmt.pix.height);
+ break;
+ }
+ }
+
return needed;
}