videolevels: use more of the video library

But gst_video_format_get_component_depth is broken in 0.10.36, so manually
get bpp for now.
This commit is contained in:
Joshua M. Doe
2012-06-26 02:00:36 -04:00
parent a8a1f57fe3
commit af6cdbd8f1
3 changed files with 909 additions and 93 deletions

View File

@@ -43,8 +43,6 @@
#include <string.h>
#include <math.h>
#include <gst/video/video.h>
/* GstVideoLevels signals and args */
enum
{
@@ -78,28 +76,18 @@ GST_ELEMENT_DETAILS ("Video videolevels adjustment",
/* the capabilities of the inputs and outputs */
static GstStaticPadTemplate gst_videolevels_src_template =
GST_STATIC_PAD_TEMPLATE ("sink",
GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("video/x-raw-gray, "
"bpp = (int) [1, 16], "
"depth = (int) 16, "
"endianness = (int) {LITTLE_ENDIAN, BIG_ENDIAN}, "
"width = " GST_VIDEO_SIZE_RANGE ", "
"height = " GST_VIDEO_SIZE_RANGE ", "
"framerate = " GST_VIDEO_FPS_RANGE)
GST_STATIC_CAPS (GST_VIDEO_CAPS_GRAY16 ("BIG_ENDIAN") ";"
GST_VIDEO_CAPS_GRAY16 ("LITTLE_ENDIAN"))
);
static GstStaticPadTemplate gst_videolevels_sink_template =
GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("video/x-raw-gray, "
"bpp = (int) 8, "
"depth = (int) 8, "
"width = " GST_VIDEO_SIZE_RANGE ", "
"height = " GST_VIDEO_SIZE_RANGE ", "
"framerate = " GST_VIDEO_FPS_RANGE)
GST_STATIC_CAPS (GST_VIDEO_CAPS_GRAY8)
);
#define GST_TYPE_VIDEOLEVELS_AUTO (gst_videolevels_auto_get_type())
@@ -434,40 +422,29 @@ static gboolean
gst_videolevels_set_caps (GstBaseTransform * base, GstCaps * incaps,
GstCaps * outcaps)
{
GstVideoLevels *levels;
GstVideoLevels *levels = GST_VIDEOLEVELS (base);
GstStructure *structure;
gboolean res;
levels = GST_VIDEOLEVELS (base);
GST_DEBUG_OBJECT (levels,
"set_caps: in %" GST_PTR_FORMAT " out %" GST_PTR_FORMAT, incaps, outcaps);
GST_DEBUG_OBJECT (incaps, "incaps");
GST_DEBUG_OBJECT (outcaps, "outcaps");
/* retrieve caps info */
res = gst_video_format_parse_caps (incaps, &levels->format_in, &levels->width,
&levels->height);
res &= gst_video_format_parse_caps (outcaps, &levels->format_out, NULL, NULL);
/* retrieve input caps info */
/* FIXME: gst_video_format_get_component_depth is broken in 0.10.36
levels->bpp_in = gst_video_format_get_component_depth (levels->format_in, 0);
levels->bpp_out = gst_video_format_get_component_depth (levels->format_out, 0); */
structure = gst_caps_get_structure (incaps, 0);
res = gst_structure_get (structure,
"width", G_TYPE_INT, &levels->width,
"height", G_TYPE_INT, &levels->height,
"bpp", G_TYPE_INT, &levels->bpp_in,
"depth", G_TYPE_INT, &levels->depth_in,
"endianness", G_TYPE_INT, &levels->endianness_in, NULL);
if (!res)
return FALSE;
/* retrieve output bpp and depth */
res &= gst_structure_get_int (structure, "bpp", &levels->bpp_in);
structure = gst_caps_get_structure (outcaps, 0);
res = gst_structure_get (structure,
"bpp", G_TYPE_INT, &levels->bpp_out,
"depth", G_TYPE_INT, &levels->depth_out, NULL);
if (!res)
return FALSE;
levels->stride_in = GST_ROUND_UP_4 (levels->width * levels->depth_in / 8);
levels->stride_out = GST_ROUND_UP_4 (levels->width * levels->depth_out / 8);
res &= gst_structure_get_int (structure, "bpp", &levels->bpp_out);
if (!res) {
GST_ERROR_OBJECT (levels, "Failed to parse caps");
}
//gst_videolevels_calculate_tables (levels);
return res;
@@ -488,27 +465,14 @@ static gboolean
gst_videolevels_get_unit_size (GstBaseTransform * base, GstCaps * caps,
guint * size)
{
GstStructure *structure;
gint width;
gint height;
gint depth;
structure = gst_caps_get_structure (caps, 0);
/* get proposed caps width, height, and depth to determine frame size */
if (gst_structure_get_int (structure, "width", &width) &&
gst_structure_get_int (structure, "height", &height) &&
gst_structure_get_int (structure, "depth", &depth)) {
guint stride = GST_ROUND_UP_4 (width * depth / 8); /* need 4-byte alignment */
*size = stride * height;
GST_DEBUG ("Get unit size %dx%d, stride %u, %u bytes", width, height,
stride, *size);
return TRUE;
if (!gst_video_get_size_from_caps (caps, size)) {
GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL),
("Unable to determine frame size from caps"));
return FALSE;
}
GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL),
("Incomplete caps, some required field missing"));
return FALSE;
GST_DEBUG ("Frame size is %d bytes", *size);
return TRUE;
}
/**
@@ -542,12 +506,12 @@ gst_videolevels_transform (GstBaseTransform * base, GstBuffer * inbuf,
videolevels->auto_adjust = 0;
g_object_notify (G_OBJECT (videolevels), "auto");
} else if (videolevels->auto_adjust == 2) {
GST_DEBUG_OBJECT (videolevels, "Auto adjusting levels (every %d ns)",
videolevels->interval);
elapsed =
GST_CLOCK_DIFF (videolevels->last_auto_timestamp, inbuf->timestamp);
if (videolevels->last_auto_timestamp == GST_CLOCK_TIME_NONE
|| elapsed >= (GstClockTimeDiff) videolevels->interval || elapsed < 0) {
GST_DEBUG_OBJECT (videolevels, "Auto adjusting levels (%d ns since last)",
elapsed);
gst_videolevels_auto_adjust (videolevels, input);
videolevels->last_auto_timestamp = GST_BUFFER_TIMESTAMP (inbuf);
}
@@ -576,16 +540,10 @@ gst_videolevels_reset (GstVideoLevels * videolevels)
{
videolevels->width = 0;
videolevels->height = 0;
videolevels->stride_in = 0;
videolevels->format_in = GST_VIDEO_FORMAT_UNKNOWN;
videolevels->format_out = GST_VIDEO_FORMAT_UNKNOWN;
videolevels->bpp_in = 0;
videolevels->depth_in = 0;
videolevels->endianness_in = 0;
videolevels->stride_out = 0;
videolevels->bpp_out = 0;
videolevels->depth_out = 0;
videolevels->endianness_out = 0;
videolevels->lower_input = DEFAULT_PROP_LOWIN;
videolevels->upper_input = DEFAULT_PROP_HIGHIN;
@@ -670,13 +628,14 @@ gst_videolevels_calculate_tables (GstVideoLevels * videolevels)
#define GINT_CLAMP(x, low, high) ((gint)(CLAMP((x),(low),(high))))
#define GUINT8_CLAMP(x, low, high) ((guint8)(CLAMP((x),(low),(high))))
/* TODO: use orc */
/* TODO: use orc/lut */
void
gst_videolevels_convert_uint16le_to_uint8 (GstVideoLevels * videolevels,
guint16 * in, guint8 * out)
{
gint i;
const gint size = videolevels->stride_in / 2 * videolevels->height;
const gint size = gst_video_format_get_size (videolevels->format_out,
videolevels->width, videolevels->height);
gdouble m;
gdouble b;
const guint16 max_in = (1 << videolevels->bpp_in) - 1;
@@ -701,13 +660,14 @@ gst_videolevels_convert_uint16le_to_uint8 (GstVideoLevels * videolevels,
out[i] = GUINT8_CLAMP (m * GUINT16_FROM_LE (in[i]) + b, low_out, high_out);
}
/* TODO: use orc */
/* TODO: use orc/lut */
void
gst_videolevels_convert_uint16be_to_uint8 (GstVideoLevels * videolevels,
guint16 * in, guint8 * out)
{
gint i;
const gint size = videolevels->stride_in / 2 * videolevels->height;
const gint size = gst_video_format_get_size (videolevels->format_out,
videolevels->width, videolevels->height);
gdouble m;
gdouble b;
const guint16 max_in = (1 << videolevels->bpp_in) - 1;
@@ -746,10 +706,12 @@ gboolean
gst_videolevels_do_levels (GstVideoLevels * videolevels, gpointer indata,
gpointer outdata)
{
if (videolevels->endianness_in == G_LITTLE_ENDIAN)
if (videolevels->format_in == GST_VIDEO_FORMAT_GRAY16_LE)
gst_videolevels_convert_uint16le_to_uint8 (videolevels, indata, outdata);
else
else if (videolevels->format_in == GST_VIDEO_FORMAT_GRAY16_BE)
gst_videolevels_convert_uint16be_to_uint8 (videolevels, indata, outdata);
else
return FALSE;
return TRUE;
//guint8 * dst = outdata;
@@ -787,6 +749,18 @@ gst_videolevels_calculate_histogram (GstVideoLevels * videolevels,
gint r;
gint c;
gfloat factor;
gint stride = gst_video_format_get_row_stride (videolevels->format_in, 0,
videolevels->width);
gint endianness;
/* TODO: add gst_video_format_get_endianness to video library */
if (videolevels->format_in == GST_VIDEO_FORMAT_GRAY16_BE)
endianness = G_BIG_ENDIAN;
else if (videolevels->format_in == GST_VIDEO_FORMAT_GRAY16_LE)
endianness = G_LITTLE_ENDIAN;
else
endianness = G_BYTE_ORDER;
factor = nbins / (gfloat) (1 << videolevels->bpp_in);
@@ -801,29 +775,21 @@ gst_videolevels_calculate_histogram (GstVideoLevels * videolevels,
memset (hist, 0, sizeof (gint) * nbins);
GST_DEBUG ("Calculating histogram");
if (videolevels->endianness_in == G_BYTE_ORDER) {
if (endianness == G_BYTE_ORDER) {
for (r = 0; r < videolevels->height; r++) {
for (c = 0; c < videolevels->width; c++) {
/* GST_DEBUG ("(%d, %d) = %d, hist[%d] = %d", r, c, data [c + r * videolevels->stride_in / 2], GINT_CLAMP (data [c + r * videolevels->stride_in / 2] * factor, 0, nbins - 1),
hist [GINT_CLAMP (data [c + r * videolevels->stride_in / 2] * factor, 0, nbins - 1)] + 1);*/
hist[GINT_CLAMP (data[c + r * videolevels->stride_in / 2] * factor, 0,
nbins - 1)]++;
hist[GINT_CLAMP (data[c + r * stride / 2] * factor, 0, nbins - 1)]++;
}
}
} else {
for (r = 0; r < videolevels->height; r++) {
for (c = 0; c < videolevels->width; c++) {
hist[GINT_CLAMP (GUINT16_FROM_BE (data[c +
r * videolevels->stride_in / 2]) * factor, 0,
nbins - 1)]++;
r * stride / 2]) * factor, 0, nbins - 1)]++;
}
}
}
//for (r = 0; r < videolevels->nbins; r++ ) {
// GST_DEBUG ("hist[%5d] = %d",r, hist[r]);
//}
return TRUE;
}