implemented "value hints" for choosing output values to use

This commit is contained in:
itsmattkc
2021-09-17 20:56:53 -07:00
parent a5e7859e1f
commit 67c7c71ca2
30 changed files with 439 additions and 85 deletions
+27 -9
View File
@@ -14,7 +14,6 @@ namespace olive {
PreviewAutoCacher::PreviewAutoCacher() :
viewer_node_(nullptr),
paused_(false),
has_changed_(false),
use_custom_range_(false),
single_frame_render_(nullptr)
{
@@ -141,7 +140,9 @@ void PreviewAutoCacher::HashesProcessed()
// The cacher might be waiting for this job to finish
if (!graph_update_queue_.isEmpty()) {
TryRender();
} else if (hash_iterator_.HasNext()) {
}
if (hash_iterator_.HasNext()) {
// Launch next hashes
QueueNextHashTask();
}
@@ -203,7 +204,12 @@ void PreviewAutoCacher::AudioRendered()
foreach (TimeRange r, intersections) {
// For each range, adjust it relative to the block and write it
r -= block->in();
block->waveform().OverwriteSums(waveform_info.waveform, r.in(), r.in() - waveform_info.range.in(), r.length());
if (waveform_info.silence) {
block->waveform().OverwriteSilence(r.in(), r.length());
} else {
block->waveform().OverwriteSums(waveform_info.waveform, r.in(), r.in() - waveform_info.range.in(), r.length());
}
}
emit block->PreviewChanged();
@@ -316,6 +322,9 @@ void PreviewAutoCacher::ProcessUpdateQueue()
case QueuedJob::kValueChanged:
CopyValue(job.input);
break;
case QueuedJob::kValueHintChanged:
CopyValueHint(job.input);
break;
}
}
graph_update_queue_.clear();
@@ -379,6 +388,13 @@ void PreviewAutoCacher::CopyValue(const NodeInput &input)
Node::CopyValuesOfElement(input.node(), our_input, input.input(), input.element());
}
void PreviewAutoCacher::CopyValueHint(const NodeInput &input)
{
Node* our_input = copy_map_.value(input.node());
Node::ValueHint hint = input.node()->GetValueHintForInput(input.input(), input.element());
our_input->SetValueHintForInput(input.input(), input.element(), hint);
}
void PreviewAutoCacher::InsertIntoCopyMap(Node *node, Node *copy)
{
// Insert into map
@@ -412,7 +428,6 @@ void PreviewAutoCacher::SetPlayhead(const rational &playhead)
cache_range_ = TimeRange(playhead - Config::Current()[QStringLiteral("DiskCacheBehind")].value<rational>(),
playhead + Config::Current()[QStringLiteral("DiskCacheAhead")].value<rational>());
has_changed_ = true;
use_custom_range_ = false;
RequeueFrames();
@@ -439,7 +454,6 @@ void PreviewAutoCacher::ClearVideoQueue(bool hard)
{
ClearQueueInternal(video_tasks_, hard, &PreviewAutoCacher::VideoRendered);
has_changed_ = true;
use_custom_range_ = false;
queued_frame_iterator_.reset();
}
@@ -486,6 +500,12 @@ void PreviewAutoCacher::ValueChanged(const NodeInput &input)
UpdateGraphChangeValue();
}
void PreviewAutoCacher::ValueHintChanged(const NodeInput &input)
{
graph_update_queue_.append({QueuedJob::kValueHintChanged, nullptr, input, nullptr});
UpdateGraphChangeValue();
}
void PreviewAutoCacher::TryRender()
{
if (!graph_update_queue_.isEmpty()) {
@@ -564,7 +584,6 @@ void PreviewAutoCacher::RequeueFrames()
if (viewer_node_
&& viewer_node_->video_frame_cache()->HasInvalidatedRanges(viewer_node_->GetVideoLength())
&& hash_tasks_.isEmpty()
&& has_changed_
&& VideoParams::FormatIsFloat(viewer_node_->GetVideoParams().format())
&& (!paused_ || use_custom_range_)) {
TimeRange using_range;
@@ -580,8 +599,6 @@ void PreviewAutoCacher::RequeueFrames()
queued_frame_iterator_ = TimeRangeListFrameIterator(invalidated, viewer_node_->video_frame_cache()->GetTimebase());
QueueNextFrameInRange(RenderManager::GetNumberOfIdealConcurrentJobs());
has_changed_ = false;
}
}
@@ -599,7 +616,6 @@ void PreviewAutoCacher::ConformFinished()
void PreviewAutoCacher::ForceCacheRange(const TimeRange &range)
{
has_changed_ = true;
use_custom_range_ = true;
custom_autocache_range_ = range;
@@ -655,6 +671,7 @@ void PreviewAutoCacher::SetViewerNode(ViewerOutput *viewer_node)
disconnect(graph, &NodeGraph::InputConnected, this, &PreviewAutoCacher::EdgeAdded);
disconnect(graph, &NodeGraph::InputDisconnected, this, &PreviewAutoCacher::EdgeRemoved);
disconnect(graph, &NodeGraph::ValueChanged, this, &PreviewAutoCacher::ValueChanged);
disconnect(graph, &NodeGraph::InputValueHintChanged, this, &PreviewAutoCacher::ValueHintChanged);
// Disconnect signal (will be a no-op if the signal was never connected)
disconnect(viewer_node_->video_frame_cache(),
@@ -705,6 +722,7 @@ void PreviewAutoCacher::SetViewerNode(ViewerOutput *viewer_node)
connect(graph, &NodeGraph::InputConnected, this, &PreviewAutoCacher::EdgeAdded);
connect(graph, &NodeGraph::InputDisconnected, this, &PreviewAutoCacher::EdgeRemoved);
connect(graph, &NodeGraph::ValueChanged, this, &PreviewAutoCacher::ValueChanged);
connect(graph, &NodeGraph::InputValueHintChanged, this, &PreviewAutoCacher::ValueHintChanged);
// Copy invalidated ranges - used to determine which frames need hashing
invalidated_video_ = viewer_node_->video_frame_cache()->GetInvalidatedRanges(viewer_node_->GetVideoLength());
+5 -3
View File
@@ -90,6 +90,7 @@ private:
void AddEdge(Node *output, const NodeInput& input);
void RemoveEdge(Node *output, const NodeInput& input);
void CopyValue(const NodeInput& input);
void CopyValueHint(const NodeInput& input);
void InsertIntoCopyMap(Node* node, Node* copy);
@@ -124,7 +125,8 @@ private:
kNodeRemoved,
kEdgeAdded,
kEdgeRemoved,
kValueChanged
kValueChanged,
kValueHintChanged
};
Type type;
@@ -147,8 +149,6 @@ private:
TimeRange cache_range_;
bool has_changed_;
bool use_custom_range_;
TimeRange custom_autocache_range_;
@@ -220,6 +220,8 @@ private slots:
void ValueChanged(const NodeInput& input);
void ValueHintChanged(const NodeInput &input);
/**
* @brief Generic function called whenever the frames to render need to be (re)queued
*/
+41 -37
View File
@@ -176,7 +176,7 @@ void RenderProcessor::Run()
QVariant sample_variant = table.Get(NodeValue::kSamples);
SampleBufferPtr samples = sample_variant.value<SampleBufferPtr>();
if (samples && ticket_->property("enablewaveforms").toBool()) {
if (ticket_->property("enablewaveforms").toBool()) {
AudioVisualWaveform vis;
vis.set_channel_count(samples->audio_params().channel_count());
vis.OverwriteSamples(samples, samples->audio_params().sample_rate());
@@ -264,52 +264,56 @@ NodeValueTable RenderProcessor::GenerateBlockTable(const Track *track, const Tim
// Destination buffer
NodeValueTable table = GenerateTable(b, track->GetValueHintForInput(Track::kBlockInput, track->GetArrayIndexFromBlock(b)),Track::TransformRangeForBlock(b, range_for_block));
SampleBufferPtr samples_from_this_block = table.Take(NodeValue::kSamples).value<SampleBufferPtr>();
ClipBlock *clip_cast = dynamic_cast<ClipBlock*>(b);
if (!samples_from_this_block) {
// If we retrieved no samples from this block, do nothing
continue;
if (samples_from_this_block) {
// If this is a clip, we might have extra speed/reverse information
if (clip_cast) {
double speed_value = clip_cast->speed();
bool reversed = clip_cast->reverse();
if (qIsNull(speed_value)) {
// Just silence, don't think there's any other practical application of 0 speed audio
samples_from_this_block->fill(0);
} else if (!qFuzzyCompare(speed_value, 1.0)) {
// Multiply time
samples_from_this_block->speed(speed_value);
}
if (reversed) {
samples_from_this_block->reverse();
}
}
int copy_length = qMin(max_dest_sz, samples_from_this_block->sample_count());
// Copy samples into destination buffer
for (int i=0; i<samples_from_this_block->audio_params().channel_count(); i++) {
block_range_buffer->set(i, samples_from_this_block->data(i), destination_offset, copy_length);
}
NodeValueTable::Merge({merged_table, table});
}
// If this is a clip, we might have extra speed/reverse information
if (ClipBlock *clip_cast = dynamic_cast<ClipBlock*>(b)) {
double speed_value = clip_cast->speed();
bool reversed = clip_cast->reverse();
// Create block waveforms if requested
if (ticket_->property("enablewaveforms").toBool() && clip_cast) {
// Format information for use in the main thread
RenderedWaveform waveform_info;
waveform_info.block = clip_cast;
waveform_info.range = range_for_block - b->in();
if (qIsNull(speed_value)) {
// Just silence, don't think there's any other practical application of 0 speed audio
samples_from_this_block->fill(0);
} else if (!qFuzzyCompare(speed_value, 1.0)) {
// Multiply time
samples_from_this_block->speed(speed_value);
}
if (reversed) {
samples_from_this_block->reverse();
}
// Create block waveforms if requested
if (ticket_->property("enablewaveforms").toBool()) {
if (!(waveform_info.silence = !samples_from_this_block.get())) {
// Generate a visual waveform from the samples acquired from this block
AudioVisualWaveform visual_waveform;
visual_waveform.set_channel_count(audio_params.channel_count());
visual_waveform.OverwriteSamples(samples_from_this_block, audio_params.sample_rate());
// Format it for use back int eh maint hread
RenderedWaveform waveform_info = {clip_cast, visual_waveform, range_for_block - b->in()};
QVector<RenderedWaveform> waveform_list = ticket_->property("waveforms").value< QVector<RenderedWaveform> >();
waveform_list.append(waveform_info);
ticket_->setProperty("waveforms", QVariant::fromValue(waveform_list));
waveform_info.waveform = visual_waveform;
}
QVector<RenderedWaveform> waveform_list = ticket_->property("waveforms").value< QVector<RenderedWaveform> >();
waveform_list.append(waveform_info);
ticket_->setProperty("waveforms", QVariant::fromValue(waveform_list));
}
int copy_length = qMin(max_dest_sz, samples_from_this_block->sample_count());
// Copy samples into destination buffer
for (int i=0; i<samples_from_this_block->audio_params().channel_count(); i++) {
block_range_buffer->set(i, samples_from_this_block->data(i), destination_offset, copy_length);
}
NodeValueTable::Merge({merged_table, table});
}
}
+1
View File
@@ -39,6 +39,7 @@ public:
const ClipBlock* block;
AudioVisualWaveform waveform;
TimeRange range;
bool silence;
};
protected: