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()
40 x_factor = y_factor = 1;
45 void ScaleConfig::copy_from(ScaleConfig &src)
48 x_factor = src.x_factor;
49 y_factor = src.y_factor;
50 constrain = src.constrain;
54 int ScaleConfig::equivalent(ScaleConfig &src)
56 return type != src.type ? 0 : type == FIXED_SCALE ?
57 EQUIV(x_factor, src.x_factor) && EQUIV(y_factor, src.y_factor) &&
58 constrain == src.constrain :
59 width == src.width && height == src.height;
62 void ScaleConfig::interpolate(ScaleConfig &prev, ScaleConfig &next,
63 int64_t prev_frame, int64_t next_frame, int64_t current_frame)
65 double u = (double)(next_frame - current_frame) / (next_frame - prev_frame);
68 this->type = prev.type;
69 this->x_factor = u*prev.x_factor + v*next.x_factor;
70 this->y_factor = u*prev.y_factor + v*next.y_factor;
71 this->constrain = prev.constrain;
72 this->width = u*prev.width + v*next.width;
73 this->height = u*prev.height + v*next.height;
78 ScaleMain::ScaleMain(PluginServer *server)
79 : PluginVClient(server)
81 this->server = server;
85 ScaleMain::~ScaleMain()
87 if(overlayer) delete overlayer;
90 const char* ScaleMain::plugin_title() { return N_("Scale"); }
91 int ScaleMain::is_realtime() { return 1; }
95 LOAD_CONFIGURATION_MACRO(ScaleMain, ScaleConfig)
98 void ScaleMain::set_type(int type)
100 if( type != config.type ) {
102 ScaleWin *swin = (ScaleWin *)thread->window;
103 int fixed_scale = type == FIXED_SCALE ? 1 : 0;
104 swin->use_scale->update(fixed_scale);
105 swin->x_factor->enabled = fixed_scale;
106 swin->y_factor->enabled = fixed_scale;
107 int fixed_size = 1 - fixed_scale;
108 swin->use_size->update(fixed_size);
109 swin->width->enabled = fixed_size;
110 swin->height->enabled = fixed_size;
111 send_configure_change();
115 void ScaleMain::save_data(KeyFrame *keyframe)
119 // cause data to be stored directly in text
120 output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
123 output.tag.set_title("SCALE");
124 output.tag.set_property("TYPE", config.type);
125 output.tag.set_property("X_FACTOR", config.x_factor);
126 output.tag.set_property("Y_FACTOR", config.y_factor);
127 output.tag.set_property("WIDTH", config.width);
128 output.tag.set_property("HEIGHT", config.height);
129 output.tag.set_property("CONSTRAIN", config.constrain);
131 output.tag.set_title("/SCALE");
133 output.append_newline();
134 output.terminate_string();
135 // data is now in *text
138 void ScaleMain::read_data(KeyFrame *keyframe)
142 input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
145 config.constrain = 0;
149 result = input.read_tag();
153 if(input.tag.title_is("SCALE"))
155 config.type = input.tag.get_property("TYPE", config.type);
156 config.x_factor = input.tag.get_property("X_FACTOR", config.x_factor);
157 config.y_factor = input.tag.get_property("Y_FACTOR", config.y_factor);
158 config.constrain = input.tag.get_property("CONSTRAIN", config.constrain);
159 config.width = input.tag.get_property("WIDTH", config.x_factor);
160 config.height = input.tag.get_property("HEIGHT", config.y_factor);
173 int ScaleMain::process_buffer(VFrame *frame,
174 int64_t start_position,
177 VFrame *input, *output;
178 input = output = frame;
180 load_configuration();
181 read_frame(frame, 0, start_position, frame_rate, get_use_opengl());
184 if( config.type == FIXED_SCALE ?
185 config.x_factor == 1 && config.y_factor == 1 :
186 config.width == frame->get_w() && config.height == frame->get_h() )
189 if(get_use_opengl()) return run_opengl();
191 VFrame *temp_frame = new_temp(frame->get_w(), frame->get_h(),
192 frame->get_color_model());
193 temp_frame->copy_from(frame);
198 overlayer = new OverlayFrame(PluginClient::get_project_smp() + 1);
203 float in_x1, in_x2, in_y1, in_y2, out_x1, out_x2, out_y1, out_y2;
204 calculate_transfer(output,
205 in_x1, in_x2, in_y1, in_y2,
206 out_x1, out_x2, out_y1, out_y2);
207 output->clear_frame();
209 // printf("ScaleMain::process_realtime 3 output=%p input=%p config.x_factor=%f config.y_factor=%f"
210 // " config.width=%d config.height=%d config.type=%d %f %f %f %f -> %f %f %f %f\n",
211 // output, input, config.x_factor, config.y_factor, config.width, config.height, config.type,
212 // in_x1, in_y1, in_x2, in_y2, out_x1, out_y1, out_x2, out_y2);
213 overlayer->overlay(output, input,
214 in_x1, in_y1, in_x2, in_y2,
215 out_x1, out_y1, out_x2, out_y2,
216 1, TRANSFER_REPLACE, get_interpolation_type());
221 void ScaleMain::calculate_transfer(VFrame *frame,
222 float &in_x1, float &in_x2, float &in_y1, float &in_y2,
223 float &out_x1, float &out_x2, float &out_y1, float &out_y2)
225 float fw = (float)frame->get_w();
226 float fh = (float)frame->get_h();
230 float x_factor = config.type == FIXED_SCALE ? config.x_factor :
231 in_x2 > 0. ? (float)config.width / in_x2 : 0;
232 float y_factor = config.type == FIXED_SCALE ? config.y_factor :
233 in_y2 > 0. ? (float)config.height / in_y2 : 0;
235 float fw2 = fw/2, fw2s = fw2*x_factor;
236 float fh2 = fh/2, fh2s = fh2*y_factor;
243 in_x1 = x_factor>0 ? in_x1 - out_x1/x_factor : 0;
247 if(out_x2 > frame->get_w()) {
248 in_x2 = x_factor>0 ? in_x2 - (out_x2-frame->get_w())/x_factor : 0;
249 out_x2 = frame->get_w();
253 in_y1 = y_factor>0 ? in_y1 - out_y1/y_factor : 0;
257 if(out_y2 > frame->get_h()) {
258 in_y2 = y_factor>0 ? in_y2 - (out_y2-frame->get_h())/y_factor : 0;
259 out_y2 = frame->get_h();
263 int ScaleMain::handle_opengl()
266 float in_x1, in_x2, in_y1, in_y2, out_x1, out_x2, out_y1, out_y2;
267 calculate_transfer(get_output(),
268 in_x1, in_x2, in_y1, in_y2,
269 out_x1, out_x2, out_y1, out_y2);
271 get_output()->to_texture();
272 get_output()->enable_opengl();
273 get_output()->init_screen();
274 get_output()->clear_pbuffer();
275 get_output()->bind_texture(0);
276 get_output()->draw_texture(
277 in_x1, in_y1, in_x2, in_y2,
278 out_x1, out_y1, out_x2, out_y2);
279 get_output()->set_opengl_state(VFrame::SCREEN);
286 NEW_WINDOW_MACRO(ScaleMain, ScaleWin)
288 void ScaleMain::update_gui()
292 load_configuration();
293 thread->window->lock_window();
294 set_type(config.type);
295 ScaleWin *swin = (ScaleWin *)thread->window;
296 swin->x_factor->update(config.x_factor);
297 swin->y_factor->update(config.y_factor);
298 swin->width->update((int64_t)config.width);
299 swin->height->update((int64_t)config.height);
300 swin->constrain->update(config.constrain);
301 thread->window->unlock_window();