diff --git a/effects/effect.cpp b/effects/effect.cpp index 9f3d80fd1..59b4ca8fe 100644 --- a/effects/effect.cpp +++ b/effects/effect.cpp @@ -147,7 +147,11 @@ void Effect::field_changed() { } bool Effect::is_enabled() { - return container->enabled_check->isChecked(); + return container->enabled_check->isChecked(); +} + +void Effect::set_enabled(bool b) { + container->enabled_check->setChecked(b); } QVariant load_data_from_string(int type, const QString& string) { @@ -290,8 +294,9 @@ Effect* Effect::copy(Clip* c) { } void Effect::process_image(double, uint8_t*, int, int) {} -void Effect::process_gl(double, QOpenGLShaderProgram&, GLTextureCoords&) {} +void Effect::process_gl(double, GLTextureCoords&) {} void Effect::process_audio(double, double, quint8*, int, int) {} +void Effect::clean_gl() {} /* Effect Row Definitions */ diff --git a/effects/effect.h b/effects/effect.h index 243d31dd9..c8d20d71a 100644 --- a/effects/effect.h +++ b/effects/effect.h @@ -180,6 +180,7 @@ public: int row_count(); bool is_enabled(); + void set_enabled(bool b); virtual void refresh(); @@ -195,7 +196,8 @@ public: const char* ffmpeg_filter; virtual void process_image(double timecode, uint8_t* data, int width, int height); - virtual void process_gl(double timecode, QOpenGLShaderProgram& shaders, GLTextureCoords& coords); + virtual void process_gl(double timecode, GLTextureCoords& coords); + virtual void clean_gl(); virtual void process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int channel_count); public slots: void field_changed(); diff --git a/effects/video/chromakeyeffect.cpp b/effects/video/chromakeyeffect.cpp index db43e98e9..1d65a3b2e 100644 --- a/effects/video/chromakeyeffect.cpp +++ b/effects/video/chromakeyeffect.cpp @@ -1,15 +1,33 @@ #include "chromakeyeffect.h" -ChromaKeyEffect::ChromaKeyEffect(Clip* c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_CHROMAKEY_EFFECT) { +ChromaKeyEffect::ChromaKeyEffect(Clip* c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_CHROMAKEY_EFFECT), vert(QOpenGLShader::Vertex), frag(QOpenGLShader::Fragment) { enable_opengl = true; color_field = add_row("Color:")->add_field(EFFECT_FIELD_COLOR); tolerance_field = add_row("Tolerance:")->add_field(EFFECT_FIELD_DOUBLE); color_field->set_color_value(Qt::green); - tolerance_field->set_double_default_value(50); + tolerance_field->set_double_default_value(10); + + tolerance_field->set_double_minimum_value(0); + tolerance_field->set_double_maximum_value(100); + + vert.compileSourceCode("varying vec2 vTexCoord;\nvoid main() {\n\tvTexCoord = gl_MultiTexCoord0.xy;\n\tgl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n}"); + frag.compileSourceCode("uniform vec4 keyColor;\nuniform float threshold;\nuniform sampler2D myTexture;\nvarying vec2 vTexCoord;\nvoid main(void) {\n\tvec4 textureColor = texture2D(myTexture, vTexCoord);\nfloat diff = length(keyColor - textureColor);\nif (diff < threshold) {gl_FragColor = vec4(0, 0, 0, 0);} else {gl_FragColor = textureColor;}\n}"); + program.addShader(&vert); + program.addShader(&frag); + program.link(); + + connect(color_field, SIGNAL(changed()), this, SLOT(field_changed())); + connect(tolerance_field, SIGNAL(changed()), this, SLOT(field_changed())); } -void ChromaKeyEffect::process_gl(double timecode, QOpenGLShaderProgram &shaders, GLTextureCoords&) { +void ChromaKeyEffect::process_gl(double timecode, GLTextureCoords&) { + program.bind(); + program.setUniformValue("keyColor", color_field->get_color_value(timecode)); + program.setUniformValue("threshold", (GLfloat) (tolerance_field->get_double_value(timecode)*0.01)); +} +void ChromaKeyEffect::clean_gl() { + program.release(); } diff --git a/effects/video/chromakeyeffect.h b/effects/video/chromakeyeffect.h index 5569ff9c0..50c70cc58 100644 --- a/effects/video/chromakeyeffect.h +++ b/effects/video/chromakeyeffect.h @@ -6,10 +6,14 @@ class ChromaKeyEffect : public Effect { public: ChromaKeyEffect(Clip* c); - void process_gl(double timecode, QOpenGLShaderProgram &shaders, GLTextureCoords &coords); + void process_gl(double timecode, GLTextureCoords &coords); + void clean_gl(); private: EffectField* color_field; EffectField* tolerance_field; + QOpenGLShaderProgram program; + QOpenGLShader vert; + QOpenGLShader frag; }; #endif // CHROMAKEYEFFECT_H diff --git a/effects/video/cropeffect.cpp b/effects/video/cropeffect.cpp index 7d35c0a19..19675cb1c 100644 --- a/effects/video/cropeffect.cpp +++ b/effects/video/cropeffect.cpp @@ -23,7 +23,7 @@ CropEffect::CropEffect(Clip *c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_CROP_EFFECT connect(bottom_field, SIGNAL(changed()), this, SLOT(field_changed())); } -void CropEffect::process_gl(double timecode, QOpenGLShaderProgram&, GLTextureCoords &coords) { +void CropEffect::process_gl(double timecode, GLTextureCoords &coords) { // store initial coord data int left = coords.vertexTopLeftX; int top = coords.vertexTopLeftY; diff --git a/effects/video/cropeffect.h b/effects/video/cropeffect.h index 174220b0e..212d8f473 100644 --- a/effects/video/cropeffect.h +++ b/effects/video/cropeffect.h @@ -7,7 +7,7 @@ class CropEffect : public Effect { public: CropEffect(Clip* c); - void process_gl(double timecode, QOpenGLShaderProgram &shaders, GLTextureCoords &coords); + void process_gl(double timecode, GLTextureCoords &coords); private: EffectField* left_field; EffectField* top_field; diff --git a/effects/video/flipeffect.cpp b/effects/video/flipeffect.cpp index 049dcceff..d338a5f76 100644 --- a/effects/video/flipeffect.cpp +++ b/effects/video/flipeffect.cpp @@ -10,7 +10,7 @@ FlipEffect::FlipEffect(Clip *c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_FLIP_EFFECT connect(vertical_field, SIGNAL(changed()), this, SLOT(field_changed())); } -void FlipEffect::process_gl(double timecode, QOpenGLShaderProgram &, GLTextureCoords &coords) { +void FlipEffect::process_gl(double timecode, GLTextureCoords &coords) { if (horizontal_field->get_bool_value(timecode)) { double tlX = coords.textureTopLeftX; double blX = coords.textureBottomLeftX; diff --git a/effects/video/flipeffect.h b/effects/video/flipeffect.h index ac192b3d3..4b20ae675 100644 --- a/effects/video/flipeffect.h +++ b/effects/video/flipeffect.h @@ -7,7 +7,7 @@ class FlipEffect : public Effect { public: FlipEffect(Clip* c); - void process_gl(double timecode, QOpenGLShaderProgram &shaders, GLTextureCoords &coords); + void process_gl(double timecode, GLTextureCoords &coords); private: EffectField* horizontal_field; EffectField* vertical_field; diff --git a/effects/video/gaussianblureffect.cpp b/effects/video/gaussianblureffect.cpp index 98fb579e3..b97b7d1d0 100644 --- a/effects/video/gaussianblureffect.cpp +++ b/effects/video/gaussianblureffect.cpp @@ -1,12 +1,21 @@ #include "gaussianblureffect.h" -GaussianBlurEffect::GaussianBlurEffect(Clip *c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_GAUSSIANBLUR_EFFECT) { +GaussianBlurEffect::GaussianBlurEffect(Clip *c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_GAUSSIANBLUR_EFFECT), frag(QOpenGLShader::Fragment), vert(QOpenGLShader::Vertex) { enable_opengl = true; + + vert.compileSourceCode("varying vec2 vTexCoord;\nvoid main() {\n\tvTexCoord = gl_MultiTexCoord0.xy;\n\tgl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n}"); + frag.compileSourceCode("uniform mediump float amount_val;\nuniform sampler2D myTexture;\nvarying vec2 vTexCoord;\nvoid main(void) {\n\tvec4 textureColor = texture2D(myTexture, vTexCoord);\n\tgl_FragColor = vec4(textureColor.r+((1.0-textureColor.r-textureColor.r)*amount_val), textureColor.g+((1.0-textureColor.g-textureColor.g)*amount_val), textureColor.b+((1.0-textureColor.b-textureColor.b)*amount_val), textureColor.a);\n}"); + program.addShader(&frag); + program.addShader(&vert); + program.link(); } -void GaussianBlurEffect::process_gl(double timecode, QOpenGLShaderProgram &shaders, GLTextureCoords &coords) { - shaders.addShaderFromSourceCode(QOpenGLShader::Vertex, "attribute vec2 position;\nvoid main() {\ngl_Position = vec4(position, 1, 1);\n}"); - shaders.addShaderFromSourceCode(QOpenGLShader::Fragment, "uniform vec3 iResolution;\nuniform sampler2D iChannel0;\nuniform bool flip;\nuniform vec2 direction;\nvoid main() {\nvec2 uv = vec2(gl_FragCoord.xy / iResolution.xy);\nif (flip) uv.y = 1.0 - uv.y;\nvec4 color = vec4(0.0);\nvec2 off1 = vec2(1.3846153846) * direction;\nvec2 off2 = vec2(3.2307692308) * direction;\ncolor += texture2D(image, uv) * 0.2270270270;\ncolor += texture2D(image, uv + (off1 / resolution)) * 0.3162162162;\ncolor += texture2D(image, uv - (off1 / resolution)) * 0.3162162162;\ncolor += texture2D(image, uv + (off2 / resolution)) * 0.0702702703;\ncolor += texture2D(image, uv - (off2 / resolution)) * 0.0702702703;\ngl_FragColor = color;}"); +void GaussianBlurEffect::process_gl(double timecode, GLTextureCoords &coords) { + program.bind(); +} + +void GaussianBlurEffect::clean_gl() { + program.release(); } diff --git a/effects/video/gaussianblureffect.h b/effects/video/gaussianblureffect.h index be0f962a5..6d9d1f998 100644 --- a/effects/video/gaussianblureffect.h +++ b/effects/video/gaussianblureffect.h @@ -7,7 +7,12 @@ class GaussianBlurEffect : public Effect { public: GaussianBlurEffect(Clip* c); - void process_gl(double timecode, QOpenGLShaderProgram &shaders, GLTextureCoords &coords); + void process_gl(double timecode, GLTextureCoords &coords); + void clean_gl(); +private: + QOpenGLShaderProgram program; + QOpenGLShader vert; + QOpenGLShader frag; }; #endif // GAUSSIANBLUREFFECT_H diff --git a/effects/video/inverteffect.cpp b/effects/video/inverteffect.cpp index 23c67e6ed..8d596f224 100644 --- a/effects/video/inverteffect.cpp +++ b/effects/video/inverteffect.cpp @@ -4,11 +4,12 @@ #include #include +#include #include #include #include -InvertEffect::InvertEffect(Clip* c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_INVERT_EFFECT) { +InvertEffect::InvertEffect(Clip* c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_INVERT_EFFECT), vert(QOpenGLShader::Vertex), frag(QOpenGLShader::Fragment) { enable_opengl = true; EffectRow* amount_row = add_row("Amount:"); @@ -20,10 +21,19 @@ InvertEffect::InvertEffect(Clip* c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_INVERT_ amount_val->set_double_default_value(100); connect(amount_val, SIGNAL(changed()), this, SLOT(field_changed())); + + vert.compileSourceCode("varying vec2 vTexCoord;\nvoid main() {\n\tvTexCoord = gl_MultiTexCoord0.xy;\n\tgl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n}"); + frag.compileSourceCode("uniform mediump float amount_val;\nuniform sampler2D myTexture;\nvarying vec2 vTexCoord;\nvoid main(void) {\n\tvec4 textureColor = texture2D(myTexture, vTexCoord);\n\tgl_FragColor = vec4(textureColor.r+((1.0-textureColor.r-textureColor.r)*amount_val), textureColor.g+((1.0-textureColor.g-textureColor.g)*amount_val), textureColor.b+((1.0-textureColor.b-textureColor.b)*amount_val), textureColor.a);\n}"); + program.addShader(&vert); + program.addShader(&frag); + program.link(); } -void InvertEffect::process_gl(double timecode, QOpenGLShaderProgram& shaders, GLTextureCoords&) { - double value = amount_val->get_double_value(timecode)*0.01; - shaders.addShaderFromSourceCode(QOpenGLShader::Vertex, "varying vec2 vTexCoord;\nvoid main() {\n\tvTexCoord = gl_MultiTexCoord0.xy;\n\tgl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n}"); - shaders.addShaderFromSourceCode(QOpenGLShader::Fragment, "uniform sampler2D myTexture;\nvarying vec2 vTexCoord;\nvoid main(void) {\n\tvec4 textureColor = texture2D(myTexture, vTexCoord);\n\tgl_FragColor = vec4(textureColor.r+((1.0-textureColor.r-textureColor.r)*" + QString::number(value, 'f', 2) + "), textureColor.g+((1.0-textureColor.g-textureColor.g)*" + QString::number(value, 'f', 2) + "), textureColor.b+((1.0-textureColor.b-textureColor.b)*" + QString::number(value, 'f', 2) + "), textureColor.a);\n}"); +void InvertEffect::process_gl(double timecode, GLTextureCoords&) { + program.bind(); + program.setUniformValue("amount_val", (GLfloat) (amount_val->get_double_value(timecode)*0.01)); +} + +void InvertEffect::clean_gl() { + program.release(); } diff --git a/effects/video/inverteffect.h b/effects/video/inverteffect.h index 18a2b939c..82e9811ae 100644 --- a/effects/video/inverteffect.h +++ b/effects/video/inverteffect.h @@ -9,9 +9,13 @@ class InvertEffect : public Effect { Q_OBJECT public: InvertEffect(Clip* c); - void process_gl(double timecode, QOpenGLShaderProgram& shaders, GLTextureCoords& coords); + void process_gl(double timecode, GLTextureCoords& coords); + void clean_gl(); private: EffectField* amount_val; + QOpenGLShader frag; + QOpenGLShader vert; + QOpenGLShaderProgram program; }; #endif // INVERTEFFECT_H diff --git a/effects/video/shakeeffect.cpp b/effects/video/shakeeffect.cpp index a11f71ab7..85ac7c418 100644 --- a/effects/video/shakeeffect.cpp +++ b/effects/video/shakeeffect.cpp @@ -49,7 +49,7 @@ void ShakeEffect::refresh() { } } -void ShakeEffect::process_gl(double timecode, QOpenGLShaderProgram&, GLTextureCoords&) { +void ShakeEffect::process_gl(double timecode, GLTextureCoords&) { if (shake_progress > shake_limit) { double ival = intensity_val->get_double_value(timecode); if ((int)ival > 0) { diff --git a/effects/video/shakeeffect.h b/effects/video/shakeeffect.h index 69f80fec3..cad853ac5 100644 --- a/effects/video/shakeeffect.h +++ b/effects/video/shakeeffect.h @@ -7,7 +7,7 @@ class ShakeEffect : public Effect { Q_OBJECT public: ShakeEffect(Clip* c); - void process_gl(double timecode, QOpenGLShaderProgram& shaders, GLTextureCoords& coords); + void process_gl(double timecode, GLTextureCoords& coords); EffectField* intensity_val; EffectField* rotation_val; diff --git a/effects/video/solideffect.cpp b/effects/video/solideffect.cpp index 26ea42af0..fad4a6411 100644 --- a/effects/video/solideffect.cpp +++ b/effects/video/solideffect.cpp @@ -40,7 +40,7 @@ void SolidEffect::enable_color() { solid_color_field->set_enabled(solid_type->get_combo_data(-1) == SOLID_TYPE_COLOR); } -void SolidEffect::process_gl(double timecode, QOpenGLShaderProgram& shaders, GLTextureCoords& coords) { +void SolidEffect::process_gl(double timecode, GLTextureCoords& coords) { } diff --git a/effects/video/solideffect.h b/effects/video/solideffect.h index 0d238115d..a3b60f147 100644 --- a/effects/video/solideffect.h +++ b/effects/video/solideffect.h @@ -10,7 +10,7 @@ public: EffectField* solid_type; EffectField* solid_color_field; EffectField* opacity_field; - void process_gl(double timecode, QOpenGLShaderProgram& shaders, GLTextureCoords& coords); + void process_gl(double timecode, GLTextureCoords& coords); void process_image(long p, uint8_t* data, int width, int height); private slots: void enable_color(); diff --git a/effects/video/transformeffect.cpp b/effects/video/transformeffect.cpp index c572106e5..4521d7131 100644 --- a/effects/video/transformeffect.cpp +++ b/effects/video/transformeffect.cpp @@ -121,7 +121,7 @@ void TransformEffect::toggle_uniform_scale(bool enabled) { scale_y->set_enabled(!enabled); } -void TransformEffect::process_gl(double timecode, QOpenGLShaderProgram&, GLTextureCoords& coords) { +void TransformEffect::process_gl(double timecode, GLTextureCoords& coords) { // position glTranslatef(position_x->get_double_value(timecode)-(parent_clip->sequence->width/2), position_y->get_double_value(timecode)-(parent_clip->sequence->height/2), 0); diff --git a/effects/video/transformeffect.h b/effects/video/transformeffect.h index a882096dc..dc885676a 100644 --- a/effects/video/transformeffect.h +++ b/effects/video/transformeffect.h @@ -8,7 +8,7 @@ class TransformEffect : public Effect { public: TransformEffect(Clip* c); void refresh(); - void process_gl(double timecode, QOpenGLShaderProgram& shaders, GLTextureCoords& coords); + void process_gl(double timecode, GLTextureCoords& coords); EffectField* position_x; EffectField* position_y; diff --git a/panels/project.cpp b/panels/project.cpp index 490a2d176..f7a82080d 100644 --- a/panels/project.cpp +++ b/panels/project.cpp @@ -844,15 +844,19 @@ bool Project::load_worker(QFile& f, QXmlStreamReader& stream, int type) { stream.readNext(); if (stream.name() == "effect" && stream.isStartElement()) { int effect_id = -1; + bool effect_enabled = true; for (int j=0;jset_enabled(effect_enabled); +// stream.writeAttribute("enabled", QString::number(e->is_enabled())); e->load(stream); c->effects.append(e); } @@ -1111,6 +1115,7 @@ void Project::save_folder(QXmlStreamWriter& stream, QTreeWidgetItem* parent, int stream.writeStartElement("effect"); // effect Effect* e = c->effects.at(k); stream.writeAttribute("id", QString::number(e->id)); + stream.writeAttribute("enabled", QString::number(e->is_enabled())); e->save(stream); stream.writeEndElement(); // effect } diff --git a/panels/timeline.cpp b/panels/timeline.cpp index 9c5fb5c92..e0fdb157c 100644 --- a/panels/timeline.cpp +++ b/panels/timeline.cpp @@ -304,16 +304,18 @@ void Timeline::redraw_all_clips(bool changed) { } void Timeline::select_all() { - selections.clear(); - for (int i=0;iclip_count();i++) { - Clip* c = sequence->get_clip(i); - Selection s; - s.in = c->timeline_in; - s.out = c->timeline_out; - s.track = c->track; - if (c != NULL) selections.append(s); + if (sequence != NULL) { + selections.clear(); + for (int i=0;iclip_count();i++) { + Clip* c = sequence->get_clip(i); + Selection s; + s.in = c->timeline_in; + s.out = c->timeline_out; + s.track = c->track; + if (c != NULL) selections.append(s); + } + repaint_timeline(); } - repaint_timeline(); } void Timeline::delete_in_out(bool ripple) { diff --git a/playback/playback.cpp b/playback/playback.cpp index ad386aa9a..cec3e3935 100644 --- a/playback/playback.cpp +++ b/playback/playback.cpp @@ -80,108 +80,105 @@ bool get_clip_frame(Clip* c, long playhead) { long clip_time = refactor_frame_number(sequence_clip_time, c->sequence->frame_rate, av_q2d(av_guess_frame_rate(c->formatCtx, c->stream, c->frame))); // do we need to update the texture? - MediaStream* ms = static_cast(c->media)->get_stream_from_file_index(c->media_stream); - if ((!ms->infinite_length/* && c->texture_frame != clip_time*/) || - (ms->infinite_length && c->texture_frame == -1)) { - AVFrame* current_frame = NULL; - bool no_frame = false; + MediaStream* ms = static_cast(c->media)->get_stream_from_file_index(c->media_stream); - // get frame data - if (ms->infinite_length) { // if clip is a still frame, we only need one - if (c->cache_A.written) { - // retrieve cached frame - current_frame = c->cache_A.frames[0]; - } else if (c->lock.tryLock()) { - // grab image - cache_clip(c, 0, true, false, false, NULL); - c->lock.unlock(); - } - } else { - // keeping a RAM cache improves performance, however it's detrimental when rendering - // determine which cache contains the requested frame - bool using_cache_A = false; - bool using_cache_B = false; - AVFrame** cache = NULL; - long cache_offset = 0; - bool cache_needs_reset = false; + AVFrame* current_frame = NULL; + bool no_frame = false; - if (c->cache_A.written && clip_time >= c->cache_A.offset && clip_time < c->cache_A.offset + c->cache_size) { - if (clip_time < c->cache_A.offset + c->cache_A.write_count) { - if (c->cache_A.mutex.tryLock()) { // lock in case cacher is still writing to it - using_cache_A = true; - c->cache_A.unread = false; - cache = c->cache_A.frames; - cache_offset = c->cache_A.offset; - c->cache_A.mutex.unlock(); - } - } else { - no_frame = true; - } - } else if (c->cache_B.written && clip_time >= c->cache_B.offset && clip_time < c->cache_B.offset + c->cache_size) { - if (clip_time < c->cache_B.offset + c->cache_B.write_count) { - if (c->cache_B.mutex.tryLock()) { // lock in case cacher is still writing to it - using_cache_B = true; - c->cache_B.unread = false; - cache = c->cache_B.frames; - cache_offset = c->cache_B.offset; - c->cache_B.mutex.unlock(); - } - } else { - no_frame = true; + // get frame data + if (ms->infinite_length) { // if clip is a still frame, we only need one + if (c->cache_A.written) { + // retrieve cached frame + current_frame = c->cache_A.frames[0]; + } else if (c->lock.tryLock()) { + // grab image + cache_clip(c, 0, true, false, false, NULL); + c->lock.unlock(); + } + } else { + // keeping a RAM cache improves performance, however it's detrimental when rendering + // determine which cache contains the requested frame + bool using_cache_A = false; + bool using_cache_B = false; + AVFrame** cache = NULL; + long cache_offset = 0; + bool cache_needs_reset = false; + + if (c->cache_A.written && clip_time >= c->cache_A.offset && clip_time < c->cache_A.offset + c->cache_size) { + if (clip_time < c->cache_A.offset + c->cache_A.write_count) { + if (c->cache_A.mutex.tryLock()) { // lock in case cacher is still writing to it + using_cache_A = true; + c->cache_A.unread = false; + cache = c->cache_A.frames; + cache_offset = c->cache_A.offset; + c->cache_A.mutex.unlock(); } } else { - // this is technically bad, unless we just seeked - c->cache_A.unread = c->cache_B.unread = false; - cache_needs_reset = true; + no_frame = true; + } + } else if (c->cache_B.written && clip_time >= c->cache_B.offset && clip_time < c->cache_B.offset + c->cache_size) { + if (clip_time < c->cache_B.offset + c->cache_B.write_count) { + if (c->cache_B.mutex.tryLock()) { // lock in case cacher is still writing to it + using_cache_B = true; + c->cache_B.unread = false; + cache = c->cache_B.frames; + cache_offset = c->cache_B.offset; + c->cache_B.mutex.unlock(); + } + } else { + no_frame = true; + } + } else { + // this is technically bad, unless we just seeked + c->cache_A.unread = c->cache_B.unread = false; + cache_needs_reset = true; + } + + if (!no_frame) { + if (cache != NULL) { + current_frame = cache[clip_time - cache_offset]; } - if (!no_frame) { - if (cache != NULL) { - current_frame = cache[clip_time - cache_offset]; - } - - // determine whether we should start filling the other cache - if (!using_cache_A || !using_cache_B) { - if (c->lock.tryLock()) { - bool write_A = (!using_cache_A && !c->cache_A.unread); - bool write_B = (!using_cache_B && !c->cache_B.unread); - if (write_A || write_B) { - // if we have no cache and need to seek, start us at the current playhead, otherwise start at the end of the current cache - cache_clip(c, (cache_needs_reset) ? clip_time : cache_offset + c->cache_size, write_A, write_B, cache_needs_reset, NULL); - } - c->lock.unlock(); + // determine whether we should start filling the other cache + if (!using_cache_A || !using_cache_B) { + if (c->lock.tryLock()) { + bool write_A = (!using_cache_A && !c->cache_A.unread); + bool write_B = (!using_cache_B && !c->cache_B.unread); + if (write_A || write_B) { + // if we have no cache and need to seek, start us at the current playhead, otherwise start at the end of the current cache + cache_clip(c, (cache_needs_reset) ? clip_time : cache_offset + c->cache_size, write_A, write_B, cache_needs_reset, NULL); } + c->lock.unlock(); } } } + } - if (current_frame != NULL) { - // set up opengl texture - if (c->texture == NULL) { - c->texture = new QOpenGLTexture(QOpenGLTexture::Target2D); - c->texture->setSize(current_frame->width, current_frame->height); - c->texture->setFormat(QOpenGLTexture::RGBA8_UNorm); - c->texture->setMipLevels(c->texture->maximumMipLevels()); - c->texture->setMinMagFilters(QOpenGLTexture::Linear, QOpenGLTexture::Linear); - c->texture->allocateStorage(QOpenGLTexture::RGBA, QOpenGLTexture::UInt8); - } - - - memcpy(c->comp_frame, current_frame->data[0], c->comp_frame_size); - for (int i=0;ieffects.size();i++) { - if (c->effects.at(i)->enable_image) { - c->effects.at(i)->process_image(sequence_clip_time, c->comp_frame, current_frame->width, current_frame->height); - } - } - - c->texture->setData(0, QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, c->comp_frame); - c->texture_frame = clip_time; - - return true; - } else if (!no_frame) { - texture_failed = true; - qDebug() << "[ERROR] Failed to retrieve frame from cache (R:" << clip_time << "| A:" << c->cache_A.offset << "-" << c->cache_A.offset+c->cache_size-1 << "| B:" << c->cache_B.offset << "-" << c->cache_B.offset+c->cache_size-1 << "| WA:" << c->cache_A.written << "| WB:" << c->cache_B.written << ")"; + if (current_frame != NULL) { + // set up opengl texture + if (c->texture == NULL) { + c->texture = new QOpenGLTexture(QOpenGLTexture::Target2D); + c->texture->setSize(current_frame->width, current_frame->height); + c->texture->setFormat(QOpenGLTexture::RGBA8_UNorm); + c->texture->setMipLevels(c->texture->maximumMipLevels()); + c->texture->setMinMagFilters(QOpenGLTexture::Linear, QOpenGLTexture::Linear); + c->texture->allocateStorage(QOpenGLTexture::RGBA, QOpenGLTexture::UInt8); } + + memcpy(c->comp_frame, current_frame->data[0], c->comp_frame_size); + for (int i=0;ieffects.size();i++) { + if (c->effects.at(i)->enable_image) { + c->effects.at(i)->process_image(sequence_clip_time, c->comp_frame, current_frame->width, current_frame->height); + } + } + + c->texture->setData(0, QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, c->comp_frame); + c->texture_frame = clip_time; + + return true; + } else if (!no_frame) { + texture_failed = true; + qDebug() << "[ERROR] Failed to retrieve frame from cache (R:" << clip_time << "| A:" << c->cache_A.offset << "-" << c->cache_A.offset+c->cache_size-1 << "| B:" << c->cache_B.offset << "-" << c->cache_B.offset+c->cache_size-1 << "| WA:" << c->cache_A.written << "| WB:" << c->cache_B.written << ")"; } } return false; diff --git a/ui/viewerwidget.cpp b/ui/viewerwidget.cpp index 1d98e162c..57d409a9c 100644 --- a/ui/viewerwidget.cpp +++ b/ui/viewerwidget.cpp @@ -180,11 +180,9 @@ void ViewerWidget::compose_sequence(QVector& nests, bool render_audio) { coords.textureTopLeftY = coords.textureTopRightY = coords.textureTopLeftX = coords.textureBottomLeftX = 0; coords.textureBottomLeftY = coords.textureBottomRightY = coords.textureTopRightX = coords.textureBottomRightX = 1.0; - QOpenGLShaderProgram shader; - for (int j=0;jeffects.size();j++) { if (c->effects.at(j)->enable_opengl && c->effects.at(j)->is_enabled()) { - c->effects.at(j)->process_gl(((double)(panel_timeline->playhead-c->timeline_in+c->clip_in)/(double)sequence->frame_rate), shader, coords); + c->effects.at(j)->process_gl(((double)(panel_timeline->playhead-c->timeline_in+c->clip_in)/(double)sequence->frame_rate), coords); } } @@ -202,9 +200,6 @@ void ViewerWidget::compose_sequence(QVector& nests, bool render_audio) { } } - bool use_gl_shaders = shader.link(); - if (use_gl_shaders) shader.bind(); - c->texture->bind(); glBegin(GL_QUADS); @@ -218,9 +213,13 @@ void ViewerWidget::compose_sequence(QVector& nests, bool render_audio) { glVertex2f(coords.vertexBottomLeftX, coords.vertexBottomLeftY); // bottom left glEnd(); - c->texture->release(); + c->texture->release(); - if (use_gl_shaders) shader.release(); + for (int j=0;jeffects.size();j++) { + if (c->effects.at(j)->enable_opengl && c->effects.at(j)->is_enabled()) { + c->effects.at(j)->clean_gl(); + } + } } } else if (render_audio && c->stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&