diff options
Diffstat (limited to 'gst/videofilter/gstvideoflip.c')
-rw-r--r-- | gst/videofilter/gstvideoflip.c | 613 |
1 files changed, 390 insertions, 223 deletions
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); |