|
@@ -1,7 +1,9 @@
|
|
|
-#include <stdint.h>
|
|
|
+#include <stdlib.h>
|
|
|
#include <linux/v4l2-subdev.h>
|
|
|
#include <strings.h>
|
|
|
+#include <assert.h>
|
|
|
#include "mode.h"
|
|
|
+#include "libmegapixels.h"
|
|
|
|
|
|
|
|
|
// TODO: The 16 bit formats are imported from millipixels and seem broken
|
|
@@ -10,131 +12,312 @@ static struct libmegapixels_modename mode_lut[] = {
|
|
|
.name = "unsupported",
|
|
|
.v4l_pixel_format = 0,
|
|
|
.media_bus_format = 0,
|
|
|
+ .bpc = 0,
|
|
|
+ .bpp = 0,
|
|
|
+ .cfa = LIBMEGAPIXELS_CFA_NONE,
|
|
|
},
|
|
|
{
|
|
|
.name = "BGGR8",
|
|
|
.v4l_pixel_format = V4L2_PIX_FMT_SBGGR8,
|
|
|
.media_bus_format = MEDIA_BUS_FMT_SBGGR8_1X8,
|
|
|
+ .bpc = 8,
|
|
|
+ .bpp = 8,
|
|
|
+ .cfa = LIBMEGAPIXELS_CFA_BGGR,
|
|
|
},
|
|
|
{
|
|
|
.name = "GBRG8",
|
|
|
.v4l_pixel_format = V4L2_PIX_FMT_SGBRG8,
|
|
|
.media_bus_format = MEDIA_BUS_FMT_SGBRG8_1X8,
|
|
|
+ .bpc = 8,
|
|
|
+ .bpp = 8,
|
|
|
+ .cfa = LIBMEGAPIXELS_CFA_GBRG,
|
|
|
},
|
|
|
{
|
|
|
.name = "GRBG8",
|
|
|
.v4l_pixel_format = V4L2_PIX_FMT_SGRBG8,
|
|
|
.media_bus_format = MEDIA_BUS_FMT_SGRBG8_1X8,
|
|
|
+ .bpc = 8,
|
|
|
+ .bpp = 8,
|
|
|
+ .cfa = LIBMEGAPIXELS_CFA_GRBG,
|
|
|
},
|
|
|
{
|
|
|
.name = "RGGB8",
|
|
|
.v4l_pixel_format = V4L2_PIX_FMT_SRGGB8,
|
|
|
.media_bus_format = MEDIA_BUS_FMT_SRGGB8_1X8,
|
|
|
+ .bpc = 8,
|
|
|
+ .bpp = 8,
|
|
|
+ .cfa = LIBMEGAPIXELS_CFA_RGGB,
|
|
|
},
|
|
|
{
|
|
|
.name = "BGGR10P",
|
|
|
.v4l_pixel_format = V4L2_PIX_FMT_SBGGR10P,
|
|
|
.media_bus_format = MEDIA_BUS_FMT_SBGGR10_1X10,
|
|
|
+ .bpc = 10,
|
|
|
+ .bpp = 10,
|
|
|
+ .cfa = LIBMEGAPIXELS_CFA_BGGR,
|
|
|
},
|
|
|
{
|
|
|
.name = "GBRG10P",
|
|
|
.v4l_pixel_format = V4L2_PIX_FMT_SGBRG10P,
|
|
|
.media_bus_format = MEDIA_BUS_FMT_SGBRG10_1X10,
|
|
|
+ .bpc = 10,
|
|
|
+ .bpp = 10,
|
|
|
+ .cfa = LIBMEGAPIXELS_CFA_GBRG,
|
|
|
},
|
|
|
{
|
|
|
.name = "GRBG10P",
|
|
|
.v4l_pixel_format = V4L2_PIX_FMT_SGRBG10P,
|
|
|
.media_bus_format = MEDIA_BUS_FMT_SGRBG10_1X10,
|
|
|
+ .bpc = 10,
|
|
|
+ .bpp = 10,
|
|
|
+ .cfa = LIBMEGAPIXELS_CFA_GRBG,
|
|
|
},
|
|
|
{
|
|
|
.name = "RGGB10P",
|
|
|
.v4l_pixel_format = V4L2_PIX_FMT_SRGGB10P,
|
|
|
.media_bus_format = MEDIA_BUS_FMT_SRGGB10_1X10,
|
|
|
+ .bpc = 10,
|
|
|
+ .bpp = 10,
|
|
|
+ .cfa = LIBMEGAPIXELS_CFA_RGGB,
|
|
|
},
|
|
|
{
|
|
|
.name = "BGGR10",
|
|
|
.v4l_pixel_format = V4L2_PIX_FMT_SBGGR10,
|
|
|
.media_bus_format = MEDIA_BUS_FMT_SBGGR10_1X10,
|
|
|
+ .bpc = 10,
|
|
|
+ .bpp = 10,
|
|
|
+ .cfa = LIBMEGAPIXELS_CFA_BGGR,
|
|
|
},
|
|
|
{
|
|
|
.name = "GBRG10",
|
|
|
.v4l_pixel_format = V4L2_PIX_FMT_SGBRG10,
|
|
|
.media_bus_format = MEDIA_BUS_FMT_SGBRG10_1X10,
|
|
|
+ .bpc = 10,
|
|
|
+ .bpp = 10,
|
|
|
+ .cfa = LIBMEGAPIXELS_CFA_GBRG,
|
|
|
},
|
|
|
{
|
|
|
.name = "GRBG10",
|
|
|
.v4l_pixel_format = V4L2_PIX_FMT_SGRBG10,
|
|
|
.media_bus_format = MEDIA_BUS_FMT_SGRBG10_1X10,
|
|
|
+ .bpc = 10,
|
|
|
+ .bpp = 10,
|
|
|
+ .cfa = LIBMEGAPIXELS_CFA_GRBG,
|
|
|
},
|
|
|
{
|
|
|
.name = "RGGB10",
|
|
|
.v4l_pixel_format = V4L2_PIX_FMT_SRGGB10,
|
|
|
.media_bus_format = MEDIA_BUS_FMT_SRGGB10_1X10,
|
|
|
+ .bpc = 10,
|
|
|
+ .bpp = 10,
|
|
|
+ .cfa = LIBMEGAPIXELS_CFA_RGGB,
|
|
|
},
|
|
|
{
|
|
|
.name = "BGGR16",
|
|
|
.v4l_pixel_format = V4L2_PIX_FMT_SBGGR16,
|
|
|
.media_bus_format = MEDIA_BUS_FMT_SBGGR10_1X10,
|
|
|
+ .bpc = 10,
|
|
|
+ .bpp = 10,
|
|
|
+ .cfa = LIBMEGAPIXELS_CFA_BGGR,
|
|
|
},
|
|
|
{
|
|
|
.name = "GBRG16",
|
|
|
.v4l_pixel_format = V4L2_PIX_FMT_SGBRG16,
|
|
|
.media_bus_format = MEDIA_BUS_FMT_SGBRG10_1X10,
|
|
|
+ .bpc = 10,
|
|
|
+ .bpp = 10,
|
|
|
+ .cfa = LIBMEGAPIXELS_CFA_GBRG,
|
|
|
},
|
|
|
{
|
|
|
.name = "GRBG16",
|
|
|
.v4l_pixel_format = V4L2_PIX_FMT_SGRBG16,
|
|
|
.media_bus_format =MEDIA_BUS_FMT_SGRBG10_1X10,
|
|
|
+ .bpc = 10,
|
|
|
+ .bpp = 10,
|
|
|
+ .cfa = LIBMEGAPIXELS_CFA_GRBG,
|
|
|
},
|
|
|
{
|
|
|
.name = "RGGB16",
|
|
|
.v4l_pixel_format = V4L2_PIX_FMT_SRGGB16,
|
|
|
.media_bus_format = MEDIA_BUS_FMT_SRGGB10_1X10,
|
|
|
+ .bpc = 10,
|
|
|
+ .bpp = 10,
|
|
|
+ .cfa = LIBMEGAPIXELS_CFA_RGGB,
|
|
|
},
|
|
|
{
|
|
|
.name = "UYVY",
|
|
|
.v4l_pixel_format = V4L2_PIX_FMT_UYVY,
|
|
|
.media_bus_format = MEDIA_BUS_FMT_UYVY8_2X8,
|
|
|
+ .bpc = 8,
|
|
|
+ .bpp = 16,
|
|
|
+ .cfa = LIBMEGAPIXELS_CFA_NONE,
|
|
|
},
|
|
|
{
|
|
|
.name = "YUYV",
|
|
|
.v4l_pixel_format = V4L2_PIX_FMT_YUYV,
|
|
|
.media_bus_format = MEDIA_BUS_FMT_YUYV8_2X8,
|
|
|
+ .bpc = 8,
|
|
|
+ .bpp = 16,
|
|
|
+ .cfa = LIBMEGAPIXELS_CFA_NONE,
|
|
|
},
|
|
|
};
|
|
|
|
|
|
-uint32_t
|
|
|
-format_name_to_v4l_pixfmt(const char *name)
|
|
|
+int
|
|
|
+libmegapixels_format_name_to_index(const char *name)
|
|
|
{
|
|
|
int count = sizeof(mode_lut) / sizeof(mode_lut[0]);
|
|
|
for (int i = 0; i < count; i++) {
|
|
|
if (strcasecmp(mode_lut[i].name, name) == 0) {
|
|
|
- return mode_lut[i].v4l_pixel_format;
|
|
|
+ return i;
|
|
|
}
|
|
|
}
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
uint32_t
|
|
|
-format_name_to_media_busfmt(const char *name)
|
|
|
+libmegapixels_format_to_v4l_pixfmt(int index)
|
|
|
+{
|
|
|
+ return mode_lut[index].v4l_pixel_format;
|
|
|
+}
|
|
|
+
|
|
|
+uint32_t
|
|
|
+libmegapixels_format_to_media_busfmt(int index)
|
|
|
+{
|
|
|
+ return mode_lut[index].media_bus_format;
|
|
|
+}
|
|
|
+
|
|
|
+int
|
|
|
+libmegapixels_v4l_pixfmt_to_index(uint32_t pixfmt)
|
|
|
{
|
|
|
int count = sizeof(mode_lut) / sizeof(mode_lut[0]);
|
|
|
for (int i = 0; i < count; i++) {
|
|
|
- if (strcasecmp(mode_lut[i].name, name) == 0) {
|
|
|
- return mode_lut[i].media_bus_format;
|
|
|
+ if (mode_lut[i].v4l_pixel_format == pixfmt) {
|
|
|
+ return i;
|
|
|
}
|
|
|
}
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-struct libmegapixels_modename *
|
|
|
-v4l_pixfmt_to_mode(uint32_t pixfmt)
|
|
|
+char *
|
|
|
+libmegapixels_v4l_pixfmt_to_string(uint32_t pixfmt)
|
|
|
{
|
|
|
int count = sizeof(mode_lut) / sizeof(mode_lut[0]);
|
|
|
for (int i = 0; i < count; i++) {
|
|
|
if (mode_lut[i].v4l_pixel_format == pixfmt) {
|
|
|
- return &mode_lut[i];
|
|
|
+ return mode_lut[i].name;
|
|
|
}
|
|
|
}
|
|
|
- return 0;
|
|
|
+ return "unknown";
|
|
|
+}
|
|
|
+
|
|
|
+// mp_pixel_format_bits_per_pixel
|
|
|
+uint32_t
|
|
|
+libmegapixels_format_bits_per_pixel(int format)
|
|
|
+{
|
|
|
+ return mode_lut[format].bpp;
|
|
|
+}
|
|
|
+
|
|
|
+const char *
|
|
|
+libmegapixels_format_cfa_pattern(int format)
|
|
|
+{
|
|
|
+ switch (mode_lut[format].cfa) {
|
|
|
+ case LIBMEGAPIXELS_CFA_BGGR:
|
|
|
+ return "\002\001\001\000";
|
|
|
+ case LIBMEGAPIXELS_CFA_GBRG:
|
|
|
+ return "\001\002\000\001";
|
|
|
+ case LIBMEGAPIXELS_CFA_GRBG:
|
|
|
+ return "\001\000\002\001";
|
|
|
+ case LIBMEGAPIXELS_CFA_RGGB:
|
|
|
+ return "\000\001\001\002";
|
|
|
+ default:
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// mp_pixel_format_width_to_bytes
|
|
|
+uint32_t
|
|
|
+libmegapixels_mode_width_to_bytes(int index, uint32_t width)
|
|
|
+{
|
|
|
+ uint32_t bits_per_pixel = mode_lut[index].bpp;
|
|
|
+ uint64_t bits_per_width = width * (uint64_t) bits_per_pixel;
|
|
|
+ uint64_t remainder = bits_per_width % 8;
|
|
|
+ if (remainder == 0)
|
|
|
+ return bits_per_width / 8;
|
|
|
+
|
|
|
+ return (bits_per_width + 8 - remainder) / 8;
|
|
|
+}
|
|
|
+
|
|
|
+uint32_t
|
|
|
+libmegapixels_mode_width_to_padding(int index, uint32_t width)
|
|
|
+{
|
|
|
+ uint64_t bytes_per_width = libmegapixels_mode_width_to_bytes(index, width);
|
|
|
+ uint64_t remainder = bytes_per_width % 8;
|
|
|
+ if (remainder == 0)
|
|
|
+ return remainder;
|
|
|
+
|
|
|
+ return 8 - remainder;
|
|
|
+}
|
|
|
+
|
|
|
+uint32_t
|
|
|
+libmegapixels_mode_raw_width_to_width(int index, uint32_t width)
|
|
|
+{
|
|
|
+ switch (mode_lut[index].v4l_pixel_format) {
|
|
|
+ case V4L2_PIX_FMT_SBGGR8:
|
|
|
+ case V4L2_PIX_FMT_SGBRG8:
|
|
|
+ case V4L2_PIX_FMT_SGRBG8:
|
|
|
+ case V4L2_PIX_FMT_SRGGB8:
|
|
|
+ return width / 2;
|
|
|
+ case V4L2_PIX_FMT_SBGGR10P:
|
|
|
+ case V4L2_PIX_FMT_SGBRG10P:
|
|
|
+ case V4L2_PIX_FMT_SGRBG10P:
|
|
|
+ case V4L2_PIX_FMT_SRGGB10P:
|
|
|
+ return width / 2 * 5;
|
|
|
+ case V4L2_PIX_FMT_UYVY:
|
|
|
+ case V4L2_PIX_FMT_YUYV:
|
|
|
+ return width;
|
|
|
+ default:
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+uint32_t
|
|
|
+libmegapixels_mode_raw_height_to_height(int index, uint32_t height)
|
|
|
+{
|
|
|
+ switch (mode_lut[index].v4l_pixel_format) {
|
|
|
+ case V4L2_PIX_FMT_SBGGR8:
|
|
|
+ case V4L2_PIX_FMT_SGBRG8:
|
|
|
+ case V4L2_PIX_FMT_SGRBG8:
|
|
|
+ case V4L2_PIX_FMT_SRGGB8:
|
|
|
+ case V4L2_PIX_FMT_SBGGR10P:
|
|
|
+ case V4L2_PIX_FMT_SGBRG10P:
|
|
|
+ case V4L2_PIX_FMT_SGRBG10P:
|
|
|
+ case V4L2_PIX_FMT_SRGGB10P:
|
|
|
+ return height / 2;
|
|
|
+ case V4L2_PIX_FMT_UYVY:
|
|
|
+ case V4L2_PIX_FMT_YUYV:
|
|
|
+ return height;
|
|
|
+ default:
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+int
|
|
|
+libmegapixels_mode_equals(libmegapixels_mode *a, libmegapixels_mode *b)
|
|
|
+{
|
|
|
+ if (a == NULL || b == NULL) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ if (a->width != b->width) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ if (a->height != b->height) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ if (a->rate != b->rate) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ if (a->format != b->format) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ return 1;
|
|
|
}
|