Commit 0b4af095 authored by Jean-Baptiste Mardelle's avatar Jean-Baptiste Mardelle
Browse files

Extract frame: fix incorrect handling of sar!= 1 profiles and incorrect use of useSourceProfile

parent a51b140a
Pipeline #210641 passed with stage
in 11 minutes and 10 seconds
......@@ -50,7 +50,7 @@ QPixmap KThumb::getImage(const QUrl &url, int frame, int width, int height)
}
// static
QImage KThumb::getFrame(Mlt::Producer *producer, int framepos, int displayWidth, int height)
QImage KThumb::getFrame(Mlt::Producer *producer, int framepos, int width, int height, int displayWidth)
{
if (producer == nullptr || !producer->is_valid()) {
QImage p(displayWidth, height, QImage::Format_ARGB32_Premultiplied);
......@@ -65,13 +65,13 @@ QImage KThumb::getFrame(Mlt::Producer *producer, int framepos, int displayWidth,
producer->seek(framepos);
Mlt::Frame *frame = producer->get_frame();
const QImage p = getFrame(frame, displayWidth, height);
const QImage p = getFrame(frame, width, height, displayWidth);
delete frame;
return p;
}
// static
QImage KThumb::getFrame(Mlt::Producer &producer, int framepos, int displayWidth, int height)
QImage KThumb::getFrame(Mlt::Producer &producer, int framepos, int width, int height, int displayWidth)
{
if (!producer.is_valid()) {
QImage p(displayWidth, height, QImage::Format_ARGB32_Premultiplied);
......@@ -80,7 +80,7 @@ QImage KThumb::getFrame(Mlt::Producer &producer, int framepos, int displayWidth,
}
producer.seek(framepos);
Mlt::Frame *frame = producer.get_frame();
const QImage p = getFrame(frame, displayWidth, height);
const QImage p = getFrame(frame, width, height, displayWidth);
delete frame;
return p;
}
......
......@@ -18,8 +18,8 @@ class Frame;
namespace KThumb {
QPixmap getImage(const QUrl &url, int width, int height = -1);
QPixmap getImage(const QUrl &url, int frame, int width, int height = -1);
QImage getFrame(Mlt::Producer *producer, int framepos, int displayWidth, int height);
QImage getFrame(Mlt::Producer &producer, int framepos, int displayWidth, int height);
QImage getFrame(Mlt::Producer *producer, int framepos, int width, int height, int displayWidth = 0);
QImage getFrame(Mlt::Producer &producer, int framepos, int width, int height, int displayWidth = 0);
QImage getFrame(Mlt::Frame *frame, int width = 0, int height = 0, int scaledWidth = 0);
/** @brief Calculates image variance, useful to know if a thumbnail is interesting.
* @return an integer between 0 and 100. 0 means no variance, eg. black image while bigger values mean contrasted image
......
......@@ -1166,22 +1166,26 @@ void Monitor::slotExtractCurrentFrame(QString frameName, bool addToProject)
}
if (dlg->exec() == QDialog::Accepted) {
QString selectedFile = fileWidget->selectedFile();
bool useSourceResolution = b != nullptr && b->isChecked();
if (!selectedFile.isEmpty()) {
if (b != nullptr) {
KdenliveSettings::setExportframe_usingsourceres(b->isChecked());
KdenliveSettings::setExportframe_usingsourceres(useSourceResolution);
}
KRecentDirs::add(QStringLiteral(":KdenliveFramesFolder"), QUrl::fromLocalFile(selectedFile).adjusted(QUrl::RemoveFilename).toLocalFile());
// check if we are using a proxy
if ((m_controller != nullptr) && !m_controller->getProducerProperty(QStringLiteral("kdenlive:proxy")).isEmpty() &&
m_controller->getProducerProperty(QStringLiteral("kdenlive:proxy")) != QLatin1String("-")) {
// using proxy, use original clip url to get frame
// Clip monitor, using proxy. Use original clip url to get frame
QTemporaryFile src(QDir::temp().absoluteFilePath(QString("XXXXXX.mlt")));
if (src.open()) {
src.setAutoRemove(false);
m_controller->cloneProducerToFile(src.fileName());
const QStringList pathInfo = {src.fileName(), selectedFile, pCore->bin()->getCurrentFolder()};
QtConcurrent::run(m_glMonitor->getControllerProxy(), &MonitorProxy::extractFrameToFile, m_glMonitor->getCurrentPos(), pathInfo,
addToProject, b != nullptr ? b->isChecked() : false);
addToProject, useSourceResolution);
} else {
// TODO: warn user, cannot open tmp file
qDebug() << "Could not create temporary file";
}
return;
} else {
......@@ -1212,7 +1216,12 @@ void Monitor::slotExtractCurrentFrame(QString frameName, bool addToProject)
[this, proxiedClips, selectedFile, existingProxies, addToProject, analysisStatus, previewScale](const QImage &img) {
m_glMonitor->sendFrameForAnalysis = analysisStatus;
m_glMonitor->releaseAnalyse();
img.save(selectedFile);
if (pCore->getCurrentSar() != 1.) {
QImage scaled = img.scaled(pCore->getCurrentFrameDisplaySize());
scaled.save(selectedFile);
} else {
img.save(selectedFile);
}
if (previewScale > 0) {
KdenliveSettings::setPreviewScaling(previewScale);
m_glMonitor->updateScaling();
......@@ -1237,15 +1246,20 @@ void Monitor::slotExtractCurrentFrame(QString frameName, bool addToProject)
}
return;
} else {
QTemporaryFile src(QDir::temp().absoluteFilePath(QString("XXXXXX.mlt")));
if (src.open()) {
src.setAutoRemove(false);
m_controller->cloneProducerToFile(src.fileName());
const QStringList pathInfo = {src.fileName(), selectedFile, pCore->bin()->getCurrentFolder()};
QtConcurrent::run(m_glMonitor->getControllerProxy(), &MonitorProxy::extractFrameToFile, m_glMonitor->getCurrentPos(), pathInfo,
addToProject, b != nullptr ? b->isChecked() : false);
QStringList pathInfo;
if (useSourceResolution) {
// Create a producer with the original clip
QTemporaryFile src(QDir::temp().absoluteFilePath(QString("XXXXXX.mlt")));
if (src.open()) {
src.setAutoRemove(false);
m_controller->cloneProducerToFile(src.fileName());
pathInfo = QStringList({src.fileName(), selectedFile, pCore->bin()->getCurrentFolder()});
}
} else {
pathInfo = QStringList({QString(), selectedFile, pCore->bin()->getCurrentFolder()});
}
return;
QtConcurrent::run(m_glMonitor->getControllerProxy(), &MonitorProxy::extractFrameToFile, m_glMonitor->getCurrentPos(), pathInfo,
addToProject, useSourceResolution);
}
}
}
......
......@@ -222,13 +222,15 @@ void MonitorProxy::extractFrameToFile(int frame_position, const QStringList &pat
const QString path = pathInfo.at(0);
const QString destPath = pathInfo.at(1);
const QString folderInfo = pathInfo.at(2);
QSize finalSize = pCore->getCurrentFrameDisplaySize();
QSize size = pCore->getCurrentFrameSize();
QImage img;
int height = size.height();
int width = size.width();
if (!useSourceProfile) {
if (path.isEmpty() || !useSourceProfile) {
// Use current monitor producer to extract frame
Mlt::Frame *frame = q->m_producer->get_frame();
QImage img = KThumb::getFrame(frame, width, height);
QImage img = KThumb::getFrame(frame, width, height, finalSize.width());
delete frame;
img.save(destPath);
if (addToProject) {
......@@ -237,39 +239,42 @@ void MonitorProxy::extractFrameToFile(int frame_position, const QStringList &pat
}
return;
}
if (!path.isEmpty()) {
QScopedPointer<Mlt::Producer> producer;
QScopedPointer<Mlt::Profile> tmpProfile;
QScopedPointer<Mlt::Producer> producer;
QScopedPointer<Mlt::Profile> tmpProfile;
if (useSourceProfile) {
tmpProfile.reset(new Mlt::Profile());
producer.reset(new Mlt::Producer(*tmpProfile, path.toUtf8().constData()));
} else {
producer.reset(new Mlt::Producer(pCore->getCurrentProfile()->profile(), path.toUtf8().constData()));
}
if (producer && producer->is_valid()) {
if (useSourceProfile) {
tmpProfile.reset(new Mlt::Profile());
producer.reset(new Mlt::Producer(*tmpProfile, path.toUtf8().constData()));
} else {
producer.reset(new Mlt::Producer(pCore->getCurrentProfile()->profile(), path.toUtf8().constData()));
}
if (producer && producer->is_valid()) {
if (useSourceProfile) {
tmpProfile->from_producer(*producer);
width = tmpProfile->width();
height = tmpProfile->height();
double projectFps = pCore->getCurrentFps();
double currentFps = tmpProfile->fps();
if (!qFuzzyCompare(projectFps, currentFps)) {
frame_position = int(frame_position * currentFps / projectFps);
}
tmpProfile->from_producer(*producer);
width = tmpProfile->width();
height = tmpProfile->height();
if (tmpProfile->sar() != 1.) {
finalSize.setWidth(qRound(height * tmpProfile->dar()));
} else {
finalSize.setWidth(0);
}
QImage img = KThumb::getFrame(producer.data(), frame_position, width, height);
img.save(destPath);
if (addToProject) {
QMetaObject::invokeMethod(pCore->bin(), "droppedUrls", Q_ARG(const QList<QUrl> &, {QUrl::fromLocalFile(destPath)}),
Q_ARG(const QString &, folderInfo));
double projectFps = pCore->getCurrentFps();
double currentFps = tmpProfile->fps();
if (!qFuzzyCompare(projectFps, currentFps)) {
frame_position = int(frame_position * currentFps / projectFps);
}
} else {
qDebug() << "::: INVALID PRODUCER: " << path;
}
if (QDir::temp().exists(path)) {
// This was a temporary playlist file, remove
QFile::remove(path);
QImage img = KThumb::getFrame(producer.data(), frame_position, width, height, finalSize.width());
img.save(destPath);
if (addToProject) {
QMetaObject::invokeMethod(pCore->bin(), "droppedUrls", Q_ARG(const QList<QUrl> &, {QUrl::fromLocalFile(destPath)}),
Q_ARG(const QString &, folderInfo));
}
} else {
qDebug() << "::: INVALID PRODUCER: " << path;
}
if (QDir::temp().exists(path)) {
// This was a temporary playlist file, remove
QFile::remove(path);
}
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment