proxy bug fixes, add moveobj, sams icons, ladspa fixes, pot sigfpe
authorGood Guy <[email protected]>
Fri, 22 Sep 2017 22:52:42 +0000 (16:52 -0600)
committerGood Guy <[email protected]>
Fri, 22 Sep 2017 22:52:42 +0000 (16:52 -0600)
24 files changed:
cinelerra-5.1/cinelerra/mwindow.C
cinelerra-5.1/cinelerra/pluginaclientlad.C
cinelerra-5.1/cinelerra/pluginclient.C
cinelerra-5.1/cinelerra/proxy.C
cinelerra-5.1/doc/shortcuts.html
cinelerra-5.1/guicast/bcpot.C
cinelerra-5.1/picon_cinfinity/ff_chromakey.png [new file with mode: 0644]
cinelerra-5.1/picon_cinfinity/ff_ciescope.png [new file with mode: 0644]
cinelerra-5.1/picon_cinfinity/ff_colorbalance.png [new file with mode: 0644]
cinelerra-5.1/picon_cinfinity/ff_colorchannelmixer.png [new file with mode: 0644]
cinelerra-5.1/picon_cinfinity/ff_colorkey.png [new file with mode: 0644]
cinelerra-5.1/picon_cinfinity/ff_colorlevels.png [new file with mode: 0644]
cinelerra-5.1/picon_cinfinity/ff_colormatrix.png [new file with mode: 0644]
cinelerra-5.1/picon_cinfinity/ff_cover_rect.png [new file with mode: 0644]
cinelerra-5.1/picon_cinfinity/ff_crop.png [new file with mode: 0644]
cinelerra-5.1/picon_cinfinity/ff_cropdetect.png [new file with mode: 0644]
cinelerra-5.1/picon_cinfinity/ff_datascope.png [new file with mode: 0644]
cinelerra-5.1/picon_cinfinity/ff_deband.png [new file with mode: 0644]
cinelerra-5.1/picon_cinfinity/ff_deflate.png [new file with mode: 0644]
cinelerra-5.1/plugins/moveobj/Makefile [new file with mode: 0644]
cinelerra-5.1/plugins/moveobj/moveobj.C [new file with mode: 0644]
cinelerra-5.1/plugins/moveobj/moveobj.h [new file with mode: 0644]
cinelerra-5.1/plugins/moveobj/moveobjwindow.C [new file with mode: 0644]
cinelerra-5.1/plugins/moveobj/moveobjwindow.h [new file with mode: 0644]

index 0334fd0229b6a4d3c8fad1512a0536e09407170b..7a1f59be404620794446f1b04d478ac996bb23e5 100644 (file)
@@ -2566,12 +2566,11 @@ SET_TRACE
 SET_TRACE
 
 //printf("MWindow::show_plugin 1\n");
-       if(!done)
-       {
-               if(!plugin->track)
-               {
-                       printf("MWindow::show_plugin track not defined.\n");
-               }
+       if( !done && !plugin->track ) {
+               printf("MWindow::show_plugin track not defined.\n");
+               done = 1;
+       }
+       if( !done ) {
                PluginServer *server = scan_plugindb(plugin->title,
                        plugin->track->data_type);
 
@@ -2958,6 +2957,8 @@ void MWindow::update_project(int load_mode)
        if(load_mode == LOADMODE_REPLACE ||
                load_mode == LOADMODE_REPLACE_CONCATENATE)
        {
+               edl->session->proxy_scale = 1;
+               edl->session->proxy_use_scaler = 0;
                gui->load_panes();
        }
 
index 982492ba8b028d2b4a695df5e92f3f06bd8df67d..91c19275f7d47305762d2f4754ec94c3c6ca72cf 100644 (file)
@@ -69,28 +69,15 @@ int PluginAClientConfig::equivalent(PluginAClientConfig &that)
 // Need PluginServer to do this.
 void PluginAClientConfig::copy_from(PluginAClientConfig &that)
 {
-       if(total_ports != that.total_ports)
-       {
-               delete_objects();
-               total_ports = that.total_ports;
-               port_data = new LADSPA_Data[total_ports];
-               port_type = new int[total_ports];
-       }
-
-       for(int i = 0; i < total_ports; i++)
-       {
+       int n = bmin(total_ports, that.total_ports);
+       for( int i=0; i<n; ++i ) {
                port_type[i] = that.port_type[i];
                port_data[i] = that.port_data[i];
-//printf("PluginAClientConfig::copy_from 1 %f %f\n", port_data[i], that.port_data[i]);
        }
-
 }
 
-void PluginAClientConfig::interpolate(PluginAClientConfig &prev,
-       PluginAClientConfig &next,
-       int64_t prev_frame,
-       int64_t next_frame,
-       int64_t current_frame)
+void PluginAClientConfig::interpolate(PluginAClientConfig &prev, PluginAClientConfig &next,
+       int64_t prev_frame, int64_t next_frame, int64_t current_frame)
 {
        copy_from(prev);
 }
@@ -101,7 +88,6 @@ void PluginAClientConfig::initialize(PluginServer *server)
 
        const LADSPA_Descriptor *lad_desc = server->lad_descriptor;
        const LADSPA_PortDescriptor *port_desc = lad_desc->PortDescriptors;
-       const LADSPA_PortRangeHint *lad_hint = lad_desc->PortRangeHints;
        int port_count = lad_desc->PortCount;
        for(int i = 0; i < port_count; i++) {
                if( !LADSPA_IS_PORT_INPUT(port_desc[i]) ) continue;
@@ -115,15 +101,14 @@ void PluginAClientConfig::initialize(PluginServer *server)
        for(int port = 0, i = 0; i < port_count; i++) {
                if( !LADSPA_IS_PORT_INPUT(port_desc[i]) ) continue;
                if( !LADSPA_IS_PORT_CONTROL(port_desc[i]) ) continue;
+               const LADSPA_PortRangeHint *lad_hint = &lad_desc->PortRangeHints[i];
+               LADSPA_PortRangeHintDescriptor hint_desc = lad_hint->HintDescriptor;
 // Convert LAD default to default value
                float value = 0.0;
-               LADSPA_PortRangeHintDescriptor hint_desc = lad_hint->HintDescriptor;
 
 // Store type of port for GUI use
                port_type[port] = PORT_NORMAL;
-               if( LADSPA_IS_HINT_SAMPLE_RATE(hint_desc) /* &&
-                   LADSPA_IS_HINT_BOUNDED_ABOVE(hint_desc) &&
-                   LADSPA_IS_HINT_BOUNDED_BELOW(hint_desc) */ ) // LAD frequency table
+               if( LADSPA_IS_HINT_SAMPLE_RATE(hint_desc) )
                        port_type[port] = PORT_FREQ_INDEX;
                else if(LADSPA_IS_HINT_TOGGLED(hint_desc))
                        port_type[port] = PORT_TOGGLE;
@@ -138,8 +123,7 @@ void PluginAClientConfig::initialize(PluginServer *server)
                else if( LADSPA_IS_HINT_DEFAULT_100(hint_desc) )
                        value = 100.0;
                else if( LADSPA_IS_HINT_DEFAULT_440(hint_desc) )
-                       value = port_type[port] == PORT_FREQ_INDEX ?
-                                440.0 / 44100 : 440.0;
+                       value = 440.0;
                else if( LADSPA_IS_HINT_DEFAULT_MAXIMUM(hint_desc) )
                        value = lad_hint->UpperBound;
                else if( LADSPA_IS_HINT_DEFAULT_MINIMUM(hint_desc) )
@@ -493,7 +477,7 @@ void PluginAClientLAD::read_data(KeyFrame *keyframe)
        char string[BCTEXTLEN];
 
        input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
-       config.initialize(server);
+       if( !config.port_data ) config.initialize(server);
 
        while(! input.read_tag() ) {
 //printf("PluginAClientLAD::read_data %s\n", input.tag.get_title());
@@ -539,6 +523,10 @@ void PluginAClientLAD::delete_plugin()
 void PluginAClientLAD::init_plugin(int total_in, int total_out, int size)
 {
        int need_reconfigure = !lad_instance ? 1 : 0;
+       if( !config.port_data ) {
+               config.initialize(server);
+               need_reconfigure = 1;
+       }
        if(buffer_allocation && buffer_allocation < size) {
                delete_buffers();
                need_reconfigure = 1;
index bc6ca8eb9e191841b4ecb4952e1edf96fb3370d8..03e8c3f1e642f43487950ef60b1f213e29a95262 100644 (file)
@@ -337,14 +337,8 @@ int PluginClient::show_gui()
        thread->start();
        thread->init_complete->lock("PluginClient::show_gui");
 // Must wait before sending any hide_gui
-       if(thread->window)
-       {
-               thread->window->init_wait();
-       }
-       else
-       {
-               return 1;
-       }
+       if( !thread->window ) return 1;
+       thread->window->init_wait();
        return 0;
 }
 
index 537fc40a1c75301a5d7b5edd036735c64c45d657..d126cf142f19d03f1026a661fb9ceed07c2fa89b 100644 (file)
@@ -80,6 +80,7 @@ ProxyThread::ProxyThread(MWindow *mwindow)
 ProxyThread::~ProxyThread()
 {
        for( int i=0; i<MAX_SIZES; ++i ) delete [] size_text[i];
+       asset->remove_user();
 }
 
 BC_Window* ProxyThread::new_gui()
@@ -121,9 +122,14 @@ void ProxyThread::calculate_sizes()
        int orig_h = mwindow->edl->session->output_h * orig_scale;
 
        if( !use_scaler ) {
+// w,h should stay even for yuv
+               int ow = orig_w, oh = orig_h;
+               if( BC_CModels::is_yuv(mwindow->edl->session->color_model) ) {
+                       ow /= 2;  oh /= 2;
+               }
                for( int i=2; i<MAX_SCALE; ++i ) {
-                       if( (orig_w % i) != 0 ) continue;
-                       if( (orig_h % i) != 0 ) continue;
+                       if( (ow % i) != 0 ) continue;
+                       if( (oh % i) != 0 ) continue;
                        size_factors[total_sizes++] = i;
                }
        }
@@ -131,7 +137,7 @@ void ProxyThread::calculate_sizes()
                size_factors[total_sizes++] = 2;   size_factors[total_sizes++] = 3;
                size_factors[total_sizes++] = 8;   size_factors[total_sizes++] = 12;
                size_factors[total_sizes++] = 16;  size_factors[total_sizes++] = 24;
-               size_factors[total_sizes++] = 32;  size_factors[total_sizes++] = 36;
+               size_factors[total_sizes++] = 32;
        }
        for( int i=1; i<total_sizes; ++i ) {
                char string[BCTEXTLEN];
@@ -227,8 +233,10 @@ void ProxyThread::to_proxy()
                                proxy_asset->video_data = 1;
                                proxy_asset->layers = 1;
                                proxy_asset->width = orig_asset->width / new_scale;
+                               if( proxy_asset->width & 1 ) ++proxy_asset->width;
                                proxy_asset->actual_width = proxy_asset->width;
                                proxy_asset->height = orig_asset->height / new_scale;
+                               if( proxy_asset->height & 1 ) ++proxy_asset->height;
                                proxy_asset->actual_height = proxy_asset->height;
                                proxy_asset->frame_rate = orig_asset->frame_rate;
                                proxy_asset->video_length = orig_asset->video_length;
@@ -473,8 +481,11 @@ void ProxyWindow::update()
 // thread->orig_scale, thread->new_scale);
        int orig_w = mwindow->edl->session->output_w * thread->orig_scale;
        int orig_h = mwindow->edl->session->output_h * thread->orig_scale;
-       sprintf(string, "%dx%d", 
-               orig_w / thread->new_scale, orig_h / thread->new_scale);
+       int new_w = orig_w / thread->new_scale;
+       if( new_w & 1 ) ++new_w;
+       int new_h = orig_h / thread->new_scale;
+       if( new_h & 1 ) ++new_h;
+       sprintf(string, "%dx%d", new_w, new_h);
        new_dimensions->update(string);
        thread->scale_to_text(string, thread->new_scale);
        scale_factor->set_text(string);
index 3bcd3c71f1bdbd88335cde54e45584857db58c32..1e875fb74e54aaabfd9b188874a27de896c307d3 100644 (file)
                <td align="left"><font face="Liberation Serif" size=4>'Shift-P'</font></td>
                <td align="left"><font face="Liberation Serif" size=4>Open preferences setup menu</font></td>
        </tr>
+       <tr>
+               <td height="26" align="left"><font face="Liberation Serif" size=4>    Pulldown</font></td>
+               <td align="left"><font face="Liberation Serif" size=4>Proxy Settings</font></td>
+               <td align="left"><font face="Liberation Serif" size=4>'Alt-P'</font></td>
+               <td align="left"><font face="Liberation Serif" size=4>Bring up Proxy settings window</font></td>
+       </tr>
        <tr>
                <td height="26" align="left"><font face="Liberation Serif" size=4><br></font></td>
                <td align="left"><font face="Liberation Serif" size=4>- Edit labels</font></td>
index 7417e79ed6a780a221aedc28058022eed0e7d15e..e934fc537d4a161ed5753ac31eadeb4b6430617b 100644 (file)
@@ -460,7 +460,8 @@ const char*  BC_FPot::get_caption()
 
 float BC_FPot::get_percentage()
 {
-       return (value - minvalue) / (maxvalue - minvalue);
+       float range = maxvalue - minvalue;
+       return range > 0 ? (value - minvalue) / range : minvalue;
 }
 
 int BC_FPot::percentage_to_value(float percentage)
@@ -549,7 +550,8 @@ const char* BC_IPot::get_caption()
 
 float BC_IPot::get_percentage()
 {
-       return ((float)value - minvalue) / (maxvalue - minvalue);
+       float range = maxvalue - minvalue;
+       return range > 0 ? ((float)value - minvalue) / range : minvalue;
 }
 
 int BC_IPot::percentage_to_value(float percentage)
@@ -633,7 +635,8 @@ const char* BC_QPot::get_caption()
 
 float BC_QPot::get_percentage()
 {
-       return ((float)value - minvalue) / (maxvalue - minvalue);
+       float range = maxvalue - minvalue;
+       return range > 0 ? ((float)value - minvalue) / range : 0;
 }
 
 int BC_QPot::percentage_to_value(float percentage)
@@ -709,7 +712,8 @@ const char* BC_PercentagePot::get_caption()
 
 float BC_PercentagePot::get_percentage()
 {
-       return (value - minvalue) / (maxvalue - minvalue);
+       float range = maxvalue - minvalue;
+       return range > 0 ? (value - minvalue) / range : minvalue;
 }
 
 int BC_PercentagePot::percentage_to_value(float percentage)
diff --git a/cinelerra-5.1/picon_cinfinity/ff_chromakey.png b/cinelerra-5.1/picon_cinfinity/ff_chromakey.png
new file mode 100644 (file)
index 0000000..c9d6b10
Binary files /dev/null and b/cinelerra-5.1/picon_cinfinity/ff_chromakey.png differ
diff --git a/cinelerra-5.1/picon_cinfinity/ff_ciescope.png b/cinelerra-5.1/picon_cinfinity/ff_ciescope.png
new file mode 100644 (file)
index 0000000..d93ad8b
Binary files /dev/null and b/cinelerra-5.1/picon_cinfinity/ff_ciescope.png differ
diff --git a/cinelerra-5.1/picon_cinfinity/ff_colorbalance.png b/cinelerra-5.1/picon_cinfinity/ff_colorbalance.png
new file mode 100644 (file)
index 0000000..803a5ea
Binary files /dev/null and b/cinelerra-5.1/picon_cinfinity/ff_colorbalance.png differ
diff --git a/cinelerra-5.1/picon_cinfinity/ff_colorchannelmixer.png b/cinelerra-5.1/picon_cinfinity/ff_colorchannelmixer.png
new file mode 100644 (file)
index 0000000..d4ef540
Binary files /dev/null and b/cinelerra-5.1/picon_cinfinity/ff_colorchannelmixer.png differ
diff --git a/cinelerra-5.1/picon_cinfinity/ff_colorkey.png b/cinelerra-5.1/picon_cinfinity/ff_colorkey.png
new file mode 100644 (file)
index 0000000..a910053
Binary files /dev/null and b/cinelerra-5.1/picon_cinfinity/ff_colorkey.png differ
diff --git a/cinelerra-5.1/picon_cinfinity/ff_colorlevels.png b/cinelerra-5.1/picon_cinfinity/ff_colorlevels.png
new file mode 100644 (file)
index 0000000..5a9ca92
Binary files /dev/null and b/cinelerra-5.1/picon_cinfinity/ff_colorlevels.png differ
diff --git a/cinelerra-5.1/picon_cinfinity/ff_colormatrix.png b/cinelerra-5.1/picon_cinfinity/ff_colormatrix.png
new file mode 100644 (file)
index 0000000..0c659f6
Binary files /dev/null and b/cinelerra-5.1/picon_cinfinity/ff_colormatrix.png differ
diff --git a/cinelerra-5.1/picon_cinfinity/ff_cover_rect.png b/cinelerra-5.1/picon_cinfinity/ff_cover_rect.png
new file mode 100644 (file)
index 0000000..d987875
Binary files /dev/null and b/cinelerra-5.1/picon_cinfinity/ff_cover_rect.png differ
diff --git a/cinelerra-5.1/picon_cinfinity/ff_crop.png b/cinelerra-5.1/picon_cinfinity/ff_crop.png
new file mode 100644 (file)
index 0000000..626f8fc
Binary files /dev/null and b/cinelerra-5.1/picon_cinfinity/ff_crop.png differ
diff --git a/cinelerra-5.1/picon_cinfinity/ff_cropdetect.png b/cinelerra-5.1/picon_cinfinity/ff_cropdetect.png
new file mode 100644 (file)
index 0000000..593c40e
Binary files /dev/null and b/cinelerra-5.1/picon_cinfinity/ff_cropdetect.png differ
diff --git a/cinelerra-5.1/picon_cinfinity/ff_datascope.png b/cinelerra-5.1/picon_cinfinity/ff_datascope.png
new file mode 100644 (file)
index 0000000..91a9663
Binary files /dev/null and b/cinelerra-5.1/picon_cinfinity/ff_datascope.png differ
diff --git a/cinelerra-5.1/picon_cinfinity/ff_deband.png b/cinelerra-5.1/picon_cinfinity/ff_deband.png
new file mode 100644 (file)
index 0000000..9711aed
Binary files /dev/null and b/cinelerra-5.1/picon_cinfinity/ff_deband.png differ
diff --git a/cinelerra-5.1/picon_cinfinity/ff_deflate.png b/cinelerra-5.1/picon_cinfinity/ff_deflate.png
new file mode 100644 (file)
index 0000000..7238f07
Binary files /dev/null and b/cinelerra-5.1/picon_cinfinity/ff_deflate.png differ
diff --git a/cinelerra-5.1/plugins/moveobj/Makefile b/cinelerra-5.1/plugins/moveobj/Makefile
new file mode 100644 (file)
index 0000000..256f85e
--- /dev/null
@@ -0,0 +1,21 @@
+default: all
+
+TOPDIR?=../..
+include $(TOPDIR)/plugin_defs
+
+PLUGIN = moveobj
+
+OBJS := \
+       $(OBJDIR)/moveobj.o \
+       $(OBJDIR)/moveobjwindow.o \
+
+want_var:=$(WANT_FINDOBJECT)
+include $(TOPDIR)/opencv_build
+include $(TOPDIR)/plugin_config
+
+all:   opencv
+       +make $(OUTPUT)
+
+$(OBJDIR)/moveobj.o: moveobj.C moveobj.h moveobjwindow.h
+$(OBJDIR)/moveobjwindow.o: moveobjwindow.C moveobj.h moveobjwindow.h
+
diff --git a/cinelerra-5.1/plugins/moveobj/moveobj.C b/cinelerra-5.1/plugins/moveobj/moveobj.C
new file mode 100644 (file)
index 0000000..b40e5f6
--- /dev/null
@@ -0,0 +1,353 @@
+/*
+ * CINELERRA
+ * Copyright (C) 1997-2014 Adam Williams <broadcast at earthling dot net>
+ * 
+ * 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 "affine.h"
+#include "clip.h"
+#include "filexml.h"
+#include "moveobj.h"
+#include "moveobjwindow.h"
+#include "language.h"
+#include "transportque.inc"
+
+REGISTER_PLUGIN(MoveObj)
+
+#define MAX_COUNT 250
+#define WIN_SIZE 20
+
+MoveObjConfig::MoveObjConfig()
+{
+       draw_vectors = 0;
+       do_stabilization = 1;
+       block_size = 20;
+       search_radius = 10;
+       settling_speed = 5;
+}
+
+int MoveObjConfig::equivalent(MoveObjConfig &that)
+{
+       return draw_vectors == that.draw_vectors &&
+               do_stabilization == that.do_stabilization &&
+               block_size == that.block_size &&
+               search_radius == that.search_radius &&
+               settling_speed == that.settling_speed;
+}
+
+void MoveObjConfig::copy_from(MoveObjConfig &that)
+{
+       draw_vectors = that.draw_vectors;
+       do_stabilization = that.do_stabilization;
+       block_size = that.block_size;
+       search_radius = that.search_radius;
+       settling_speed = that.settling_speed;
+}
+
+void MoveObjConfig::interpolate( MoveObjConfig &prev, MoveObjConfig &next, 
+       long prev_frame, long next_frame, long current_frame)
+{
+       copy_from(next);
+}
+
+void MoveObjConfig::limits()
+{
+       bclamp(block_size, 5, 100);
+       bclamp(search_radius, 1, 100);
+       bclamp(settling_speed, 0, 100);
+}
+
+
+MoveObj::MoveObj(PluginServer *server)
+ : PluginVClient(server)
+{
+       affine = 0;
+       prev_position = next_position = -1;
+       x_accum = y_accum = 0;
+       angle_accum = 0;
+       prev_corners = 0;
+       next_corners = 0;
+}
+
+MoveObj::~MoveObj()
+{
+       delete affine;
+       delete prev_corners;
+       delete next_corners;
+}
+
+const char* MoveObj::plugin_title() { return N_("MoveObj"); }
+int MoveObj::is_realtime() { return 1; }
+
+NEW_WINDOW_MACRO(MoveObj, MoveObjWindow);
+LOAD_CONFIGURATION_MACRO(MoveObj, MoveObjConfig)
+
+void MoveObj::save_data(KeyFrame *keyframe)
+{
+       FileXML output;
+
+// cause data to be stored directly in text
+       output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
+       output.tag.set_title("MOVEOBJ");
+       output.tag.set_property("DRAW_VECTORS", config.draw_vectors);
+       output.tag.set_property("DO_STABILIZATION", config.do_stabilization);
+       output.tag.set_property("BLOCK_SIZE", config.block_size);
+       output.tag.set_property("SEARCH_RADIUS", config.search_radius);
+       output.tag.set_property("SETTLING_SPEED", config.settling_speed);
+       output.append_tag();
+       output.append_newline();
+       output.tag.set_title("/MOVEOBJ");
+       output.append_tag();
+       output.append_newline();
+       output.terminate_string();
+}
+
+void MoveObj::read_data(KeyFrame *keyframe)
+{
+       FileXML input;
+       input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
+
+       int result = 0;
+       while( !(result = input.read_tag()) ) {
+               if( input.tag.title_is("MOVEOBJ") ) {
+                       config.draw_vectors = input.tag.get_property("DRAW_VECTORS", config.draw_vectors);
+                       config.do_stabilization = input.tag.get_property("DO_STABILIZATION", config.do_stabilization);
+                       config.block_size = input.tag.get_property("BLOCK_SIZE", config.block_size);
+                       config.search_radius = input.tag.get_property("SEARCH_RADIUS", config.search_radius);
+                       config.settling_speed = input.tag.get_property("SETTLING_SPEED", config.settling_speed);
+                       config.limits();
+               }
+               else if( input.tag.title_is("/MOVEOBJ") )
+                       result = 1;
+       }
+}
+
+void MoveObj::update_gui()
+{
+       if( !thread ) return;
+       if( !load_configuration() ) return;
+       thread->window->lock_window("MoveObj::update_gui");
+       MoveObjWindow *window = (MoveObjWindow*)thread->window;
+
+       window->vectors->update(config.draw_vectors);
+       window->do_stabilization->update(config.do_stabilization);
+       window->block_size->update(config.block_size);
+       window->search_radius->update(config.search_radius);
+       window->settling_speed->update(config.settling_speed);
+
+       thread->window->unlock_window();
+}
+
+void MoveObj::to_mat(Mat &mat, int mcols, int mrows,
+       VFrame *inp, int ix,int iy, BC_CModel mcolor_model)
+{
+       int mcomp = BC_CModels::components(mcolor_model);
+       int mbpp = BC_CModels::calculate_pixelsize(mcolor_model);
+       int psz = mbpp / mcomp;
+       int mdepth = psz < 2 ? CV_8U : CV_16U;
+       if( mat.dims != 2 || mat.depth() != mdepth || mat.channels() != mcomp ||
+           mat.cols != mcols || mat.rows != mrows ) {
+               mat.release();
+       }
+       if( mat.empty() ) {
+               int type = CV_MAKETYPE(mdepth, mcomp);
+               mat.create(mrows, mcols, type);
+       }
+       uint8_t *mat_rows[mrows];
+       for( int y=0; y<mrows; ++y ) mat_rows[y] = mat.ptr(y);
+       uint8_t **inp_rows = inp->get_rows();
+       int ibpl = inp->get_bytes_per_line(), obpl = mcols * mbpp;
+       int icolor_model = inp->get_color_model();
+       BC_CModels::transfer(mat_rows, mcolor_model, 0,0, mcols,mrows, obpl,
+               inp_rows, icolor_model, ix,iy, mcols,mrows, ibpl, 0);
+//     VFrame vfrm(mat_rows[0], -1, mcols,mrows, mcolor_model, mat_rows[1]-mat_rows[0]);
+//     static int vfrm_no = 0; char vfn[64]; sprintf(vfn,"/tmp/dat/%06d.png", vfrm_no++);
+//     vfrm.write_png(vfn);
+}
+
+int MoveObj::process_buffer(VFrame *frame, int64_t start_position, double frame_rate)
+{
+
+       //int need_reconfigure =
+       load_configuration();
+       VFrame *input = get_input(0), *output = get_output(0);
+       int w = input->get_w(), h = input->get_h();
+       int color_model = input->get_color_model();
+
+       if( accum_matrix.empty() ) {
+               accum_matrix = Mat::eye(3,3, CV_64F);
+       }
+       if( !affine ) {
+               int cpus1 = PluginClient::get_project_smp() + 1;
+               affine = new AffineEngine(cpus1, cpus1);
+       }
+       if( !prev_corners ) prev_corners = new ptV();
+       if( !next_corners ) next_corners = new ptV();
+
+// Get the position of previous reference frame.
+       int64_t actual_previous_number = start_position;
+       int skip_current = 0;
+       if( get_direction() == PLAY_REVERSE ) {
+               if( ++actual_previous_number < get_source_start() + get_total_len() ) {
+                       KeyFrame *keyframe = get_next_keyframe(start_position, 1);
+                       if( keyframe->position > 0 &&
+                           actual_previous_number >= keyframe->position )
+                               skip_current = 1;
+               }
+               else
+                       skip_current = 1;
+       }
+       else {
+               if( --actual_previous_number >= get_source_start() ) {
+                       KeyFrame *keyframe = get_prev_keyframe(start_position, 1);
+                       if( keyframe->position > 0 &&
+                           actual_previous_number < keyframe->position)
+                               skip_current = 1;
+               }
+               else
+                       skip_current = 1;
+       }
+       
+
+// move currrent image to previous position
+       if( next_position >= 0 && next_position == actual_previous_number ) {
+               Mat mat = prev_mat;  prev_mat = next_mat;  next_mat = mat;
+               ptV *pts = prev_corners;  prev_corners = next_corners;  next_corners = pts;
+               prev_position = next_position;
+       }
+       else
+// load previous image
+       if( actual_previous_number >= 0 ) {
+               read_frame(input, 0, actual_previous_number, frame_rate, 0);
+               to_mat(prev_mat, w,h, input, 0,0, BC_GREY8);
+       }
+
+       if( skip_current || prev_position != actual_previous_number ) {
+               skip_current = 1;
+               accum_matrix = Mat::eye(3,3, CV_64F);
+       }
+
+
+// load next image
+       next_position = start_position;
+       VFrame *iframe = !config.do_stabilization ? input : new_temp(w,h, color_model);
+       read_frame(iframe, 0, start_position, frame_rate, 0);
+       to_mat(next_mat, w,h, iframe, 0,0, BC_GREY8);
+
+       int corner_count = MAX_COUNT;
+       int search_radius = config.block_size;
+       int min_distance = config.search_radius;
+
+       goodFeaturesToTrack(next_mat,
+               *next_corners, corner_count, 0.01,        // quality_level
+               min_distance, noArray(), search_radius,
+               0,           // use_harris
+               0.04);       // k
+
+       ptV pt1, pt2;
+       if( !next_mat.empty() && next_corners->size() > 3 ) {
+               cornerSubPix(next_mat, *next_corners, Size(WIN_SIZE, WIN_SIZE), Size(-1,-1),
+                       cvTermCriteria(CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 20, 0.03));
+       }
+       if( !prev_mat.empty() && prev_corners->size() > 3 ) {
+// optical flow
+               Mat st, err;
+               ptV &prev = *prev_corners, &next = *next_corners;
+               calcOpticalFlowPyrLK(prev_mat, next_mat, prev, next,
+                       st, err, Size(WIN_SIZE, WIN_SIZE), 5, 
+                       cvTermCriteria(CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 20, 0.3), 0);
+               float fails = 0.5 * w + 1;
+               uint8_t *stp = st.ptr<uint8_t>();
+               float *errp = err.ptr<float>();
+               for( int i=0,n=next_corners->size(); i<n; ++i ) {
+                       if( stp[i] == 0 || errp[i] > fails ) continue;
+                       pt1.push_back(next[i]);  
+                       pt2.push_back(prev[i]);
+               }
+       }
+
+       int points = pt1.size();
+       if( points > 0 && !skip_current ) {
+               if( config.draw_vectors ) {
+                       int sz = bmin(w,h) / 222 + 2;
+                       for( int i = 0; i < points; ++i )
+                               iframe->draw_arrow(pt1[i].x,pt1[i].y, pt2[i].x,pt2[i].y, sz);
+               }
+#ifdef _RANSAC
+// ransac
+               int ninliers = 0;
+               Mat_<float> translationM =
+                       estimateGlobalMotionRansac(pt1, pt2, MM_TRANSLATION, 
+                               RansacParams::default2dMotion(MM_TRANSLATION),
+                               0, &ninliers);
+               Mat_<float> rotationM =
+                       estimateGlobalMotionRansac(pt1, pt2, MM_ROTATION, 
+                               RansacParams::default2dMotion(MM_ROTATION),
+                               0, &ninliers);
+
+               double temp[9];
+               Mat temp_matrix = Mat(3, 3, CV_64F, temp);
+               for( int i=0; i<9; ++i )
+                       temp[i] = i == 2 || i == 5 ?
+                               translationM(i / 3, i % 3) :
+                               rotationM(i / 3, i % 3);
+               accum_matrix = temp_matrix * accum_matrix;
+#else
+// homography
+
+               Mat M1(1, points, CV_32FC2, &pt1[0].x);  
+               Mat M2(1, points, CV_32FC2, &pt2[0].x);  
+
+//M2 = H*M1 , old = H*current  
+               Mat H = findHomography(M1, M2, CV_RANSAC, 2);
+               if( !H.dims || !H.rows || !H.cols )
+                       printf("MoveObj::process_buffer %d: Find Homography Fail!\n", __LINE__);  
+               else
+                       accum_matrix = H * accum_matrix;
+#endif
+       }
+
+       double *amat = accum_matrix.ptr<double>();
+// deglitch
+//     if( EQUIV(amat[0], 0) ) {
+//printf("MoveObj::process_buffer %d\n", __LINE__);
+//             accum_matrix = Mat::eye(3,3, CV_64F);
+//     }
+
+       if( config.do_stabilization ) {
+               Mat identity = Mat::eye(3,3, CV_64F);
+               double w0 = config.settling_speed/100., w1 = 1.-w0;
+// interpolate with identity matrix
+               accum_matrix = w0*identity + w1*accum_matrix;
+
+               AffineMatrix matrix;
+               for( int i=0,k=0; i<3; ++i )
+                       for( int j=0; j<3; ++j )
+                               matrix.values[i][j] = amat[k++];
+
+//printf("MoveObj::process_buffer %d %jd matrix=\n", __LINE__, start_position);
+//matrix.dump();
+
+               affine->set_matrix(&matrix);
+// iframe is always temp, if we get here
+               output->clear_frame();
+               affine->process(output, iframe, 0, AffineEngine::TRANSFORM,
+                       0,0, w,0, w,h, 0,h, 1);
+       }
+
+       return 0;
+}
diff --git a/cinelerra-5.1/plugins/moveobj/moveobj.h b/cinelerra-5.1/plugins/moveobj/moveobj.h
new file mode 100644 (file)
index 0000000..d82d0f6
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * CINELERRA
+ * Copyright (C) 1997-2014 Adam Williams <broadcast at earthling dot net>
+ * 
+ * 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
+ */
+
+#ifndef MOVEOBJ_H
+#define MOVEOBJ_H
+
+#include "affine.inc"
+#include "pluginvclient.h"
+
+#include "opencv2/core/types.hpp"
+#include "opencv2/core/mat.hpp"
+#include "opencv2/calib3d.hpp"
+#include "opencv2/video/video.hpp"
+
+#include <vector>
+
+using namespace std;
+using namespace cv;
+
+//#define _RANSAC
+#ifdef _RANSAC
+#include <opencv2/videostab/motion_core.hpp>
+#include <opencv2/videostab/global_motion.hpp>
+
+using namespace videostab;
+#endif
+
+class MoveObjConfig
+{
+public:
+       MoveObjConfig();
+
+       int equivalent(MoveObjConfig &that);
+       void copy_from(MoveObjConfig &that);
+       void interpolate(MoveObjConfig &prev, MoveObjConfig &next, 
+               long prev_frame, long next_frame, long current_frame);
+       void limits();
+       int draw_vectors;
+       int do_stabilization;
+       int settling_speed;
+// percent
+       int block_size;
+       int search_radius;
+};
+
+class MoveObj : public PluginVClient
+{
+public:
+       MoveObj(PluginServer *server);
+       ~MoveObj();
+// required for all realtime plugins
+       PLUGIN_CLASS_MEMBERS2(MoveObjConfig)
+       int is_realtime();
+       void update_gui();
+       void save_data(KeyFrame *keyframe);
+       void read_data(KeyFrame *keyframe);
+       int process_buffer(VFrame *frame, int64_t start_position, double frame_rate);
+       AffineEngine *affine;
+       void to_mat(Mat &mat, int mcols, int mrows,
+               VFrame *inp, int ix,int iy, BC_CModel mcolor_model);
+
+       long prev_position, next_position;
+
+//opencv
+        typedef vector<Point2f> ptV;
+
+        BC_CModel cvmodel;
+       Mat accum_matrix;
+       double accum_matrix_mem[9];
+       double x_accum, y_accum, angle_accum;
+       Mat prev_mat, next_mat;
+       ptV *prev_corners, *next_corners;
+};
+
+#endif
diff --git a/cinelerra-5.1/plugins/moveobj/moveobjwindow.C b/cinelerra-5.1/plugins/moveobj/moveobjwindow.C
new file mode 100644 (file)
index 0000000..aac65d6
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * CINELERRA
+ * Copyright (C) 2014 Adam Williams <broadcast at earthling dot net>
+ * 
+ * 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 "clip.h"
+#include "language.h"
+#include "moveobj.h"
+#include "moveobjwindow.h"
+#include "theme.h"
+
+MoveObjWindow::MoveObjWindow(MoveObj *plugin)
+ : PluginClientWindow(plugin, 320, 240, 320, 240, 0)
+{
+       this->plugin = plugin; 
+}
+
+MoveObjWindow::~MoveObjWindow()
+{
+}
+
+void MoveObjWindow::create_objects()
+{
+       int x = 10, y = 10;
+       int margin = plugin->get_theme()->widget_border;
+       BC_Title *title;
+
+       add_subwindow(vectors = new MoveObjVectors(this, x, y));
+       y += vectors->get_h() + margin;
+       add_subwindow(do_stabilization = new MoveObjDoStabilization(this,
+               x, y));
+       y += do_stabilization->get_h() + margin;
+       add_subwindow(title = new BC_Title(x, y, _("Block size:")));
+       add_subwindow(block_size = new MoveObjBlockSize(this,
+               x + title->get_w() + margin, y));
+       y += block_size->get_h() + margin;
+       add_subwindow(title = new BC_Title(x, y, _("Search radius:")));
+       add_subwindow(search_radius = new MoveObjSearchRadius(this,
+               x + title->get_w() + margin, y));
+       y += search_radius->get_h() + margin;
+       add_subwindow(title = new BC_Title(x, y, _("Settling speed:")));
+       add_subwindow(settling_speed = new MoveObjSettling(this,
+               x + title->get_w() + margin, y));
+
+       show_window(1);
+}
+
+MoveObjVectors::MoveObjVectors(MoveObjWindow *gui, int x, int y)
+ : BC_CheckBox(x, y, gui->plugin->config.draw_vectors, _("Draw vectors"))
+{
+       this->gui = gui;
+}
+
+int MoveObjVectors::handle_event()
+{
+       gui->plugin->config.draw_vectors = get_value();
+       gui->plugin->send_configure_change();
+       return 1;
+}
+
+
+MoveObjDoStabilization::MoveObjDoStabilization(MoveObjWindow *gui, int x, int y)
+ : BC_CheckBox(x, y, gui->plugin->config.do_stabilization, _("Do stabilization"))
+{
+       this->gui = gui;
+}
+
+int MoveObjDoStabilization::handle_event()
+{
+       gui->plugin->config.do_stabilization = get_value();
+       gui->plugin->send_configure_change();
+       return 1;
+}
+
+
+MoveObjBlockSize::MoveObjBlockSize(MoveObjWindow *gui, int x, int y)
+ : BC_IPot(x, y, (int64_t)gui->plugin->config.block_size, (int64_t)5, (int64_t)100)
+{
+       this->gui = gui;
+}
+
+int MoveObjBlockSize::handle_event()
+{
+       gui->plugin->config.block_size = (int)get_value();
+       gui->plugin->send_configure_change();
+       return 1;
+}
+
+
+MoveObjSearchRadius::MoveObjSearchRadius(MoveObjWindow *gui, int x, int y)
+ : BC_IPot(x, y, (int64_t)gui->plugin->config.search_radius, (int64_t)1, (int64_t)100)
+{
+       this->gui = gui;
+}
+
+int MoveObjSearchRadius::handle_event()
+{
+       gui->plugin->config.search_radius = (int)get_value();
+       gui->plugin->send_configure_change();
+       return 1;
+}
+
+
+MoveObjSettling::MoveObjSettling(MoveObjWindow *gui, int x, int y)
+ : BC_IPot(x, y, (int64_t)gui->plugin->config.settling_speed, (int64_t)0, (int64_t)100)
+{
+       this->gui = gui;
+}
+
+int MoveObjSettling::handle_event()
+{
+       gui->plugin->config.settling_speed = (int)get_value();
+       gui->plugin->send_configure_change();
+       return 1;
+}
+
diff --git a/cinelerra-5.1/plugins/moveobj/moveobjwindow.h b/cinelerra-5.1/plugins/moveobj/moveobjwindow.h
new file mode 100644 (file)
index 0000000..c672da6
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * CINELERRA
+ * Copyright (C) 2008-2014 Adam Williams <broadcast at earthling dot net>
+ * 
+ * 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
+ * 
+ */
+
+#ifndef MOVEOBJWINDOW_H
+#define MOVEOBJWINDOW_H
+
+
+#include "guicast.h"
+
+class MoveObj;
+class MoveObjWindow;
+
+
+class MoveObjVectors : public BC_CheckBox
+{
+public:
+       MoveObjVectors(MoveObjWindow *gui, int x, int y);
+       int handle_event();
+       MoveObjWindow *gui;
+};
+
+class MoveObjDoStabilization : public BC_CheckBox
+{
+public:
+       MoveObjDoStabilization(MoveObjWindow *gui, int x, int y);
+       int handle_event();
+       MoveObjWindow *gui;
+};
+
+class MoveObjBlockSize : public BC_IPot
+{
+public:
+       MoveObjBlockSize(MoveObjWindow *gui, int x, int y);
+       int handle_event();
+       MoveObjWindow *gui;
+};
+
+class MoveObjSearchRadius : public BC_IPot
+{
+public:
+       MoveObjSearchRadius(MoveObjWindow *gui, int x, int y);
+       int handle_event();
+       MoveObjWindow *gui;
+};
+
+class MoveObjMaxMovement : public BC_IPot
+{
+public:
+       MoveObjMaxMovement(MoveObjWindow *gui, int x, int y);
+       int handle_event();
+       MoveObjWindow *gui;
+};
+
+class MoveObjSettling : public BC_IPot
+{
+public:
+       MoveObjSettling(MoveObjWindow *gui, int x, int y);
+       int handle_event();
+       MoveObjWindow *gui;
+};
+
+class MoveObjWindow : public PluginClientWindow
+{
+public:
+       MoveObjWindow(MoveObj *plugin);
+       ~MoveObjWindow();
+
+       void create_objects();
+
+       MoveObj *plugin;
+       MoveObjVectors *vectors;
+       MoveObjDoStabilization *do_stabilization;
+       MoveObjBlockSize *block_size;
+       MoveObjSearchRadius *search_radius;
+// not implemented
+//     MoveObjMaxMovement *max_movement;
+       MoveObjSettling *settling_speed;
+};
+
+#endif