render: fix issue responding to cancelled tasks
This commit is contained in:
@@ -86,7 +86,7 @@ bool Decoder::Open(const CodecStream &stream)
|
||||
}
|
||||
}
|
||||
|
||||
TexturePtr Decoder::RetrieveVideo(Renderer *renderer, const rational &timecode, const RetrieveVideoParams ÷r, const QAtomicInt *cancelled)
|
||||
TexturePtr Decoder::RetrieveVideo(Renderer *renderer, const rational &timecode, const RetrieveVideoParams ÷r, CancelAtom *cancelled)
|
||||
{
|
||||
QMutexLocker locker(&mutex_);
|
||||
|
||||
@@ -102,7 +102,7 @@ TexturePtr Decoder::RetrieveVideo(Renderer *renderer, const rational &timecode,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (cancelled && *cancelled) {
|
||||
if (cancelled && cancelled->IsCancelled()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -160,7 +160,7 @@ void Decoder::Close()
|
||||
}
|
||||
}
|
||||
|
||||
bool Decoder::ConformAudio(const QVector<QString> &output_filenames, const AudioParams ¶ms, const QAtomicInt *cancelled)
|
||||
bool Decoder::ConformAudio(const QVector<QString> &output_filenames, const AudioParams ¶ms, CancelAtom *cancelled)
|
||||
{
|
||||
return ConformAudioInternal(output_filenames, params, cancelled);
|
||||
}
|
||||
@@ -264,7 +264,7 @@ int64_t Decoder::GetImageSequenceIndex(const QString &filename)
|
||||
return number_only.toLongLong();
|
||||
}
|
||||
|
||||
TexturePtr Decoder::RetrieveVideoInternal(Renderer *renderer, const rational &timecode, const RetrieveVideoParams ÷r, const QAtomicInt *cancelled)
|
||||
TexturePtr Decoder::RetrieveVideoInternal(Renderer *renderer, const rational &timecode, const RetrieveVideoParams ÷r, CancelAtom *cancelled)
|
||||
{
|
||||
Q_UNUSED(timecode)
|
||||
Q_UNUSED(divider)
|
||||
@@ -272,7 +272,7 @@ TexturePtr Decoder::RetrieveVideoInternal(Renderer *renderer, const rational &ti
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool Decoder::ConformAudioInternal(const QVector<QString> &filenames, const AudioParams ¶ms, const QAtomicInt* cancelled)
|
||||
bool Decoder::ConformAudioInternal(const QVector<QString> &filenames, const AudioParams ¶ms, CancelAtom *cancelled)
|
||||
{
|
||||
Q_UNUSED(filenames)
|
||||
Q_UNUSED(cancelled)
|
||||
|
||||
+5
-5
@@ -192,7 +192,7 @@ public:
|
||||
*
|
||||
* This function is thread safe and can only run while the decoder is open. \see Open()
|
||||
*/
|
||||
TexturePtr RetrieveVideo(Renderer *renderer, const rational& timecode, const RetrieveVideoParams& params, const QAtomicInt *cancelled = nullptr);
|
||||
TexturePtr RetrieveVideo(Renderer *renderer, const rational& timecode, const RetrieveVideoParams& params, CancelAtom *cancelled = nullptr);
|
||||
|
||||
enum RetrieveAudioStatus {
|
||||
kInvalid = -1,
|
||||
@@ -227,7 +227,7 @@ public:
|
||||
*
|
||||
* This function is re-entrant.
|
||||
*/
|
||||
virtual FootageDescription Probe(const QString& filename, const QAtomicInt* cancelled) const = 0;
|
||||
virtual FootageDescription Probe(const QString& filename, CancelAtom *cancelled) const = 0;
|
||||
|
||||
/**
|
||||
* @brief Closes media/deallocates memory
|
||||
@@ -239,7 +239,7 @@ public:
|
||||
/**
|
||||
* @brief Conform audio stream
|
||||
*/
|
||||
bool ConformAudio(const QVector<QString> &output_filenames, const AudioParams ¶ms, const QAtomicInt *cancelled = nullptr);
|
||||
bool ConformAudio(const QVector<QString> &output_filenames, const AudioParams ¶ms, CancelAtom *cancelled = nullptr);
|
||||
|
||||
/**
|
||||
* @brief Create a Decoder instance using a Decoder ID
|
||||
@@ -287,9 +287,9 @@ protected:
|
||||
* Sub-classes must override this function IF they support video. Function is already mutexed
|
||||
* so sub-classes don't need to worry about thread safety.
|
||||
*/
|
||||
virtual TexturePtr RetrieveVideoInternal(Renderer *renderer, const rational& timecode, const RetrieveVideoParams& params, const QAtomicInt *cancelled);
|
||||
virtual TexturePtr RetrieveVideoInternal(Renderer *renderer, const rational& timecode, const RetrieveVideoParams& params, CancelAtom *cancelled);
|
||||
|
||||
virtual bool ConformAudioInternal(const QVector<QString>& filenames, const AudioParams ¶ms, const QAtomicInt* cancelled);
|
||||
virtual bool ConformAudioInternal(const QVector<QString>& filenames, const AudioParams ¶ms, CancelAtom *cancelled);
|
||||
|
||||
void SignalProcessingProgress(int64_t ts, int64_t duration);
|
||||
|
||||
|
||||
@@ -141,10 +141,10 @@ bool FFmpegDecoder::OpenInternal()
|
||||
return output_frame;
|
||||
}*/
|
||||
|
||||
TexturePtr FFmpegDecoder::RetrieveVideoInternal(Renderer *renderer, const rational &timecode, const RetrieveVideoParams ¶ms, const QAtomicInt *cancelled)
|
||||
TexturePtr FFmpegDecoder::RetrieveVideoInternal(Renderer *renderer, const rational &timecode, const RetrieveVideoParams ¶ms, CancelAtom *cancelled)
|
||||
{
|
||||
if (AVFramePtr f = RetrieveFrame(timecode, cancelled)) {
|
||||
if (cancelled && *cancelled) {
|
||||
if (cancelled && cancelled->IsCancelled()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -289,7 +289,7 @@ QString FFmpegDecoder::id() const
|
||||
return QStringLiteral("ffmpeg");
|
||||
}
|
||||
|
||||
FootageDescription FFmpegDecoder::Probe(const QString &filename, const QAtomicInt *cancelled) const
|
||||
FootageDescription FFmpegDecoder::Probe(const QString &filename, CancelAtom *cancelled) const
|
||||
{
|
||||
// Return value
|
||||
FootageDescription desc(id());
|
||||
@@ -514,7 +514,7 @@ QString FFmpegDecoder::FFmpegError(int error_code)
|
||||
return QStringLiteral("%1 %2").arg(QString::number(error_code), err);
|
||||
}
|
||||
|
||||
bool FFmpegDecoder::ConformAudioInternal(const QVector<QString> &filenames, const AudioParams ¶ms, const QAtomicInt *cancelled)
|
||||
bool FFmpegDecoder::ConformAudioInternal(const QVector<QString> &filenames, const AudioParams ¶ms, CancelAtom *cancelled)
|
||||
{
|
||||
// Iterate through each audio frame and extract the PCM data
|
||||
|
||||
@@ -564,7 +564,7 @@ bool FFmpegDecoder::ConformAudioInternal(const QVector<QString> &filenames, cons
|
||||
|
||||
while (true) {
|
||||
// Check if we have a `cancelled` ptr and its value
|
||||
if (cancelled && *cancelled) {
|
||||
if (cancelled && cancelled->IsCancelled()) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -744,7 +744,7 @@ void FFmpegDecoder::ClearFrameCache()
|
||||
}
|
||||
}
|
||||
|
||||
AVFramePtr FFmpegDecoder::RetrieveFrame(const rational& time, const QAtomicInt *cancelled)
|
||||
AVFramePtr FFmpegDecoder::RetrieveFrame(const rational& time, CancelAtom *cancelled)
|
||||
{
|
||||
int64_t target_ts = GetTimeInTimebaseUnits(time, instance_.avstream()->time_base, instance_.avstream()->start_time);
|
||||
|
||||
@@ -782,7 +782,7 @@ AVFramePtr FFmpegDecoder::RetrieveFrame(const rational& time, const QAtomicInt *
|
||||
|
||||
while (true) {
|
||||
// Break out of loop if we've cancelled
|
||||
if (cancelled && *cancelled) {
|
||||
if (cancelled && cancelled->IsCancelled()) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -793,7 +793,7 @@ AVFramePtr FFmpegDecoder::RetrieveFrame(const rational& time, const QAtomicInt *
|
||||
// Pull from the decoder
|
||||
ret = instance_.GetFrame(working_packet_, filtered.get());
|
||||
|
||||
if (cancelled && *cancelled) {
|
||||
if (cancelled && cancelled->IsCancelled()) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,6 @@ extern "C" {
|
||||
#include <libswresample/swresample.h>
|
||||
}
|
||||
|
||||
#include <QAtomicInt>
|
||||
#include <QTimer>
|
||||
#include <QVector>
|
||||
#include <QWaitCondition>
|
||||
@@ -64,12 +63,12 @@ public:
|
||||
virtual bool SupportsVideo() override{return true;}
|
||||
virtual bool SupportsAudio() override{return true;}
|
||||
|
||||
virtual FootageDescription Probe(const QString &filename, const QAtomicInt *cancelled) const override;
|
||||
virtual FootageDescription Probe(const QString &filename, CancelAtom *cancelled) const override;
|
||||
|
||||
protected:
|
||||
virtual bool OpenInternal() override;
|
||||
virtual TexturePtr RetrieveVideoInternal(Renderer *renderer, const rational& timecode, const RetrieveVideoParams& params, const QAtomicInt *cancelled) override;
|
||||
virtual bool ConformAudioInternal(const QVector<QString>& filenames, const AudioParams ¶ms, const QAtomicInt* cancelled) override;
|
||||
virtual TexturePtr RetrieveVideoInternal(Renderer *renderer, const rational& timecode, const RetrieveVideoParams& params, CancelAtom *cancelled) override;
|
||||
virtual bool ConformAudioInternal(const QVector<QString>& filenames, const AudioParams ¶ms, CancelAtom *cancelled) override;
|
||||
virtual void CloseInternal() override;
|
||||
|
||||
private:
|
||||
@@ -151,7 +150,7 @@ private:
|
||||
|
||||
void ClearFrameCache();
|
||||
|
||||
AVFramePtr RetrieveFrame(const rational &time, const QAtomicInt *cancelled);
|
||||
AVFramePtr RetrieveFrame(const rational &time, CancelAtom *cancelled);
|
||||
|
||||
void RemoveFirstFrame();
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ QString OIIODecoder::id() const
|
||||
return QStringLiteral("oiio");
|
||||
}
|
||||
|
||||
FootageDescription OIIODecoder::Probe(const QString &filename, const QAtomicInt* cancelled) const
|
||||
FootageDescription OIIODecoder::Probe(const QString &filename, CancelAtom *cancelled) const
|
||||
{
|
||||
Q_UNUSED(cancelled)
|
||||
|
||||
@@ -116,7 +116,7 @@ bool OIIODecoder::OpenInternal()
|
||||
return OpenImageHandler(stream().filename(), stream().stream());
|
||||
}
|
||||
|
||||
TexturePtr OIIODecoder::RetrieveVideoInternal(Renderer *renderer, const rational &timecode, const RetrieveVideoParams ¶ms, const QAtomicInt *cancelled)
|
||||
TexturePtr OIIODecoder::RetrieveVideoInternal(Renderer *renderer, const rational &timecode, const RetrieveVideoParams ¶ms, CancelAtom *cancelled)
|
||||
{
|
||||
Q_UNUSED(timecode)
|
||||
Q_UNUSED(cancelled)
|
||||
|
||||
@@ -40,11 +40,11 @@ public:
|
||||
|
||||
virtual bool SupportsVideo() override{return true;}
|
||||
|
||||
virtual FootageDescription Probe(const QString& filename, const QAtomicInt* cancelled) const override;
|
||||
virtual FootageDescription Probe(const QString& filename, CancelAtom *cancelled) const override;
|
||||
|
||||
protected:
|
||||
virtual bool OpenInternal() override;
|
||||
virtual TexturePtr RetrieveVideoInternal(Renderer *renderer, const rational& timecode, const RetrieveVideoParams& params, const QAtomicInt *cancelled) override;
|
||||
virtual TexturePtr RetrieveVideoInternal(Renderer *renderer, const rational& timecode, const RetrieveVideoParams& params, CancelAtom *cancelled) override;
|
||||
virtual void CloseInternal() override;
|
||||
|
||||
private:
|
||||
|
||||
@@ -55,8 +55,6 @@ set(OLIVE_SOURCES
|
||||
common/ratiodialog.h
|
||||
common/rational.cpp
|
||||
common/rational.h
|
||||
common/threadedobject.cpp
|
||||
common/threadedobject.h
|
||||
common/threadsafemap.h
|
||||
common/timecodefunctions.cpp
|
||||
common/timecodefunctions.h
|
||||
|
||||
@@ -21,35 +21,38 @@
|
||||
#ifndef CANCELABLEOBJECT_H
|
||||
#define CANCELABLEOBJECT_H
|
||||
|
||||
#include <QAtomicInt>
|
||||
|
||||
#include "common/define.h"
|
||||
#include "render/cancelatom.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class CancelableObject {
|
||||
public:
|
||||
CancelableObject() :
|
||||
cancelled_(false)
|
||||
CancelableObject()
|
||||
{
|
||||
}
|
||||
|
||||
void Cancel()
|
||||
{
|
||||
cancelled_ = true;
|
||||
cancel_.Cancel();
|
||||
CancelEvent();
|
||||
}
|
||||
|
||||
const QAtomicInt& IsCancelled() const
|
||||
CancelAtom *GetCancelAtom()
|
||||
{
|
||||
return cancelled_;
|
||||
return &cancel_;
|
||||
}
|
||||
|
||||
bool IsCancelled()
|
||||
{
|
||||
return cancel_.IsCancelled();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void CancelEvent(){}
|
||||
|
||||
private:
|
||||
QAtomicInt cancelled_;
|
||||
CancelAtom cancel_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2022 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/>.
|
||||
|
||||
***/
|
||||
|
||||
#include "threadedobject.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
void ThreadedObject::LockDeletes()
|
||||
{
|
||||
threadobj_delete_lock_++;
|
||||
}
|
||||
|
||||
void ThreadedObject::UnlockDeletes()
|
||||
{
|
||||
Q_ASSERT(AreDeletesLocked());
|
||||
|
||||
threadobj_delete_lock_--;
|
||||
}
|
||||
|
||||
bool ThreadedObject::AreDeletesLocked()
|
||||
{
|
||||
return (threadobj_delete_lock_ > 0);
|
||||
}
|
||||
|
||||
void ThreadedObject::LockMutex()
|
||||
{
|
||||
threadobj_main_lock_.lock();
|
||||
}
|
||||
|
||||
void ThreadedObject::UnlockMutex()
|
||||
{
|
||||
threadobj_main_lock_.unlock();
|
||||
}
|
||||
|
||||
bool ThreadedObject::TryLockMutex(int timeout)
|
||||
{
|
||||
return threadobj_main_lock_.tryLock(timeout);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2022 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 THREADEDOBJECT_H
|
||||
#define THREADEDOBJECT_H
|
||||
|
||||
#include <QMutex>
|
||||
|
||||
#include "common/define.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class ThreadedObject
|
||||
{
|
||||
public:
|
||||
|
||||
void LockMutex();
|
||||
void UnlockMutex();
|
||||
bool TryLockMutex(int timeout = 0);
|
||||
|
||||
void LockDeletes();
|
||||
void UnlockDeletes();
|
||||
bool AreDeletesLocked();
|
||||
|
||||
private:
|
||||
QMutex threadobj_main_lock_;
|
||||
|
||||
QAtomicInt threadobj_delete_lock_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // THREADEDOBJECT_H
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "footagedescription.h"
|
||||
#include "node/output/viewer/viewer.h"
|
||||
#include "render/audioparams.h"
|
||||
#include "render/cancelatom.h"
|
||||
#include "render/videoparams.h"
|
||||
|
||||
namespace olive {
|
||||
@@ -141,7 +142,7 @@ public:
|
||||
*/
|
||||
void set_timestamp(const qint64 &t);
|
||||
|
||||
void SetCancelPointer(const QAtomicInt* c)
|
||||
void SetCancelPointer(CancelAtom *c)
|
||||
{
|
||||
cancelled_ = c;
|
||||
}
|
||||
@@ -232,7 +233,7 @@ private:
|
||||
|
||||
bool valid_;
|
||||
|
||||
const QAtomicInt* cancelled_;
|
||||
CancelAtom *cancelled_;
|
||||
|
||||
private slots:
|
||||
void CheckFootage();
|
||||
|
||||
@@ -260,7 +260,6 @@ NodeValueTable NodeTraverser::ProcessInput(const Node* node, const QString& inpu
|
||||
|
||||
NodeTraverser::NodeTraverser() :
|
||||
cancel_(nullptr),
|
||||
heard_cancel_(false),
|
||||
transform_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
+7
-15
@@ -26,6 +26,7 @@
|
||||
#include "codec/decoder.h"
|
||||
#include "common/cancelableobject.h"
|
||||
#include "node/output/track/track.h"
|
||||
#include "render/cancelatom.h"
|
||||
#include "render/job/footagejob.h"
|
||||
#include "render/job/colortransformjob.h"
|
||||
#include "value.h"
|
||||
@@ -130,24 +131,16 @@ protected:
|
||||
|
||||
bool IsCancelled()
|
||||
{
|
||||
bool c = cancel_ && *cancel_;
|
||||
if (c) {
|
||||
heard_cancel_ = true;
|
||||
}
|
||||
return c;
|
||||
return cancel_ && cancel_->IsCancelled();
|
||||
}
|
||||
|
||||
bool HeardCancel() const { return heard_cancel_; }
|
||||
|
||||
const QAtomicInt *GetCancelPointer() const
|
||||
bool HeardCancel() const
|
||||
{
|
||||
return cancel_;
|
||||
return cancel_ && cancel_->HeardCancel();
|
||||
}
|
||||
|
||||
void SetCancelPointer(const QAtomicInt *cancel)
|
||||
{
|
||||
cancel_ = cancel;
|
||||
}
|
||||
CancelAtom *GetCancelPointer() const { return cancel_; }
|
||||
void SetCancelPointer(CancelAtom *cancel) { cancel_ = cancel; }
|
||||
|
||||
void ResolveJobs(NodeValue &value, const TimeRange &range);
|
||||
|
||||
@@ -165,8 +158,7 @@ private:
|
||||
|
||||
AudioParams audio_params_;
|
||||
|
||||
const QAtomicInt *cancel_;
|
||||
bool heard_cancel_;
|
||||
CancelAtom *cancel_;
|
||||
|
||||
const Node *transform_start_;
|
||||
const Node *transform_now_;
|
||||
|
||||
@@ -24,6 +24,7 @@ set(OLIVE_SOURCES
|
||||
render/audioparams.h
|
||||
render/audioplaybackcache.cpp
|
||||
render/audioplaybackcache.h
|
||||
render/cancelatom.h
|
||||
render/color.cpp
|
||||
render/color.h
|
||||
render/colorprocessor.cpp
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
#ifndef CANCELATOM_H
|
||||
#define CANCELATOM_H
|
||||
|
||||
#include <QMutex>
|
||||
|
||||
namespace olive {
|
||||
|
||||
class CancelAtom
|
||||
{
|
||||
public:
|
||||
CancelAtom() :
|
||||
cancelled_(false),
|
||||
heard_(false)
|
||||
{}
|
||||
|
||||
bool IsCancelled()
|
||||
{
|
||||
QMutexLocker locker(&mutex_);
|
||||
if (cancelled_) {
|
||||
heard_ = true;
|
||||
}
|
||||
return cancelled_;
|
||||
}
|
||||
|
||||
void Cancel()
|
||||
{
|
||||
QMutexLocker locker(&mutex_);
|
||||
cancelled_ = true;
|
||||
}
|
||||
|
||||
bool HeardCancel()
|
||||
{
|
||||
QMutexLocker locker(&mutex_);
|
||||
return heard_;
|
||||
}
|
||||
|
||||
private:
|
||||
QMutex mutex_;
|
||||
|
||||
bool cancelled_;
|
||||
|
||||
bool heard_;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // CANCELATOM_H
|
||||
@@ -134,7 +134,7 @@ void RenderProcessor::Run()
|
||||
// Depending on the render ticket type, start a job
|
||||
RenderManager::TicketType type = ticket_->property("type").value<RenderManager::TicketType>();
|
||||
|
||||
SetCancelPointer(&ticket_->IsCancelled());
|
||||
SetCancelPointer(ticket_->GetCancelAtom());
|
||||
|
||||
SetCacheVideoParams(ticket_->property("vparam").value<VideoParams>());
|
||||
SetCacheAudioParams(ticket_->property("aparam").value<AudioParams>());
|
||||
|
||||
@@ -42,7 +42,7 @@ bool ConformTask::Run()
|
||||
|
||||
connect(decoder.get(), &Decoder::IndexProgress, this, &ConformTask::ProgressChanged);
|
||||
|
||||
bool ret = decoder->ConformAudio(output_filenames_, params_, &IsCancelled());
|
||||
bool ret = decoder->ConformAudio(output_filenames_, params_, GetCancelAtom());
|
||||
|
||||
decoder->Close();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user