architecture: move loop modes to clips
This commit is contained in:
@@ -109,7 +109,7 @@ TexturePtr Decoder::RetrieveVideo(Renderer *renderer, const rational &timecode,
|
||||
return RetrieveVideoInternal(renderer, timecode, divider, cancelled);
|
||||
}
|
||||
|
||||
Decoder::RetrieveAudioStatus Decoder::RetrieveAudio(SampleBuffer &dest, const TimeRange &range, const AudioParams ¶ms, const QString& cache_path, Footage::LoopMode loop_mode, RenderMode::Mode mode)
|
||||
Decoder::RetrieveAudioStatus Decoder::RetrieveAudio(SampleBuffer &dest, const TimeRange &range, const AudioParams ¶ms, const QString& cache_path, LoopMode loop_mode, RenderMode::Mode mode)
|
||||
{
|
||||
QMutexLocker locker(&mutex_);
|
||||
|
||||
@@ -280,7 +280,7 @@ bool Decoder::ConformAudioInternal(const QVector<QString> &filenames, const Audi
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Decoder::RetrieveAudioFromConform(SampleBuffer &sample_buffer, const QVector<QString> &conform_filenames, const TimeRange& range, Footage::LoopMode loop_mode, const AudioParams &input_params)
|
||||
bool Decoder::RetrieveAudioFromConform(SampleBuffer &sample_buffer, const QVector<QString> &conform_filenames, const TimeRange& range, LoopMode loop_mode, const AudioParams &input_params)
|
||||
{
|
||||
PlanarFileDevice input;
|
||||
if (input.open(conform_filenames, QFile::ReadOnly)) {
|
||||
@@ -290,7 +290,7 @@ bool Decoder::RetrieveAudioFromConform(SampleBuffer &sample_buffer, const QVecto
|
||||
const qint64 buffer_length_in_bytes = sample_buffer.sample_count() * input_params.bytes_per_sample_per_channel();
|
||||
|
||||
while (write_index < buffer_length_in_bytes) {
|
||||
if (loop_mode == Footage::kLoopModeLoop) {
|
||||
if (loop_mode == kLoopModeLoop) {
|
||||
while (read_index >= input.size()) {
|
||||
read_index -= input.size();
|
||||
}
|
||||
|
||||
+8
-3
@@ -35,7 +35,6 @@ extern "C" {
|
||||
#include "codec/samplebuffer.h"
|
||||
#include "common/rational.h"
|
||||
#include "node/block/block.h"
|
||||
#include "node/project/footage/footage.h"
|
||||
#include "node/project/footage/footagedescription.h"
|
||||
#include "task/task.h"
|
||||
|
||||
@@ -72,6 +71,12 @@ public:
|
||||
kIndexUnavailable
|
||||
};
|
||||
|
||||
enum LoopMode {
|
||||
kLoopModeOff,
|
||||
kLoopModeLoop,
|
||||
kLoopModeClamp
|
||||
};
|
||||
|
||||
Decoder();
|
||||
|
||||
/**
|
||||
@@ -209,7 +214,7 @@ public:
|
||||
*
|
||||
* This function is thread safe and can only run while the decoder is open. \see Open()
|
||||
*/
|
||||
RetrieveAudioStatus RetrieveAudio(SampleBuffer &dest, const TimeRange& range, const AudioParams& params, const QString &cache_path, Footage::LoopMode loop_mode, RenderMode::Mode mode);
|
||||
RetrieveAudioStatus RetrieveAudio(SampleBuffer &dest, const TimeRange& range, const AudioParams& params, const QString &cache_path, LoopMode loop_mode, RenderMode::Mode mode);
|
||||
|
||||
/**
|
||||
* @brief Determine the last time this decoder instance was used in any way
|
||||
@@ -316,7 +321,7 @@ signals:
|
||||
private:
|
||||
void UpdateLastAccessed();
|
||||
|
||||
bool RetrieveAudioFromConform(SampleBuffer &sample_buffer, const QVector<QString> &conform_filenames, const TimeRange &range, Footage::LoopMode loop_mode, const AudioParams ¶ms);
|
||||
bool RetrieveAudioFromConform(SampleBuffer &sample_buffer, const QVector<QString> &conform_filenames, const TimeRange &range, LoopMode loop_mode, const AudioParams ¶ms);
|
||||
|
||||
CodecStream stream_;
|
||||
|
||||
|
||||
@@ -38,12 +38,12 @@ SpeedDurationDialog::SpeedDurationDialog(const QVector<ClipBlock *> &clips, cons
|
||||
clips_(clips),
|
||||
timebase_(timebase)
|
||||
{
|
||||
setWindowTitle(tr("Speed/Duration"));
|
||||
setWindowTitle(tr("Clip Properties"));
|
||||
|
||||
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||
|
||||
{
|
||||
QGroupBox *speed_group = new QGroupBox();
|
||||
QGroupBox *speed_group = new QGroupBox(tr("Speed/Duration"));
|
||||
layout->addWidget(speed_group);
|
||||
|
||||
QGridLayout *speed_layout = new QGridLayout(speed_group);
|
||||
@@ -72,16 +72,39 @@ SpeedDurationDialog::SpeedDurationDialog(const QVector<ClipBlock *> &clips, cons
|
||||
link_box_ = new QCheckBox(tr("Link Speed and Duration"));
|
||||
link_box_->setChecked(true);
|
||||
speed_layout->addWidget(link_box_, row, 0, 1, 2);
|
||||
}
|
||||
|
||||
row++;
|
||||
|
||||
reverse_box_ = new QCheckBox(tr("Reverse"));
|
||||
layout->addWidget(reverse_box_);
|
||||
speed_layout->addWidget(reverse_box_, row, 0, 1, 2);
|
||||
|
||||
row++;
|
||||
|
||||
maintain_audio_pitch_box_ = new QCheckBox(tr("Maintain Audio Pitch"));
|
||||
layout->addWidget(maintain_audio_pitch_box_);
|
||||
speed_layout->addWidget(maintain_audio_pitch_box_, row, 0, 1, 2);
|
||||
|
||||
row++;
|
||||
|
||||
ripple_box_ = new QCheckBox(tr("Ripple Trailing Clips"));
|
||||
layout->addWidget(ripple_box_);
|
||||
speed_layout->addWidget(ripple_box_, row, 0, 1, 2);
|
||||
}
|
||||
|
||||
{
|
||||
auto loop_box = new QGroupBox(tr("Loop"));
|
||||
layout->addWidget(loop_box);
|
||||
|
||||
auto loop_layout = new QGridLayout(loop_box);
|
||||
|
||||
int row = 0;
|
||||
|
||||
loop_layout->addWidget(new QLabel(tr("Loop:")), row, 0);
|
||||
|
||||
loop_combo_ = new QComboBox();
|
||||
loop_combo_->addItem(tr("None"), Decoder::kLoopModeOff);
|
||||
loop_combo_->addItem(tr("Loop"), Decoder::kLoopModeLoop);
|
||||
loop_combo_->addItem(tr("Clamp"), Decoder::kLoopModeClamp);
|
||||
loop_layout->addWidget(loop_combo_, row, 1);
|
||||
}
|
||||
|
||||
QDialogButtonBox *btns = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
btns->setCenterButtons(true);
|
||||
@@ -94,6 +117,7 @@ SpeedDurationDialog::SpeedDurationDialog(const QVector<ClipBlock *> &clips, cons
|
||||
start_duration_ = clips.first()->length();
|
||||
start_reverse_ = clips.first()->reverse();
|
||||
start_maintain_audio_pitch_ = clips.first()->maintain_audio_pitch();
|
||||
start_loop_ = clips.first()->loop_mode();
|
||||
for (int i=1; i<clips.size(); i++) {
|
||||
ClipBlock *c = clips.at(i);
|
||||
|
||||
@@ -116,6 +140,10 @@ SpeedDurationDialog::SpeedDurationDialog(const QVector<ClipBlock *> &clips, cons
|
||||
if (start_maintain_audio_pitch_ != -1 && clip_maintain_pitch != start_maintain_audio_pitch_) {
|
||||
start_maintain_audio_pitch_ = -1;
|
||||
}
|
||||
|
||||
if (start_loop_ != -1 && c->loop_mode() != start_loop_) {
|
||||
start_loop_ = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (qIsNaN(start_speed_)) {
|
||||
@@ -141,6 +169,12 @@ SpeedDurationDialog::SpeedDurationDialog(const QVector<ClipBlock *> &clips, cons
|
||||
} else {
|
||||
maintain_audio_pitch_box_->setChecked(start_maintain_audio_pitch_);
|
||||
}
|
||||
|
||||
if (start_loop_ == -1) {
|
||||
loop_combo_->setCurrentIndex(-1);
|
||||
} else {
|
||||
loop_combo_->setCurrentIndex(start_loop_);
|
||||
}
|
||||
}
|
||||
|
||||
void SpeedDurationDialog::accept()
|
||||
@@ -211,6 +245,12 @@ void SpeedDurationDialog::accept()
|
||||
}
|
||||
}
|
||||
|
||||
if (loop_combo_->currentIndex() != -1) {
|
||||
foreach (ClipBlock *c, clips_) {
|
||||
command->add_child(new NodeParamSetStandardValueCommand(NodeKeyframeTrackReference(NodeInput(c, ClipBlock::kLoopModeInput)), loop_combo_->currentData()));
|
||||
}
|
||||
}
|
||||
|
||||
Core::instance()->undo_stack()->push(command);
|
||||
|
||||
super::accept();
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#define SPEEDDURATIONDIALOG_H
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QComboBox>
|
||||
#include <QDialog>
|
||||
|
||||
#include "node/block/clip/clip.h"
|
||||
@@ -62,6 +63,8 @@ private:
|
||||
|
||||
QCheckBox *ripple_box_;
|
||||
|
||||
QComboBox *loop_combo_;
|
||||
|
||||
int start_reverse_;
|
||||
|
||||
int start_maintain_audio_pitch_;
|
||||
@@ -70,6 +73,8 @@ private:
|
||||
|
||||
rational start_duration_;
|
||||
|
||||
int start_loop_;
|
||||
|
||||
rational timebase_;
|
||||
|
||||
private slots:
|
||||
|
||||
@@ -34,6 +34,7 @@ const QString ClipBlock::kMediaInInput = QStringLiteral("media_in_in");
|
||||
const QString ClipBlock::kSpeedInput = QStringLiteral("speed_in");
|
||||
const QString ClipBlock::kReverseInput = QStringLiteral("reverse_in");
|
||||
const QString ClipBlock::kMaintainAudioPitchInput = QStringLiteral("maintain_audio_pitch_in");
|
||||
const QString ClipBlock::kLoopModeInput = QStringLiteral("loop_in");
|
||||
|
||||
ClipBlock::ClipBlock() :
|
||||
in_transition_(nullptr),
|
||||
@@ -56,6 +57,8 @@ ClipBlock::ClipBlock() :
|
||||
//SetValueHintForInput(kBufferIn, ValueHint(NodeValue::kBuffer));
|
||||
|
||||
SetEffectInput(kBufferIn);
|
||||
|
||||
AddInput(kLoopModeInput, NodeValue::kCombo, 0, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable));
|
||||
}
|
||||
|
||||
QString ClipBlock::Name() const
|
||||
@@ -89,7 +92,8 @@ void ClipBlock::set_length_and_media_out(const rational &length)
|
||||
|
||||
if (reverse()) {
|
||||
// Calculate media_in adjustment
|
||||
rational proposed_media_in = SequenceToMediaTime(this->length() - length, true);
|
||||
|
||||
rational proposed_media_in = SequenceToMediaTime(this->length() - length, kSTMIgnoreReverse | kSTMIgnoreLoop);
|
||||
set_media_in(proposed_media_in);
|
||||
}
|
||||
|
||||
@@ -104,7 +108,7 @@ void ClipBlock::set_length_and_media_in(const rational &length)
|
||||
|
||||
if (!reverse()) {
|
||||
// Calculate media_in adjustment
|
||||
rational proposed_media_in = SequenceToMediaTime(this->length() - length, false, true);
|
||||
rational proposed_media_in = SequenceToMediaTime(this->length() - length, kSTMIgnoreSpeed | kSTMIgnoreLoop);
|
||||
|
||||
waveform_.TrimIn(proposed_media_in - media_in());
|
||||
|
||||
@@ -127,7 +131,7 @@ void ClipBlock::set_media_in(const rational &media_in)
|
||||
SetStandardValue(kMediaInInput, QVariant::fromValue(media_in));
|
||||
}
|
||||
|
||||
rational ClipBlock::SequenceToMediaTime(const rational &sequence_time, bool ignore_reverse, bool ignore_speed) const
|
||||
rational ClipBlock::SequenceToMediaTime(const rational &sequence_time, uint64_t flags) const
|
||||
{
|
||||
// These constants are not considered "values" per se, so we don't modify them
|
||||
if (sequence_time == RATIONAL_MIN || sequence_time == RATIONAL_MAX) {
|
||||
@@ -136,11 +140,11 @@ rational ClipBlock::SequenceToMediaTime(const rational &sequence_time, bool igno
|
||||
|
||||
rational media_time = sequence_time;
|
||||
|
||||
if (reverse() && !ignore_reverse) {
|
||||
if (reverse() && !(flags & kSTMIgnoreReverse)) {
|
||||
media_time = length() - media_time;
|
||||
}
|
||||
|
||||
if (!ignore_speed) {
|
||||
if (!(flags & kSTMIgnoreSpeed)) {
|
||||
double speed_value = speed();
|
||||
if (qIsNull(speed_value)) {
|
||||
// Effectively holds the frame at the in point
|
||||
@@ -153,6 +157,23 @@ rational ClipBlock::SequenceToMediaTime(const rational &sequence_time, bool igno
|
||||
|
||||
media_time += media_in();
|
||||
|
||||
/*if (!(flags & kSTMIgnoreLoop)
|
||||
&& this->loop_mode() != kLoopModeOff
|
||||
&& connected_viewer_
|
||||
&& !connected_viewer_->GetLength().isNull()
|
||||
&& (media_time < 0 || media_time >= connected_viewer_->GetLength())) {
|
||||
if (loop_mode() == kLoopModeLoop) {
|
||||
while (media_time < 0) {
|
||||
media_time += connected_viewer_->GetLength();
|
||||
}
|
||||
while (media_time >= connected_viewer_->GetLength()) {
|
||||
media_time -= connected_viewer_->GetLength();
|
||||
}
|
||||
} else if (loop_mode() == kLoopModeClamp) {
|
||||
media_time = std::clamp(media_time, rational(0), connected_viewer_->GetLength()-connected_viewer_->GetVideoParams().frame_rate_as_time_base());
|
||||
}
|
||||
}*/
|
||||
|
||||
return media_time;
|
||||
}
|
||||
|
||||
@@ -282,6 +303,8 @@ void ClipBlock::Retranslate()
|
||||
SetInputName(kSpeedInput, tr("Speed"));
|
||||
SetInputName(kReverseInput, tr("Reverse"));
|
||||
SetInputName(kMaintainAudioPitchInput, tr("Maintain Audio Pitch"));
|
||||
SetInputName(kLoopModeInput, tr("Loop"));
|
||||
SetComboBoxStrings(kLoopModeInput, {tr("None"), tr("Loop"), tr("Clamp")});
|
||||
}
|
||||
|
||||
TimeRange ClipBlock::media_range() const
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#define CLIPBLOCK_H
|
||||
|
||||
#include "audio/audiovisualwaveform.h"
|
||||
#include "codec/decoder.h"
|
||||
#include "node/block/block.h"
|
||||
|
||||
namespace olive {
|
||||
@@ -121,17 +122,39 @@ public:
|
||||
|
||||
TimeRange media_range() const;
|
||||
|
||||
/**
|
||||
* @brief Get currently set loop mode
|
||||
*/
|
||||
Decoder::LoopMode loop_mode() const
|
||||
{
|
||||
return static_cast<Decoder::LoopMode>(GetStandardValue(kLoopModeInput).toInt());
|
||||
}
|
||||
|
||||
void set_loop_mode(Decoder::LoopMode l)
|
||||
{
|
||||
SetStandardValue(kLoopModeInput, int(l));
|
||||
}
|
||||
|
||||
static const QString kBufferIn;
|
||||
static const QString kMediaInInput;
|
||||
static const QString kSpeedInput;
|
||||
static const QString kReverseInput;
|
||||
static const QString kMaintainAudioPitchInput;
|
||||
static const QString kLoopModeInput;
|
||||
|
||||
protected:
|
||||
virtual void LinkChangeEvent() override;
|
||||
|
||||
private:
|
||||
rational SequenceToMediaTime(const rational& sequence_time, bool ignore_reverse = false, bool ignore_speed = false) const;
|
||||
enum SequenceToMediaTimeFlag
|
||||
{
|
||||
kSTMNone,
|
||||
kSTMIgnoreReverse,
|
||||
kSTMIgnoreSpeed,
|
||||
kSTMIgnoreLoop
|
||||
};
|
||||
|
||||
rational SequenceToMediaTime(const rational& sequence_time, uint64_t flags = kSTMNone) const;
|
||||
|
||||
rational MediaToSequenceTime(const rational& media_time) const;
|
||||
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
namespace olive {
|
||||
|
||||
const QString Footage::kFilenameInput = QStringLiteral("file_in");
|
||||
const QString Footage::kLoopModeInput = QStringLiteral("loop_in");
|
||||
|
||||
#define super ViewerOutput
|
||||
|
||||
@@ -49,8 +48,6 @@ Footage::Footage(const QString &filename) :
|
||||
{
|
||||
SetCacheTextures(true);
|
||||
|
||||
PrependInput(kLoopModeInput, NodeValue::kCombo, 0, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable));
|
||||
|
||||
PrependInput(kFilenameInput, NodeValue::kFile, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable));
|
||||
|
||||
Clear();
|
||||
@@ -70,8 +67,6 @@ void Footage::Retranslate()
|
||||
super::Retranslate();
|
||||
|
||||
SetInputName(kFilenameInput, tr("Filename"));
|
||||
SetInputName(kLoopModeInput, tr("Loop Mode"));
|
||||
SetComboBoxStrings(kLoopModeInput, {tr("None"), tr("Loop"), tr("Clamp")});
|
||||
}
|
||||
|
||||
void Footage::InputValueChangedEvent(const QString &input, int element)
|
||||
@@ -139,11 +134,6 @@ void Footage::SetValid()
|
||||
valid_ = true;
|
||||
}
|
||||
|
||||
Footage::LoopMode Footage::loop_mode() const
|
||||
{
|
||||
return static_cast<LoopMode>(GetStandardValue(kLoopModeInput).toInt());
|
||||
}
|
||||
|
||||
QString Footage::filename() const
|
||||
{
|
||||
return GetStandardValue(kFilenameInput).toString();
|
||||
@@ -263,17 +253,15 @@ void Footage::Value(const NodeValueRow &value, const NodeGlobals &globals, NodeV
|
||||
// Pop filename from table
|
||||
QString file = value[kFilenameInput].toString();
|
||||
|
||||
LoopMode loop_mode = static_cast<LoopMode>(value[kLoopModeInput].toInt());
|
||||
|
||||
// If the file exists and the reference is valid, push a footage job to the renderer
|
||||
if (QFileInfo(file).exists()) {
|
||||
if (QFileInfo::exists(file)) {
|
||||
// Push length
|
||||
table->Push(NodeValue::kRational, QVariant::fromValue(GetLength()), this, false, QStringLiteral("length"));
|
||||
table->Push(NodeValue::kRational, QVariant::fromValue(GetLength()), this, QStringLiteral("length"));
|
||||
|
||||
// Push each stream as a footage job
|
||||
for (int i=0; i<GetTotalStreamCount(); i++) {
|
||||
Track::Reference ref = GetReferenceFromRealIndex(i);
|
||||
FootageJob job(decoder_, filename(), ref.type(), GetLength(), loop_mode);
|
||||
FootageJob job(decoder_, filename(), ref.type(), GetLength());
|
||||
|
||||
NodeValue::Type type;
|
||||
|
||||
@@ -339,7 +327,7 @@ bool TimeIsOutOfBounds(const rational& time, const rational& length)
|
||||
return time < 0 || time >= length;
|
||||
}
|
||||
|
||||
rational Footage::AdjustTimeByLoopMode(rational time, Footage::LoopMode loop_mode, const rational &length, VideoParams::Type type, const rational& timebase)
|
||||
rational Footage::AdjustTimeByLoopMode(rational time, Decoder::LoopMode loop_mode, const rational &length, VideoParams::Type type, const rational& timebase)
|
||||
{
|
||||
if (type == VideoParams::kVideoTypeStill) {
|
||||
// No looping for still images
|
||||
@@ -348,15 +336,15 @@ rational Footage::AdjustTimeByLoopMode(rational time, Footage::LoopMode loop_mod
|
||||
|
||||
if (TimeIsOutOfBounds(time, length)) {
|
||||
switch (loop_mode) {
|
||||
case kLoopModeOff:
|
||||
case Decoder::kLoopModeOff:
|
||||
// Return no time to indicate no frame should be shown here
|
||||
time = rational::NaN;
|
||||
break;
|
||||
case kLoopModeClamp:
|
||||
case Decoder::kLoopModeClamp:
|
||||
// Clamp footage time to length
|
||||
time = clamp(time, rational(0), length - timebase);
|
||||
break;
|
||||
case kLoopModeLoop:
|
||||
case Decoder::kLoopModeLoop:
|
||||
// Loop footage time around job length
|
||||
do {
|
||||
if (time >= length) {
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <QList>
|
||||
#include <QDateTime>
|
||||
|
||||
#include "codec/decoder.h"
|
||||
#include "common/rational.h"
|
||||
#include "footagedescription.h"
|
||||
#include "node/output/viewer/viewer.h"
|
||||
@@ -44,12 +45,6 @@ class Footage : public ViewerOutput
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum LoopMode {
|
||||
kLoopModeOff,
|
||||
kLoopModeLoop,
|
||||
kLoopModeClamp
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Footage Constructor
|
||||
*/
|
||||
@@ -101,11 +96,6 @@ public:
|
||||
*/
|
||||
void SetValid();
|
||||
|
||||
/**
|
||||
* @brief Get currently set loop mode
|
||||
*/
|
||||
LoopMode loop_mode() const;
|
||||
|
||||
/**
|
||||
* @brief Return the current filename of this Footage object
|
||||
*/
|
||||
@@ -183,7 +173,7 @@ public:
|
||||
|
||||
virtual Node *GetConnectedSampleOutput() override;
|
||||
|
||||
static rational AdjustTimeByLoopMode(rational time, LoopMode loop_mode, const rational& length, VideoParams::Type type, const rational &timebase);
|
||||
static rational AdjustTimeByLoopMode(rational time, Decoder::LoopMode loop_mode, const rational& length, VideoParams::Type type, const rational &timebase);
|
||||
|
||||
virtual void LoadFinishedEvent() override;
|
||||
|
||||
@@ -191,7 +181,6 @@ public:
|
||||
virtual qint64 mod_time() const override;
|
||||
|
||||
static const QString kFilenameInput;
|
||||
static const QString kLoopModeInput;
|
||||
|
||||
protected:
|
||||
virtual void InputValueChangedEvent(const QString &input, int element) override;
|
||||
|
||||
+12
-2
@@ -21,6 +21,7 @@
|
||||
#include "traverser.h"
|
||||
|
||||
#include "node.h"
|
||||
#include "node/block/clip/clip.h"
|
||||
#include "render/job/footagejob.h"
|
||||
#include "render/rendermanager.h"
|
||||
|
||||
@@ -30,6 +31,12 @@ NodeValueDatabase NodeTraverser::GenerateDatabase(const Node* node, const TimeRa
|
||||
{
|
||||
NodeValueDatabase database;
|
||||
|
||||
// HACK: Pick up loop mode from clips
|
||||
Decoder::LoopMode old_loop_mode = loop_mode_;
|
||||
if (const ClipBlock *clip = dynamic_cast<const ClipBlock*>(node)) {
|
||||
loop_mode_ = clip->loop_mode();
|
||||
}
|
||||
|
||||
// We need to insert tables into the database for each input
|
||||
foreach (const QString& input, node->inputs()) {
|
||||
if (IsCancelled()) {
|
||||
@@ -39,6 +46,8 @@ NodeValueDatabase NodeTraverser::GenerateDatabase(const Node* node, const TimeRa
|
||||
database.Insert(input, ProcessInput(node, input, range));
|
||||
}
|
||||
|
||||
loop_mode_ = old_loop_mode;
|
||||
|
||||
return database;
|
||||
}
|
||||
|
||||
@@ -260,7 +269,8 @@ NodeValueTable NodeTraverser::ProcessInput(const Node* node, const QString& inpu
|
||||
|
||||
NodeTraverser::NodeTraverser() :
|
||||
cancel_(nullptr),
|
||||
transform_(nullptr)
|
||||
transform_(nullptr),
|
||||
loop_mode_(Decoder::kLoopModeOff)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -436,7 +446,7 @@ void NodeTraverser::ResolveJobs(NodeValue &val, const TimeRange &range)
|
||||
|
||||
if (job.type() == Track::kVideo) {
|
||||
|
||||
rational footage_time = Footage::AdjustTimeByLoopMode(range.in(), job.loop_mode(), job.length(), job.video_params().video_type(), job.video_params().frame_rate_as_time_base());
|
||||
rational footage_time = Footage::AdjustTimeByLoopMode(range.in(), loop_mode_, job.length(), job.video_params().video_type(), job.video_params().frame_rate_as_time_base());
|
||||
|
||||
TexturePtr tex;
|
||||
|
||||
|
||||
@@ -149,6 +149,8 @@ protected:
|
||||
return block_stack_.empty() ? nullptr : block_stack_.back();
|
||||
}
|
||||
|
||||
Decoder::LoopMode loop_mode() const { return loop_mode_; }
|
||||
|
||||
private:
|
||||
void PreProcessRow(const TimeRange &range, NodeValueRow &row);
|
||||
|
||||
@@ -166,6 +168,8 @@ private:
|
||||
|
||||
std::list<Block*> block_stack_;
|
||||
|
||||
Decoder::LoopMode loop_mode_;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -29,17 +29,15 @@ class FootageJob
|
||||
{
|
||||
public:
|
||||
FootageJob() :
|
||||
type_(Track::kNone),
|
||||
loop_mode_(Footage::kLoopModeOff)
|
||||
type_(Track::kNone)
|
||||
{
|
||||
}
|
||||
|
||||
FootageJob(const QString& decoder, const QString& filename, Track::Type type, const rational& length, Footage::LoopMode loop_mode) :
|
||||
FootageJob(const QString& decoder, const QString& filename, Track::Type type, const rational& length) :
|
||||
decoder_(decoder),
|
||||
filename_(filename),
|
||||
type_(type),
|
||||
length_(length),
|
||||
loop_mode_(loop_mode)
|
||||
length_(length)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -98,16 +96,6 @@ public:
|
||||
length_ = length;
|
||||
}
|
||||
|
||||
Footage::LoopMode loop_mode() const
|
||||
{
|
||||
return loop_mode_;
|
||||
}
|
||||
|
||||
void set_loop_mode(Footage::LoopMode loop_mode)
|
||||
{
|
||||
loop_mode_ = loop_mode;
|
||||
}
|
||||
|
||||
private:
|
||||
QString decoder_;
|
||||
|
||||
@@ -123,8 +111,6 @@ private:
|
||||
|
||||
rational length_;
|
||||
|
||||
Footage::LoopMode loop_mode_;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -503,7 +503,7 @@ void RenderProcessor::ProcessAudioFootage(SampleBuffer &destination, const Foota
|
||||
Decoder::RetrieveAudioStatus status = decoder->RetrieveAudio(destination,
|
||||
input_time, audio_params,
|
||||
stream.cache_path(),
|
||||
stream.loop_mode(),
|
||||
loop_mode(),
|
||||
static_cast<RenderMode::Mode>(ticket_->property("mode").toInt()));
|
||||
|
||||
if (status == Decoder::kWaitingForConform) {
|
||||
|
||||
@@ -531,20 +531,47 @@ void TimelineView::DrawBlock(QPainter *painter, bool foreground, Block *block, q
|
||||
// Draw zebra stripes and markers
|
||||
if (clip->connected_viewer()) {
|
||||
if (!clip->connected_viewer()->GetLength().isNull()) {
|
||||
painter->setPen(shadow_color);
|
||||
|
||||
if (clip->media_in() < 0) {
|
||||
qreal zebra_right = TimeToScene(clip->in() - clip->media_in());
|
||||
|
||||
switch (clip->loop_mode()) {
|
||||
case Decoder::kLoopModeOff:
|
||||
// Draw stripes for sections of clip < 0
|
||||
qreal zebra_right = TimeToScene(-clip->media_in());
|
||||
if (zebra_right > GetTimelineLeftBound()) {
|
||||
DrawZebraStripes(painter, QRectF(block_left, block_top, zebra_right, block_height));
|
||||
DrawZebraStripes(painter, QRectF(block_left, block_top, zebra_right - block_left, block_height));
|
||||
}
|
||||
break;
|
||||
case Decoder::kLoopModeLoop:
|
||||
for (qreal i=zebra_right; i>block_left; i-=TimeToScene(clip->connected_viewer()->GetLength())) {
|
||||
painter->drawLine(i, block_top, i, block_top + block_height);
|
||||
}
|
||||
break;
|
||||
case Decoder::kLoopModeClamp:
|
||||
painter->drawLine(zebra_right, block_top, zebra_right, block_top + block_height);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (clip->length() + clip->media_in() > clip->connected_viewer()->GetLength()) {
|
||||
// Draw stripes for sections for clip > clip length
|
||||
qreal zebra_left = TimeToScene(clip->out() - (clip->media_in() + clip->length() - clip->connected_viewer()->GetLength()));
|
||||
switch (clip->loop_mode()) {
|
||||
case Decoder::kLoopModeOff:
|
||||
// Draw stripes for sections for clip > clip length
|
||||
if (zebra_left < GetTimelineRightBound()) {
|
||||
DrawZebraStripes(painter, QRectF(zebra_left, block_top, block_right - zebra_left, block_height));
|
||||
}
|
||||
break;
|
||||
case Decoder::kLoopModeLoop:
|
||||
for (qreal i=zebra_left; i<block_right; i+=TimeToScene(clip->connected_viewer()->GetLength())) {
|
||||
painter->drawLine(i, block_top, i, block_top + block_height);
|
||||
}
|
||||
break;
|
||||
case Decoder::kLoopModeClamp:
|
||||
painter->drawLine(zebra_left, block_top, zebra_left, block_top + block_height);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user