diff options
author | David Schleef <ds@schleef.org> | 2003-06-13 05:37:19 +0000 |
---|---|---|
committer | David Schleef <ds@schleef.org> | 2003-06-13 05:37:19 +0000 |
commit | 176e9f83f383570682c67392e90a32ebae61c567 (patch) | |
tree | 8f3ca4504108e009ce89f1bf3be08155749fd5e2 /gst/videoflip | |
parent | 195e19b6ada8f9c215fd3b7d2b6522bcf378887b (diff) |
Rotate/flip video by increments of 90 degrees.
Original commit message from CVS:
Rotate/flip video by increments of 90 degrees.
Diffstat (limited to 'gst/videoflip')
-rw-r--r-- | gst/videoflip/Makefile.am | 12 | ||||
-rw-r--r-- | gst/videoflip/gstvideoflip.c | 455 | ||||
-rw-r--r-- | gst/videoflip/gstvideoflip.h | 94 | ||||
-rw-r--r-- | gst/videoflip/videoflip.c | 233 | ||||
-rw-r--r-- | gst/videoflip/videoflip.h | 46 |
5 files changed, 840 insertions, 0 deletions
diff --git a/gst/videoflip/Makefile.am b/gst/videoflip/Makefile.am new file mode 100644 index 00000000..ad9b7a9e --- /dev/null +++ b/gst/videoflip/Makefile.am @@ -0,0 +1,12 @@ +plugindir = $(libdir)/gstreamer-@GST_MAJORMINOR@ + +plugin_LTLIBRARIES = libgstvideoflip.la + +libgstvideoflip_la_SOURCES = \ + gstvideoflip.c \ + videoflip.c +libgstvideoflip_la_CFLAGS = $(GST_CFLAGS) +libgstvideoflip_la_LIBADD = +libgstvideoflip_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) + +noinst_HEADERS = gstvideoflip.h videoflip.h diff --git a/gst/videoflip/gstvideoflip.c b/gst/videoflip/gstvideoflip.c new file mode 100644 index 00000000..6f51d705 --- /dev/null +++ b/gst/videoflip/gstvideoflip.c @@ -0,0 +1,455 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +/*#define DEBUG_ENABLED */ +#include <gstvideoflip.h> +#include <videoflip.h> + + + +/* elementfactory information */ +static GstElementDetails videoflip_details = { + "Video scaler", + "Filter/Video", + "LGPL", + "Resizes video", + VERSION, + "Wim Taymans <wim.taymans@chello.be>", + "(C) 2000", +}; + +/* GstVideoflip signals and args */ +enum { + /* FILL ME */ + LAST_SIGNAL +}; + +enum { + ARG_0, + ARG_METHOD, + /* FILL ME */ +}; + +static void gst_videoflip_class_init (GstVideoflipClass *klass); +static void gst_videoflip_init (GstVideoflip *videoflip); + +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 void gst_videoflip_chain (GstPad *pad, GstBuffer *buf); +static GstCaps * gst_videoflip_get_capslist(void); + +static GstElementClass *parent_class = NULL; + +#define GST_TYPE_VIDEOFLIP_METHOD (gst_videoflip_method_get_type()) + +static GType +gst_videoflip_method_get_type(void) +{ + static GType videoflip_method_type = 0; + static GEnumValue videoflip_methods[] = { + { GST_VIDEOFLIP_METHOD_IDENTITY, "0", "Identity (no rotation)" }, + { GST_VIDEOFLIP_METHOD_90R, "1", "Rotate right 90 degrees" }, + { GST_VIDEOFLIP_METHOD_180, "2", "Rotate 180 degrees" }, + { GST_VIDEOFLIP_METHOD_90L, "3", "Rotate left 90 degrees" }, + { GST_VIDEOFLIP_METHOD_HORIZ, "4", "Flip horizontally" }, + { GST_VIDEOFLIP_METHOD_VERT, "5", "Flip vertically" }, + { GST_VIDEOFLIP_METHOD_TRANS, "6", "Flip across upper left/lower right diagonal" }, + { GST_VIDEOFLIP_METHOD_OTHER, "7", "Flip across upper right/lower left diagonal" }, + { 0, NULL, NULL }, + }; + if(!videoflip_method_type){ + videoflip_method_type = g_enum_register_static("GstVideoflipMethod", + videoflip_methods); + } + return videoflip_method_type; +} + +GType +gst_videoflip_get_type (void) +{ + static GType videoflip_type = 0; + + if (!videoflip_type) { + static const GTypeInfo videoflip_info = { + sizeof(GstVideoflipClass), NULL, + NULL, + (GClassInitFunc)gst_videoflip_class_init, + NULL, + NULL, + sizeof(GstVideoflip), + 0, + (GInstanceInitFunc)gst_videoflip_init, + }; + videoflip_type = g_type_register_static(GST_TYPE_ELEMENT, "GstVideoflip", &videoflip_info, 0); + } + return videoflip_type; +} + +static void +gst_videoflip_class_init (GstVideoflipClass *klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass*)klass; + gstelement_class = (GstElementClass*)klass; + + g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_METHOD, + g_param_spec_enum("method","method","method", + GST_TYPE_VIDEOFLIP_METHOD, GST_VIDEOFLIP_METHOD_90R, + G_PARAM_READWRITE)); + + parent_class = g_type_class_ref(GST_TYPE_ELEMENT); + + gobject_class->set_property = gst_videoflip_set_property; + gobject_class->get_property = gst_videoflip_get_property; + +} + +static GstPadTemplate * +gst_videoflip_src_template_factory(void) +{ + static GstPadTemplate *templ = NULL; + + if(!templ){ + GstCaps *caps = GST_CAPS_NEW("src","video/raw", + "width", GST_PROPS_INT_RANGE (0, G_MAXINT), + "height", GST_PROPS_INT_RANGE (0, G_MAXINT)); + + caps = gst_caps_intersect(caps, gst_videoflip_get_capslist ()); + + templ = GST_PAD_TEMPLATE_NEW("src", GST_PAD_SRC, GST_PAD_ALWAYS, caps); + } + return templ; +} + +static GstPadTemplate * +gst_videoflip_sink_template_factory(void) +{ + static GstPadTemplate *templ = NULL; + + if(!templ){ + GstCaps *caps = GST_CAPS_NEW("sink","video/raw", + "width", GST_PROPS_INT_RANGE (0, G_MAXINT), + "height", GST_PROPS_INT_RANGE (0, G_MAXINT)); + + caps = gst_caps_intersect(caps, gst_videoflip_get_capslist ()); + + templ = GST_PAD_TEMPLATE_NEW("src", GST_PAD_SINK, GST_PAD_ALWAYS, caps); + } + return templ; +} + +static GstCaps * +gst_videoflip_get_capslist(void) +{ + static GstCaps *capslist = NULL; + GstCaps *caps; + int i; + + if (capslist){ + gst_caps_ref(capslist); + return capslist; + } + + for(i=0;i<videoflip_n_formats;i++){ + caps = videoflip_get_caps(videoflip_formats + i); + capslist = gst_caps_append(capslist, caps); + } + + gst_caps_ref(capslist); + return capslist; +} + +static GstCaps * +gst_videoflip_sink_getcaps (GstPad *pad, GstCaps *caps) +{ + GstVideoflip *videoflip; + GstCaps *capslist = NULL; + GstCaps *peercaps; + GstCaps *sizecaps; + int i; + + GST_DEBUG(0,"gst_videoflip_src_link"); + videoflip = GST_VIDEOFLIP (gst_pad_get_parent (pad)); + + /* get list of peer's caps */ + if(pad == videoflip->srcpad){ + peercaps = gst_pad_get_allowed_caps (videoflip->sinkpad); + }else{ + peercaps = gst_pad_get_allowed_caps (videoflip->srcpad); + } + + /* FIXME videoflip doesn't allow passthru of video formats it + * doesn't understand. */ + /* Look through our list of caps and find those that match with + * the peer's formats. Create a list of them. */ + for(i=0;i<videoflip_n_formats;i++){ + GstCaps *fromcaps = videoflip_get_caps(videoflip_formats + i); + if(gst_caps_is_always_compatible(fromcaps, peercaps)){ + capslist = gst_caps_append(capslist, fromcaps); + } + gst_caps_unref (fromcaps); + } + gst_caps_unref (peercaps); + + sizecaps = GST_CAPS_NEW("videoflip_size","video/raw", + "width", GST_PROPS_INT_RANGE (0, G_MAXINT), + "height", GST_PROPS_INT_RANGE (0, G_MAXINT)); + + caps = gst_caps_intersect(caps, gst_videoflip_get_capslist ()); + gst_caps_unref (sizecaps); + + return caps; +} + + +static GstPadLinkReturn +gst_videoflip_src_link (GstPad *pad, GstCaps *caps) +{ + GstVideoflip *videoflip; + GstPadLinkReturn ret; + GstCaps *peercaps; + + GST_DEBUG(0,"gst_videoflip_src_link"); + videoflip = GST_VIDEOFLIP (gst_pad_get_parent (pad)); + + if (!GST_CAPS_IS_FIXED (caps)) { + return GST_PAD_LINK_DELAYED; + } + + gst_caps_debug(caps,"ack"); + + videoflip->format = videoflip_find_by_caps (caps); + g_return_val_if_fail(videoflip->format, GST_PAD_LINK_REFUSED); + + gst_caps_get_int (caps, "width", &videoflip->to_width); + gst_caps_get_int (caps, "height", &videoflip->to_height); + + GST_DEBUG(0,"width %d height %d",videoflip->to_width,videoflip->to_height); + + peercaps = gst_caps_copy(caps); + + gst_caps_set(peercaps, "width", GST_PROPS_INT_RANGE (0, G_MAXINT)); + gst_caps_set(peercaps, "height", GST_PROPS_INT_RANGE (0, G_MAXINT)); + + ret = gst_pad_try_set_caps (videoflip->srcpad, peercaps); + + gst_caps_unref(peercaps); + + if(ret==GST_PAD_LINK_OK){ + caps = gst_pad_get_caps (videoflip->srcpad); + + gst_caps_get_int (caps, "width", &videoflip->from_width); + gst_caps_get_int (caps, "height", &videoflip->from_height); + gst_videoflip_setup(videoflip); + } + + return ret; +} + +static GstPadLinkReturn +gst_videoflip_sink_link (GstPad *pad, GstCaps *caps) +{ + GstVideoflip *videoflip; + GstPadLinkReturn ret; + GstCaps *peercaps; + + GST_DEBUG(0,"gst_videoflip_src_link"); + videoflip = GST_VIDEOFLIP (gst_pad_get_parent (pad)); + + if (!GST_CAPS_IS_FIXED (caps)) { + return GST_PAD_LINK_DELAYED; + } + + videoflip->format = videoflip_find_by_caps (caps); + gst_caps_debug(caps,"ack"); + g_return_val_if_fail(videoflip->format, GST_PAD_LINK_REFUSED); + + gst_caps_get_int (caps, "width", &videoflip->from_width); + gst_caps_get_int (caps, "height", &videoflip->from_height); + + gst_videoflip_setup(videoflip); + + peercaps = gst_caps_copy(caps); + + gst_caps_set(peercaps, "width", GST_PROPS_INT (videoflip->to_width)); + gst_caps_set(peercaps, "height", GST_PROPS_INT (videoflip->to_height)); + + ret = gst_pad_try_set_caps (videoflip->srcpad, peercaps); + + gst_caps_unref(peercaps); + + if(ret==GST_PAD_LINK_OK){ + caps = gst_pad_get_caps (videoflip->srcpad); + + gst_caps_get_int (caps, "width", &videoflip->to_width); + gst_caps_get_int (caps, "height", &videoflip->to_height); + gst_videoflip_setup(videoflip); + } + + return ret; +} + +static void +gst_videoflip_init (GstVideoflip *videoflip) +{ + GST_DEBUG(0,"gst_videoflip_init"); + videoflip->sinkpad = gst_pad_new_from_template ( + GST_PAD_TEMPLATE_GET (gst_videoflip_sink_template_factory), + "sink"); + gst_element_add_pad(GST_ELEMENT(videoflip),videoflip->sinkpad); + gst_pad_set_chain_function(videoflip->sinkpad,gst_videoflip_chain); + gst_pad_set_link_function(videoflip->sinkpad,gst_videoflip_sink_link); + gst_pad_set_getcaps_function(videoflip->sinkpad,gst_videoflip_sink_getcaps); + + videoflip->srcpad = gst_pad_new_from_template ( + GST_PAD_TEMPLATE_GET (gst_videoflip_src_template_factory), + "src"); + gst_element_add_pad(GST_ELEMENT(videoflip),videoflip->srcpad); + gst_pad_set_link_function(videoflip->srcpad,gst_videoflip_src_link); + //gst_pad_set_getcaps_function(videoflip->srcpad,gst_videoflip_getcaps); + + videoflip->inited = FALSE; + videoflip->force_size = FALSE; +} + + +static void +gst_videoflip_chain (GstPad *pad, GstBuffer *buf) +{ + GstVideoflip *videoflip; + guchar *data; + gulong size; + GstBuffer *outbuf; + + GST_DEBUG (0,"gst_videoflip_chain"); + + g_return_if_fail (pad != NULL); + g_return_if_fail (GST_IS_PAD (pad)); + g_return_if_fail (buf != NULL); + + videoflip = GST_VIDEOFLIP (gst_pad_get_parent (pad)); + g_return_if_fail (videoflip->inited); + + data = GST_BUFFER_DATA(buf); + size = GST_BUFFER_SIZE(buf); + + if(videoflip->passthru){ + gst_pad_push(videoflip->srcpad, buf); + return; + } + + GST_DEBUG (0,"gst_videoflip_chain: got buffer of %ld bytes in '%s'",size, + GST_OBJECT_NAME (videoflip)); + + GST_DEBUG(0,"size=%ld from=%dx%d to=%dx%d fromsize=%ld (should be %d) tosize=%d", + size, + videoflip->from_width, videoflip->from_height, + videoflip->to_width, videoflip->to_height, + size, videoflip->from_buf_size, + videoflip->to_buf_size); + + g_return_if_fail (size == videoflip->from_buf_size); + + outbuf = gst_buffer_new(); + /* FIXME: handle bufferpools */ + GST_BUFFER_SIZE(outbuf) = videoflip->to_buf_size; + GST_BUFFER_DATA(outbuf) = g_malloc (videoflip->to_buf_size); + GST_BUFFER_TIMESTAMP(outbuf) = GST_BUFFER_TIMESTAMP(buf); + + g_return_if_fail(videoflip->format); + GST_DEBUG (0,"format %s",videoflip->format->fourcc); + g_return_if_fail(videoflip->format->scale); + + videoflip->format->scale(videoflip, GST_BUFFER_DATA(outbuf), data); + + GST_DEBUG (0,"gst_videoflip_chain: pushing buffer of %d bytes in '%s'",GST_BUFFER_SIZE(outbuf), + GST_OBJECT_NAME (videoflip)); + + gst_pad_push(videoflip->srcpad, outbuf); + + gst_buffer_unref(buf); +} + +static void +gst_videoflip_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + GstVideoflip *src; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_VIDEOFLIP(object)); + src = GST_VIDEOFLIP(object); + + GST_DEBUG(0,"gst_videoflip_set_property"); + switch (prop_id) { + case ARG_METHOD: + src->method = g_value_get_enum (value); + break; + default: + break; + } +} + +static void +gst_videoflip_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + GstVideoflip *src; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_VIDEOFLIP(object)); + src = GST_VIDEOFLIP(object); + + switch (prop_id) { + case ARG_METHOD: + g_value_set_enum (value, src->method); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + + +static gboolean +plugin_init (GModule *module, GstPlugin *plugin) +{ + GstElementFactory *factory; + + /* create an elementfactory for the videoflip element */ + factory = gst_element_factory_new("videoflip",GST_TYPE_VIDEOFLIP, + &videoflip_details); + g_return_val_if_fail(factory != NULL, FALSE); + + gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (gst_videoflip_sink_template_factory)); + gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (gst_videoflip_src_template_factory)); + + gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory)); + + return TRUE; +} + +GstPluginDesc plugin_desc = { + GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "videoflip", + plugin_init +}; diff --git a/gst/videoflip/gstvideoflip.h b/gst/videoflip/gstvideoflip.h new file mode 100644 index 00000000..e3463e5e --- /dev/null +++ b/gst/videoflip/gstvideoflip.h @@ -0,0 +1,94 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_VIDEOFLIP_H__ +#define __GST_VIDEOFLIP_H__ + + +#include <config.h> +#include <gst/gst.h> + + +G_BEGIN_DECLS + +typedef enum { + GST_VIDEOFLIP_METHOD_IDENTITY, + GST_VIDEOFLIP_METHOD_90R, + GST_VIDEOFLIP_METHOD_180, + GST_VIDEOFLIP_METHOD_90L, + GST_VIDEOFLIP_METHOD_HORIZ, + GST_VIDEOFLIP_METHOD_VERT, + GST_VIDEOFLIP_METHOD_TRANS, + GST_VIDEOFLIP_METHOD_OTHER, +} GstVideoflipMethod; + + +#define GST_TYPE_VIDEOFLIP \ + (gst_videoflip_get_type()) +#define GST_VIDEOFLIP(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VIDEOFLIP,GstVideoflip)) +#define GST_VIDEOFLIP_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VIDEOFLIP,GstVideoflip)) +#define GST_IS_VIDEOFLIP(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VIDEOFLIP)) +#define GST_IS_VIDEOFLIP_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VIDEOFLIP)) + +typedef struct _GstVideoflip GstVideoflip; +typedef struct _GstVideoflipClass GstVideoflipClass; + +struct _GstVideoflip { + GstElement element; + + GstPad *sinkpad,*srcpad; + + gboolean force_size; + gint forced_width; + gint forced_height; + + /* video state */ + gboolean inited; + struct videoflip_format_struct *format; + gint to_width; + gint to_height; + gint from_width; + gint from_height; + gboolean passthru; + + GstVideoflipMethod method; + + /* private */ + gint from_buf_size; + gint to_buf_size; +}; + +struct _GstVideoflipClass { + GstElementClass parent_class; +}; + +GType gst_videoflip_get_type(void); + +void gst_videoflip_setup(GstVideoflip *); +#define gst_videoflip_scale(scale, src, dest) (scale)->scale_cc((scale), (src), (dest)) + +G_END_DECLS + +#endif /* __GST_VIDEOFLIP_H__ */ + diff --git a/gst/videoflip/videoflip.c b/gst/videoflip/videoflip.c new file mode 100644 index 00000000..ea93a7c6 --- /dev/null +++ b/gst/videoflip/videoflip.c @@ -0,0 +1,233 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#define DEBUG_ENABLED +#include <gst/gst.h> +#include <stdlib.h> +#include <math.h> +#include <videoflip.h> +#include <string.h> + +#include "config.h" +#include "gstvideoflip.h" + +static void gst_videoflip_planar411 (GstVideoflip *scale, unsigned char *dest, unsigned char *src); + +static void gst_videoflip_flip(GstVideoflip *videoflip, unsigned char *dest, + unsigned char *src, int sw, int sh, int dw, int dh); + +struct videoflip_format_struct videoflip_formats[] = { + /* planar */ + { "YV12", 12, gst_videoflip_planar411, }, + { "I420", 12, gst_videoflip_planar411, }, + { "IYUV", 12, gst_videoflip_planar411, }, +}; + +int videoflip_n_formats = sizeof(videoflip_formats)/sizeof(videoflip_formats[0]); + +GstCaps * +videoflip_get_caps(struct videoflip_format_struct *format) +{ + unsigned int fourcc; + GstCaps *caps; + + if(format->scale==NULL) + return NULL; + + fourcc = GST_MAKE_FOURCC(format->fourcc[0],format->fourcc[1],format->fourcc[2],format->fourcc[3]); + + if(format->bpp){ + caps = GST_CAPS_NEW ("videoflip", "video/raw", + "format", GST_PROPS_FOURCC (fourcc), + "depth", GST_PROPS_INT(format->bpp), + "bpp", GST_PROPS_INT(format->depth), + "endianness", GST_PROPS_INT(format->endianness), + "red_mask", GST_PROPS_INT(format->red_mask), + "green_mask", GST_PROPS_INT(format->green_mask), + "blue_mask", GST_PROPS_INT(format->blue_mask)); + }else{ + caps = GST_CAPS_NEW ("videoflip", "video/raw", + "format", GST_PROPS_FOURCC (fourcc)); + } + + return caps; +} + +struct videoflip_format_struct * +videoflip_find_by_caps(GstCaps *caps) +{ + int i; + + GST_DEBUG (0,"finding %p",caps); + + g_return_val_if_fail(caps != NULL, NULL); + + for (i = 0; i < videoflip_n_formats; i++){ + GstCaps *c; + + c = videoflip_get_caps(videoflip_formats + i); + if(c){ + if(gst_caps_is_always_compatible(caps, c)){ + gst_caps_unref(c); + return videoflip_formats + i; + } + gst_caps_unref(c); + } + } + + return NULL; +} + +void +gst_videoflip_setup (GstVideoflip *videoflip) +{ + if(videoflip->from_width==0 || videoflip->from_height==0){ + return; + } + + switch(videoflip->method){ + case GST_VIDEOFLIP_METHOD_90R: + case GST_VIDEOFLIP_METHOD_90L: + case GST_VIDEOFLIP_METHOD_TRANS: + case GST_VIDEOFLIP_METHOD_OTHER: + videoflip->to_height = videoflip->from_width; + videoflip->to_width = videoflip->from_height; + break; + case GST_VIDEOFLIP_METHOD_IDENTITY: + case GST_VIDEOFLIP_METHOD_180: + case GST_VIDEOFLIP_METHOD_HORIZ: + case GST_VIDEOFLIP_METHOD_VERT: + videoflip->to_height = videoflip->from_height; + videoflip->to_width = videoflip->from_width; + break; + default: + /* FIXME */ + break; + } + + GST_DEBUG (0,"format=%p \"%s\" from %dx%d to %dx%d", + videoflip->format, videoflip->format->fourcc, + videoflip->from_width, videoflip->from_height, + videoflip->to_width, videoflip->to_height); + + if(videoflip->method == GST_VIDEOFLIP_METHOD_IDENTITY){ + GST_DEBUG (0,"videoflip: using passthru"); + videoflip->passthru = TRUE; + videoflip->inited = TRUE; + return; + } + + videoflip->from_buf_size = (videoflip->from_width * videoflip->from_height + * videoflip->format->depth) / 8; + videoflip->to_buf_size = (videoflip->to_width * videoflip->to_height + * videoflip->format->depth) / 8; + + videoflip->inited = TRUE; +} + +static void +gst_videoflip_planar411 (GstVideoflip *scale, unsigned char *dest, unsigned char *src) +{ + int sw = scale->from_width; + int sh = scale->from_height; + int dw = scale->to_width; + int dh = scale->to_height; + + GST_DEBUG (0,"videoflip: scaling planar 4:1:1 %dx%d to %dx%d", sw, sh, dw, dh); + + gst_videoflip_flip(scale, dest, src, sw, sh, dw, dh); + + src += sw*sh; + dest += dw*dh; + + dh = dh>>1; + dw = dw>>1; + sh = sh>>1; + sw = sw>>1; + + gst_videoflip_flip(scale, dest, src, sw, sh, dw, dh); + + src += sw*sh; + dest += dw*dh; + + gst_videoflip_flip(scale, dest, src, sw, sh, dw, dh); +} + +static void +gst_videoflip_flip(GstVideoflip *videoflip, unsigned char *dest, + unsigned char *src, int sw, int sh, int dw, int dh) +{ + 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: + /* FIXME */ + break; + } +} + diff --git a/gst/videoflip/videoflip.h b/gst/videoflip/videoflip.h new file mode 100644 index 00000000..e61cbffe --- /dev/null +++ b/gst/videoflip/videoflip.h @@ -0,0 +1,46 @@ +/* GStreamer + * Copyright (C) <2003> David A. Schleef <ds@schleef.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __VIDEOFLIP_H__ +#define __VIDEOFLIP_H__ + +#include "gstvideoflip.h" + +struct videoflip_format_struct { + char *fourcc; + int depth; + void (*scale)(GstVideoflip *,unsigned char *dest, unsigned char *src); + int bpp; + unsigned int endianness; + unsigned int red_mask; + unsigned int green_mask; + unsigned int blue_mask; +}; + +extern struct videoflip_format_struct videoflip_formats[]; +extern int videoflip_n_formats; + +GstCaps *videoflip_get_caps(struct videoflip_format_struct *format); + +struct videoflip_format_struct *videoflip_find_by_caps(GstCaps *caps); + + +#endif + |