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 _("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.terminate_string();
132 // data is now in *text
135 void ScaleMain::read_data(KeyFrame *keyframe)
139 input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
142 config.constrain = 0;
146 result = input.read_tag();
150 if(input.tag.title_is("SCALE"))
152 config.type = input.tag.get_property("TYPE", config.type);
153 config.x_factor = input.tag.get_property("X_FACTOR", config.x_factor);
154 config.y_factor = input.tag.get_property("Y_FACTOR", config.y_factor);
155 config.constrain = input.tag.get_property("CONSTRAIN", config.constrain);
156 config.width = input.tag.get_property("WIDTH", config.x_factor);
157 config.height = input.tag.get_property("HEIGHT", config.y_factor);
170 int ScaleMain::process_buffer(VFrame *frame,
171 int64_t start_position,
174 VFrame *input, *output;
175 input = output = frame;
177 load_configuration();
178 read_frame(frame, 0, start_position, frame_rate, get_use_opengl());
181 if( config.type == FIXED_SCALE ?
182 config.x_factor == 1 && config.y_factor == 1 :
183 config.width == frame->get_w() && config.height == frame->get_h() )
186 if(get_use_opengl()) return run_opengl();
188 VFrame *temp_frame = new_temp(frame->get_w(), frame->get_h(),
189 frame->get_color_model());
190 temp_frame->copy_from(frame);
195 overlayer = new OverlayFrame(PluginClient::get_project_smp() + 1);
200 float in_x1, in_x2, in_y1, in_y2, out_x1, out_x2, out_y1, out_y2;
201 calculate_transfer(output,
202 in_x1, in_x2, in_y1, in_y2,
203 out_x1, out_x2, out_y1, out_y2);
204 output->clear_frame();
206 // printf("ScaleMain::process_realtime 3 output=%p input=%p config.x_factor=%f config.y_factor=%f"
207 // " config.width=%d config.height=%d config.type=%d %f %f %f %f -> %f %f %f %f\n",
208 // output, input, config.x_factor, config.y_factor, config.width, config.height, config.type,
209 // in_x1, in_y1, in_x2, in_y2, out_x1, out_y1, out_x2, out_y2);
210 overlayer->overlay(output, input,
211 in_x1, in_y1, in_x2, in_y2,
212 out_x1, out_y1, out_x2, out_y2,
213 1, TRANSFER_REPLACE, get_interpolation_type());
218 void ScaleMain::calculate_transfer(VFrame *frame,
219 float &in_x1, float &in_x2, float &in_y1, float &in_y2,
220 float &out_x1, float &out_x2, float &out_y1, float &out_y2)
222 float fw = (float)frame->get_w();
223 float fh = (float)frame->get_h();
227 float x_factor = config.type == FIXED_SCALE ? config.x_factor :
228 in_x2 > 0. ? (float)config.width / in_x2 : 0;
229 float y_factor = config.type == FIXED_SCALE ? config.y_factor :
230 in_y2 > 0. ? (float)config.height / in_y2 : 0;
232 float fw2 = fw/2, fw2s = fw2*x_factor;
233 float fh2 = fh/2, fh2s = fh2*y_factor;
240 in_x1 = x_factor>0 ? in_x1 - out_x1/x_factor : 0;
244 if(out_x2 > frame->get_w()) {
245 in_x2 = x_factor>0 ? in_x2 - (out_x2-frame->get_w())/x_factor : 0;
246 out_x2 = frame->get_w();
250 in_y1 = y_factor>0 ? in_y1 - out_y1/y_factor : 0;
254 if(out_y2 > frame->get_h()) {
255 in_y2 = y_factor>0 ? in_y2 - (out_y2-frame->get_h())/y_factor : 0;
256 out_y2 = frame->get_h();
260 int ScaleMain::handle_opengl()
263 float in_x1, in_x2, in_y1, in_y2, out_x1, out_x2, out_y1, out_y2;
264 calculate_transfer(get_output(),
265 in_x1, in_x2, in_y1, in_y2,
266 out_x1, out_x2, out_y1, out_y2);
268 get_output()->to_texture();
269 get_output()->enable_opengl();
270 get_output()->init_screen();
271 get_output()->clear_pbuffer();
272 get_output()->bind_texture(0);
273 get_output()->draw_texture(
274 in_x1, in_y1, in_x2, in_y2,
275 out_x1, out_y1, out_x2, out_y2);
276 get_output()->set_opengl_state(VFrame::SCREEN);
283 NEW_WINDOW_MACRO(ScaleMain, ScaleWin)
285 void ScaleMain::update_gui()
289 load_configuration();
290 thread->window->lock_window();
291 set_type(config.type);
292 ScaleWin *swin = (ScaleWin *)thread->window;
293 swin->x_factor->update(config.x_factor);
294 swin->y_factor->update(config.y_factor);
295 swin->width->update((int64_t)config.width);
296 swin->height->update((int64_t)config.height);
297 swin->constrain->update(config.constrain);
298 thread->window->unlock_window();