4 * Copyright (C) 1997-2012 Adam Williams <broadcast at earthling dot net>
5 * Copyright (C) 2003-2016 Cinelerra CV contributors
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "bcdisplayinfo.h"
26 #include "freezeframe.h"
28 #include "transportque.inc"
35 REGISTER_PLUGIN(FreezeFrameMain)
41 FreezeFrameConfig::FreezeFrameConfig()
47 void FreezeFrameConfig::copy_from(FreezeFrameConfig &that)
49 enabled = that.enabled;
50 line_double = that.line_double;
53 int FreezeFrameConfig::equivalent(FreezeFrameConfig &that)
55 return enabled == that.enabled &&
56 line_double == that.line_double;
59 void FreezeFrameConfig::interpolate(FreezeFrameConfig &prev,
60 FreezeFrameConfig &next,
65 this->enabled = prev.enabled;
66 this->line_double = prev.line_double;
78 FreezeFrameWindow::FreezeFrameWindow(FreezeFrameMain *client)
79 : PluginClientWindow(client, xS(160), yS(40), xS(160), yS(40), 0)
81 this->client = client;
84 FreezeFrameWindow::~FreezeFrameWindow()
88 void FreezeFrameWindow::create_objects()
90 int x = xS(10), y = yS(10);
91 add_tool(enabled = new FreezeFrameToggle(client,
92 &client->config.enabled,
96 // Try using extra effect for the line double since it doesn't
97 // change the overhead.
99 // add_tool(line_double = new FreezeFrameToggle(client,
100 // &client->config.line_double,
103 // _("Line double")));
113 FreezeFrameToggle::FreezeFrameToggle(FreezeFrameMain *client,
118 : BC_CheckBox(x, y, *value, text)
120 this->client = client;
123 FreezeFrameToggle::~FreezeFrameToggle()
126 int FreezeFrameToggle::handle_event()
128 *value = get_value();
129 client->send_configure_change();
144 FreezeFrameMain::FreezeFrameMain(PluginServer *server)
145 : PluginVClient(server)
149 first_frame_position = -1;
152 FreezeFrameMain::~FreezeFrameMain()
155 if(first_frame) delete first_frame;
158 const char* FreezeFrameMain::plugin_title() { return N_("Freeze Frame"); }
159 int FreezeFrameMain::is_synthesis() { return 1; }
160 int FreezeFrameMain::is_realtime() { return 1; }
163 NEW_WINDOW_MACRO(FreezeFrameMain, FreezeFrameWindow)
165 int FreezeFrameMain::load_configuration()
167 KeyFrame *prev_keyframe = get_prev_keyframe(get_source_position());
168 int64_t prev_position = edl_to_local(prev_keyframe->position);
169 if(prev_position < get_source_start()) prev_position = get_source_start();
170 read_data(prev_keyframe);
171 // Invalidate stored frame
172 if(config.enabled) first_frame_position = prev_position;
176 void FreezeFrameMain::update_gui()
180 load_configuration();
181 ((FreezeFrameWindow*)thread->window)->lock_window();
182 ((FreezeFrameWindow*)thread->window)->enabled->update(config.enabled);
183 // thread->window->line_double->update(config.line_double);
184 thread->window->unlock_window();
188 void FreezeFrameMain::save_data(KeyFrame *keyframe)
192 // cause data to be stored directly in text
193 output.set_shared_output(keyframe->xbuf);
194 output.tag.set_title("FREEZEFRAME");
198 output.tag.set_title("ENABLED");
200 output.tag.set_title("/ENABLED");
203 if(config.line_double)
205 output.tag.set_title("LINE_DOUBLE");
207 output.tag.set_title("/LINE_DOUBLE");
210 output.tag.set_title("/FREEZEFRAME");
212 output.append_newline();
213 output.terminate_string();
214 // data is now in *text
217 void FreezeFrameMain::read_data(KeyFrame *keyframe)
221 input.set_shared_input(keyframe->xbuf);
225 config.line_double = 0;
229 result = input.read_tag();
233 if(input.tag.title_is("ENABLED"))
237 if(input.tag.title_is("LINE_DOUBLE"))
239 config.line_double = 1;
251 int FreezeFrameMain::process_buffer(VFrame *frame,
252 int64_t start_position,
255 int64_t previous_first_frame = first_frame_position;
256 load_configuration();
258 // Just entered frozen range
259 if(!first_frame && config.enabled)
262 first_frame = new VFrame(frame->get_w(), frame->get_h(),
263 frame->get_color_model(), 0);
264 //printf("FreezeFrameMain::process_buffer 1 %jd\n", first_frame_position);
265 read_frame(first_frame,
267 get_direction() == PLAY_REVERSE ? first_frame_position + 1 : first_frame_position,
270 if(get_use_opengl()) return run_opengl();
271 frame->copy_from(first_frame);
275 if(!first_frame && !config.enabled)
284 // Just left frozen range
285 if(first_frame && !config.enabled)
297 if(first_frame && config.enabled)
299 // Had a keyframe in frozen range. Load new first frame
300 if(previous_first_frame != first_frame_position)
302 read_frame(first_frame,
304 get_direction() == PLAY_REVERSE ? first_frame_position + 1 : first_frame_position,
308 if(get_use_opengl()) return run_opengl();
309 frame->copy_from(first_frame);
313 // Line double to support interlacing
314 // if(config.line_double && config.enabled)
316 // for(int i = 0; i < frame->get_h() - 1; i += 2)
318 // memcpy(frame->get_rows()[i + 1],
319 // frame->get_rows()[i],
320 // frame->get_bytes_per_line());
329 int FreezeFrameMain::handle_opengl()
332 get_output()->enable_opengl();
333 get_output()->init_screen();
334 first_frame->to_texture();
335 first_frame->bind_texture(0);
336 first_frame->draw_texture();
337 get_output()->set_opengl_state(VFrame::SCREEN);