aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-Baptiste Mardelle <[email protected]>2015-04-02 23:37:32 +0200
committerJean-Baptiste Mardelle <[email protected]>2015-04-02 23:37:32 +0200
commitc10357a3371d3b9c3121f3bd36227fb6472f0b52 (patch)
treeb8ff15c25763009c1e9fbaf7c2efd2adaff0fc09
parent5c964d699fd23fbf2a4e61712188083dfaa8fc26 (diff)
Porting monitor code to Shotcut's opengl/movit/qml, first step.
Code needs a lot of cleaning, but it kind of works :)
-rw-r--r--data/CMakeLists.txt1
-rw-r--r--data/kdenlivemonitor.qml50
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/bin/projectclip.cpp2
-rw-r--r--src/core.cpp2
-rw-r--r--src/core.h4
-rw-r--r--src/doc/kdenlivedoc.cpp1
-rw-r--r--src/doc/kthumb.cpp13
-rw-r--r--src/kdenlivesettings.kcfg5
-rw-r--r--src/mainwindow.cpp64
-rw-r--r--src/monitor/CMakeLists.txt3
-rw-r--r--src/monitor/abstractmonitor.cpp9
-rw-r--r--src/monitor/abstractmonitor.h2
-rw-r--r--src/monitor/glwidget.cpp852
-rw-r--r--src/monitor/glwidget.h194
-rw-r--r--src/monitor/monitor.cpp224
-rw-r--r--src/monitor/monitor.h21
-rw-r--r--src/monitor/monitormanager.cpp4
-rw-r--r--src/monitor/recmonitor.cpp4
-rw-r--r--src/monitor/videoglwidget.cpp3
-rw-r--r--src/renderer.cpp180
-rw-r--r--src/renderer.h10
-rw-r--r--src/stopmotion/stopmotion.cpp6
23 files changed, 1426 insertions, 230 deletions
diff --git a/data/CMakeLists.txt b/data/CMakeLists.txt
index 665ea72..8388120 100644
--- a/data/CMakeLists.txt
+++ b/data/CMakeLists.txt
@@ -18,6 +18,7 @@ install(FILES
timeline_vthumbs.png
kdenliveeffectscategory.rc
kdenlivetranscodingrc
+ kdenlivemonitor.qml
DESTINATION ${DATA_INSTALL_DIR}/kdenlive)
install(FILES kdenlive.notifyrc DESTINATION ${KNOTIFYRC_INSTALL_DIR})
install(FILES kdenlive_projectprofiles.knsrc kdenlive_renderprofiles.knsrc kdenlive_wipes.knsrc kdenlive_titles.knsrc DESTINATION ${CONFIG_INSTALL_DIR})
diff --git a/data/kdenlivemonitor.qml b/data/kdenlivemonitor.qml
new file mode 100644
index 0000000..617632a
--- /dev/null
+++ b/data/kdenlivemonitor.qml
@@ -0,0 +1,50 @@
+import QtQuick 2.0
+
+Item {
+ id: root
+
+ // default size, but scalable by user
+ height: 300; width: 400
+ property string comment
+ property string framenum
+ Rectangle {
+ anchors {
+ right: parent.right
+ //left: parent.left
+ bottom: parent.bottom
+ }
+ width: label.width + 10
+ height: label.height + 10
+ //height: root.height * 0.1
+ color: "#99ff0000"
+
+ Text {
+ id: label
+ objectName: "overlaytext"
+ anchors.centerIn: parent
+ text: root.framenum
+ }
+ }
+
+ Rectangle {
+ objectName: "marker"
+ anchors {
+ right: parent.right
+ top: parent.top
+ }
+ width: marker.width + 10
+ height: marker.height + 5
+ color: "#99ff0000"
+ border.color: "#33ff0000"
+ border.width: 3
+ radius: 5
+ visible: root.comment != ""
+ Text {
+ id: marker
+ objectName: "markertext"
+ anchors.centerIn: parent
+ color: "white"
+ text: root.comment
+ }
+ }
+}
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 92cc0df..bd578c9 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -244,7 +244,7 @@ target_link_libraries(kdenlive
kiss_fft
)
-qt5_use_modules( kdenlive Script Widgets Concurrent OpenGL)
+qt5_use_modules( kdenlive Script Widgets Concurrent Qml Quick)
if(Q_WS_X11)
include_directories(${X11_Xlib_INCLUDE_PATH})
diff --git a/src/bin/projectclip.cpp b/src/bin/projectclip.cpp
index 2bfa5af..e3a190a 100644
--- a/src/bin/projectclip.cpp
+++ b/src/bin/projectclip.cpp
@@ -209,7 +209,7 @@ void ProjectClip::reloadProducer(bool thumbnailOnly)
void ProjectClip::setCurrent(bool current, bool notify)
{
AbstractProjectItem::setCurrent(current, notify);
- if (current) {
+ if (current && m_controller) {
bin()->openProducer(m_controller);
}
}
diff --git a/src/core.cpp b/src/core.cpp
index f696c03..b7dd7e8 100644
--- a/src/core.cpp
+++ b/src/core.cpp
@@ -19,7 +19,6 @@ the Free Software Foundation, either version 3 of the License, or
#include <locale>
#include <QDebug>
-
Core *Core::m_self = NULL;
@@ -55,6 +54,7 @@ void Core::init()
emit coreIsReady();
}
+
Core* Core::self()
{
return m_self;
diff --git a/src/core.h b/src/core.h
index 4922231..ad389eb 100644
--- a/src/core.h
+++ b/src/core.h
@@ -56,7 +56,7 @@ public:
MonitorManager *monitorManager();
/** @brief Returns a pointer to the project bin controller. */
BinController *binController();
-
+
Bin *bin();
private:
@@ -72,7 +72,7 @@ private:
MonitorManager *m_monitorManager;
BinController *m_binController;
Bin *m_binWidget;
-
+
signals:
void coreIsReady();
};
diff --git a/src/doc/kdenlivedoc.cpp b/src/doc/kdenlivedoc.cpp
index d61e7b1..348668b 100644
--- a/src/doc/kdenlivedoc.cpp
+++ b/src/doc/kdenlivedoc.cpp
@@ -1095,6 +1095,7 @@ const QString KdenliveDoc::description() const
bool KdenliveDoc::addClip(QDomElement elem, const QString &clipId, bool createClipItem)
{
+ qDebug()<<"*** KDENLIVE DOC ADD CLIP CMD * * * *";
const QString producerId = clipId.section('_', 0, 0);
elem.setAttribute("id", producerId);
pCore->bin()->createClip(elem);
diff --git a/src/doc/kthumb.cpp b/src/doc/kthumb.cpp
index c55fe92..9480ccb 100644
--- a/src/doc/kthumb.cpp
+++ b/src/doc/kthumb.cpp
@@ -179,6 +179,12 @@ QImage KThumb::getProducerFrame(int framepos, int frameWidth, int displayWidth,
//static
QImage KThumb::getFrame(Mlt::Producer *producer, int framepos, int frameWidth, int displayWidth, int height)
{
+
+ QImage p1(displayWidth, height, QImage::Format_ARGB32_Premultiplied);
+ p1.fill(QColor(Qt::red).rgb());
+ return p1;
+
+
if (producer == NULL || !producer->is_valid()) {
QImage p(displayWidth, height, QImage::Format_ARGB32_Premultiplied);
p.fill(QColor(Qt::red).rgb());
@@ -207,11 +213,16 @@ QImage KThumb::getFrame(Mlt::Frame *frame, int frameWidth, int displayWidth, int
Q_UNUSED(frameWidth)
QImage p(displayWidth, height, QImage::Format_ARGB32_Premultiplied);
+ /*p.fill(QColor(Qt::red).rgb());
+ return p;*/
+
if (frame == NULL || !frame->is_valid()) {
p.fill(QColor(Qt::red).rgb());
return p;
}
-
+ frame->set("rescale.interp", "bilinear");
+ frame->set("deinterlace_method", "onefield");
+ frame->set("top_field_first", -1);
int ow = displayWidth;//frameWidth;
int oh = height;
mlt_image_format format = mlt_image_rgb24a;
diff --git a/src/kdenlivesettings.kcfg b/src/kdenlivesettings.kcfg
index 7160a52..2d64619 100644
--- a/src/kdenlivesettings.kcfg
+++ b/src/kdenlivesettings.kcfg
@@ -206,6 +206,11 @@
<label>Use OpenGL for video display.</label>
<default>false</default>
</entry>
+
+ <entry name="gpu_accel" type="Bool">
+ <label>Use Movit for GPU accelerated display and effects.</label>
+ <default>false</default>
+ </entry>
<entry name="video_driver" type="UInt">
<label>Video driver used for output.</label>
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 210cda3..8d18f97 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -186,13 +186,14 @@ MainWindow::MainWindow(const QString &MltPath, const QUrl &Url, const QString &
m_projectMonitor = new Monitor(Kdenlive::ProjectMonitor, pCore->monitorManager(), this);
-#ifndef Q_WS_MAC
+/*
+ //TODO disabled until ported to qml
m_recMonitor = new RecMonitor(Kdenlive::RecordMonitor, pCore->monitorManager(), this);
connect(m_recMonitor, SIGNAL(addProjectClip(QUrl)), this, SLOT(slotAddProjectClip(QUrl)));
connect(m_recMonitor, SIGNAL(addProjectClipList(QList<QUrl>)), this, SLOT(slotAddProjectClipList(QList<QUrl>)));
connect(m_recMonitor, SIGNAL(showConfigDialog(int,int)), this, SLOT(slotPreferences(int,int)));
-#endif /* ! Q_WS_MAC */
+*/
pCore->monitorManager()->initMonitors(m_clipMonitor, m_projectMonitor, m_recMonitor);
m_effectStack = new EffectStackView2(m_projectMonitor);
@@ -208,9 +209,9 @@ MainWindow::MainWindow(const QString &MltPath, const QUrl &Url, const QString &
// Add monitors here to keep them at the right of the window
m_clipMonitorDock = addDock(i18n("Clip Monitor"), "clip_monitor", m_clipMonitor);
m_projectMonitorDock = addDock(i18n("Project Monitor"), "project_monitor", m_projectMonitor);
-#ifndef Q_WS_MAC
- m_recMonitorDock = addDock(i18n("Record Monitor"), "record_monitor", m_recMonitor);
-#endif
+ if (m_recMonitor) {
+ m_recMonitorDock = addDock(i18n("Record Monitor"), "record_monitor", m_recMonitor);
+ }
m_undoView = new QUndoView();
m_undoView->setCleanIcon(QIcon::fromTheme("edit-clear"));
@@ -234,9 +235,9 @@ MainWindow::MainWindow(const QString &MltPath, const QUrl &Url, const QString &
tabifyDockWidget(m_effectListDock, m_transitionConfigDock);
tabifyDockWidget(m_clipMonitorDock, m_projectMonitorDock);
-#ifndef Q_WS_MAC
- tabifyDockWidget(m_clipMonitorDock, m_recMonitorDock);
-#endif
+ if (m_recMonitor) {
+ tabifyDockWidget(m_clipMonitorDock, m_recMonitorDock);
+ }
setCentralWidget(m_timelineArea);
readOptions();
@@ -342,8 +343,8 @@ MainWindow::MainWindow(const QString &MltPath, const QUrl &Url, const QString &
m_timelineContextTransitionMenu->addAction(actionCollection()->action("auto_transition"));
- connect(m_projectMonitorDock, SIGNAL(visibilityChanged(bool)), m_projectMonitor, SLOT(refreshMonitor(bool)));
- connect(m_clipMonitorDock, SIGNAL(visibilityChanged(bool)), m_clipMonitor, SLOT(refreshMonitor(bool)));
+ //connect(m_projectMonitorDock, SIGNAL(visibilityChanged(bool)), m_projectMonitor, SLOT(refreshMonitor(bool)));
+ //connect(m_clipMonitorDock, SIGNAL(visibilityChanged(bool)), m_clipMonitor, SLOT(refreshMonitor(bool)));
connect(m_effectList, SIGNAL(addEffect(QDomElement)), this, SLOT(slotAddEffect(QDomElement)));
connect(m_effectList, SIGNAL(reloadEffects()), this, SLOT(slotReloadEffects()));
@@ -351,8 +352,8 @@ MainWindow::MainWindow(const QString &MltPath, const QUrl &Url, const QString &
m_projectBinDock->raise();
- actionCollection()->addAssociatedWidget(m_clipMonitor->container());
- actionCollection()->addAssociatedWidget(m_projectMonitor->container());
+ /*actionCollection()->addAssociatedWidget(m_clipMonitor->container());
+ actionCollection()->addAssociatedWidget(m_projectMonitor->container());*/
QList<QPair<QString, QAction *> > viewActions;
QPair <QString, QAction *> pair;
@@ -442,7 +443,7 @@ MainWindow::MainWindow(const QString &MltPath, const QUrl &Url, const QString &
#ifdef USE_JOGSHUTTLE
new JogManager(this);
#endif
- KMessageBox::information(this, "Warning, development version for testing only. we are currently working on core functionnalities,\ndo not save any project or your project files might be corrupted.");
+ //KMessageBox::information(this, "Warning, development version for testing only. we are currently working on core functionnalities,\ndo not save any project or your project files might be corrupted.");
}
MainWindow::~MainWindow()
@@ -1285,9 +1286,9 @@ void MainWindow::slotEditProjectSettings()
if (w->exec() == QDialog::Accepted) {
QString profile = w->selectedProfile();
project->setProjectFolder(w->selectedFolder());
-#ifndef Q_WS_MAC
- m_recMonitor->slotUpdateCaptureFolder(project->projectFolder().path() + QDir::separator());
-#endif
+ if (m_recMonitor) {
+ m_recMonitor->slotUpdateCaptureFolder(project->projectFolder().path() + QDir::separator());
+ }
if (m_renderWidget) {
m_renderWidget->setDocumentPath(project->projectFolder().path() + QDir::separator());
}
@@ -1571,15 +1572,15 @@ void MainWindow::connectDocument()
pCore->monitorManager()->setDocument(project);
trackView->updateProjectFps();
project->checkProjectClips();
-#ifndef Q_WS_MAC
- m_recMonitor->slotUpdateCaptureFolder(project->projectFolder().path() + QDir::separator());
-#endif
+ if (m_recMonitor) {
+ m_recMonitor->slotUpdateCaptureFolder(project->projectFolder().path() + QDir::separator());
+ }
//Update the mouse position display so it will display in DF/NDF format by default based on the project setting.
slotUpdateMousePosition(0);
// Make sure monitor is visible so that it is painted black on startup
- show();
- pCore->monitorManager()->activateMonitor(Kdenlive::ClipMonitor, true);
+ //show();
+ //pCore->monitorManager()->activateMonitor(Kdenlive::ClipMonitor, true);
// set tool to select tool
m_buttonSelectTool->setChecked(true);
}
@@ -1636,10 +1637,10 @@ void MainWindow::slotPreferences(int page, int option)
connect(dialog, SIGNAL(settingsChanged(QString)), this, SLOT(updateConfiguration()));
connect(dialog, SIGNAL(settingsChanged(QString)), SIGNAL(configurationChanged()));
connect(dialog, SIGNAL(doResetProfile()), pCore->monitorManager(), SLOT(slotResetProfiles()));
-#ifndef Q_WS_MAC
- connect(dialog, SIGNAL(updateCaptureFolder()), this, SLOT(slotUpdateCaptureFolder()));
- connect(dialog, SIGNAL(updateFullScreenGrab()), m_recMonitor, SLOT(slotUpdateFullScreenGrab()));
-#endif
+ if (m_recMonitor) {
+ connect(dialog, SIGNAL(updateCaptureFolder()), this, SLOT(slotUpdateCaptureFolder()));
+ connect(dialog, SIGNAL(updateFullScreenGrab()), m_recMonitor, SLOT(slotUpdateFullScreenGrab()));
+ }
dialog->show();
if (page != -1) {
dialog->showPage(page, option);
@@ -1648,13 +1649,12 @@ void MainWindow::slotPreferences(int page, int option)
void MainWindow::slotUpdateCaptureFolder()
{
-
-#ifndef Q_WS_MAC
- if (pCore->projectManager()->current())
- m_recMonitor->slotUpdateCaptureFolder(pCore->projectManager()->current()->projectFolder().path() + QDir::separator());
- else
- m_recMonitor->slotUpdateCaptureFolder(KdenliveSettings::defaultprojectfolder());
-#endif
+ if (m_recMonitor) {
+ if (pCore->projectManager()->current())
+ m_recMonitor->slotUpdateCaptureFolder(pCore->projectManager()->current()->projectFolder().path() + QDir::separator());
+ else
+ m_recMonitor->slotUpdateCaptureFolder(KdenliveSettings::defaultprojectfolder());
+ }
}
void MainWindow::updateConfiguration()
diff --git a/src/monitor/CMakeLists.txt b/src/monitor/CMakeLists.txt
index afe73b2..abe0de8 100644
--- a/src/monitor/CMakeLists.txt
+++ b/src/monitor/CMakeLists.txt
@@ -1,5 +1,6 @@
set(kdenlive_SRCS
${kdenlive_SRCS}
+ monitor/glwidget.cpp
monitor/abstractmonitor.cpp
monitor/monitor.cpp
monitor/monitoreditwidget.cpp
@@ -9,5 +10,5 @@ set(kdenlive_SRCS
monitor/smallruler.cpp
monitor/twostateaction.cpp
monitor/videosurface.cpp
+ monitor/sharedframe.cpp
PARENT_SCOPE)
-
diff --git a/src/monitor/abstractmonitor.cpp b/src/monitor/abstractmonitor.cpp
index e42da85..62d3cad 100644
--- a/src/monitor/abstractmonitor.cpp
+++ b/src/monitor/abstractmonitor.cpp
@@ -20,6 +20,7 @@
#include "abstractmonitor.h"
#include "monitormanager.h"
+#include "glwidget.h"
#include "kdenlivesettings.h"
@@ -35,22 +36,22 @@ AbstractMonitor::AbstractMonitor(Kdenlive::MonitorId id, MonitorManager *manager
m_id(id),
m_monitorManager(manager)
{
- videoBox = new VideoContainer(this);
+ //videoBox = new VideoContainer(this);
}
AbstractMonitor::~AbstractMonitor()
{
- delete videoSurface;
+ //delete videoSurface;
}
void AbstractMonitor::createVideoSurface()
{
- QVBoxLayout *lay = new QVBoxLayout;
+ /*QVBoxLayout *lay = new QVBoxLayout;
lay->setContentsMargins(0, 0, 0, 0);
videoSurface = new VideoSurface;
lay->addWidget(videoSurface);
- videoBox->setLayout(lay);
+ videoBox->setLayout(lay);*/
}
bool AbstractMonitor::isActive() const
diff --git a/src/monitor/abstractmonitor.h b/src/monitor/abstractmonitor.h
index 2aa30e1..85424c1 100644
--- a/src/monitor/abstractmonitor.h
+++ b/src/monitor/abstractmonitor.h
@@ -33,7 +33,7 @@
class MonitorManager;
class VideoContainer;
-class VideoSurface;
+class GLWidget;
class AbstractRender: public QObject
{
diff --git a/src/monitor/glwidget.cpp b/src/monitor/glwidget.cpp
new file mode 100644
index 0000000..c611a89
--- /dev/null
+++ b/src/monitor/glwidget.cpp
@@ -0,0 +1,852 @@
+/*
+ * Copyright (c) 2011-2014 Meltytech, LLC
+ * Author: Dan Dennedy <[email protected]>
+ *
+ * GL shader based on BSD licensed code from Peter Bengtsson:
+ * http://www.fourcc.org/source/YUV420P-OpenGL-GLSLang.c
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <QtWidgets>
+#include <QOpenGLFunctions_3_2_Core>
+#include <QUrl>
+#include <QOffscreenSurface>
+#include <QtQml>
+
+#include <mlt++/Mlt.h>
+#include "glwidget.h"
+#include "core.h"
+#include "kdenlivesettings.h"
+#include "mltcontroller/bincontroller.h"
+//#include "qmltypes/qmlutilities.h"
+//#include "qmltypes/qmlfilter.h"
+//#include "mainwindow.h"
+
+#define USE_GL_SYNC // Use glFinish() if not defined.
+
+#define check_error() { int err = glGetError(); if (err != GL_NO_ERROR) { qCritical() << "GL error" << hex << err << dec << "at" << __FILE__ << ":" << __LINE__; } }
+
+#ifndef GL_TIMEOUT_IGNORED
+#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull
+#endif
+
+#ifndef Q_OS_WIN
+typedef GLenum (*ClientWaitSync_fp) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+static ClientWaitSync_fp ClientWaitSync = 0;
+#endif
+
+using namespace Mlt;
+
+GLWidget::GLWidget(bool accel, QObject *parent)
+ : QQuickView((QWindow*) parent)
+ , m_shader(0)
+ , m_glslManager(0)
+ , m_initSem(0)
+ , m_isInitialized(false)
+ , m_threadStartEvent(0)
+ , m_threadStopEvent(0)
+ , m_threadCreateEvent(0)
+ , m_threadJoinEvent(0)
+ , m_frameRenderer(0)
+ , m_zoom(0.0f)
+ , m_offset(QPoint(0, 0))
+ , m_consumer(0)
+ , m_producer(0)
+{
+ qDebug() << "begin";
+ m_texture[0] = m_texture[1] = m_texture[2] = 0;
+ qRegisterMetaType<Mlt::Frame>("Mlt::Frame");
+ qRegisterMetaType<SharedFrame>("SharedFrame");
+
+ setPersistentOpenGLContext(true);
+ setPersistentSceneGraph(true);
+ setClearBeforeRendering(false);
+ setResizeMode(QQuickView::SizeRootObjectToView);
+
+ //rootContext->setContextProperty("settings", &ShotcutSettings::singleton());
+ /*rootContext()->setContextProperty("application", &QmlApplication::singleton());
+ rootContext()->setContextProperty("profile", &QmlProfile::singleton());
+ rootContext()->setContextProperty("view", new QmlView(this));*/
+
+/* QDir importPath = QmlUtilities::qmlDir();
+ importPath.cd("modules");
+ engine()->addImportPath(importPath.path());
+ QmlUtilities::setCommonProperties((QQuickView*)this);*/
+
+ if (KdenliveSettings::gpu_accel())
+ m_glslManager = new Mlt::Filter(*pCore->binController()->profile(), "glsl.manager");
+ if ((m_glslManager && !m_glslManager->is_valid())) {
+ delete m_glslManager;
+ m_glslManager = 0;
+ }
+
+ connect(this, SIGNAL(sceneGraphInitialized()), SLOT(initializeGL()), Qt::DirectConnection);
+ connect(this, SIGNAL(sceneGraphInitialized()), SLOT(setBlankScene()), Qt::QueuedConnection);
+ connect(this, SIGNAL(beforeRendering()), SLOT(paintGL()), Qt::DirectConnection);
+ qDebug() << "end";
+}
+
+GLWidget::~GLWidget()
+{
+ qDebug();
+ //stop();
+ delete m_glslManager;
+ delete m_threadStartEvent;
+ delete m_threadStopEvent;
+ delete m_threadCreateEvent;
+ delete m_threadJoinEvent;
+ if (m_frameRenderer && m_frameRenderer->isRunning()) {
+ QMetaObject::invokeMethod(m_frameRenderer, "cleanup");
+ m_frameRenderer->quit();
+ m_frameRenderer->wait();
+ m_frameRenderer->deleteLater();
+ }
+ delete m_shader;
+}
+
+void GLWidget::initializeGL()
+{
+ qDebug() << "begin";
+ if (m_isInitialized) return;
+
+ initializeOpenGLFunctions();
+ openglContext()->blockSignals(true);
+ /*openglContext()->doneCurrent();
+ openglContext()->setShareContext(pCore->glShareWidget()->context());
+ openglContext()->setFormat(requestedFormat());
+ openglContext()->create();
+ openglContext()->makeCurrent(this);*/
+ createShader();
+
+#if defined(USE_GL_SYNC) && !defined(Q_OS_WIN)
+ // getProcAddress is not working for me on Windows.
+ if (KdenliveSettings::gpu_accel()) {
+ if (m_glslManager && openglContext()->hasExtension("GL_ARB_sync")) {
+ ClientWaitSync = (ClientWaitSync_fp) openglContext()->getProcAddress("glClientWaitSync");
+ }
+ if (!ClientWaitSync) {
+ emit gpuNotSupported();
+ delete m_glslManager;
+ m_glslManager = 0;
+ }
+ }
+#endif
+
+ openglContext()->doneCurrent();
+ m_frameRenderer = new FrameRenderer(openglContext());
+ openglContext()->makeCurrent(this);//openglContext()->surface());
+ openglContext()->blockSignals(false);
+ connect(m_frameRenderer, SIGNAL(frameDisplayed(const SharedFrame&)), this, SIGNAL(frameDisplayed(const SharedFrame&)), Qt::QueuedConnection);
+ connect(m_frameRenderer, SIGNAL(textureReady(GLuint,GLuint,GLuint)), SLOT(updateTexture(GLuint,GLuint,GLuint)), Qt::DirectConnection);
+ connect(this, SIGNAL(textureUpdated()), SLOT(update()), Qt::QueuedConnection);
+
+ m_initSem.release();
+ m_isInitialized = true;
+ qDebug() << "end";
+}
+
+void GLWidget::setBlankScene()
+{
+ //setSource(QmlUtilities::blankVui());
+}
+
+void GLWidget::resizeGL(int width, int height)
+{
+ int x, y, w, h;
+ double this_aspect = (double) width / height;
+ double video_aspect = pCore->binController()->profile()->dar();
+
+ // Special case optimisation to negate odd effect of sample aspect ratio
+ // not corresponding exactly with image resolution.
+ if ((int) (this_aspect * 1000) == (int) (video_aspect * 1000))
+ {
+ w = width;
+ h = height;
+ }
+ // Use OpenGL to normalise sample aspect ratio
+ else if (height * video_aspect > width)
+ {
+ w = width;
+ h = width / video_aspect;
+ }
+ else
+ {
+ w = height * video_aspect;
+ h = height;
+ }
+ x = (width - w) / 2;
+ y = (height - h) / 2;
+ m_rect.setRect(x, y, w, h);
+ emit rectChanged();
+}
+
+void GLWidget::resizeEvent(QResizeEvent* event)
+{
+ QQuickView::resizeEvent(event);
+ resizeGL(event->size().width(), event->size().height());
+}
+
+void GLWidget::createShader()
+{
+ m_shader = new QOpenGLShaderProgram;
+ m_shader->addShaderFromSourceCode(QOpenGLShader::Vertex,
+ "uniform mat4 projection;"
+ "uniform mat4 modelView;"
+ "attribute vec4 vertex;"
+ "attribute vec2 texCoord;"
+ "varying vec2 coordinates;"
+ "void main(void) {"
+ " gl_Position = projection * modelView * vertex;"
+ " coordinates = texCoord;"
+ "}");
+ if (m_glslManager) {
+ m_shader->addShaderFromSourceCode(QOpenGLShader::Fragment,
+ "uniform sampler2D tex;"
+ "varying vec2 coordinates;"
+ "void main(void) {"
+ " gl_FragColor = texture2D(tex, coordinates);"
+ "}");
+ m_shader->link();
+ m_textureLocation[0] = m_shader->uniformLocation("tex");
+ } else {
+ m_shader->addShaderFromSourceCode(QOpenGLShader::Fragment,
+ "uniform sampler2D Ytex, Utex, Vtex;"
+ "uniform int colorspace;"
+ "varying vec2 coordinates;"
+ "void main(void) {"
+ " vec3 texel;"
+ " texel.r = texture2D(Ytex, coordinates).r - 0.0625;" // Y
+ " texel.g = texture2D(Utex, coordinates).r - 0.5;" // U
+ " texel.b = texture2D(Vtex, coordinates).r - 0.5;" // V
+ " mat3 coefficients;"
+ " if (colorspace == 601) {"
+ " coefficients = mat3("
+ " 1.1643, 1.1643, 1.1643," // column 1
+ " 0.0, -0.39173, 2.017," // column 2
+ " 1.5958, -0.8129, 0.0);" // column 3
+ " } else {" // ITU-R 709
+ " coefficients = mat3("
+ " 1.1643, 1.1643, 1.1643," // column 1
+ " 0.0, -0.213, 2.112," // column 2
+ " 1.793, -0.533, 0.0);" // column 3
+ " }"
+ " gl_FragColor = vec4(coefficients * texel, 1.0);"
+ "}");
+ m_shader->link();
+ m_textureLocation[0] = m_shader->uniformLocation("Ytex");
+ m_textureLocation[1] = m_shader->uniformLocation("Utex");
+ m_textureLocation[2] = m_shader->uniformLocation("Vtex");
+ m_colorspaceLocation = m_shader->uniformLocation("colorspace");
+ }
+ m_projectionLocation = m_shader->uniformLocation("projection");
+ m_modelViewLocation = m_shader->uniformLocation("modelView");
+ m_vertexLocation = m_shader->attributeLocation("vertex");
+ m_texCoordLocation = m_shader->attributeLocation("texCoord");
+}
+
+void GLWidget::paintGL()
+{
+ int width = this->width() * devicePixelRatio();
+ int height = this->height() * devicePixelRatio();
+
+ glDisable(GL_BLEND);
+ glDisable(GL_DEPTH_TEST);
+ glDepthMask(GL_FALSE);
+ glViewport(0, 0, width, height);
+ check_error();
+ QColor color = QPalette().color(QPalette::Window);
+ glClearColor(color.redF(), color.greenF(), color.blueF(), color.alphaF());
+ glClear(GL_COLOR_BUFFER_BIT);
+ check_error();
+
+ if (!m_texture[0]) return;
+
+ // Bind textures.
+ for (int i = 0; i < 3; ++i) {
+ if (m_texture[i]) {
+ glActiveTexture(GL_TEXTURE0 + i);
+ glBindTexture(GL_TEXTURE_2D, m_texture[i]);
+ check_error();
+ }
+ }
+
+ // Init shader program.
+ m_shader->bind();
+ if (m_glslManager) {
+ m_shader->setUniformValue(m_textureLocation[0], 0);
+ } else {
+ m_shader->setUniformValue(m_textureLocation[0], 0);
+ m_shader->setUniformValue(m_textureLocation[1], 1);
+ m_shader->setUniformValue(m_textureLocation[2], 2);
+ //TODO:
+ //m_shader->setUniformValue(m_colorspaceLocation, MLT.profile().colorspace());
+ }
+ check_error();
+
+ // Setup an orthographic projection.
+ QMatrix4x4 projection;
+ projection.scale(2.0f / width, 2.0f / height);
+ m_shader->setUniformValue(m_projectionLocation, projection);
+ check_error();
+
+ // Set model view.
+ QMatrix4x4 modelView;
+ if (m_zoom > 0.0) {
+ if (offset().x() || offset().y())
+ modelView.translate(-offset().x() * devicePixelRatio(),
+ offset().y() * devicePixelRatio());
+ modelView.scale(zoom(), zoom());
+ }
+ m_shader->setUniformValue(m_modelViewLocation, modelView);
+ check_error();
+
+ // Provide vertices of triangle strip.
+ QVector<QVector2D> vertices;
+ width = m_rect.width() * devicePixelRatio();
+ height = m_rect.height() * devicePixelRatio();
+ vertices << QVector2D(float(-width)/2.0f, float(-height)/2.0f);
+ vertices << QVector2D(float(-width)/2.0f, float( height)/2.0f);
+ vertices << QVector2D(float( width)/2.0f, float(-height)/2.0f);
+ vertices << QVector2D(float( width)/2.0f, float( height)/2.0f);
+ m_shader->enableAttributeArray(m_vertexLocation);
+ check_error();
+ m_shader->setAttributeArray(m_vertexLocation, vertices.constData());
+ check_error();
+
+ // Provide texture coordinates.
+ QVector<QVector2D> texCoord;
+ texCoord << QVector2D(0.0f, 1.0f);
+ texCoord << QVector2D(0.0f, 0.0f);
+ texCoord << QVector2D(1.0f, 1.0f);
+ texCoord << QVector2D(1.0f, 0.0f);
+ m_shader->enableAttributeArray(m_texCoordLocation);
+ check_error();
+ m_shader->setAttributeArray(m_texCoordLocation, texCoord.constData());
+ check_error();
+
+ // Render
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, vertices.size());
+ check_error();
+
+ // Cleanup
+ m_shader->disableAttributeArray(m_vertexLocation);
+ m_shader->disableAttributeArray(m_texCoordLocation);
+ m_shader->release();
+ for (int i = 0; i < 3; ++i) {
+ if (m_texture[i]) {
+ glActiveTexture(GL_TEXTURE0 + i);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ check_error();
+ }
+ }
+ glActiveTexture(GL_TEXTURE0);
+ check_error();
+}
+
+void GLWidget::wheelEvent(QWheelEvent * event)
+{
+ emit mouseSeek(event->delta(), event->modifiers() == Qt::ControlModifier);
+ event->accept();
+}
+
+
+void GLWidget::mousePressEvent(QMouseEvent* event)
+{
+ QQuickView::mousePressEvent(event);
+ if (event->isAccepted()) return;
+ if (event->button() == Qt::LeftButton)
+ m_dragStart = event->pos();
+}
+
+void GLWidget::mouseMoveEvent(QMouseEvent* event)
+{
+ QQuickView::mouseMoveEvent(event);
+ if (event->isAccepted()) return;
+/* if (event->modifiers() == Qt::ShiftModifier && m_producer) {
+ emit seekTo(m_producer->get_length() * event->x() / width());
+ return;
+ }*/
+ if (!(event->buttons() & Qt::LeftButton))
+ return;
+ if (m_dragStart == QPoint() || (event->pos() - m_dragStart).manhattanLength() < QApplication::startDragDistance())
+ return;
+ emit startDrag();
+}
+
+void GLWidget::keyPressEvent(QKeyEvent* event)
+{
+ event->ignore();
+ return;
+ QQuickView::keyPressEvent(event);
+ if (event->isAccepted()) return;
+ //MAIN.keyPressEvent(event);
+}
+
+void GLWidget::createThread(RenderThread **thread, thread_function_t function, void *data)
+{
+#ifdef Q_OS_WIN
+ // On Windows, MLT event consumer-thread-create is fired from the Qt main thread.
+ while (!m_isInitialized)
+ qApp->processEvents();
+#else
+ if (!m_isInitialized) {
+ m_initSem.acquire();
+ }
+#endif
+ (*thread) = new RenderThread(function, data, m_glslManager? openglContext() : 0);
+ (*thread)->start();
+}
+
+static void onThreadCreate(mlt_properties owner, GLWidget* self,
+ RenderThread** thread, int* priority, thread_function_t function, void* data )
+{
+ Q_UNUSED(owner)
+ Q_UNUSED(priority)
+ self->createThread(thread, function, data);
+}
+
+static void onThreadJoin(mlt_properties owner, GLWidget* self, RenderThread* thread)
+{
+ Q_UNUSED(owner)
+ Q_UNUSED(self)
+ if (thread) {
+ thread->quit();
+ thread->wait();
+ delete thread;
+ }
+}
+
+void GLWidget::startGlsl()
+{
+ if (m_glslManager) {
+ qDebug()<<"++++++++++++++++++++++ STARTING GLSL +++++++++++++++++++++++++++++";
+ m_glslManager->fire_event("init glsl");
+ if (!m_glslManager->get_int("glsl_supported")) {
+ delete m_glslManager;
+ m_glslManager = 0;
+ // Need to destroy MLT global reference to prevent filters from trying to use GPU.
+ mlt_properties_set_data(mlt_global_properties(), "glslManager", NULL, 0, NULL, NULL);
+ emit gpuNotSupported();
+ }
+ else {
+ emit started();
+ }
+ }
+}
+
+static void onThreadStarted(mlt_properties owner, GLWidget* self)
+{
+ Q_UNUSED(owner)
+ self->startGlsl();
+}
+
+void GLWidget::stopGlsl()
+{
+ qDebug()<<"++++++++++++++++++++++ STOPPING GLSL +++++++++++++++++++++++++++++";
+ m_glslManager->fire_event("close glsl");
+ m_texture[0] = 0;
+}
+
+static void onThreadStopped(mlt_properties owner, GLWidget* self)
+{
+ Q_UNUSED(owner)
+ self->stopGlsl();
+}
+
+int GLWidget::setProducer(Mlt::Producer* producer, bool isMulti)
+{
+ int error = 0;//Controller::setProducer(producer, isMulti);
+ qDebug()<<"****************\nSET PRODUCER\n-----------------------";
+ m_producer = producer;
+ if (!error && producer) {
+ error = reconfigure(isMulti);
+ if (!error) {
+ // The profile display aspect ratio may have changed.
+ resizeGL(width(), height());
+ }
+ }
+ return error;
+}
+
+int GLWidget::reconfigure(bool isMulti)
+{
+ int error = 0;
+ // use SDL for audio, OpenGL for video
+ QString serviceName = property("mlt_service").toString();
+ if (!m_consumer || !m_consumer->is_valid()) {
+ if (serviceName.isEmpty()) {
+ m_consumer = new Mlt::FilteredConsumer(*pCore->binController()->profile(), "sdl_audio");
+ if (m_consumer->is_valid())
+ serviceName = "sdl_audio";
+ else
+ serviceName = "rtaudio";
+ delete m_consumer;
+ }
+ if (isMulti)
+ m_consumer = new Mlt::FilteredConsumer(*pCore->binController()->profile(), "multi");
+ else
+ m_consumer = new Mlt::FilteredConsumer(*pCore->binController()->profile(), serviceName.toLatin1().constData());
+
+ delete m_threadStartEvent;
+ m_threadStartEvent = 0;
+ delete m_threadStopEvent;
+ m_threadStopEvent = 0;
+
+ delete m_threadCreateEvent;
+ m_threadCreateEvent = m_consumer->listen("consumer-thread-create", this, (mlt_listener) onThreadCreate);
+ delete m_threadJoinEvent;
+ m_threadJoinEvent = m_consumer->listen("consumer-thread-join", this, (mlt_listener) onThreadJoin);
+ }
+ if (m_consumer->is_valid()) {
+ m_consumer->stop();
+ // Connect the producer to the consumer - tell it to "run" later
+ m_consumer->connect(*m_producer);
+ // Make an event handler for when a frame's image should be displayed
+ m_consumer->listen("consumer-frame-show", this, (mlt_listener) on_frame_show);
+ //m_consumer->set("real_time", MLT.realTime());
+ m_consumer->set("mlt_image_format", "yuv422");
+ //TODO:
+ //m_consumer->set("color_trc", Settings.playerGamma().toLatin1().constData());
+
+ if (isMulti) {
+ m_consumer->set("terminate_on_pause", 0);
+ m_consumer->set("0", serviceName.toLatin1().constData());
+ if (serviceName == "sdl_audio")
+#ifdef Q_OS_WIN
+ m_consumer->set("0.audio_buffer", 2048);
+#else
+ m_consumer->set("0.audio_buffer", 512);
+#endif
+ /*if (!m_consumer->profile()->progressive())
+ m_consumer->set("0.progressive", property("progressive").toBool());*/
+
+ m_consumer->set("0.deinterlace_method", KdenliveSettings::mltdeinterlacer().toUtf8().constData());
+ m_consumer->set("0.rescale", KdenliveSettings::mltinterpolation().toUtf8().constData());
+ m_consumer->set("0.buffer", 25);
+ m_consumer->set("0.prefill", 1);
+ if (property("keyer").isValid())
+ m_consumer->set("0.keyer", property("keyer").toInt());
+ }
+ else {
+ if (serviceName == "sdl_audio")
+#ifdef Q_OS_WIN
+ m_consumer->set("audio_buffer", 2048);
+#else
+ m_consumer->set("audio_buffer", 512);
+#endif
+ /*if (!m_consumer->profile()->progressive())
+ m_consumer->set("progressive", property("progressive").toBool());*/
+ m_consumer->set("deinterlace_method", KdenliveSettings::mltdeinterlacer().toUtf8().constData());
+ m_consumer->set("rescale", KdenliveSettings::mltinterpolation().toUtf8().constData());
+ m_consumer->set("buffer", 25);
+ m_consumer->set("prefill", 1);
+ m_consumer->set("scrub_audio", 1);
+ if (property("keyer").isValid())
+ m_consumer->set("keyer", property("keyer").toInt());
+ }
+ if (m_glslManager) {
+ if (!m_threadStartEvent)
+ m_threadStartEvent = m_consumer->listen("consumer-thread-started", this, (mlt_listener) onThreadStarted);
+ /*if (!m_threadStopEvent)
+ m_threadStopEvent = m_consumer->listen("consumer-thread-stopped", this, (mlt_listener) onThreadStopped);*/
+ if (!serviceName.startsWith("decklink") && !isMulti)
+ m_consumer->set("mlt_image_format", "glsl");
+ } else {
+ emit started();
+ }
+ }
+ else {
+ // Cleanup on error
+ error = 2;
+ //Controller::closeConsumer();
+ //Controller::close();
+ }
+ return error;
+}
+
+QPoint GLWidget::offset() const
+{
+ return QPoint(m_offset.x() - (m_consumer->profile()->width() * m_zoom - width()) / 2,
+ m_offset.y() - (m_consumer->profile()->height() * m_zoom - height()) / 2);
+}
+
+void GLWidget::setZoom(float zoom)
+{
+ m_zoom = zoom;
+ emit zoomChanged();
+ update();
+}
+
+void GLWidget::mouseReleaseEvent(QMouseEvent * event)
+{
+ m_dragStart = QPoint();
+ if (event->button() != Qt::RightButton) {
+ emit monitorPlay();
+ }
+}
+
+void GLWidget::mouseDoubleClickEvent(QMouseEvent * event)
+{
+ emit switchFullScreen();
+ event->accept();
+}
+
+void GLWidget::setOffsetX(int x)
+{
+ m_offset.setX(x);
+ emit offsetChanged();
+ update();
+}
+
+void GLWidget::setOffsetY(int y)
+{
+ m_offset.setY(y);
+ emit offsetChanged();
+ update();
+}
+
+/*void GLWidget::setCurrentFilter(QmlFilter* filter, QmlMetadata* meta)
+{
+ rootContext()->setContextProperty("filter", filter);
+ if (meta && QFile::exists(meta->vuiFilePath().toLocalFile())) {
+ setSource(meta->vuiFilePath());
+ } else {
+ setBlankScene();
+ }
+}*/
+
+Mlt::Consumer *GLWidget::consumer()
+{
+ return m_consumer;
+}
+
+void GLWidget::updateTexture(GLuint yName, GLuint uName, GLuint vName)
+{
+ m_texture[0] = yName;
+ m_texture[1] = uName;
+ m_texture[2] = vName;
+ emit textureUpdated();
+}
+
+// MLT consumer-frame-show event handler
+void GLWidget::on_frame_show(mlt_consumer, void* self, mlt_frame frame_ptr)
+{
+ GLWidget* widget = static_cast<GLWidget*>(self);
+ int timeout = (widget->consumer()->get_int("real_time") > 0)? 0: 1000;
+ if (widget->m_frameRenderer && widget->m_frameRenderer->semaphore()->tryAcquire(1, timeout)) {
+ Mlt::Frame frame(frame_ptr);
+ if (frame.get_int("rendered")) {
+ QMetaObject::invokeMethod(widget->m_frameRenderer, "showFrame", Qt::QueuedConnection, Q_ARG(Mlt::Frame, frame));
+ }
+ }
+}
+
+
+RenderThread::RenderThread(thread_function_t function, void *data, QOpenGLContext *context)
+ : QThread(0)
+ , m_function(function)
+ , m_data(data)
+ , m_context(0)
+ , m_surface(0)
+{
+ qDebug()<<"=========\nSTARTING RDR THREAD\n================";
+ if (context) {
+ m_context = new QOpenGLContext;
+ m_context->setFormat(context->format());
+ m_context->setShareContext(context);
+ m_context->create();
+ m_surface = new QOffscreenSurface;
+ m_surface->setFormat(m_context->format());
+ m_surface->create();
+ m_context->moveToThread(this);
+ }
+}
+
+void RenderThread::run()
+{
+ if (m_context) {
+ m_context->makeCurrent(m_surface);
+ }
+ m_function(m_data);
+ if (m_context) {
+ m_context->doneCurrent();
+ delete m_context;
+ }
+ qDebug()<<"=========\nRDR THREAD DONE!!\n================";
+}
+
+FrameRenderer::FrameRenderer(QOpenGLContext* shareContext)
+ : QThread(0)
+ , m_semaphore(3)
+ , m_frame()
+ , m_context(0)
+ , m_surface(0)
+ , m_gl32(0)
+{
+ Q_ASSERT(shareContext);
+ m_renderTexture[0] = m_renderTexture[1] = m_renderTexture[2] = 0;
+ m_displayTexture[0] = m_displayTexture[1] = m_displayTexture[2] = 0;
+ m_context = new QOpenGLContext;
+ m_context->setFormat(shareContext->format());
+ m_context->setShareContext(shareContext);
+ m_context->create();
+ m_surface = new QOffscreenSurface;
+ m_surface->setFormat(m_context->format());
+ m_surface->create();
+ m_context->moveToThread(this);
+ setObjectName("FrameRenderer");
+ moveToThread(this);
+ start();
+}
+
+FrameRenderer::~FrameRenderer()
+{
+ qDebug();
+ delete m_context;
+ delete m_gl32;
+}
+
+void FrameRenderer::showFrame(Mlt::Frame frame)
+{
+ if (m_context->isValid()) {
+ int width = 0;
+ int height = 0;
+
+ m_context->makeCurrent(m_surface);
+
+ if (KdenliveSettings::gpu_accel()) {
+ frame.set("movit.convert.use_texture", 1);
+ mlt_image_format format = mlt_image_glsl_texture;
+ const GLuint* textureId = (GLuint*) frame.get_image(format, width, height);
+
+#ifdef USE_GL_SYNC
+ GLsync sync = (GLsync) frame.get_data("movit.convert.fence");
+ if (sync) {
+#ifdef Q_OS_WIN
+ // On Windows, use QOpenGLFunctions_3_2_Core instead of getProcAddress.
+ if (!m_gl32) {
+ m_gl32 = m_context->versionFunctions<QOpenGLFunctions_3_2_Core>();
+ if (m_gl32)
+ m_gl32->initializeOpenGLFunctions();
+ }
+ if (m_gl32) {
+ m_gl32->glClientWaitSync(sync, 0, GL_TIMEOUT_IGNORED);
+ check_error();
+ }
+#else
+ if (ClientWaitSync) {
+ ClientWaitSync(sync, 0, GL_TIMEOUT_IGNORED);
+ check_error();
+ }
+#endif // Q_OS_WIN
+ }
+#else
+ glFinish();
+#endif // USE_GL_FENCE
+ emit textureReady(*textureId);
+ }
+ else {
+ mlt_image_format format = mlt_image_yuv420p;
+ const uint8_t* image = frame.get_image(format, width, height);
+
+ // Upload each plane of YUV to a texture.
+ if (m_renderTexture[0] && m_renderTexture[1] && m_renderTexture[2])
+ glDeleteTextures(3, m_renderTexture);
+ glGenTextures(3, m_renderTexture);
+ check_error();
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
+
+ glBindTexture (GL_TEXTURE_2D, m_renderTexture[0]);
+ check_error();
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ check_error();
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ check_error();
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ check_error();
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ check_error();
+ glTexImage2D (GL_TEXTURE_2D, 0, GL_RED, width, height, 0,
+ GL_RED, GL_UNSIGNED_BYTE, image);
+ check_error();
+
+ glBindTexture (GL_TEXTURE_2D, m_renderTexture[1]);
+ check_error();
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ check_error();
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ check_error();
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ check_error();
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ check_error();
+ glTexImage2D (GL_TEXTURE_2D, 0, GL_RED, width/2, height/4, 0,
+ GL_RED, GL_UNSIGNED_BYTE, image + width * height);
+ check_error();
+
+ glBindTexture (GL_TEXTURE_2D, m_renderTexture[2]);
+ check_error();
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ check_error();
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ check_error();
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ check_error();
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ check_error();
+ glTexImage2D (GL_TEXTURE_2D, 0, GL_RED, width/2, height/4, 0,
+ GL_RED, GL_UNSIGNED_BYTE, image + width * height + width/2 * height/2);
+ check_error();
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ check_error();
+ glFinish();
+
+ for (int i = 0; i < 3; ++i)
+ qSwap(m_renderTexture[i], m_displayTexture[i]);
+ emit textureReady(m_displayTexture[0], m_displayTexture[1], m_displayTexture[2]);
+ }
+ m_context->doneCurrent();
+
+ // Save this frame for future use and to keep a reference to the GL Texture.
+ m_frame = SharedFrame(frame);
+
+ // The frame is now done being modified and can be shared with the rest
+ // of the application.
+ emit frameDisplayed(m_frame);
+ }
+ m_semaphore.release();
+}
+
+SharedFrame FrameRenderer::getDisplayFrame()
+{
+ return m_frame;
+}
+
+void FrameRenderer::cleanup()
+{
+ qDebug();
+ if (m_renderTexture[0] && m_renderTexture[1] && m_renderTexture[2]) {
+ m_context->makeCurrent(m_surface);
+ glDeleteTextures(3, m_renderTexture);
+ if (m_displayTexture[0] && m_displayTexture[1] && m_displayTexture[2])
+ glDeleteTextures(3, m_displayTexture);
+ m_context->doneCurrent();
+ m_renderTexture[0] = m_renderTexture[1] = m_renderTexture[2] = 0;
+ m_displayTexture[0] = m_displayTexture[1] = m_displayTexture[2] = 0;
+ }
+}
+
+
diff --git a/src/monitor/glwidget.h b/src/monitor/glwidget.h
new file mode 100644
index 0000000..342866a
--- /dev/null
+++ b/src/monitor/glwidget.h
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2011-2014 Meltytech, LLC
+ * Author: Dan Dennedy <[email protected]>
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GLWIDGET_H
+#define GLWIDGET_H
+
+#include <QSemaphore>
+#include <QQuickView>
+#include <QOpenGLFunctions>
+#include <QOpenGLShaderProgram>
+#include <QOpenGLFramebufferObject>
+#include <QOpenGLContext>
+#include <QMutex>
+#include <QThread>
+#include <QRect>
+#include "sharedframe.h"
+
+class QOpenGLFunctions_3_2_Core;
+class QOffscreenSurface;
+class QOpenGLTexture;
+//class QmlFilter;
+//class QmlMetadata;
+
+namespace Mlt {
+class Filter;
+}
+
+class RenderThread;
+class FrameRenderer;
+
+
+typedef void* ( *thread_function_t )( void* );
+
+class GLWidget : public QQuickView, protected QOpenGLFunctions
+{
+ Q_OBJECT
+ Q_PROPERTY(QRect rect READ rect NOTIFY rectChanged)
+ Q_PROPERTY(float zoom READ zoom NOTIFY zoomChanged)
+ Q_PROPERTY(QPoint offset READ offset NOTIFY offsetChanged)
+
+public:
+ GLWidget(bool accel = false, QObject *parent = 0);
+ ~GLWidget();
+
+ void createThread(RenderThread** thread, thread_function_t function, void* data);
+ void startGlsl();
+ void stopGlsl();
+ int setProducer(Mlt::Producer*, bool isMulti = false);
+ int reconfigure(bool isMulti);
+
+ int displayWidth() const { return m_rect.width(); }
+ int displayHeight() const { return m_rect.height(); }
+
+ QObject* videoWidget() { return this; }
+ QQuickView* videoQuickView() { return this; }
+ Mlt::Filter* glslManager() const { return m_glslManager; }
+ QRect rect() const { return m_rect; }
+ float zoom() const { return m_zoom /** MLT.profile().width() / m_rect.width()*/; }
+ QPoint offset() const;
+ Mlt::Consumer *consumer();
+ Mlt::Producer *producer();
+
+protected:
+ void mouseReleaseEvent(QMouseEvent * event);
+ void mouseDoubleClickEvent(QMouseEvent * event);
+ void wheelEvent(QWheelEvent * event);
+
+public slots:
+ void setZoom(float zoom);
+ void setOffsetX(int x);
+ void setOffsetY(int y);
+ void setBlankScene();
+ //void setCurrentFilter(QmlFilter* filter, QmlMetadata* meta);
+
+signals:
+ void frameDisplayed(const SharedFrame& frame);
+ void textureUpdated();
+ void dragStarted();
+ void seekTo(int x);
+ void gpuNotSupported();
+ void started();
+ void paused();
+ void playing();
+ void rectChanged();
+ void zoomChanged();
+ void offsetChanged();
+ void monitorPlay();
+ void switchFullScreen();
+ void mouseSeek(int eventDelta, bool fast);
+ void startDrag();
+
+private:
+ QRect m_rect;
+ GLuint m_texture[3];
+ QOpenGLShaderProgram* m_shader;
+ QPoint m_dragStart;
+ Mlt::Filter* m_glslManager;
+ Mlt::Consumer* m_consumer;
+ Mlt::Producer* m_producer;
+ QSemaphore m_initSem;
+ bool m_isInitialized;
+ Mlt::Event* m_threadStartEvent;
+ Mlt::Event* m_threadStopEvent;
+ Mlt::Event* m_threadCreateEvent;
+ Mlt::Event* m_threadJoinEvent;
+ FrameRenderer* m_frameRenderer;
+ int m_projectionLocation;
+ int m_modelViewLocation;
+ int m_vertexLocation;
+ int m_texCoordLocation;
+ int m_colorspaceLocation;
+ int m_textureLocation[3];
+ float m_zoom;
+ QPoint m_offset;
+
+ static void on_frame_show(mlt_consumer, void* self, mlt_frame frame);
+
+private slots:
+ void initializeGL();
+ void resizeGL(int width, int height);
+ void updateTexture(GLuint yName, GLuint uName, GLuint vName);
+ void paintGL();
+
+protected:
+ void resizeEvent(QResizeEvent* event);
+ void mousePressEvent(QMouseEvent *);
+ void mouseMoveEvent(QMouseEvent *);
+ void keyPressEvent(QKeyEvent* event);
+ void createShader();
+};
+
+class RenderThread : public QThread
+{
+ Q_OBJECT
+public:
+ RenderThread(thread_function_t function, void* data, QOpenGLContext *context);
+
+protected:
+ void run();
+
+private:
+ thread_function_t m_function;
+ void* m_data;
+ QOpenGLContext* m_context;
+ QOffscreenSurface* m_surface;
+};
+
+class FrameRenderer : public QThread
+{
+ Q_OBJECT
+public:
+ FrameRenderer(QOpenGLContext* shareContext);
+ ~FrameRenderer();
+ QSemaphore* semaphore() { return &m_semaphore; }
+ QOpenGLContext* context() const { return m_context; }
+ SharedFrame getDisplayFrame();
+ Q_INVOKABLE void showFrame(Mlt::Frame frame);
+
+public slots:
+ void cleanup();
+
+signals:
+ void textureReady(GLuint yName, GLuint uName = 0, GLuint vName = 0);
+ void frameDisplayed(const SharedFrame& frame);
+
+private:
+ QSemaphore m_semaphore;
+ SharedFrame m_frame;
+ QOpenGLContext* m_context;
+ QOffscreenSurface* m_surface;
+public:
+ GLuint m_renderTexture[3];
+ GLuint m_displayTexture[3];
+ QOpenGLFunctions_3_2_Core* m_gl32;
+};
+
+
+
+#endif
diff --git a/src/monitor/monitor.cpp b/src/monitor/monitor.cpp
index 5815a48..f950814 100644
--- a/src/monitor/monitor.cpp
+++ b/src/monitor/monitor.cpp
@@ -23,6 +23,7 @@
#include "monitorscene.h"
#include "monitoreditwidget.h"
#include "videosurface.h"
+#include "glwidget.h"
#include "smallruler.h"
#include "mltcontroller/clipcontroller.h"
#include "kdenlivesettings.h"
@@ -31,6 +32,7 @@
#include "klocalizedstring.h"
#include <KRecentDirs>
+#include <KMessageBox>
#include <QDebug>
#include <QMouseEvent>
@@ -44,6 +46,7 @@
#include <QDrag>
#include <QFileDialog>
#include <QMimeData>
+#include <QQuickItem>
#define SEEK_INACTIVE (-1)
@@ -60,17 +63,39 @@ Monitor::Monitor(Kdenlive::MonitorId id, MonitorManager *manager, QWidget *paren
, m_effectWidget(NULL)
, m_selectedClip(NULL)
, m_loopClipTransition(true)
-#ifdef USE_OPENGL
- , m_glWidget(NULL)
-#endif
, m_editMarker(NULL)
+ , m_glMonitor(NULL)
+ , m_rootItem(NULL)
{
QVBoxLayout *layout = new QVBoxLayout;
layout->setContentsMargins(0, 0, 0, 0);
layout->setSpacing(0);
+ // Create container widget
+ m_glWidget = new QWidget;
+ QGridLayout* glayout = new QGridLayout(m_glWidget);
+ glayout->setSpacing(0);
+ glayout->setContentsMargins(0, 0, 0, 0);
+
+ // Create QML OpenGL widget
+ /*if (id != Kdenlive::ProjectMonitor)*/ {
+ m_glMonitor = new GLWidget;//(id == Kdenlive::ProjectMonitor);
+ QWidget *videoWidget = QWidget::createWindowContainer(qobject_cast<QWindow*>(m_glMonitor), this);
+ glayout->addWidget(videoWidget, 0, 0);
+
+ connect(m_glMonitor, SIGNAL(frameDisplayed(const SharedFrame&)), this, SLOT(onFrameDisplayed(const SharedFrame&)));
+ connect(m_glMonitor, SIGNAL(mouseSeek(int,bool)), this, SLOT(slotMouseSeek(int,bool)));
+ connect(m_glMonitor, SIGNAL(monitorPlay()), this, SLOT(slotPlay()));
+ connect(m_glMonitor, SIGNAL(startDrag()), this, SLOT(slotStartDrag()));
+ connect(m_glMonitor, SIGNAL(switchFullScreen()), this, SLOT(slotSwitchFullScreen()));
+ m_glMonitor->setSource(QUrl::fromLocalFile(QStandardPaths::locate(QStandardPaths::DataLocation, QStringLiteral("kdenlivemonitor.qml"))));
+ m_rootItem = m_glMonitor->rootObject();
+ }
+ m_glWidget->setMinimumSize(QSize(320, 180));
+ layout->addWidget(m_glWidget, 10);
+
// Video widget holder
- layout->addWidget(videoBox, 10);
+ //layout->addWidget(videoBox, 10);
layout->addStretch();
// Get base size for icons
@@ -148,29 +173,7 @@ Monitor::Monitor(Kdenlive::MonitorId id, MonitorManager *manager, QWidget *paren
setLayout(layout);
setMinimumHeight(200);
- bool monitorCreated = false;
-#ifdef Q_WS_MAC
- createOpenGlWidget(videoBox);
- monitorCreated = true;
- //m_glWidget->setFixedSize(width, height);
-#elif defined(USE_OPENGL)
- if (KdenliveSettings::openglmonitors()) {
- monitorCreated = createOpenGlWidget(videoBox);
- }
-#endif
- if (!monitorCreated) {
- createVideoSurface();
- render = new Render(m_id, m_monitorManager->binController(), (int) videoSurface->winId(), this);
- connect(videoSurface, SIGNAL(refreshMonitor()), render, SLOT(doRefresh()));
- }
-#ifdef USE_OPENGL
- else if (m_glWidget) {
- QVBoxLayout *lay = new QVBoxLayout;
- lay->setContentsMargins(0, 0, 0, 0);
- lay->addWidget(m_glWidget);
- videoBox->setLayout(lay);
- }
-#endif
+ render = new Render(m_id, m_monitorManager->binController(), m_glMonitor, this);
// Monitor ruler
m_ruler = new SmallRuler(this, render);
@@ -189,14 +192,13 @@ Monitor::Monitor(Kdenlive::MonitorId id, MonitorManager *manager, QWidget *paren
connect(m_ruler, SIGNAL(zoneChanged(QPoint)), this, SLOT(setClipZone(QPoint)));
}
- if (videoSurface) videoSurface->show();
if (id == Kdenlive::ProjectMonitor) {
- m_effectWidget = new MonitorEditWidget(render, videoBox);
+ /*m_effectWidget = new MonitorEditWidget(render, m_glWidget);
connect(m_effectWidget, SIGNAL(showEdit(bool,bool)), this, SLOT(slotShowEffectScene(bool,bool)));
m_toolbar->addAction(m_effectWidget->getVisibilityAction());
videoBox->layout()->addWidget(m_effectWidget);
- m_effectWidget->hide();
+ m_effectWidget->hide();*/
}
QWidget *spacer = new QWidget(this);
@@ -224,22 +226,6 @@ QWidget *Monitor::container()
return videoBox;
}
-#ifdef USE_OPENGL
-bool Monitor::createOpenGlWidget(QWidget *parent)
-{
- render = new Render(id(), m_monitorManager->binController(), 0, this);
- m_glWidget = new VideoGLWidget(parent);
- if (m_glWidget == NULL) {
- // Creation failed, we are in trouble...
- return false;
- }
- m_glWidget->setImageAspectRatio(render->dar());
- m_glWidget->setBackgroundColor(KdenliveSettings::window_background());
- connect(render, SIGNAL(showImageSignal(QImage)), m_glWidget, SLOT(showImage(QImage)));
- return true;
-}
-#endif
-
void Monitor::setupMenu(QMenu *goMenu, QAction *playZone, QAction *loopZone, QMenu *markerMenu, QAction *loopClip, QWidget* parent)
{
m_contextMenu = new QMenu(parent);
@@ -293,8 +279,14 @@ void Monitor::setupMenu(QMenu *goMenu, QAction *playZone, QAction *loopZone, QMe
dropFrames->setChecked(true);
connect(dropFrames, SIGNAL(toggled(bool)), this, SLOT(slotSwitchDropFrames(bool)));
+ QAction *gpuAccel = m_contextMenu->addAction(QIcon(), i18n("GPU acceleration"));
+ gpuAccel->setCheckable(true);
+ gpuAccel->setChecked(KdenliveSettings::gpu_accel());
+ connect(gpuAccel, SIGNAL(toggled(bool)), this, SLOT(slotSwitchGpuAccel(bool)));
+
m_configMenu->addAction(showTips);
m_configMenu->addAction(dropFrames);
+ m_configMenu->addAction(gpuAccel);
}
void Monitor::slotGoToMarker(QAction *action)
@@ -316,7 +308,7 @@ void Monitor::slotSetSizeOneToOne()
height = height * 0.8;
}
//qDebug() << "// MONITOR; set SIZE: " << width << ", " << height;
- videoBox->setFixedSize(width, height);
+ m_glWidget->setFixedSize(width, height);
updateGeometry();
adjustSize();
//m_ui.video_frame->setMinimumSize(0, 0);
@@ -336,7 +328,7 @@ void Monitor::slotSetSizeOneToTwo()
height = height * 0.8;
}
//qDebug() << "// MONITOR; set SIZE: " << width << ", " << height;
- videoBox->setFixedSize(width, height);
+ m_glWidget->setFixedSize(width, height);
updateGeometry();
adjustSize();
//m_ui.video_frame->setMinimumSize(0, 0);
@@ -345,7 +337,7 @@ void Monitor::slotSetSizeOneToTwo()
void Monitor::resetSize()
{
- videoBox->setMinimumSize(0, 0);
+ m_glWidget->setMinimumSize(0, 0);
}
QString Monitor::getTimecodeFromFrames(int pos)
@@ -453,7 +445,7 @@ void Monitor::mousePressEvent(QMouseEvent * event)
{
if (render) render->setActiveMonitor();
if (event->button() != Qt::RightButton) {
- if (videoBox->geometry().contains(event->pos()) && (!m_overlay || !m_overlay->underMouse())) {
+ if (m_glWidget->geometry().contains(event->pos()) && (!m_overlay || !m_overlay->underMouse())) {
m_dragStarted = true;
m_DragStartPosition = event->pos();
}
@@ -470,14 +462,14 @@ void Monitor::resizeEvent(QResizeEvent *event)
void Monitor::slotSwitchFullScreen()
{
- videoBox->switchFullScreen();
+ switchFullScreen();
}
// virtual
void Monitor::mouseReleaseEvent(QMouseEvent * event)
{
if (m_dragStarted && event->button() != Qt::RightButton) {
- if (videoBox->geometry().contains(event->pos()) && (!m_effectWidget || !m_effectWidget->isVisible())) {
+ if (m_glMonitor->geometry().contains(event->pos()) && (!m_effectWidget || !m_effectWidget->isVisible())) {
if (isActive()) slotPlay();
else slotActivateMonitor();
} //else event->ignore(); //QWidget::mouseReleaseEvent(event);
@@ -486,6 +478,27 @@ void Monitor::mouseReleaseEvent(QMouseEvent * event)
event->accept();
}
+
+void Monitor::slotStartDrag()
+{
+ QDrag *drag = new QDrag(this);
+ QMimeData *mimeData = new QMimeData;
+
+ QStringList list;
+ list.append(m_controller->clipId());
+ QPoint p = m_ruler->zone();
+ list.append(QString::number(p.x()));
+ list.append(QString::number(p.y()));
+ QByteArray data;
+ data.append(list.join(";").toUtf8());
+ mimeData->setData("kdenlive/clip", data);
+ drag->setMimeData(mimeData);
+ /*QPixmap pix = m_currentClip->thumbnail();
+ drag->setPixmap(pix);
+ drag->setHotSpot(QPoint(0, 50));*/
+ drag->start(Qt::MoveAction);
+}
+
// virtual
void Monitor::mouseMoveEvent(QMouseEvent *event)
{
@@ -554,7 +567,7 @@ void Monitor::wheelEvent(QWheelEvent * event)
void Monitor::mouseDoubleClickEvent(QMouseEvent * event)
{
if (!KdenliveSettings::openglmonitors()) {
- videoBox->switchFullScreen();
+ switchFullScreen();
event->accept();
}
}
@@ -632,6 +645,7 @@ void Monitor::slotSeek()
void Monitor::slotSeek(int pos)
{
+ qDebug()<<"+ + + ++ SEEKING TO: "<<pos;
if (render == NULL) return;
slotActivateMonitor();
render->seekToFrame(pos);
@@ -640,7 +654,7 @@ void Monitor::slotSeek(int pos)
void Monitor::checkOverlay()
{
- if (m_overlay == NULL) return;
+ if (m_rootItem == NULL) return;
QString overlayText;
int pos = m_timePos->getValue();//render->seekFramePosition();
QPoint zone = m_ruler->zone();
@@ -657,8 +671,7 @@ void Monitor::checkOverlay()
}
}
}
- if (m_overlay->isVisible() && overlayText.isEmpty()) m_overlay->setOverlayText(QString(), false);
- else m_overlay->setOverlayText(overlayText);
+ m_rootItem->setProperty("comment", overlayText);
}
void Monitor::slotStart()
@@ -802,9 +815,6 @@ void Monitor::stop()
void Monitor::start()
{
if (!isVisible() || !isActive()) return;
-#ifdef USE_OPENGL
- if (m_glWidget) m_glWidget->activateMonitor();
-#endif
if (render) render->startConsumer();
}
@@ -980,9 +990,6 @@ void Monitor::setCustomProfile(const QString &profile, const Timecode &tc)
if (!render->hasProfile(profile)) {
slotActivateMonitor();
render->resetProfile(profile);
-#ifdef USE_OPENGL
- if (m_glWidget) m_glWidget->setImageAspectRatio(render->dar());
-#endif
}
}
@@ -993,9 +1000,6 @@ void Monitor::resetProfile(const QString &profile)
if (!render->hasProfile(profile)) {
slotActivateMonitor();
render->resetProfile(profile);
-#ifdef USE_OPENGL
- if (m_glWidget) m_glWidget->setImageAspectRatio(render->dar());
-#endif
}
if (m_effectWidget)
m_effectWidget->resetProfile(render);
@@ -1024,37 +1028,22 @@ void Monitor::slotSwitchDropFrames(bool show)
render->setDropFrames(show);
}
+void Monitor::slotSwitchGpuAccel(bool enable)
+{
+ KMessageBox::information(this, i18n("You need to restart Kdenlive to apply the change in GPU acceleration"));
+ KdenliveSettings::setGpu_accel(enable);
+}
+
void Monitor::slotSwitchMonitorInfo(bool show)
{
KdenliveSettings::setDisplayMonitorInfo(show);
if (show) {
- if (m_overlay) return;
- if (videoSurface == NULL) {
- // Using OpenGL display
-#ifdef USE_OPENGL
- if (m_glWidget->layout()) delete m_glWidget->layout();
- m_overlay = new Overlay();
- connect(m_overlay, SIGNAL(editMarker()), this, SLOT(slotEditMarker()));
- QVBoxLayout *layout = new QVBoxLayout;
- layout->addStretch(10);
- layout->addWidget(m_overlay);
- m_glWidget->setLayout(layout);
-#endif
- } else {
- if (videoSurface->layout()) delete videoSurface->layout();
- m_overlay = new Overlay();
- connect(m_overlay, SIGNAL(editMarker()), this, SLOT(slotEditMarker()));
- QVBoxLayout *layout = new QVBoxLayout;
- layout->addStretch(10);
- layout->addWidget(m_overlay);
- videoSurface->setLayout(layout);
- m_overlay->raise();
- m_overlay->setHidden(true);
- }
- checkOverlay();
- } else {
- delete m_overlay;
- m_overlay = NULL;
+ m_rootItem = m_glMonitor->rootObject();
+ m_rootItem->setProperty("visible", true);
+ }
+ else {
+ m_rootItem->setProperty("visible", false);
+ m_rootItem = NULL;
}
}
@@ -1107,6 +1096,7 @@ void Monitor::slotSetSelectedClip(Transition* item)
void Monitor::slotShowEffectScene(bool show, bool manuallyTriggered)
{
+ return;
if (m_id == Kdenlive::ProjectMonitor) {
if (!m_effectWidget->getVisibilityAction()->isChecked())
show = false;
@@ -1143,7 +1133,8 @@ void Monitor::slotShowEffectScene(bool show, bool manuallyTriggered)
if (!manuallyTriggered)
m_effectWidget->showVisibilityButton(show);
setUpdatesEnabled(true);
- videoBox->setEnabled(show);
+ //TODO:
+ //videoBox->setEnabled(show);
//render->doRefresh();
}
}
@@ -1180,6 +1171,26 @@ void Monitor::slotShowVolume()
m_volumePopup->show();
}
+
+void Monitor::onFrameDisplayed(const SharedFrame& frame)
+{
+ int position = frame.get_position();
+ render->checkFrameNumber(position);
+ if (m_rootItem) m_rootItem->setProperty("framenum", QString::number(position));
+ seekCursor(position);
+ /*if (position < m_length) {
+ m_position = position;
+ m_positionSpinner->blockSignals(true);
+ m_positionSpinner->setValue(position);
+ m_positionSpinner->blockSignals(false);
+ m_scrubber->onSeek(position);
+ }
+ */
+ if (position >= m_length)
+ render->pause();
+ //emit endOfStream();
+}
+
AbstractRender *Monitor::abstractRender()
{
return render;
@@ -1210,6 +1221,33 @@ void Monitor::setPalette ( const QPalette & p)
}
+void Monitor::switchFullScreen()
+{
+ // TODO: disable screensaver?
+ if (!m_glWidget->isFullScreen()) {
+ // Check if we ahave a multiple monitor setup
+ int monitors = QApplication::desktop()->screenCount();
+ int screen = -1;
+ if (monitors > 1) {
+ QRect screenres;
+ // Move monitor widget to the second screen (one screen for Kdenlive, the other one for the Monitor widget
+ //int currentScreen = QApplication::desktop()->screenNumber(this);
+ for (int i = 0; screen == -1 && i < QApplication::desktop()->screenCount(); i++) {
+ if (i != QApplication::desktop()->screenNumber(this))
+ screen = i;
+ }
+ }
+ m_glWidget->setParent(QApplication::desktop()->screen(screen));
+ m_glWidget->move(QApplication::desktop()->screenGeometry(screen).bottomLeft());
+ m_glWidget->showFullScreen();
+ } else {
+ m_glWidget->showNormal();
+ QVBoxLayout *lay = (QVBoxLayout *) layout();
+ lay->insertWidget(0, m_glWidget, 10);
+ }
+}
+
+
Overlay::Overlay(QWidget* parent) :
QLabel(parent)
{
diff --git a/src/monitor/monitor.h b/src/monitor/monitor.h
index 5d752b6..360d577 100644
--- a/src/monitor/monitor.h
+++ b/src/monitor/monitor.h
@@ -26,14 +26,13 @@
#include "renderer.h"
#include "definitions.h"
#include "timecodedisplay.h"
-#ifdef USE_OPENGL
-#include "monitor/videoglwidget.h"
-#endif
+#include "monitor/sharedframe.h"
+
#include <QLabel>
#include <QDomElement>
#include <QToolBar>
-
+#include <QWindow>
#include <QIcon>
class SmallRuler;
@@ -46,7 +45,7 @@ class Monitor;
class MonitorManager;
class QSlider;
class TwostateAction;
-
+class QQuickItem;
class Overlay : public QLabel
{
@@ -119,6 +118,7 @@ protected:
private:
ClipController *m_controller;
+ GLWidget *m_glMonitor;
SmallRuler *m_ruler;
Overlay *m_overlay;
int m_length;
@@ -140,11 +140,7 @@ private:
/** true if selected clip is transition, false = selected clip is clip.
* Necessary because sometimes we get two signals, e.g. we get a clip and we get selected transition = NULL. */
bool m_loopClipTransition;
-
-#ifdef USE_OPENGL
- VideoGLWidget *m_glWidget;
- bool createOpenGlWidget(QWidget *parent);
-#endif
+ QWidget *m_glWidget;
GenTime getSnapForPos(bool previous);
Qt::WindowFlags m_baseFlags;
@@ -152,6 +148,8 @@ private:
QWidget *m_volumeWidget;
QSlider *m_audioSlider;
QAction *m_editMarker;
+ QQuickItem *m_rootItem;
+ void switchFullScreen();
private slots:
void seekCursor(int pos);
@@ -170,6 +168,9 @@ private slots:
void slotShowVolume();
void slotEditMarker();
void slotExtractCurrentZone();
+ void onFrameDisplayed(const SharedFrame& frame);
+ void slotStartDrag();
+ void slotSwitchGpuAccel(bool enable);
public slots:
void slotOpenFile(const QString &);
diff --git a/src/monitor/monitormanager.cpp b/src/monitor/monitormanager.cpp
index 48a4005..1b2e5de 100644
--- a/src/monitor/monitormanager.cpp
+++ b/src/monitor/monitormanager.cpp
@@ -107,7 +107,9 @@ bool MonitorManager::activateMonitor(Kdenlive::MonitorId name, bool forceRefresh
if (m_monitorsList.at(i)->id() == name) {
m_activeMonitor = m_monitorsList.at(i);
}
- else m_monitorsList.at(i)->stop();
+ else {
+ m_monitorsList.at(i)->stop();
+ }
}
if (m_activeMonitor) {
m_activeMonitor->blockSignals(true);
diff --git a/src/monitor/recmonitor.cpp b/src/monitor/recmonitor.cpp
index d96e67b..08b3ba5 100644
--- a/src/monitor/recmonitor.cpp
+++ b/src/monitor/recmonitor.cpp
@@ -27,6 +27,7 @@
#include "capture/managecapturesdialog.h"
#include "dialogs/profilesdialog.h"
#include "videosurface.h"
+#include "glwidget.h"
#include <config-kdenlive.h>
#include <QDebug>
@@ -1045,7 +1046,8 @@ void RecMonitor::buildMltDevice(const QString &path)
{
if (m_captureDevice == NULL) {
m_monitorManager->updateScopeSource();
- m_captureDevice = new MltDeviceCapture(path, videoSurface, this);
+ //TODO
+ //m_captureDevice = new MltDeviceCapture(path, videoSurface, this);
connect(m_captureDevice, &MltDeviceCapture::droppedFrames, this, &RecMonitor::slotDroppedFrames);
m_captureDevice->sendFrameForAnalysis = m_analyse;
m_monitorManager->updateScopeSource();
diff --git a/src/monitor/videoglwidget.cpp b/src/monitor/videoglwidget.cpp
index a1fab90..d8eda94 100644
--- a/src/monitor/videoglwidget.cpp
+++ b/src/monitor/videoglwidget.cpp
@@ -19,6 +19,7 @@
***************************************************************************/
#include "videoglwidget.h"
+#include "kdenlivesettings.h"
#include <QApplication>
#include <QMouseEvent>
@@ -38,7 +39,7 @@ VideoGLWidget::VideoGLWidget(QWidget *parent)
, m_image_height(0)
, m_texture(0)
, m_display_ratio(4.0 / 3.0)
- , m_backgroundColor(Qt::gray)
+ , m_backgroundColor(KdenliveSettings::window_background())
{
setAttribute(Qt::WA_OpaquePaintEvent);
}
diff --git a/src/renderer.cpp b/src/renderer.cpp
index e145bb3..0a2333f 100644
--- a/src/renderer.cpp
+++ b/src/renderer.cpp
@@ -31,6 +31,7 @@
#include "dialogs/profilesdialog.h"
#include "mltcontroller/bincontroller.h"
#include "bin/projectclip.h"
+#include "monitor/glwidget.h"
#include "mltcontroller/clipcontroller.h"
#include <mlt++/Mlt.h>
@@ -98,7 +99,7 @@ void Render::consumer_gl_frame_show(mlt_consumer consumer, Render * self, mlt_fr
emit self->mltFrameReceived(new Mlt::Frame(frame_ptr));
}
-Render::Render(Kdenlive::MonitorId rendererName, BinController *binController, int winid, QWidget *parent) :
+Render::Render(Kdenlive::MonitorId rendererName, BinController *binController, GLWidget *qmlView, QWidget *parent) :
AbstractRender(rendererName, parent),
requestedSeekPosition(SEEK_INACTIVE),
showFrameSemaphore(1),
@@ -114,16 +115,22 @@ Render::Render(Kdenlive::MonitorId rendererName, BinController *binController, i
m_isLoopMode(false),
m_isSplitView(false),
m_blackClip(NULL),
- m_winid(winid),
- m_paused(true),
+ m_qmlView(qmlView),
m_isActive(false)
{
qRegisterMetaType<stringMap> ("stringMap");
analyseAudio = KdenliveSettings::monitor_audio();
- buildConsumer();
+ //buildConsumer();
+ m_blackClip = new Mlt::Producer(*m_mltProfile, "colour:black");
+ m_blackClip->set("id", "black");
+ m_blackClip->set("mlt_type", "producer");
m_mltProducer = m_blackClip->cut(0, 1);
- m_mltConsumer->connect(*m_mltProducer);
- m_mltProducer->set_speed(0.0);
+ if (m_qmlView) {
+ m_qmlView->setProducer(m_mltProducer);
+ m_mltConsumer = qmlView->consumer();
+ }
+ /*m_mltConsumer->connect(*m_mltProducer);
+ m_mltProducer->set_speed(0.0);*/
m_refreshTimer.setSingleShot(true);
m_refreshTimer.setInterval(100);
connect(&m_refreshTimer, SIGNAL(timeout()), this, SLOT(refresh()));
@@ -155,7 +162,7 @@ void Render::slotSwitchFullscreen()
m_mltConsumer->set("full_screen", 1);
}
-void Render::buildConsumer()
+/*void Render::buildConsumer()
{
delete m_blackClip;
m_blackClip = NULL;
@@ -248,18 +255,17 @@ void Render::buildConsumer()
QString audioDriver = KdenliveSettings::audiodrivername();
- /*
// Disabled because the "auto" detected driver was sometimes wrong
- if (audioDriver.isEmpty())
- audioDriver = KdenliveSettings::autoaudiodrivername();
- */
+ //if (audioDriver.isEmpty())
+ // audioDriver = KdenliveSettings::autoaudiodrivername();
+
if (!audioDriver.isEmpty())
m_mltConsumer->set("audio_driver", audioDriver.toUtf8().constData());
m_mltConsumer->set("frequency", 48000);
m_mltConsumer->set("real_time", KdenliveSettings::mltthreads());
-}
+}*/
Mlt::Producer *Render::invalidProducer(const QString &id)
{
@@ -286,6 +292,7 @@ bool Render::hasProfile(const QString &profileName) const
int Render::resetProfile(const QString &profileName, bool dropSceneList)
{
+ return 0;
m_refreshTimer.stop();
if (m_mltConsumer) {
if (externalConsumer == KdenliveSettings::external_display()) {
@@ -370,16 +377,15 @@ void Render::seek(int time)
requestedSeekPosition = time;
m_mltConsumer->purge();
m_mltProducer->seek(time);
- if (m_paused && !externalConsumer) {
+ if (!externalConsumer) {
m_mltConsumer->set("refresh", 1);
- m_paused = false;
}
- else if (m_winid != 0 && m_mltProducer->get_speed() == 0) {
+ /*else if (m_winid != 0 && m_mltProducer->get_speed() == 0) {
// workaround specific bug in MLT's SDL consumer
m_mltConsumer->stop();
m_mltConsumer->start();
m_mltConsumer->set("refresh", 1);
- }
+ }*/
}
else requestedSeekPosition = time;
}
@@ -645,6 +651,7 @@ void Render::processFileProperties()
requestClipInfo info;
QLocale locale;
locale.setNumberOptions(QLocale::OmitGroupSeparator);
+
while (!m_requestList.isEmpty()) {
m_infoMutex.lock();
info = m_requestList.takeFirst();
@@ -999,6 +1006,20 @@ void Render::processFileProperties()
int variance;
QImage img;
+ // Check if we are using GPU accel, then we need to use alternate producer
+ Mlt::Producer *tmpProd;
+ if (KdenliveSettings::gpu_accel()) {
+ QString service = producer->get("mlt_service");
+ tmpProd = new Mlt::Producer(*m_mltProfile, service.toUtf8().constData(), producer->get("resource"));
+ Mlt::Filter scaler(*m_mltProfile, "swscale");
+ Mlt::Filter converter(*m_mltProfile, "avcolor_space");
+ tmpProd->attach(scaler);
+ tmpProd->attach(converter);
+ }
+ else {
+ tmpProd = producer;
+ }
+ frame = tmpProd->get_frame();
do {
img = KThumb::getFrame(frame, imageWidth, fullWidth, info.imageHeight);
variance = KThumb::imageVariance(img);
@@ -1007,7 +1028,7 @@ void Render::processFileProperties()
frameNumber = duration > 100 ? 100 : duration / 2 ;
producer->seek(frameNumber);
delete frame;
- frame = producer->get_frame();
+ frame = tmpProd->get_frame();
variance = -1;
}
} while (variance == -1);
@@ -1168,20 +1189,16 @@ int Render::setProducer(Mlt::Producer *producer, int position)
QMutexLocker locker(&m_mutex);
QString currentId;
int consumerPosition = 0;
- if (m_winid == -1 || !m_mltConsumer) {
- qDebug()<<" / / / / WARNING, MONITOR NOT READY";
- if (producer) delete producer;
- return -1;
- }
bool monitorIsActive = false;
- m_mltConsumer->set("refresh", 0);
- if (!m_mltConsumer->is_stopped()) {
- monitorIsActive = true;
- m_mltConsumer->stop();
+ if (m_mltConsumer) {
+ m_mltConsumer->set("refresh", 0);
+ /*if (!m_mltConsumer->is_stopped()) {
+ monitorIsActive = true;
+ m_mltConsumer->stop();
+ }*/
+ //m_mltConsumer->purge();
+ consumerPosition = m_mltConsumer->position();
}
- m_mltConsumer->purge();
- consumerPosition = m_mltConsumer->position();
-
blockSignals(true);
if (!producer || !producer->is_valid()) {
@@ -1199,6 +1216,7 @@ int Render::setProducer(Mlt::Producer *producer, int position)
if (position != -1) producer->seek(position);
m_fps = producer->get_fps();
int volume = KdenliveSettings::volume();
+ /*
if (producer->get_int("_audioclip") == 1) {
// This is an audio only clip, create fake multitrack to apply audiowave filter
Mlt::Tractor *tractor = new Mlt::Tractor();
@@ -1228,18 +1246,25 @@ int Render::setProducer(Mlt::Producer *producer, int position)
}
producer->set("meta.volume", (double)volume / 100);
- blockSignals(false);
+
if (m_mltProducer) {
m_mltProducer->set_speed(0);
delete m_mltProducer;
m_mltProducer = NULL;
}
-
- m_mltConsumer->connect(*producer);
+ */
+ blockSignals(false);
m_mltProducer = producer;
m_mltProducer->set_speed(0);
+ if (m_qmlView) {
+ m_qmlView->setProducer(producer);
+ m_mltConsumer = m_qmlView->consumer();
+ m_mltConsumer->set("refresh", 1);
+ }
+ //m_mltConsumer->connect(*producer);
+
if (monitorIsActive) {
- startConsumer();
+ //startConsumer();
}
emit durationChanged(m_mltProducer->get_playtime(), m_mltProducer->get_in());
position = m_mltProducer->position();
@@ -1273,7 +1298,7 @@ int Render::setSceneList(QString playlist, int position)
requestedSeekPosition = SEEK_INACTIVE;
m_refreshTimer.stop();
QMutexLocker locker(&m_mutex);
- if (m_winid == -1) return -1;
+ //if (m_winid == -1) return -1;
int error = 0;
//qDebug() << "////// RENDER, SET SCENE LIST:\n" << playlist <<"\n..........:::.";
@@ -1287,7 +1312,7 @@ int Render::setSceneList(QString playlist, int position)
if (m_mltConsumer) {
if (!m_mltConsumer->is_stopped()) {
- m_mltConsumer->stop();
+ //m_mltConsumer->stop();
}
m_mltConsumer->set("refresh", 0);
} else {
@@ -1381,9 +1406,13 @@ int Render::setSceneList(QString playlist, int position)
QString retain = QString("xml_retain %1").arg(m_binController->binPlaylistId());
tractor.set(retain.toUtf8().constData(), m_binController->service(), 0);
//if (!m_binController->hasClip("black")) m_binController->addClipToBin("black", *m_blackClip);
+ if (m_qmlView) {
+ m_qmlView->setProducer(m_mltProducer);
+ m_mltConsumer = m_qmlView->consumer();
+ }
//qDebug() << "// NEW SCENE LIST DURATION SET TO: " << m_mltProducer->get_playtime();
- m_mltConsumer->connect(*m_mltProducer);
+ //m_mltConsumer->connect(*m_mltProducer);
m_mltProducer->set_speed(0);
fillSlowMotionProducers();
emit durationChanged(m_mltProducer->get_playtime());
@@ -1418,7 +1447,7 @@ int Render::reloadSceneList(QString playlist, int position)
requestedSeekPosition = SEEK_INACTIVE;
m_refreshTimer.stop();
QMutexLocker locker(&m_mutex);
- if (m_winid == -1) return -1;
+ //if (m_winid == -1) return -1;
int error = 0;
//qDebug() << "////// RENDER, SET SCENE LIST:\n" << playlist <<"\n..........:::.";
@@ -1432,7 +1461,7 @@ int Render::reloadSceneList(QString playlist, int position)
if (m_mltConsumer) {
if (!m_mltConsumer->is_stopped()) {
- m_mltConsumer->stop();
+ //m_mltConsumer->stop();
}
m_mltConsumer->set("refresh", 0);
} else {
@@ -1645,10 +1674,10 @@ void Render::start()
{
m_refreshTimer.stop();
QMutexLocker locker(&m_mutex);
- if (m_winid == -1) {
+ /*if (m_winid == -1) {
//qDebug() << "----- BROKEN MONITOR: " << m_name << ", RESTART";
return;
- }
+ }*/
if (!m_mltConsumer) {
//qDebug()<<" / - - - STARTED BEFORE CONSUMER!!!";
return;
@@ -1704,7 +1733,6 @@ void Render::pause()
requestedSeekPosition = SEEK_INACTIVE;
if (!m_mltProducer || !m_mltConsumer || !m_isActive)
return;
- m_paused = true;
m_mltProducer->set_speed(0.0);
/*m_mltConsumer->set("refresh", 0);
//if (!m_mltConsumer->is_stopped()) m_mltConsumer->stop();
@@ -1723,32 +1751,27 @@ void Render::switchPlay(bool play)
if (!m_mltProducer || !m_mltConsumer || !m_isActive)
return;
if (m_isZoneMode) resetZoneMode();
- if (play && m_paused) {
+ if (play && playSpeed() == 0) {
if (m_name == Kdenlive::ClipMonitor && m_mltConsumer->position() == m_mltProducer->get_out()) m_mltProducer->seek(0);
- m_paused = false;
m_mltProducer->set_speed(1.0);
if (m_mltConsumer->is_stopped()) {
m_mltConsumer->start();
}
m_mltConsumer->set("refresh", 1);
} else if (!play) {
- m_paused = true;
- if (m_winid == 0) {
- // OpenGL consumer
- m_mltProducer->set_speed(0.0);
- //m_mltConsumer->set("refresh", 0);
- //m_mltProducer->set_speed(0.0);
- //m_mltConsumer->purge();
- //m_mltProducer->seek(m_mltConsumer->position());
- }
- else {
- // SDL consumer, hack to allow pausing near the end of the playlist
- m_mltConsumer->set("refresh", 0);
- m_mltConsumer->stop();
- m_mltProducer->set_speed(0.0);
- m_mltProducer->seek(m_mltConsumer->position());
- m_mltConsumer->start();
- }
+ // OpenGL consumer
+ m_mltConsumer->set("refresh", 0);
+ m_mltConsumer->purge();
+ m_mltProducer->set_speed(0.0);
+ m_mltProducer->seek(m_mltConsumer->position());
+ //m_mltConsumer->set("refresh", 0);
+
+ // SDL consumer, hack to allow pausing near the end of the playlist
+ /*m_mltConsumer->set("refresh", 0);
+ m_mltConsumer->stop();
+ m_mltProducer->set_speed(0.0);
+ m_mltProducer->seek(m_mltConsumer->position());
+ m_mltConsumer->start();*/
}
}
@@ -1764,7 +1787,6 @@ void Render::play(double speed)
if (m_mltConsumer->is_stopped() && speed != 0) {
m_mltConsumer->start();
}
- m_paused = speed == 0;
if (current_speed == 0 && speed != 0) m_mltConsumer->set("refresh", 1);
}
@@ -1773,7 +1795,6 @@ void Render::play(const GenTime & startTime)
requestedSeekPosition = SEEK_INACTIVE;
if (!m_mltProducer || !m_mltConsumer || !m_isActive)
return;
- m_paused = false;
m_mltProducer->seek((int)(startTime.frames(m_fps)));
m_mltProducer->set_speed(1.0);
m_mltConsumer->set("refresh", 1);
@@ -1797,7 +1818,6 @@ bool Render::playZone(const GenTime & startTime, const GenTime & stopTime)
return false;
m_mltProducer->set("out", (int)(stopTime.frames(m_fps)));
m_mltProducer->seek((int)(startTime.frames(m_fps)));
- m_paused = false;
m_mltProducer->set_speed(1.0);
if (m_mltConsumer->is_stopped()) m_mltConsumer->start();
m_mltConsumer->set("refresh", 1);
@@ -1836,12 +1856,12 @@ void Render::seekToFrameDiff(int diff)
void Render::refreshIfActive()
{
- if (!m_mltConsumer->is_stopped() && m_mltProducer && m_paused && m_isActive) m_refreshTimer.start();
+ if (!m_mltConsumer->is_stopped() && m_mltProducer && (playSpeed() == 0) && m_isActive) m_refreshTimer.start();
}
void Render::doRefresh()
{
- if (m_mltProducer && m_paused && m_isActive) m_refreshTimer.start();
+ if (m_mltProducer && (playSpeed() == 0) && m_isActive) m_refreshTimer.start();
}
void Render::refresh()
@@ -1863,7 +1883,7 @@ void Render::setDropFrames(bool show)
if (m_mltConsumer) {
int dropFrames = KdenliveSettings::mltthreads();
if (show == false) dropFrames = -dropFrames;
- m_mltConsumer->stop();
+ //m_mltConsumer->stop();
m_mltConsumer->set("real_time", dropFrames);
if (m_mltConsumer->start() == -1) {
qWarning() << "ERROR, Cannot start monitor";
@@ -1876,7 +1896,7 @@ void Render::setConsumerProperty(const QString &name, const QString &value)
{
QMutexLocker locker(&m_mutex);
if (m_mltConsumer) {
- m_mltConsumer->stop();
+ //m_mltConsumer->stop();
m_mltConsumer->set(name.toUtf8().constData(), value.toUtf8().constData());
if (m_isActive && m_mltConsumer->start() == -1) {
qWarning() << "ERROR, Cannot start monitor";
@@ -1888,7 +1908,7 @@ void Render::setConsumerProperty(const QString &name, const QString &value)
bool Render::isPlaying() const
{
if (!m_mltConsumer || m_mltConsumer->is_stopped()) return false;
- return !m_paused;
+ return playSpeed() != 0;
}
double Render::playSpeed() const
@@ -1933,13 +1953,27 @@ void Render::emitFrameNumber()
int currentPos = m_mltConsumer->position();
if (currentPos == requestedSeekPosition) {
requestedSeekPosition = SEEK_INACTIVE;
- m_paused = true;
}
emit rendererPosition(currentPos);
if (requestedSeekPosition != SEEK_INACTIVE) {
m_mltConsumer->purge();
m_mltProducer->seek(requestedSeekPosition);
- if (m_mltProducer->get_speed() == 0 && !m_paused) {
+ if (playSpeed() == 0) {
+ m_mltConsumer->set("refresh", 1);
+ }
+ requestedSeekPosition = SEEK_INACTIVE;
+ }
+}
+
+void Render::checkFrameNumber(int pos)
+{
+ if (pos == requestedSeekPosition) {
+ requestedSeekPosition = SEEK_INACTIVE;
+ }
+ if (requestedSeekPosition != SEEK_INACTIVE) {
+ m_mltConsumer->purge();
+ m_mltProducer->seek(requestedSeekPosition);
+ if (m_mltProducer->get_speed() == 0) {
m_mltConsumer->set("refresh", 1);
}
requestedSeekPosition = SEEK_INACTIVE;
@@ -1949,9 +1983,8 @@ void Render::emitFrameNumber()
void Render::emitConsumerStopped(bool forcePause)
{
// This is used to know when the playing stopped
- if (m_mltProducer && (forcePause || (!m_paused && m_mltProducer->get_speed() == 0))) {
+ if (m_mltProducer && (forcePause || (m_mltProducer->get_speed() == 0))) {
double pos = m_mltConsumer->position();
- m_paused = true;
if (m_isLoopMode) play(m_loopStart);
//else if (m_isZoneMode) resetZoneMode();
emit rendererStopped((int) pos);
@@ -1985,9 +2018,6 @@ void Render::slotCheckSeeking()
{
if (requestedSeekPosition != SEEK_INACTIVE) {
m_mltProducer->seek(requestedSeekPosition);
- if (m_paused) {
- refresh();
- }
requestedSeekPosition = SEEK_INACTIVE;
}
}
diff --git a/src/renderer.h b/src/renderer.h
index 877cc34..532a9f5 100644
--- a/src/renderer.h
+++ b/src/renderer.h
@@ -55,6 +55,7 @@
class KComboBox;
class BinController;
class ClipController;
+class GLWidget;
namespace Mlt
{
@@ -102,7 +103,7 @@ class Render: public AbstractRender
* @param rendererName A unique identifier for this renderer
* @param winid The parent widget identifier (required for SDL display). Set to 0 for OpenGL rendering
* @param profile The MLT profile used for the renderer (default one will be used if empty). */
- Render(Kdenlive::MonitorId rendererName, BinController *binController, int winid, QWidget *parent = 0);
+ Render(Kdenlive::MonitorId rendererName, BinController *binController, GLWidget *qmlView, QWidget *parent = 0);
/** @brief Destroy the MLT Renderer. */
virtual ~Render();
@@ -339,6 +340,9 @@ class Render: public AbstractRender
/** @brief Ask to set this monitor as active */
void setActiveMonitor();
+ /** @brief Renderer moved to a new frame, check seeking */
+ void checkFrameNumber(int pos);
+
QSemaphore showFrameSemaphore;
bool externalConsumer;
@@ -359,6 +363,7 @@ private:
Mlt::Event *m_showFrameEvent;
Mlt::Event *m_pauseEvent;
BinController *m_binController;
+ GLWidget *m_qmlView;
double m_fps;
/** @brief True if we are playing a zone.
@@ -385,7 +390,6 @@ private:
QLocale m_locale;
QFuture <void> m_infoThread;
QList <requestClipInfo> m_requestList;
- bool m_paused;
/** @brief True if this monitor is active. */
bool m_isActive;
@@ -399,7 +403,7 @@ private:
/** @brief Build the MLT Consumer object with initial settings.
* @param profileName The MLT profile to use for the consumer */
- void buildConsumer();
+ //void buildConsumer();
void resetZoneMode();
void fillSlowMotionProducers();
/** @brief Get the track number of the lowest audible (non muted) audio track
diff --git a/src/stopmotion/stopmotion.cpp b/src/stopmotion/stopmotion.cpp
index 8a9864b..3c53e60 100644
--- a/src/stopmotion/stopmotion.cpp
+++ b/src/stopmotion/stopmotion.cpp
@@ -307,7 +307,8 @@ StopmotionWidget::StopmotionWidget(MonitorManager *manager, const QUrl &projectF
profilePath = KdenliveSettings::current_profile();
}
- m_captureDevice = new MltDeviceCapture(profilePath, m_monitor->videoSurface, this);
+ //TODO:
+ //m_captureDevice = new MltDeviceCapture(profilePath, m_monitor->videoSurface, this);
m_captureDevice->sendFrameForAnalysis = KdenliveSettings::analyse_stopmotion();
m_monitor->setRender(m_captureDevice);
connect(m_captureDevice, SIGNAL(frameSaved(QString)), this, SLOT(slotNewThumb(QString)));
@@ -484,7 +485,8 @@ void StopmotionWidget::slotLive(bool isOn)
}
if (m_captureDevice == NULL) {
- m_captureDevice = new MltDeviceCapture(profilePath, m_monitor->videoSurface, this);
+ //TODO:
+ //m_captureDevice = new MltDeviceCapture(profilePath, m_monitor->videoSurface, this);
m_captureDevice->sendFrameForAnalysis = KdenliveSettings::analyse_stopmotion();
m_monitor->setRender(m_captureDevice);
connect(m_captureDevice, SIGNAL(frameSaved(QString)), this, SLOT(slotNewThumb(QString)));