render: use events to iterate gradually through frame queue
Fixes #1665
This commit is contained in:
@@ -151,6 +151,7 @@ private:
|
||||
class TimeRangeListFrameIterator
|
||||
{
|
||||
public:
|
||||
TimeRangeListFrameIterator() = default;
|
||||
TimeRangeListFrameIterator(const TimeRangeList &list, const rational &timebase);
|
||||
|
||||
bool GetNext(rational *out);
|
||||
@@ -168,6 +169,11 @@ public:
|
||||
|
||||
int size();
|
||||
|
||||
void reset()
|
||||
{
|
||||
*this = TimeRangeListFrameIterator();
|
||||
}
|
||||
|
||||
private:
|
||||
void UpdateIndexIfNecessary();
|
||||
|
||||
|
||||
@@ -274,6 +274,8 @@ void PreviewAutoCacher::VideoRendered()
|
||||
TryRender();
|
||||
}
|
||||
|
||||
QueueNextFrameInRange(1);
|
||||
|
||||
delete watcher;
|
||||
}
|
||||
|
||||
@@ -442,6 +444,7 @@ void PreviewAutoCacher::ClearVideoQueue(bool hard)
|
||||
|
||||
has_changed_ = true;
|
||||
use_custom_range_ = false;
|
||||
queued_frame_iterator_.reset();
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::ClearAudioQueue(bool hard)
|
||||
@@ -579,31 +582,9 @@ void PreviewAutoCacher::RequeueFrames()
|
||||
}
|
||||
|
||||
TimeRangeList invalidated = viewer_node_->video_frame_cache()->GetInvalidatedRanges().Intersects(using_range);
|
||||
TimeRangeListFrameIterator invalidated_ranges(invalidated, viewer_node_->video_frame_cache()->GetTimebase());
|
||||
queued_frame_iterator_ = TimeRangeListFrameIterator(invalidated, viewer_node_->video_frame_cache()->GetTimebase());
|
||||
|
||||
rational t;
|
||||
while (invalidated_ranges.GetNext(&t)) {
|
||||
const QByteArray& hash = viewer_node_->video_frame_cache()->GetHash(t);
|
||||
|
||||
RenderTicketWatcher* render_task = video_tasks_.key(hash);
|
||||
|
||||
if (t >= using_range.in()
|
||||
&& t < using_range.out()) {
|
||||
// We want this hash, if we're not already rendering, start render now
|
||||
if (!render_task && !video_download_tasks_.key(hash)) {
|
||||
// Don't render any hash more than once
|
||||
RenderFrame(hash, t, false, false);
|
||||
}
|
||||
} else if (render_task) {
|
||||
// Cancel this frame unless it's already started
|
||||
QMutexLocker locker(render_task->GetTicket()->lock());
|
||||
|
||||
if (!render_task->GetTicket()->IsRunning(false)) {
|
||||
video_tasks_.remove(render_task);
|
||||
delete render_task;
|
||||
}
|
||||
}
|
||||
}
|
||||
QueueNextFrameInRange(RenderManager::GetNumberOfIdealConcurrentJobs());
|
||||
|
||||
has_changed_ = false;
|
||||
}
|
||||
@@ -777,6 +758,24 @@ void PreviewAutoCacher::ClearQueueRemoveEventInternal(QVector<RenderTicketWatche
|
||||
Q_UNUSED(it)
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::QueueNextFrameInRange(int max)
|
||||
{
|
||||
rational t;
|
||||
while (max && queued_frame_iterator_.GetNext(&t)) {
|
||||
const QByteArray& hash = viewer_node_->video_frame_cache()->GetHash(t);
|
||||
|
||||
RenderTicketWatcher* render_task = video_tasks_.key(hash);
|
||||
|
||||
// We want this hash, if we're not already rendering, start render now
|
||||
if (!render_task && !video_download_tasks_.key(hash)) {
|
||||
// Don't render any hash more than once
|
||||
RenderFrame(hash, t, false, false);
|
||||
|
||||
max--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, typename Func>
|
||||
void PreviewAutoCacher::ClearQueueInternal(T& list, bool hard, Func member)
|
||||
{
|
||||
|
||||
@@ -115,6 +115,9 @@ private:
|
||||
void ClearQueueRemoveEventInternal(QMap<RenderTicketWatcher*, TimeRange>::iterator it);
|
||||
void ClearQueueRemoveEventInternal(QVector<RenderTicketWatcher*>::iterator it);
|
||||
|
||||
void QueueNextFrameInRange(int max);
|
||||
TimeRangeListFrameIterator queued_frame_iterator_;
|
||||
|
||||
class QueuedJob {
|
||||
public:
|
||||
enum Type {
|
||||
|
||||
@@ -123,6 +123,11 @@ public:
|
||||
return backend_;
|
||||
}
|
||||
|
||||
static int GetNumberOfIdealConcurrentJobs()
|
||||
{
|
||||
return QThread::idealThreadCount();
|
||||
}
|
||||
|
||||
signals:
|
||||
|
||||
private:
|
||||
|
||||
Reference in New Issue
Block a user