diff options
Diffstat (limited to 'gst/videofilter')
-rw-r--r-- | gst/videofilter/Makefile.am | 16 | ||||
-rw-r--r-- | gst/videofilter/gstvideobalance.c | 12 | ||||
-rw-r--r-- | gst/videofilter/gstvideobalance.h | 4 | ||||
-rw-r--r-- | gst/videofilter/gstvideofilter.c | 484 | ||||
-rw-r--r-- | gst/videofilter/gstvideofilter.h | 59 | ||||
-rw-r--r-- | gst/videofilter/gstvideoflip.c | 613 | ||||
-rw-r--r-- | gst/videofilter/gstvideoflip.h | 13 |
7 files changed, 413 insertions, 788 deletions
diff --git a/gst/videofilter/Makefile.am b/gst/videofilter/Makefile.am index 2cc94db8..17b3c3fa 100644 --- a/gst/videofilter/Makefile.am +++ b/gst/videofilter/Makefile.am @@ -1,5 +1,5 @@ lib_LTLIBRARIES = libgstvideofilter-@GST_MAJORMINOR@.la -noinst_LTLIBRARIES = libgstvideoexample.la +# noinst_LTLIBRARIES = libgstvideoexample.la plugin_LTLIBRARIES = libgstvideoflip.la noinst_HEADERS = gstvideofilter.h gstvideoflip.h @@ -11,14 +11,16 @@ libgstvideofilter_@GST_MAJORMINOR@_la_SOURCES = gstvideofilter.c gstvideofilter. libgstvideofilter_@GST_MAJORMINOR@_la_CFLAGS = $(GST_CFLAGS) libgstvideofilter_@GST_MAJORMINOR@_la_LDFLAGS = $(GST_LIBS) -libgstvideoexample_la_SOURCES = gstvideoexample.c -libgstvideoexample_la_CFLAGS = $(GST_CFLAGS) -libgstvideoexample_la_LIBADD = libgstvideofilter-@GST_MAJORMINOR@.la $(GST_LIBS) -libgstvideoexample_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +# libgstvideoexample_la_SOURCES = gstvideoexample.c +# libgstvideoexample_la_CFLAGS = $(GST_CFLAGS) +# libgstvideoexample_la_LIBADD = libgstvideofilter-@GST_MAJORMINOR@.la $(GST_LIBS) +# libgstvideoexample_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstvideoflip_la_SOURCES = gstvideoflip.c -libgstvideoflip_la_CFLAGS = $(GST_CFLAGS) -libgstvideoflip_la_LIBADD = libgstvideofilter-@GST_MAJORMINOR@.la $(GST_LIBS) +libgstvideoflip_la_CFLAGS = $(GST_CFLAGS) $(GST_BASE_CFLAGS) \ + $(GST_PLUGINS_BASE_CFLAGS) +libgstvideoflip_la_LIBADD = libgstvideofilter-@GST_MAJORMINOR@.la $(GST_LIBS) \ + $(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS) libgstvideoflip_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) # libgstvideobalance_la_SOURCES = gstvideobalance.c diff --git a/gst/videofilter/gstvideobalance.c b/gst/videofilter/gstvideobalance.c index 0825aa46..919f13ff 100644 --- a/gst/videofilter/gstvideobalance.c +++ b/gst/videofilter/gstvideobalance.c @@ -27,7 +27,6 @@ #include "config.h" #endif -/*#define DEBUG_ENABLED */ #include "gstvideobalance.h" #ifdef HAVE_LIBOIL #include <liboil/liboil.h> @@ -40,12 +39,6 @@ /* GstVideobalance signals and args */ enum { - /* FILL ME */ - LAST_SIGNAL -}; - -enum -{ ARG_0, ARG_CONTRAST, ARG_BRIGHTNESS, @@ -117,11 +110,6 @@ gst_videobalance_get_type (void) return videobalance_type; } -static GstVideofilterFormat gst_videobalance_formats[] = { - {"I420", 12, gst_videobalance_planar411,}, -}; - - static void gst_videobalance_base_init (gpointer g_class) { diff --git a/gst/videofilter/gstvideobalance.h b/gst/videofilter/gstvideobalance.h index 45aab910..ac709f88 100644 --- a/gst/videofilter/gstvideobalance.h +++ b/gst/videofilter/gstvideobalance.h @@ -21,12 +21,8 @@ #ifndef __GST_VIDEOBALANCE_H__ #define __GST_VIDEOBALANCE_H__ - -#include <gst/gst.h> - #include "gstvideofilter.h" - G_BEGIN_DECLS #define GST_TYPE_VIDEOBALANCE \ diff --git a/gst/videofilter/gstvideofilter.c b/gst/videofilter/gstvideofilter.c index 89951bb9..a7d9db0e 100644 --- a/gst/videofilter/gstvideofilter.c +++ b/gst/videofilter/gstvideofilter.c @@ -22,40 +22,15 @@ #include "config.h" #endif -#include <string.h> -/*#define DEBUG_ENABLED */ #include "gstvideofilter.h" GST_DEBUG_CATEGORY_STATIC (gst_videofilter_debug); #define GST_CAT_DEFAULT gst_videofilter_debug -/* GstVideofilter signals and args */ -enum -{ - /* FILL ME */ - LAST_SIGNAL -}; - -enum -{ - ARG_0, - ARG_METHOD - /* FILL ME */ -}; - -static void gst_videofilter_base_init (gpointer g_class); static void gst_videofilter_class_init (gpointer g_class, gpointer class_data); static void gst_videofilter_init (GTypeInstance * instance, gpointer g_class); -static void gst_videofilter_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_videofilter_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); - -static GstFlowReturn gst_videofilter_chain (GstPad * pad, GstBuffer * buffer); -GstCaps *gst_videofilter_class_get_capslist (GstVideofilterClass * klass); - -static GstElementClass *parent_class = NULL; +static GstBaseTransformClass *parent_class = NULL; GType gst_videofilter_get_type (void) @@ -65,7 +40,7 @@ gst_videofilter_get_type (void) if (!videofilter_type) { static const GTypeInfo videofilter_info = { sizeof (GstVideofilterClass), - gst_videofilter_base_init, + NULL, NULL, gst_videofilter_class_init, NULL, @@ -75,484 +50,37 @@ gst_videofilter_get_type (void) gst_videofilter_init, }; - videofilter_type = g_type_register_static (GST_TYPE_ELEMENT, + videofilter_type = g_type_register_static (GST_TYPE_BASE_TRANSFORM, "GstVideofilter", &videofilter_info, G_TYPE_FLAG_ABSTRACT); } return videofilter_type; } static void -gst_videofilter_base_init (gpointer g_class) -{ - static GstElementDetails videofilter_details = { - "Video scaler", - "Filter/Effect/Video", - "Resizes video", - "David Schleef <ds@schleef.org>" - }; - GstVideofilterClass *klass = (GstVideofilterClass *) g_class; - GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - - klass->formats = g_ptr_array_new (); - - gst_element_class_set_details (element_class, &videofilter_details); -} - -static void gst_videofilter_class_init (gpointer g_class, gpointer class_data) { GObjectClass *gobject_class; GstElementClass *gstelement_class; + GstBaseTransformClass *trans_class; GstVideofilterClass *klass; klass = (GstVideofilterClass *) g_class; gobject_class = (GObjectClass *) klass; gstelement_class = (GstElementClass *) klass; + trans_class = (GstBaseTransformClass *) klass; - parent_class = g_type_class_ref (GST_TYPE_ELEMENT); - - gobject_class->set_property = gst_videofilter_set_property; - gobject_class->get_property = gst_videofilter_get_property; + parent_class = g_type_class_peek_parent (klass); GST_DEBUG_CATEGORY_INIT (gst_videofilter_debug, "videofilter", 0, "videofilter"); } -static GstStructure * -gst_videofilter_format_get_structure (GstVideofilterFormat * format) -{ - unsigned int fourcc; - GstStructure *structure; - - if (format->filter_func == NULL) - return NULL; - - fourcc = - GST_MAKE_FOURCC (format->fourcc[0], format->fourcc[1], format->fourcc[2], - format->fourcc[3]); - - if (format->depth) { - structure = gst_structure_new ("video/x-raw-rgb", - "depth", G_TYPE_INT, format->depth, - "bpp", G_TYPE_INT, format->bpp, - "endianness", G_TYPE_INT, format->endianness, - "red_mask", G_TYPE_INT, format->red_mask, - "green_mask", G_TYPE_INT, format->green_mask, - "blue_mask", G_TYPE_INT, format->blue_mask, NULL); - } else { - structure = gst_structure_new ("video/x-raw-yuv", - "format", GST_TYPE_FOURCC, fourcc, NULL); - } - - gst_structure_set (structure, - "height", GST_TYPE_INT_RANGE, 1, G_MAXINT, - "width", GST_TYPE_INT_RANGE, 1, G_MAXINT, - "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); - - return structure; -} - -GstCaps * -gst_videofilter_class_get_capslist (GstVideofilterClass * klass) -{ - GstCaps *caps; - GstStructure *structure; - int i; - - caps = gst_caps_new_empty (); - for (i = 0; i < klass->formats->len; i++) { - structure = - gst_videofilter_format_get_structure (g_ptr_array_index (klass->formats, - i)); - gst_caps_append_structure (caps, structure); - } - - return caps; -} - -static GstCaps * -gst_videofilter_getcaps (GstPad * pad) -{ - GstVideofilter *videofilter; - GstVideofilterClass *klass; - GstCaps *caps; - GstPad *peer; - int i; - - videofilter = GST_VIDEOFILTER (GST_PAD_PARENT (pad)); - GST_DEBUG_OBJECT (videofilter, "gst_videofilter_getcaps"); - - klass = GST_VIDEOFILTER_CLASS (G_OBJECT_GET_CLASS (videofilter)); - - /* we can handle anything that was registered */ - caps = gst_caps_new_empty (); - for (i = 0; i < klass->formats->len; i++) { - GstCaps *fromcaps; - - fromcaps = - gst_caps_new_full (gst_videofilter_format_get_structure - (g_ptr_array_index (klass->formats, i)), NULL); - - gst_caps_append (caps, fromcaps); - } - - peer = gst_pad_get_peer (pad); - if (peer) { - GstCaps *peercaps; - - peercaps = gst_pad_get_caps (peer); - if (peercaps) { - GstCaps *icaps; - - icaps = gst_caps_intersect (peercaps, caps); - gst_caps_unref (peercaps); - gst_caps_unref (caps); - caps = icaps; - } - //gst_object_unref (peer); - } - - return caps; -} - -static gboolean -gst_videofilter_setcaps (GstPad * pad, GstCaps * caps) -{ - GstVideofilter *videofilter; - GstStructure *structure; - int width, height; - const GValue *framerate; - int ret; - - videofilter = GST_VIDEOFILTER (GST_PAD_PARENT (pad)); - - structure = gst_caps_get_structure (caps, 0); - - videofilter->format = - gst_videofilter_find_format_by_structure (videofilter, structure); - g_return_val_if_fail (videofilter->format, GST_PAD_LINK_REFUSED); - - ret = gst_structure_get_int (structure, "width", &width); - ret &= gst_structure_get_int (structure, "height", &height); - - framerate = gst_structure_get_value (structure, "framerate"); - ret &= (framerate != NULL && GST_VALUE_HOLDS_FRACTION (framerate)); - - if (!ret) - return FALSE; - - gst_pad_set_caps (videofilter->srcpad, caps); - - GST_DEBUG_OBJECT (videofilter, "width %d height %d", width, height); - -#if 0 - if (pad == videofilter->srcpad) { - videofilter->to_width = width; - videofilter->to_height = height; - } else { - videofilter->from_width = width; - videofilter->from_height = height; - } -#endif - videofilter->to_width = width; - videofilter->to_height = height; - videofilter->from_width = width; - videofilter->from_height = height; - g_value_copy (framerate, &videofilter->framerate); - - gst_videofilter_setup (videofilter); - - return TRUE; -} - static void gst_videofilter_init (GTypeInstance * instance, gpointer g_class) { GstVideofilter *videofilter = GST_VIDEOFILTER (instance); - GstPadTemplate *pad_template; GST_DEBUG_OBJECT (videofilter, "gst_videofilter_init"); - pad_template = - gst_element_class_get_pad_template (GST_ELEMENT_CLASS (g_class), "sink"); - g_return_if_fail (pad_template != NULL); - videofilter->sinkpad = gst_pad_new_from_template (pad_template, "sink"); - gst_element_add_pad (GST_ELEMENT (videofilter), videofilter->sinkpad); - gst_pad_set_chain_function (videofilter->sinkpad, gst_videofilter_chain); - gst_pad_set_setcaps_function (videofilter->sinkpad, gst_videofilter_setcaps); - gst_pad_set_getcaps_function (videofilter->sinkpad, gst_videofilter_getcaps); - - pad_template = - gst_element_class_get_pad_template (GST_ELEMENT_CLASS (g_class), "src"); - g_return_if_fail (pad_template != NULL); - videofilter->srcpad = gst_pad_new_from_template (pad_template, "src"); - gst_element_add_pad (GST_ELEMENT (videofilter), videofilter->srcpad); - gst_pad_set_getcaps_function (videofilter->srcpad, gst_videofilter_getcaps); - videofilter->inited = FALSE; - g_value_init (&videofilter->framerate, GST_TYPE_FRACTION); -} - -static GstFlowReturn -gst_videofilter_chain (GstPad * pad, GstBuffer * buf) -{ - GstVideofilter *videofilter; - guchar *data; - gulong size; - GstBuffer *outbuf; - GstFlowReturn ret; - - videofilter = GST_VIDEOFILTER (GST_PAD_PARENT (pad)); - GST_DEBUG_OBJECT (videofilter, "gst_videofilter_chain"); - - if (videofilter->passthru) { - return gst_pad_push (videofilter->srcpad, buf); - } - - if (GST_PAD_CAPS (pad) == NULL) { - return GST_FLOW_NOT_NEGOTIATED; - } - - data = GST_BUFFER_DATA (buf); - size = GST_BUFFER_SIZE (buf); - - GST_LOG_OBJECT (videofilter, "got buffer of %ld bytes in '%s'", size, - GST_OBJECT_NAME (videofilter)); - - GST_LOG_OBJECT (videofilter, - "size=%ld from=%dx%d to=%dx%d fromsize=%ld (should be %d) tosize=%d", - size, videofilter->from_width, videofilter->from_height, - videofilter->to_width, videofilter->to_height, size, - videofilter->from_buf_size, videofilter->to_buf_size); - - - if (size > videofilter->from_buf_size) { - GST_INFO_OBJECT (videofilter, "buffer size %ld larger than expected (%d)", - size, videofilter->from_buf_size); - return GST_FLOW_ERROR; - } - - ret = gst_pad_alloc_buffer (videofilter->srcpad, GST_BUFFER_OFFSET_NONE, - videofilter->to_buf_size, GST_PAD_CAPS (videofilter->srcpad), &outbuf); - if (ret != GST_FLOW_OK) - goto no_buffer; - - g_return_val_if_fail (GST_BUFFER_DATA (outbuf), GST_FLOW_ERROR); - - GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buf); - GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (buf); - - g_return_val_if_fail (videofilter->format, GST_FLOW_ERROR); - GST_DEBUG_OBJECT (videofilter, "format %s", videofilter->format->fourcc); - - videofilter->in_buf = buf; - videofilter->out_buf = outbuf; - - videofilter->format->filter_func (videofilter, GST_BUFFER_DATA (outbuf), - data); - gst_buffer_unref (buf); - - GST_LOG_OBJECT (videofilter, "pushing buffer of %d bytes in '%s'", - GST_BUFFER_SIZE (outbuf), GST_OBJECT_NAME (videofilter)); - - ret = gst_pad_push (videofilter->srcpad, outbuf); - - return ret; - -no_buffer: - { - return ret; - } -} - -static void -gst_videofilter_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstVideofilter *videofilter; - - g_return_if_fail (GST_IS_VIDEOFILTER (object)); - videofilter = GST_VIDEOFILTER (object); - - GST_DEBUG_OBJECT (videofilter, "gst_videofilter_set_property"); - switch (prop_id) { - default: - break; - } -} - -static void -gst_videofilter_get_property (GObject * object, guint prop_id, GValue * value, - GParamSpec * pspec) -{ - GstVideofilter *videofilter; - - g_return_if_fail (GST_IS_VIDEOFILTER (object)); - videofilter = GST_VIDEOFILTER (object); - - switch (prop_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -int -gst_videofilter_get_input_width (GstVideofilter * videofilter) -{ - g_return_val_if_fail (GST_IS_VIDEOFILTER (videofilter), 0); - - return videofilter->from_width; -} - -int -gst_videofilter_get_input_height (GstVideofilter * videofilter) -{ - g_return_val_if_fail (GST_IS_VIDEOFILTER (videofilter), 0); - - return videofilter->from_height; -} - -void -gst_videofilter_set_output_size (GstVideofilter * videofilter, - int width, int height) -{ - GstCaps *srccaps; - GstStructure *structure; - - g_return_if_fail (GST_IS_VIDEOFILTER (videofilter)); - - videofilter->to_width = width; - videofilter->to_height = height; - - videofilter->to_buf_size = (videofilter->to_width * videofilter->to_height - * videofilter->format->bpp) / 8; - - //srccaps = gst_caps_copy (gst_pad_get_negotiated_caps (videofilter->srcpad)); - srccaps = gst_caps_copy (GST_PAD_CAPS (videofilter->srcpad)); - structure = gst_caps_get_structure (srccaps, 0); - - gst_structure_set (structure, "width", G_TYPE_INT, width, - "height", G_TYPE_INT, height, NULL); - - gst_pad_set_caps (videofilter->srcpad, srccaps); -} - -void -gst_videofilter_setup (GstVideofilter * videofilter) -{ - GstVideofilterClass *klass; - - GST_DEBUG_OBJECT (videofilter, "setup"); - - klass = GST_VIDEOFILTER_CLASS (G_OBJECT_GET_CLASS (videofilter)); - - if (klass->setup) { - GST_DEBUG_OBJECT (videofilter, "calling class setup method"); - klass->setup (videofilter); - } - - if (videofilter->to_width == 0) { - videofilter->to_width = videofilter->from_width; - } - if (videofilter->to_height == 0) { - videofilter->to_height = videofilter->from_height; - } - - g_return_if_fail (videofilter->format != NULL); - g_return_if_fail (videofilter->from_width > 0); - g_return_if_fail (videofilter->from_height > 0); - g_return_if_fail (videofilter->to_width > 0); - g_return_if_fail (videofilter->to_height > 0); - - videofilter->from_buf_size = - (videofilter->from_width * videofilter->from_height * - videofilter->format->bpp) / 8; - videofilter->to_buf_size = - (videofilter->to_width * videofilter->to_height * - videofilter->format->bpp) / 8; - - GST_DEBUG_OBJECT (videofilter, "from_buf_size %d to_buf_size %d", - videofilter->from_buf_size, videofilter->to_buf_size); - videofilter->inited = TRUE; -} - -GstVideofilterFormat * -gst_videofilter_find_format_by_structure (GstVideofilter * videofilter, - const GstStructure * structure) -{ - int i; - GstVideofilterClass *klass; - GstVideofilterFormat *format; - gboolean ret; - - klass = GST_VIDEOFILTER_CLASS (G_OBJECT_GET_CLASS (videofilter)); - - g_return_val_if_fail (structure != NULL, NULL); - - if (strcmp (gst_structure_get_name (structure), "video/x-raw-yuv") == 0) { - guint32 fourcc; - - ret = gst_structure_get_fourcc (structure, "format", &fourcc); - if (!ret) - return NULL; - for (i = 0; i < klass->formats->len; i++) { - guint32 format_fourcc; - - format = g_ptr_array_index (klass->formats, i); - format_fourcc = GST_STR_FOURCC (format->fourcc); - if (format->depth == 0 && format_fourcc == fourcc) { - return format; - } - } - } else if (strcmp (gst_structure_get_name (structure), "video/x-raw-rgb") - == 0) { - int bpp; - int depth; - int endianness; - int red_mask; - int green_mask; - int blue_mask; - - ret = gst_structure_get_int (structure, "bpp", &bpp); - ret &= gst_structure_get_int (structure, "depth", &depth); - ret &= gst_structure_get_int (structure, "endianness", &endianness); - ret &= gst_structure_get_int (structure, "red_mask", &red_mask); - ret &= gst_structure_get_int (structure, "green_mask", &green_mask); - ret &= gst_structure_get_int (structure, "blue_mask", &blue_mask); - if (!ret) - return NULL; - for (i = 0; i < klass->formats->len; i++) { - format = g_ptr_array_index (klass->formats, i); - if (format->bpp == bpp && format->depth == depth && - format->endianness == endianness && format->red_mask == red_mask && - format->green_mask == green_mask && format->blue_mask == blue_mask) { - return format; - } - } - } - - return NULL; -} - -void -gst_videofilter_class_add_format (GstVideofilterClass * videofilterclass, - GstVideofilterFormat * format) -{ - g_ptr_array_add (videofilterclass->formats, format); -} - -void -gst_videofilter_class_add_pad_templates (GstVideofilterClass * - videofilter_class) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (videofilter_class); - - gst_element_class_add_pad_template (element_class, - gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - gst_videofilter_class_get_capslist (videofilter_class))); - - gst_element_class_add_pad_template (element_class, - gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, - gst_videofilter_class_get_capslist (videofilter_class))); } diff --git a/gst/videofilter/gstvideofilter.h b/gst/videofilter/gstvideofilter.h index 9923a2a7..a2f9ef04 100644 --- a/gst/videofilter/gstvideofilter.h +++ b/gst/videofilter/gstvideofilter.h @@ -21,32 +21,13 @@ #ifndef __GST_VIDEOFILTER_H__ #define __GST_VIDEOFILTER_H__ - -#include <gst/gst.h> - +#include <gst/base/gstbasetransform.h> G_BEGIN_DECLS typedef struct _GstVideofilter GstVideofilter; typedef struct _GstVideofilterClass GstVideofilterClass; -typedef void (*GstVideofilterFilterFunc)(GstVideofilter *filter, - void *out_data, void *in_data); - -typedef void (*GstVideofilterSetupFunc)(GstVideofilter *filter); - -typedef struct _GstVideofilterFormat GstVideofilterFormat; -struct _GstVideofilterFormat { - char *fourcc; - int bpp; - GstVideofilterFilterFunc filter_func; - int depth; - unsigned int endianness; - unsigned int red_mask; - unsigned int green_mask; - unsigned int blue_mask; -}; - #define GST_TYPE_VIDEOFILTER \ (gst_videofilter_get_type()) #define GST_VIDEOFILTER(obj) \ @@ -59,51 +40,17 @@ struct _GstVideofilterFormat { (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VIDEOFILTER)) struct _GstVideofilter { - GstElement element; - - GstPad *sinkpad,*srcpad; + GstBaseTransform element; - /* video state */ gboolean inited; - GstVideofilterFormat *format; - gint to_width; - gint to_height; - gint from_width; - gint from_height; - gboolean passthru; - - /* private */ - gint from_buf_size; - gint to_buf_size; - GValue framerate; - - GstBuffer *in_buf; - GstBuffer *out_buf; }; struct _GstVideofilterClass { - GstElementClass parent_class; - - GPtrArray *formats; - GstVideofilterSetupFunc setup; + GstBaseTransformClass parent_class; }; GType gst_videofilter_get_type(void); -int gst_videofilter_get_input_width(GstVideofilter *videofilter); -int gst_videofilter_get_input_height(GstVideofilter *videofilter); -void gst_videofilter_set_output_size(GstVideofilter *videofilter, - int width, int height); -GstVideofilterFormat *gst_videofilter_find_format_by_structure (GstVideofilter *filter, - const GstStructure *structure); -GstCaps *gst_videofilter_class_get_capslist(GstVideofilterClass *videofilterclass); -void gst_videofilter_setup (GstVideofilter * videofilter); - -void gst_videofilter_class_add_format(GstVideofilterClass *videofilterclass, - GstVideofilterFormat *format); -void gst_videofilter_class_add_pad_templates (GstVideofilterClass *videofilterclass); - G_END_DECLS #endif /* __GST_VIDEOFILTER_H__ */ - diff --git a/gst/videofilter/gstvideoflip.c b/gst/videofilter/gstvideoflip.c index da9a76b9..d0f3263e 100644 --- a/gst/videofilter/gstvideoflip.c +++ b/gst/videofilter/gstvideoflip.c @@ -27,17 +27,11 @@ #include "config.h" #endif -/*#define DEBUG_ENABLED */ #include "gstvideoflip.h" -#include <string.h> -/* GstVideoflip signals and args */ -enum -{ - /* FILL ME */ - LAST_SIGNAL -}; +#include <gst/video/video.h> +/* GstVideoflip signals and args */ enum { ARG_0, @@ -45,21 +39,30 @@ enum /* FILL ME */ }; -GST_DEBUG_CATEGORY_STATIC (gst_videoflip_debug); -#define GST_CAT_DEFAULT gst_videoflip_debug +GST_DEBUG_CATEGORY (videoflip_debug); +#define GST_CAT_DEFAULT videoflip_debug -static void gst_videoflip_base_init (gpointer g_class); -static void gst_videoflip_class_init (gpointer g_class, gpointer class_data); -static void gst_videoflip_init (GTypeInstance * instance, gpointer g_class); +static GstElementDetails videoflip_details = +GST_ELEMENT_DETAILS ("Video Flipper", + "Filter/Effect/Video", + "Flips and rotates video", + "David Schleef <ds@schleef.org>"); + +static GstStaticPadTemplate gst_videoflip_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("{ IYUV, I420, YV12 }")) + ); -static void gst_videoflip_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_videoflip_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); +static GstStaticPadTemplate gst_videoflip_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("{ IYUV, I420, YV12 }")) + ); -static void gst_videoflip_planar411 (GstVideofilter * videofilter, void *dest, - void *src); -static void gst_videoflip_setup (GstVideofilter * videofilter); +static GstVideofilterClass *parent_class = NULL; #define GST_TYPE_VIDEOFLIP_METHOD (gst_videoflip_method_get_type()) @@ -72,7 +75,7 @@ gst_videoflip_method_get_type (void) {GST_VIDEOFLIP_METHOD_90R, "Rotate clockwise 90 degrees", "clockwise"}, {GST_VIDEOFLIP_METHOD_180, "Rotate 180 degrees", "rotate-180"}, {GST_VIDEOFLIP_METHOD_90L, "Rotate counter-clockwise 90 degrees", - "counterclockwise"}, + "counterclockwise"}, {GST_VIDEOFLIP_METHOD_HORIZ, "Flip horizontally", "horizontal-flip"}, {GST_VIDEOFLIP_METHOD_VERT, "Flip vertically", "vertical-flip"}, {GST_VIDEOFLIP_METHOD_TRANS, @@ -89,90 +92,318 @@ gst_videoflip_method_get_type (void) return videoflip_method_type; } -GType -gst_videoflip_get_type (void) +static gboolean +gst_videoflip_set_caps (GstBaseTransform * btrans, GstCaps * incaps, + GstCaps * outcaps) { - static GType videoflip_type = 0; + GstVideoflip *vf; + GstStructure *in_s, *out_s; + gboolean ret = FALSE; + + vf = GST_VIDEOFLIP (btrans); + + in_s = gst_caps_get_structure (incaps, 0); + out_s = gst_caps_get_structure (outcaps, 0); + + if (gst_structure_get_int (in_s, "width", &vf->from_width) && + gst_structure_get_int (in_s, "height", &vf->from_height) && + gst_structure_get_int (out_s, "width", &vf->to_width) && + gst_structure_get_int (out_s, "height", &vf->to_height)) { + /* Check that they are correct */ + switch (vf->method) { + case GST_VIDEOFLIP_METHOD_90R: + case GST_VIDEOFLIP_METHOD_90L: + case GST_VIDEOFLIP_METHOD_TRANS: + case GST_VIDEOFLIP_METHOD_OTHER: + if ((vf->from_width != vf->to_height) || + (vf->from_height != vf->to_width)) { + GST_DEBUG_OBJECT (vf, "we are inverting width and height but caps " + "are not correct : %dx%d to %dx%d", vf->from_width, + vf->from_height, vf->to_width, vf->to_height); + goto beach; + } + break; + case GST_VIDEOFLIP_METHOD_IDENTITY: + + break; + case GST_VIDEOFLIP_METHOD_180: + case GST_VIDEOFLIP_METHOD_HORIZ: + case GST_VIDEOFLIP_METHOD_VERT: + if ((vf->from_width != vf->to_width) || + (vf->from_height != vf->to_height)) { + GST_DEBUG_OBJECT (vf, "we are keeping width and height but caps " + "are not correct : %dx%d to %dx%d", vf->from_width, + vf->from_height, vf->to_width, vf->to_height); + goto beach; + } + break; + default: + g_assert_not_reached (); + break; + } + } - if (!videoflip_type) { - static const GTypeInfo videoflip_info = { - sizeof (GstVideoflipClass), - gst_videoflip_base_init, - NULL, - gst_videoflip_class_init, - NULL, - NULL, - sizeof (GstVideoflip), - 0, - gst_videoflip_init, - }; + ret = TRUE; - videoflip_type = g_type_register_static (GST_TYPE_VIDEOFILTER, - "GstVideoflip", &videoflip_info, 0); +beach: + return ret; +} + +static GstCaps * +gst_videoflip_transform_caps (GstBaseTransform * trans, + GstPadDirection direction, GstCaps * caps) +{ + GstVideoflip *videoflip; + GstCaps *ret; + gint width, height, i; + + videoflip = GST_VIDEOFLIP (trans); + + ret = gst_caps_copy (caps); + + for (i = 0; i < gst_caps_get_size (ret); i++) { + GstStructure *structure = gst_caps_get_structure (ret, i); + + if (gst_structure_get_int (structure, "width", &width) && + gst_structure_get_int (structure, "height", &height)) { + + switch (videoflip->method) { + case GST_VIDEOFLIP_METHOD_90R: + case GST_VIDEOFLIP_METHOD_90L: + case GST_VIDEOFLIP_METHOD_TRANS: + case GST_VIDEOFLIP_METHOD_OTHER: + gst_structure_set (structure, "width", G_TYPE_INT, height, + "height", G_TYPE_INT, width, NULL); + break; + case GST_VIDEOFLIP_METHOD_IDENTITY: + case GST_VIDEOFLIP_METHOD_180: + case GST_VIDEOFLIP_METHOD_HORIZ: + case GST_VIDEOFLIP_METHOD_VERT: + gst_structure_set (structure, "width", G_TYPE_INT, width, + "height", G_TYPE_INT, height, NULL); + break; + default: + g_assert_not_reached (); + break; + } + } } - return videoflip_type; + + GST_DEBUG_OBJECT (videoflip, "transformed %" GST_PTR_FORMAT " to %" + GST_PTR_FORMAT, caps, ret); + + return ret; } -static GstVideofilterFormat gst_videoflip_formats[] = { - /* planar */ - {"YV12", 12, gst_videoflip_planar411,}, - {"I420", 12, gst_videoflip_planar411,}, - {"IYUV", 12, gst_videoflip_planar411,}, -}; +/* Useful macros */ +#define GST_VIDEO_I420_Y_ROWSTRIDE(width) (GST_ROUND_UP_4(width)) +#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) -static void -gst_videoflip_base_init (gpointer g_class) +#define GST_VIDEO_I420_Y_OFFSET(w,h) (0) +#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))) +#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)) + +#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)) + +static gboolean +gst_videoflip_get_unit_size (GstBaseTransform * btrans, GstCaps * caps, + guint * size) { - static GstElementDetails videoflip_details = - GST_ELEMENT_DETAILS ("Video Flipper", - "Filter/Effect/Video", - "Flips and rotates video", - "David Schleef <ds@schleef.org>"); - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - GstVideofilterClass *videofilter_class = GST_VIDEOFILTER_CLASS (g_class); - int i; + GstVideoflip *videoflip; + GstStructure *structure; + gboolean ret = FALSE; + gint width, height; - gst_element_class_set_details (element_class, &videoflip_details); + videoflip = GST_VIDEOFLIP (btrans); + + structure = gst_caps_get_structure (caps, 0); - for (i = 0; i < G_N_ELEMENTS (gst_videoflip_formats); i++) { - gst_videofilter_class_add_format (videofilter_class, - gst_videoflip_formats + i); + if (gst_structure_get_int (structure, "width", &width) && + gst_structure_get_int (structure, "height", &height)) { + *size = GST_VIDEO_I420_SIZE (width, height); + ret = TRUE; + GST_DEBUG_OBJECT (videoflip, "our frame size is %d bytes (%dx%d)", *size, + width, height); } - gst_videofilter_class_add_pad_templates (GST_VIDEOFILTER_CLASS (g_class)); + return ret; } -static void -gst_videoflip_class_init (gpointer g_class, gpointer class_data) +static GstFlowReturn +gst_videoflip_flip (GstVideoflip * videoflip, unsigned char *dest, + unsigned char *src, int sw, int sh, int dw, int dh) { - GObjectClass *gobject_class; - GstVideofilterClass *videofilter_class; + GstFlowReturn ret = GST_FLOW_OK; + int x, y; + + switch (videoflip->method) { + case GST_VIDEOFLIP_METHOD_90R: + for (y = 0; y < dh; y++) { + for (x = 0; x < dw; x++) { + dest[y * dw + x] = src[(sh - 1 - x) * sw + y]; + } + } + break; + case GST_VIDEOFLIP_METHOD_90L: + for (y = 0; y < dh; y++) { + for (x = 0; x < dw; x++) { + dest[y * dw + x] = src[x * sw + (sw - 1 - y)]; + } + } + break; + case GST_VIDEOFLIP_METHOD_180: + for (y = 0; y < dh; y++) { + for (x = 0; x < dw; x++) { + dest[y * dw + x] = src[(sh - 1 - y) * sw + (sw - 1 - x)]; + } + } + break; + case GST_VIDEOFLIP_METHOD_HORIZ: + for (y = 0; y < dh; y++) { + for (x = 0; x < dw; x++) { + dest[y * dw + x] = src[y * sw + (sw - 1 - x)]; + } + } + break; + case GST_VIDEOFLIP_METHOD_VERT: + for (y = 0; y < dh; y++) { + for (x = 0; x < dw; x++) { + dest[y * dw + x] = src[(sh - 1 - y) * sw + x]; + } + } + break; + case GST_VIDEOFLIP_METHOD_TRANS: + for (y = 0; y < dh; y++) { + for (x = 0; x < dw; x++) { + dest[y * dw + x] = src[x * sw + y]; + } + } + break; + case GST_VIDEOFLIP_METHOD_OTHER: + for (y = 0; y < dh; y++) { + for (x = 0; x < dw; x++) { + dest[y * dw + x] = src[(sh - 1 - x) * sw + (sw - 1 - y)]; + } + } + break; + default: + ret = GST_FLOW_ERROR; + break; + } - gobject_class = G_OBJECT_CLASS (g_class); - videofilter_class = GST_VIDEOFILTER_CLASS (g_class); + return ret; +} - gobject_class->set_property = gst_videoflip_set_property; - gobject_class->get_property = gst_videoflip_get_property; +static GstFlowReturn +gst_videoflip_transform (GstBaseTransform * trans, GstBuffer * in, + GstBuffer * out) +{ + GstVideoflip *videoflip; + gpointer dest, src; + int sw, sh, dw, dh; + GstFlowReturn ret = GST_FLOW_OK; - g_object_class_install_property (gobject_class, ARG_METHOD, - g_param_spec_enum ("method", "method", "method", - GST_TYPE_VIDEOFLIP_METHOD, GST_VIDEOFLIP_METHOD_90R, - G_PARAM_READWRITE)); + videoflip = GST_VIDEOFLIP (trans); + + gst_buffer_stamp (out, in); + + src = GST_BUFFER_DATA (in); + dest = GST_BUFFER_DATA (out); + sw = videoflip->from_width; + sh = videoflip->from_height; + dw = videoflip->to_width; + dh = videoflip->to_height; + + GST_LOG_OBJECT (videoflip, "videoflip: scaling planar 4:1:1 %dx%d to %dx%d", + sw, sh, dw, dh); + + ret = gst_videoflip_flip (videoflip, dest, src, sw, sh, dw, dh); + if (ret != GST_FLOW_OK) + goto beach; + + src += sw * sh; + dest += dw * dh; + + dh = dh >> 1; + dw = dw >> 1; + sh = sh >> 1; + sw = sw >> 1; - videofilter_class->setup = gst_videoflip_setup; + ret = gst_videoflip_flip (videoflip, dest, src, sw, sh, dw, dh); + if (ret != GST_FLOW_OK) + goto beach; + + src += sw * sh; + dest += dw * dh; + + ret = gst_videoflip_flip (videoflip, dest, src, sw, sh, dw, dh); + +beach: + return ret; } -static void -gst_videoflip_init (GTypeInstance * instance, gpointer g_class) +static gboolean +gst_videoflip_handle_src_event (GstPad * pad, GstEvent * event) { - GstVideoflip *videoflip = GST_VIDEOFLIP (instance); - GstVideofilter *videofilter; + GstVideoflip *vf; + gboolean ret; + gdouble x, y; + GstStructure *structure; + + vf = GST_VIDEOFLIP (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT (vf, "handling %s event", GST_EVENT_TYPE_NAME (event)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_NAVIGATION: + event = + GST_EVENT (gst_mini_object_make_writable (GST_MINI_OBJECT (event))); + + structure = (GstStructure *) gst_event_get_structure (event); + if (gst_structure_get_double (structure, "pointer_x", &x) && + gst_structure_get_double (structure, "pointer_y", &y)) { + switch (vf->method) { + case GST_VIDEOFLIP_METHOD_90R: + case GST_VIDEOFLIP_METHOD_OTHER: + x = y; + y = vf->to_width - x; + break; + case GST_VIDEOFLIP_METHOD_90L: + case GST_VIDEOFLIP_METHOD_TRANS: + x = vf->to_height - y; + y = x; + break; + case GST_VIDEOFLIP_METHOD_180: + x = vf->to_width - x; + y = vf->to_height - y; + break; + case GST_VIDEOFLIP_METHOD_HORIZ: + x = vf->to_width - x; + y = y; + break; + case GST_VIDEOFLIP_METHOD_VERT: + x = x; + y = vf->to_height - y; + break; + default: + x = x; + y = y; + break; + } + gst_structure_set (structure, "pointer_x", G_TYPE_DOUBLE, x, + "pointer_y", G_TYPE_DOUBLE, y, NULL); + } + break; + default: + break; + } - GST_DEBUG_OBJECT (videoflip, "gst_videoflip_init"); + ret = gst_pad_event_default (pad, event); - videofilter = GST_VIDEOFILTER (videoflip); + gst_object_unref (vf); - /* do stuff */ + return ret; } static void @@ -186,16 +417,25 @@ gst_videoflip_set_property (GObject * object, guint prop_id, videoflip = GST_VIDEOFLIP (object); videofilter = GST_VIDEOFILTER (object); - GST_DEBUG_OBJECT (videoflip, "gst_videoflip_set_property"); switch (prop_id) { case ARG_METHOD: - videoflip->method = g_value_get_enum (value); - if (videofilter->inited) { - GST_DEBUG_OBJECT (videoflip, "setting up videoflip again"); - gst_videofilter_setup (videofilter); + { + GstVideoflipMethod method; + + method = g_value_get_enum (value); + if (method != videoflip->method) { + GstBaseTransform *btrans = GST_BASE_TRANSFORM (videoflip); + + g_mutex_lock (btrans->transform_lock); + gst_pad_set_caps (btrans->sinkpad, NULL); + gst_pad_set_caps (btrans->srcpad, NULL); + g_mutex_unlock (btrans->transform_lock); + videoflip->method = method; } + } break; default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } @@ -219,167 +459,94 @@ gst_videoflip_get_property (GObject * object, guint prop_id, GValue * value, } } -static gboolean -plugin_init (GstPlugin * plugin) +static void +gst_videoflip_base_init (gpointer g_class) { - GST_DEBUG_CATEGORY_INIT (gst_videoflip_debug, "videoflip", 0, "videoflip"); - - return gst_element_register (plugin, "videoflip", GST_RANK_NONE, - GST_TYPE_VIDEOFLIP); -} - -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - "videoflip", - "Flips and rotates video", - plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN); + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); -static void gst_videoflip_flip (GstVideoflip * videoflip, - unsigned char *dest, unsigned char *src, int sw, int sh, int dw, int dh); + gst_element_class_set_details (element_class, &videoflip_details); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_videoflip_sink_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_videoflip_src_template)); +} static void -gst_videoflip_setup (GstVideofilter * videofilter) +gst_videoflip_class_init (gpointer klass, gpointer class_data) { - int from_width, from_height; - GstVideoflip *videoflip; - - videoflip = GST_VIDEOFLIP (videofilter); - GST_DEBUG_OBJECT (videoflip, "gst_videoflip_setup"); + GObjectClass *gobject_class; + GstBaseTransformClass *trans_class; - from_width = gst_videofilter_get_input_width (videofilter); - from_height = gst_videofilter_get_input_height (videofilter); + gobject_class = (GObjectClass *) klass; + trans_class = (GstBaseTransformClass *) klass; - if (from_width == 0 || from_height == 0) { - return; - } + parent_class = g_type_class_peek_parent (klass); - switch (videoflip->method) { - case GST_VIDEOFLIP_METHOD_90R: - case GST_VIDEOFLIP_METHOD_90L: - case GST_VIDEOFLIP_METHOD_TRANS: - case GST_VIDEOFLIP_METHOD_OTHER: - gst_videofilter_set_output_size (videofilter, from_height, from_width); - break; - case GST_VIDEOFLIP_METHOD_IDENTITY: - case GST_VIDEOFLIP_METHOD_180: - case GST_VIDEOFLIP_METHOD_HORIZ: - case GST_VIDEOFLIP_METHOD_VERT: - gst_videofilter_set_output_size (videofilter, from_width, from_height); - break; - default: - g_assert_not_reached (); - break; - } + gobject_class->set_property = gst_videoflip_set_property; + gobject_class->get_property = gst_videoflip_get_property; - GST_DEBUG_OBJECT (videoflip, "format=%p \"%s\" from %dx%d to %dx%d", - videofilter->format, videofilter->format->fourcc, - from_width, from_height, videofilter->to_width, videofilter->to_height); + g_object_class_install_property (gobject_class, ARG_METHOD, + g_param_spec_enum ("method", "method", "method", + GST_TYPE_VIDEOFLIP_METHOD, GST_VIDEOFLIP_METHOD_90R, + G_PARAM_READWRITE)); - if (videoflip->method == GST_VIDEOFLIP_METHOD_IDENTITY) { - GST_DEBUG_OBJECT (videoflip, "videoflip: using passthru"); - videofilter->passthru = TRUE; - } else { - videofilter->passthru = FALSE; - } + trans_class->transform_caps = + GST_DEBUG_FUNCPTR (gst_videoflip_transform_caps); + trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_videoflip_set_caps); + trans_class->get_unit_size = GST_DEBUG_FUNCPTR (gst_videoflip_get_unit_size); + trans_class->transform = GST_DEBUG_FUNCPTR (gst_videoflip_transform); } static void -gst_videoflip_planar411 (GstVideofilter * videofilter, void *dest, void *src) +gst_videoflip_init (GTypeInstance * instance, gpointer g_class) { - GstVideoflip *videoflip; - int sw; - int sh; - int dw; - int dh; - - g_return_if_fail (GST_IS_VIDEOFLIP (videofilter)); - videoflip = GST_VIDEOFLIP (videofilter); - - sw = videofilter->from_width; - sh = videofilter->from_height; - dw = videofilter->to_width; - dh = videofilter->to_height; - - GST_LOG_OBJECT (videoflip, "videoflip: scaling planar 4:1:1 %dx%d to %dx%d", - sw, sh, dw, dh); - - gst_videoflip_flip (videoflip, dest, src, sw, sh, dw, dh); + GstVideoflip *videoflip = GST_VIDEOFLIP (instance); + GstBaseTransform *btrans = GST_BASE_TRANSFORM (instance); - src += sw * sh; - dest += dw * dh; + GST_DEBUG_OBJECT (videoflip, "gst_videoflip_init"); - dh = dh >> 1; - dw = dw >> 1; - sh = sh >> 1; - sw = sw >> 1; + videoflip->method = GST_VIDEOFLIP_METHOD_90R; - gst_videoflip_flip (videoflip, dest, src, sw, sh, dw, dh); + gst_pad_set_event_function (btrans->srcpad, + GST_DEBUG_FUNCPTR (gst_videoflip_handle_src_event)); +} - src += sw * sh; - dest += dw * dh; +static gboolean +plugin_init (GstPlugin * plugin) +{ + GST_DEBUG_CATEGORY_INIT (videoflip_debug, "videoflip", 0, "videoflip"); - gst_videoflip_flip (videoflip, dest, src, sw, sh, dw, dh); + return gst_element_register (plugin, "videoflip", GST_RANK_NONE, + GST_TYPE_VIDEOFLIP); } -static void -gst_videoflip_flip (GstVideoflip * videoflip, unsigned char *dest, - unsigned char *src, int sw, int sh, int dw, int dh) +GType +gst_videoflip_get_type (void) { - int x, y; + static GType videoflip_type = 0; - switch (videoflip->method) { - case GST_VIDEOFLIP_METHOD_90R: - for (y = 0; y < dh; y++) { - for (x = 0; x < dw; x++) { - dest[y * dw + x] = src[(sh - 1 - x) * sw + y]; - } - } - break; - case GST_VIDEOFLIP_METHOD_90L: - for (y = 0; y < dh; y++) { - for (x = 0; x < dw; x++) { - dest[y * dw + x] = src[x * sw + (sw - 1 - y)]; - } - } - break; - case GST_VIDEOFLIP_METHOD_180: - for (y = 0; y < dh; y++) { - for (x = 0; x < dw; x++) { - dest[y * dw + x] = src[(sh - 1 - y) * sw + (sw - 1 - x)]; - } - } - break; - case GST_VIDEOFLIP_METHOD_HORIZ: - for (y = 0; y < dh; y++) { - for (x = 0; x < dw; x++) { - dest[y * dw + x] = src[y * sw + (sw - 1 - x)]; - } - } - break; - case GST_VIDEOFLIP_METHOD_VERT: - for (y = 0; y < dh; y++) { - for (x = 0; x < dw; x++) { - dest[y * dw + x] = src[(sh - 1 - y) * sw + x]; - } - } - break; - case GST_VIDEOFLIP_METHOD_TRANS: - for (y = 0; y < dh; y++) { - for (x = 0; x < dw; x++) { - dest[y * dw + x] = src[x * sw + y]; - } - } - break; - case GST_VIDEOFLIP_METHOD_OTHER: - for (y = 0; y < dh; y++) { - for (x = 0; x < dw; x++) { - dest[y * dw + x] = src[(sh - 1 - x) * sw + (sw - 1 - y)]; - } - } - break; - default: - /* FIXME */ - break; + if (!videoflip_type) { + static const GTypeInfo videoflip_info = { + sizeof (GstVideoflipClass), + gst_videoflip_base_init, + NULL, + gst_videoflip_class_init, + NULL, + NULL, + sizeof (GstVideoflip), + 0, + gst_videoflip_init, + }; + + videoflip_type = g_type_register_static (GST_TYPE_VIDEOFILTER, + "GstVideoflip", &videoflip_info, 0); } + return videoflip_type; } + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "videoflip", + "Flips and rotates video", + plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN); diff --git a/gst/videofilter/gstvideoflip.h b/gst/videofilter/gstvideoflip.h index 83b37718..d21ed4ac 100644 --- a/gst/videofilter/gstvideoflip.h +++ b/gst/videofilter/gstvideoflip.h @@ -17,16 +17,11 @@ * Boston, MA 02111-1307, USA. */ - #ifndef __GST_VIDEOFLIP_H__ #define __GST_VIDEOFLIP_H__ - -#include <gst/gst.h> - #include "gstvideofilter.h" - G_BEGIN_DECLS typedef enum { @@ -37,7 +32,7 @@ typedef enum { GST_VIDEOFLIP_METHOD_HORIZ, GST_VIDEOFLIP_METHOD_VERT, GST_VIDEOFLIP_METHOD_TRANS, - GST_VIDEOFLIP_METHOD_OTHER, + GST_VIDEOFLIP_METHOD_OTHER } GstVideoflipMethod; #define GST_TYPE_VIDEOFLIP \ @@ -56,7 +51,10 @@ typedef struct _GstVideoflipClass GstVideoflipClass; struct _GstVideoflip { GstVideofilter videofilter; - + + gint from_width, from_height; + gint to_width, to_height; + GstVideoflipMethod method; }; @@ -69,4 +67,3 @@ GType gst_videoflip_get_type(void); G_END_DECLS #endif /* __GST_VIDEOFLIP_H__ */ - |