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 }