nodes are given a time range

This commit is contained in:
itsmattkc
2019-10-22 14:58:06 +11:00
parent 9da5e7c9be
commit 5f86b9b9c7
32 changed files with 110 additions and 77 deletions
+3 -3
View File
@@ -49,7 +49,7 @@ void AlphaOverBlend::Release()
{
}
QVariant AlphaOverBlend::Value(NodeOutput *param, const rational &time)
QVariant AlphaOverBlend::Value(NodeOutput *param, const rational &in, const rational &out)
{
// Find the current Renderer instance
RenderInstance* renderer = VideoRendererProcessor::CurrentInstance();
@@ -61,8 +61,8 @@ QVariant AlphaOverBlend::Value(NodeOutput *param, const rational &time)
// The only parameter should be texture output, but for future proofing we put this here
if (param == texture_output()) {
RenderTexturePtr base = base_input()->get_value(time).value<RenderTexturePtr>();
RenderTexturePtr blend = blend_input()->get_value(time).value<RenderTexturePtr>();
RenderTexturePtr base = base_input()->get_value(in, out).value<RenderTexturePtr>();
RenderTexturePtr blend = blend_input()->get_value(in, out).value<RenderTexturePtr>();
if (base == nullptr && blend == nullptr) {
return 0;
+1 -1
View File
@@ -36,7 +36,7 @@ public:
virtual void Release() override;
protected:
virtual QVariant Value(NodeOutput* param, const rational& time) override;
virtual QVariant Value(NodeOutput* param, const rational &in, const rational &out) override;
private:
};
+12 -2
View File
@@ -38,6 +38,10 @@ Block::Block() :
texture_output_->set_data_type(NodeParam::kTexture);
AddParameter(texture_output_);
samples_output_ = new NodeOutput("samples_out");
samples_output_->set_data_type(NodeParam::kSamples);
AddParameter(samples_output_);
connect(this, SIGNAL(EdgeAdded(NodeEdgePtr)), this, SLOT(EdgeAddedSlot(NodeEdgePtr)), Qt::DirectConnection);
connect(this, SIGNAL(EdgeRemoved(NodeEdgePtr)), this, SLOT(EdgeRemovedSlot(NodeEdgePtr)), Qt::DirectConnection);
}
@@ -99,9 +103,10 @@ NodeInput *Block::previous_input()
return previous_input_;
}
QVariant Block::Value(NodeOutput *output, const rational &time)
QVariant Block::Value(NodeOutput *output, const rational &in, const rational &out)
{
Q_UNUSED(time)
Q_UNUSED(in)
Q_UNUSED(out)
if (output == block_output_) {
// Simply set the output value to a pointer to this Block
@@ -158,6 +163,11 @@ NodeOutput *Block::texture_output()
return texture_output_;
}
NodeOutput *Block::samples_output()
{
return samples_output_;
}
NodeOutput *Block::block_output()
{
return block_output_;
+3 -1
View File
@@ -60,6 +60,7 @@ public:
NodeInput* previous_input();
NodeOutput* texture_output();
NodeOutput* samples_output();
NodeOutput* block_output();
static void ConnectBlocks(Block* previous, Block* next);
@@ -103,7 +104,7 @@ signals:
void Refreshed();
protected:
virtual QVariant Value(NodeOutput* output, const rational& time) override;
virtual QVariant Value(NodeOutput* output, const rational &in, const rational &out) override;
rational SequenceToMediaTime(const rational& sequence_time);
@@ -116,6 +117,7 @@ private:
NodeOutput* block_output_;
NodeOutput* texture_output_;
NodeOutput* samples_output_;
rational in_point_;
rational out_point_;
+5 -7
View File
@@ -61,21 +61,19 @@ NodeInput *ClipBlock::texture_input()
return texture_input_;
}
QVariant ClipBlock::Value(NodeOutput* param, const rational& time)
QVariant ClipBlock::Value(NodeOutput* param, const rational& v_in, const rational &v_out)
{
if (param == texture_output()) {
// If the time retrieved is within this block, get texture information
if (texture_input()->IsConnected() && time >= in() && time < out()) {
// We convert the time given (timeline time) to media time
rational media_time = SequenceToMediaTime(time);
if (texture_input()->IsConnected() && v_in >= in() && v_out < out()) {
// Retrieve texture
return texture_input_->get_value(media_time);
// We convert the time given (timeline time) to media time
return texture_input_->get_value(SequenceToMediaTime(v_in), SequenceToMediaTime(v_out));
}
return 0;
}
return Block::Value(param, time);
return Block::Value(param, v_in, v_out);
}
void ClipBlock::InvalidateCache(const rational &start_range, const rational &end_range, NodeInput *from)
+1 -1
View File
@@ -47,7 +47,7 @@ public:
virtual QList<NodeDependency> RunDependencies(NodeOutput *output, const rational &time) override;
protected:
virtual QVariant Value(NodeOutput* output, const rational& time) override;
virtual QVariant Value(NodeOutput* output, const rational &v_in, const rational &v_out) override;
private:
NodeInput* texture_input_;
+5 -3
View File
@@ -62,8 +62,10 @@ QString OpacityNode::id()
return "org.olivevideoeditor.Olive.opacity";
}
QVariant OpacityNode::Value(NodeOutput *output, const rational &time)
QVariant OpacityNode::Value(NodeOutput *output, const rational &in, const rational &out)
{
Q_UNUSED(out)
// Find the current Renderer instance
RenderInstance* renderer = VideoRendererProcessor::CurrentInstance();
@@ -73,7 +75,7 @@ QVariant OpacityNode::Value(NodeOutput *output, const rational &time)
}
if (output == texture_output_) {
RenderTexturePtr input_tex = texture_input_->get_value(time).value<RenderTexturePtr>();
RenderTexturePtr input_tex = texture_input_->get_value(in).value<RenderTexturePtr>();
if (input_tex == nullptr) {
return 0;
@@ -89,7 +91,7 @@ QVariant OpacityNode::Value(NodeOutput *output, const rational &time)
// Set opacity to value
ShaderPtr pipeline = renderer->default_pipeline();
pipeline->bind();
pipeline->setUniformValue("opacity", opacity_input_->get_value(time).toFloat()*0.01f);
pipeline->setUniformValue("opacity", opacity_input_->get_value(in).toFloat()*0.01f);
pipeline->release();
renderer->context()->functions()->glBlendFunc(GL_ONE, GL_ZERO);
+1 -1
View File
@@ -36,7 +36,7 @@ public:
virtual QString id() override;
virtual QVariant Value(NodeOutput *output, const rational &time) override;
virtual QVariant Value(NodeOutput *output, const rational &in, const rational &out) override;
virtual void Retranslate() override;
+7 -5
View File
@@ -80,23 +80,25 @@ void TransformDistort::Retranslate()
anchor_input_->set_name(tr("Anchor Point"));
}
QVariant TransformDistort::Value(NodeOutput *output, const rational &time)
QVariant TransformDistort::Value(NodeOutput *output, const rational &in, const rational &out)
{
Q_UNUSED(out)
if (output == matrix_output_) {
QMatrix4x4 mat;
// Position translate
QVector2D pos = position_input_->get_value(time).value<QVector2D>();
QVector2D pos = position_input_->get_value(in).value<QVector2D>();
mat.translate(pos);
// Rotation
mat.rotate(rotation_input_->get_value(time).toFloat(), 0, 0, 1);
mat.rotate(rotation_input_->get_value(in).toFloat(), 0, 0, 1);
// Scale
mat.scale(scale_input_->get_value(time).value<QVector2D>()*0.01f);
mat.scale(scale_input_->get_value(in).value<QVector2D>()*0.01f);
// Anchor Point
mat.translate(-anchor_input_->get_value(time).value<QVector2D>());
mat.translate(-anchor_input_->get_value(in).value<QVector2D>());
return mat;
}
+1 -1
View File
@@ -39,7 +39,7 @@ public:
virtual void Retranslate() override;
protected:
virtual QVariant Value(NodeOutput *output, const rational &time) override;
virtual QVariant Value(NodeOutput *output, const rational &in, const rational &out) override;
private:
NodeInput* position_input_;
+3 -2
View File
@@ -57,10 +57,11 @@ NodeOutput *SolidGenerator::texture_output()
return texture_output_;
}
QVariant SolidGenerator::Value(NodeOutput *output, const rational &time)
QVariant SolidGenerator::Value(NodeOutput *output, const rational &in, const rational &out)
{
Q_UNUSED(output)
Q_UNUSED(time)
Q_UNUSED(in)
Q_UNUSED(out)
/*
// FIXME: Test code
+1 -1
View File
@@ -42,7 +42,7 @@ public:
NodeOutput* texture_output();
protected:
virtual QVariant Value(NodeOutput* output, const rational& time) override;
virtual QVariant Value(NodeOutput* output, const rational &in, const rational &out) override;
private:
NodeInput* color_input_;
+5 -4
View File
@@ -69,22 +69,23 @@ Node *NodeInput::get_connected_node()
return nullptr;
}
QVariant NodeInput::get_value(const rational& time)
QVariant NodeInput::get_value(const rational& in, const rational& out)
{
QVariant v;
if (time_ != time || !value_caching_) {
if (in_ != in || out_ != out || !value_caching_) {
// Retrieve the value
if (!edges_.isEmpty()) {
// A connection - use the output of the connected Node
value_ = get_connected_output()->get_value(time);
value_ = get_connected_output()->get_value(in, out);
} else {
// No connections - use the internal value
// FIXME: Re-implement keyframing
value_ = keyframes_.first().value();
}
time_ = time;
in_ = in;
out_ = out;
}
v = value_;
+1 -1
View File
@@ -93,7 +93,7 @@ public:
* If no output is connected, this will return a user-defined value, either a static value if this input is not
* keyframed, or an interpolated value between the keyframes at this time.
*/
QVariant get_value(const rational &time);
QVariant get_value(const rational &in, const rational &out = -1);
/**
* @brief Set the value at a given time
+7 -5
View File
@@ -129,8 +129,10 @@ void MediaInput::Hash(QCryptographicHash *hash, NodeOutput *from, const rational
}
}
QVariant MediaInput::Value(NodeOutput *output, const rational &time)
QVariant MediaInput::Value(NodeOutput *output, const rational &in, const rational &out)
{
Q_UNUSED(out)
// FIXME: Hardcoded value
bool alpha_is_associated = false;
@@ -149,12 +151,12 @@ QVariant MediaInput::Value(NodeOutput *output, const rational &time)
}
// Check if we need to get a frame or not
if (frame_ == nullptr || frame_->native_timestamp() != decoder_->GetTimestampFromTime(time)) {
if (frame_ == nullptr || frame_->native_timestamp() != decoder_->GetTimestampFromTime(in)) {
// Get frame from Decoder
frame_ = decoder_->Retrieve(time);
frame_ = decoder_->Retrieve(in);
if (frame_ == nullptr) {
qDebug() << "Received a null frame while time was" << time.toDouble();
qDebug() << "Received a null frame while time was" << in.toDouble();
return 0;
}
@@ -261,7 +263,7 @@ QVariant MediaInput::Value(NodeOutput *output, const rational &time)
2.0f / static_cast<float>(renderer->height() * renderer->divider()));
// Multiply by input transformation
transform *= matrix_input_->get_value(time).value<QMatrix4x4>();
transform *= matrix_input_->get_value(in).value<QMatrix4x4>();
// Scale texture to the media size
transform.scale(static_cast<float>(frame_->width()), static_cast<float>(frame_->height()));
+1 -1
View File
@@ -55,7 +55,7 @@ public:
virtual void Hash(QCryptographicHash *hash, NodeOutput* from, const rational &time) override;
protected:
virtual QVariant Value(NodeOutput* output, const rational& time) override;
virtual QVariant Value(NodeOutput* output, const rational& in, const rational& out) override;
private:
bool SetupDecoder();
+2 -2
View File
@@ -180,11 +180,11 @@ void Node::ClearCachedValuesInParameters(const rational &start_range, const rati
}
}
QVariant Node::Run(NodeOutput* output, const rational& time)
QVariant Node::Run(NodeOutput* output, const rational& in, const rational &out)
{
run_lock_.lock();
QVariant v = Value(output, time);
QVariant v = Value(output, in, out);
run_lock_.unlock();
+2 -2
View File
@@ -129,7 +129,7 @@ public:
*
* It's recommended to call this directly over Value(), yet in derivatives of Node, override Value().
*/
QVariant Run(NodeOutput* output, const rational& time);
QVariant Run(NodeOutput* output, const rational &in, const rational &out);
/**
* @brief For nodes that have different dependencies at different times, this function can be used for that purpose
@@ -252,7 +252,7 @@ protected:
* corresponding output if it's connected to one. If your node doesn't directly deal with time, the default behavior
* of the NodeParam objects will handle everything related to it automatically.
*/
virtual QVariant Value(NodeOutput* output, const rational& time) = 0;
virtual QVariant Value(NodeOutput* output, const rational &in, const rational &out) = 0;
/**
* @brief Retrieve the last timecode Process() was called with
+8 -6
View File
@@ -59,17 +59,18 @@ void NodeOutput::set_data_type(const NodeParam::DataType &type)
}
}
QVariant NodeOutput::get_value(const rational& time)
QVariant NodeOutput::get_value(const rational& in, const rational& out)
{
mutex_.lock();
QVariant v;
if (time_ != time || !value_caching_) {
if (in_ != in || out_ != out || !value_caching_) {
// Update the value
value_ = parent()->Run(this, time);
value_ = parent()->Run(this, in_, out_);
time_ = time;
in_ = in;
out_ = out;
}
v = value_;
@@ -79,9 +80,10 @@ QVariant NodeOutput::get_value(const rational& time)
return v;
}
void NodeOutput::push_value(const QVariant &v, const rational &time)
void NodeOutput::push_value(const QVariant &v, const rational &in, const rational &out)
{
value_ = v;
time_ = time;
in_ = in;
out_ = out;
}
+2 -2
View File
@@ -61,9 +61,9 @@ public:
* In many cases for efficiency, the Node can also ignore this request if it knows the output data will not change
* (i.e. if the time has not changed from the last Process()).
*/
virtual QVariant get_value(const rational &time);
virtual QVariant get_value(const rational &in, const rational &out);
void push_value(const QVariant& v, const rational& time);
void push_value(const QVariant& v, const rational& in, const rational &out);
private:
DataType data_type_;
+4 -3
View File
@@ -94,11 +94,12 @@ const rational &TimelineOutput::Timebase()
return timebase_;
}
QVariant TimelineOutput::Value(NodeOutput *output, const rational &time)
QVariant TimelineOutput::Value(NodeOutput *output, const rational &in, const rational &out)
{
if (output == length_output_) {
Q_UNUSED(time)
Q_UNUSED(in)
Q_UNUSED(out)
if (output == length_output_) {
return QVariant::fromValue(length_);
}
+1 -1
View File
@@ -67,7 +67,7 @@ signals:
void TrackRemoved(TrackOutput* track);
protected:
virtual QVariant Value(NodeOutput* output, const rational& time) override;
virtual QVariant Value(NodeOutput* output, const rational &in, const rational &out) override;
private:
QVector<NodeInput*> track_inputs_;
+3 -3
View File
@@ -176,7 +176,7 @@ void TrackList::TrackConnectionRemoved(NodeEdgePtr edge)
return;
}
DetachTrack(Node::ValueToPtr<TrackOutput>(edge->output()->get_value(0)));
DetachTrack(Node::ValueToPtr<TrackOutput>(edge->output()->get_value(0, 0)));
}
void TrackList::TrackEdgeAdded(NodeEdgePtr edge)
@@ -186,7 +186,7 @@ void TrackList::TrackEdgeAdded(NodeEdgePtr edge)
// If this edge pertains to the track's track input, all the tracks just added need attaching
if (edge->input() == track->track_input()) {
TrackOutput* added_track = Node::ValueToPtr<TrackOutput>(edge->output()->get_value(0));
TrackOutput* added_track = Node::ValueToPtr<TrackOutput>(edge->output()->get_value(0, 0));
AttachTrack(added_track);
}
@@ -199,7 +199,7 @@ void TrackList::TrackEdgeRemoved(NodeEdgePtr edge)
// If this edge pertains to the track's track input, all the tracks just added need attaching
if (edge->input() == track->track_input()) {
TrackOutput* added_track = Node::ValueToPtr<TrackOutput>(edge->output()->get_value(0));
TrackOutput* added_track = Node::ValueToPtr<TrackOutput>(edge->output()->get_value(0, 0));
DetachTrack(added_track);
}
+11 -4
View File
@@ -192,25 +192,32 @@ void TrackOutput::InvalidateCache(const rational &start_range, const rational &e
}
}
QVariant TrackOutput::Value(NodeOutput *output, const rational &time)
QVariant TrackOutput::Value(NodeOutput *output, const rational &in, const rational &out)
{
if (output == track_output_) {
// Set track output correctly
return PtrToValue(this);
} else if (output == texture_output()) {
ValidateCurrentBlock(time);
ValidateCurrentBlock(in);
if (current_block_ != this) {
// At this point, we must have found the correct block so we use its texture output to produce the image
return current_block_->texture_output()->get_value(time);
return current_block_->texture_output()->get_value(in, out);
}
// No texture is valid
return 0;
} else if (output == samples_output()) {
ValidateCurrentBlock(in);
if (current_block_ != this) {
// FIXME: String together samples from blocks in this range
qDebug() << "FIXME: Implement this";
}
}
// Run default node processing
return Block::Value(output, time);
return Block::Value(output, in, out);
}
void TrackOutput::InsertBlockBetweenBlocks(Block *block, Block *before, Block *after)
+1 -1
View File
@@ -146,7 +146,7 @@ signals:
void BlockRemoved(Block* block);
protected:
virtual QVariant Value(NodeOutput* output, const rational& time) override;
virtual QVariant Value(NodeOutput* output, const rational& in, const rational &out) override;
private:
/**
+3 -2
View File
@@ -126,10 +126,11 @@ rational ViewerOutput::Length()
return length_input_->get_value(0).value<rational>();
}
QVariant ViewerOutput::Value(NodeOutput *output, const rational &time)
QVariant ViewerOutput::Value(NodeOutput *output, const rational &in, const rational &out)
{
Q_UNUSED(output)
Q_UNUSED(time)
Q_UNUSED(in)
Q_UNUSED(out)
return 0;
}
+1 -1
View File
@@ -67,7 +67,7 @@ signals:
void SizeChanged(int width, int height);
protected:
virtual QVariant Value(NodeOutput* output, const rational& time) override;
virtual QVariant Value(NodeOutput* output, const rational &in, const rational &out) override;
private:
NodeInput* texture_input_;
+6 -4
View File
@@ -32,7 +32,8 @@
#include "node/output.h"
NodeParam::NodeParam(const QString &id) :
time_(-1),
in_(-1),
out_(-1),
value_caching_(true),
id_(id)
{
@@ -292,12 +293,13 @@ void NodeParam::ClearCachedValue()
{
// Since get_value() will (read: should) never receive a negative number, this will effectively invalidate any value
// currently cached
time_ = -1;
in_ = -1;
out_ = -1;
}
const rational &NodeParam::LastRequestedTime()
const rational &NodeParam::LastRequestedIn()
{
return time_;
return in_;
}
bool NodeParam::ValueCachingEnabled()
+4 -3
View File
@@ -261,7 +261,7 @@ public:
/**
* @brief Retrieve the last time this parameter had a value requested from
*/
const rational& LastRequestedTime();
const rational& LastRequestedIn();
bool ValueCachingEnabled();
void SetValueCachingEnabled(bool enabled);
@@ -297,9 +297,10 @@ protected:
QVariant value_;
/**
* @brief Last timecode that a value was requested with
* @brief Last timecodes that a value was requested with
*/
rational time_;
rational in_;
rational out_;
/**
* @brief Internal value for whether value caching is enabled
+3 -2
View File
@@ -72,8 +72,9 @@ void Sequence::add_default_nodes()
audio_track_output_->SetCanBeDeleted(false);
AddNode(audio_track_output_);
// Connect track to viewer
// Connect tracks to viewer
NodeParam::ConnectEdge(video_track_output_->texture_output(), viewer_output_->texture_input());
NodeParam::ConnectEdge(audio_track_output_->samples_output(), viewer_output_->samples_input());
// Connect timeline length to viewer
NodeParam::ConnectEdge(timeline_output_->length_output(), viewer_output_->length_input());
@@ -104,7 +105,7 @@ QString Sequence::duration()
return QString();
}
rational timeline_length = timeline_output_->length_output()->get_value(0).value<rational>();
rational timeline_length = timeline_output_->length_output()->get_value(0, 0).value<rational>();
int64_t timestamp = olive::time_to_timestamp(timeline_length, video_time_base_);
@@ -130,7 +130,7 @@ void AudioRendererProcessThread::ProcessLoop()
}
// Get the requested value
texture_ = output_to_process->get_value(path_.time()).value<RenderTexturePtr>();
texture_ = output_to_process->get_value(path_.time(), path_.time()).value<RenderTexturePtr>();
render_instance()->context()->functions()->glFinish();
}
@@ -130,7 +130,7 @@ void RendererProcessThread::ProcessLoop()
}
// Get the requested value
texture_ = output_to_process->get_value(path_.time()).value<RenderTexturePtr>();
texture_ = output_to_process->get_value(path_.time(), path_.time()).value<RenderTexturePtr>();
render_instance()->context()->functions()->glFinish();
}