4 * Copyright (C) 1997-2012 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
22 #include "bcdisplayinfo.h"
25 #include "freezeframe.h"
27 #include "transportque.inc"
34 REGISTER_PLUGIN(FreezeFrameMain)
40 FreezeFrameConfig::FreezeFrameConfig()
46 void FreezeFrameConfig::copy_from(FreezeFrameConfig &that)
48 enabled = that.enabled;
49 line_double = that.line_double;
52 int FreezeFrameConfig::equivalent(FreezeFrameConfig &that)
54 return enabled == that.enabled &&
55 line_double == that.line_double;
58 void FreezeFrameConfig::interpolate(FreezeFrameConfig &prev,
59 FreezeFrameConfig &next,
64 this->enabled = prev.enabled;
65 this->line_double = prev.line_double;
77 FreezeFrameWindow::FreezeFrameWindow(FreezeFrameMain *client)
78 : PluginClientWindow(client,
85 this->client = client;
88 FreezeFrameWindow::~FreezeFrameWindow()
92 void FreezeFrameWindow::create_objects()
95 add_tool(enabled = new FreezeFrameToggle(client,
96 &client->config.enabled,
100 // Try using extra effect for the line double since it doesn't
101 // change the overhead.
103 // add_tool(line_double = new FreezeFrameToggle(client,
104 // &client->config.line_double,
107 // _("Line double")));
117 FreezeFrameToggle::FreezeFrameToggle(FreezeFrameMain *client,
122 : BC_CheckBox(x, y, *value, text)
124 this->client = client;
127 FreezeFrameToggle::~FreezeFrameToggle()
130 int FreezeFrameToggle::handle_event()
132 *value = get_value();
133 client->send_configure_change();
148 FreezeFrameMain::FreezeFrameMain(PluginServer *server)
149 : PluginVClient(server)
153 first_frame_position = -1;
156 FreezeFrameMain::~FreezeFrameMain()
159 if(first_frame) delete first_frame;
162 const char* FreezeFrameMain::plugin_title() { return _("Freeze Frame"); }
163 int FreezeFrameMain::is_synthesis() { return 1; }
164 int FreezeFrameMain::is_realtime() { return 1; }
167 NEW_WINDOW_MACRO(FreezeFrameMain, FreezeFrameWindow)
169 int FreezeFrameMain::load_configuration()
171 KeyFrame *prev_keyframe = get_prev_keyframe(get_source_position());
172 int64_t prev_position = edl_to_local(prev_keyframe->position);
173 if(prev_position < get_source_start()) prev_position = get_source_start();
174 read_data(prev_keyframe);
175 // Invalidate stored frame
176 if(config.enabled) first_frame_position = prev_position;
180 void FreezeFrameMain::update_gui()
184 load_configuration();
185 ((FreezeFrameWindow*)thread->window)->lock_window();
186 ((FreezeFrameWindow*)thread->window)->enabled->update(config.enabled);
187 // thread->window->line_double->update(config.line_double);
188 thread->window->unlock_window();
192 void FreezeFrameMain::save_data(KeyFrame *keyframe)
196 // cause data to be stored directly in text
197 output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
198 output.tag.set_title("FREEZEFRAME");
202 output.tag.set_title("ENABLED");
204 output.tag.set_title("/ENABLED");
207 if(config.line_double)
209 output.tag.set_title("LINE_DOUBLE");
211 output.tag.set_title("/LINE_DOUBLE");
214 output.tag.set_title("/FREEZEFRAME");
216 output.append_newline();
217 output.terminate_string();
218 // data is now in *text
221 void FreezeFrameMain::read_data(KeyFrame *keyframe)
225 input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
229 config.line_double = 0;
233 result = input.read_tag();
237 if(input.tag.title_is("ENABLED"))
241 if(input.tag.title_is("LINE_DOUBLE"))
243 config.line_double = 1;
255 int FreezeFrameMain::process_buffer(VFrame *frame,
256 int64_t start_position,
259 int64_t previous_first_frame = first_frame_position;
260 load_configuration();
262 // Just entered frozen range
263 if(!first_frame && config.enabled)
266 first_frame = new VFrame(0,
270 frame->get_color_model(),
272 //printf("FreezeFrameMain::process_buffer 1 %jd\n", first_frame_position);
273 read_frame(first_frame,
275 get_direction() == PLAY_REVERSE ? first_frame_position + 1 : first_frame_position,
278 if(get_use_opengl()) return run_opengl();
279 frame->copy_from(first_frame);
283 if(!first_frame && !config.enabled)
292 // Just left frozen range
293 if(first_frame && !config.enabled)
305 if(first_frame && config.enabled)
307 // Had a keyframe in frozen range. Load new first frame
308 if(previous_first_frame != first_frame_position)
310 read_frame(first_frame,
312 get_direction() == PLAY_REVERSE ? first_frame_position + 1 : first_frame_position,
316 if(get_use_opengl()) return run_opengl();
317 frame->copy_from(first_frame);
321 // Line double to support interlacing
322 // if(config.line_double && config.enabled)
324 // for(int i = 0; i < frame->get_h() - 1; i += 2)
326 // memcpy(frame->get_rows()[i + 1],
327 // frame->get_rows()[i],
328 // frame->get_bytes_per_line());
337 int FreezeFrameMain::handle_opengl()
340 get_output()->enable_opengl();
341 get_output()->init_screen();
342 first_frame->to_texture();
343 first_frame->bind_texture(0);
344 first_frame->draw_texture();
345 get_output()->set_opengl_state(VFrame::SCREEN);