videotestsrc: Support video/x-bayer 10/12/14/16 bit depths

Add support for generation of 10/12/14/16 bit bayer test pattern.
The implementation is rather simplistic, just take the ARGB
input, generate 16-bit data out of it instead of 8-bit, shift
them as required by the output bitness, and apply endian swap.

Example usage:
```
$ gst-launch-1.0 videotestsrc ! \
    video/x-bayer,width=512,height=512,format=bggr12le ! \
    bayer2rgb ! \
    video/x-raw,format=RGBA64_LE ! \
    videoconvert ! \
    autovideosink
```

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4686>
This commit is contained in:
Marek Vasut 2023-05-19 20:44:33 +02:00
parent e569b8ba1e
commit 5ad834ce28
5 changed files with 98 additions and 11 deletions

View file

@ -15141,7 +15141,7 @@
"long-name": "Video test source",
"pad-templates": {
"src": {
"caps": "video/x-raw:\n format: { ABGR64_LE, BGRA64_LE, AYUV64, ARGB64_LE, ARGB64, RGBA64_LE, ABGR64_BE, BGRA64_BE, ARGB64_BE, RGBA64_BE, GBRA_12LE, GBRA_12BE, Y412_LE, Y412_BE, A444_10LE, GBRA_10LE, A444_10BE, GBRA_10BE, A422_10LE, A422_10BE, A420_10LE, A420_10BE, RGB10A2_LE, BGR10A2_LE, Y410, GBRA, ABGR, VUYA, BGRA, AYUV, ARGB, RGBA, A420, AV12, Y444_16LE, Y444_16BE, v216, P016_LE, P016_BE, Y444_12LE, GBR_12LE, Y444_12BE, GBR_12BE, I422_12LE, I422_12BE, Y212_LE, Y212_BE, I420_12LE, I420_12BE, P012_LE, P012_BE, Y444_10LE, GBR_10LE, Y444_10BE, GBR_10BE, r210, I422_10LE, I422_10BE, NV16_10LE32, Y210, v210, UYVP, I420_10LE, I420_10BE, P010_10LE, NV12_10LE32, NV12_10LE40, P010_10BE, NV12_10BE_8L128, Y444, RGBP, GBR, BGRP, NV24, xBGR, BGRx, xRGB, RGBx, BGR, IYU2, v308, RGB, Y42B, NV61, NV16, VYUY, UYVY, YVYU, YUY2, I420, YV12, NV21, NV12, NV12_8L128, NV12_64Z32, NV12_4L4, NV12_32L32, NV12_16L32S, Y41B, IYU1, YVU9, YUV9, RGB16, BGR16, RGB15, BGR15, RGB8P, GRAY16_LE, GRAY16_BE, GRAY10_LE32, GRAY8 }\n width: [ 1, 2147483647 ]\n height: [ 1, 2147483647 ]\n framerate: [ 0/1, 2147483647/1 ]\n multiview-mode: { (string)mono, (string)left, (string)right }\nvideo/x-bayer:\n format: { bggr, rggb, grbg, gbrg }\n width: [ 1, 2147483647 ]\n height: [ 1, 2147483647 ]\n framerate: [ 0/1, 2147483647/1 ]\n multiview-mode: { (string)mono, (string)left, (string)right }\n",
"caps": "video/x-raw:\n format: { ABGR64_LE, BGRA64_LE, AYUV64, ARGB64_LE, ARGB64, RGBA64_LE, ABGR64_BE, BGRA64_BE, ARGB64_BE, RGBA64_BE, GBRA_12LE, GBRA_12BE, Y412_LE, Y412_BE, A444_10LE, GBRA_10LE, A444_10BE, GBRA_10BE, A422_10LE, A422_10BE, A420_10LE, A420_10BE, RGB10A2_LE, BGR10A2_LE, Y410, GBRA, ABGR, VUYA, BGRA, AYUV, ARGB, RGBA, A420, AV12, Y444_16LE, Y444_16BE, v216, P016_LE, P016_BE, Y444_12LE, GBR_12LE, Y444_12BE, GBR_12BE, I422_12LE, I422_12BE, Y212_LE, Y212_BE, I420_12LE, I420_12BE, P012_LE, P012_BE, Y444_10LE, GBR_10LE, Y444_10BE, GBR_10BE, r210, I422_10LE, I422_10BE, NV16_10LE32, Y210, v210, UYVP, I420_10LE, I420_10BE, P010_10LE, NV12_10LE32, NV12_10LE40, P010_10BE, NV12_10BE_8L128, Y444, RGBP, GBR, BGRP, NV24, xBGR, BGRx, xRGB, RGBx, BGR, IYU2, v308, RGB, Y42B, NV61, NV16, VYUY, UYVY, YVYU, YUY2, I420, YV12, NV21, NV12, NV12_8L128, NV12_64Z32, NV12_4L4, NV12_32L32, NV12_16L32S, Y41B, IYU1, YVU9, YUV9, RGB16, BGR16, RGB15, BGR15, RGB8P, GRAY16_LE, GRAY16_BE, GRAY10_LE32, GRAY8 }\n width: [ 1, 2147483647 ]\n height: [ 1, 2147483647 ]\n framerate: [ 0/1, 2147483647/1 ]\n multiview-mode: { (string)mono, (string)left, (string)right }\nvideo/x-bayer:\n format: { bggr, rggb, grbg, gbrg, bggr10le, rggb10le, grbg10le, gbrg10le, bggr10be, rggb10be, grbg10be, gbrg10be, bggr12le, rggb12le, grbg12le, gbrg12le, bggr12be, rggb12be, grbg12be, gbrg12be, bggr14le, rggb14le, grbg14le, gbrg14le, bggr14be, rggb14be, grbg14be, gbrg14be, bggr16le, rggb16le, grbg16le, gbrg16le, bggr16be, rggb16be, grbg16be, gbrg16be }\n width: [ 1, 2147483647 ]\n height: [ 1, 2147483647 ]\n framerate: [ 0/1, 2147483647/1 ]\n multiview-mode: { (string)mono, (string)left, (string)right }\n",
"direction": "src",
"presence": "always"
}

View file

@ -89,11 +89,30 @@ enum
PROP_LAST
};
#define BAYER_CAPS_GEN(mask, bits, endian) \
" "#mask#bits#endian
#define VTS_VIDEO_CAPS GST_VIDEO_CAPS_MAKE (GST_VIDEO_FORMATS_ALL) "," \
#define BAYER_CAPS_ORD(bits, endian) \
BAYER_CAPS_GEN(bggr, bits, endian)"," \
BAYER_CAPS_GEN(rggb, bits, endian)"," \
BAYER_CAPS_GEN(grbg, bits, endian)"," \
BAYER_CAPS_GEN(gbrg, bits, endian)
#define BAYER_CAPS_BITS(bits) \
BAYER_CAPS_ORD(bits, le)"," \
BAYER_CAPS_ORD(bits, be)
#define BAYER_CAPS_ALL \
BAYER_CAPS_ORD(,)"," \
BAYER_CAPS_BITS(10)"," \
BAYER_CAPS_BITS(12)"," \
BAYER_CAPS_BITS(14)"," \
BAYER_CAPS_BITS(16)
#define VTS_VIDEO_CAPS GST_VIDEO_CAPS_MAKE (GST_VIDEO_FORMATS_ALL) "," \
"multiview-mode = { mono, left, right }" \
";" \
"video/x-bayer, format=(string) { bggr, rggb, grbg, gbrg }, " \
"video/x-bayer, format=(string) {" BAYER_CAPS_ALL " },"\
"width = " GST_VIDEO_SIZE_RANGE ", " \
"height = " GST_VIDEO_SIZE_RANGE ", " \
"framerate = " GST_VIDEO_FPS_RANGE ", " \
@ -826,6 +845,8 @@ gst_video_test_src_get_property (GObject * object, guint prop_id,
}
}
#define DIV_ROUND_UP(s,v) (((s) + ((v)-1)) / (v))
static gboolean
gst_video_test_src_parse_caps (const GstCaps * caps, GstVideoInfo * info,
GstVideoTestSrc * videotestsrc)
@ -834,7 +855,7 @@ gst_video_test_src_parse_caps (const GstCaps * caps, GstVideoInfo * info,
gboolean ret;
const GValue *framerate;
const gchar *str;
gint x_inv = 0, y_inv = 0;
gint x_inv = 0, y_inv = 0, bpp = 0, bigendian = 0;
GST_DEBUG ("parsing caps");
@ -868,14 +889,39 @@ gst_video_test_src_parse_caps (const GstCaps * caps, GstVideoInfo * info,
y_inv = 0;
} else
goto invalid_format;
if (strlen (str) == 4) { /* 8bit bayer */
bpp = 8;
} else if (strlen (str) == 8) { /* 10/12/14/16 le/be bayer */
bpp = (gint) g_ascii_strtoull (str + 4, NULL, 10);
if (bpp & 1) /* odd bpp bayer formats not supported */
goto invalid_format;
if (bpp < 10 || bpp > 16) /* bayer 10,12,14,16 only */
goto invalid_format;
if (g_str_has_suffix (str, "le"))
bigendian = 0;
else if (g_str_has_suffix (str, "be"))
bigendian = 1;
else
goto invalid_format;
} else
goto invalid_format;
if (bpp == 8)
info->finfo = gst_video_format_get_info (GST_VIDEO_FORMAT_GRAY8);
else if (bigendian)
info->finfo = gst_video_format_get_info (GST_VIDEO_FORMAT_GRAY16_BE);
else
info->finfo = gst_video_format_get_info (GST_VIDEO_FORMAT_GRAY16_LE);
}
videotestsrc->bayer = TRUE;
videotestsrc->bpp = bpp;
videotestsrc->x_invert = x_inv;
videotestsrc->y_invert = y_inv;
info->finfo = gst_video_format_get_info (GST_VIDEO_FORMAT_GRAY8);
info->stride[0] = GST_ROUND_UP_4 (info->width);
info->stride[0] = GST_ROUND_UP_4 (info->width) * DIV_ROUND_UP (bpp, 8);
info->size = info->stride[0] * info->height;
return ret;
@ -971,7 +1017,7 @@ gst_video_test_src_setcaps (GstBaseSrc * bsrc, GstCaps * caps)
goto parse_failed;
} else if (gst_structure_has_name (structure, "video/x-bayer")) {
if (!gst_video_test_src_parse_caps (caps, &info, &videotestsrc))
if (!gst_video_test_src_parse_caps (caps, &info, videotestsrc))
goto parse_failed;
} else {
goto unsupported_caps;

View file

@ -149,6 +149,7 @@ struct _GstVideoTestSrc {
GstVideoInfo info; /* protected by the object or stream lock */
GstVideoChromaResample *subsample;
gboolean bayer;
gint bpp;
gint x_invert;
gint y_invert;

View file

@ -158,7 +158,8 @@ static void paint_tmpline_ARGB (paintinfo * p, int x, int w);
static void paint_tmpline_AYUV (paintinfo * p, int x, int w);
static void convert_hline_generic (paintinfo * p, GstVideoFrame * frame, int y);
static void convert_hline_bayer (paintinfo * p, GstVideoFrame * frame, int y);
static void convert_hline_bayer8 (paintinfo * p, GstVideoFrame * frame, int y);
static void convert_hline_bayer16 (paintinfo * p, GstVideoFrame * frame, int y);
#define SCALEBITS 10
#define ONE_HALF (1 << (SCALEBITS - 1))
@ -208,7 +209,6 @@ videotestsrc_setup_paintinfo (GstVideoTestSrc * v, paintinfo * p, int w, int h)
GstVideoInfo *info = &v->info;
width = GST_VIDEO_INFO_WIDTH (info);
if (info->colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_BT601) {
p->colors = vts_colors_bt601_ycbcr_100;
} else {
@ -217,7 +217,10 @@ videotestsrc_setup_paintinfo (GstVideoTestSrc * v, paintinfo * p, int w, int h)
if (v->bayer) {
p->paint_tmpline = paint_tmpline_ARGB;
p->convert_tmpline = convert_hline_bayer;
if (v->bpp == 8)
p->convert_tmpline = convert_hline_bayer8;
else
p->convert_tmpline = convert_hline_bayer16;
} else {
p->convert_tmpline = convert_hline_generic;
if (GST_VIDEO_INFO_IS_RGB (info)) {
@ -236,6 +239,7 @@ videotestsrc_setup_paintinfo (GstVideoTestSrc * v, paintinfo * p, int w, int h)
p->x_offset = (v->horizontal_speed * v->n_frames) % width;
if (p->x_offset < 0)
p->x_offset += width;
p->bpp = v->bpp;
p->x_invert = v->x_invert;
p->y_invert = v->y_invert;
@ -1679,7 +1683,7 @@ convert_hline_generic (paintinfo * p, GstVideoFrame * frame, int y)
}
static void
convert_hline_bayer (paintinfo * p, GstVideoFrame * frame, int y)
convert_hline_bayer8 (paintinfo * p, GstVideoFrame * frame, int y)
{
int i;
guint8 *data = GST_VIDEO_FRAME_PLANE_DATA (frame, 0);
@ -1696,6 +1700,41 @@ convert_hline_bayer (paintinfo * p, GstVideoFrame * frame, int y)
}
}
static guint16
bayer_scale_and_swap (paintinfo * p, const GstVideoFormatInfo * finfo,
guint8 r8)
{
guint16 r16 = (r8 << (p->bpp - 8)) | (r8 >> (16 - p->bpp));
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
if (!GST_VIDEO_FORMAT_INFO_IS_LE (finfo))
r16 = GUINT16_SWAP_LE_BE (r16);
#else
if (GST_VIDEO_FORMAT_INFO_IS_LE (finfo))
r16 = GUINT16_SWAP_LE_BE (r16);
#endif
return r16;
}
static void
convert_hline_bayer16 (paintinfo * p, GstVideoFrame * frame, int y)
{
const GstVideoFormatInfo *finfo = frame->info.finfo;
guint8 *data = GST_VIDEO_FRAME_PLANE_DATA (frame, 0);
guint16 *R16 =
(guint16 *) (data + y * GST_VIDEO_FRAME_PLANE_STRIDE (frame, 0));
guint8 *argb = p->tmpline;
gint width = GST_VIDEO_FRAME_WIDTH (frame);
int x_inv = p->x_invert;
int y_inv = p->y_invert;
int y_offset = 1 - ((y ^ y_inv) & 1);
int i;
for (i = 0; i < width; i++) {
int x_offset = 2 - ((i ^ x_inv) & 1);
R16[i] = bayer_scale_and_swap (p, finfo, argb[4 * i + y_offset + x_offset]);
}
}
void
gst_video_test_src_pinwheel (GstVideoTestSrc * v, GstClockTime pts,
GstVideoFrame * frame)

View file

@ -42,6 +42,7 @@ struct paintinfo_struct
GstVideoChromaResample *subsample;
int x_offset;
int bpp;
int x_invert;
int y_invert;