File indexing completed on 2024-05-19 04:55:08

0001 /*
0002     SPDX-FileCopyrightText: 2013-2016 Meltytech LLC
0003     SPDX-FileCopyrightText: 2013-2016 Dan Dennedy <dan@dennedy.org>
0004 
0005     SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0006 */
0007 
0008 #include "thumbnailprovider.h"
0009 #include "bin/projectclip.h"
0010 #include "bin/projectitemmodel.h"
0011 #include "core.h"
0012 #include "doc/kthumb.h"
0013 #include "utils/thumbnailcache.hpp"
0014 
0015 #include <QCryptographicHash>
0016 #include <QDebug>
0017 #include <mlt++/MltFilter.h>
0018 #include <mlt++/MltProfile.h>
0019 
0020 ThumbnailProvider::ThumbnailProvider()
0021     : QQuickImageProvider(QQmlImageProviderBase::Image, QQmlImageProviderBase::ForceAsynchronousImageLoading)
0022 {
0023 }
0024 
0025 ThumbnailProvider::~ThumbnailProvider() = default;
0026 
0027 QImage ThumbnailProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
0028 {
0029     QImage result;
0030     // id is binID/#frameNumber
0031     QString binId = id.section('/', 0, 0);
0032     bool ok;
0033     int frameNumber = id.section('#', -1).toInt(&ok);
0034     if (ok) {
0035         std::shared_ptr<ProjectClip> binClip = pCore->projectItemModel()->getClipByBinID(binId);
0036         if (binClip) {
0037             int duration = binClip->frameDuration();
0038             if (frameNumber > duration) {
0039                 // for endless loopable clips, we rewrite the position
0040                 frameNumber = frameNumber - ((frameNumber / duration) * duration);
0041             }
0042             result = ThumbnailCache::get()->getThumbnail(binClip->hashForThumbs(), binId, frameNumber);
0043             if (!result.isNull()) {
0044 
0045                 *size = result.size();
0046                 return result;
0047             }
0048             std::unique_ptr<Mlt::Producer> prod = binClip->getThumbProducer();
0049             if (prod && prod->is_valid()) {
0050                 result = makeThumbnail(std::move(prod), frameNumber, requestedSize);
0051                 ThumbnailCache::get()->storeThumbnail(binId, frameNumber, result, false);
0052             }
0053         }
0054     }
0055     if (size) *size = result.size();
0056     return result;
0057 }
0058 
0059 QImage ThumbnailProvider::makeThumbnail(std::unique_ptr<Mlt::Producer> producer, int frameNumber, const QSize &requestedSize)
0060 {
0061     Q_UNUSED(requestedSize)
0062     producer->seek(frameNumber);
0063     std::unique_ptr<Mlt::Frame> frame(producer->get_frame());
0064     if (frame == nullptr || !frame->is_valid()) {
0065         return QImage();
0066     }
0067     // TODO: cache these values ?
0068     frame->set("consumer.deinterlacer", "onefield");
0069     frame->set("consumer.top_field_first", -1);
0070     frame->set("consumer.rescale", "nearest");
0071     int imageHeight = pCore->thumbProfile().height();
0072     int imageWidth = pCore->thumbProfile().width();
0073     int fullWidth = qRound(imageHeight * pCore->getCurrentDar());
0074     return KThumb::getFrame(frame.get(), imageWidth, imageHeight, fullWidth);
0075 }