X-Git-Url: http://git.cinelerra-gg.org/git/?a=blobdiff_plain;f=cinelerra-5.1%2Fplugins%2Ffreezeframe%2Ffreezeframe.C;fp=cinelerra-5.1%2Fplugins%2Ffreezeframe%2Ffreezeframe.C;h=69385755bb94173f203a0c097027753a94695f76;hb=30bdb85eb33a8ee7ba675038a86c6be59c43d7bd;hp=0000000000000000000000000000000000000000;hpb=52fcc46226f9df46f9ce9d0566dc568455a7db0b;p=goodguy%2Fhistory.git diff --git a/cinelerra-5.1/plugins/freezeframe/freezeframe.C b/cinelerra-5.1/plugins/freezeframe/freezeframe.C new file mode 100644 index 00000000..69385755 --- /dev/null +++ b/cinelerra-5.1/plugins/freezeframe/freezeframe.C @@ -0,0 +1,350 @@ + +/* + * CINELERRA + * Copyright (C) 1997-2012 Adam Williams + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "bcdisplayinfo.h" +#include "bchash.h" +#include "filexml.h" +#include "freezeframe.h" +#include "language.h" +#include "transportque.inc" + + + +#include + + +REGISTER_PLUGIN(FreezeFrameMain) + + + + + +FreezeFrameConfig::FreezeFrameConfig() +{ + enabled = 0; + line_double = 0; +} + +void FreezeFrameConfig::copy_from(FreezeFrameConfig &that) +{ + enabled = that.enabled; + line_double = that.line_double; +} + +int FreezeFrameConfig::equivalent(FreezeFrameConfig &that) +{ + return enabled == that.enabled && + line_double == that.line_double; +} + +void FreezeFrameConfig::interpolate(FreezeFrameConfig &prev, + FreezeFrameConfig &next, + long prev_frame, + long next_frame, + long current_frame) +{ + this->enabled = prev.enabled; + this->line_double = prev.line_double; +} + + + + + + + + + + +FreezeFrameWindow::FreezeFrameWindow(FreezeFrameMain *client) + : PluginClientWindow(client, + 200, + 100, + 200, + 100, + 0) +{ + this->client = client; +} + +FreezeFrameWindow::~FreezeFrameWindow() +{ +} + +void FreezeFrameWindow::create_objects() +{ + int x = 10, y = 10; + add_tool(enabled = new FreezeFrameToggle(client, + &client->config.enabled, + x, + y, + _("Enabled"))); +// Try using extra effect for the line double since it doesn't +// change the overhead. +// y += 30; +// add_tool(line_double = new FreezeFrameToggle(client, +// &client->config.line_double, +// x, +// y, +// _("Line double"))); + show_window(); + flush(); +} + + + + + + +FreezeFrameToggle::FreezeFrameToggle(FreezeFrameMain *client, + int *value, + int x, + int y, + char *text) + : BC_CheckBox(x, y, *value, text) +{ + this->client = client; + this->value = value; +} +FreezeFrameToggle::~FreezeFrameToggle() +{ +} +int FreezeFrameToggle::handle_event() +{ + *value = get_value(); + client->send_configure_change(); + return 1; +} + + + + + + + + + + + + +FreezeFrameMain::FreezeFrameMain(PluginServer *server) + : PluginVClient(server) +{ + + first_frame = 0; + first_frame_position = -1; +} + +FreezeFrameMain::~FreezeFrameMain() +{ + + if(first_frame) delete first_frame; +} + +const char* FreezeFrameMain::plugin_title() { return _("Freeze Frame"); } +int FreezeFrameMain::is_synthesis() { return 1; } +int FreezeFrameMain::is_realtime() { return 1; } + + +NEW_WINDOW_MACRO(FreezeFrameMain, FreezeFrameWindow) + +int FreezeFrameMain::load_configuration() +{ + KeyFrame *prev_keyframe = get_prev_keyframe(get_source_position()); + int64_t prev_position = edl_to_local(prev_keyframe->position); + if(prev_position < get_source_start()) prev_position = get_source_start(); + read_data(prev_keyframe); +// Invalidate stored frame + if(config.enabled) first_frame_position = prev_position; + return 0; +} + +void FreezeFrameMain::update_gui() +{ + if(thread) + { + load_configuration(); + ((FreezeFrameWindow*)thread->window)->lock_window(); + ((FreezeFrameWindow*)thread->window)->enabled->update(config.enabled); +// thread->window->line_double->update(config.line_double); + thread->window->unlock_window(); + } +} + +void FreezeFrameMain::save_data(KeyFrame *keyframe) +{ + FileXML output; + +// cause data to be stored directly in text + output.set_shared_output(keyframe->get_data(), MESSAGESIZE); + output.tag.set_title("FREEZEFRAME"); + output.append_tag(); + if(config.enabled) + { + output.tag.set_title("ENABLED"); + output.append_tag(); + output.tag.set_title("/ENABLED"); + output.append_tag(); + } + if(config.line_double) + { + output.tag.set_title("LINE_DOUBLE"); + output.append_tag(); + output.tag.set_title("/LINE_DOUBLE"); + output.append_tag(); + } + output.tag.set_title("/FREEZEFRAME"); + output.append_tag(); + output.append_newline(); + output.terminate_string(); +// data is now in *text +} + +void FreezeFrameMain::read_data(KeyFrame *keyframe) +{ + FileXML input; + + input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data())); + + int result = 0; + config.enabled = 0; + config.line_double = 0; + + while(!result) + { + result = input.read_tag(); + + if(!result) + { + if(input.tag.title_is("ENABLED")) + { + config.enabled = 1; + } + if(input.tag.title_is("LINE_DOUBLE")) + { + config.line_double = 1; + } + } + } +} + + + + + + + +int FreezeFrameMain::process_buffer(VFrame *frame, + int64_t start_position, + double frame_rate) +{ + int64_t previous_first_frame = first_frame_position; + load_configuration(); + +// Just entered frozen range + if(!first_frame && config.enabled) + { + if(!first_frame) + first_frame = new VFrame(0, + -1, + frame->get_w(), + frame->get_h(), + frame->get_color_model(), + -1); +//printf("FreezeFrameMain::process_buffer 1 %jd\n", first_frame_position); + read_frame(first_frame, + 0, + get_direction() == PLAY_REVERSE ? first_frame_position + 1 : first_frame_position, + frame_rate, + get_use_opengl()); + if(get_use_opengl()) return run_opengl(); + frame->copy_from(first_frame); + } + else +// Still not frozen + if(!first_frame && !config.enabled) + { + read_frame(frame, + 0, + start_position, + frame_rate, + get_use_opengl()); + } + else +// Just left frozen range + if(first_frame && !config.enabled) + { + delete first_frame; + first_frame = 0; + read_frame(frame, + 0, + start_position, + frame_rate, + get_use_opengl()); + } + else +// Still frozen + if(first_frame && config.enabled) + { +// Had a keyframe in frozen range. Load new first frame + if(previous_first_frame != first_frame_position) + { + read_frame(first_frame, + 0, + get_direction() == PLAY_REVERSE ? first_frame_position + 1 : first_frame_position, + frame_rate, + get_use_opengl()); + } + if(get_use_opengl()) return run_opengl(); + frame->copy_from(first_frame); + } + + +// Line double to support interlacing +// if(config.line_double && config.enabled) +// { +// for(int i = 0; i < frame->get_h() - 1; i += 2) +// { +// memcpy(frame->get_rows()[i + 1], +// frame->get_rows()[i], +// frame->get_bytes_per_line()); +// } +// } + + + + return 0; +} + +int FreezeFrameMain::handle_opengl() +{ +#ifdef HAVE_GL + get_output()->enable_opengl(); + get_output()->init_screen(); + first_frame->to_texture(); + first_frame->bind_texture(0); + first_frame->draw_texture(); + get_output()->set_opengl_state(VFrame::SCREEN); +#endif + return 0; +} + +