Browse Source

Implement YUV preview

Martijn Braam 4 years ago
parent
commit
cd7cd8b177
4 changed files with 92 additions and 9 deletions
  1. 42 7
      main.c
  2. 1 1
      meson.build
  3. 46 1
      quickpreview.c
  4. 3 0
      quickpreview.h

+ 42 - 7
main.c

@@ -18,7 +18,7 @@
 #include <locale.h>
 #include "config.h"
 #include "ini.h"
-#include "quickdebayer.h"
+#include "quickpreview.h"
 
 #define NUM_CAMERAS 5
 
@@ -609,16 +609,48 @@ process_image(const int *p, int size)
 	static const float neutral[] = {1.0, 1.0, 1.0};
 	static uint16_t isospeed[] = {0};
 
+	/*
+	int sizing = -1;
+
+	switch(current.fmt) {
+		case V4L2_PIX_FMT_SBGGR8:
+		case V4L2_PIX_FMT_SGBRG8:
+		case V4L2_PIX_FMT_SGRBG8:
+		case V4L2_PIX_FMT_SRGGB8:
+			sizing = 1;
+			break;
+		case V4L2_PIX_FMT_UYVY:
+			sizing = 2;
+			break;
+	}
+	*/
+
 	// Only process preview frames when not capturing
 	if (capture == 0) {
-		if(current.width > 1280) {
+		if(current.width > 1920) {
 			skip = 3;
 		}
+		if(current.width > 1281) {
+			skip = 2;
+		}
 		pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, current.width / (skip*2), current.height / (skip*2));
 		pixels = gdk_pixbuf_get_pixels(pixbuf);
-		quick_debayer((const uint8_t *)p, pixels, current.fmt,
-			       current.width, current.height, skip,
-			       current.blacklevel);
+
+		switch(current.fmt) {
+			case V4L2_PIX_FMT_SBGGR8:
+			case V4L2_PIX_FMT_SGBRG8:
+			case V4L2_PIX_FMT_SGRBG8:
+			case V4L2_PIX_FMT_SRGGB8:
+				quick_debayer((const uint8_t *)p, pixels, current.fmt,
+						current.width, current.height, skip,
+						current.blacklevel);
+				break;
+			case V4L2_PIX_FMT_UYVY:
+			case V4L2_PIX_FMT_YUYV:
+				quick_yuv2rgb((const uint8_t *)p, pixels, current.fmt,
+						current.width, current.height, skip);
+				break;
+		}
 
 		if (current.rotate == 0) {
 			pixbufrot = pixbuf;
@@ -905,8 +937,8 @@ get_frame()
 			}
 			errno_exit("select");
 		} else if (r == 0) {
-			fprintf(stderr, "select timeout\\n");
-			exit(EXIT_FAILURE);
+			g_printerr("get_frame: select timeout\n");
+			return TRUE;
 		}
 
 		if (read_frame(current.video_fd)) {
@@ -991,6 +1023,9 @@ config_ini_handler(void *user, const char *section, const char *name,
 			} else if (strcmp(value, "GBRG8") == 0) {
 				cc->fmt = V4L2_PIX_FMT_SGBRG8;
 				cc->mbus = MEDIA_BUS_FMT_SGBRG8_1X8;
+			} else if (strcmp(value, "UYVY") == 0) {
+				cc->fmt = V4L2_PIX_FMT_UYVY;
+				cc->mbus = MEDIA_BUS_FMT_UYVY8_2X8;
 			} else {
 				g_printerr("Unsupported pixelformat %s\n", value);
 				exit(1);

+ 1 - 1
meson.build

@@ -15,7 +15,7 @@ configure_file(
   output: 'config.h',
   configuration: conf )
 
-executable('megapixels', 'main.c', 'ini.c', 'quickdebayer.c', resources, dependencies : [gtkdep, libm, tiff], install : true)
+executable('megapixels', 'main.c', 'ini.c', 'quickpreview.c', resources, dependencies : [gtkdep, libm, tiff], install : true)
 
 install_data(['data/org.postmarketos.Megapixels.desktop'],
              install_dir : get_option('datadir') / 'applications')

+ 46 - 1
quickdebayer.c → quickpreview.c

@@ -4,7 +4,7 @@
  */
 
 #include <linux/videodev2.h>
-#include "quickdebayer.h"
+#include "quickpreview.h"
 
 /* Linear -> sRGB lookup table */
 static const int srgb[] = {
@@ -82,3 +82,48 @@ void quick_debayer(const uint8_t *source, uint8_t *destination,
 		}
 	} while (i < input_size);
 }
+
+
+// YUV format to RGB, currently only extracts the Y channel for a grayscale preview
+void quick_yuv2rgb(const uint8_t *source, uint8_t *destination,
+		uint32_t pix_fmt, int width, int height, int skip)
+{
+	int stride = width * 2;
+	int pixelsize = 4;
+	int input_size = width * 2 * height;
+	int i = 0, j = 0;
+	int row_left = stride;
+	uint8_t Y1, Y2, U, V;
+	do {
+		switch (pix_fmt) {
+			case V4L2_PIX_FMT_UYVY:
+				Y1 = source[i+1];
+				Y2 = source[i+3];
+				U = source[i];
+				V = source[i+2];
+				break;
+			case V4L2_PIX_FMT_YUYV:
+				Y1 = source[i];
+				Y2 = source[i+2];
+				U = source[i+1];
+				V = source[i+3];
+				break;
+		}
+		destination[j] = Y1;
+		destination[j+1] = Y1;
+		destination[j+2] = Y1;
+		j += 3;
+		destination[j] = Y2;
+		destination[j+1] = Y2;
+		destination[j+2] = Y2;
+		j += 3;
+
+		i += pixelsize * skip * 2;
+		row_left -= (pixelsize * skip * 2);
+		if(row_left < (pixelsize * skip * 2)){
+			i = i + row_left;
+			row_left = width;
+			i = i + (stride * skip);
+		}
+	} while (i < input_size);
+}

+ 3 - 0
quickdebayer.h → quickpreview.h

@@ -3,3 +3,6 @@
 void quick_debayer(const uint8_t *source, uint8_t *destination,
 		   uint32_t pix_fmt, int width, int height, int skip,
 		   int blacklevel);
+
+void quick_yuv2rgb(const uint8_t *source, uint8_t *destination,
+		   uint32_t pix_fmt, int width, int height, int skip);