updated exporter to work with new frame flow
This commit is contained in:
@@ -96,7 +96,7 @@ void Encoder::Open()
|
||||
}
|
||||
}
|
||||
|
||||
void Encoder::Write(FramePtr frame)
|
||||
void Encoder::WriteFrame(FramePtr frame)
|
||||
{
|
||||
if (open_) {
|
||||
WriteInternal(frame);
|
||||
|
||||
+3
-1
@@ -61,7 +61,7 @@ public:
|
||||
|
||||
public slots:
|
||||
void Open();
|
||||
void Write(FramePtr frame);
|
||||
void WriteFrame(FramePtr frame);
|
||||
virtual void WriteAudio(const AudioRenderingParams& pcm_info, const QString& pcm_filename) = 0;
|
||||
void Close();
|
||||
|
||||
@@ -71,6 +71,8 @@ signals:
|
||||
|
||||
void Closed();
|
||||
|
||||
void AudioComplete();
|
||||
|
||||
protected:
|
||||
virtual bool OpenInternal() = 0;
|
||||
virtual void WriteInternal(FramePtr frame) = 0;
|
||||
|
||||
@@ -89,6 +89,8 @@ void FFmpegEncoder::WriteAudio(const AudioRenderingParams &pcm_info, const QStri
|
||||
|
||||
pcm.close();
|
||||
}
|
||||
|
||||
emit AudioComplete();
|
||||
}
|
||||
|
||||
bool FFmpegEncoder::OpenInternal()
|
||||
|
||||
@@ -20,7 +20,9 @@ Exporter::Exporter(ViewerOutput* viewer,
|
||||
color_processor_(color_processor),
|
||||
encoder_(encoder),
|
||||
export_status_(false),
|
||||
export_msg_(tr("Export hasn't started yet"))
|
||||
export_msg_(tr("Export hasn't started yet")),
|
||||
video_done_(false),
|
||||
audio_done_(false)
|
||||
{
|
||||
connect(this, &Exporter::ExportEnded, this, &Exporter::deleteLater);
|
||||
}
|
||||
@@ -53,20 +55,16 @@ void Exporter::StartExporting()
|
||||
video_params_.time_base(),
|
||||
video_params_.format(),
|
||||
video_params_.mode()));
|
||||
video_backend_->SetExportMode(true);
|
||||
audio_backend_->SetViewerNode(viewer_node_);
|
||||
audio_backend_->SetParameters(audio_params_);
|
||||
|
||||
// Connect to renderers
|
||||
connect(video_backend_, &VideoRenderBackend::CachedFrameReady, this, &Exporter::FrameRendered);
|
||||
connect(audio_backend_, &AudioRenderBackend::QueueComplete, this, &Exporter::AudioRendered);
|
||||
|
||||
// Create renderers
|
||||
waiting_for_frame_ = 0;
|
||||
|
||||
// Open encoder and wait for result
|
||||
connect(encoder_, &Encoder::OpenSucceeded, this, &Exporter::EncoderOpenedSuccessfully, Qt::QueuedConnection);
|
||||
connect(encoder_, &Encoder::OpenFailed, this, &Exporter::EncoderOpenFailed, Qt::QueuedConnection);
|
||||
connect(encoder_, &Encoder::AudioComplete, this, &Exporter::AudioEncodeComplete, Qt::QueuedConnection);
|
||||
connect(encoder_, &Encoder::Closed, encoder_, &Encoder::deleteLater, Qt::QueuedConnection);
|
||||
|
||||
QMetaObject::invokeMethod(encoder_,
|
||||
@@ -81,6 +79,10 @@ void Exporter::SetExportMessage(const QString &s)
|
||||
|
||||
void Exporter::ExportSucceeded()
|
||||
{
|
||||
if (!audio_done_ || !video_done_) {
|
||||
return;
|
||||
}
|
||||
|
||||
Cleanup();
|
||||
|
||||
video_backend_->deleteLater();
|
||||
@@ -99,10 +101,8 @@ void Exporter::ExportFailed()
|
||||
emit ExportEnded();
|
||||
}
|
||||
|
||||
void Exporter::FrameRendered(const rational &time, QVariant value)
|
||||
void Exporter::EncodeFrame(const rational &time, QVariant value)
|
||||
{
|
||||
qDebug() << "Received" << time.toDouble() << "- waiting for" << waiting_for_frame_.toDouble();
|
||||
|
||||
if (time == waiting_for_frame_) {
|
||||
bool get_cached = false;
|
||||
|
||||
@@ -132,7 +132,7 @@ void Exporter::FrameRendered(const rational &time, QVariant value)
|
||||
|
||||
// Encode (may require re-associating alpha?)
|
||||
QMetaObject::invokeMethod(encoder_,
|
||||
"Write",
|
||||
"WriteFrame",
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(FramePtr, frame));
|
||||
|
||||
@@ -145,6 +145,8 @@ void Exporter::FrameRendered(const rational &time, QVariant value)
|
||||
} while (cached_frames_.contains(waiting_for_frame_));
|
||||
|
||||
if (waiting_for_frame_ >= viewer_node_->Length()) {
|
||||
video_done_ = true;
|
||||
|
||||
ExportSucceeded();
|
||||
}
|
||||
} else {
|
||||
@@ -152,6 +154,23 @@ void Exporter::FrameRendered(const rational &time, QVariant value)
|
||||
}
|
||||
}
|
||||
|
||||
void Exporter::FrameRendered(const rational &time, QVariant value)
|
||||
{
|
||||
qDebug() << "Received" << time.toDouble() << "- waiting for" << waiting_for_frame_.toDouble();
|
||||
|
||||
const QMap<rational, QByteArray>& time_hash_map = video_backend_->frame_cache()->time_hash_map();
|
||||
|
||||
QByteArray map_hash = time_hash_map.value(time);
|
||||
|
||||
EncodeFrame(time, value);
|
||||
|
||||
QList<rational> matching_times = matched_frames_.value(map_hash);
|
||||
foreach (const rational& t, matching_times) {
|
||||
qDebug() << " Also matches" << t;
|
||||
EncodeFrame(t, value);
|
||||
}
|
||||
}
|
||||
|
||||
void Exporter::AudioRendered()
|
||||
{
|
||||
// Retrieve the audio filename
|
||||
@@ -167,14 +186,28 @@ void Exporter::AudioRendered()
|
||||
audio_backend_->deleteLater();
|
||||
}
|
||||
|
||||
void Exporter::AudioEncodeComplete()
|
||||
{
|
||||
audio_done_ = true;
|
||||
|
||||
ExportSucceeded();
|
||||
}
|
||||
|
||||
void Exporter::EncoderOpenedSuccessfully()
|
||||
{
|
||||
// Invalidate caches
|
||||
if (encoder_->params().video_enabled()) {
|
||||
// First we generate the hashes so we know exactly how many frames we need
|
||||
video_backend_->SetOperatingMode(VideoRenderWorker::kHashOnly);
|
||||
connect(video_backend_, &VideoRenderBackend::QueueComplete, this, &Exporter::VideoHashesComplete);
|
||||
|
||||
video_backend_->InvalidateCache(0, viewer_node_->Length());
|
||||
}
|
||||
|
||||
if (encoder_->params().audio_enabled()) {
|
||||
// We set the audio backend to render the full sequence to the disk
|
||||
connect(audio_backend_, &AudioRenderBackend::QueueComplete, this, &Exporter::AudioRendered);
|
||||
|
||||
audio_backend_->InvalidateCache(0, viewer_node_->Length());
|
||||
}
|
||||
}
|
||||
@@ -190,3 +223,49 @@ void Exporter::EncoderClosed()
|
||||
emit ProgressChanged(100);
|
||||
emit ExportEnded();
|
||||
}
|
||||
|
||||
void Exporter::VideoHashesComplete()
|
||||
{
|
||||
// We've got our hashes, time to kick off actual rendering
|
||||
disconnect(video_backend_, &VideoRenderBackend::QueueComplete, this, &Exporter::VideoHashesComplete);
|
||||
|
||||
// Determine what frames will be hashed
|
||||
TimeRangeList ranges;
|
||||
ranges.append(TimeRange(0, viewer_node_->Length()));
|
||||
|
||||
QMap<rational, QByteArray>::const_iterator i;
|
||||
QMap<rational, QByteArray>::iterator j;
|
||||
|
||||
// Copy time hash map
|
||||
QMap<rational, QByteArray> time_hash_map = video_backend_->frame_cache()->time_hash_map();
|
||||
|
||||
// Check for any times that share duplicate hashes
|
||||
for (i=time_hash_map.begin();i!=time_hash_map.end();i++) {
|
||||
j = time_hash_map.begin();
|
||||
|
||||
while (j != time_hash_map.end()) {
|
||||
if (i != j && i.value() == j.value()) {
|
||||
// Remove the time range from this and
|
||||
ranges.RemoveTimeRange(TimeRange(j.key(), j.key() + video_backend_->params().time_base()));
|
||||
|
||||
QList<rational> times_with_this_hash = matched_frames_.value(i.value());
|
||||
times_with_this_hash.append(j.key());
|
||||
matched_frames_.insert(i.value(), times_with_this_hash);
|
||||
|
||||
j = time_hash_map.erase(j);
|
||||
} else {
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set video backend to render mode but NOT hash or download
|
||||
video_backend_->SetOperatingMode(VideoRenderWorker::kRenderOnly);
|
||||
video_backend_->SetOnlySignalLastFrameRequested(false);
|
||||
|
||||
connect(video_backend_, &VideoRenderBackend::CachedFrameReady, this, &Exporter::FrameRendered);
|
||||
|
||||
foreach (const TimeRange& range, ranges) {
|
||||
video_backend_->InvalidateCache(range.in(), range.out());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,6 +61,8 @@ private:
|
||||
|
||||
void ExportFailed();
|
||||
|
||||
void EncodeFrame(const rational &time, QVariant value);
|
||||
|
||||
ColorProcessorPtr color_processor_;
|
||||
|
||||
Encoder* encoder_;
|
||||
@@ -73,17 +75,27 @@ private:
|
||||
|
||||
QHash<rational, QVariant> cached_frames_;
|
||||
|
||||
QHash< QByteArray, QList<rational> > matched_frames_;
|
||||
|
||||
bool video_done_;
|
||||
|
||||
bool audio_done_;
|
||||
|
||||
private slots:
|
||||
void FrameRendered(const rational& time, QVariant value);
|
||||
|
||||
void AudioRendered();
|
||||
|
||||
void AudioEncodeComplete();
|
||||
|
||||
void EncoderOpenedSuccessfully();
|
||||
|
||||
void EncoderOpenFailed();
|
||||
|
||||
void EncoderClosed();
|
||||
|
||||
void VideoHashesComplete();
|
||||
|
||||
};
|
||||
|
||||
#endif // EXPORTER_H
|
||||
|
||||
@@ -141,7 +141,7 @@ void OpenGLBackend::DecompileInternal()
|
||||
shader_cache_.Clear();
|
||||
}
|
||||
|
||||
void OpenGLBackend::EmitCachedFrameReady(const QList<rational> ×, const QVariant &value, qint64 job_time)
|
||||
void OpenGLBackend::EmitCachedFrameReady(const rational &time, const QVariant &value, qint64 job_time)
|
||||
{
|
||||
OpenGLTextureCache::ReferencePtr ref = value.value<OpenGLTextureCache::ReferencePtr>();
|
||||
OpenGLTexturePtr tex;
|
||||
@@ -152,9 +152,7 @@ void OpenGLBackend::EmitCachedFrameReady(const QList<rational> ×, const QVa
|
||||
tex = nullptr;
|
||||
}
|
||||
|
||||
foreach (const rational& t, times) {
|
||||
emit CachedFrameReady(t, QVariant::fromValue(tex), job_time);
|
||||
}
|
||||
emit CachedFrameReady(time, QVariant::fromValue(tex), job_time);
|
||||
}
|
||||
|
||||
OpenGLTexturePtr OpenGLBackend::CopyTexture(OpenGLTexturePtr input)
|
||||
|
||||
@@ -28,7 +28,7 @@ protected:
|
||||
|
||||
virtual void DecompileInternal() override;
|
||||
|
||||
virtual void EmitCachedFrameReady(const QList<rational> ×, const QVariant& value, qint64 job_time) override;
|
||||
virtual void EmitCachedFrameReady(const rational &time, const QVariant& value, qint64 job_time) override;
|
||||
|
||||
private:
|
||||
OpenGLTexturePtr CopyTexture(OpenGLTexturePtr input);
|
||||
|
||||
@@ -237,7 +237,10 @@ void RenderBackend::CacheNext()
|
||||
}
|
||||
|
||||
if (cache_queue_.isEmpty()) {
|
||||
emit QueueComplete();
|
||||
if (AllProcessorsAreAvailable()) {
|
||||
emit QueueComplete();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -89,6 +89,7 @@ protected:
|
||||
|
||||
void QueueValueUpdate();
|
||||
|
||||
bool AllProcessorsAreAvailable() const;
|
||||
bool WorkerIsBusy(RenderWorker* worker) const;
|
||||
void SetWorkerBusyState(RenderWorker* worker, bool busy);
|
||||
|
||||
@@ -104,8 +105,6 @@ protected slots:
|
||||
void QueueRecompile();
|
||||
|
||||
private:
|
||||
bool AllProcessorsAreAvailable() const;
|
||||
|
||||
/**
|
||||
* @brief Internal list of RenderProcessThreads
|
||||
*/
|
||||
|
||||
@@ -33,7 +33,8 @@
|
||||
|
||||
VideoRenderBackend::VideoRenderBackend(QObject *parent) :
|
||||
RenderBackend(parent),
|
||||
export_mode_(false)
|
||||
operating_mode_(VideoRenderWorker::kHashRenderCache),
|
||||
only_signal_last_frame_requested_(true)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -71,12 +72,15 @@ const VideoRenderingParams &VideoRenderBackend::params() const
|
||||
|
||||
void VideoRenderBackend::SetParameters(const VideoRenderingParams& params)
|
||||
{
|
||||
if (!AllProcessorsAreAvailable()) {
|
||||
qCritical() << "Attempted to set parameters on a backend whose workers are still busy";
|
||||
return;
|
||||
}
|
||||
|
||||
// Set new parameters
|
||||
params_ = params;
|
||||
|
||||
// Set params on all processors
|
||||
// FIXME: Undefined behavior if the processors are currently working, this may need to be delayed like the
|
||||
// recompile signal
|
||||
foreach (RenderWorker* worker, processors_) {
|
||||
static_cast<VideoRenderWorker*>(worker)->SetParameters(params_);
|
||||
}
|
||||
@@ -85,9 +89,23 @@ void VideoRenderBackend::SetParameters(const VideoRenderingParams& params)
|
||||
RegenerateCacheID();
|
||||
}
|
||||
|
||||
void VideoRenderBackend::SetExportMode(bool enabled)
|
||||
void VideoRenderBackend::SetOperatingMode(const VideoRenderWorker::OperatingMode &mode)
|
||||
{
|
||||
export_mode_ = enabled;
|
||||
if (!AllProcessorsAreAvailable()) {
|
||||
qCritical() << "Attempted to set operating mode on a backend whose workers are still busy";
|
||||
return;
|
||||
}
|
||||
|
||||
operating_mode_ = mode;
|
||||
|
||||
foreach (RenderWorker* worker, processors_) {
|
||||
static_cast<VideoRenderWorker*>(worker)->SetOperatingMode(operating_mode_);
|
||||
}
|
||||
}
|
||||
|
||||
void VideoRenderBackend::SetOnlySignalLastFrameRequested(bool enabled)
|
||||
{
|
||||
only_signal_last_frame_requested_ = enabled;
|
||||
}
|
||||
|
||||
bool VideoRenderBackend::IsRendered(const rational &time) const
|
||||
@@ -121,6 +139,8 @@ void VideoRenderBackend::ConnectWorkerToThis(RenderWorker *processor)
|
||||
{
|
||||
VideoRenderWorker* video_processor = static_cast<VideoRenderWorker*>(processor);
|
||||
|
||||
video_processor->SetOperatingMode(operating_mode_);
|
||||
|
||||
connect(video_processor, &VideoRenderWorker::CompletedFrame, this, &VideoRenderBackend::ThreadCompletedFrame);
|
||||
connect(video_processor, &VideoRenderWorker::HashAlreadyBeingCached, this, &VideoRenderBackend::ThreadSkippedFrame);
|
||||
connect(video_processor, &VideoRenderWorker::CompletedDownload, this, &VideoRenderBackend::ThreadCompletedDownload);
|
||||
@@ -206,8 +226,15 @@ TimeRange VideoRenderBackend::PopNextFrameFromQueue()
|
||||
|
||||
void VideoRenderBackend::ThreadCompletedFrame(NodeDependency path, qint64 job_time, QByteArray hash, QVariant value)
|
||||
{
|
||||
if (last_time_requested_ == path.in() || frame_cache_.TimeToHash(last_time_requested_) == hash) {
|
||||
EmitCachedFrameReady({last_time_requested_}, value, job_time);
|
||||
if (!only_signal_last_frame_requested_ || last_time_requested_ == path.in() || frame_cache_.TimeToHash(last_time_requested_) == hash) {
|
||||
EmitCachedFrameReady(path.in(), value, job_time);
|
||||
}
|
||||
|
||||
if (!(operating_mode_ & VideoRenderWorker::kDownloadOnly)) {
|
||||
// If we're not downloading, the worker is done here
|
||||
SetWorkerBusyState(static_cast<RenderWorker*>(sender()), false);
|
||||
|
||||
CacheNext();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "render/pixelformat.h"
|
||||
#include "render/rendermodes.h"
|
||||
#include "videorenderframecache.h"
|
||||
#include "videorenderworker.h"
|
||||
|
||||
/**
|
||||
* @brief A multithreaded OpenGL based renderer for node systems
|
||||
@@ -53,10 +54,16 @@ public:
|
||||
*/
|
||||
void SetParameters(const VideoRenderingParams ¶ms);
|
||||
|
||||
void SetExportMode(bool enabled);
|
||||
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
|
||||
@@ -85,10 +92,6 @@ protected:
|
||||
|
||||
virtual TimeRange PopNextFrameFromQueue() override;
|
||||
|
||||
VideoRenderFrameCache* frame_cache();
|
||||
|
||||
const VideoRenderingParams& params() const;
|
||||
|
||||
/**
|
||||
* @brief Internal function for generating the cache ID
|
||||
*/
|
||||
@@ -98,9 +101,9 @@ protected:
|
||||
|
||||
virtual void ConnectWorkerToThis(RenderWorker* processor) override;
|
||||
|
||||
virtual void EmitCachedFrameReady(const QList<rational> ×, const QVariant& value, qint64 job_time) = 0;
|
||||
virtual void EmitCachedFrameReady(const rational &time, const QVariant& value, qint64 job_time) = 0;
|
||||
|
||||
bool export_mode_;
|
||||
VideoRenderWorker::OperatingMode operating_mode_;
|
||||
|
||||
signals:
|
||||
void CachedFrameReady(const rational& time, QVariant value, qint64 job_time);
|
||||
@@ -121,6 +124,8 @@ private:
|
||||
|
||||
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);
|
||||
|
||||
@@ -109,6 +109,11 @@ QList<rational> VideoRenderFrameCache::FramesWithHash(const QByteArray &hash)
|
||||
return times;
|
||||
}
|
||||
|
||||
const QMap<rational, QByteArray> &VideoRenderFrameCache::time_hash_map() const
|
||||
{
|
||||
return time_hash_map_;
|
||||
}
|
||||
|
||||
QString VideoRenderFrameCache::CachePathName(const QByteArray &hash) const
|
||||
{
|
||||
QDir this_cache_dir = QDir(GetMediaCacheLocation()).filePath(cache_id_);
|
||||
|
||||
@@ -45,6 +45,8 @@ public:
|
||||
|
||||
QList<rational> FramesWithHash(const QByteArray& hash);
|
||||
|
||||
const QMap<rational, QByteArray>& time_hash_map() const;
|
||||
|
||||
private:
|
||||
QMap<rational, QByteArray> time_hash_map_;
|
||||
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
|
||||
VideoRenderWorker::VideoRenderWorker(VideoRenderFrameCache *frame_cache, QObject *parent) :
|
||||
RenderWorker(parent),
|
||||
frame_cache_(frame_cache)
|
||||
frame_cache_(frame_cache),
|
||||
operating_mode_(kHashRenderCache)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -22,16 +23,27 @@ NodeValueTable VideoRenderWorker::RenderInternal(const NodeDependency& path, con
|
||||
{
|
||||
// Get hash of node graph
|
||||
// We use SHA-1 for speed (benchmarks show it's the fastest hash available to us)
|
||||
QCryptographicHash hasher(QCryptographicHash::Sha1);
|
||||
HashNodeRecursively(&hasher, path.node(), path.in());
|
||||
QByteArray hash = hasher.result();
|
||||
QByteArray hash;
|
||||
if (operating_mode_ & kHashOnly) {
|
||||
QCryptographicHash hasher(QCryptographicHash::Sha1);
|
||||
HashNodeRecursively(&hasher, path.node(), path.in());
|
||||
hash = hasher.result();
|
||||
}
|
||||
|
||||
NodeValueTable value;
|
||||
|
||||
if (frame_cache_->HasHash(hash)) {
|
||||
if (!(operating_mode_ & kRenderOnly)) {
|
||||
|
||||
// Emit only the hash
|
||||
emit CompletedDownload(path, job_time, hash);
|
||||
|
||||
} else if ((operating_mode_ & kHashOnly) && frame_cache_->HasHash(hash)) {
|
||||
|
||||
// We've already cached this hash, no need to continue
|
||||
emit HashAlreadyExists(path, job_time, hash);
|
||||
} else if (frame_cache_->TryCache(path.in(), hash)) {
|
||||
|
||||
} else if (!(operating_mode_ & kHashOnly) || frame_cache_->TryCache(path.in(), hash)) {
|
||||
|
||||
// This hash is available for us to cache, start traversing graph
|
||||
value = ProcessNode(path);
|
||||
|
||||
@@ -42,17 +54,22 @@ NodeValueTable VideoRenderWorker::RenderInternal(const NodeDependency& path, con
|
||||
emit CompletedFrame(path, job_time, hash, texture);
|
||||
|
||||
// If we actually have a texture, download it into the disk cache
|
||||
if (!texture.isNull()) {
|
||||
if ((operating_mode_ & kDownloadOnly) && !texture.isNull()) {
|
||||
Download(path, hash, texture, frame_cache_->CachePathName(hash));
|
||||
}
|
||||
|
||||
frame_cache_->RemoveHashFromCurrentlyCaching(hash);
|
||||
|
||||
// Signal that this job is complete
|
||||
emit CompletedDownload(path, job_time, hash);
|
||||
if (operating_mode_ & kDownloadOnly) {
|
||||
// Signal that this job is complete
|
||||
emit CompletedDownload(path, job_time, hash);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// Another thread must be caching this already, nothing to be done
|
||||
emit HashAlreadyBeingCached(path, job_time, hash);
|
||||
|
||||
}
|
||||
|
||||
return value;
|
||||
@@ -161,6 +178,11 @@ void VideoRenderWorker::SetParameters(const VideoRenderingParams &video_params)
|
||||
ParametersChangedEvent();
|
||||
}
|
||||
|
||||
void VideoRenderWorker::SetOperatingMode(const VideoRenderWorker::OperatingMode &mode)
|
||||
{
|
||||
operating_mode_ = mode;
|
||||
}
|
||||
|
||||
bool VideoRenderWorker::InitInternal()
|
||||
{
|
||||
download_buffer_.resize(PixelService::GetBufferSize(video_params().format(), video_params().effective_width(), video_params().effective_height()));
|
||||
|
||||
@@ -12,10 +12,41 @@
|
||||
class VideoRenderWorker : public RenderWorker {
|
||||
Q_OBJECT
|
||||
public:
|
||||
/**
|
||||
* @brief VideoRenderWorker uses hashes to recognize frames that are identical to others in the render queue
|
||||
*
|
||||
* This mode can modify the behavior of the worker, either to disable hash verification or only generate hashes and
|
||||
* not render. These are only used in the context of exporting.
|
||||
*
|
||||
* These are also flags that can be or'd together, mostly for the convenience of checking which functionalities are
|
||||
* disabled and enabled.
|
||||
*/
|
||||
enum OperatingMode {
|
||||
/// Generate hashes but don't render or download anything
|
||||
kHashOnly = 0x1,
|
||||
|
||||
/// Render but don't download or hash
|
||||
kRenderOnly = 0x2,
|
||||
|
||||
/// Enable download (NEVER USE THIS ON ITS OWN, this is only here for checking flags, download-only mode makes no sense)
|
||||
kDownloadOnly = 0x4,
|
||||
|
||||
/// Use hash verification and render, but don't cache any frames to disk
|
||||
kHashAndRenderOnly = 0x3,
|
||||
|
||||
/// Render and download, but don't use hash verification
|
||||
kRenderAndCacheOnly = 0x6,
|
||||
|
||||
/// Render and use hashes to identify exact matches (default)
|
||||
kHashRenderCache = 0x7
|
||||
};
|
||||
|
||||
VideoRenderWorker(VideoRenderFrameCache* frame_cache, QObject* parent = nullptr);
|
||||
|
||||
void SetParameters(const VideoRenderingParams& video_params);
|
||||
|
||||
void SetOperatingMode(const OperatingMode& mode);
|
||||
|
||||
signals:
|
||||
void CompletedFrame(NodeDependency path, qint64 job_time, QByteArray hash, QVariant value);
|
||||
|
||||
@@ -57,6 +88,8 @@ private:
|
||||
|
||||
QByteArray download_buffer_;
|
||||
|
||||
OperatingMode operating_mode_;
|
||||
|
||||
private slots:
|
||||
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user