From bf7f88dbb589de79422d59843f4990f2d1f6ffec Mon Sep 17 00:00:00 2001 From: Michael Roitzsch Date: Sun, 1 Dec 2002 14:52:55 +0000 Subject: first Advent - time for some presents: xine's first post plugin CVS patchset: 3398 CVS date: 2002/12/01 14:52:55 --- src/post/.cvsignore | 2 + src/post/Makefile.am | 22 +++++ src/post/planar/.cvsignore | 6 ++ src/post/planar/Makefile.am | 30 ++++++ src/post/planar/invert.c | 224 ++++++++++++++++++++++++++++++++++++++++++++ src/xine-engine/post.c | 168 +++++++++++++++++++++++++++++++++ src/xine-engine/post.h | 118 +++++++++++++++++++++++ 7 files changed, 570 insertions(+) create mode 100644 src/post/.cvsignore create mode 100644 src/post/Makefile.am create mode 100644 src/post/planar/.cvsignore create mode 100644 src/post/planar/Makefile.am create mode 100644 src/post/planar/invert.c create mode 100644 src/xine-engine/post.c create mode 100644 src/xine-engine/post.h diff --git a/src/post/.cvsignore b/src/post/.cvsignore new file mode 100644 index 000000000..282522db0 --- /dev/null +++ b/src/post/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/src/post/Makefile.am b/src/post/Makefile.am new file mode 100644 index 000000000..6f1112a24 --- /dev/null +++ b/src/post/Makefile.am @@ -0,0 +1,22 @@ +SUBDIRS = \ + planar + +debug: + @list='$(SUBDIRS)'; for subdir in $$list; do \ + (cd $$subdir && $(MAKE) $@) || exit; \ + done; + +install-debug: debug + @list='$(SUBDIRS)'; for subdir in $$list; do \ + (cd $$subdir && $(MAKE) $@) || exit; \ + done; + +mostlyclean-generic: + -rm -f *~ \#* .*~ .\#* + + +maintainer-clean-generic: + -@echo "This command is intended for maintainers to use;" + -@echo "it deletes files that may require special tools to rebuild." + -rm -f Makefile.in + diff --git a/src/post/planar/.cvsignore b/src/post/planar/.cvsignore new file mode 100644 index 000000000..7d926a554 --- /dev/null +++ b/src/post/planar/.cvsignore @@ -0,0 +1,6 @@ +Makefile +Makefile.in +.libs +.deps +*.lo +*.la diff --git a/src/post/planar/Makefile.am b/src/post/planar/Makefile.am new file mode 100644 index 000000000..59d4518aa --- /dev/null +++ b/src/post/planar/Makefile.am @@ -0,0 +1,30 @@ +## +## Process this file with automake to produce Makefile.in +## + +AM_CFLAGS = @ANSI_FLAGS@ +DEBUG_CFLAGS = @DEBUG_CFLAGS@ @ANSI_FLAGS@ + +LIBTOOL = $(SHELL) $(top_builddir)/libtool-nofpic + +libdir = $(XINE_PLUGINDIR)/post + +lib_LTLIBRARIES = xineplug_post_invert.la + +xineplug_post_invert_la_SOURCES = invert.c +xineplug_post_invert_la_LIBADD = $(XINE_LIB) +xineplug_post_invert_la_LDFLAGS = -avoid-version -module @XINE_PLUGIN_MIN_SYMS@ + +debug: + @$(MAKE) CFLAGS="$(DEBUG_CFLAGS)" + +install-debug: debug + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +mostlyclean-generic: + -rm -f *~ \#* .*~ .\#* + +maintainer-clean-generic: + -@echo "This command is intended for maintainers to use;" + -@echo "it deletes files that may require special tools to rebuild." + -rm -f Makefile.in diff --git a/src/post/planar/invert.c b/src/post/planar/invert.c new file mode 100644 index 000000000..1f5bdf05b --- /dev/null +++ b/src/post/planar/invert.c @@ -0,0 +1,224 @@ +/* + * Copyright (C) 2000-2002 the xine project + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * $Id: invert.c,v 1.1 2002/12/01 14:52:55 mroi Exp $ + */ + +/* + * simple video inverter plugin + */ + +#include "xine_internal.h" +#include "post.h" + + +/* plugin class initialization function */ +static void *invert_init_plugin(xine_t *xine, void *); + + +/* plugin catalog information */ +plugin_info_t xine_plugin_info[] = { + /* type, API, "name", version, special_info, init_function */ + { PLUGIN_POST, 1, "invert", XINE_VERSION_CODE, NULL, &invert_init_plugin }, + { PLUGIN_NONE, 0, "", 0, NULL, NULL } +}; + + +/* plugin class functions */ +static post_plugin_t *invert_open_plugin(post_class_t *class_gen, int inputs, + xine_audio_port_t **audio_target, + xine_video_port_t **video_target); +static char *invert_get_identifier(post_class_t *class_gen); +static char *invert_get_description(post_class_t *class_gen); +static void invert_class_dispose(post_class_t *class_gen); + +/* plugin instance functions */ +static void invert_dispose(post_plugin_t *this_gen); + +/* rewire function */ +static int invert_rewire(xine_post_out_t *output, void *data); + +/* replaced video_port functions */ +static vo_frame_t *invert_get_frame(xine_video_port_t *port_gen, uint32_t width, + uint32_t height, int ratio_code, + int format, int flags); + +/* replaced vo_frame functions */ +static int invert_draw(vo_frame_t *frame, xine_stream_t *stream); + + +static void *invert_init_plugin(xine_t *xine, void *data) +{ + post_class_t *class = (post_class_t *)malloc(sizeof(post_class_t)); + + if (!class) + return NULL; + + class->open_plugin = invert_open_plugin; + class->get_identifier = invert_get_identifier; + class->get_description = invert_get_description; + class->dispose = invert_class_dispose; + + return class; +} + + +static post_plugin_t *invert_open_plugin(post_class_t *class_gen, int inputs, + xine_audio_port_t **audio_target, + xine_video_port_t **video_target) +{ + post_plugin_t *this = (post_plugin_t *)malloc(sizeof(post_plugin_t)); + xine_post_in_t *input = (xine_post_in_t *)malloc(sizeof(xine_post_in_t)); + xine_post_out_t *output = (xine_post_out_t *)malloc(sizeof(xine_post_out_t)); + post_video_port_t *port; + + if (!this || !input || !output || !video_target || !video_target[0]) { + free(this); + free(input); + free(output); + return NULL; + } + + port = post_intercept_video_port(video_target[0]); + /* replace with our own get_frame function */ + port->port.get_frame = invert_get_frame; + + input->name = "video"; + input->type = XINE_POST_DATA_VIDEO; + input->data = (xine_video_port_t *)&port->port; + + output->name = "inverted video"; + output->type = XINE_POST_DATA_VIDEO; + output->data = (xine_video_port_t **)&port->original_port; + output->rewire = invert_rewire; + + this->xine_post.audio_input = (xine_audio_port_t **)malloc(sizeof(xine_audio_port_t *)); + this->xine_post.audio_input[0] = NULL; + this->xine_post.video_input = (xine_video_port_t **)malloc(sizeof(xine_video_port_t *) * 2); + this->xine_post.video_input[0] = &port->port; + this->xine_post.video_input[1] = NULL; + + this->input = xine_list_new(); + this->output = xine_list_new(); + + xine_list_append_content(this->input, input); + xine_list_append_content(this->output, output); + + this->dispose = invert_dispose; + + return this; +} + +static char *invert_get_identifier(post_class_t *class_gen) +{ + return "invert"; +} + +static char *invert_get_description(post_class_t *class_gen) +{ + return "inverts the colours of every video frame"; +} + +static void invert_class_dispose(post_class_t *class_gen) +{ + free(class_gen); +} + + +static void invert_dispose(post_plugin_t *this) +{ + free(this->xine_post.audio_input); + free(this->xine_post.video_input); + free(xine_list_first_content(this->input)); + free(xine_list_first_content(this->output)); + xine_list_free(this->input); + xine_list_free(this->output); + free(this); +} + + +static int invert_rewire(xine_post_out_t *output, void *data) +{ + if (!data) + return 0; + *(xine_video_port_t **)output->data = (xine_video_port_t *)data; + return 1; +} + + +static vo_frame_t *invert_get_frame(xine_video_port_t *port_gen, uint32_t width, + uint32_t height, int ratio_code, + int format, int flags) +{ + post_video_port_t *port = (post_video_port_t *)port_gen; + vo_frame_t *frame; + + frame = port->original_port->get_frame(port->original_port, + width, height, ratio_code, format, flags); + post_intercept_video_frame(frame, port); + /* replace with our own draw function */ + frame->draw = invert_draw; + return frame; +} + + +static int invert_draw(vo_frame_t *frame, xine_stream_t *stream) +{ + post_video_port_t *port = (post_video_port_t *)frame->port; + vo_frame_t *inverted_frame; + int size, i, skip; + + inverted_frame = port->original_port->get_frame(port->original_port, + frame->width, frame->height, frame->ratio, frame->format, VO_BOTH_FIELDS); + inverted_frame->pts = frame->pts; + inverted_frame->duration = frame->duration; + + switch (inverted_frame->format) { + case XINE_IMGFMT_YUY2: + size = inverted_frame->pitches[0] * inverted_frame->height; + for (i = 0; i < size; i++) + inverted_frame->base[0][i] = 0xff - frame->base[0][i]; + break; + case XINE_IMGFMT_YV12: + /* Y */ + size = inverted_frame->pitches[0] * inverted_frame->height; + for (i = 0; i < size; i++) + inverted_frame->base[0][i] = 0xff - frame->base[0][i]; + /* U */ + size = inverted_frame->pitches[1] * ((inverted_frame->height + 1) / 2); + for (i = 0; i < size; i++) + inverted_frame->base[1][i] = 0xff - frame->base[1][i]; + /* U */ + size = inverted_frame->pitches[2] * ((inverted_frame->height + 1) / 2); + for (i = 0; i < size; i++) + inverted_frame->base[2][i] = 0xff - frame->base[2][i]; + break; + default: + printf("invert: cannot handle image format %i\n", frame->format); + inverted_frame->free(inverted_frame); + inverted_frame = frame; + } + post_restore_video_frame(frame, port); + skip = inverted_frame->draw(inverted_frame, stream); + if (frame != inverted_frame) + inverted_frame->free(inverted_frame); + frame->vpts = inverted_frame->vpts; + + return skip; +} diff --git a/src/xine-engine/post.c b/src/xine-engine/post.c new file mode 100644 index 000000000..c65e53400 --- /dev/null +++ b/src/xine-engine/post.c @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2000-2002 the xine project + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * $Id: post.c,v 1.1 2002/12/01 14:52:55 mroi Exp $ + */ + +/* + * some helper functions for post plugins + */ + +#include "post.h" + + +/* dummy intercept functions that just pass the call on to the original port */ +static uint32_t post_video_get_capabilities(xine_video_port_t *port_gen) { + post_video_port_t *port = (post_video_port_t *)port_gen; + return port->original_port->get_capabilities(port->original_port); +} + +static void post_video_open(xine_video_port_t *port_gen, xine_stream_t *stream) { + post_video_port_t *port = (post_video_port_t *)port_gen; + port->original_port->open(port->original_port, stream); +} + +static vo_frame_t *post_video_get_frame(xine_video_port_t *port_gen, uint32_t width, + uint32_t height, int ratio_code, int format, int flags) { + post_video_port_t *port = (post_video_port_t *)port_gen; + return port->original_port->get_frame(port->original_port, + width, height, ratio_code, format, flags); +} + +static vo_frame_t *post_video_get_last_frame(xine_video_port_t *port_gen) { + post_video_port_t *port = (post_video_port_t *)port_gen; + return port->original_port->get_last_frame(port->original_port); +} + +static void post_video_enable_ovl(xine_video_port_t *port_gen, int ovl_enable) { + post_video_port_t *port = (post_video_port_t *)port_gen; + port->original_port->enable_ovl(port->original_port, ovl_enable); +} + +static void post_video_close(xine_video_port_t *port_gen, xine_stream_t *stream) { + post_video_port_t *port = (post_video_port_t *)port_gen; + port->original_port->close(port->original_port, stream); +} + +static void post_video_exit(xine_video_port_t *port_gen) { + post_video_port_t *port = (post_video_port_t *)port_gen; + port->original_port->exit(port->original_port); +} + +static video_overlay_instance_t *post_video_get_overlay_instance(xine_video_port_t *port_gen) { + post_video_port_t *port = (post_video_port_t *)port_gen; + return port->original_port->get_overlay_instance(port->original_port); +} + +static void post_video_flush(xine_video_port_t *port_gen) { + post_video_port_t *port = (post_video_port_t *)port_gen; + port->original_port->flush(port->original_port); +} + + +post_video_port_t *post_intercept_video_port(xine_video_port_t *original) { + post_video_port_t *post_port = (post_video_port_t *)malloc(sizeof(post_video_port_t)); + + if (!post_port) + return NULL; + + post_port->port.get_capabilities = post_video_get_capabilities; + post_port->port.open = post_video_open; + post_port->port.get_frame = post_video_get_frame; + post_port->port.get_last_frame = post_video_get_last_frame; + post_port->port.enable_ovl = post_video_enable_ovl; + post_port->port.close = post_video_close; + post_port->port.exit = post_video_exit; + post_port->port.get_overlay_instance = post_video_get_overlay_instance; + post_port->port.flush = post_video_flush; + post_port->port.driver = original->driver; + + post_port->original_port = original; + + return post_port; +} + + +/* functions intercepting frame calls */ +static void post_frame_free(vo_frame_t *vo_img) { + post_video_port_t *port = (post_video_port_t *)vo_img->port; + post_restore_video_frame(vo_img, port); + vo_img->free(vo_img); +} + +static void post_frame_copy(vo_frame_t *vo_img, uint8_t **src) { + post_video_port_t *port = (post_video_port_t *)vo_img->port; + vo_img->port = port->original_port; + port->original_frame.copy(vo_img, src); + vo_img->port = &port->port; +} + +static void post_frame_field(vo_frame_t *vo_img, int which_field) { + post_video_port_t *port = (post_video_port_t *)vo_img->port; + vo_img->port = port->original_port; + port->original_frame.field(vo_img, which_field); + vo_img->port = &port->port; +} + +static int post_frame_draw(vo_frame_t *vo_img, xine_stream_t *stream) { + post_video_port_t *port = (post_video_port_t *)vo_img->port; + post_restore_video_frame(vo_img, port); + return vo_img->draw(vo_img, stream); +} + +static void post_frame_displayed(vo_frame_t *vo_img) { + post_video_port_t *port = (post_video_port_t *)vo_img->port; + post_restore_video_frame(vo_img, port); + vo_img->displayed(vo_img); +} + +static void post_frame_dispose(vo_frame_t *vo_img) { + post_video_port_t *port = (post_video_port_t *)vo_img->port; + post_restore_video_frame(vo_img, port); + vo_img->dispose(vo_img); +} + + +void post_intercept_video_frame(vo_frame_t *frame, post_video_port_t *port) { + port->original_frame.port = frame->port; + port->original_frame.free = frame->free; + port->original_frame.copy = frame->copy; + port->original_frame.field = frame->field; + port->original_frame.draw = frame->draw; + port->original_frame.displayed = frame->displayed; + port->original_frame.dispose = frame->dispose; + + frame->port = &port->port; + frame->free = post_frame_free; + frame->copy = frame->copy ? post_frame_copy : NULL; /* this one can be NULL */ + frame->field = post_frame_field; + frame->draw = post_frame_draw; + frame->displayed = post_frame_displayed; + frame->dispose = post_frame_dispose; +} + +void post_restore_video_frame(vo_frame_t *frame, post_video_port_t *port) { + frame->port = port->original_port; + frame->free = port->original_frame.free; + frame->copy = port->original_frame.copy; + frame->field = port->original_frame.field; + frame->draw = port->original_frame.draw; + frame->displayed = port->original_frame.displayed; + frame->dispose = port->original_frame.dispose; +} diff --git a/src/xine-engine/post.h b/src/xine-engine/post.h new file mode 100644 index 000000000..373480c46 --- /dev/null +++ b/src/xine-engine/post.h @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2000-2002 the xine project + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * $Id: post.h,v 1.1 2002/12/01 14:52:56 mroi Exp $ + * + * post plugin definitions + * + */ + +#ifndef XINE_POST_H +#define XINE_POST_H + +#include "xine.h" +#include "video_out.h" +#include "xineutils.h" + +#define POST_PLUGIN_IFACE_VERSION 1 + + +typedef struct post_class_s post_class_t; +typedef struct post_plugin_s post_plugin_t; + + +struct post_class_s { + + /* + * open a new instance of this plugin class + */ + post_plugin_t* (*open_plugin) (post_class_t *this, int inputs, + xine_audio_port_t **audio_target, + xine_video_port_t **video_target); + + /* + * return short, human readable identifier for this plugin class + */ + char* (*get_identifier) (post_class_t *this); + + /* + * return human readable (verbose = 1 line) description for + * this plugin class + */ + char* (*get_description) (post_class_t *this); + + /* + * free all class-related resources + */ + + void (*dispose) (post_class_t *this); +}; + +struct post_plugin_s { + + /* public part of the plugin */ + xine_post_t xine_post; + + /* + * the connections announced by the plugin + * the plugin must fill these with xine_post_{in,out}_t on init + */ + xine_list_t *input; + xine_list_t *output; + + /* + * close down, free all resources + */ + void (*dispose) (post_plugin_t *this); + + /* plugins don't have to care for the stuff below */ + + /* used when the user requests a list of all inputs/outputs */ + const char **input_ids; + const char **output_ids; + + /* used by plugin loader */ + void *node; +}; + + +/* helper structure for intercepting video port calls */ +typedef struct post_video_port_s post_video_port_t; +struct post_video_port_s { + + /* the new public port with replaced function pointers */ + xine_video_port_t port; + + /* the original port to call its functions from inside yours */ + xine_video_port_t *original_port; + + /* here you can keep information about the frames */ + vo_frame_t original_frame; +}; + +/* use this to create a new video port in which port functions can + * be replaced with own implementation */ +post_video_port_t *post_intercept_video_port(xine_video_port_t *port); + +/* use this to modify a frame to so that functions can be replaced + * with own implementations */ +void post_intercept_video_frame(vo_frame_t *frame, post_video_port_t *port); +void post_restore_video_frame(vo_frame_t *frame, post_video_port_t *port); + +#endif -- cgit v1.2.3