gamma: Use libgstvideo for format specific values and make gamma processing more generic

Allows us to easily add support for new color formats later.
This commit is contained in:
Sebastian Dröge 2010-04-17 18:13:46 +02:00
parent 18273152b3
commit 155e48fb90
2 changed files with 47 additions and 27 deletions

View file

@ -89,7 +89,6 @@ static gboolean gst_gamma_set_caps (GstBaseTransform * base, GstCaps * incaps,
static GstFlowReturn gst_gamma_transform_ip (GstBaseTransform * transform, static GstFlowReturn gst_gamma_transform_ip (GstBaseTransform * transform,
GstBuffer * buf); GstBuffer * buf);
static void gst_gamma_planar411_ip (GstGamma * gamma, guint8 * data, gint size);
static void gst_gamma_calculate_tables (GstGamma * gamma); static void gst_gamma_calculate_tables (GstGamma * gamma);
GST_BOILERPLATE (GstGamma, gst_gamma, GstVideoFilter, GST_TYPE_VIDEO_FILTER); GST_BOILERPLATE (GstGamma, gst_gamma, GstVideoFilter, GST_TYPE_VIDEO_FILTER);
@ -197,45 +196,54 @@ gst_gamma_calculate_tables (GstGamma * gamma)
} }
} }
/* Useful macros */ static void
#define GST_VIDEO_I420_Y_ROWSTRIDE(width) (GST_ROUND_UP_4(width)) gst_gamma_planar_ip (GstGamma * gamma, guint8 * data)
#define GST_VIDEO_I420_U_ROWSTRIDE(width) (GST_ROUND_UP_8(width)/2) {
#define GST_VIDEO_I420_V_ROWSTRIDE(width) ((GST_ROUND_UP_8(GST_VIDEO_I420_Y_ROWSTRIDE(width)))/2) gint size;
#define GST_VIDEO_I420_Y_OFFSET(w,h) (0) data =
#define GST_VIDEO_I420_U_OFFSET(w,h) (GST_VIDEO_I420_Y_OFFSET(w,h)+(GST_VIDEO_I420_Y_ROWSTRIDE(w)*GST_ROUND_UP_2(h))) data + gst_video_format_get_component_offset (gamma->format, 0,
#define GST_VIDEO_I420_V_OFFSET(w,h) (GST_VIDEO_I420_U_OFFSET(w,h)+(GST_VIDEO_I420_U_ROWSTRIDE(w)*GST_ROUND_UP_2(h)/2)) gamma->width, gamma->height);
#define GST_VIDEO_I420_SIZE(w,h) (GST_VIDEO_I420_V_OFFSET(w,h)+(GST_VIDEO_I420_V_ROWSTRIDE(w)*GST_ROUND_UP_2(h)/2)) size =
gst_video_format_get_row_stride (gamma->format, 0,
gamma->width) * gst_video_format_get_component_height (gamma->format, 0,
gamma->height);
oil_tablelookup_u8 (data, 1, data, 1, gamma->gamma_table, 1, size);
}
static gboolean static gboolean
gst_gamma_set_caps (GstBaseTransform * base, GstCaps * incaps, gst_gamma_set_caps (GstBaseTransform * base, GstCaps * incaps,
GstCaps * outcaps) GstCaps * outcaps)
{ {
GstGamma *gamma = GST_GAMMA (base); GstGamma *gamma = GST_GAMMA (base);
GstStructure *structure;
gboolean res;
GST_DEBUG_OBJECT (gamma, GST_DEBUG_OBJECT (gamma,
"setting caps: in %" GST_PTR_FORMAT " out %" GST_PTR_FORMAT, incaps, "setting caps: in %" GST_PTR_FORMAT " out %" GST_PTR_FORMAT, incaps,
outcaps); outcaps);
structure = gst_caps_get_structure (incaps, 0); if (!gst_video_format_parse_caps (incaps, &gamma->format, &gamma->width,
&gamma->height))
goto invalid_caps;
res = gst_structure_get_int (structure, "width", &gamma->width); gamma->size =
res &= gst_structure_get_int (structure, "height", &gamma->height); gst_video_format_get_size (gamma->format, gamma->width, gamma->height);
if (!res)
goto done;
gamma->size = GST_VIDEO_I420_SIZE (gamma->width, gamma->height); switch (gamma->format) {
case GST_VIDEO_FORMAT_I420:
case GST_VIDEO_FORMAT_YV12:
gamma->process = gst_gamma_planar_ip;
break;
default:
goto invalid_caps;
break;
}
done: return TRUE;
return res;
}
static void invalid_caps:
gst_gamma_planar411_ip (GstGamma * gamma, guint8 * data, gint size) GST_ERROR_OBJECT (gamma, "Invalid caps: %" GST_PTR_FORMAT, incaps);
{ return FALSE;
oil_tablelookup_u8 (data, 1, data, 1, gamma->gamma_table, 1, size);
} }
static GstFlowReturn static GstFlowReturn
@ -246,6 +254,9 @@ gst_gamma_transform_ip (GstBaseTransform * base, GstBuffer * outbuf)
guint size; guint size;
GstClockTime timestamp, stream_time; GstClockTime timestamp, stream_time;
if (!gamma->process)
goto not_negotiated;
timestamp = GST_BUFFER_TIMESTAMP (outbuf); timestamp = GST_BUFFER_TIMESTAMP (outbuf);
stream_time = stream_time =
gst_segment_to_stream_time (&base->segment, GST_FORMAT_TIME, timestamp); gst_segment_to_stream_time (&base->segment, GST_FORMAT_TIME, timestamp);
@ -266,8 +277,7 @@ gst_gamma_transform_ip (GstBaseTransform * base, GstBuffer * outbuf)
goto wrong_size; goto wrong_size;
GST_OBJECT_LOCK (gamma); GST_OBJECT_LOCK (gamma);
gst_gamma_planar411_ip (gamma, data, gamma->process (gamma, data);
gamma->height * GST_VIDEO_I420_Y_ROWSTRIDE (gamma->width));
GST_OBJECT_UNLOCK (gamma); GST_OBJECT_UNLOCK (gamma);
done: done:
@ -280,6 +290,11 @@ wrong_size:
(NULL), ("Invalid buffer size %d, expected %d", size, gamma->size)); (NULL), ("Invalid buffer size %d, expected %d", size, gamma->size));
return GST_FLOW_ERROR; return GST_FLOW_ERROR;
} }
not_negotiated:
{
GST_ERROR_OBJECT (gamma, "Not negotiated yet");
return GST_FLOW_NOT_NEGOTIATED;
}
} }
static gboolean static gboolean

View file

@ -24,6 +24,8 @@
#ifndef __GST_VIDEO_GAMMA_H__ #ifndef __GST_VIDEO_GAMMA_H__
#define __GST_VIDEO_GAMMA_H__ #define __GST_VIDEO_GAMMA_H__
#include <gst/gst.h>
#include <gst/video/video.h>
#include <gst/video/gstvideofilter.h> #include <gst/video/gstvideofilter.h>
G_BEGIN_DECLS G_BEGIN_DECLS
@ -52,15 +54,18 @@ struct _GstGamma
GstVideoFilter videofilter; GstVideoFilter videofilter;
/* format */ /* format */
GstVideoFormat format;
gint width; gint width;
gint height; gint height;
gint size; gint size;
/* properties */ /* properties */
double gamma; gdouble gamma;
/* tables */ /* tables */
guint8 gamma_table[256]; guint8 gamma_table[256];
void (*process) (GstGamma *gamma, guint8 *data);
}; };
struct _GstGammaClass struct _GstGammaClass