mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-22 16:26:39 +00:00
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:
parent
e569b8ba1e
commit
5ad834ce28
5 changed files with 98 additions and 11 deletions
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -89,11 +89,30 @@ enum
|
|||
PROP_LAST
|
||||
};
|
||||
|
||||
#define BAYER_CAPS_GEN(mask, bits, endian) \
|
||||
" "#mask#bits#endian
|
||||
|
||||
#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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -42,6 +42,7 @@ struct paintinfo_struct
|
|||
GstVideoChromaResample *subsample;
|
||||
int x_offset;
|
||||
|
||||
int bpp;
|
||||
int x_invert;
|
||||
int y_invert;
|
||||
|
||||
|
|
Loading…
Reference in a new issue