-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Hello all,
recently, I had some problems with creating special maskings,
and I didn't find any solution with the existing plugins.
So I wrote a new plugin, see the attached diff.
The Problem
- -----------
On the "Mask Track" we have some interesting Footage, in my case
some animated fractals. By using Color correction, Histogram and
Chromakey, we can create an animated Mask out of this
But now we want to apply this mask to the "Content Track", which
contains quite different footage. We deliberately don't want to
apply Chroma keying to the Content Track, as much as we don't want
to overlay the Mask Track ontop of the Content Track (Which could
be done with the overlay plugin, e.g. with "Multiply" mode).
We just want the content to use the Alpha Channel of the Mask track.
"Reroute" Plugin
- ----------------
This new Plugin is a multitrack video realtime effect, similar to the
Overlayer, i.e. it works only as a shared effect, it has to be applied
simultanousely to two tracks. You can chosse which of this tracks
will be the target (output) track. Further, you can choose between
three operation modes:
- replace Target: just overwrite everything on the target track with
the contents of the source track /at the point where the plugins
are inserted in the render pipeline/
- Components only: replace the Components (RGB or YUV) of the target
track by the Components of the source track (again at the point
where the plugins are inserted), but retain the Alpha of the
target track
- Alpha replace: same principle, other way round: overwrite the
Alpha of the target and retain the Component content.
See the screenshot: http://ichthyostega.de/cinelerra/plugin/reroute-demo1.png
Here the Content Track "Top" is pojected to the left, and the Mask track
with the animated Fractal is shown at the right side. The Content Track
has its own Mask (applied after plugins of course, otherwise it would
be replaced by the new alpha). On the Mask Track, I use a Chromakey
to mask out some of the middle blue shades. Finally, my new plugin
overwrites the Alpha channel of the target Track (which here is the
top one) with the contents of the Alpha channel in the Mask track.
Needless to say, because the contents of the Mask track can be
processed further (blur, color correction, further masking)
after the plugin, this openes endles masking and compositing
possibilities.
Question to the Cinelerra-Gurus: did I miss something?
Did I overlook the obvious solution? Is my Plugin acceptable?
Cheers,
Hermann Vosseler
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
iD8DBQFGXLaoZbZrB6HelLIRAj91AKC0FZ4+7M/iDN34bNba5j/FQSaVngCg+uBs
8U+rDmUT+4zHzggo6Xz0PVQ=
=WPKb
-----END PGP SIGNATURE-----
____________________________________________________
A new Video/realtime Plugin for Cinelerra: "Reroute"
May 2007
_________________________________________
(c) Hermann VoÃeler <[EMAIL PROTECTED]>
This code is Free Software and may be used and redistibuted
under the terms and conditions of the
GNU GENERAL PUBLIC LICENSE, Version 2
It is based on Cinelerra-SVN -r1008 and can be pulled from GIT at:
git://git.pipapo.org/git/cinelerra/ichthyo/#plugin-reroute
The new plugin enables to selectively transfer the Alpha channel
or the Components (RGB or YUV) or both from a source track to
a target track, partially overwriting the target's contents.
It works as a shared plugin. The typical usage scenario is
to build up a possibly animated Mask in one track and then
to transfer the Alpha channel to another content track
====================================================================================
diff --git a/configure.in b/configure.in
index 94e2df5..f577b4c 100644
--- a/configure.in
+++ b/configure.in
@@ -512,6 +512,7 @@ AC_OUTPUT(Makefile cinelerra-cvs-current.spec po/Makefile.in \
plugins/overlayaudio/Makefile \
plugins/pitch/Makefile \
plugins/polar/Makefile \
+ plugins/reroute/Makefile
plugins/reframert/Makefile
plugins/reframe/Makefile plugins/resample/Makefile plugins/reverb/Makefile \
plugins/reverseaudio/Makefile plugins/reversevideo/Makefile plugins/rgb601/Makefile \
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 02937db..ca39e82 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -74,6 +74,7 @@ SUBDIRS= \
radialblur \
reframe \
reframert \
+ reroute \
resample \
reverb \
reverseaudio \
diff --git a/plugins/reroute/.gitignore b/plugins/reroute/.gitignore
new file mode 100644
index 0000000..282522d
--- /dev/null
+++ b/plugins/reroute/.gitignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/plugins/reroute/Makefile.am b/plugins/reroute/Makefile.am
new file mode 100644
index 0000000..7138533
--- /dev/null
+++ b/plugins/reroute/Makefile.am
@@ -0,0 +1,11 @@
+plugin_LTLIBRARIES = reroute.la
+reroute_la_LDFLAGS = -avoid-version -module -shared
+reroute_la_LIBADD =
+reroute_la_SOURCES = reroute.C
+AM_CXXFLAGS = $(LARGEFILE_CFLAGS)
+
+INCLUDES = -I$(top_srcdir)/guicast -I$(top_srcdir)/cinelerra -I$(top_srcdir)/quicktime
+LIBTOOL = $(SHELL) $(top_builddir)/libtool $(LTCXX_FLAGS)
+
+noinst_HEADERS = picon_png.h
+EXTRA_DIST = picon.png
diff --git a/plugins/reroute/picon.png b/plugins/reroute/picon.png
new file mode 100644
index 0000000..2bbd087
Binary files /dev/null and b/plugins/reroute/picon.png differ
diff --git a/plugins/reroute/picon_png.h b/plugins/reroute/picon_png.h
new file mode 100644
index 0000000..c4407cf
--- /dev/null
+++ b/plugins/reroute/picon_png.h
@@ -0,0 +1,67 @@
+#ifndef PICON_PNG_H
+#define PICON_PNG_H
+
+static unsigned char picon_png[] =
+{
+ 0x00, 0x00, 0x03, 0x9e,
+0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52,
+0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x32, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1e, 0x3f, 0x88,
+0xb1, 0x00, 0x00, 0x00, 0x06, 0x62, 0x4b, 0x47, 0x44, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xa0,
+0xbd, 0xa7, 0x93, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x10, 0x00,
+0x00, 0x0b, 0x10, 0x01, 0xad, 0x23, 0xbd, 0x75, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45,
+0x07, 0xd7, 0x05, 0x1d, 0x14, 0x30, 0x0c, 0x64, 0xa3, 0xf7, 0x71, 0x00, 0x00, 0x00, 0x2b, 0x74,
+0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x72, 0x65, 0x2d, 0x72, 0x6f,
+0x75, 0x74, 0x65, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x20, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e,
+0x20, 0x66, 0x6f, 0x72, 0x20, 0x43, 0x69, 0x6e, 0x65, 0x6c, 0x65, 0x72, 0x72, 0x61, 0xad, 0x21,
+0x68, 0xa7, 0x00, 0x00, 0x02, 0xf4, 0x49, 0x44, 0x41, 0x54, 0x68, 0xde, 0xed, 0x59, 0xcf, 0x6f,
+0x12, 0x41, 0x18, 0x7d, 0x1f, 0x41, 0x4d, 0xc4, 0x3f, 0xa0, 0x44, 0x8d, 0xc6, 0x94, 0x78, 0x31,
+0x1e, 0x1a, 0xb9, 0x14, 0x43, 0xbc, 0x58, 0x93, 0xc6, 0x03, 0x04, 0x96, 0x43, 0xf5, 0xd4, 0x26,
+0x26, 0xc6, 0x63, 0x8f, 0x70, 0x84, 0xbb, 0x26, 0x7a, 0x69, 0x42, 0x6f, 0xed, 0x61, 0x59, 0xa4,
+0x89, 0xd1, 0x44, 0x39, 0x19, 0xa1, 0xd1, 0x1e, 0x38, 0x94, 0x3b, 0x49, 0xa3, 0x09, 0x3d, 0x78,
+0x14, 0x25, 0x56, 0x18, 0x0f, 0x74, 0xcb, 0x2c, 0x05, 0xba, 0x33, 0xfb, 0x83, 0x85, 0xf4, 0x4b,
+0x08, 0x99, 0x2c, 0xcc, 0xce, 0xdb, 0xf7, 0xbd, 0xef, 0x7d, 0x33, 0x4b, 0x44, 0xc4, 0x18, 0x63,
+0xb0, 0x18, 0x04, 0xfb, 0x83, 0x89, 0xdc, 0xdb, 0x87, 0x19, 0x09, 0x3f, 0x11, 0x81, 0x31, 0x66,
+0x80, 0x9f, 0xe4, 0x06, 0xc5, 0x67, 0xfd, 0x01, 0xdb, 0x18, 0x78, 0x14, 0x44, 0x8e, 0x2e, 0xae,
+0xa2, 0x66, 0x01, 0x00, 0x11, 0x25, 0x0d, 0x00, 0xa8, 0x16, 0x72, 0x86, 0x31, 0x7f, 0xff, 0xd9,
+0x61, 0xc4, 0xcb, 0x8b, 0x1b, 0xc5, 0x84, 0x3e, 0xe6, 0xe3, 0x9c, 0x11, 0x37, 0x62, 0x14, 0x13,
+0xfa, 0x18, 0xc8, 0xf4, 0x19, 0xb1, 0xa1, 0xf4, 0x7a, 0x83, 0x11, 0x2f, 0x03, 0x39, 0xd7, 0xc8,
+0x54, 0x6b, 0xc4, 0xab, 0x20, 0xe2, 0xb1, 0xe5, 0xe9, 0x67, 0x24, 0x1e, 0x5b, 0x66, 0x33, 0xa3,
+0x91, 0xf5, 0x95, 0xc5, 0xd9, 0xd0, 0x48, 0x44, 0x49, 0x4f, 0xb7, 0x46, 0xf4, 0xb4, 0x92, 0xaa,
+0x5a, 0x44, 0x04, 0x78, 0xc0, 0x4f, 0x74, 0x10, 0xeb, 0x2b, 0x8b, 0xa8, 0x16, 0x72, 0xe2, 0x1a,
+0x71, 0xba, 0x1d, 0x17, 0x01, 0xf1, 0xb6, 0xf4, 0x5e, 0xde, 0x47, 0xba, 0xdd, 0xae, 0x67, 0x04,
+0x6e, 0x86, 0x89, 0x89, 0x68, 0x44, 0x53, 0xf3, 0x4c, 0x8f, 0x8a, 0x9a, 0x75, 0x2c, 0x7f, 0x5d,
+0xa9, 0x5a, 0xfa, 0x93, 0xbc, 0x9f, 0xca, 0xd0, 0x38, 0x5d, 0x98, 0x65, 0xc2, 0x73, 0x3e, 0xc2,
+0x83, 0x98, 0x0a, 0x46, 0x86, 0xe5, 0xb4, 0x15, 0x26, 0x5c, 0xd7, 0x88, 0xa6, 0xe6, 0x99, 0x9d,
+0xee, 0x3d, 0x51, 0x46, 0x12, 0xca, 0xea, 0xa9, 0x9c, 0x36, 0xdb, 0x4b, 0x79, 0x5a, 0x23, 0x76,
+0xea, 0xc2, 0x55, 0x46, 0x78, 0x5f, 0x88, 0xc7, 0x76, 0x0d, 0xa6, 0x27, 0xcb, 0x84, 0x27, 0x7a,
+0x2d, 0xb3, 0x4c, 0x90, 0x60, 0xbb, 0xe1, 0x77, 0x5a, 0xe8, 0x7c, 0x17, 0x6b, 0x96, 0x09, 0x1d,
+0x84, 0x67, 0x34, 0x92, 0x50, 0x56, 0x85, 0xff, 0x43, 0x92, 0x8d, 0x9f, 0xdf, 0x69, 0x7d, 0x88,
+0xe4, 0xfc, 0x00, 0x08, 0x36, 0x71, 0x8d, 0x9c, 0xe5, 0x1f, 0x76, 0x32, 0xe1, 0x38, 0x23, 0x73,
+0x68, 0x9a, 0x62, 0xa2, 0x07, 0x20, 0x63, 0xf9, 0x5c, 0xcb, 0x6f, 0x25, 0x65, 0xac, 0x06, 0xd9,
+0xb8, 0x11, 0xb2, 0x83, 0x11, 0x92, 0xdd, 0x73, 0x57, 0xd4, 0xde, 0x6b, 0x99, 0x61, 0x5d, 0xb1,
+0xb0, 0x8f, 0xf8, 0x7c, 0x3e, 0x21, 0x26, 0x74, 0x83, 0x8b, 0x28, 0x69, 0x68, 0x6a, 0xfe, 0x44,
+0x98, 0xfc, 0xa7, 0xb4, 0xf3, 0x01, 0x9d, 0x4e, 0x07, 0x00, 0xb0, 0xf3, 0x69, 0x0f, 0x44, 0x84,
+0x70, 0x38, 0x3c, 0x72, 0x5e, 0x3b, 0xde, 0xfd, 0x59, 0x62, 0xa4, 0xba, 0xbb, 0xa7, 0x83, 0x30,
+0xc4, 0xd6, 0x76, 0x11, 0x5b, 0xdb, 0x7e, 0x68, 0x6a, 0x1e, 0x85, 0x72, 0x0d, 0x00, 0xf0, 0x30,
+0x7c, 0x7d, 0x6c, 0xce, 0x57, 0xd4, 0x2c, 0xeb, 0x6b, 0xc6, 0x61, 0x8d, 0xf0, 0x13, 0x7d, 0x6f,
+0xfe, 0xc4, 0xeb, 0x37, 0xf9, 0x61, 0x29, 0x76, 0x02, 0x2c, 0x99, 0x5a, 0x23, 0x00, 0x2c, 0x10,
+0xb8, 0x8c, 0x3b, 0x91, 0x25, 0x14, 0x0b, 0x9b, 0xc7, 0x57, 0x82, 0x98, 0x43, 0xd3, 0x1b, 0xbd,
+0x56, 0xe9, 0xe3, 0x37, 0x1c, 0x1d, 0xfd, 0xc3, 0xc2, 0xc2, 0x5d, 0xd4, 0x6a, 0xfb, 0x34, 0x00,
+0x88, 0xf1, 0xa0, 0x5a, 0xad, 0xdf, 0x78, 0xf2, 0xf4, 0x39, 0xf1, 0xe5, 0xf9, 0x10, 0x41, 0x03,
+0xb0, 0x1e, 0xe8, 0x8c, 0xb4, 0x46, 0xfc, 0x32, 0xd5, 0x2a, 0xa2, 0xa4, 0xf1, 0x22, 0x57, 0x00,
+0x00, 0x3c, 0x5a, 0x7a, 0x80, 0x5a, 0x6d, 0x7f, 0x58, 0x01, 0x60, 0xa3, 0x0a, 0xc2, 0x31, 0x53,
+0x06, 0xcf, 0xd1, 0xbf, 0xf9, 0x6b, 0x42, 0x8c, 0xc8, 0xea, 0xac, 0xd1, 0x68, 0x00, 0x00, 0x42,
+0xf3, 0xb7, 0x2c, 0xa5, 0xc4, 0xb8, 0x85, 0x0b, 0x69, 0x44, 0x04, 0x08, 0x3f, 0x51, 0xab, 0xf5,
+0x0b, 0x00, 0x10, 0xb8, 0x12, 0x90, 0x2a, 0xcf, 0x9e, 0x39, 0x45, 0xb9, 0x74, 0xf1, 0x02, 0xfe,
+0xb4, 0xff, 0xa2, 0xdd, 0x6e, 0x4f, 0xac, 0x57, 0x93, 0xee, 0xb5, 0x78, 0x1f, 0x99, 0x0f, 0xdd,
+0x06, 0x00, 0x1c, 0x1c, 0xfc, 0x18, 0x6a, 0x0d, 0x6e, 0xef, 0x73, 0xa4, 0x19, 0x89, 0x46, 0xa3,
+0xa8, 0xd7, 0xeb, 0x28, 0x97, 0x3f, 0x9f, 0xf5, 0x53, 0x26, 0x9b, 0x5e, 0xae, 0xf8, 0xc8, 0xbd,
+0x1b, 0xbd, 0x33, 0xe3, 0x2f, 0x95, 0xaf, 0x83, 0x8b, 0x9d, 0xc8, 0x69, 0xb8, 0x34, 0x23, 0xa1,
+0x9b, 0x41, 0x24, 0x12, 0x8f, 0xa1, 0x69, 0xef, 0x46, 0xa5, 0xd3, 0x29, 0x3f, 0x11, 0x65, 0xc6,
+0x15, 0x1f, 0x01, 0x80, 0x43, 0x6c, 0xe2, 0xda, 0xd5, 0x20, 0x5e, 0xbe, 0xda, 0x18, 0x55, 0xa9,
+0xc8, 0x2d, 0x86, 0x2c, 0xf5, 0x5a, 0xc9, 0xd4, 0x9a, 0x99, 0x12, 0x2b, 0x5d, 0x7e, 0x85, 0x35,
+0x62, 0xf6, 0x45, 0xcf, 0xb8, 0x89, 0x26, 0x1d, 0xff, 0x01, 0x33, 0x26, 0xd9, 0x87, 0x68, 0xa3,
+0x5a, 0x64, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
+};
+
+#endif
diff --git a/plugins/reroute/reroute.C b/plugins/reroute/reroute.C
new file mode 100644
index 0000000..16a595b
--- /dev/null
+++ b/plugins/reroute/reroute.C
@@ -0,0 +1,553 @@
+#include "bcdisplayinfo.h"
+#include "clip.h"
+#include "bchash.h"
+#include "filexml.h"
+#include "guicast.h"
+#include "keyframe.h"
+#include "language.h"
+#include "overlayframe.h"
+#include "picon_png.h"
+#include "pluginvclient.h"
+#include "vframe.h"
+
+#include <string.h>
+#include <stdint.h>
+
+
+class Reroute;
+class RerouteWindow;
+
+
+class RerouteConfig
+{
+public:
+ RerouteConfig();
+
+
+
+ static char* operation_to_text(int operation);
+ int operation;
+ enum
+ {
+ REPLACE,
+ REPLACE_COMPONENTS,
+ REPLACE_ALPHA
+ };
+
+ static char* output_to_text(int output_track);
+ int output_track;
+ enum
+ {
+ TOP,
+ BOTTOM
+ };
+};
+
+
+
+
+
+
+class RerouteOperation : public BC_PopupMenu
+{
+public:
+ RerouteOperation(Reroute *plugin,
+ int x,
+ int y);
+ void create_objects();
+ int handle_event();
+ Reroute *plugin;
+};
+
+class RerouteOutput : public BC_PopupMenu
+{
+public:
+ RerouteOutput(Reroute *plugin,
+ int x,
+ int y);
+ void create_objects();
+ int handle_event();
+ Reroute *plugin;
+};
+
+
+class RerouteWindow : public BC_Window
+{
+public:
+ RerouteWindow(Reroute *plugin, int x, int y);
+ ~RerouteWindow();
+
+ void create_objects();
+ int close_event();
+
+ Reroute *plugin;
+ RerouteOperation *operation;
+ RerouteOutput *output;
+};
+
+
+PLUGIN_THREAD_HEADER(Reroute, RerouteThread, RerouteWindow)
+
+
+
+class Reroute : public PluginVClient
+{
+public:
+ Reroute(PluginServer *server);
+ ~Reroute();
+
+
+ PLUGIN_CLASS_MEMBERS(RerouteConfig, RerouteThread);
+
+ int process_buffer(VFrame **frame, int64_t start_position, double frame_rate);
+ int is_realtime();
+ int is_multichannel();
+ int load_defaults();
+ int save_defaults();
+ void save_data(KeyFrame *keyframe);
+ void read_data(KeyFrame *keyframe);
+ void update_gui();
+
+ int output_track;
+ int input_track;
+};
+
+
+
+
+
+
+
+
+
+
+
+
+RerouteConfig::RerouteConfig()
+{
+ operation = RerouteConfig::REPLACE;
+ output_track = RerouteConfig::TOP;
+}
+
+
+char* RerouteConfig::operation_to_text(int operation)
+{
+ switch(operation)
+ {
+ case RerouteConfig::REPLACE: return _("replace Target");
+ case RerouteConfig::REPLACE_COMPONENTS: return _("Components only");
+ case RerouteConfig::REPLACE_ALPHA: return _("Alpha replace");
+ }
+ return "";
+}
+
+char* RerouteConfig::output_to_text(int output_track)
+{
+ switch(output_track)
+ {
+ case RerouteConfig::TOP: return _("Top");
+ case RerouteConfig::BOTTOM: return _("Bottom");
+ }
+ return "";
+}
+
+
+
+
+
+
+
+
+
+RerouteWindow::RerouteWindow(Reroute *plugin, int x, int y)
+ : BC_Window(plugin->gui_string,
+ x,
+ y,
+ 300,
+ 160,
+ 300,
+ 160,
+ 0,
+ 0,
+ 1)
+{
+ this->plugin = plugin;
+}
+
+RerouteWindow::~RerouteWindow()
+{
+}
+
+void RerouteWindow::create_objects()
+{
+ int x = 10, y = 10;
+
+ BC_Title *title;
+ add_subwindow(title = new BC_Title(x, y, _("Target track:")));
+
+ int col2 = title->get_w() + 5;
+ add_subwindow(output = new RerouteOutput(plugin,
+ x + col2,
+ y));
+ output->create_objects();
+
+ y += 30;
+ add_subwindow(title = new BC_Title(x, y, _("Operation:")));
+ add_subwindow(operation = new RerouteOperation(plugin,
+ x + col2,
+ y));
+ operation->create_objects();
+
+ show_window();
+ flush();
+}
+
+WINDOW_CLOSE_EVENT(RerouteWindow)
+
+
+
+
+
+
+
+RerouteOperation::RerouteOperation(Reroute *plugin,
+ int x,
+ int y)
+ : BC_PopupMenu(x,
+ y,
+ 150,
+ RerouteConfig::operation_to_text(plugin->config.operation),
+ 1)
+{
+ this->plugin = plugin;
+}
+
+void RerouteOperation::create_objects()
+{
+ add_item(new BC_MenuItem(
+ RerouteConfig::operation_to_text(
+ RerouteConfig::REPLACE)));
+ add_item(new BC_MenuItem(
+ RerouteConfig::operation_to_text(
+ RerouteConfig::REPLACE_COMPONENTS)));
+ add_item(new BC_MenuItem(
+ RerouteConfig::operation_to_text(
+ RerouteConfig::REPLACE_ALPHA)));
+}
+
+int RerouteOperation::handle_event()
+{
+ char *text = get_text();
+
+ if(!strcmp(text,
+ RerouteConfig::operation_to_text(
+ RerouteConfig::REPLACE)))
+ plugin->config.operation = RerouteConfig::REPLACE;
+ else
+ if(!strcmp(text,
+ RerouteConfig::operation_to_text(
+ RerouteConfig::REPLACE_COMPONENTS)))
+ plugin->config.operation = RerouteConfig::REPLACE_COMPONENTS;
+ else
+ if(!strcmp(text,
+ RerouteConfig::operation_to_text(
+ RerouteConfig::REPLACE_ALPHA)))
+ plugin->config.operation = RerouteConfig::REPLACE_ALPHA;
+
+ plugin->send_configure_change();
+ return 1;
+}
+
+
+RerouteOutput::RerouteOutput(Reroute *plugin,
+ int x,
+ int y)
+ : BC_PopupMenu(x,
+ y,
+ 100,
+ RerouteConfig::output_to_text(plugin->config.output_track),
+ 1)
+{
+ this->plugin = plugin;
+}
+
+void RerouteOutput::create_objects()
+{
+ add_item(new BC_MenuItem(
+ RerouteConfig::output_to_text(
+ RerouteConfig::TOP)));
+ add_item(new BC_MenuItem(
+ RerouteConfig::output_to_text(
+ RerouteConfig::BOTTOM)));
+}
+
+int RerouteOutput::handle_event()
+{
+ char *text = get_text();
+
+ if(!strcmp(text,
+ RerouteConfig::output_to_text(
+ RerouteConfig::TOP)))
+ plugin->config.output_track = RerouteConfig::TOP;
+ else
+ if(!strcmp(text,
+ RerouteConfig::output_to_text(
+ RerouteConfig::BOTTOM)))
+ plugin->config.output_track = RerouteConfig::BOTTOM;
+
+ plugin->send_configure_change();
+ return 1;
+}
+
+
+
+
+
+/***** Register Plugin ***********************************/
+
+PLUGIN_THREAD_OBJECT(Reroute, RerouteThread, RerouteWindow)
+
+REGISTER_PLUGIN(Reroute)
+
+
+
+
+
+
+
+Reroute::Reroute(PluginServer *server)
+ : PluginVClient(server)
+{
+ PLUGIN_CONSTRUCTOR_MACRO
+}
+
+
+Reroute::~Reroute()
+{
+ PLUGIN_DESTRUCTOR_MACRO
+}
+
+
+
+/*
+ * Main operation
+ *
+ *****************************************/
+template<class TYPE, int COMPONENTS>
+struct px_type
+{
+ static inline
+ void transfer(VFrame*, VFrame*, bool, bool) ;
+};
+
+template<class TYPE, int COMPONENTS>
+void px_type<TYPE,COMPONENTS>::transfer(VFrame *source, VFrame *target, bool do_components, bool do_alpha)
+//partially overwrite target data buffer
+{
+ int w = target->get_w();
+ int h = source->get_h();
+ do_alpha = do_alpha && (COMPONENTS > 3); // only possible if we have alpha
+
+ for(int i = 0; i < h; i++)
+ {
+ TYPE *inpx = (TYPE*)source->get_rows()[i];
+ TYPE *outpx = (TYPE*)target->get_rows()[i];
+
+ for(int j = 0; j < w; j++)
+ {
+ if(do_components)
+ {
+ outpx[0] = inpx[0];
+ outpx[1] = inpx[1];
+ outpx[2] = inpx[2];
+ }
+ if(do_alpha)
+ outpx[3] = inpx[3];
+
+ inpx += COMPONENTS;
+ outpx += COMPONENTS;
+ }
+ }
+}
+
+
+
+int Reroute::process_buffer(VFrame **frame,
+ int64_t start_position,
+ double frame_rate)
+{
+ load_configuration();
+
+ bool do_components, do_alpha;
+ switch(config.operation)
+ {
+ case RerouteConfig::REPLACE: do_components = do_alpha=true; break;
+ case RerouteConfig::REPLACE_ALPHA: do_components=false; do_alpha=true; break;
+ case RerouteConfig::REPLACE_COMPONENTS: do_components=true; do_alpha=false; break;
+ }
+
+ if(config.output_track == RerouteConfig::TOP)
+ {
+ input_track = get_total_buffers() - 1;
+ output_track = 0;
+ }
+ else
+ {
+ input_track = 0;
+ output_track = get_total_buffers() - 1;
+ }
+
+
+ // output buffers for source and target track
+ VFrame *source = frame[input_track];
+ VFrame *target = frame[output_track];
+
+ // input track always passed through unaltered
+ read_frame(source,
+ input_track,
+ start_position,
+ frame_rate,
+ false ); // no OpenGL support
+
+ // no real operation necessary
+ // unless applied to multiple tracks....
+ if(get_total_buffers() <= 1)
+ return 0;
+
+ if(config.operation == RerouteConfig::REPLACE)
+ {
+ target->copy_from(source);
+ return 0;
+ }
+
+
+ // prepare data for output track
+ // (to be overidden partially)
+ read_frame(target,
+ output_track,
+ start_position,
+ frame_rate);
+
+ switch(source->get_color_model())
+ {
+ case BC_RGB_FLOAT:
+ px_type<float,3>::transfer(source,target, do_components,do_alpha);
+ break;
+ case BC_RGBA_FLOAT:
+ px_type<float,4>::transfer(source,target, do_components,do_alpha);
+ break;
+ case BC_RGB888:
+ case BC_YUV888:
+ px_type<unsigned char,3>::transfer(source,target, do_components,do_alpha);
+ break;
+ case BC_RGBA8888:
+ case BC_YUVA8888:
+ px_type<unsigned char,4>::transfer(source,target, do_components,do_alpha);
+ break;
+ case BC_RGB161616:
+ case BC_YUV161616:
+ px_type<uint16_t,3>::transfer(source,target, do_components,do_alpha);
+ break;
+ case BC_RGBA16161616:
+ case BC_YUVA16161616:
+ px_type<uint16_t,4>::transfer(source,target, do_components,do_alpha);
+ break;
+ }
+
+ return 0;
+}
+
+
+
+
+
+
+
+
+char* Reroute::plugin_title() { return N_("Reroute"); }
+int Reroute::is_realtime() { return 1; }
+int Reroute::is_multichannel() { return 1; }
+
+
+NEW_PICON_MACRO(Reroute)
+
+SHOW_GUI_MACRO(Reroute, RerouteThread)
+
+RAISE_WINDOW_MACRO(Reroute)
+
+SET_STRING_MACRO(Reroute);
+
+
+
+int Reroute::load_configuration()
+{
+ KeyFrame *prev_keyframe;
+ prev_keyframe = get_prev_keyframe(get_source_position());
+ read_data(prev_keyframe);
+ return 0;
+}
+
+int Reroute::load_defaults()
+{
+ char directory[BCTEXTLEN];
+// set the default directory
+ sprintf(directory, "%sreroute.rc", BCASTDIR);
+
+// load the defaults
+ defaults = new BC_Hash(directory);
+ defaults->load();
+
+ config.operation = defaults->get("OPERATION", config.operation);
+ config.output_track = defaults->get("OUTPUT_TRACK", config.output_track);
+ return 0;
+}
+
+int Reroute::save_defaults()
+{
+ defaults->update("OPERATION", config.operation);
+ defaults->update("OUTPUT_TRACK", config.output_track);
+ defaults->save();
+ return 0;
+}
+
+void Reroute::save_data(KeyFrame *keyframe)
+{
+ FileXML output;
+
+// write configuration data as XML text
+ output.set_shared_string(keyframe->data, MESSAGESIZE);
+ output.tag.set_title("REROUTE");
+ output.tag.set_property("OPERATION", config.operation);
+ output.tag.set_property("OUTPUT_TRACK", config.output_track);
+ output.append_tag();
+ output.tag.set_title("/REROUTE");
+ output.append_tag();
+ output.terminate_string();
+}
+
+void Reroute::read_data(KeyFrame *keyframe)
+{
+ FileXML input;
+ input.set_shared_string(keyframe->data, strlen(keyframe->data));
+ int result = 0;
+
+ while(!input.read_tag())
+ {
+ if(input.tag.title_is("REROUTE"))
+ {
+ config.operation = input.tag.get_property("OPERATION", config.operation);
+ config.output_track = input.tag.get_property("OUTPUT_TRACK", config.output_track);
+ }
+ }
+}
+
+void Reroute::update_gui()
+{
+ if(thread)
+ {
+ thread->window->lock_window("Reroute::update_gui");
+ thread->window->operation->set_text(RerouteConfig::operation_to_text(config.operation));
+ thread->window->output->set_text(RerouteConfig::output_to_text(config.output_track));
+ thread->window->unlock_window();
+ }
+}