From 56aee6aedeeed3efd10ada8fe3c229eddc01ef05 Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Thu, 13 Mar 2014 22:16:48 +0100 Subject: [PATCH] Integrate with the required MLT hooks for getting Movit to work. --- src/clipmanager.h | 1 + src/main.cpp | 2 ++ src/recmonitor.cpp | 1 + src/renderer.cpp | 74 +++++++++++++++++++++++++++++++++++++--------- src/renderer.h | 5 ++++ 5 files changed, 69 insertions(+), 14 deletions(-) diff --git a/src/clipmanager.h b/src/clipmanager.h index 172d0d52..0dba867f 100644 --- a/src/clipmanager.h +++ b/src/clipmanager.h @@ -126,6 +126,7 @@ Q_OBJECT public: /** @brief remove a clip id from the queue list. */ void stopThumbs(const QString &id); void projectTreeThumbReady(const QString &id, int frame, const QImage &img, int type); + QGLWidget *getMainContext() const { return m_mainGLContext; } #if KDE_IS_VERSION(4,5,0) KImageCache* pixmapCache; diff --git a/src/main.cpp b/src/main.cpp index 54dfd83d..d791a58f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -30,6 +30,8 @@ int main(int argc, char *argv[]) { + QCoreApplication::setAttribute(Qt::AA_X11InitThreads); + KAboutData aboutData(QByteArray("kdenlive"), QByteArray("kdenlive"), ki18n("Kdenlive"), VERSION, ki18n("An open source video editor."), diff --git a/src/recmonitor.cpp b/src/recmonitor.cpp index de9f07fa..956d3e6d 100644 --- a/src/recmonitor.cpp +++ b/src/recmonitor.cpp @@ -44,6 +44,7 @@ #include #include #include +#include RecMonitor::RecMonitor(Kdenlive::MonitorId name, MonitorManager *manager, QWidget *parent) : diff --git a/src/renderer.cpp b/src/renderer.cpp index d141a4f6..19067517 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -43,11 +43,13 @@ #include #include #include +#include #include #include #include +#include #define SEEK_INACTIVE (-1) @@ -81,6 +83,32 @@ void Render::consumer_frame_show(mlt_consumer, Render * self, mlt_frame frame_pt } } +void Render::consumer_thread_started(mlt_consumer, Render * self, mlt_frame) +{ + pthread_t thr = pthread_self(); + if (self->m_renderThreadGLContexts.count(thr) == 0) { + QGLWidget *ctx = new QGLWidget(0, self->m_mainGLContext); + ctx->resize(0, 0); + self->m_renderThreadGLContexts.insert(thr, ctx); + } + self->m_renderThreadGLContexts[thr]->makeCurrent(); + self->m_glslManager->fire_event("init glsl"); + if (!self->m_glslManager->get_int("glsl_supported")) { + QMessageBox::critical(NULL, i18n("Movit failed initialization"), + i18n("Initialization of OpenGL filters failed. Exiting.")); + qApp->quit(); + } +} + +void Render::consumer_thread_stopped(mlt_consumer, Render * self, mlt_frame) +{ + pthread_t thr = pthread_self(); + assert(self->m_renderThreadGLContexts.count(thr) != 0); + self->m_renderThreadGLContexts[thr]->makeCurrent(); + delete self->m_renderThreadGLContexts[thr]; + self->m_renderThreadGLContexts.remove(thr); +} + /* static void consumer_paused(mlt_consumer, Render * self, mlt_frame frame_ptr) { @@ -121,6 +149,8 @@ Render::Render(Kdenlive::MonitorId rendererName, int winid, QString profile, QWi m_mltProducer(NULL), m_mltProfile(NULL), m_showFrameEvent(NULL), + m_consumerThreadStartedEvent(NULL), + m_consumerThreadStoppedEvent(NULL), m_pauseEvent(NULL), m_isZoneMode(false), m_isLoopMode(false), @@ -166,6 +196,8 @@ void Render::closeMlt() m_requestList.clear(); m_infoThread.waitForFinished(); delete m_showFrameEvent; + delete m_consumerThreadStartedEvent; + delete m_consumerThreadStoppedEvent; delete m_pauseEvent; delete m_mltConsumer; delete m_mltProducer; @@ -292,7 +324,9 @@ void Render::buildConsumer(const QString &profileName) m_mltConsumer->set("scrub_audio", 1); m_mltConsumer->set("preview_off", 1); m_mltConsumer->set("audio_buffer", 512); - m_mltConsumer->set("preview_format", mlt_image_rgb24a); + m_mltConsumer->set("mlt_image_format", "glsl"); + m_consumerThreadStartedEvent = m_mltConsumer->listen("consumer-thread-started", this, (mlt_listener) consumer_thread_started); + m_consumerThreadStoppedEvent = m_mltConsumer->listen("consumer-thread-stopped", this, (mlt_listener) consumer_thread_stopped); } m_mltConsumer->set("buffer", "1"); m_showFrameEvent = m_mltConsumer->listen("consumer-frame-show", this, (mlt_listener) consumer_gl_frame_show); @@ -1260,6 +1294,10 @@ void Render::startConsumer() { KMessageBox::error(qApp->activeWindow(), i18n("Could not create the video preview window.\nThere is something wrong with your Kdenlive install or your driver settings, please fix it.")); if (m_showFrameEvent) delete m_showFrameEvent; m_showFrameEvent = NULL; + if (m_consumerThreadStartedEvent) delete m_consumerThreadStartedEvent; + m_consumerThreadStartedEvent = NULL; + if (m_consumerThreadStoppedEvent) delete m_consumerThreadStoppedEvent; + m_consumerThreadStoppedEvent = NULL; if (m_pauseEvent) delete m_pauseEvent; m_pauseEvent = NULL; delete m_mltConsumer; @@ -1825,12 +1863,12 @@ int Render::seekFramePosition() const void Render::emitFrameUpdated(Mlt::Frame& frame) { - mlt_image_format format = mlt_image_rgb24; + mlt_image_format format = mlt_image_rgb24a; int width = 0; int height = 0; const uchar* image = frame.get_image(format, width, height); - QImage qimage(width, height, QImage::Format_RGB888); //Format_ARGB32_Premultiplied); - memcpy(qimage.scanLine(0), image, width * height * 3); + QImage qimage(width, height, QImage::Format_ARGB32_Premultiplied); + memcpy(qimage.scanLine(0), image, width * height * 4); emit frameUpdated(qimage); } @@ -1908,18 +1946,26 @@ void Render::showFrame(Mlt::Frame* frame) if (currentPos == requestedSeekPosition) requestedSeekPosition = SEEK_INACTIVE; emit rendererPosition(currentPos); if (frame->is_valid()) { - mlt_image_format format = mlt_image_rgb24; + mlt_image_format format = mlt_image_glsl_texture; int width = 0; int height = 0; - const uchar* image = frame->get_image(format, width, height); - QImage qimage(width, height, QImage::Format_RGB888); //Format_ARGB32_Premultiplied); - memcpy(qimage.scanLine(0), image, width * height * 3); - if (analyseAudio) showAudio(*frame); - delete frame; - emit showImageSignal(qimage); - if (sendFrameForAnalysis) { - emit frameUpdated(qimage); - } + m_GLContext->makeCurrent(); + frame->set("movit.convert.use_texture", 1); + const uint8_t* image = frame->get_image(format, width, height); + const GLuint* texnum = (GLuint *)image; + if (format == mlt_image_glsl_texture) { + emit showImageSignal(*texnum); + delete frame; + } else { + QImage qimage(width, height, QImage::Format_ARGB32_Premultiplied); + memcpy(qimage.scanLine(0), image, width * height * 4); + if (analyseAudio) showAudio(*frame); + delete frame; + emit showImageSignal(qimage); + if (sendFrameForAnalysis) { + emit frameUpdated(qimage); + } + } } else delete frame; showFrameSemaphore.release(); emit checkSeeking(); diff --git a/src/renderer.h b/src/renderer.h index 96e23dce..43be7b8b 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -357,6 +357,8 @@ class Render: public AbstractRender protected: static void consumer_frame_show(mlt_consumer, Render * self, mlt_frame frame_ptr); static void consumer_gl_frame_show(mlt_consumer, Render * self, mlt_frame frame_ptr); + static void consumer_thread_started(mlt_consumer, Render * self, mlt_frame frame_ptr); + static void consumer_thread_stopped(mlt_consumer, Render * self, mlt_frame frame_ptr); private: @@ -369,6 +371,8 @@ private: Mlt::Producer * m_mltProducer; Mlt::Profile *m_mltProfile; Mlt::Event *m_showFrameEvent; + Mlt::Event *m_consumerThreadStartedEvent; + Mlt::Event *m_consumerThreadStoppedEvent; Mlt::Event *m_pauseEvent; double m_fps; @@ -402,6 +406,7 @@ private: bool m_isActive; QGLWidget *m_mainGLContext; QGLWidget *m_GLContext; + QMap m_renderThreadGLContexts; Mlt::Filter* m_glslManager; void closeMlt(); -- 2.39.2