1 /* 2 SPDX-FileCopyrightText: 2016 Jean-Baptiste Mardelle <jb@kdenlive.org> 3 4 SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 5 */ 6 7 #ifndef PREVIEWMANAGER_H 8 #define PREVIEWMANAGER_H 9 10 #include "definitions.h" 11 12 #include <QDir> 13 #include <QFuture> 14 #include <QMutex> 15 #include <QProcess> 16 #include <QTimer> 17 18 class TimelineController; 19 20 namespace Mlt { 21 class Tractor; 22 class Playlist; 23 class Producer; 24 } // namespace Mlt 25 26 /** @class PreviewManager 27 @brief Handles timeline preview. 28 This manager creates an additional video track on top of the current timeline and renders 29 chunks (small video files of 25 frames) that are added on this track when rendered. 30 This allow us to get a preview with a smooth playback of our project. 31 Only the preview zone is rendered. Once defined, a preview zone shows as a red line below 32 the timeline ruler. As chunks are rendered, the zone turns to green. 33 */ 34 class PreviewManager : public QObject 35 { 36 Q_OBJECT 37 38 public: 39 friend class TimelineController; 40 41 explicit PreviewManager(TimelineController *controller, Mlt::Tractor *tractor); 42 ~PreviewManager() override; 43 /** @brief: initialize base variables, return false if error. */ 44 bool initialize(); 45 /** @brief: a timeline operation caused changes to frames between startFrame and endFrame. */ 46 void invalidatePreview(int startFrame, int endFrame); 47 /** @brief: after a small delay (some operations trigger several invalidatePreview calls), take care of these invalidated chunks. */ 48 void invalidatePreviews(); 49 /** @brief: user adds current timeline zone to the preview zone. */ 50 void addPreviewRange(const QPoint zone, bool add); 51 /** @brief: Remove all existing previews. */ 52 void clearPreviewRange(bool resetZones); 53 /** @brief: stops current rendering process. */ 54 void abortRendering(); 55 /** @brief: rendering parameters have changed, reload them. */ 56 bool loadParams(); 57 /** @brief: Create the preview track if not existing. */ 58 bool buildPreviewTrack(); 59 /** @brief: Delete the preview track. */ 60 void deletePreviewTrack(); 61 /** @brief: Whenever we save or render our project, we remove the preview track so it is not saved. */ 62 void reconnectTrack(); 63 /** @brief: After project save or render, re-add our preview track. */ 64 void disconnectTrack(); 65 /** @brief: Returns directory currently used to store the preview files. */ 66 const QDir getCacheDir() const; 67 /** @brief: Load existing ruler chunks. */ 68 void loadChunks(QVariantList previewChunks, QVariantList dirtyChunks, const QDateTime &documentDate, Mlt::Playlist &playlist); 69 int setOverlayTrack(Mlt::Playlist *overlay); 70 /** @brief Remove the effect compare overlay track */ 71 void removeOverlayTrack(); 72 /** @brief The current preview chunk being processed, -1 if none */ 73 int workingPreview; 74 /** @brief Returns the list of existing chunks */ 75 QPair<QStringList, QStringList> previewChunks() const; 76 bool hasOverlayTrack() const; 77 bool hasPreviewTrack() const; 78 int addedTracks() const; 79 80 private: 81 TimelineController *m_controller; 82 Mlt::Tractor *m_tractor; 83 Mlt::Playlist *m_previewTrack; 84 Mlt::Playlist *m_overlayTrack; 85 int m_previewTrackIndex; 86 /** @brief: The kdenlive renderer app. */ 87 QString m_renderer; 88 /** @brief: The kdenlive timeline preview process. */ 89 QProcess m_previewProcess; 90 /** @brief: The directory used to store the preview files. */ 91 QDir m_cacheDir; 92 /** @brief: The directory used to store undo history of preview files (child of m_cacheDir). */ 93 QDir m_undoDir; 94 QMutex m_previewMutex; 95 QStringList m_consumerParams; 96 QString m_extension; 97 /** @brief: Timer used to autostart preview rendering. */ 98 QTimer m_previewTimer; 99 /** @brief: Since some timeline operations generate several invalidate calls, use a timer to get them all. */ 100 QTimer m_previewGatherTimer; 101 bool m_initialized; 102 QList<int> m_waitingThumbs; 103 QFuture<void> m_previewThread; 104 /** @brief: The count of chunks to process - to calculate job progress */ 105 int m_chunksToRender; 106 /** @brief: The count of already processed chunks - to calculate job progress */ 107 int m_processedChunks; 108 /** @brief: The render process output, useful in case of failure */ 109 QString m_errorLog; 110 /** @brief: After an undo/redo, if we have preview history, use it. */ 111 void reloadChunks(const QVariantList chunks); 112 /** @brief: A chunk failed to render, abort. */ 113 void corruptedChunk(int workingPreview, const QString &fileName); 114 /** @brief: Re-enable timeline preview track. */ 115 void enable(); 116 /** @brief: Temporarily disable timeline preview track. */ 117 void disable(); 118 119 private slots: 120 /** @brief: To avoid filling the hard drive, remove preview undo history after 5 steps. */ 121 void doCleanupOldPreviews(); 122 /** @brief: Start the real rendering process. */ 123 void doPreviewRender(const QString &scene); // std::shared_ptr<Mlt::Producer> sourceProd); 124 /** @brief: If user does an undo, then makes a new timeline operation, delete undo history of more recent stack . */ 125 void slotRemoveInvalidUndo(int ix); 126 /** @brief: When the timer collecting invalid zones is done, process. */ 127 void slotProcessDirtyChunks(); 128 /** @brief: Process preview rendering output. */ 129 void receivedStderr(); 130 void processEnded(int, QProcess::ExitStatus status); 131 132 public slots: 133 /** @brief: Prepare and start rendering. */ 134 void startPreviewRender(); 135 /** @brief: A chunk has been created, notify ruler. */ 136 void gotPreviewRender(int frame, const QString &file, int progress); 137 138 protected: 139 QVariantList m_renderedChunks; 140 QVariantList m_dirtyChunks; 141 mutable QMutex m_dirtyMutex; 142 143 signals: 144 void abortPreview(); 145 void cleanupOldPreviews(); 146 void previewRender(int frame, const QString &file, int progress); 147 }; 148 149 #endif 150