gst-plugin-linescan/common/genicampixelformat.h

248 lines
8.1 KiB
C

/* GStreamer
* Copyright (c) 2018 outside US, United States Government, Joshua M. Doe <oss@nvl.army.mil>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Suite 500,
* Boston, MA 02110-1335, USA.
*/
#define GST_GENICAM_PIXEL_FORMAT_MAKE_BAYER8(format) \
"video/x-bayer, " \
"format = (string) " format ", " \
"width = " GST_VIDEO_SIZE_RANGE ", " \
"height = " GST_VIDEO_SIZE_RANGE ", " \
"framerate = " GST_VIDEO_FPS_RANGE
#define GST_GENICAM_PIXEL_FORMAT_MAKE_BAYER16(format,endianness) \
"video/x-bayer, " \
"format = (string) " format ", " \
"endianness = (int) " endianness ", " \
"bpp = (int) {16, 14, 12, 10}, " \
"width = " GST_VIDEO_SIZE_RANGE ", " \
"height = " GST_VIDEO_SIZE_RANGE ", " \
"framerate = " GST_VIDEO_FPS_RANGE
typedef struct
{
const char *pixel_format;
int endianness;
const char *gst_caps_string;
int bpp;
int depth;
int row_multiple;
} GstGenicamPixelFormatInfo;
GstGenicamPixelFormatInfo gst_genicam_pixel_format_infos[] = {
{"Mono 8", 0, GST_VIDEO_CAPS_MAKE ("GRAY8"), 8, 8, 4}
,
{"Mono 10", G_LITTLE_ENDIAN, GST_VIDEO_CAPS_MAKE ("GRAY16_LE"), 10, 16, 4}
,
{"Mono 10", G_BIG_ENDIAN, GST_VIDEO_CAPS_MAKE ("GRAY16_BE"), 10, 16, 4}
,
{"Mono 12", G_LITTLE_ENDIAN, GST_VIDEO_CAPS_MAKE ("GRAY16_LE"), 12, 16, 4}
,
{"Mono 12", G_BIG_ENDIAN, GST_VIDEO_CAPS_MAKE ("GRAY16_BE"), 12, 16, 4}
,
{"Mono 14", G_LITTLE_ENDIAN, GST_VIDEO_CAPS_MAKE ("GRAY16_LE"), 14, 16, 4}
,
{"Mono 14", G_BIG_ENDIAN, GST_VIDEO_CAPS_MAKE ("GRAY16_BE"), 14, 16, 4}
,
{"Mono 16", G_LITTLE_ENDIAN, GST_VIDEO_CAPS_MAKE ("GRAY16_LE"), 16, 16, 4}
,
{"Mono 16", G_BIG_ENDIAN, GST_VIDEO_CAPS_MAKE ("GRAY16_BE"), 16, 16, 4}
,
{"BGRA 8 Packed", 0, GST_VIDEO_CAPS_MAKE ("BGRA"), 32, 32, 4}
,
{"YUV 422 Packed", 0, GST_VIDEO_CAPS_MAKE ("UYVY"), 16, 16, 4}
,
{"Bayer BG 8", 0, GST_GENICAM_PIXEL_FORMAT_MAKE_BAYER8 ("bggr"), 8, 8, 1}
,
{"Bayer GR 8", 0, GST_GENICAM_PIXEL_FORMAT_MAKE_BAYER8 ("grbg"), 8, 8, 1}
,
{"Bayer RG 8", 0, GST_GENICAM_PIXEL_FORMAT_MAKE_BAYER8 ("rggb"), 8, 8, 1}
,
{"Bayer GB 8", 0, GST_GENICAM_PIXEL_FORMAT_MAKE_BAYER8 ("gbrg"), 8, 8, 1}
,
//TODO: make sure we use standard caps strings for 16-bit Bayer
{"Bayer BG 10", 0, GST_GENICAM_PIXEL_FORMAT_MAKE_BAYER16 ("bggr16", "1234"), 10, 16, 1}
,
{"Bayer GR 10", 0, GST_GENICAM_PIXEL_FORMAT_MAKE_BAYER16 ("grbg16", "1234"), 10, 16, 1}
,
{"Bayer RG 10", 0, GST_GENICAM_PIXEL_FORMAT_MAKE_BAYER16 ("rggb16", "1234"), 10, 16, 1}
,
{"Bayer GB 10", 0, GST_GENICAM_PIXEL_FORMAT_MAKE_BAYER16 ("gbrg16", "1234"), 10, 16, 1}
,
{"Bayer BG 12", 0, GST_GENICAM_PIXEL_FORMAT_MAKE_BAYER16 ("bggr16", "1234"), 12, 16, 1}
,
{"Bayer GR 12", 0, GST_GENICAM_PIXEL_FORMAT_MAKE_BAYER16 ("grbg16", "1234"), 12, 16, 1}
,
{"Bayer RG 12", 0, GST_GENICAM_PIXEL_FORMAT_MAKE_BAYER16 ("rggb16", "1234"), 12, 16, 1}
,
{"Bayer GB 12", 0, GST_GENICAM_PIXEL_FORMAT_MAKE_BAYER16 ("gbrg16", "1234"), 12, 16, 1}
,
{"Bayer BG 14", 0, GST_GENICAM_PIXEL_FORMAT_MAKE_BAYER16 ("bggr16", "1234"), 14, 16, 1}
,
{"Bayer GR 14", 0, GST_GENICAM_PIXEL_FORMAT_MAKE_BAYER16 ("grbg16", "1234"), 14, 16, 1}
,
{"Bayer RG 14", 0, GST_GENICAM_PIXEL_FORMAT_MAKE_BAYER16 ("rggb16", "1234"), 14, 16, 1}
,
{"Bayer GB 14", 0, GST_GENICAM_PIXEL_FORMAT_MAKE_BAYER16 ("gbrg16", "1234"), 14, 16, 1}
,
{"Bayer BG 16", 0, GST_GENICAM_PIXEL_FORMAT_MAKE_BAYER16 ("bggr16", "1234"), 16, 16, 1}
,
{"Bayer GR 16", 0, GST_GENICAM_PIXEL_FORMAT_MAKE_BAYER16 ("grbg16", "1234"), 16, 16, 1}
,
{"Bayer RG 16", 0, GST_GENICAM_PIXEL_FORMAT_MAKE_BAYER16 ("rggb16", "1234"), 16, 16, 1}
,
{"Bayer GB 16", 0, GST_GENICAM_PIXEL_FORMAT_MAKE_BAYER16 ("gbrg16", "1234"), 16, 16, 1}
,
{"JPEG", 0, "image/jpeg", 8, 8, 1}
};
int strcmp_ignore_whitespace (const char *s1, const char *s2)
{
const char *p1 = s1, *p2 = s2;
while (TRUE) {
/* skip all whitespace characters in both strings */
while (g_ascii_isspace(*p1)) ++p1;
if (!*p1) break;
while (g_ascii_isspace(*p2)) ++p2;
if (!*p2) return 1;
if (*p2 > *p1) return -1;
if (*p1 > *p2) return 1;
++p1;
++p2;
}
if (*p2) return -1;
return 0;
}
static const GstGenicamPixelFormatInfo *
gst_genicam_pixel_format_get_info (const char *pixel_format, int endianness)
{
int i;
for (i = 0; i < G_N_ELEMENTS (gst_genicam_pixel_format_infos); i++) {
GstGenicamPixelFormatInfo *info = &gst_genicam_pixel_format_infos[i];
if (strcmp_ignore_whitespace (pixel_format, info->pixel_format) == 0 &&
(info->endianness == endianness || info->endianness == 0))
return info;
}
GST_WARNING ("PixelFormat '%s' is not supported", pixel_format);
return NULL;
}
static const char *
gst_genicam_pixel_format_to_caps_string (const char *pixel_format,
int endianness)
{
const GstGenicamPixelFormatInfo *info =
gst_genicam_pixel_format_get_info (pixel_format, endianness);
if (!info)
return NULL;
return info->gst_caps_string;
}
static const char *
gst_genicam_pixel_format_from_caps (const GstCaps * caps, int *endianness)
{
int i;
for (i = 0; i < G_N_ELEMENTS (gst_genicam_pixel_format_infos); i++) {
GstCaps *super_caps;
super_caps = gst_caps_from_string (gst_genicam_pixel_format_infos[i].gst_caps_string);
if (gst_caps_is_subset (caps, super_caps)) {
*endianness = gst_genicam_pixel_format_infos[i].endianness;
return gst_genicam_pixel_format_infos[i].pixel_format;
}
}
return NULL;
}
static int
gst_genicam_pixel_format_get_depth (const char *pixel_format,
int endianness)
{
const GstGenicamPixelFormatInfo *info =
gst_genicam_pixel_format_get_info (pixel_format, endianness);
if (!info)
return 0;
return info->depth;
}
static int
gst_genicam_pixel_format_get_stride (const char *pixel_format,
int endianness, int width)
{
return width * gst_genicam_pixel_format_get_depth (pixel_format,
endianness) / 8;
}
static GstCaps *
gst_genicam_pixel_format_caps_from_pixel_format (const char *pixel_format,
int endianness, int width, int height, int framerate_n, int framerate_d,
int par_n, int par_d)
{
const char *caps_string;
GstCaps *caps;
GstStructure *structure;
GST_DEBUG
("Trying to create caps from: %s, endianness=%d, %dx%d, fps=%d/%d, par=%d/%d",
pixel_format, endianness, width, height, framerate_n, framerate_d, par_n,
par_d);
caps_string =
gst_genicam_pixel_format_to_caps_string (pixel_format, endianness);
if (caps_string == NULL)
return NULL;
GST_DEBUG ("Got caps string: %s", caps_string);
structure = gst_structure_from_string (caps_string, NULL);
if (structure == NULL)
return NULL;
gst_structure_set (structure,
"width", G_TYPE_INT, width,
"height", G_TYPE_INT, height,
"framerate", GST_TYPE_FRACTION, framerate_n, framerate_d,
"pixel-aspect-ratio", GST_TYPE_FRACTION, par_n, par_d, NULL);
if (g_str_has_prefix (pixel_format, "Bayer")) {
const GstGenicamPixelFormatInfo *info = gst_genicam_pixel_format_get_info(pixel_format, endianness);
g_assert (info);
gst_structure_set(structure, "bpp", G_TYPE_INT, (gint)info->bpp, NULL);
}
caps = gst_caps_new_empty ();
gst_caps_append_structure (caps, structure);
caps = gst_caps_fixate (caps);
return caps;
}