refactored so sequence is again a derivative of viewer
This commit is contained in:
+9
-6
@@ -342,10 +342,11 @@ void Core::DialogPreferencesShow()
|
||||
|
||||
void Core::DialogExportShow()
|
||||
{
|
||||
Sequence* viewer = GetSequenceToExport();
|
||||
ViewerOutput* viewer;
|
||||
TimelinePoints* points;
|
||||
|
||||
if (viewer) {
|
||||
ExportDialog* ed = new ExportDialog(viewer, main_window_);
|
||||
if (GetSequenceToExport(&viewer, &points) && viewer) {
|
||||
ExportDialog* ed = new ExportDialog(viewer, points, main_window_);
|
||||
connect(ed, &ExportDialog::finished, ed, &ExportDialog::deleteLater);
|
||||
ed->open();
|
||||
}
|
||||
@@ -751,7 +752,7 @@ void Core::SaveProjectInternal(Project* project, const QString& override_filenam
|
||||
task_dialog->open();
|
||||
}
|
||||
|
||||
Sequence *Core::GetSequenceToExport()
|
||||
bool Core::GetSequenceToExport(ViewerOutput** viewer, TimelinePoints** points)
|
||||
{
|
||||
// First try the most recently focused time based window
|
||||
TimeBasedPanel* time_panel = PanelManager::instance()->MostRecentlyFocused<TimeBasedPanel>();
|
||||
@@ -769,7 +770,9 @@ Sequence *Core::GetSequenceToExport()
|
||||
tr("This Sequence is empty. There is nothing to export."),
|
||||
QMessageBox::Ok);
|
||||
} else {
|
||||
return time_panel->GetConnectedViewer();
|
||||
*viewer = time_panel->GetConnectedViewer();
|
||||
*points = time_panel->GetConnectedTimelinePoints();
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
QMessageBox::critical(main_window_,
|
||||
@@ -778,7 +781,7 @@ Sequence *Core::GetSequenceToExport()
|
||||
QMessageBox::Ok);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
QString Core::GetAutoRecoveryIndexFilename()
|
||||
|
||||
+1
-1
@@ -496,7 +496,7 @@ private:
|
||||
/**
|
||||
* @brief Retrieves the currently most active sequence for exporting
|
||||
*/
|
||||
Sequence* GetSequenceToExport();
|
||||
bool GetSequenceToExport(ViewerOutput **viewer, TimelinePoints **points);
|
||||
|
||||
static QString GetAutoRecoveryIndexFilename();
|
||||
|
||||
|
||||
@@ -39,9 +39,10 @@
|
||||
|
||||
namespace olive {
|
||||
|
||||
ExportDialog::ExportDialog(Sequence *sequence, QWidget *parent) :
|
||||
ExportDialog::ExportDialog(ViewerOutput *viewer_node, TimelinePoints *points, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
sequence_(sequence)
|
||||
viewer_node_(viewer_node),
|
||||
timeline_points_(points)
|
||||
{
|
||||
QHBoxLayout* layout = new QHBoxLayout(this);
|
||||
|
||||
@@ -104,7 +105,7 @@ ExportDialog::ExportDialog(Sequence *sequence, QWidget *parent) :
|
||||
range_combobox_ = new QComboBox();
|
||||
range_combobox_->addItem(tr("Entire Sequence"));
|
||||
range_combobox_->addItem(tr("In to Out"));
|
||||
range_combobox_->setEnabled(sequence_->timeline_points()->workarea()->enabled());
|
||||
range_combobox_->setEnabled(timeline_points_ && timeline_points_->workarea()->enabled());
|
||||
|
||||
preferences_layout->addWidget(range_combobox_, row, 1, 1, 3);
|
||||
|
||||
@@ -136,7 +137,7 @@ ExportDialog::ExportDialog(Sequence *sequence, QWidget *parent) :
|
||||
|
||||
QTabWidget* preferences_tabs = new QTabWidget();
|
||||
QScrollArea* video_area = new QScrollArea();
|
||||
color_manager_ = sequence_->project()->color_manager();
|
||||
color_manager_ = viewer_node_->project()->color_manager();
|
||||
video_tab_ = new ExportVideoTab(color_manager_);
|
||||
video_area->setWidgetResizable(true);
|
||||
video_area->setWidget(video_tab_);
|
||||
@@ -188,18 +189,18 @@ ExportDialog::ExportDialog(Sequence *sequence, QWidget *parent) :
|
||||
&ExportDialog::FormatChanged);
|
||||
FormatChanged(ExportFormat::kFormatMPEG4);
|
||||
|
||||
video_tab_->width_slider()->SetValue(sequence_->video_params().width());
|
||||
video_tab_->width_slider()->SetDefaultValue(sequence_->video_params().width());
|
||||
video_tab_->height_slider()->SetValue(sequence_->video_params().height());
|
||||
video_tab_->height_slider()->SetDefaultValue(sequence_->video_params().height());
|
||||
video_tab_->frame_rate_combobox()->SetFrameRate(sequence_->video_params().time_base().flipped());
|
||||
video_tab_->pixel_aspect_combobox()->SetPixelAspectRatio(sequence_->video_params().pixel_aspect_ratio());
|
||||
video_tab_->width_slider()->SetValue(viewer_node_->video_params().width());
|
||||
video_tab_->width_slider()->SetDefaultValue(viewer_node_->video_params().width());
|
||||
video_tab_->height_slider()->SetValue(viewer_node_->video_params().height());
|
||||
video_tab_->height_slider()->SetDefaultValue(viewer_node_->video_params().height());
|
||||
video_tab_->frame_rate_combobox()->SetFrameRate(viewer_node_->video_params().time_base().flipped());
|
||||
video_tab_->pixel_aspect_combobox()->SetPixelAspectRatio(viewer_node_->video_params().pixel_aspect_ratio());
|
||||
video_tab_->pixel_format_field()->SetPixelFormat(static_cast<VideoParams::Format>(Config::Current()["OnlinePixelFormat"].toInt()));
|
||||
video_tab_->interlaced_combobox()->SetInterlaceMode(sequence_->video_params().interlacing());
|
||||
audio_tab_->sample_rate_combobox()->SetSampleRate(sequence_->audio_params().sample_rate());
|
||||
audio_tab_->channel_layout_combobox()->SetChannelLayout(sequence_->audio_params().channel_layout());
|
||||
video_tab_->interlaced_combobox()->SetInterlaceMode(viewer_node_->video_params().interlacing());
|
||||
audio_tab_->sample_rate_combobox()->SetSampleRate(viewer_node_->audio_params().sample_rate());
|
||||
audio_tab_->channel_layout_combobox()->SetChannelLayout(viewer_node_->audio_params().channel_layout());
|
||||
|
||||
video_aspect_ratio_ = static_cast<double>(sequence_->video_params().width()) / static_cast<double>(sequence_->video_params().height());
|
||||
video_aspect_ratio_ = static_cast<double>(viewer_node_->video_params().width()) / static_cast<double>(viewer_node_->video_params().height());
|
||||
|
||||
connect(video_tab_->width_slider(),
|
||||
&IntegerSlider::ValueChanged,
|
||||
@@ -227,8 +228,8 @@ ExportDialog::ExportDialog(Sequence *sequence, QWidget *parent) :
|
||||
static_cast<void(ViewerWidget::*)(const ColorTransform&)>(&ViewerWidget::SetColorTransform));
|
||||
|
||||
// Set viewer to view the node
|
||||
preview_viewer_->ConnectViewerNode(sequence_);
|
||||
preview_viewer_->ruler()->ConnectTimelinePoints(sequence_->timeline_points());
|
||||
preview_viewer_->ConnectViewerNode(viewer_node_);
|
||||
preview_viewer_->ruler()->ConnectTimelinePoints(timeline_points_);
|
||||
preview_viewer_->SetColorMenuEnabled(false);
|
||||
preview_viewer_->SetColorTransform(video_tab_->CurrentOCIOColorSpace());
|
||||
}
|
||||
@@ -315,7 +316,7 @@ void ExportDialog::StartExport()
|
||||
return;
|
||||
}
|
||||
|
||||
ExportTask* task = new ExportTask(sequence_, color_manager_, GenerateParams());
|
||||
ExportTask* task = new ExportTask(viewer_node_, color_manager_, GenerateParams());
|
||||
TaskDialog* td = new TaskDialog(task, tr("Export"), this);
|
||||
connect(td, &TaskDialog::TaskSucceeded, this, &ExportDialog::ExportFinished);
|
||||
td->open();
|
||||
@@ -428,7 +429,7 @@ void ExportDialog::LoadPresets()
|
||||
|
||||
void ExportDialog::SetDefaultFilename()
|
||||
{
|
||||
Project* p = sequence_->project();
|
||||
Project* p = viewer_node_->project();
|
||||
|
||||
QDir doc_location;
|
||||
|
||||
@@ -438,7 +439,7 @@ void ExportDialog::SetDefaultFilename()
|
||||
doc_location = QFileInfo(p->filename()).dir();
|
||||
}
|
||||
|
||||
QString file_location = doc_location.filePath(sequence_->GetLabel());
|
||||
QString file_location = doc_location.filePath(viewer_node_->GetLabel());
|
||||
filename_edit_->setText(file_location);
|
||||
}
|
||||
|
||||
@@ -459,11 +460,12 @@ ExportParams ExportDialog::GenerateParams() const
|
||||
|
||||
ExportParams params;
|
||||
params.SetFilename(filename_edit_->text().trimmed());
|
||||
params.SetExportLength(sequence_->GetLength());
|
||||
params.SetExportLength(viewer_node_->GetLength());
|
||||
|
||||
if (range_combobox_->currentIndex() == kRangeInToOut
|
||||
&& sequence_->timeline_points()->workarea()->enabled()) {
|
||||
params.set_custom_range(sequence_->timeline_points()->workarea()->range());
|
||||
if (range_combobox_->isEnabled() && range_combobox_->currentIndex() == kRangeInToOut) {
|
||||
// Assume if this combobox is enabled, that we have timeline points - a check that we make
|
||||
// in this dialog's constructor
|
||||
params.set_custom_range(timeline_points_->workarea()->range());
|
||||
}
|
||||
|
||||
if (video_tab_->scaling_method_combobox()->isEnabled()) {
|
||||
@@ -500,8 +502,8 @@ void ExportDialog::UpdateViewerDimensions()
|
||||
|
||||
QMatrix4x4 transform =
|
||||
ExportParams::GenerateMatrix(static_cast<ExportParams::VideoScalingMethod>(video_tab_->scaling_method_combobox()->currentData().toInt()),
|
||||
sequence_->video_params().width(),
|
||||
sequence_->video_params().height(),
|
||||
viewer_node_->video_params().width(),
|
||||
viewer_node_->video_params().height(),
|
||||
static_cast<int>(video_tab_->width_slider()->GetValue()),
|
||||
static_cast<int>(video_tab_->height_slider()->GetValue()));
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ class ExportDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ExportDialog(Sequence* sequence, QWidget* parent = nullptr);
|
||||
ExportDialog(ViewerOutput* viewer_node, TimelinePoints* points, QWidget* parent = nullptr);
|
||||
|
||||
protected:
|
||||
virtual void closeEvent(QCloseEvent *e) override;
|
||||
@@ -51,7 +51,8 @@ private:
|
||||
|
||||
ExportParams GenerateParams() const;
|
||||
|
||||
Sequence* sequence_;
|
||||
ViewerOutput* viewer_node_;
|
||||
TimelinePoints* timeline_points_;
|
||||
|
||||
ExportFormat::Format previously_selected_format_;
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "node/math/math/math.h"
|
||||
#include "node/math/merge/merge.h"
|
||||
#include "node/output/viewer/viewer.h"
|
||||
#include "project/item/sequence/sequence.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
|
||||
@@ -20,13 +20,39 @@
|
||||
|
||||
#include "viewer.h"
|
||||
|
||||
#include "config/config.h"
|
||||
#include "core.h"
|
||||
#include "node/traverser.h"
|
||||
#include "widget/videoparamedit/videoparamedit.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
#define super Sequence
|
||||
const QString ViewerOutput::kVideoParamsInput = QStringLiteral("video_param_in");
|
||||
const QString ViewerOutput::kAudioParamsInput = QStringLiteral("audio_param_in");
|
||||
const QString ViewerOutput::kTextureInput = QStringLiteral("tex_in");
|
||||
const QString ViewerOutput::kSamplesInput = QStringLiteral("samples_in");
|
||||
|
||||
const uint64_t ViewerOutput::kVideoParamEditMask = VideoParamEdit::kWidthHeight | VideoParamEdit::kInterlacing | VideoParamEdit::kFrameRate | VideoParamEdit::kPixelAspect;
|
||||
|
||||
#define super Node
|
||||
|
||||
ViewerOutput::ViewerOutput() :
|
||||
Sequence(true)
|
||||
video_frame_cache_(this),
|
||||
audio_playback_cache_(this),
|
||||
operation_stack_(0)
|
||||
{
|
||||
AddInput(kVideoParamsInput, NodeValue::kVideoParams, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable));
|
||||
SetInputProperty(kVideoParamsInput, QStringLiteral("mask"), QVariant::fromValue(kVideoParamEditMask));
|
||||
|
||||
AddInput(kAudioParamsInput, NodeValue::kAudioParams, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable));
|
||||
|
||||
AddInput(kTextureInput, NodeValue::kTexture, InputFlags(kInputFlagNotKeyframable));
|
||||
AddInput(kSamplesInput, NodeValue::kSamples, InputFlags(kInputFlagNotKeyframable));
|
||||
}
|
||||
|
||||
ViewerOutput::~ViewerOutput()
|
||||
{
|
||||
DisconnectAll();
|
||||
}
|
||||
|
||||
Node *ViewerOutput::copy() const
|
||||
@@ -54,4 +80,275 @@ QString ViewerOutput::Description() const
|
||||
return tr("Interface between a Viewer panel and the node system.");
|
||||
}
|
||||
|
||||
QString ViewerOutput::duration() const
|
||||
{
|
||||
rational timeline_length = GetLength();
|
||||
|
||||
int64_t timestamp = Timecode::time_to_timestamp(timeline_length, video_params().time_base());
|
||||
|
||||
return Timecode::timestamp_to_timecode(timestamp, video_params().time_base(), Core::instance()->GetTimecodeDisplay());
|
||||
}
|
||||
|
||||
QString ViewerOutput::rate() const
|
||||
{
|
||||
return tr("%1 FPS").arg(video_params().time_base().flipped().toDouble());
|
||||
}
|
||||
|
||||
void ViewerOutput::set_default_parameters()
|
||||
{
|
||||
int width = Config::Current()["DefaultSequenceWidth"].toInt();
|
||||
int height = Config::Current()["DefaultSequenceHeight"].toInt();
|
||||
|
||||
set_video_params(VideoParams(width,
|
||||
height,
|
||||
Config::Current()["DefaultSequenceFrameRate"].value<rational>(),
|
||||
static_cast<VideoParams::Format>(Config::Current()["OfflinePixelFormat"].toInt()),
|
||||
VideoParams::kInternalChannelCount,
|
||||
Config::Current()["DefaultSequencePixelAspect"].value<rational>(),
|
||||
Config::Current()["DefaultSequenceInterlacing"].value<VideoParams::Interlacing>(),
|
||||
VideoParams::generate_auto_divider(width, height)));
|
||||
set_audio_params(AudioParams(Config::Current()["DefaultSequenceAudioFrequency"].toInt(),
|
||||
Config::Current()["DefaultSequenceAudioLayout"].toULongLong(),
|
||||
AudioParams::kInternalFormat));
|
||||
}
|
||||
|
||||
void ViewerOutput::ShiftVideoCache(const rational &from, const rational &to)
|
||||
{
|
||||
video_frame_cache_.Shift(from, to);
|
||||
|
||||
ShiftVideoEvent(from, to);
|
||||
}
|
||||
|
||||
void ViewerOutput::ShiftAudioCache(const rational &from, const rational &to)
|
||||
{
|
||||
audio_playback_cache_.Shift(from, to);
|
||||
|
||||
ShiftAudioEvent(from, to);
|
||||
}
|
||||
|
||||
void ViewerOutput::ShiftCache(const rational &from, const rational &to)
|
||||
{
|
||||
ShiftVideoCache(from, to);
|
||||
ShiftAudioCache(from, to);
|
||||
}
|
||||
|
||||
void ViewerOutput::InvalidateCache(const TimeRange& range, const QString& from, int element, qint64 job_time)
|
||||
{
|
||||
Q_UNUSED(element)
|
||||
|
||||
if (operation_stack_ == 0) {
|
||||
if (from == kTextureInput || from == kSamplesInput
|
||||
|| from == kVideoParamsInput || from == kAudioParamsInput) {
|
||||
TimeRange invalidated_range(qMax(rational(), range.in()),
|
||||
qMin(GetLength(), range.out()));
|
||||
|
||||
if (invalidated_range.in() != invalidated_range.out()) {
|
||||
if (from == kTextureInput || from == kVideoParamsInput) {
|
||||
video_frame_cache_.Invalidate(invalidated_range, job_time);
|
||||
} else {
|
||||
audio_playback_cache_.Invalidate(invalidated_range, job_time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VerifyLength();
|
||||
}
|
||||
|
||||
super::InvalidateCache(range, from, element, job_time);
|
||||
}
|
||||
|
||||
const rational& ViewerOutput::GetLength() const
|
||||
{
|
||||
return last_length_;
|
||||
}
|
||||
|
||||
void ViewerOutput::Retranslate()
|
||||
{
|
||||
super::Retranslate();
|
||||
|
||||
SetInputName(kVideoParamsInput, tr("Video Parameters"));
|
||||
SetInputName(kAudioParamsInput, tr("Audio Parameters"));
|
||||
|
||||
SetInputName(kTextureInput, tr("Texture"));
|
||||
SetInputName(kSamplesInput, tr("Samples"));
|
||||
}
|
||||
|
||||
void ViewerOutput::VerifyLength()
|
||||
{
|
||||
if (operation_stack_ != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
NodeTraverser traverser;
|
||||
|
||||
rational video_length, audio_length, subtitle_length;
|
||||
|
||||
{
|
||||
video_length = GetCustomLength(Track::kVideo);
|
||||
|
||||
if (video_length.isNull() && IsInputConnected(kTextureInput)) {
|
||||
NodeValueTable t = traverser.GenerateTable(GetConnectedOutput(kTextureInput), TimeRange(0, 0));
|
||||
video_length = t.Get(NodeValue::kRational, QStringLiteral("length")).value<rational>();
|
||||
}
|
||||
|
||||
video_frame_cache_.SetLength(video_length);
|
||||
}
|
||||
|
||||
{
|
||||
audio_length = GetCustomLength(Track::kAudio);
|
||||
|
||||
if (audio_length.isNull() && IsInputConnected(kSamplesInput)) {
|
||||
NodeValueTable t = traverser.GenerateTable(GetConnectedOutput(kSamplesInput), TimeRange(0, 0));
|
||||
audio_length = t.Get(NodeValue::kRational, QStringLiteral("length")).value<rational>();
|
||||
}
|
||||
|
||||
audio_playback_cache_.SetLength(audio_length);
|
||||
}
|
||||
|
||||
{
|
||||
subtitle_length = GetCustomLength(Track::kSubtitle);
|
||||
}
|
||||
|
||||
rational real_length = qMax(subtitle_length, qMax(video_length, audio_length));
|
||||
|
||||
if (real_length != last_length_) {
|
||||
last_length_ = real_length;
|
||||
emit LengthChanged(last_length_);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewerOutput::InputConnectedEvent(const QString &input, int element, const NodeOutput &output)
|
||||
{
|
||||
if (input == kTextureInput) {
|
||||
emit TextureInputChanged();
|
||||
}
|
||||
|
||||
super::InputConnectedEvent(input, element, output);
|
||||
}
|
||||
|
||||
void ViewerOutput::InputDisconnectedEvent(const QString &input, int element, const NodeOutput &output)
|
||||
{
|
||||
if (input == kTextureInput) {
|
||||
emit TextureInputChanged();
|
||||
}
|
||||
|
||||
super::InputDisconnectedEvent(input, element, output);
|
||||
}
|
||||
|
||||
rational ViewerOutput::GetCustomLength(Track::Type type) const
|
||||
{
|
||||
Q_UNUSED(type)
|
||||
return rational();
|
||||
}
|
||||
|
||||
void ViewerOutput::BeginOperation()
|
||||
{
|
||||
operation_stack_++;
|
||||
|
||||
super::BeginOperation();
|
||||
}
|
||||
|
||||
void ViewerOutput::EndOperation()
|
||||
{
|
||||
operation_stack_--;
|
||||
|
||||
super::EndOperation();
|
||||
}
|
||||
|
||||
void ViewerOutput::InputValueChangedEvent(const QString &input, int element)
|
||||
{
|
||||
if (input == kVideoParamsInput) {
|
||||
|
||||
VideoParams new_video_params = video_params();
|
||||
|
||||
bool size_changed = cached_video_params_.width() != new_video_params.width() || cached_video_params_.height() != new_video_params.height();
|
||||
bool timebase_changed = cached_video_params_.time_base() != new_video_params.time_base();
|
||||
bool pixel_aspect_changed = cached_video_params_.pixel_aspect_ratio() != new_video_params.pixel_aspect_ratio();
|
||||
bool interlacing_changed = cached_video_params_.interlacing() != new_video_params.interlacing();
|
||||
|
||||
if (size_changed) {
|
||||
emit SizeChanged(new_video_params.width(), new_video_params.height());
|
||||
}
|
||||
|
||||
if (pixel_aspect_changed) {
|
||||
emit PixelAspectChanged(new_video_params.pixel_aspect_ratio());
|
||||
}
|
||||
|
||||
if (interlacing_changed) {
|
||||
emit InterlacingChanged(new_video_params.interlacing());
|
||||
}
|
||||
|
||||
if (timebase_changed) {
|
||||
video_frame_cache_.SetTimebase(new_video_params.time_base());
|
||||
emit TimebaseChanged(new_video_params.time_base());
|
||||
}
|
||||
|
||||
emit VideoParamsChanged();
|
||||
|
||||
cached_video_params_ = video_params();
|
||||
|
||||
} else if (input == kAudioParamsInput) {
|
||||
|
||||
emit AudioParamsChanged();
|
||||
|
||||
audio_playback_cache_.SetParameters(audio_params());
|
||||
|
||||
}
|
||||
|
||||
super::InputValueChangedEvent(input, element);
|
||||
}
|
||||
|
||||
void ViewerOutput::ShiftVideoEvent(const rational &from, const rational &to)
|
||||
{
|
||||
Q_UNUSED(from)
|
||||
Q_UNUSED(to)
|
||||
}
|
||||
|
||||
void ViewerOutput::ShiftAudioEvent(const rational &from, const rational &to)
|
||||
{
|
||||
Q_UNUSED(from)
|
||||
Q_UNUSED(to)
|
||||
}
|
||||
|
||||
void ViewerOutput::set_parameters_from_footage(const QVector<Footage *> footage)
|
||||
{
|
||||
foreach (Footage* f, footage) {
|
||||
QVector<VideoParams> video_streams = f->GetEnabledVideoStreams();
|
||||
QVector<AudioParams> audio_streams = f->GetEnabledAudioStreams();
|
||||
|
||||
foreach (const VideoParams& s, video_streams) {
|
||||
bool found_video_params = false;
|
||||
rational using_timebase;
|
||||
|
||||
if (s.video_type() == VideoParams::kVideoTypeStill) {
|
||||
// If this is a still image, we'll use it's resolution but won't set
|
||||
// `found_video_params` in case something with a frame rate comes along which we'll
|
||||
// prioritize
|
||||
using_timebase = video_params().time_base();
|
||||
} else {
|
||||
using_timebase = s.frame_rate().flipped();
|
||||
found_video_params = true;
|
||||
}
|
||||
|
||||
set_video_params(VideoParams(s.width(),
|
||||
s.height(),
|
||||
using_timebase,
|
||||
static_cast<VideoParams::Format>(Config::Current()[QStringLiteral("OfflinePixelFormat")].toInt()),
|
||||
VideoParams::kInternalChannelCount,
|
||||
s.pixel_aspect_ratio(),
|
||||
s.interlacing(),
|
||||
VideoParams::generate_auto_divider(s.width(), s.height())));
|
||||
|
||||
if (found_video_params) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!audio_streams.isEmpty()) {
|
||||
const AudioParams& s = audio_streams.first();
|
||||
set_audio_params(AudioParams(s.sample_rate(), s.channel_layout(), AudioParams::kInternalFormat));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,7 +21,15 @@
|
||||
#ifndef VIEWER_H
|
||||
#define VIEWER_H
|
||||
|
||||
#include "project/item/sequence/sequence.h"
|
||||
#include "common/rational.h"
|
||||
#include "node/node.h"
|
||||
#include "node/output/track/track.h"
|
||||
#include "project/item/footage/footage.h"
|
||||
#include "render/audioparams.h"
|
||||
#include "render/audioplaybackcache.h"
|
||||
#include "render/framehashcache.h"
|
||||
#include "render/videoparams.h"
|
||||
#include "render/videoparams.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
@@ -30,11 +38,12 @@ namespace olive {
|
||||
*
|
||||
* Receives update/time change signals from ViewerPanels and responds by sending them a texture of that frame
|
||||
*/
|
||||
class ViewerOutput : public Sequence
|
||||
class ViewerOutput : public Node
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ViewerOutput();
|
||||
virtual ~ViewerOutput() override;
|
||||
|
||||
virtual Node* copy() const override;
|
||||
|
||||
@@ -43,6 +52,108 @@ public:
|
||||
virtual QVector<CategoryID> Category() const override;
|
||||
virtual QString Description() const override;
|
||||
|
||||
virtual QString duration() const override;
|
||||
virtual QString rate() const override;
|
||||
|
||||
void set_default_parameters();
|
||||
|
||||
void set_parameters_from_footage(const QVector<Footage *> footage);
|
||||
|
||||
void ShiftVideoCache(const rational& from, const rational& to);
|
||||
void ShiftAudioCache(const rational& from, const rational& to);
|
||||
void ShiftCache(const rational& from, const rational& to);
|
||||
|
||||
virtual void InvalidateCache(const TimeRange& range, const QString& from, int element, qint64 job_time) override;
|
||||
|
||||
VideoParams video_params() const
|
||||
{
|
||||
return GetStandardValue(kVideoParamsInput).value<VideoParams>();
|
||||
}
|
||||
|
||||
AudioParams audio_params() const
|
||||
{
|
||||
return GetStandardValue(kAudioParamsInput).value<AudioParams>();
|
||||
}
|
||||
|
||||
void set_video_params(const VideoParams &video)
|
||||
{
|
||||
SetStandardValue(kVideoParamsInput, QVariant::fromValue(video));
|
||||
}
|
||||
|
||||
void set_audio_params(const AudioParams &audio)
|
||||
{
|
||||
SetStandardValue(kAudioParamsInput, QVariant::fromValue(audio));
|
||||
}
|
||||
|
||||
const rational &GetLength() const;
|
||||
|
||||
FrameHashCache* video_frame_cache()
|
||||
{
|
||||
return &video_frame_cache_;
|
||||
}
|
||||
|
||||
AudioPlaybackCache* audio_playback_cache()
|
||||
{
|
||||
return &audio_playback_cache_;
|
||||
}
|
||||
|
||||
virtual void Retranslate() override;
|
||||
|
||||
virtual void BeginOperation() override;
|
||||
|
||||
virtual void EndOperation() override;
|
||||
|
||||
static const QString kVideoParamsInput;
|
||||
static const QString kAudioParamsInput;
|
||||
|
||||
static const QString kTextureInput;
|
||||
static const QString kSamplesInput;
|
||||
|
||||
static const uint64_t kVideoParamEditMask;
|
||||
|
||||
signals:
|
||||
void TimebaseChanged(const rational&);
|
||||
|
||||
void LengthChanged(const rational& length);
|
||||
|
||||
void SizeChanged(int width, int height);
|
||||
|
||||
void PixelAspectChanged(const rational& pixel_aspect);
|
||||
|
||||
void InterlacingChanged(VideoParams::Interlacing mode);
|
||||
|
||||
void VideoParamsChanged();
|
||||
void AudioParamsChanged();
|
||||
|
||||
void TextureInputChanged();
|
||||
|
||||
public slots:
|
||||
void VerifyLength();
|
||||
|
||||
protected:
|
||||
virtual void InputConnectedEvent(const QString &input, int element, const NodeOutput &output) override;
|
||||
|
||||
virtual void InputDisconnectedEvent(const QString &input, int element, const NodeOutput &output) override;
|
||||
|
||||
virtual rational GetCustomLength(Track::Type type) const;
|
||||
|
||||
virtual void ShiftVideoEvent(const rational &from, const rational &to);
|
||||
|
||||
virtual void ShiftAudioEvent(const rational &from, const rational &to);
|
||||
|
||||
virtual void InputValueChangedEvent(const QString& input, int element) override;
|
||||
|
||||
private:
|
||||
rational last_length_;
|
||||
|
||||
FrameHashCache video_frame_cache_;
|
||||
|
||||
AudioPlaybackCache audio_playback_cache_;
|
||||
|
||||
int operation_stack_;
|
||||
|
||||
VideoParams cached_video_params_;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -108,22 +108,7 @@ void TimeBasedPanel::ShuttleRight()
|
||||
emit ShuttleRightRequested();
|
||||
}
|
||||
|
||||
TimeBasedWidget *TimeBasedPanel::GetTimeBasedWidget() const
|
||||
{
|
||||
return widget_;
|
||||
}
|
||||
|
||||
Sequence *TimeBasedPanel::GetConnectedViewer() const
|
||||
{
|
||||
return widget_->GetConnectedNode();
|
||||
}
|
||||
|
||||
TimeRuler *TimeBasedPanel::ruler() const
|
||||
{
|
||||
return widget_->ruler();
|
||||
}
|
||||
|
||||
void TimeBasedPanel::ConnectViewerNode(Sequence *node)
|
||||
void TimeBasedPanel::ConnectViewerNode(ViewerOutput *node)
|
||||
{
|
||||
if (widget_->GetConnectedNode() == node) {
|
||||
return;
|
||||
|
||||
@@ -32,15 +32,26 @@ class TimeBasedPanel : public PanelWidget
|
||||
public:
|
||||
TimeBasedPanel(const QString& object_name, QWidget *parent = nullptr);
|
||||
|
||||
void ConnectViewerNode(Sequence *node);
|
||||
void ConnectViewerNode(ViewerOutput *node);
|
||||
|
||||
void DisconnectViewerNode();
|
||||
|
||||
rational GetTime();
|
||||
|
||||
Sequence *GetConnectedViewer() const;
|
||||
ViewerOutput *GetConnectedViewer() const
|
||||
{
|
||||
return widget_->GetConnectedNode();
|
||||
}
|
||||
|
||||
TimeRuler* ruler() const;
|
||||
TimelinePoints* GetConnectedTimelinePoints() const
|
||||
{
|
||||
return widget_->GetConnectedTimelinePoints();
|
||||
}
|
||||
|
||||
TimeRuler* ruler() const
|
||||
{
|
||||
return widget_->ruler();
|
||||
}
|
||||
|
||||
virtual void ZoomIn() override;
|
||||
|
||||
@@ -107,7 +118,10 @@ signals:
|
||||
void ShuttleRightRequested();
|
||||
|
||||
protected:
|
||||
TimeBasedWidget* GetTimeBasedWidget() const;
|
||||
TimeBasedWidget* GetTimeBasedWidget() const
|
||||
{
|
||||
return widget_;
|
||||
}
|
||||
|
||||
void SetTimeBasedWidget(TimeBasedWidget* widget);
|
||||
|
||||
|
||||
@@ -22,68 +22,35 @@
|
||||
|
||||
#include <QThread>
|
||||
|
||||
#include "config/config.h"
|
||||
#include "common/channellayout.h"
|
||||
#include "common/timecodefunctions.h"
|
||||
#include "common/xmlutils.h"
|
||||
#include "node/factory.h"
|
||||
#include "panel/panelmanager.h"
|
||||
#include "panel/node/node.h"
|
||||
#include "panel/curve/curve.h"
|
||||
#include "panel/param/param.h"
|
||||
#include "panel/timeline/timeline.h"
|
||||
#include "panel/sequenceviewer/sequenceviewer.h"
|
||||
#include "ui/icons/icons.h"
|
||||
#include "widget/videoparamedit/videoparamedit.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
const QString Sequence::kVideoParamsInput = QStringLiteral("video_param_in");
|
||||
const QString Sequence::kAudioParamsInput = QStringLiteral("audio_param_in");
|
||||
const QString Sequence::kTextureInput = QStringLiteral("tex_in");
|
||||
const QString Sequence::kSamplesInput = QStringLiteral("samples_in");
|
||||
const QString Sequence::kTrackInputFormat = QStringLiteral("track_in_%1");
|
||||
|
||||
const uint64_t Sequence::kVideoParamEditMask = VideoParamEdit::kWidthHeight | VideoParamEdit::kInterlacing | VideoParamEdit::kFrameRate | VideoParamEdit::kPixelAspect;
|
||||
#define super ViewerOutput
|
||||
|
||||
#define super Node
|
||||
|
||||
Sequence::Sequence(bool viewer_only_mode) :
|
||||
video_frame_cache_(this),
|
||||
audio_playback_cache_(this),
|
||||
operation_stack_(0)
|
||||
Sequence::Sequence()
|
||||
{
|
||||
AddInput(kVideoParamsInput, NodeValue::kVideoParams, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable));
|
||||
SetInputProperty(kVideoParamsInput, QStringLiteral("mask"), QVariant::fromValue(kVideoParamEditMask));
|
||||
// Create TrackList instances
|
||||
track_lists_.resize(Track::kCount);
|
||||
|
||||
AddInput(kAudioParamsInput, NodeValue::kAudioParams, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable));
|
||||
for (int i=0;i<Track::kCount;i++) {
|
||||
// Create track input
|
||||
QString track_input_id = kTrackInputFormat.arg(i);
|
||||
|
||||
AddInput(kTextureInput, NodeValue::kTexture, InputFlags(kInputFlagNotKeyframable));
|
||||
AddInput(kSamplesInput, NodeValue::kSamples, InputFlags(kInputFlagNotKeyframable));
|
||||
AddInput(track_input_id, NodeValue::kNone, InputFlags(kInputFlagNotKeyframable | kInputFlagArray));
|
||||
|
||||
if (!viewer_only_mode) {
|
||||
// Create TrackList instances
|
||||
track_lists_.resize(Track::kCount);
|
||||
IgnoreInvalidationsFrom(track_input_id);
|
||||
|
||||
for (int i=0;i<Track::kCount;i++) {
|
||||
// Create track input
|
||||
QString track_input_id = kTrackInputFormat.arg(i);
|
||||
|
||||
AddInput(track_input_id, NodeValue::kNone, InputFlags(kInputFlagNotKeyframable | kInputFlagArray));
|
||||
|
||||
IgnoreInvalidationsFrom(track_input_id);
|
||||
|
||||
TrackList* list = new TrackList(this, static_cast<Track::Type>(i), track_input_id);
|
||||
track_lists_.replace(i, list);
|
||||
connect(list, &TrackList::TrackListChanged, this, &Sequence::UpdateTrackCache);
|
||||
connect(list, &TrackList::LengthChanged, this, &Sequence::VerifyLength);
|
||||
connect(list, &TrackList::TrackAdded, this, &Sequence::TrackAdded);
|
||||
connect(list, &TrackList::TrackRemoved, this, &Sequence::TrackRemoved);
|
||||
}
|
||||
TrackList* list = new TrackList(this, static_cast<Track::Type>(i), track_input_id);
|
||||
track_lists_.replace(i, list);
|
||||
connect(list, &TrackList::TrackListChanged, this, &Sequence::UpdateTrackCache);
|
||||
connect(list, &TrackList::LengthChanged, this, &Sequence::VerifyLength);
|
||||
connect(list, &TrackList::TrackAdded, this, &Sequence::TrackAdded);
|
||||
connect(list, &TrackList::TrackRemoved, this, &Sequence::TrackRemoved);
|
||||
}
|
||||
|
||||
// Create UUID for this node
|
||||
uuid_ = QUuid::createUuid();
|
||||
}
|
||||
|
||||
Sequence::~Sequence()
|
||||
@@ -103,80 +70,6 @@ QIcon Sequence::icon() const
|
||||
return icon::Sequence;
|
||||
}
|
||||
|
||||
QString Sequence::duration() const
|
||||
{
|
||||
rational timeline_length = GetLength();
|
||||
|
||||
int64_t timestamp = Timecode::time_to_timestamp(timeline_length, video_params().time_base());
|
||||
|
||||
return Timecode::timestamp_to_timecode(timestamp, video_params().time_base(), Core::instance()->GetTimecodeDisplay());
|
||||
}
|
||||
|
||||
QString Sequence::rate() const
|
||||
{
|
||||
return tr("%1 FPS").arg(video_params().time_base().flipped().toDouble());
|
||||
}
|
||||
|
||||
void Sequence::set_default_parameters()
|
||||
{
|
||||
int width = Config::Current()["DefaultSequenceWidth"].toInt();
|
||||
int height = Config::Current()["DefaultSequenceHeight"].toInt();
|
||||
|
||||
set_video_params(VideoParams(width,
|
||||
height,
|
||||
Config::Current()["DefaultSequenceFrameRate"].value<rational>(),
|
||||
static_cast<VideoParams::Format>(Config::Current()["OfflinePixelFormat"].toInt()),
|
||||
VideoParams::kInternalChannelCount,
|
||||
Config::Current()["DefaultSequencePixelAspect"].value<rational>(),
|
||||
Config::Current()["DefaultSequenceInterlacing"].value<VideoParams::Interlacing>(),
|
||||
VideoParams::generate_auto_divider(width, height)));
|
||||
set_audio_params(AudioParams(Config::Current()["DefaultSequenceAudioFrequency"].toInt(),
|
||||
Config::Current()["DefaultSequenceAudioLayout"].toULongLong(),
|
||||
AudioParams::kInternalFormat));
|
||||
}
|
||||
|
||||
void Sequence::set_parameters_from_footage(const QVector<Footage *> footage)
|
||||
{
|
||||
|
||||
foreach (Footage* f, footage) {
|
||||
QVector<VideoParams> video_streams = f->GetEnabledVideoStreams();
|
||||
QVector<AudioParams> audio_streams = f->GetEnabledAudioStreams();
|
||||
|
||||
foreach (const VideoParams& s, video_streams) {
|
||||
bool found_video_params = false;
|
||||
rational using_timebase;
|
||||
|
||||
if (s.video_type() == VideoParams::kVideoTypeStill) {
|
||||
// If this is a still image, we'll use it's resolution but won't set
|
||||
// `found_video_params` in case something with a frame rate comes along which we'll
|
||||
// prioritize
|
||||
using_timebase = video_params().time_base();
|
||||
} else {
|
||||
using_timebase = s.frame_rate().flipped();
|
||||
found_video_params = true;
|
||||
}
|
||||
|
||||
set_video_params(VideoParams(s.width(),
|
||||
s.height(),
|
||||
using_timebase,
|
||||
static_cast<VideoParams::Format>(Config::Current()[QStringLiteral("OfflinePixelFormat")].toInt()),
|
||||
VideoParams::kInternalChannelCount,
|
||||
s.pixel_aspect_ratio(),
|
||||
s.interlacing(),
|
||||
VideoParams::generate_auto_divider(s.width(), s.height())));
|
||||
|
||||
if (found_video_params) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!audio_streams.isEmpty()) {
|
||||
const AudioParams& s = audio_streams.first();
|
||||
set_audio_params(AudioParams(s.sample_rate(), s.channel_layout(), AudioParams::kInternalFormat));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QVector<Track *> Sequence::GetUnlockedTracks() const
|
||||
{
|
||||
QVector<Track*> tracks = GetTracks();
|
||||
@@ -195,12 +88,6 @@ void Sequence::Retranslate()
|
||||
{
|
||||
super::Retranslate();
|
||||
|
||||
SetInputName(kVideoParamsInput, tr("Video Parameters"));
|
||||
SetInputName(kAudioParamsInput, tr("Audio Parameters"));
|
||||
|
||||
SetInputName(kTextureInput, tr("Texture"));
|
||||
SetInputName(kSamplesInput, tr("Samples"));
|
||||
|
||||
for (int i=0;i<Track::kCount;i++) {
|
||||
QString input_name;
|
||||
|
||||
@@ -246,15 +133,11 @@ rational Sequence::GetCustomLength(Track::Type type) const
|
||||
|
||||
void Sequence::InputConnectedEvent(const QString &input, int element, const NodeOutput &output)
|
||||
{
|
||||
if (input == kTextureInput) {
|
||||
emit TextureInputChanged();
|
||||
} else {
|
||||
foreach (TrackList* list, track_lists_) {
|
||||
if (list->track_input() == input) {
|
||||
// Return because we found our input
|
||||
list->TrackConnected(output.node(), element);
|
||||
return;
|
||||
}
|
||||
foreach (TrackList* list, track_lists_) {
|
||||
if (list->track_input() == input) {
|
||||
// Return because we found our input
|
||||
list->TrackConnected(output.node(), element);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,15 +146,11 @@ void Sequence::InputConnectedEvent(const QString &input, int element, const Node
|
||||
|
||||
void Sequence::InputDisconnectedEvent(const QString &input, int element, const NodeOutput &output)
|
||||
{
|
||||
if (input == kTextureInput) {
|
||||
emit TextureInputChanged();
|
||||
} else {
|
||||
foreach (TrackList* list, track_lists_) {
|
||||
if (list->track_input() == input) {
|
||||
// Return because we found our input
|
||||
list->TrackDisconnected(output.node(), element);
|
||||
return;
|
||||
}
|
||||
foreach (TrackList* list, track_lists_) {
|
||||
if (list->track_input() == input) {
|
||||
// Return because we found our input
|
||||
list->TrackDisconnected(output.node(), element);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -296,113 +175,6 @@ void Sequence::UpdateTrackCache()
|
||||
}
|
||||
}
|
||||
|
||||
void Sequence::ShiftVideoCache(const rational &from, const rational &to)
|
||||
{
|
||||
video_frame_cache_.Shift(from, to);
|
||||
|
||||
ShiftVideoEvent(from, to);
|
||||
}
|
||||
|
||||
void Sequence::ShiftAudioCache(const rational &from, const rational &to)
|
||||
{
|
||||
audio_playback_cache_.Shift(from, to);
|
||||
|
||||
ShiftAudioEvent(from, to);
|
||||
}
|
||||
|
||||
void Sequence::ShiftCache(const rational &from, const rational &to)
|
||||
{
|
||||
ShiftVideoCache(from, to);
|
||||
ShiftAudioCache(from, to);
|
||||
}
|
||||
|
||||
void Sequence::InvalidateCache(const TimeRange& range, const QString& from, int element, qint64 job_time)
|
||||
{
|
||||
Q_UNUSED(element)
|
||||
|
||||
if (operation_stack_ == 0) {
|
||||
if (from == kTextureInput || from == kSamplesInput) {
|
||||
TimeRange invalidated_range(qMax(rational(), range.in()),
|
||||
qMin(GetLength(), range.out()));
|
||||
|
||||
if (invalidated_range.in() != invalidated_range.out()) {
|
||||
if (from == kTextureInput) {
|
||||
video_frame_cache_.Invalidate(invalidated_range, job_time);
|
||||
} else {
|
||||
audio_playback_cache_.Invalidate(invalidated_range, job_time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VerifyLength();
|
||||
}
|
||||
|
||||
super::InvalidateCache(range, from, element, job_time);
|
||||
}
|
||||
|
||||
const rational& Sequence::GetLength() const
|
||||
{
|
||||
return last_length_;
|
||||
}
|
||||
|
||||
void Sequence::VerifyLength()
|
||||
{
|
||||
if (operation_stack_ != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
NodeTraverser traverser;
|
||||
|
||||
rational video_length, audio_length, subtitle_length;
|
||||
|
||||
{
|
||||
video_length = GetCustomLength(Track::kVideo);
|
||||
|
||||
if (video_length.isNull() && IsInputConnected(kTextureInput)) {
|
||||
NodeValueTable t = traverser.GenerateTable(GetConnectedOutput(kTextureInput), TimeRange(0, 0));
|
||||
video_length = t.Get(NodeValue::kRational, QStringLiteral("length")).value<rational>();
|
||||
}
|
||||
|
||||
video_frame_cache_.SetLength(video_length);
|
||||
}
|
||||
|
||||
{
|
||||
audio_length = GetCustomLength(Track::kAudio);
|
||||
|
||||
if (audio_length.isNull() && IsInputConnected(kSamplesInput)) {
|
||||
NodeValueTable t = traverser.GenerateTable(GetConnectedOutput(kSamplesInput), TimeRange(0, 0));
|
||||
audio_length = t.Get(NodeValue::kRational, QStringLiteral("length")).value<rational>();
|
||||
}
|
||||
|
||||
audio_playback_cache_.SetLength(audio_length);
|
||||
}
|
||||
|
||||
{
|
||||
subtitle_length = GetCustomLength(Track::kSubtitle);
|
||||
}
|
||||
|
||||
rational real_length = qMax(subtitle_length, qMax(video_length, audio_length));
|
||||
|
||||
if (real_length != last_length_) {
|
||||
last_length_ = real_length;
|
||||
emit LengthChanged(last_length_);
|
||||
}
|
||||
}
|
||||
|
||||
void Sequence::BeginOperation()
|
||||
{
|
||||
operation_stack_++;
|
||||
|
||||
super::BeginOperation();
|
||||
}
|
||||
|
||||
void Sequence::EndOperation()
|
||||
{
|
||||
operation_stack_--;
|
||||
|
||||
super::EndOperation();
|
||||
}
|
||||
|
||||
void Sequence::LoadInternal(QXmlStreamReader *reader, XMLNodeData &xml_node_data, uint version, const QAtomicInt *cancelled)
|
||||
{
|
||||
Q_UNUSED(xml_node_data)
|
||||
@@ -426,53 +198,4 @@ void Sequence::SaveInternal(QXmlStreamWriter *writer) const
|
||||
writer->writeEndElement(); // points
|
||||
}
|
||||
|
||||
void Sequence::InputValueChangedEvent(const QString &input, int element)
|
||||
{
|
||||
if (input == kVideoParamsInput) {
|
||||
|
||||
VideoParams new_video_params = video_params();
|
||||
|
||||
bool size_changed = cached_video_params_.width() != new_video_params.width() || cached_video_params_.height() != new_video_params.height();
|
||||
bool timebase_changed = cached_video_params_.time_base() != new_video_params.time_base();
|
||||
bool pixel_aspect_changed = cached_video_params_.pixel_aspect_ratio() != new_video_params.pixel_aspect_ratio();
|
||||
bool interlacing_changed = cached_video_params_.interlacing() != new_video_params.interlacing();
|
||||
|
||||
if (size_changed) {
|
||||
emit SizeChanged(new_video_params.width(), new_video_params.height());
|
||||
}
|
||||
|
||||
if (pixel_aspect_changed) {
|
||||
emit PixelAspectChanged(new_video_params.pixel_aspect_ratio());
|
||||
}
|
||||
|
||||
if (interlacing_changed) {
|
||||
emit InterlacingChanged(new_video_params.interlacing());
|
||||
}
|
||||
|
||||
if (timebase_changed) {
|
||||
video_frame_cache_.SetTimebase(new_video_params.time_base());
|
||||
emit TimebaseChanged(new_video_params.time_base());
|
||||
}
|
||||
|
||||
emit VideoParamsChanged();
|
||||
|
||||
cached_video_params_ = video_params();
|
||||
video_frame_cache_.InvalidateAll();
|
||||
|
||||
} else if (input == kAudioParamsInput) {
|
||||
|
||||
emit AudioParamsChanged();
|
||||
|
||||
// This will automatically InvalidateAll
|
||||
audio_playback_cache_.SetParameters(audio_params());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void Sequence::ShiftVideoEvent(const rational &from, const rational &to)
|
||||
{
|
||||
Q_UNUSED(from)
|
||||
Q_UNUSED(to)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,23 +21,8 @@
|
||||
#ifndef SEQUENCE_H
|
||||
#define SEQUENCE_H
|
||||
|
||||
#include <QUuid>
|
||||
|
||||
#include "common/rational.h"
|
||||
#include "node/block/block.h"
|
||||
#include "node/graph.h"
|
||||
#include "node/node.h"
|
||||
#include "node/output/track/track.h"
|
||||
#include "node/output/track/tracklist.h"
|
||||
#include "node/traverser.h"
|
||||
#include "project/item/footage/footage.h"
|
||||
#include "render/audioparams.h"
|
||||
#include "render/audioplaybackcache.h"
|
||||
#include "render/framehashcache.h"
|
||||
#include "render/videoparams.h"
|
||||
#include "render/videoparams.h"
|
||||
#include "timeline/timelinecommon.h"
|
||||
#include "timeline/timelinepoints.h"
|
||||
#include "node/output/viewer/viewer.h"
|
||||
#include "timeline/timelinepoints.h"
|
||||
|
||||
namespace olive {
|
||||
@@ -45,11 +30,11 @@ namespace olive {
|
||||
/**
|
||||
* @brief The main timeline object, an graph of edited clips that forms a complete edit
|
||||
*/
|
||||
class Sequence : public Node, public TimelinePoints
|
||||
class Sequence : public ViewerOutput
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Sequence(bool viewer_only_mode = false);
|
||||
Sequence();
|
||||
|
||||
virtual ~Sequence() override;
|
||||
|
||||
@@ -82,13 +67,6 @@ public:
|
||||
|
||||
virtual QIcon icon() const override;
|
||||
|
||||
virtual QString duration() const override;
|
||||
virtual QString rate() const override;
|
||||
|
||||
void set_default_parameters();
|
||||
|
||||
void set_parameters_from_footage(const QVector<Footage *> footage);
|
||||
|
||||
const QVector<Track *> &GetTracks() const
|
||||
{
|
||||
return track_cache_;
|
||||
@@ -109,130 +87,42 @@ public:
|
||||
return track_lists_.at(type);
|
||||
}
|
||||
|
||||
void ShiftVideoCache(const rational& from, const rational& to);
|
||||
void ShiftAudioCache(const rational& from, const rational& to);
|
||||
void ShiftCache(const rational& from, const rational& to);
|
||||
|
||||
virtual void InvalidateCache(const TimeRange& range, const QString& from, int element, qint64 job_time) override;
|
||||
|
||||
VideoParams video_params() const
|
||||
{
|
||||
return GetStandardValue(kVideoParamsInput).value<VideoParams>();
|
||||
}
|
||||
|
||||
AudioParams audio_params() const
|
||||
{
|
||||
return GetStandardValue(kAudioParamsInput).value<AudioParams>();
|
||||
}
|
||||
|
||||
void set_video_params(const VideoParams &video)
|
||||
{
|
||||
SetStandardValue(kVideoParamsInput, QVariant::fromValue(video));
|
||||
}
|
||||
|
||||
void set_audio_params(const AudioParams &audio)
|
||||
{
|
||||
SetStandardValue(kAudioParamsInput, QVariant::fromValue(audio));
|
||||
}
|
||||
|
||||
const rational &GetLength() const;
|
||||
|
||||
virtual void Retranslate() override;
|
||||
|
||||
FrameHashCache* video_frame_cache()
|
||||
{
|
||||
return &video_frame_cache_;
|
||||
}
|
||||
|
||||
AudioPlaybackCache* audio_playback_cache()
|
||||
{
|
||||
return &audio_playback_cache_;
|
||||
}
|
||||
|
||||
virtual void BeginOperation() override;
|
||||
|
||||
virtual void EndOperation() override;
|
||||
|
||||
static const QString kVideoParamsInput;
|
||||
static const QString kAudioParamsInput;
|
||||
|
||||
static const QString kTextureInput;
|
||||
static const QString kSamplesInput;
|
||||
static const QString kTrackInputFormat;
|
||||
|
||||
static const uint64_t kVideoParamEditMask;
|
||||
|
||||
TimelinePoints* timeline_points()
|
||||
{
|
||||
return &timeline_points_;
|
||||
}
|
||||
|
||||
const QUuid& uuid() const
|
||||
{
|
||||
return uuid_;
|
||||
}
|
||||
|
||||
virtual bool IsItem() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
signals:
|
||||
void TimebaseChanged(const rational&);
|
||||
|
||||
void LengthChanged(const rational& length);
|
||||
|
||||
void SizeChanged(int width, int height);
|
||||
|
||||
void PixelAspectChanged(const rational& pixel_aspect);
|
||||
|
||||
void InterlacingChanged(VideoParams::Interlacing mode);
|
||||
|
||||
void VideoParamsChanged();
|
||||
void AudioParamsChanged();
|
||||
|
||||
void TrackAdded(Track* track);
|
||||
void TrackRemoved(Track* track);
|
||||
|
||||
void TextureInputChanged();
|
||||
|
||||
public slots:
|
||||
void VerifyLength();
|
||||
|
||||
protected:
|
||||
virtual void InputConnectedEvent(const QString &input, int element, const NodeOutput &output) override;
|
||||
|
||||
virtual void InputDisconnectedEvent(const QString &input, int element, const NodeOutput &output) override;
|
||||
|
||||
virtual rational GetCustomLength(Track::Type type) const;
|
||||
|
||||
virtual void ShiftVideoEvent(const rational &from, const rational &to);
|
||||
|
||||
virtual void ShiftAudioEvent(const rational &from, const rational &to);
|
||||
|
||||
virtual void LoadInternal(QXmlStreamReader* reader, XMLNodeData &xml_node_data, uint version, const QAtomicInt* cancelled) override;
|
||||
|
||||
virtual void SaveInternal(QXmlStreamWriter *writer) const override;
|
||||
|
||||
virtual void InputValueChangedEvent(const QString& input, int element) override;
|
||||
virtual void ShiftAudioEvent(const rational &from, const rational &to) override;
|
||||
|
||||
virtual void InputConnectedEvent(const QString &input, int element, const NodeOutput &output) override;
|
||||
|
||||
virtual void InputDisconnectedEvent(const QString &input, int element, const NodeOutput &output) override;
|
||||
|
||||
virtual rational GetCustomLength(Track::Type type) const override;
|
||||
|
||||
signals:
|
||||
void TrackAdded(Track* track);
|
||||
void TrackRemoved(Track* track);
|
||||
|
||||
private:
|
||||
QVector<TrackList*> track_lists_;
|
||||
|
||||
QVector<Track*> track_cache_;
|
||||
|
||||
QUuid uuid_;
|
||||
|
||||
rational last_length_;
|
||||
|
||||
FrameHashCache video_frame_cache_;
|
||||
|
||||
AudioPlaybackCache audio_playback_cache_;
|
||||
|
||||
int operation_stack_;
|
||||
|
||||
VideoParams cached_video_params_;
|
||||
|
||||
TimelinePoints timeline_points_;
|
||||
|
||||
private slots:
|
||||
|
||||
@@ -21,8 +21,9 @@
|
||||
#ifndef PROJECT_H
|
||||
#define PROJECT_H
|
||||
|
||||
#include <QObject>
|
||||
#include <memory>
|
||||
#include <QObject>
|
||||
#include <QUuid>
|
||||
|
||||
#include "node/project/projectsettings/projectsettings.h"
|
||||
#include "node/output/viewer/viewer.h"
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include <QApplication>
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
|
||||
#include "project/item/sequence/sequence.h"
|
||||
#include "project/project.h"
|
||||
#include "render/rendermanager.h"
|
||||
#include "render/renderprocessor.h"
|
||||
@@ -65,13 +64,13 @@ void PreviewAutoCacher::SetPaused(bool paused)
|
||||
}
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::GenerateHashes(Sequence *viewer, FrameHashCache* cache, const QVector<rational> ×, qint64 job_time)
|
||||
void PreviewAutoCacher::GenerateHashes(ViewerOutput *viewer, FrameHashCache* cache, const QVector<rational> ×, qint64 job_time)
|
||||
{
|
||||
std::vector<QByteArray> existing_hashes;
|
||||
|
||||
foreach (const rational& time, times) {
|
||||
// See if hash already exists in disk cache
|
||||
QByteArray hash = RenderManager::Hash(viewer->GetConnectedNode(Sequence::kTextureInput), viewer->video_params(), time);
|
||||
QByteArray hash = RenderManager::Hash(viewer->GetConnectedNode(ViewerOutput::kTextureInput), viewer->video_params(), time);
|
||||
|
||||
// Check memory list since disk checking is slow
|
||||
bool hash_exists = (std::find(existing_hashes.begin(), existing_hashes.end(), hash) != existing_hashes.end());
|
||||
@@ -590,7 +589,7 @@ void PreviewAutoCacher::ForceCacheRange(const TimeRange &range)
|
||||
RequeueFrames();
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::SetViewerNode(Sequence *viewer_node)
|
||||
void PreviewAutoCacher::SetViewerNode(ViewerOutput *viewer_node)
|
||||
{
|
||||
if (viewer_node_ == viewer_node) {
|
||||
return;
|
||||
@@ -662,7 +661,7 @@ void PreviewAutoCacher::SetViewerNode(Sequence *viewer_node)
|
||||
}
|
||||
|
||||
// Find copied viewer node
|
||||
copied_viewer_node_ = static_cast<Sequence*>(copy_map_.value(viewer_node_));
|
||||
copied_viewer_node_ = static_cast<ViewerOutput*>(copy_map_.value(viewer_node_));
|
||||
|
||||
// Copy parameters
|
||||
copied_viewer_node_->set_video_params(viewer_node_->video_params());
|
||||
|
||||
@@ -31,7 +31,7 @@ public:
|
||||
/**
|
||||
* @brief Set the viewer node to auto-cache
|
||||
*/
|
||||
void SetViewerNode(Sequence *viewer_node);
|
||||
void SetViewerNode(ViewerOutput *viewer_node);
|
||||
|
||||
/**
|
||||
* @brief If the mouse is held during the next cache invalidation, cache anyway
|
||||
@@ -85,7 +85,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
static void GenerateHashes(Sequence *viewer, FrameHashCache *cache, const QVector<rational>& times, qint64 job_time);
|
||||
static void GenerateHashes(ViewerOutput *viewer, FrameHashCache *cache, const QVector<rational>& times, qint64 job_time);
|
||||
|
||||
void TryRender();
|
||||
|
||||
@@ -125,13 +125,13 @@ private:
|
||||
NodeOutput output;
|
||||
};
|
||||
|
||||
Sequence* viewer_node_;
|
||||
ViewerOutput* viewer_node_;
|
||||
|
||||
Project copied_project_;
|
||||
|
||||
QVector<QueuedJob> graph_update_queue_;
|
||||
QHash<Node*, Node*> copy_map_;
|
||||
Sequence* copied_viewer_node_;
|
||||
ViewerOutput* copied_viewer_node_;
|
||||
QVector<Node*> created_nodes_;
|
||||
|
||||
bool paused_;
|
||||
|
||||
@@ -99,7 +99,7 @@ QByteArray RenderManager::Hash(const Node *n, const VideoParams ¶ms, const r
|
||||
return hasher.result();
|
||||
}
|
||||
|
||||
RenderTicketPtr RenderManager::RenderFrame(Sequence* viewer, ColorManager* color_manager,
|
||||
RenderTicketPtr RenderManager::RenderFrame(ViewerOutput *viewer, ColorManager* color_manager,
|
||||
const rational& time, RenderMode::Mode mode,
|
||||
FrameHashCache* cache, bool prioritize)
|
||||
{
|
||||
@@ -117,7 +117,7 @@ RenderTicketPtr RenderManager::RenderFrame(Sequence* viewer, ColorManager* color
|
||||
prioritize);
|
||||
}
|
||||
|
||||
RenderTicketPtr RenderManager::RenderFrame(Sequence* viewer, ColorManager* color_manager,
|
||||
RenderTicketPtr RenderManager::RenderFrame(ViewerOutput *viewer, ColorManager* color_manager,
|
||||
const rational& time, RenderMode::Mode mode,
|
||||
const VideoParams &video_params, const AudioParams &audio_params,
|
||||
const QSize& force_size,
|
||||
@@ -156,12 +156,12 @@ RenderTicketPtr RenderManager::RenderFrame(Sequence* viewer, ColorManager* color
|
||||
return ticket;
|
||||
}
|
||||
|
||||
RenderTicketPtr RenderManager::RenderAudio(Sequence* viewer, const TimeRange& r, bool generate_waveforms, bool prioritize)
|
||||
RenderTicketPtr RenderManager::RenderAudio(ViewerOutput* viewer, const TimeRange& r, bool generate_waveforms, bool prioritize)
|
||||
{
|
||||
return RenderAudio(viewer, r, viewer->audio_params(), generate_waveforms, prioritize);
|
||||
}
|
||||
|
||||
RenderTicketPtr RenderManager::RenderAudio(Sequence* viewer, const TimeRange &r, const AudioParams ¶ms, bool generate_waveforms, bool prioritize)
|
||||
RenderTicketPtr RenderManager::RenderAudio(ViewerOutput* viewer, const TimeRange &r, const AudioParams ¶ms, bool generate_waveforms, bool prioritize)
|
||||
{
|
||||
// Create ticket
|
||||
RenderTicketPtr ticket = std::make_shared<RenderTicket>();
|
||||
|
||||
@@ -80,10 +80,10 @@ public:
|
||||
*
|
||||
* This function is thread-safe.
|
||||
*/
|
||||
RenderTicketPtr RenderFrame(Sequence *viewer, ColorManager* color_manager,
|
||||
RenderTicketPtr RenderFrame(ViewerOutput *viewer, ColorManager* color_manager,
|
||||
const rational& time, RenderMode::Mode mode,
|
||||
FrameHashCache* cache = nullptr, bool prioritize = false);
|
||||
RenderTicketPtr RenderFrame(Sequence* viewer, ColorManager* color_manager,
|
||||
RenderTicketPtr RenderFrame(ViewerOutput* viewer, ColorManager* color_manager,
|
||||
const rational& time, RenderMode::Mode mode,
|
||||
const VideoParams& video_params, const AudioParams& audio_params,
|
||||
const QSize& force_size,
|
||||
@@ -101,8 +101,8 @@ public:
|
||||
*
|
||||
* This function is thread-safe.
|
||||
*/
|
||||
RenderTicketPtr RenderAudio(Sequence* viewer, const TimeRange& r, const AudioParams& params, bool generate_waveforms, bool prioritize = false);
|
||||
RenderTicketPtr RenderAudio(Sequence *viewer, const TimeRange& r, bool generate_waveforms, bool prioritize = false);
|
||||
RenderTicketPtr RenderAudio(ViewerOutput* viewer, const TimeRange& r, const AudioParams& params, bool generate_waveforms, bool prioritize = false);
|
||||
RenderTicketPtr RenderAudio(ViewerOutput *viewer, const TimeRange& r, bool generate_waveforms, bool prioritize = false);
|
||||
|
||||
RenderTicketPtr SaveFrameToCache(FrameHashCache* cache, FramePtr frame, const QByteArray& hash, bool prioritize = false);
|
||||
|
||||
|
||||
@@ -54,11 +54,11 @@ void RenderProcessor::Run()
|
||||
switch (type) {
|
||||
case RenderManager::kTypeVideo:
|
||||
{
|
||||
Sequence* viewer = Node::ValueToPtr<Sequence>(ticket_->property("viewer"));
|
||||
ViewerOutput* viewer = Node::ValueToPtr<ViewerOutput>(ticket_->property("viewer"));
|
||||
const VideoParams& video_params = ticket_->property("vparam").value<VideoParams>();
|
||||
rational time = ticket_->property("time").value<rational>();
|
||||
|
||||
NodeValueTable table = ProcessInput(viewer, Sequence::kTextureInput,
|
||||
NodeValueTable table = ProcessInput(viewer, ViewerOutput::kTextureInput,
|
||||
TimeRange(time, time + video_params.time_base()));
|
||||
|
||||
TexturePtr texture = table.Get(NodeValue::kTexture).value<TexturePtr>();
|
||||
@@ -130,10 +130,10 @@ void RenderProcessor::Run()
|
||||
}
|
||||
case RenderManager::kTypeAudio:
|
||||
{
|
||||
Sequence* viewer = Node::ValueToPtr<Sequence>(ticket_->property("viewer"));
|
||||
ViewerOutput* viewer = Node::ValueToPtr<ViewerOutput>(ticket_->property("viewer"));
|
||||
TimeRange time = ticket_->property("time").value<TimeRange>();
|
||||
|
||||
NodeValueTable table = ProcessInput(viewer, Sequence::kSamplesInput, time);
|
||||
NodeValueTable table = ProcessInput(viewer, ViewerOutput::kSamplesInput, time);
|
||||
|
||||
ticket_->Finish(table.Get(NodeValue::kSamples), IsCancelled());
|
||||
break;
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
namespace olive {
|
||||
|
||||
ExportTask::ExportTask(Sequence *viewer_node,
|
||||
ExportTask::ExportTask(ViewerOutput *viewer_node,
|
||||
ColorManager* color_manager,
|
||||
const ExportParams& params) :
|
||||
RenderTask(viewer_node, params.video_params(), params.audio_params()),
|
||||
|
||||
@@ -33,7 +33,7 @@ class ExportTask : public RenderTask
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ExportTask(Sequence *viewer_node, ColorManager *color_manager, const ExportParams ¶ms);
|
||||
ExportTask(ViewerOutput *viewer_node, ColorManager *color_manager, const ExportParams ¶ms);
|
||||
|
||||
protected:
|
||||
virtual bool Run() override;
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
namespace olive {
|
||||
|
||||
RenderTask::RenderTask(Sequence* viewer, const VideoParams &vparams, const AudioParams &aparams) :
|
||||
RenderTask::RenderTask(ViewerOutput *viewer, const VideoParams &vparams, const AudioParams &aparams) :
|
||||
viewer_(viewer),
|
||||
video_params_(vparams),
|
||||
audio_params_(aparams),
|
||||
|
||||
@@ -35,7 +35,7 @@ class RenderTask : public Task
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
RenderTask(Sequence* viewer, const VideoParams &vparams, const AudioParams &aparams);
|
||||
RenderTask(ViewerOutput* viewer, const VideoParams &vparams, const AudioParams &aparams);
|
||||
|
||||
virtual ~RenderTask() override;
|
||||
|
||||
@@ -53,7 +53,7 @@ protected:
|
||||
|
||||
virtual void AudioDownloaded(const TimeRange& range, SampleBufferPtr samples, qint64 job_time) = 0;
|
||||
|
||||
Sequence* viewer() const
|
||||
ViewerOutput* viewer() const
|
||||
{
|
||||
return viewer_;
|
||||
}
|
||||
@@ -87,7 +87,7 @@ private:
|
||||
|
||||
void StartTicket(const QByteArray &hash, QThread *watcher_thread, ColorManager *manager, const rational &time, RenderMode::Mode mode, FrameHashCache *cache, const QSize &force_size, const QMatrix4x4 &force_matrix, VideoParams::Format force_format, ColorProcessorPtr force_color_output);
|
||||
|
||||
Sequence* viewer_;
|
||||
ViewerOutput* viewer_;
|
||||
|
||||
VideoParams video_params_;
|
||||
|
||||
|
||||
@@ -185,7 +185,7 @@ void CurveWidget::TimeTargetChangedEvent(Node *target)
|
||||
view_->SetTimeTarget(target);
|
||||
}
|
||||
|
||||
void CurveWidget::ConnectedNodeChanged(Sequence *n)
|
||||
void CurveWidget::ConnectedNodeChanged(ViewerOutput *n)
|
||||
{
|
||||
SetTimeTarget(n);
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ protected:
|
||||
|
||||
virtual void TimeTargetChangedEvent(Node* target) override;
|
||||
|
||||
virtual void ConnectedNodeChanged(Sequence* n) override;
|
||||
virtual void ConnectedNodeChanged(ViewerOutput* n) override;
|
||||
|
||||
private:
|
||||
void SetKeyframeButtonEnabled(bool enable);
|
||||
|
||||
@@ -226,7 +226,7 @@ void NodeParamView::TimeChangedEvent(const int64_t ×tamp)
|
||||
UpdateItemTime(timestamp);
|
||||
}
|
||||
|
||||
void NodeParamView::ConnectedNodeChanged(Sequence *n)
|
||||
void NodeParamView::ConnectedNodeChanged(ViewerOutput *n)
|
||||
{
|
||||
// Set viewer as a time target
|
||||
keyframe_view_->SetTimeTarget(n);
|
||||
|
||||
@@ -96,7 +96,7 @@ protected:
|
||||
virtual void TimebaseChangedEvent(const rational&) override;
|
||||
virtual void TimeChangedEvent(const int64_t &) override;
|
||||
|
||||
virtual void ConnectedNodeChanged(Sequence* n) override;
|
||||
virtual void ConnectedNodeChanged(ViewerOutput* n) override;
|
||||
|
||||
private:
|
||||
void UpdateItemTime(const int64_t ×tamp);
|
||||
|
||||
@@ -68,12 +68,12 @@ const int64_t &TimeBasedWidget::GetTimestamp() const
|
||||
return ruler_->GetTime();
|
||||
}
|
||||
|
||||
Sequence *TimeBasedWidget::GetConnectedNode() const
|
||||
ViewerOutput *TimeBasedWidget::GetConnectedNode() const
|
||||
{
|
||||
return viewer_node_;
|
||||
}
|
||||
|
||||
void TimeBasedWidget::ConnectViewerNode(Sequence *node)
|
||||
void TimeBasedWidget::ConnectViewerNode(ViewerOutput *node)
|
||||
{
|
||||
if (viewer_node_ == node) {
|
||||
return;
|
||||
@@ -101,7 +101,7 @@ void TimeBasedWidget::ConnectViewerNode(Sequence *node)
|
||||
if (viewer_node_) {
|
||||
connect(viewer_node_, &ViewerOutput::LengthChanged, this, &TimeBasedWidget::UpdateMaximumScroll);
|
||||
|
||||
if ((points_ = ConnectTimelinePoints())) {
|
||||
if ((points_ = GetTimelinePointsToConnect())) {
|
||||
ruler()->ConnectTimelinePoints(points_);
|
||||
scrollbar_->ConnectTimelinePoints(points_);
|
||||
}
|
||||
@@ -242,9 +242,15 @@ void TimeBasedWidget::resizeEvent(QResizeEvent *event)
|
||||
UpdateMaximumScroll();
|
||||
}
|
||||
|
||||
TimelinePoints *TimeBasedWidget::ConnectTimelinePoints()
|
||||
TimelinePoints *TimeBasedWidget::GetTimelinePointsToConnect()
|
||||
{
|
||||
return viewer_node_->timeline_points();
|
||||
Sequence* sequence = dynamic_cast<Sequence*>(viewer_node_);
|
||||
|
||||
if (sequence) {
|
||||
return sequence->timeline_points();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Project *TimeBasedWidget::GetTimelinePointsProject()
|
||||
|
||||
@@ -46,9 +46,11 @@ public:
|
||||
|
||||
void ZoomOut();
|
||||
|
||||
Sequence* GetConnectedNode() const;
|
||||
ViewerOutput* GetConnectedNode() const;
|
||||
|
||||
void ConnectViewerNode(Sequence *node);
|
||||
TimelinePoints* GetConnectedTimelinePoints() const;
|
||||
|
||||
void ConnectViewerNode(ViewerOutput *node);
|
||||
|
||||
void SetScaleAndCenterOnPlayhead(const double& scale);
|
||||
|
||||
@@ -105,22 +107,20 @@ protected:
|
||||
|
||||
virtual void ScaleChangedEvent(const double &) override;
|
||||
|
||||
virtual void ConnectedNodeChanged(Sequence*){}
|
||||
virtual void ConnectedNodeChanged(ViewerOutput*){}
|
||||
|
||||
virtual void ConnectNodeInternal(Sequence*){}
|
||||
virtual void ConnectNodeInternal(ViewerOutput*){}
|
||||
|
||||
virtual void DisconnectNodeInternal(Sequence*){}
|
||||
virtual void DisconnectNodeInternal(ViewerOutput*){}
|
||||
|
||||
void SetAutoMaxScrollBar(bool e);
|
||||
|
||||
virtual void resizeEvent(QResizeEvent *event) override;
|
||||
|
||||
virtual TimelinePoints* ConnectTimelinePoints();
|
||||
virtual TimelinePoints* GetTimelinePointsToConnect();
|
||||
|
||||
virtual Project* GetTimelinePointsProject();
|
||||
|
||||
TimelinePoints* GetConnectedTimelinePoints() const;
|
||||
|
||||
void ConnectTimelineView(TimeBasedView* base, bool connect_time_change_event = true);
|
||||
|
||||
void PassWheelEventsToScrollBar(QObject* object);
|
||||
@@ -189,7 +189,7 @@ private:
|
||||
|
||||
bool UserIsDraggingPlayhead() const;
|
||||
|
||||
Sequence* viewer_node_;
|
||||
ViewerOutput* viewer_node_;
|
||||
|
||||
TimeRuler* ruler_;
|
||||
|
||||
|
||||
@@ -1395,9 +1395,9 @@ public:
|
||||
QString relevant_input;
|
||||
|
||||
if (timeline_->type() == Track::kVideo) {
|
||||
relevant_input = Sequence::kTextureInput;
|
||||
relevant_input = ViewerOutput::kTextureInput;
|
||||
} else {
|
||||
relevant_input = Sequence::kSamplesInput;
|
||||
relevant_input = ViewerOutput::kSamplesInput;
|
||||
}
|
||||
|
||||
if (!timeline_->parent()->IsInputConnected(relevant_input)) {
|
||||
|
||||
@@ -218,10 +218,12 @@ void TimelineWidget::ScaleChangedEvent(const double &scale)
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineWidget::ConnectNodeInternal(Sequence *n)
|
||||
void TimelineWidget::ConnectNodeInternal(ViewerOutput *n)
|
||||
{
|
||||
connect(n, &ViewerOutput::TrackAdded, this, &TimelineWidget::AddTrack);
|
||||
connect(n, &ViewerOutput::TrackRemoved, this, &TimelineWidget::RemoveTrack);
|
||||
Sequence* s = static_cast<Sequence*>(n);
|
||||
|
||||
connect(s, &Sequence::TrackAdded, this, &TimelineWidget::AddTrack);
|
||||
connect(s, &Sequence::TrackRemoved, this, &TimelineWidget::RemoveTrack);
|
||||
connect(n, &ViewerOutput::TimebaseChanged, this, &TimelineWidget::SetTimebase);
|
||||
|
||||
ruler()->SetPlaybackCache(n->video_frame_cache());
|
||||
@@ -229,7 +231,6 @@ void TimelineWidget::ConnectNodeInternal(Sequence *n)
|
||||
SetTimebase(n->video_params().time_base());
|
||||
|
||||
for (int i=0;i<views_.size();i++) {
|
||||
Sequence* s = static_cast<Sequence*>(n);
|
||||
Track::Type track_type = static_cast<Track::Type>(i);
|
||||
TimelineView* view = views_.at(i)->view();
|
||||
TrackList* track_list = s->track_list(track_type);
|
||||
@@ -246,15 +247,16 @@ void TimelineWidget::ConnectNodeInternal(Sequence *n)
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineWidget::DisconnectNodeInternal(Sequence *n)
|
||||
void TimelineWidget::DisconnectNodeInternal(ViewerOutput *n)
|
||||
{
|
||||
disconnect(n, &ViewerOutput::TrackAdded, this, &TimelineWidget::AddTrack);
|
||||
disconnect(n, &ViewerOutput::TrackRemoved, this, &TimelineWidget::RemoveTrack);
|
||||
Sequence* s = static_cast<Sequence*>(n);
|
||||
|
||||
disconnect(s, &Sequence::TrackAdded, this, &TimelineWidget::AddTrack);
|
||||
disconnect(s, &Sequence::TrackRemoved, this, &TimelineWidget::RemoveTrack);
|
||||
disconnect(n, &ViewerOutput::TimebaseChanged, this, &TimelineWidget::SetTimebase);
|
||||
|
||||
DeselectAll();
|
||||
|
||||
Sequence* s = static_cast<Sequence*>(n);
|
||||
foreach (Track* track, s->GetTracks()) {
|
||||
RemoveTrack(track);
|
||||
}
|
||||
|
||||
@@ -245,8 +245,8 @@ protected:
|
||||
virtual void TimeChangedEvent(const int64_t &) override;
|
||||
virtual void ScaleChangedEvent(const double &) override;
|
||||
|
||||
virtual void ConnectNodeInternal(Sequence* n) override;
|
||||
virtual void DisconnectNodeInternal(Sequence* n) override;
|
||||
virtual void ConnectNodeInternal(ViewerOutput* n) override;
|
||||
virtual void DisconnectNodeInternal(ViewerOutput* n) override;
|
||||
|
||||
virtual void CopyNodesToClipboardInternal(QXmlStreamWriter *writer, void* userdata) override;
|
||||
virtual void PasteNodesFromClipboardInternal(QXmlStreamReader *reader, XMLNodeData &xml_node_data, void* userdata) override;
|
||||
|
||||
@@ -102,7 +102,7 @@ void AddTool::MouseRelease(TimelineViewMouseEvent *event)
|
||||
command->add_child(new NodeAddCommand(graph,
|
||||
clip));
|
||||
|
||||
command->add_child(new TrackPlaceBlockCommand(static_cast<Sequence*>(parent()->GetConnectedNode())->track_list(track.type()),
|
||||
command->add_child(new TrackPlaceBlockCommand(sequence()->track_list(track.type()),
|
||||
track.index(),
|
||||
clip,
|
||||
ghost_->GetAdjustedIn()));
|
||||
|
||||
@@ -313,12 +313,11 @@ void ImportTool::DropGhosts(bool insert)
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
|
||||
NodeGraph* dst_graph = nullptr;
|
||||
Sequence* sequence = nullptr;
|
||||
Sequence* sequence = this->sequence();
|
||||
bool open_sequence = false;
|
||||
|
||||
if (parent()->GetConnectedNode()) {
|
||||
sequence = parent()->GetConnectedNode();
|
||||
dst_graph = parent()->GetConnectedNode()->parent();
|
||||
if (sequence) {
|
||||
dst_graph = sequence->parent();
|
||||
} else {
|
||||
// There's no active timeline here, ask the user what to do
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ void FootageViewerWidget::SetFootage(Footage *footage)
|
||||
}
|
||||
}
|
||||
|
||||
TimelinePoints *FootageViewerWidget::ConnectTimelinePoints()
|
||||
TimelinePoints *FootageViewerWidget::GetTimelinePointsToConnect()
|
||||
{
|
||||
return footage_;
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ public:
|
||||
void SetFootage(Footage* footage);
|
||||
|
||||
protected:
|
||||
virtual TimelinePoints* ConnectTimelinePoints() override;
|
||||
virtual TimelinePoints* GetTimelinePointsToConnect() override;
|
||||
|
||||
virtual Project* GetTimelinePointsProject() override;
|
||||
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
#include "common/ratiodialog.h"
|
||||
#include "common/timecodefunctions.h"
|
||||
#include "config/config.h"
|
||||
#include "project/item/sequence/sequence.h"
|
||||
#include "project/project.h"
|
||||
#include "render/rendermanager.h"
|
||||
#include "task/taskmanager.h"
|
||||
@@ -44,12 +43,14 @@
|
||||
|
||||
namespace olive {
|
||||
|
||||
#define super TimeBasedWidget
|
||||
|
||||
QVector<ViewerWidget*> ViewerWidget::instances_;
|
||||
|
||||
const int kMaxPreQueueSize = 16;
|
||||
|
||||
ViewerWidget::ViewerWidget(QWidget *parent) :
|
||||
TimeBasedWidget(false, true, parent),
|
||||
super(false, true, parent),
|
||||
playback_speed_(0),
|
||||
frame_cache_job_time_(0),
|
||||
color_menu_enabled_(true),
|
||||
@@ -168,7 +169,7 @@ void ViewerWidget::TimeChangedEvent(const int64_t &i)
|
||||
last_time_ = i;
|
||||
}
|
||||
|
||||
void ViewerWidget::ConnectNodeInternal(Sequence *n)
|
||||
void ViewerWidget::ConnectNodeInternal(ViewerOutput *n)
|
||||
{
|
||||
connect(n, &ViewerOutput::SizeChanged, this, &ViewerWidget::SetViewerResolution);
|
||||
connect(n, &ViewerOutput::PixelAspectChanged, this, &ViewerWidget::SetViewerPixelAspect);
|
||||
@@ -220,7 +221,7 @@ void ViewerWidget::ConnectNodeInternal(Sequence *n)
|
||||
ForceUpdate();
|
||||
}
|
||||
|
||||
void ViewerWidget::DisconnectNodeInternal(Sequence *n)
|
||||
void ViewerWidget::DisconnectNodeInternal(ViewerOutput *n)
|
||||
{
|
||||
PauseInternal();
|
||||
|
||||
@@ -252,21 +253,21 @@ void ViewerWidget::DisconnectNodeInternal(Sequence *n)
|
||||
QMetaObject::invokeMethod(this, "UpdateStack", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void ViewerWidget::ConnectedNodeChanged(Sequence *n)
|
||||
void ViewerWidget::ConnectedNodeChanged(ViewerOutput *n)
|
||||
{
|
||||
auto_cacher_.SetViewerNode(n);
|
||||
}
|
||||
|
||||
void ViewerWidget::ScaleChangedEvent(const double &s)
|
||||
{
|
||||
TimeBasedWidget::ScaleChangedEvent(s);
|
||||
super::ScaleChangedEvent(s);
|
||||
|
||||
waveform_view_->SetScale(s);
|
||||
}
|
||||
|
||||
void ViewerWidget::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
TimeBasedWidget::resizeEvent(event);
|
||||
super::resizeEvent(event);
|
||||
|
||||
UpdateMinimumScale();
|
||||
}
|
||||
@@ -285,11 +286,11 @@ bool ViewerWidget::IsPlaying() const
|
||||
return playback_speed_ != 0;
|
||||
}
|
||||
|
||||
void ViewerWidget::ConnectViewerNode(Sequence *node, ColorManager* color_manager)
|
||||
void ViewerWidget::ConnectViewerNode(ViewerOutput *node, ColorManager* color_manager)
|
||||
{
|
||||
override_color_manager_ = color_manager;
|
||||
|
||||
TimeBasedWidget::ConnectViewerNode(node);
|
||||
super::ConnectViewerNode(node);
|
||||
}
|
||||
|
||||
void ViewerWidget::SetColorMenuEnabled(bool enabled)
|
||||
@@ -1053,7 +1054,7 @@ void ViewerWidget::SetSignalCursorColorEnabled(bool e)
|
||||
|
||||
void ViewerWidget::TimebaseChangedEvent(const rational &timebase)
|
||||
{
|
||||
TimeBasedWidget::TimebaseChangedEvent(timebase);
|
||||
super::TimebaseChangedEvent(timebase);
|
||||
|
||||
controls_->SetTimebase(timebase);
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ public:
|
||||
|
||||
bool IsPlaying() const;
|
||||
|
||||
void ConnectViewerNode(Sequence *node, ColorManager *color_manager = nullptr);
|
||||
void ConnectViewerNode(ViewerOutput *node, ColorManager *color_manager = nullptr);
|
||||
|
||||
/**
|
||||
* @brief Enable or disable the color management menu
|
||||
@@ -153,9 +153,9 @@ protected:
|
||||
virtual void TimebaseChangedEvent(const rational &) override;
|
||||
virtual void TimeChangedEvent(const int64_t &) override;
|
||||
|
||||
virtual void ConnectNodeInternal(Sequence *) override;
|
||||
virtual void DisconnectNodeInternal(Sequence *) override;
|
||||
virtual void ConnectedNodeChanged(Sequence*n) override;
|
||||
virtual void ConnectNodeInternal(ViewerOutput *) override;
|
||||
virtual void DisconnectNodeInternal(ViewerOutput *) override;
|
||||
virtual void ConnectedNodeChanged(ViewerOutput*n) override;
|
||||
|
||||
virtual void ScaleChangedEvent(const double& s) override;
|
||||
|
||||
|
||||
@@ -549,7 +549,7 @@ void MainWindow::RemoveProjectPanel(ProjectPanel *panel)
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::TimelineFocused(Sequence* viewer)
|
||||
void MainWindow::TimelineFocused(ViewerOutput* viewer)
|
||||
{
|
||||
sequence_viewer_panel_->ConnectViewerNode(viewer);
|
||||
param_panel_->ConnectViewerNode(viewer);
|
||||
|
||||
@@ -130,7 +130,7 @@ private:
|
||||
|
||||
void RemoveProjectPanel(ProjectPanel* panel);
|
||||
|
||||
void TimelineFocused(Sequence *viewer);
|
||||
void TimelineFocused(ViewerOutput *viewer);
|
||||
|
||||
QByteArray premaximized_state_;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user