From: Good Guy Date: Mon, 4 Sep 2017 23:29:49 +0000 (-0600) Subject: add rumbler plugin, perspective plugin fixes X-Git-Url: https://git.cinelerra-gg.org/git/?a=commitdiff_plain;h=49c01a0e18593cf77c326b6a82bff37de16786a4;p=goodguy%2Fhistory.git add rumbler plugin, perspective plugin fixes --- diff --git a/cinelerra-5.1/info/plugins.txt b/cinelerra-5.1/info/plugins.txt index 89128f48..00abacd1 100644 --- a/cinelerra-5.1/info/plugins.txt +++ b/cinelerra-5.1/info/plugins.txt @@ -3,8 +3,8 @@ # Name of plugin followed by: and then description. # Additional lines start with 2 tabs. # Lines should be less than 70 characters long. +#123456789012345678901234567890123456789012345678901234567890123456789 # For usage/readability, a period (.) creates space. -# 1080 to 480: Extracts 2 1920x540 fields from 1920x1080 image, resizes them separately, and combines them to 1920x480 interlaced image. @@ -156,6 +156,7 @@ Reroute: Selectively transfer the alpha channel or the Reverse video: Reverse media on the timeline in realtime. Rotate: Rotate the video in degree increments around a pivot point or reverse and flip the video. +Rumbler: Jiggle space and time at a given rate for dream-like video. SVG via Inkscape: Allow the manipulation of an SVG image with Inkscape without having to exit the program. Scale: Reduce or expand the image size depending on the ratio. diff --git a/cinelerra-5.1/plugin_defs b/cinelerra-5.1/plugin_defs index de386bc7..428cda21 100644 --- a/cinelerra-5.1/plugin_defs +++ b/cinelerra-5.1/plugin_defs @@ -38,8 +38,8 @@ video_tools := blur decimate delayvideo denoisemjpeg denoisevideo downsample \ fieldframe flash framefield freezeframe greycstoration interpolatepixels \ interpolatevideo invertvideo linearblur loopvideo \ motion2 motionblur motion motion-cv motion-hv motion51 \ - overlay radialblur reframe reframert reroute \ - reversevideo seltempavg sharpen svg titler timeavg timefront \ + overlay radialblur reframe reframert reroute reversevideo \ + rumbler seltempavg sharpen svg titler timeavg timefront \ unsharp videoscope wave zoomblur plugin_dirs += blending diff --git a/cinelerra-5.1/plugins/Makefile b/cinelerra-5.1/plugins/Makefile index d1bc16aa..5815bc19 100644 --- a/cinelerra-5.1/plugins/Makefile +++ b/cinelerra-5.1/plugins/Makefile @@ -106,6 +106,7 @@ DIRS = \ rgb601 \ rgbshift \ rotate \ + rumbler \ scale \ shapewipe \ sharpen \ diff --git a/cinelerra-5.1/plugins/perspective/perspective.C b/cinelerra-5.1/plugins/perspective/perspective.C index c9ec3e4f..ea1aa4d7 100644 --- a/cinelerra-5.1/plugins/perspective/perspective.C +++ b/cinelerra-5.1/plugins/perspective/perspective.C @@ -906,7 +906,7 @@ case tag: { \ } } - return 1; + return 0; } @@ -919,7 +919,7 @@ int PerspectiveMain::handle_opengl() config.x3, config.y3, config.x4, config.y4, config.forward); engine->set_opengl(0); - return 0; #endif + return 0; } diff --git a/cinelerra-5.1/plugins/rumbler/Makefile b/cinelerra-5.1/plugins/rumbler/Makefile new file mode 100644 index 00000000..967bcb50 --- /dev/null +++ b/cinelerra-5.1/plugins/rumbler/Makefile @@ -0,0 +1,10 @@ +include ../../plugin_defs + +OBJS = $(OBJDIR)/rumbler.o + +PLUGIN = rumbler + +include ../../plugin_config + + +$(OBJDIR)/rumbler.o: rumbler.C diff --git a/cinelerra-5.1/plugins/rumbler/picon_cinfinity.png b/cinelerra-5.1/plugins/rumbler/picon_cinfinity.png new file mode 100644 index 00000000..3eba0727 Binary files /dev/null and b/cinelerra-5.1/plugins/rumbler/picon_cinfinity.png differ diff --git a/cinelerra-5.1/plugins/rumbler/picon_original.png b/cinelerra-5.1/plugins/rumbler/picon_original.png new file mode 100644 index 00000000..48c98c32 Binary files /dev/null and b/cinelerra-5.1/plugins/rumbler/picon_original.png differ diff --git a/cinelerra-5.1/plugins/rumbler/picon_smoother.png b/cinelerra-5.1/plugins/rumbler/picon_smoother.png new file mode 100644 index 00000000..50533636 Binary files /dev/null and b/cinelerra-5.1/plugins/rumbler/picon_smoother.png differ diff --git a/cinelerra-5.1/plugins/rumbler/rumbler.C b/cinelerra-5.1/plugins/rumbler/rumbler.C new file mode 100644 index 00000000..ec822d15 --- /dev/null +++ b/cinelerra-5.1/plugins/rumbler/rumbler.C @@ -0,0 +1,361 @@ + +/* + * CINELERRA + * Copyright (C) 2008 Adam Williams + * + * This program 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. + * + * This program 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 + * + */ + +#include "bcdisplayinfo.h" +#include "affine.h" +#include "clip.h" +#include "bchash.h" +#include "filexml.h" +#include "guicast.h" +#include "keyframe.h" +#include "language.h" +#include "pluginvclient.h" +#include "vframe.h" + +#include +#include +#include + + +class Rumbler; +class RumblerConfig; +class RumblerRate; +class RumblerSeq; +class RumblerWindow; + + +class RumblerConfig +{ +public: + RumblerConfig(); + float time_rumble, time_rate; + float space_rumble, space_rate; + int sequence; + void copy_from(RumblerConfig &that); + int equivalent(RumblerConfig &that); + void interpolate(RumblerConfig &prev, RumblerConfig &next, + int64_t prev_frame, int64_t next_frame, int64_t current_frame); +}; + +class RumblerRate : public BC_TextBox +{ +public: + RumblerRate(Rumbler *plugin, RumblerWindow *gui, + float &value, int x, int y); + int handle_event(); + Rumbler *plugin; + RumblerWindow *gui; + float *value; +}; + +class RumblerSeq : public BC_TextBox +{ +public: + RumblerSeq(Rumbler *plugin, RumblerWindow *gui, + int &value, int x, int y); + int handle_event(); + Rumbler *plugin; + RumblerWindow *gui; + int *value; +}; + + +class RumblerWindow : public PluginClientWindow +{ +public: + RumblerWindow(Rumbler *plugin); + ~RumblerWindow(); + void create_objects(); + + Rumbler *plugin; + RumblerRate *time_rumble, *time_rate; + RumblerRate *space_rumble, *space_rate; + RumblerSeq *seq; +}; + +class Rumbler : public PluginVClient +{ +public: + Rumbler(PluginServer *server); + ~Rumbler(); + + PLUGIN_CLASS_MEMBERS(RumblerConfig) + + int process_buffer(VFrame *frame, int64_t start_position, double frame_rate); + int is_realtime(); + void save_data(KeyFrame *keyframe); + void read_data(KeyFrame *keyframe); + void update_gui(); + int handle_opengl(); + static double rumble(int64_t seq, double cur, double per, double amp); + + VFrame *input, *output, *temp; + float x1,y1, x2,y2, x3,y3, x4,y4; + AffineEngine *engine; +}; + + +RumblerConfig::RumblerConfig() +{ + time_rumble = 10; + time_rate = 1.; + space_rumble = 10; + space_rate = 1.; + sequence = 0; +} + +void RumblerConfig::copy_from(RumblerConfig &that) +{ + time_rumble = that.time_rumble; + time_rate = that.time_rate; + space_rumble = that.space_rumble; + space_rate = that.space_rate; + sequence = that.sequence; +} + +int RumblerConfig::equivalent(RumblerConfig &that) +{ + return time_rumble == that.time_rumble && + time_rate == that.time_rate && + space_rumble == that.space_rumble && + space_rate == that.space_rate && + sequence == that.sequence; +} + +void RumblerConfig::interpolate(RumblerConfig &prev, RumblerConfig &next, + int64_t prev_frame, int64_t next_frame, int64_t current_frame) +{ + double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame); + double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame); + this->time_rumble = prev.time_rumble * prev_scale + next.time_rumble * next_scale; + this->time_rate = prev.time_rate * prev_scale + next.time_rate * next_scale; + this->space_rumble = prev.space_rumble * prev_scale + next.space_rumble * next_scale; + this->space_rate = prev.space_rate * prev_scale + next.space_rate * next_scale; + this->sequence = prev.sequence; +} + +RumblerWindow::RumblerWindow(Rumbler *plugin) + : PluginClientWindow(plugin, 300, 120, 300, 120, 0) +{ + this->plugin = plugin; +} + +RumblerWindow::~RumblerWindow() +{ +} + +void RumblerWindow::create_objects() +{ + int x = 10, x1 = x + 64, x2 =x1 + 100; + int y = 10; + BC_Title *title; + + add_subwindow(title = new BC_Title(x1, y, _("rumble"))); + add_subwindow(title = new BC_Title(x2, y, _("rate"))); + y += title->get_h() + 10; + add_subwindow(title = new BC_Title(x, y, _("time:"))); + add_subwindow(time_rumble = new RumblerRate(plugin, this, plugin->config.time_rumble, x1, y)); + add_subwindow(time_rate = new RumblerRate(plugin, this, plugin->config.time_rate, x2, y)); + y += title->get_h() + 10; + add_subwindow(title = new BC_Title(x, y, _("space:"))); + add_subwindow(space_rumble = new RumblerRate(plugin, this, plugin->config.space_rumble, x1, y)); + add_subwindow(space_rate = new RumblerRate(plugin, this, plugin->config.space_rate, x2, y)); + y += title->get_h() + 10; + add_subwindow(title = new BC_Title(x, y, _("seq:"))); + add_subwindow(seq = new RumblerSeq(plugin, this, plugin->config.sequence, x1, y)); + + show_window(); + flush(); +} + + +RumblerRate::RumblerRate(Rumbler *plugin, RumblerWindow *gui, + float &value, int x, int y) + : BC_TextBox(x, y, 90, 1, value) +{ + this->plugin = plugin; + this->value = &value; + this->gui = gui; +} + +int RumblerRate::handle_event() +{ + *value = atof(get_text()); + plugin->send_configure_change(); + return 1; +} + +RumblerSeq::RumblerSeq(Rumbler *plugin, RumblerWindow *gui, + int &value, int x, int y) + : BC_TextBox(x, y, 72, 1, value) +{ + this->plugin = plugin; + this->value = &value; + this->gui = gui; +} + +int RumblerSeq::handle_event() +{ + *value = atoi(get_text()); + plugin->send_configure_change(); + return 1; +} + + +REGISTER_PLUGIN(Rumbler) + +Rumbler::Rumbler(PluginServer *server) + : PluginVClient(server) +{ + engine = 0; +} + +Rumbler::~Rumbler() +{ + delete engine; +} + + +double Rumbler::rumble(int64_t seq, double cur, double per, double amp) +{ + if( !per || !amp ) return 0.; + int64_t t = cur / per; + double t0 = t * per; + srandom(t += seq); + static const int64_t rmax1 = ((int64_t)RAND_MAX) + 1; + double prev = (double)random() / rmax1 - 0.5; + srandom(t+1); + double next = (double)random() / rmax1 - 0.5; + double v = (cur-t0) / per, u = 1. - v; + return amp*(u*prev + v*next); +} + +int Rumbler::process_buffer(VFrame *frame, int64_t start_position, double frame_rate) +{ + load_configuration(); + input = frame; + output = frame; + double cur = frame_rate > 0 ? start_position / frame_rate : 0; + double per = config.time_rate > 0 ? 1./config.time_rate : 0; + double rum = config.time_rumble; + int seq = config.sequence; + int64_t pos = rumble(seq+0x0000000, cur, per, rum) + start_position; + read_frame(frame, 0, pos, frame_rate, 0); + cur = frame_rate > 0 ? start_position / frame_rate : 0; + per = config.space_rate > 0 ? 1./config.space_rate : 0; + rum = config.space_rumble; + x1 = rumble(seq+0x1000000, cur, per, rum) + 0; + y1 = rumble(seq+0x2000000, cur, per, rum) + 0; + x2 = rumble(seq+0x3000000, cur, per, rum) + 100; + y2 = rumble(seq+0x4000000, cur, per, rum) + 0; + x3 = rumble(seq+0x5000000, cur, per, rum) + 100; + y3 = rumble(seq+0x6000000, cur, per, rum) + 100; + x4 = rumble(seq+0x7000000, cur, per, rum) + 0; + y4 = rumble(seq+0x8000000, cur, per, rum) + 100; + if( !engine ) { + int cpus = get_project_smp() + 1; + engine = new AffineEngine(cpus, cpus); + } + + if( get_use_opengl() ) + return run_opengl(); + + int w = frame->get_w(), h = frame->get_h(); + int color_model = frame->get_color_model(); + input = new_temp(w, h, color_model); + input->copy_from(frame); + output->clear_frame(); + engine->process(output, input, input, + AffineEngine::PERSPECTIVE, + x1, y1, x2, y2, x3, y3, x4, y4, 1); + + return 0; +} + +int Rumbler::handle_opengl() +{ +#ifdef HAVE_GL + engine->set_opengl(1); + engine->process(output, input, input, + AffineEngine::PERSPECTIVE, + x1, y1, x2, y2, x3, y3, x4, y4, 1); + engine->set_opengl(0); +#endif + return 0; +} + + +const char* Rumbler::plugin_title() { return _("Rumbler"); } +int Rumbler::is_realtime() { return 1; } + +NEW_WINDOW_MACRO(Rumbler, RumblerWindow) + +LOAD_CONFIGURATION_MACRO(Rumbler, RumblerConfig) + +void Rumbler::save_data(KeyFrame *keyframe) +{ + FileXML output; + + output.set_shared_output(keyframe->get_data(), MESSAGESIZE); + output.tag.set_title("RUMBLER"); + output.tag.set_property("TIME_RUMBLE", config.time_rumble); + output.tag.set_property("TIME_RATE", config.time_rate); + output.tag.set_property("SPACE_RUMBLE", config.space_rumble); + output.tag.set_property("SPACE_RATE", config.space_rate); + output.tag.set_property("SEQUENCE", config.sequence); + output.append_tag(); + output.tag.set_title("/RUMBLER"); + output.append_tag(); + output.append_newline(); + output.terminate_string(); +} + +void Rumbler::read_data(KeyFrame *keyframe) +{ + FileXML input; + + input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data())); + + while( !input.read_tag() ) { + if( input.tag.title_is("RUMBLER") ) { + config.time_rumble = input.tag.get_property("TIME_RUMBLE", config.time_rumble); + config.time_rate = input.tag.get_property("TIME_RATE", config.time_rate); + config.space_rumble = input.tag.get_property("SPACE_RUMBLE", config.space_rumble); + config.space_rate = input.tag.get_property("SPACE_RATE", config.space_rate); + config.sequence = input.tag.get_property("SEQUENCE", config.sequence); + } + } +} + +void Rumbler::update_gui() +{ + if( !thread ) return; + if( !load_configuration() ) return; + RumblerWindow *window = (RumblerWindow*)thread->window; + window->lock_window("Rumbler::update_gui"); + window->time_rumble->update(config.time_rumble); + window->time_rate->update(config.time_rate); + window->space_rumble->update(config.space_rumble); + window->space_rate->update(config.space_rate); + window->seq->update((float)config.sequence); + window->unlock_window(); +} +