4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #include "pluginserver.h"
33 REGISTER_PLUGIN(ScaleMain)
37 ScaleConfig::ScaleConfig()
39 reset(RESET_DEFAULT_SETTINGS);
42 void ScaleConfig::reset(int clear)
58 case RESET_DEFAULT_SETTINGS :
61 x_factor = y_factor = 1;
62 width = 1280; height = 720;
69 void ScaleConfig::copy_from(ScaleConfig &src)
72 x_factor = src.x_factor;
73 y_factor = src.y_factor;
74 constrain = src.constrain;
78 int ScaleConfig::equivalent(ScaleConfig &src)
80 return type != src.type ? 0 : type == FIXED_SCALE ?
81 EQUIV(x_factor, src.x_factor) && EQUIV(y_factor, src.y_factor) &&
82 constrain == src.constrain :
83 width == src.width && height == src.height;
86 void ScaleConfig::interpolate(ScaleConfig &prev, ScaleConfig &next,
87 int64_t prev_frame, int64_t next_frame, int64_t current_frame)
89 double u = (double)(next_frame - current_frame) / (next_frame - prev_frame);
92 this->type = prev.type;
93 this->x_factor = u*prev.x_factor + v*next.x_factor;
94 this->y_factor = u*prev.y_factor + v*next.y_factor;
95 this->constrain = prev.constrain;
96 this->width = u*prev.width + v*next.width;
97 this->height = u*prev.height + v*next.height;
102 ScaleMain::ScaleMain(PluginServer *server)
103 : PluginVClient(server)
105 this->server = server;
109 ScaleMain::~ScaleMain()
111 if(overlayer) delete overlayer;
114 const char* ScaleMain::plugin_title() { return N_("Scale"); }
115 int ScaleMain::is_realtime() { return 1; }
119 LOAD_CONFIGURATION_MACRO(ScaleMain, ScaleConfig)
122 void ScaleMain::set_type(int type)
124 if( type != config.type ) {
126 ScaleWin *swin = (ScaleWin *)thread->window;
127 int fixed_scale = type == FIXED_SCALE ? 1 : 0;
128 swin->use_scale->update(fixed_scale);
129 swin->x_factor_text->enabled = fixed_scale;
130 swin->y_factor_text->enabled = fixed_scale;
131 int fixed_size = 1 - fixed_scale;
132 swin->use_size->update(fixed_size);
133 swin->width_text->enabled = fixed_size;
134 swin->height_text->enabled = fixed_size;
135 send_configure_change();
139 void ScaleMain::save_data(KeyFrame *keyframe)
143 // cause data to be stored directly in text
144 output.set_shared_output(keyframe->xbuf);
147 output.tag.set_title("SCALE");
148 output.tag.set_property("TYPE", config.type);
149 output.tag.set_property("X_FACTOR", config.x_factor);
150 output.tag.set_property("Y_FACTOR", config.y_factor);
151 output.tag.set_property("WIDTH", config.width);
152 output.tag.set_property("HEIGHT", config.height);
153 output.tag.set_property("CONSTRAIN", config.constrain);
155 output.tag.set_title("/SCALE");
157 output.append_newline();
158 output.terminate_string();
159 // data is now in *text
162 void ScaleMain::read_data(KeyFrame *keyframe)
166 input.set_shared_input(keyframe->xbuf);
169 config.constrain = 0;
173 result = input.read_tag();
177 if(input.tag.title_is("SCALE"))
179 config.type = input.tag.get_property("TYPE", config.type);
180 config.x_factor = input.tag.get_property("X_FACTOR", config.x_factor);
181 config.y_factor = input.tag.get_property("Y_FACTOR", config.y_factor);
182 config.constrain = input.tag.get_property("CONSTRAIN", config.constrain);
183 config.width = input.tag.get_property("WIDTH", config.x_factor);
184 config.height = input.tag.get_property("HEIGHT", config.y_factor);
197 int ScaleMain::process_buffer(VFrame *frame,
198 int64_t start_position,
201 VFrame *input, *output;
202 input = output = frame;
204 load_configuration();
205 read_frame(frame, 0, start_position, frame_rate, get_use_opengl());
208 if( config.type == FIXED_SCALE ?
209 config.x_factor == 1 && config.y_factor == 1 :
210 config.width == frame->get_w() && config.height == frame->get_h() )
213 if(get_use_opengl()) return run_opengl();
215 VFrame *temp_frame = new_temp(frame->get_w(), frame->get_h(),
216 frame->get_color_model());
217 temp_frame->copy_from(frame);
222 overlayer = new OverlayFrame(PluginClient::get_project_smp() + 1);
227 float in_x1, in_x2, in_y1, in_y2, out_x1, out_x2, out_y1, out_y2;
228 calculate_transfer(output,
229 in_x1, in_x2, in_y1, in_y2,
230 out_x1, out_x2, out_y1, out_y2);
231 output->clear_frame();
233 // printf("ScaleMain::process_realtime 3 output=%p input=%p config.x_factor=%f config.y_factor=%f"
234 // " config.width=%d config.height=%d config.type=%d %f %f %f %f -> %f %f %f %f\n",
235 // output, input, config.x_factor, config.y_factor, config.width, config.height, config.type,
236 // in_x1, in_y1, in_x2, in_y2, out_x1, out_y1, out_x2, out_y2);
237 overlayer->overlay(output, input,
238 in_x1, in_y1, in_x2, in_y2,
239 out_x1, out_y1, out_x2, out_y2,
240 1, TRANSFER_REPLACE, get_interpolation_type());
245 void ScaleMain::calculate_transfer(VFrame *frame,
246 float &in_x1, float &in_x2, float &in_y1, float &in_y2,
247 float &out_x1, float &out_x2, float &out_y1, float &out_y2)
249 float fw = (float)frame->get_w();
250 float fh = (float)frame->get_h();
254 float x_factor = config.type == FIXED_SCALE ? config.x_factor :
255 in_x2 > 0. ? (float)config.width / in_x2 : 0;
256 float y_factor = config.type == FIXED_SCALE ? config.y_factor :
257 in_y2 > 0. ? (float)config.height / in_y2 : 0;
259 float fw2 = fw/2, fw2s = fw2*x_factor;
260 float fh2 = fh/2, fh2s = fh2*y_factor;
267 in_x1 = x_factor>0 ? in_x1 - out_x1/x_factor : 0;
271 if(out_x2 > frame->get_w()) {
272 in_x2 = x_factor>0 ? in_x2 - (out_x2-frame->get_w())/x_factor : 0;
273 out_x2 = frame->get_w();
277 in_y1 = y_factor>0 ? in_y1 - out_y1/y_factor : 0;
281 if(out_y2 > frame->get_h()) {
282 in_y2 = y_factor>0 ? in_y2 - (out_y2-frame->get_h())/y_factor : 0;
283 out_y2 = frame->get_h();
287 int ScaleMain::handle_opengl()
290 float in_x1, in_x2, in_y1, in_y2, out_x1, out_x2, out_y1, out_y2;
291 calculate_transfer(get_output(),
292 in_x1, in_x2, in_y1, in_y2,
293 out_x1, out_x2, out_y1, out_y2);
295 get_output()->to_texture();
296 get_output()->enable_opengl();
297 get_output()->init_screen();
298 get_output()->clear_pbuffer();
299 get_output()->bind_texture(0);
300 get_output()->draw_texture(
301 in_x1, in_y1, in_x2, in_y2,
302 out_x1, out_y1, out_x2, out_y2);
303 get_output()->set_opengl_state(VFrame::SCREEN);
310 NEW_WINDOW_MACRO(ScaleMain, ScaleWin)
312 void ScaleMain::update_gui()
316 load_configuration();
317 thread->window->lock_window();
318 set_type(config.type);
319 ScaleWin *swin = (ScaleWin *)thread->window;
320 swin->update(RESET_ALL);
322 // Needed to update Enable-Disable GUI when "Preset Edit" is used.
323 swin->update_scale_size_enable();
325 thread->window->unlock_window();