diff --git a/app/task/render/render.cpp b/app/task/render/render.cpp index d46d1d778..175e3144d 100644 --- a/app/task/render/render.cpp +++ b/app/task/render/render.cpp @@ -87,89 +87,25 @@ void RenderTask::Render(const TimeRangeList& video_range, } } - QMap times_to_render; - std::list render_lookup_table; - QList times; - QList hashes; + QVector times; + QVector hashes; + std::list frame_queue; if (!video_range.isEmpty()) { + QList existing_hashes; - { - QList existing_hashes; - - foreach (const TimeRange& r, video_range) { - total_length += r.length().toDouble(); - } - - times = viewer_->video_frame_cache()->GetFrameListFromTimeRange(video_range); - - QFuture > hash_future = backend_.Hash(times); - hashes = hash_future.result(); - - // Determine any duplicates - for (int index=0;indexvideo_frame_cache()->CachePathName(hash)); - - if (hash_exists) { - existing_hashes.append(hash); - } - } - - if (hash_exists) { - // Already exists, no need to render it again - FrameDownloaded(hash, {time}); - progress_counter += video_frame_sz; - emit ProgressChanged(progress_counter / total_length); - } - } - - if (!hash_exists && (!map_contains_hash || times_to_render.value(hash) > time)) { - times_to_render.insert(hash, time); - } - } + foreach (const TimeRange& r, video_range) { + total_length += r.length().toDouble(); } - // Render all frames necessary - { - QMap::const_iterator i; - std::list::iterator j; + times = viewer_->video_frame_cache()->GetFrameListFromTimeRange(video_range); - std::list sorted_times; + QFuture > hash_future = backend_.Hash(times); + hashes = hash_future.result(); - // Rendering is generally more efficient when done sequentially, so we sort the - // times chronologically here - for (i=times_to_render.begin(); i!=times_to_render.end(); i++) { - bool inserted = false; - - for (j=sorted_times.begin(); j!=sorted_times.end(); j++) { - if (j->time > i.value()) { - sorted_times.insert(j, {i.value(), i.key()});\ - inserted = true; - break; - } - } - - if (!inserted) { - sorted_times.push_back({i.value(), i.key()}); - } - } - - // Start render jobs in sorted order - for (j=sorted_times.begin(); j!=sorted_times.end(); j++) { - render_lookup_table.push_back({j->hash, backend_.RenderFrame(j->time)}); - } + for (int i=0;i::iterator j; std::list::iterator k; + std::list running_hashes; + std::list existing_hashes; + while (!IsCancelled() && (!render_lookup_table.empty() + || !frame_queue.empty() || !download_futures.empty() || !audio_lookup_table.empty())) { + if (!frame_queue.empty()) { + // Pop another frame off the frame queue + const HashTimePair& p = frame_queue.front(); + + // Check if we're already rendering this hash + bool rendering_hash = (std::find(running_hashes.begin(), running_hashes.end(), p.hash) != running_hashes.end()); + + // Skip this hash if we're already rendering it + if (!rendering_hash) { + // Check if this frame already exists (has already been rendered previously or during this job) + bool hash_exists = false; + + if (use_disk_cache) { + bool hash_exists = (std::find(existing_hashes.begin(), existing_hashes.end(), p.hash) != existing_hashes.end()); + + if (!hash_exists) { + hash_exists = QFileInfo::exists(viewer_->video_frame_cache()->CachePathName(p.hash)); + + if (hash_exists) { + existing_hashes.push_back(p.hash); + } + } + + if (hash_exists) { + // Already exists, no need to render it again + FrameDownloaded(p.hash, {p.time}); + progress_counter += video_frame_sz; + emit ProgressChanged(progress_counter / total_length); + } + } + + // If no existing disk cache was found, queue it now + if (!hash_exists) { + render_lookup_table.push_back({p.hash, backend_.RenderFrame(p.time)}); + running_hashes.push_back(p.hash); + } + } + + // Remove first element + frame_queue.pop_front(); + } + i = render_lookup_table.begin(); while (!IsCancelled() && i != render_lookup_table.end()) { @@ -216,6 +198,8 @@ void RenderTask::Render(const TimeRangeList& video_range, FrameDownloaded(j->hash, times_with_hash); + existing_hashes.push_back(j->hash); + // Signal process progress_counter += times_with_hash.size() * video_frame_sz; emit ProgressChanged(progress_counter / total_length);