From 1c620af9f5fc67af9d3eefb22a86d8f4a9104b6d Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sun, 20 Jan 2019 12:07:22 +1100 Subject: [PATCH] work on frei0r support --- effects/internal/frei0reffect.cpp | 64 +++++++++++ effects/internal/frei0reffect.h | 20 ++++ io/path.cpp | 9 ++ io/path.h | 1 + main.cpp | 11 +- olive.pro | 8 +- panels/panels.cpp | 1 + playback/playback.cpp | 27 +++-- project/effect.cpp | 178 +----------------------------- project/effect.h | 6 +- project/effectloaders.cpp | 178 ++++++++++++++++++++++++++++++ project/effectloaders.h | 8 ++ 12 files changed, 318 insertions(+), 193 deletions(-) create mode 100644 effects/internal/frei0reffect.cpp create mode 100644 effects/internal/frei0reffect.h create mode 100644 project/effectloaders.cpp create mode 100644 project/effectloaders.h diff --git a/effects/internal/frei0reffect.cpp b/effects/internal/frei0reffect.cpp new file mode 100644 index 000000000..dddbc5c90 --- /dev/null +++ b/effects/internal/frei0reffect.cpp @@ -0,0 +1,64 @@ +#include "frei0reffect.h" + +#include + +#include + +typedef f0r_instance_t (*f0rConstructFunc)(unsigned int width, unsigned int height); +typedef int (*f0rInitFunc) (); +typedef void (*f0rDeinitFunc) (); +typedef void (*f0rUpdateFunc) (f0r_instance_t instance, + double time, const uint32_t* inframe, uint32_t* outframe); +typedef void (*f0rDestructFunc)(f0r_instance_t instance); + +Frei0rEffect::Frei0rEffect(Clip *c, const EffectMeta *em) : Effect(c, em) { + enable_image = true; + + add_row("Heck"); + + + // Windows DLL loading routine + QString dll_fn = "E:/invert0r.dll"; + LPCWSTR dll_fn_w = reinterpret_cast(dll_fn.utf16()); + + modulePtr = LoadLibrary(dll_fn_w); + if(modulePtr == nullptr) { + DWORD dll_err = GetLastError(); + qCritical() << "Failed to load VST" << dll_fn_w << "-" << dll_err; + QString msg_err = tr("Failed to load VST plugin \"%1\": %2").arg(dll_fn, QString::number(dll_err)); + if (dll_err == 193) { +#ifdef _WIN64 + msg_err += "\n\n" + tr("NOTE: You can't load 32-bit VST plugins into a 64-bit build of Olive. Please find a 64-bit version of this plugin or switch to a 32-bit build of Olive."); +#elif _WIN32 + msg_err += "\n\n" + tr("NOTE: You can't load 64-bit VST plugins into a 32-bit build of Olive. Please find a 32-bit version of this plugin or switch to a 64-bit build of Olive."); +#endif + } + QMessageBox::critical(nullptr, tr("Error loading VST plugin"), msg_err); + return; + } + + f0rConstructFunc construct = reinterpret_cast(GetProcAddress(modulePtr, "f0r_construct")); + + f0rInitFunc init = reinterpret_cast(GetProcAddress(modulePtr, "f0r_init")); + + init(); + + instance = construct(1920, 1080); +} + +Frei0rEffect::~Frei0rEffect() { + if (modulePtr != nullptr) { + FreeModule(modulePtr); + + f0rDestructFunc destruct = reinterpret_cast(GetProcAddress(modulePtr, "f0r_destruct")); + destruct(instance); + + f0rDeinitFunc deinit = reinterpret_cast(GetProcAddress(modulePtr, "f0r_deinit")); + deinit(); + } +} + +void Frei0rEffect::process_image(double timecode, uint8_t *input, uint8_t *output, int size) { + f0rUpdateFunc update_func = reinterpret_cast(GetProcAddress(modulePtr, "f0r_update")); + update_func(instance, timecode, reinterpret_cast(input), reinterpret_cast(output)); +} diff --git a/effects/internal/frei0reffect.h b/effects/internal/frei0reffect.h new file mode 100644 index 000000000..241941921 --- /dev/null +++ b/effects/internal/frei0reffect.h @@ -0,0 +1,20 @@ +#ifndef FREI0REFFECT_H +#define FREI0REFFECT_H + +#include "project/effect.h" + +#include + +class Frei0rEffect : public Effect { + Q_OBJECT +public: + Frei0rEffect(Clip* c, const EffectMeta* em); + ~Frei0rEffect(); + + virtual void process_image(double timecode, uint8_t* input, uint8_t* output, int size); +private: + HMODULE modulePtr; + f0r_instance_t instance; +}; + +#endif // FREI0REFFECT_H diff --git a/io/path.cpp b/io/path.cpp index 2d24812f0..79248904d 100644 --- a/io/path.cpp +++ b/io/path.cpp @@ -32,3 +32,12 @@ QString get_config_path() { return QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation); } } + +QList get_effects_paths() { + QList effects_paths; + effects_paths.append(get_app_dir() + "/effects"); + effects_paths.append(get_app_dir() + "/../share/olive-editor/effects"); + QString env_path(qgetenv("OLIVE_EFFECTS_PATH")); + if (!env_path.isEmpty()) effects_paths.append(env_path); + return effects_paths; +} diff --git a/io/path.h b/io/path.h index 9eff9033f..2e2f6d841 100644 --- a/io/path.h +++ b/io/path.h @@ -6,5 +6,6 @@ QString get_app_dir(); QString get_data_path(); QString get_config_path(); +QList get_effects_paths(); #endif // PATH_H diff --git a/main.cpp b/main.cpp index 2b15e5bac..d11e9886d 100644 --- a/main.cpp +++ b/main.cpp @@ -20,9 +20,7 @@ int main(int argc, char *argv[]) { bool launch_fullscreen = false; QString load_proj; -#ifndef NODEBUG - qInstallMessageHandler(debug_message_handler); -#endif + bool use_internal_logger = true; if (argc > 1) { for (int i=1;i diff --git a/playback/playback.cpp b/playback/playback.cpp index 4e16d8d54..b8573942e 100644 --- a/playback/playback.cpp +++ b/playback/playback.cpp @@ -255,26 +255,35 @@ void get_clip_frame(Clip* c, long playhead, bool& texture_failed) { int nb_components = av_pix_fmt_desc_get(static_cast(c->pix_fmt))->nb_components; glPixelStorei(GL_UNPACK_ROW_LENGTH, target_frame->linesize[0]/nb_components); - bool copied = false; - uint8_t* data = target_frame->data[0]; + // 2 data buffers to ping-pong between + bool using_db_1 = true; + uint8_t* data_buffer_1 = target_frame->data[0]; + uint8_t* data_buffer_2 = nullptr; + int frame_size; for (int i=0;ieffects.size();i++) { Effect* e = c->effects.at(i); if (e->enable_image) { - if (!copied) { + if (data_buffer_1 == target_frame->data[0]) { frame_size = target_frame->linesize[0]*target_frame->height; - data = new uint8_t[frame_size]; - memcpy(data, target_frame->data[0], frame_size); - copied = true; + + data_buffer_1 = new uint8_t[frame_size]; + data_buffer_2 = new uint8_t[frame_size]; + + memcpy(data_buffer_1, target_frame->data[0], frame_size); } - e->process_image(get_timecode(c, playhead), data, frame_size); + e->process_image(get_timecode(c, playhead), using_db_1 ? data_buffer_1 : data_buffer_2, using_db_1 ? data_buffer_2 : data_buffer_1, frame_size); + using_db_1 = !using_db_1; } } - c->texture->setData(0, get_gl_pix_fmt_from_av(c->pix_fmt), QOpenGLTexture::UInt8, data); + c->texture->setData(0, get_gl_pix_fmt_from_av(c->pix_fmt), QOpenGLTexture::UInt8, using_db_1 ? data_buffer_1 : data_buffer_2); - if (copied) delete [] data; + if (data_buffer_1 != target_frame->data[0]) { + delete [] data_buffer_1; + delete [] data_buffer_2; + } glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); } diff --git a/project/effect.cpp b/project/effect.cpp index 8812364a3..386d006c9 100644 --- a/project/effect.cpp +++ b/project/effect.cpp @@ -32,6 +32,7 @@ #include "effects/internal/vsthostwin.h" #endif #include "effects/internal/fillleftrighteffect.h" +#include "effects/internal/frei0reffect.h" #include #include @@ -69,6 +70,7 @@ Effect* create_effect(Clip* c, const EffectMeta* em) { #ifdef _WIN32 case EFFECT_INTERNAL_VST: return new VSTHostWin(c, em); #endif + case EFFECT_INTERNAL_FREI0R: return new Frei0rEffect(c, em); } } else { qCritical() << "Invalid effect data"; @@ -88,180 +90,6 @@ const EffectMeta* get_internal_meta(int internal_id, int type) { return nullptr; } -void load_internal_effects() { - if (!shaders_are_enabled) qWarning() << "Shaders are disabled, some effects may be nonfunctional"; - - EffectMeta em; - - // internal effects - em.type = EFFECT_TYPE_EFFECT; - em.subtype = EFFECT_TYPE_AUDIO; - - em.name = "Volume"; - em.internal = EFFECT_INTERNAL_VOLUME; - effects.append(em); - - em.name = "Pan"; - em.internal = EFFECT_INTERNAL_PAN; - effects.append(em); - -#ifdef _WIN32 - em.name = "VST Plugin 2.x"; - em.internal = EFFECT_INTERNAL_VST; - effects.append(em); -#endif - - em.name = "Tone"; - em.internal = EFFECT_INTERNAL_TONE; - effects.append(em); - - em.name = "Noise"; - em.internal = EFFECT_INTERNAL_NOISE; - effects.append(em); - - em.name = "Fill Left/Right"; - em.internal = EFFECT_INTERNAL_FILLLEFTRIGHT; - effects.append(em); - - em.subtype = EFFECT_TYPE_VIDEO; - - em.name = "Transform"; - em.category = "Distort"; - em.internal = EFFECT_INTERNAL_TRANSFORM; - effects.append(em); - - em.name = "Corner Pin"; - em.internal = EFFECT_INTERNAL_CORNERPIN; - effects.append(em); - - /*em.name = "Mask"; - em.internal = EFFECT_INTERNAL_MASK; - effects.append(em);*/ - - em.name = "Shake"; - em.internal = EFFECT_INTERNAL_SHAKE; - effects.append(em); - - em.name = "Text"; - em.category = "Render"; - em.internal = EFFECT_INTERNAL_TEXT; - effects.append(em); - - em.name = "Timecode"; - em.internal = EFFECT_INTERNAL_TIMECODE; - effects.append(em); - - em.name = "Solid"; - em.internal = EFFECT_INTERNAL_SOLID; - effects.append(em); - - // internal transitions - em.type = EFFECT_TYPE_TRANSITION; - em.category = ""; - - em.name = "Cross Dissolve"; - em.internal = TRANSITION_INTERNAL_CROSSDISSOLVE; - effects.append(em); - - em.subtype = EFFECT_TYPE_AUDIO; - - em.name = "Linear Fade"; - em.internal = TRANSITION_INTERNAL_LINEARFADE; - effects.append(em); - - em.name = "Exponential Fade"; - em.internal = TRANSITION_INTERNAL_EXPONENTIALFADE; - effects.append(em); - - em.name = "Logarithmic Fade"; - em.internal = TRANSITION_INTERNAL_LOGARITHMICFADE; - effects.append(em); -} - -QList get_effects_paths() { - QList effects_paths; - effects_paths.append(get_app_dir() + "/effects"); - effects_paths.append(get_app_dir() + "/../share/olive-editor/effects"); - QString env_path(qgetenv("OLIVE_EFFECTS_PATH")); - if (!env_path.isEmpty()) effects_paths.append(env_path); - return effects_paths; -} - -void load_shader_effects() { - QList effects_paths = get_effects_paths(); - - for (int h=0;h entries = effects_dir.entryList(QStringList("*.xml"), QDir::Files); - for (int i=0;istart(); -} - -EffectInit::EffectInit() { - panel_effect_controls->effects_loaded.lock(); -} - -void EffectInit::run() { - qInfo() << "Initializing effects..."; - load_internal_effects(); - load_shader_effects(); - load_vst_effects(); - panel_effect_controls->effects_loaded.unlock(); - qInfo() << "Finished initializing effects"; -} - Effect::Effect(Clip* c, const EffectMeta *em) : parent_clip(c), meta(em), @@ -866,7 +694,7 @@ void Effect::endEffect() { bound = false; } -void Effect::process_image(double, uint8_t *, int) {} +void Effect::process_image(double, uint8_t *input, uint8_t *output, int) {} Effect* Effect::copy(Clip* c) { Effect* copy = create_effect(c, meta); diff --git a/project/effect.h b/project/effect.h index 330426b2c..2bc940458 100644 --- a/project/effect.h +++ b/project/effect.h @@ -38,7 +38,6 @@ extern bool shaders_are_enabled; extern QVector effects; double log_volume(double linear); -void init_effects(); Effect* create_effect(Clip* c, const EffectMeta *em); const EffectMeta* get_internal_meta(int internal_id, int type); @@ -65,7 +64,8 @@ const EffectMeta* get_internal_meta(int internal_id, int type); #define EFFECT_INTERNAL_FILLLEFTRIGHT 10 #define EFFECT_INTERNAL_VST 11 #define EFFECT_INTERNAL_CORNERPIN 12 -#define EFFECT_INTERNAL_COUNT 13 +#define EFFECT_INTERNAL_FREI0R 13 +#define EFFECT_INTERNAL_COUNT 14 #define KEYFRAME_TYPE_LINEAR 0 #define KEYFRAME_TYPE_BEZIER 1 @@ -156,7 +156,7 @@ public: const char* ffmpeg_filter; - virtual void process_image(double timecode, uint8_t* data, int size); + virtual void process_image(double timecode, uint8_t* input, uint8_t* output, int size); virtual void process_shader(double timecode, GLTextureCoords&); virtual void process_coords(double timecode, GLTextureCoords& coords, int data); virtual GLuint process_superimpose(double timecode); diff --git a/project/effectloaders.cpp b/project/effectloaders.cpp new file mode 100644 index 000000000..1af06cca9 --- /dev/null +++ b/project/effectloaders.cpp @@ -0,0 +1,178 @@ +#include "effectloaders.h" + +#include "project/effect.h" +#include "project/transition.h" +#include "io/path.h" +#include "panels/panels.h" +#include "panels/effectcontrols.h" + +#include +#include + +#include + +void load_internal_effects() { + if (!shaders_are_enabled) qWarning() << "Shaders are disabled, some effects may be nonfunctional"; + + EffectMeta em; + + // internal effects + em.type = EFFECT_TYPE_EFFECT; + em.subtype = EFFECT_TYPE_AUDIO; + + em.name = "Volume"; + em.internal = EFFECT_INTERNAL_VOLUME; + effects.append(em); + + em.name = "Pan"; + em.internal = EFFECT_INTERNAL_PAN; + effects.append(em); + +#ifdef _WIN32 + em.name = "VST Plugin 2.x"; + em.internal = EFFECT_INTERNAL_VST; + effects.append(em); +#endif + + em.name = "Tone"; + em.internal = EFFECT_INTERNAL_TONE; + effects.append(em); + + em.name = "Noise"; + em.internal = EFFECT_INTERNAL_NOISE; + effects.append(em); + + em.name = "Fill Left/Right"; + em.internal = EFFECT_INTERNAL_FILLLEFTRIGHT; + effects.append(em); + + em.subtype = EFFECT_TYPE_VIDEO; + + // TEMPORARY begin + em.name = "Frei0r Plugin"; + em.internal = EFFECT_INTERNAL_FREI0R; + effects.append(em); + // TEMPORARY end + + em.name = "Transform"; + em.category = "Distort"; + em.internal = EFFECT_INTERNAL_TRANSFORM; + effects.append(em); + + em.name = "Corner Pin"; + em.internal = EFFECT_INTERNAL_CORNERPIN; + effects.append(em); + + /*em.name = "Mask"; + em.internal = EFFECT_INTERNAL_MASK; + effects.append(em);*/ + + em.name = "Shake"; + em.internal = EFFECT_INTERNAL_SHAKE; + effects.append(em); + + em.name = "Text"; + em.category = "Render"; + em.internal = EFFECT_INTERNAL_TEXT; + effects.append(em); + + em.name = "Timecode"; + em.internal = EFFECT_INTERNAL_TIMECODE; + effects.append(em); + + em.name = "Solid"; + em.internal = EFFECT_INTERNAL_SOLID; + effects.append(em); + + // internal transitions + em.type = EFFECT_TYPE_TRANSITION; + em.category = ""; + + em.name = "Cross Dissolve"; + em.internal = TRANSITION_INTERNAL_CROSSDISSOLVE; + effects.append(em); + + em.subtype = EFFECT_TYPE_AUDIO; + + em.name = "Linear Fade"; + em.internal = TRANSITION_INTERNAL_LINEARFADE; + effects.append(em); + + em.name = "Exponential Fade"; + em.internal = TRANSITION_INTERNAL_EXPONENTIALFADE; + effects.append(em); + + em.name = "Logarithmic Fade"; + em.internal = TRANSITION_INTERNAL_LOGARITHMICFADE; + effects.append(em); +} + +void load_shader_effects() { + QList effects_paths = get_effects_paths(); + + for (int h=0;h entries = effects_dir.entryList(QStringList("*.xml"), QDir::Files); + for (int i=0;istart(); +} + +EffectInit::EffectInit() { + panel_effect_controls->effects_loaded.lock(); +} + +void EffectInit::run() { + qInfo() << "Initializing effects..."; + load_internal_effects(); + load_shader_effects(); + panel_effect_controls->effects_loaded.unlock(); + qInfo() << "Finished initializing effects"; +} diff --git a/project/effectloaders.h b/project/effectloaders.h new file mode 100644 index 000000000..3d88cf64e --- /dev/null +++ b/project/effectloaders.h @@ -0,0 +1,8 @@ +#ifndef EFFECTLOADERS_H +#define EFFECTLOADERS_H + +#include + +void init_effects(); + +#endif // EFFECTLOADERS_H