Files
oak-editor/app/render/backend/videorenderbackend.h
T
itsmattkc 1c5d55012b video renderer will always render frames closest to the playhead first
A few commits ago, the render behavior was changed to only render within a
user-specified range of the playhead. This works well, but it would still
render from the start of the range (usually before the playhead) to the end,
meaning it couldn't keep up with the playhead as well as it should. This
commit prioritizes frames close to the playhead and renders outwards to
address this.
2020-01-12 01:14:56 +11:00

150 lines
4.3 KiB
C++

/***
Olive - Non-Linear Video Editor
Copyright (C) 2019 Olive Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#ifndef VIDEORENDERERBACKEND_H
#define VIDEORENDERERBACKEND_H
#include <QLinkedList>
#include "colorprocessorcache.h"
#include "node/output/viewer/viewer.h"
#include "renderbackend.h"
#include "render/pixelformat.h"
#include "render/rendermodes.h"
#include "videorenderframecache.h"
#include "videorenderworker.h"
/**
* @brief A multithreaded OpenGL based renderer for node systems
*/
class VideoRenderBackend : public RenderBackend
{
Q_OBJECT
public:
/**
* @brief Renderer Constructor
*
* Constructing a Renderer object will not start any threads/backend on its own. Use Start() to do this and Stop()
* when the Renderer is about to be destroyed.
*/
VideoRenderBackend(QObject* parent = nullptr);
/**
* @brief Set parameters of the Renderer
*
* The Renderer owns the buffers that are used in the rendering process and this function sets the kind of buffers
* to use. The Renderer must be stopped when calling this function.
*/
void SetParameters(const VideoRenderingParams &params);
void SetOperatingMode(const VideoRenderWorker::OperatingMode& mode);
void SetOnlySignalLastFrameRequested(bool enabled);
bool IsRendered(const rational& time) const;
VideoRenderFrameCache* frame_cache();
const VideoRenderingParams& params() const;
protected:
/**
* @brief Allocate and start the multithreaded backend
*/
virtual bool InitInternal() override;
/**
* @brief Terminate and deallocate the multithreaded backend
*/
virtual void CloseInternal() override;
struct HashTimeMapping {
rational time;
QByteArray hash;
};
virtual void ConnectViewer(ViewerOutput* node) override;
virtual void DisconnectViewer(ViewerOutput* node) override;
const char *GetCachedFrame(const rational& time);
virtual NodeInput* GetDependentInput() override;
virtual bool CanRender() override;
virtual TimeRange PopNextFrameFromQueue() override;
/**
* @brief Internal function for generating the cache ID
*/
virtual bool GenerateCacheIDInternal(QCryptographicHash& hash) override;
virtual void CacheIDChangedEvent(const QString& id) override;
virtual void ConnectWorkerToThis(RenderWorker* processor) override;
virtual void EmitCachedFrameReady(const rational &time, const QVariant& value, qint64 job_time) = 0;
virtual void InvalidateCacheInternal(const rational &start_range, const rational &end_range) override;
VideoRenderWorker::OperatingMode operating_mode_;
signals:
void CachedFrameReady(const rational& time, QVariant value, qint64 job_time);
void CachedTimeReady(const rational& time, qint64 job_time);
void RangeInvalidated(const TimeRange& range);
private:
bool TimeIsQueued(const TimeRange &time) const;
bool JobIsCurrent(const NodeDependency &dep, const qint64& job_time) const;
bool SetFrameHash(const NodeDependency& dep, const QByteArray& hash, const qint64& job_time);
void Requeue();
VideoRenderingParams params_;
QByteArray cache_frame_load_buffer_;
VideoRenderFrameCache frame_cache_;
TimeRangeList invalidated_;
rational last_time_requested_;
bool only_signal_last_frame_requested_;
private slots:
void ThreadCompletedFrame(NodeDependency path, qint64 job_time, QByteArray hash, QVariant value);
void ThreadCompletedDownload(NodeDependency dep, qint64 job_time, QByteArray hash);
void ThreadSkippedFrame(NodeDependency dep, qint64 job_time, QByteArray hash);
void ThreadHashAlreadyExists(NodeDependency dep, qint64 job_time, QByteArray hash);
void TruncateFrameCacheLength(const rational& length);
void FrameRemovedFromDiskCache(const QByteArray& hash);
};
#endif // VIDEORENDERERBACKEND_H