/*
* CINELERRA
- * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
+ * Copyright (C) 2008-2016 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
int64_t prev_frame,
int64_t next_frame,
int64_t current_frame);
- double scale;
+// was scale
+ double num;
+ double denom;
int stretch;
int interp;
int optic_flow;
};
-class ReframeRTScale : public BC_TumbleTextBox
+class ReframeRTNum : public BC_TumbleTextBox
{
public:
- ReframeRTScale(ReframeRT *plugin,
+ ReframeRTNum(ReframeRT *plugin,
+ ReframeRTWindow *gui,
+ int x,
+ int y);
+ int handle_event();
+ ReframeRT *plugin;
+};
+
+class ReframeRTDenom : public BC_TumbleTextBox
+{
+public:
+ ReframeRTDenom(ReframeRT *plugin,
ReframeRTWindow *gui,
int x,
int y);
~ReframeRTWindow();
void create_objects();
ReframeRT *plugin;
- ReframeRTScale *scale;
+ ReframeRTNum *num;
+ ReframeRTDenom *denom;
ReframeRTStretch *stretch;
ReframeRTDownsample *downsample;
ReframeRTInterpolate *interpolate;
ReframeRTConfig::ReframeRTConfig()
{
- scale = 1.0;
+ num = 1.0;
+ denom = 1.0;
stretch = 0;
interp = 0;
optic_flow = 1;
int ReframeRTConfig::equivalent(ReframeRTConfig &src)
{
- return fabs(scale - src.scale) < 0.0001 &&
+ return fabs(num - src.num) < 0.0001 &&
+ fabs(denom - src.denom) < 0.0001 &&
stretch == src.stretch &&
interp == src.interp;
}
void ReframeRTConfig::copy_from(ReframeRTConfig &src)
{
- this->scale = src.scale;
+ this->num = src.num;
+ this->denom = src.denom;
this->stretch = src.stretch;
this->interp = src.interp;
}
{
this->interp = prev.interp;
this->stretch = prev.stretch;
+ this->denom = prev.denom;
if (this->interp && prev_frame != next_frame)
{
+ double next_weight = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
+ double prev_weight = (double)(next_frame - current_frame) / (next_frame - prev_frame);
+ double prev_slope = prev.num / prev.denom, next_slope = next.num / next.denom;
// for interpolation, this is (for now) a simple linear slope to the next keyframe.
- double slope = (next.scale - prev.scale) / (next_frame - prev_frame);
- this->scale = (slope * (current_frame - prev_frame)) + prev.scale;
+ double scale = prev_slope * prev_weight + next_slope * next_weight;
+ this->num = this->denom * scale;
}
else
{
- this->scale = prev.scale;
+ this->num = prev.num;
}
}
void ReframeRTConfig::boundaries()
{
- if(fabs(scale) < 0.0001) scale = 0.0001;
+ if(num < 0.0001) num = 0.0001;
+ if(denom < 0.0001) denom = 0.0001;
}
ReframeRTWindow::ReframeRTWindow(ReframeRT *plugin)
- : PluginClientWindow(plugin, 230, 160, 230, 160, 0)
+ : PluginClientWindow(plugin, 230, 190, 230, 190, 0)
{
this->plugin = plugin;
}
void ReframeRTWindow::create_objects()
{
- int x = 10, y = 10;
+ int x = plugin->get_theme()->window_border;
+ int y = plugin->get_theme()->window_border;
BC_Title *title;
- add_subwindow(title = new BC_Title(x, y, _("Scale by amount:")));
+ add_subwindow(title = new BC_Title(x, y, _("Input frames:")));
y += title->get_h() + plugin->get_theme()->widget_border;
- scale = new ReframeRTScale(plugin,
+ num = new ReframeRTNum(plugin,
this,
x,
y);
- scale->create_objects();
- scale->set_increment(0.1);
- y += 30;
- add_subwindow(stretch = new ReframeRTStretch(plugin,
+ num->create_objects();
+ num->set_increment(1.0);
+
+ y += num->get_h() + plugin->get_theme()->widget_border;
+ add_subwindow(title = new BC_Title(x, y, _("Output frames:")));
+ y += title->get_h() + plugin->get_theme()->widget_border;
+ denom = new ReframeRTDenom(plugin,
this,
x,
- y));
+ y);
+ denom->create_objects();
+ denom->set_increment(1.0);
+
+
+ y += denom->get_h() + plugin->get_theme()->widget_border;
+ add_subwindow(stretch = new ReframeRTStretch(plugin, this, x, y));
y += 30;
- add_subwindow(downsample = new ReframeRTDownsample(plugin,
- this,
- x,
- y));
+ add_subwindow(downsample = new ReframeRTDownsample(plugin, this, x, y));
y += 30;
- add_subwindow(interpolate = new ReframeRTInterpolate(plugin,
- this,
- x,
- y));
+ add_subwindow(interpolate = new ReframeRTInterpolate(plugin, this, x, y));
+ y += 30;
+ add_subwindow(stretch = new ReframeRTStretch(plugin, this, x, y));
+ y += stretch->get_h() + plugin->get_theme()->widget_border;
+ add_subwindow(downsample = new ReframeRTDownsample(plugin, this, x, y));
show_window();
- flush();
}
-ReframeRTScale::ReframeRTScale(ReframeRT *plugin,
+ReframeRTNum::ReframeRTNum(ReframeRT *plugin,
+ ReframeRTWindow *gui,
+ int x,
+ int y)
+ : BC_TumbleTextBox(gui,
+ (float)plugin->config.num,
+ (float)0.0001,
+ (float)1000,
+ x,
+ y,
+ gui->get_w() - plugin->get_theme()->window_border * 3)
+{
+ this->plugin = plugin;
+}
+
+int ReframeRTNum::handle_event()
+{
+ plugin->config.num = atof(get_text());
+ plugin->config.boundaries();
+ plugin->send_configure_change();
+ return 1;
+}
+
+
+ReframeRTDenom::ReframeRTDenom(ReframeRT *plugin,
ReframeRTWindow *gui,
int x,
int y)
: BC_TumbleTextBox(gui,
- (float)plugin->config.scale,
+ (float)plugin->config.denom,
(float)-1000,
(float)1000,
x,
y,
- 100)
+ gui->get_w() - plugin->get_theme()->window_border * 3)
{
this->plugin = plugin;
}
-int ReframeRTScale::handle_event()
+int ReframeRTDenom::handle_event()
{
- plugin->config.scale = atof(get_text());
+ plugin->config.denom = atof(get_text());
plugin->config.boundaries();
plugin->send_configure_change();
return 1;
}
+
ReframeRTStretch::ReframeRTStretch(ReframeRT *plugin,
ReframeRTWindow *gui,
int x,
}
-const char* ReframeRT::plugin_title() { return _("ReframeRT"); }
+const char* ReframeRT::plugin_title() { return N_("ReframeRT"); }
int ReframeRT::is_realtime() { return 1; }
int ReframeRT::is_synthesis() { return 1; }
// the area under the curve is the number of frames to advance
// as long as interpolate() uses a linear slope we can use geometry to determine this
// if interpolate() changes to use a curve then this needs use (possibly) the definite integral
- input_frame += (int64_t)(segment_len * ((prev_config.scale + config.scale) / 2));
+ double prev_scale = prev_config.num / prev_config.denom;
+ double config_scale = config.num / config.denom;
+ input_frame += (int64_t)(segment_len * ((prev_scale + config_scale) / 2));
} while (!is_current_keyframe);
// Change rate
if (!config.stretch)
- input_rate *= config.scale;
+ {
+ input_rate *= config.num / config.denom;
+
+ }
// printf("ReframeRT::process_buffer %d %lld %f %lld %f\n",
// __LINE__,
// cause data to be stored directly in text
output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
output.tag.set_title("REFRAMERT");
- output.tag.set_property("SCALE", config.scale);
+// for backwards compatability, we call num scale
+ output.tag.set_property("SCALE", config.num);
+ output.tag.set_property("DENOM", config.denom);
output.tag.set_property("STRETCH", config.stretch);
output.tag.set_property("INTERPOLATE", config.interp);
output.append_tag();
{
if(input.tag.title_is("REFRAMERT"))
{
- config.scale = input.tag.get_property("SCALE", config.scale);
+// for backwards compatability, we call num scale
+ config.num = input.tag.get_property("SCALE", config.num);
+ config.denom = input.tag.get_property("DENOM", config.denom);
config.stretch = input.tag.get_property("STRETCH", config.stretch);
config.interp = input.tag.get_property("INTERPOLATE", config.interp);
}
{
ReframeRTWindow* window = (ReframeRTWindow*)thread->window;
window->lock_window("ReframeRT::update_gui");
- window->scale->update((float)config.scale);
+ window->num->update((float)config.num);
+ window->denom->update((float)config.denom);
window->stretch->update(config.stretch);
window->downsample->update(!config.stretch);
window->interpolate->update(config.interp);