File indexing completed on 2024-05-05 04:22:01

0001 // SPDX-FileCopyrightText: 2012-2022 The KPhotoAlbum Development Team
0002 //
0003 // SPDX-License-Identifier: GPL-2.0-or-later
0004 
0005 #include "VideoThumbnails.h"
0006 
0007 #include "VideoLengthExtractor.h"
0008 
0009 #include <BackgroundJobs/ExtractOneThumbnailJob.h>
0010 #include <BackgroundJobs/HandleVideoThumbnailRequestJob.h>
0011 #include <BackgroundJobs/ReadVideoLengthJob.h>
0012 #include <BackgroundTaskManager/JobManager.h>
0013 #include <MainWindow/FeatureDialog.h>
0014 
0015 ImageManager::VideoThumbnails::VideoThumbnails(QObject *parent)
0016     : QObject(parent)
0017     , m_pendingRequest(false)
0018     , m_index(0)
0019 {
0020     m_cache.resize(10);
0021     m_activeRequests.reserve(10);
0022 }
0023 
0024 void ImageManager::VideoThumbnails::setVideoFile(const DB::FileName &fileName)
0025 {
0026     m_index = 0;
0027     m_videoFile = fileName;
0028     if (loadFramesFromCache(fileName))
0029         return;
0030 
0031     // no video thumbnails without ffmpeg:
0032     if (!MainWindow::FeatureDialog::hasVideoThumbnailer())
0033         return;
0034 
0035     if (!fileName.exists())
0036         return;
0037 
0038     cancelPreviousJobs();
0039     m_pendingRequest = false;
0040     for (int i = 0; i < 10; ++i)
0041         m_cache[i] = QImage();
0042 
0043     BackgroundJobs::ReadVideoLengthJob *lengthJob = new BackgroundJobs::ReadVideoLengthJob(fileName, BackgroundTaskManager::ForegroundCycleRequest);
0044 
0045     for (int i = 0; i < 10; ++i) {
0046         BackgroundJobs::ExtractOneThumbnailJob *extractJob = new BackgroundJobs::ExtractOneThumbnailJob(fileName, i, BackgroundTaskManager::ForegroundCycleRequest);
0047         extractJob->addDependency(lengthJob);
0048         connect(extractJob, &BackgroundJobs::ExtractOneThumbnailJob::completed, this, &VideoThumbnails::gotFrame);
0049         m_activeRequests.append(QPointer<BackgroundJobs::ExtractOneThumbnailJob>(extractJob));
0050     }
0051     BackgroundTaskManager::JobManager::instance()->addJob(lengthJob);
0052 }
0053 
0054 void ImageManager::VideoThumbnails::requestNext()
0055 {
0056     for (int i = 0; i < 10; ++i) {
0057         m_index = (m_index + 1) % 10;
0058         if (!m_cache[m_index].isNull()) {
0059             Q_EMIT frameLoaded(m_cache[m_index]);
0060             m_pendingRequest = false;
0061             return;
0062         }
0063     }
0064     m_pendingRequest = true;
0065 }
0066 
0067 void ImageManager::VideoThumbnails::gotFrame()
0068 {
0069     const BackgroundJobs::ExtractOneThumbnailJob *job = qobject_cast<BackgroundJobs::ExtractOneThumbnailJob *>(sender());
0070     const int index = job->index();
0071     const DB::FileName thumbnailFile = BackgroundJobs::HandleVideoThumbnailRequestJob::frameName(m_videoFile, index);
0072     m_cache[index] = QImage(thumbnailFile.absolute());
0073 
0074     if (m_pendingRequest) {
0075         m_index = index;
0076         Q_EMIT frameLoaded(m_cache[index]);
0077     }
0078 }
0079 
0080 bool ImageManager::VideoThumbnails::loadFramesFromCache(const DB::FileName &fileName)
0081 {
0082     for (int i = 0; i < 10; ++i) {
0083         const DB::FileName thumbnailFile = BackgroundJobs::HandleVideoThumbnailRequestJob::frameName(fileName, i);
0084         if (!thumbnailFile.exists())
0085             return false;
0086 
0087         QImage image(thumbnailFile.absolute());
0088         if (image.isNull())
0089             return false;
0090 
0091         m_cache[i] = image;
0092     }
0093     return true;
0094 }
0095 
0096 void ImageManager::VideoThumbnails::cancelPreviousJobs()
0097 {
0098     for (const QPointer<BackgroundJobs::ExtractOneThumbnailJob> &job : m_activeRequests) {
0099         if (!job.isNull())
0100             job->cancel();
0101     }
0102     m_activeRequests.clear();
0103 }
0104 // vi:expandtab:tabstop=4 shiftwidth=4:
0105 
0106 #include "moc_VideoThumbnails.cpp"