fixed flicker issue when previewing some media

This commit is contained in:
itsmattkc
2019-09-10 15:55:59 +10:00
parent d1ce224e8b
commit 4c40475a6c
7 changed files with 58 additions and 62 deletions
+35 -30
View File
@@ -276,14 +276,9 @@ void RendererProcessor::Start()
SLOT(ThreadCallback(RenderTexturePtr, const rational&, const QByteArray&)),
Qt::QueuedConnection);
connect(threads_.first().get(),
SIGNAL(FrameExists(const rational&, const QByteArray&)),
SIGNAL(FrameSkipped(const rational&, const QByteArray&)),
this,
SLOT(ThreadFrameAlreadyExists(const rational&, const QByteArray&)),
Qt::QueuedConnection);
connect(threads_.first().get(),
SIGNAL(FrameIgnored()),
this,
SLOT(ThreadIgnoredFrame()),
SLOT(ThreadSkippedFrame(const rational&, const QByteArray&)),
Qt::QueuedConnection);
download_threads_.resize(background_thread_count);
@@ -294,9 +289,9 @@ void RendererProcessor::Start()
download_threads_[i]->StartThread(QThread::LowPriority);
connect(download_threads_[i].get(),
SIGNAL(Downloaded(const rational&, const QByteArray&)),
SIGNAL(Downloaded(const QByteArray&)),
this,
SLOT(MapHashToTimecode(const rational&, const QByteArray&)),
SLOT(DownloadThreadComplete(const QByteArray&)),
Qt::QueuedConnection);
}
@@ -364,7 +359,7 @@ void RendererProcessor::CacheNext()
rational cache_frame = cache_queue_.takeFirst();
qDebug() << "[RendererProcessor] Caching" << cache_frame.toDouble();
//qDebug() << "[RendererProcessor] Caching" << cache_frame.toDouble();
threads_.first()->Queue(NodeDependency(texture_input_->get_connected_output(), cache_frame), true);
@@ -381,6 +376,11 @@ QString RendererProcessor::CachePathName(const QByteArray &hash)
return this_cache_dir.filePath(filename);
}
void RendererProcessor::DeferMap(const rational &time, const QByteArray &hash)
{
deferred_maps_.append({time, hash});
}
bool RendererProcessor::HasHash(const QByteArray &hash)
{
return QFileInfo::exists(CachePathName(hash));
@@ -423,19 +423,20 @@ void RendererProcessor::ThreadCallback(RenderTexturePtr texture, const rational&
// Threads are all done now, time to proceed
caching_ = false;
DeferMap(time, hash);
if (texture != nullptr) {
// We received a texture, time to start downloading it
QString fn = CachePathName(hash);
download_threads_[last_download_thread_%download_threads_.size()]->Queue(texture,
fn,
time,
hash);
last_download_thread_++;
} else {
// There was no texture here, we must update the viewer
MapHashToTimecode(time, hash);
DownloadThreadComplete(hash);
}
// If the connected output is using this time, signal it to update
@@ -458,39 +459,43 @@ void RendererProcessor::ThreadRequestSibling(NodeDependency dep)
}
}
void RendererProcessor::ThreadFrameAlreadyExists(const rational &time, const QByteArray &hash)
void RendererProcessor::ThreadSkippedFrame(const rational& time, const QByteArray& hash)
{
caching_ = false;
// Update hash map with new hash
MapHashToTimecode(time, hash);
DeferMap(time, hash);
// Signal output to update value
if (texture_output_->IsConnected()
&& texture_output_->LastRequestedTime() == time) {
texture_output_->ClearCachedValue();
SendInvalidateCache(time, time);
if (!IsCaching(hash)) {
DownloadThreadComplete(hash);
// Signal output to update value
if (texture_output_->IsConnected()
&& texture_output_->LastRequestedTime() == time) {
texture_output_->ClearCachedValue();
SendInvalidateCache(time, time);
}
}
// Start caching the next frame
CacheNext();
}
void RendererProcessor::MapHashToTimecode(const rational& time, const QByteArray& hash)
void RendererProcessor::DownloadThreadComplete(const QByteArray &hash)
{
// Insert into hash map
time_hash_map_.insert(time, hash);
cache_hash_list_mutex_.lock();
cache_hash_list_.removeAll(hash);
cache_hash_list_mutex_.unlock();
}
void RendererProcessor::ThreadIgnoredFrame()
{
caching_ = false;
for (int i=0;i<deferred_maps_.size();i++) {
const HashTimeMapping& deferred = deferred_maps_.at(i);
CacheNext();
if (deferred_maps_.at(i).hash == hash) {
// Insert into hash map
time_hash_map_.insert(deferred.time, deferred.hash);
deferred_maps_.removeAt(i);
i--;
}
}
}
RendererThreadBase* RendererProcessor::CurrentThread()
+11 -4
View File
@@ -119,6 +119,11 @@ protected:
virtual QVariant Value(NodeOutput* output, const rational& time) override;
private:
struct HashTimeMapping {
rational time;
QByteArray hash;
};
/**
* @brief Allocate and start the multithreaded backend
*/
@@ -148,6 +153,8 @@ private:
*/
QString CachePathName(const QByteArray &hash);
void DeferMap(const rational &time, const QByteArray &hash);
/**
* @brief Internal list of RenderProcessThreads
*/
@@ -198,16 +205,16 @@ private:
QMutex cache_hash_list_mutex_;
QVector<QByteArray> cache_hash_list_;
QList<HashTimeMapping> deferred_maps_;
private slots:
void ThreadCallback(RenderTexturePtr texture, const rational& time, const QByteArray& hash);
void ThreadRequestSibling(NodeDependency dep);
void ThreadFrameAlreadyExists(const rational &time, const QByteArray &hash);
void ThreadSkippedFrame(const rational &time, const QByteArray &hash);
void MapHashToTimecode(const rational &time, const QByteArray &hash);
void ThreadIgnoredFrame();
void DownloadThreadComplete(const QByteArray &hash);
};
@@ -18,11 +18,11 @@ RendererDownloadThread::RendererDownloadThread(QOpenGLContext *share_ctx,
{
}
void RendererDownloadThread::Queue(RenderTexturePtr texture, const QString& fn, const rational& time, const QByteArray &hash)
void RendererDownloadThread::Queue(RenderTexturePtr texture, const QString& fn, const QByteArray &hash)
{
texture_queue_lock_.lock();
texture_queue_.append({texture, fn, time, hash});
texture_queue_.append({texture, fn, hash});
wait_cond_.wakeAll();
@@ -118,7 +118,7 @@ void RendererDownloadThread::ProcessLoop()
out->write_image(format_info.oiio_desc, data_buffer.data());
out->close();
emit Downloaded(entry.time, entry.hash);
emit Downloaded(entry.hash);
} else {
qWarning() << tr("Failed to open output file \"%1\"").arg(entry.filename);
}
@@ -9,17 +9,18 @@ class RendererDownloadThread : public RendererThreadBase
public:
RendererDownloadThread(QOpenGLContext* share_ctx,
const int& width,
const int& height, const int &divider,
const int& height,
const int &divider,
const olive::PixelFormat& format,
const olive::RenderMode& mode);
void Queue(RenderTexturePtr texture, const QString &fn, const rational &time, const QByteArray &hash);
void Queue(RenderTexturePtr texture, const QString &fn, const QByteArray &hash);
public slots:
virtual void Cancel() override;
signals:
void Downloaded(const rational& time, const QByteArray& hash);
void Downloaded(const QByteArray& hash);
protected:
virtual void ProcessLoop() override;
@@ -28,7 +29,6 @@ private:
struct DownloadQueueEntry {
RenderTexturePtr texture;
QString filename;
rational time;
QByteArray hash;
};
@@ -79,8 +79,6 @@ void RendererProcessThread::ProcessLoop()
// Main waiting condition
wait_cond_.wait(&mutex_);
qDebug() << this << "woke for a queued frame";
if (cancelled_) {
break;
}
@@ -111,8 +109,6 @@ void RendererProcessThread::ProcessLoop()
bool has_hash = parent_->HasHash(hash_);
bool can_cache = false;
qDebug() << this << "starting background cache of frame" << path_.time().toDouble();
if (!has_hash){
if ((can_cache = parent_->TryCache(hash_))) {
@@ -127,17 +123,10 @@ void RendererProcessThread::ProcessLoop()
}
// Get the requested value
qDebug() << this << "starting cache of" << hash_.toHex();
texture_ = output_to_process->get_value(path_.time()).value<RenderTexturePtr>();
render_instance()->context()->functions()->glFinish();
qDebug() << this << "completed cache of" << hash_.toHex();
} else {
qDebug() << this << "hash is in use";
}
} else {
qDebug() << this << "hash" << hash_.toHex() << "exists";
}
foreach (Node* dep, all_deps) {
@@ -146,15 +135,12 @@ void RendererProcessThread::ProcessLoop()
node_to_process->Unlock();
if (has_hash && !parent_->IsCaching(hash_)) {
// This hash already exists, no need to cache, just record it
emit FrameExists(path_.time(), hash_);
} else if (can_cache) {
if (can_cache) {
// We cached this frame, signal that it will need to be downloaded to disk
emit CachedFrame(texture_, path_.time(), hash_);
} else {
// Some other dork is caching this frame, skip it
emit FrameIgnored();
// This hash already exists, no need to cache, just map it
emit FrameSkipped(path_.time(), hash_);
}
}
}
@@ -49,9 +49,7 @@ signals:
void CachedFrame(RenderTexturePtr texture, const rational& time, const QByteArray& hash);
void FrameExists(const rational& time, const QByteArray& hash);
void FrameIgnored();
void FrameSkipped(const rational& time, const QByteArray& hash);
private:
RendererProcessor* parent_;