videolevels: support GRAY8 input
This commit is contained in:
parent
ff8376b9d2
commit
45bc0f24aa
@ -30,4 +30,5 @@ GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
|
|||||||
GST_VERSION_MINOR,
|
GST_VERSION_MINOR,
|
||||||
videoadjust,
|
videoadjust,
|
||||||
"Filters that apply transform from 16-bit to 8-bit video",
|
"Filters that apply transform from 16-bit to 8-bit video",
|
||||||
plugin_init, PACKAGE_VERSION, GST_LICENSE, PACKAGE_NAME, GST_PACKAGE_ORIGIN);
|
plugin_init, PACKAGE_VERSION, GST_LICENSE, PACKAGE_NAME,
|
||||||
|
GST_PACKAGE_ORIGIN);
|
||||||
|
|||||||
@ -75,7 +75,7 @@ static GstStaticPadTemplate gst_videolevels_src_template =
|
|||||||
GST_STATIC_PAD_TEMPLATE ("sink",
|
GST_STATIC_PAD_TEMPLATE ("sink",
|
||||||
GST_PAD_SINK,
|
GST_PAD_SINK,
|
||||||
GST_PAD_ALWAYS,
|
GST_PAD_ALWAYS,
|
||||||
GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ GRAY16_LE, GRAY16_BE }"))
|
GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ GRAY16_LE, GRAY16_BE, GRAY8 }"))
|
||||||
//";"
|
//";"
|
||||||
// "video/x-bayer,format=(string){bggr16,grbg16,gbrg16,rggb16},"
|
// "video/x-bayer,format=(string){bggr16,grbg16,gbrg16,rggb16},"
|
||||||
// "bpp=(int){10,12,14,16},endianness={1234,4321},"
|
// "bpp=(int){10,12,14,16},endianness={1234,4321},"
|
||||||
@ -136,6 +136,7 @@ static gboolean gst_videolevels_calculate_histogram (GstVideoLevels *
|
|||||||
videolevels, guint16 * data);
|
videolevels, guint16 * data);
|
||||||
static gboolean gst_videolevels_auto_adjust (GstVideoLevels * videolevels,
|
static gboolean gst_videolevels_auto_adjust (GstVideoLevels * videolevels,
|
||||||
guint16 * data);
|
guint16 * data);
|
||||||
|
static void gst_videolevels_check_passthrough (GstVideoLevels * videolevels);
|
||||||
|
|
||||||
/* setup debug */
|
/* setup debug */
|
||||||
GST_DEBUG_CATEGORY_STATIC (videolevels_debug);
|
GST_DEBUG_CATEGORY_STATIC (videolevels_debug);
|
||||||
@ -255,6 +256,7 @@ gst_videolevels_init (GstVideoLevels * videolevels)
|
|||||||
{
|
{
|
||||||
GST_DEBUG_OBJECT (videolevels, "init class instance");
|
GST_DEBUG_OBJECT (videolevels, "init class instance");
|
||||||
|
|
||||||
|
videolevels->passthrough = FALSE;
|
||||||
gst_videolevels_reset (videolevels);
|
gst_videolevels_reset (videolevels);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -385,8 +387,8 @@ gst_videolevels_transform_caps (GstBaseTransform * trans,
|
|||||||
|
|
||||||
if (direction == GST_PAD_SRC) {
|
if (direction == GST_PAD_SRC) {
|
||||||
newst =
|
newst =
|
||||||
gst_structure_from_string ("video/x-raw,format={GRAY16_LE,GRAY16_BE}",
|
gst_structure_from_string
|
||||||
NULL);
|
("video/x-raw,format={GRAY16_LE,GRAY16_BE,GRAY8}", NULL);
|
||||||
} else {
|
} else {
|
||||||
newst = gst_structure_from_string ("video/x-raw,format=GRAY8", NULL);
|
newst = gst_structure_from_string ("video/x-raw,format=GRAY8", NULL);
|
||||||
}
|
}
|
||||||
@ -428,8 +430,16 @@ gst_videolevels_set_info (GstVideoFilter * filter, GstCaps * incaps,
|
|||||||
memcpy (&levels->info_out, out_info, sizeof (GstVideoInfo));
|
memcpy (&levels->info_out, out_info, sizeof (GstVideoInfo));
|
||||||
|
|
||||||
s = gst_caps_get_structure (incaps, 0);
|
s = gst_caps_get_structure (incaps, 0);
|
||||||
if (!gst_structure_get_int (s, "bpp", &levels->bpp_in))
|
|
||||||
levels->bpp_in = 16;
|
if (levels->info_in.finfo->format == GST_VIDEO_FORMAT_GRAY8) {
|
||||||
|
levels->bpp_in = 8;
|
||||||
|
levels->nbins = 256;
|
||||||
|
} else {
|
||||||
|
if (!gst_structure_get_int (s, "bpp", &levels->bpp_in)) {
|
||||||
|
levels->bpp_in = 16;
|
||||||
|
}
|
||||||
|
levels->nbins = 4096;
|
||||||
|
}
|
||||||
g_assert (levels->bpp_in >= 1 && levels->bpp_in <= 16);
|
g_assert (levels->bpp_in >= 1 && levels->bpp_in <= 16);
|
||||||
|
|
||||||
res = gst_videolevels_calculate_lut (levels);
|
res = gst_videolevels_calculate_lut (levels);
|
||||||
@ -488,17 +498,32 @@ gst_videolevels_transform_frame (GstVideoFilter * filter,
|
|||||||
out_stride = GST_VIDEO_FRAME_PLANE_STRIDE (out_frame, 0);
|
out_stride = GST_VIDEO_FRAME_PLANE_STRIDE (out_frame, 0);
|
||||||
|
|
||||||
lut = videolevels->lookup_table;
|
lut = videolevels->lookup_table;
|
||||||
for (r = 0; r < in_frame->info.height; r++) {
|
if (videolevels->bpp_in > 8) {
|
||||||
guint16 *src = (guint16 *) in_data;
|
for (r = 0; r < in_frame->info.height; r++) {
|
||||||
guint8 *dst = out_data;
|
guint16 *src = (guint16 *) in_data;
|
||||||
|
guint8 *dst = out_data;
|
||||||
|
|
||||||
for (c = 0; c < in_frame->info.width; c++) {
|
for (c = 0; c < in_frame->info.width; c++) {
|
||||||
//GST_LOG_OBJECT (videolevels, "Converting pixel (%d, %d), %d->%d", c, r, *src, lut[*src]);
|
//GST_LOG_OBJECT (videolevels, "Converting pixel (%d, %d), %d->%d", c, r, *src, lut[*src]);
|
||||||
*dst++ = lut[*src++];
|
*dst++ = lut[*src++];
|
||||||
|
}
|
||||||
|
|
||||||
|
in_data += in_stride;
|
||||||
|
out_data += out_stride;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
for (r = 0; r < in_frame->info.height; r++) {
|
||||||
|
guint8 *src = (guint8 *) in_data;
|
||||||
|
guint8 *dst = out_data;
|
||||||
|
|
||||||
in_data += in_stride;
|
for (c = 0; c < in_frame->info.width; c++) {
|
||||||
out_data += out_stride;
|
//GST_LOG_OBJECT (videolevels, "Converting pixel (%d, %d), %d->%d", c, r, *src, lut[*src]);
|
||||||
|
*dst++ = lut[*src++];
|
||||||
|
}
|
||||||
|
|
||||||
|
in_data += in_stride;
|
||||||
|
out_data += out_stride;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_LOG_OBJECT (videolevels, "Processing took %" G_GINT64_FORMAT "ms",
|
GST_LOG_OBJECT (videolevels, "Processing took %" G_GINT64_FORMAT "ms",
|
||||||
@ -540,6 +565,7 @@ gst_videolevels_reset (GstVideoLevels * videolevels)
|
|||||||
videolevels->lower_pix_sat = 0.01f;
|
videolevels->lower_pix_sat = 0.01f;
|
||||||
videolevels->upper_pix_sat = 0.01f;
|
videolevels->upper_pix_sat = 0.01f;
|
||||||
|
|
||||||
|
/* if GRAY8, this will be set in set_info */
|
||||||
videolevels->nbins = 4096;
|
videolevels->nbins = 4096;
|
||||||
|
|
||||||
g_free (videolevels->histogram);
|
g_free (videolevels->histogram);
|
||||||
@ -549,6 +575,7 @@ gst_videolevels_reset (GstVideoLevels * videolevels)
|
|||||||
#define GINT_CLAMP(x, low, high) ((gint)(CLAMP((x),(low),(high))))
|
#define GINT_CLAMP(x, low, high) ((gint)(CLAMP((x),(low),(high))))
|
||||||
#define GUINT8_CLAMP(x, low, high) ((guint8)(CLAMP((x),(low),(high))))
|
#define GUINT8_CLAMP(x, low, high) ((guint8)(CLAMP((x),(low),(high))))
|
||||||
|
|
||||||
|
/* TODO: rename this, as this handles uint8_to_uint8 as well */
|
||||||
static void
|
static void
|
||||||
gst_videolevels_calculate_lut_uint16_to_uint8 (GstVideoLevels * videolevels,
|
gst_videolevels_calculate_lut_uint16_to_uint8 (GstVideoLevels * videolevels,
|
||||||
gint endianness)
|
gint endianness)
|
||||||
@ -569,10 +596,12 @@ gst_videolevels_calculate_lut_uint16_to_uint8 (GstVideoLevels * videolevels,
|
|||||||
g_object_notify_by_pspec (G_OBJECT (videolevels), properties[PROP_LOWIN]);
|
g_object_notify_by_pspec (G_OBJECT (videolevels), properties[PROP_LOWIN]);
|
||||||
}
|
}
|
||||||
if (videolevels->upper_input < 0 || videolevels->upper_input > max_in) {
|
if (videolevels->upper_input < 0 || videolevels->upper_input > max_in) {
|
||||||
videolevels->lower_input = max_in;
|
videolevels->upper_input = max_in;
|
||||||
g_object_notify_by_pspec (G_OBJECT (videolevels), properties[PROP_HIGHIN]);
|
g_object_notify_by_pspec (G_OBJECT (videolevels), properties[PROP_HIGHIN]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gst_videolevels_check_passthrough (videolevels);
|
||||||
|
|
||||||
low_in = videolevels->lower_input;
|
low_in = videolevels->lower_input;
|
||||||
high_in = videolevels->upper_input;
|
high_in = videolevels->upper_input;
|
||||||
|
|
||||||
@ -613,6 +642,11 @@ gst_videolevels_calculate_lut (GstVideoLevels * videolevels)
|
|||||||
case GST_VIDEO_FORMAT_UNKNOWN:
|
case GST_VIDEO_FORMAT_UNKNOWN:
|
||||||
/* no format set yet, don't do anything */
|
/* no format set yet, don't do anything */
|
||||||
break;
|
break;
|
||||||
|
case GST_VIDEO_FORMAT_GRAY8:
|
||||||
|
GST_LOG_OBJECT (videolevels, "Calculating lookup table uint8 -> uint8");
|
||||||
|
gst_videolevels_calculate_lut_uint16_to_uint8 (videolevels,
|
||||||
|
G_LITTLE_ENDIAN);
|
||||||
|
break;
|
||||||
case GST_VIDEO_FORMAT_GRAY16_LE:
|
case GST_VIDEO_FORMAT_GRAY16_LE:
|
||||||
GST_LOG_OBJECT (videolevels,
|
GST_LOG_OBJECT (videolevels,
|
||||||
"Calculating lookup table uint16le -> uint8");
|
"Calculating lookup table uint16le -> uint8");
|
||||||
@ -659,7 +693,6 @@ gst_videolevels_calculate_histogram (GstVideoLevels * videolevels,
|
|||||||
else
|
else
|
||||||
endianness = G_BYTE_ORDER;
|
endianness = G_BYTE_ORDER;
|
||||||
|
|
||||||
|
|
||||||
factor = (nbins - 1.0) / maxVal;
|
factor = (nbins - 1.0) / maxVal;
|
||||||
|
|
||||||
if (videolevels->histogram == NULL) {
|
if (videolevels->histogram == NULL) {
|
||||||
@ -674,17 +707,26 @@ gst_videolevels_calculate_histogram (GstVideoLevels * videolevels,
|
|||||||
memset (hist, 0, sizeof (gint) * nbins);
|
memset (hist, 0, sizeof (gint) * nbins);
|
||||||
|
|
||||||
GST_LOG_OBJECT (videolevels, "Calculating histogram");
|
GST_LOG_OBJECT (videolevels, "Calculating histogram");
|
||||||
if (endianness == G_BYTE_ORDER) {
|
if (videolevels->bpp_in > 8) {
|
||||||
for (r = 0; r < videolevels->info_in.height; r++) {
|
if (endianness == G_BYTE_ORDER) {
|
||||||
for (c = 0; c < videolevels->info_in.width; c++) {
|
for (r = 0; r < videolevels->info_in.height; r++) {
|
||||||
hist[GINT_CLAMP (data[c + r * stride / 2] * factor, 0, nbins - 1)]++;
|
for (c = 0; c < videolevels->info_in.width; c++) {
|
||||||
|
hist[GINT_CLAMP (data[c + r * stride / 2] * factor, 0, nbins - 1)]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (r = 0; r < videolevels->info_in.height; r++) {
|
||||||
|
for (c = 0; c < videolevels->info_in.width; c++) {
|
||||||
|
hist[GINT_CLAMP (GUINT16_FROM_BE (data[c +
|
||||||
|
r * stride / 2]) * factor, 0, nbins - 1)]++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
guint8 *data8 = (guint8 *) data;
|
||||||
for (r = 0; r < videolevels->info_in.height; r++) {
|
for (r = 0; r < videolevels->info_in.height; r++) {
|
||||||
for (c = 0; c < videolevels->info_in.width; c++) {
|
for (c = 0; c < videolevels->info_in.width; c++) {
|
||||||
hist[GINT_CLAMP (GUINT16_FROM_BE (data[c +
|
hist[GINT_CLAMP (data8[c + r * stride / 2] * factor, 0, nbins - 1)]++;
|
||||||
r * stride / 2]) * factor, 0, nbins - 1)]++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -747,3 +789,21 @@ gst_videolevels_auto_adjust (GstVideoLevels * videolevels, guint16 * data)
|
|||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_videolevels_check_passthrough (GstVideoLevels * levels)
|
||||||
|
{
|
||||||
|
gboolean passthrough;
|
||||||
|
if (levels->info_in.finfo->format == GST_VIDEO_FORMAT_GRAY8 &&
|
||||||
|
levels->lower_input == levels->lower_output &&
|
||||||
|
levels->upper_input == levels->upper_output) {
|
||||||
|
passthrough = TRUE;
|
||||||
|
} else {
|
||||||
|
passthrough = FALSE;
|
||||||
|
}
|
||||||
|
if (passthrough != levels->passthrough) {
|
||||||
|
levels->passthrough = passthrough;
|
||||||
|
gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (levels),
|
||||||
|
levels->passthrough);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -91,6 +91,8 @@ struct _GstVideoLevels
|
|||||||
gint * histogram;
|
gint * histogram;
|
||||||
|
|
||||||
guint64 last_auto_timestamp;
|
guint64 last_auto_timestamp;
|
||||||
|
|
||||||
|
gboolean passthrough;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstVideoLevelsClass
|
struct _GstVideoLevelsClass
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user