#include "lofwindow.h" // repeat last output frame on read_frame error // uses vframe.status as read status REGISTER_PLUGIN(LofEffect) LofConfig::LofConfig() { errs = 0; miss = 1; mark = 1; } void LofConfig::copy_from(LofConfig &src) { errs = src.errs; miss = src.miss; mark = src.mark; } int LofConfig::equivalent(LofConfig &src) { if( errs != src.errs ) return 0; if( miss != src.miss ) return 0; if( mark != src.mark ) return 0; return 1; } void LofConfig::interpolate(LofConfig &prev, LofConfig &next, long prev_frame, long next_frame, long current_frame) { copy_from(prev); } LofEffect::LofEffect(PluginServer *server) : PluginVClient(server) { frm = 0; } LofEffect::~LofEffect() { delete frm; } const char* LofEffect::plugin_title() { return _("Last Frame"); } int LofEffect::is_realtime() { return 1; } NEW_WINDOW_MACRO(LofEffect, LofWindow) LOAD_CONFIGURATION_MACRO(LofEffect, LofConfig) void LofEffect::update_gui() { if(thread) { thread->window->lock_window(); load_configuration(); ((LofWindow*)thread->window)->update(); thread->window->unlock_window(); } } void LofEffect::save_data(KeyFrame *keyframe) { FileXML output; output.set_shared_output(keyframe->get_data(), MESSAGESIZE); output.tag.set_title("LOF"); output.tag.set_property("ERRS", config.errs); output.tag.set_property("MISS", config.miss); output.tag.set_property("MARK", config.mark); output.append_tag(); output.terminate_string(); } void LofEffect::read_data(KeyFrame *keyframe) { FileXML input; input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data())); while(!input.read_tag()) { if(input.tag.title_is("LOF")) { config.errs = input.tag.get_property("ERRS", config.errs); config.miss = input.tag.get_property("MISS", config.miss); config.mark = input.tag.get_property("MARK", config.mark); } } } int LofEffect::process_buffer(VFrame *frame, int64_t start_position, double frame_rate) { load_configuration(); int w = frame->get_w(), h = frame->get_h(); int colormodel = frame->get_color_model(); if( frm && (frm->get_w() != w || frm->get_h() != h || frm->get_color_model() != colormodel ) ) { delete frm; frm = 0; } int ret = read_frame(frame, 0, start_position, frame_rate, get_use_opengl()); if( ret >= 0 ) ret = frame->get_status(); if( ret > 0 ) { if( !frm ) frm = new VFrame(w, h, colormodel, -1); frm->copy_from(frame); } else if( !frm ) frame->clear_frame(); else if( (ret < 0 && config.errs) || (!ret && config.miss) ) { frame->copy_from(frm); if( config.mark ) { VFrame dot(1, 1, BC_RGBA8888, -1); *(uint32_t*)dot.get_rows()[0] = 0xff0000ff; int scl = 48, sz = 3, ww = w/scl, hh = h/scl; if( ww < sz ) ww = w > sz ? sz : w; if( hh < sz ) hh = h > sz ? sz : h; BC_CModels::transfer( frame->get_rows(), dot.get_rows(), frame->get_y(), frame->get_u(), frame->get_v(), dot.get_y(), dot.get_u(), dot.get_v(), 0, 0, 1, 1, 0, 0, ww, hh, dot.get_color_model(), frame->get_color_model(), 0, dot.get_w(), frame->get_w()); } } return 0; }