various: allow users to override the start and end index of image sequences
Also includes various fixes to footage property setting/signalling.
This commit is contained in:
@@ -21,7 +21,9 @@
|
||||
#include "videostreamproperties.h"
|
||||
|
||||
#include <QGridLayout>
|
||||
#include <QGroupBox>
|
||||
#include <QLabel>
|
||||
#include <QMessageBox>
|
||||
#include <OpenColorIO/OpenColorIO.h>
|
||||
namespace OCIO = OCIO_NAMESPACE::v1;
|
||||
|
||||
@@ -35,12 +37,16 @@ VideoStreamProperties::VideoStreamProperties(ImageStreamPtr stream) :
|
||||
QGridLayout* video_layout = new QGridLayout(this);
|
||||
video_layout->setMargin(0);
|
||||
|
||||
video_layout->addWidget(new QLabel(tr("Color Space:")), 0, 0);
|
||||
int row = 0;
|
||||
|
||||
video_layout->addWidget(new QLabel(tr("Color Space:")), row, 0);
|
||||
|
||||
video_color_space_ = new QComboBox();
|
||||
OCIO::ConstConfigRcPtr config = stream->footage()->project()->color_manager()->GetConfig();
|
||||
int number_of_colorspaces = config->getNumColorSpaces();
|
||||
|
||||
video_color_space_->addItem(tr("Default (%1)").arg(stream->footage()->project()->default_input_colorspace()));
|
||||
|
||||
for (int i=0;i<number_of_colorspaces;i++) {
|
||||
QString colorspace = config->getColorSpaceNameByIndex(i);
|
||||
|
||||
@@ -49,22 +55,91 @@ VideoStreamProperties::VideoStreamProperties(ImageStreamPtr stream) :
|
||||
|
||||
video_color_space_->setCurrentText(stream_->colorspace());
|
||||
|
||||
video_layout->addWidget(video_color_space_, 0, 1);
|
||||
video_layout->addWidget(video_color_space_, row, 1);
|
||||
|
||||
row++;
|
||||
|
||||
video_premultiply_alpha_ = new QCheckBox(tr("Premultiplied Alpha"));
|
||||
video_premultiply_alpha_->setChecked(stream_->premultiplied_alpha());
|
||||
video_layout->addWidget(video_premultiply_alpha_, 1, 0, 1, 2);
|
||||
video_layout->addWidget(video_premultiply_alpha_, row, 0, 1, 2);
|
||||
|
||||
row++;
|
||||
|
||||
if (IsImageSequence(stream.get())) {
|
||||
QGroupBox* imgseq_group = new QGroupBox(tr("Image Sequence"));
|
||||
QGridLayout* imgseq_layout = new QGridLayout(imgseq_group);
|
||||
|
||||
int imgseq_row = 0;
|
||||
|
||||
VideoStream* video_stream = static_cast<VideoStream*>(stream.get());
|
||||
|
||||
imgseq_layout->addWidget(new QLabel(tr("Start Index:")), imgseq_row, 0);
|
||||
|
||||
imgseq_start_time_ = new IntegerSlider();
|
||||
imgseq_start_time_->SetMinimum(0);
|
||||
imgseq_start_time_->SetValue(video_stream->start_time());
|
||||
imgseq_layout->addWidget(imgseq_start_time_, imgseq_row, 1);
|
||||
|
||||
imgseq_row++;
|
||||
|
||||
imgseq_layout->addWidget(new QLabel(tr("End Index:")), imgseq_row, 0);
|
||||
|
||||
imgseq_end_time_ = new IntegerSlider();
|
||||
imgseq_end_time_->SetMinimum(0);
|
||||
imgseq_end_time_->SetValue(video_stream->start_time() + video_stream->duration());
|
||||
imgseq_layout->addWidget(imgseq_end_time_, imgseq_row, 1);
|
||||
|
||||
video_layout->addWidget(imgseq_group, row, 0, 1, 2);
|
||||
}
|
||||
}
|
||||
|
||||
void VideoStreamProperties::Accept(QUndoCommand *parent)
|
||||
{
|
||||
QString set_colorspace;
|
||||
|
||||
if (video_color_space_->currentIndex() > 0) {
|
||||
set_colorspace = video_color_space_->currentText();
|
||||
}
|
||||
|
||||
if (video_premultiply_alpha_->isChecked() != stream_->premultiplied_alpha()
|
||||
|| video_color_space_->currentText() != stream_->colorspace()) {
|
||||
|| set_colorspace != stream_->colorspace(false)) {
|
||||
|
||||
new VideoStreamChangeCommand(stream_,
|
||||
video_premultiply_alpha_->isChecked(),
|
||||
video_color_space_->currentText(),
|
||||
set_colorspace,
|
||||
parent);
|
||||
}
|
||||
|
||||
if (IsImageSequence(stream_.get())) {
|
||||
VideoStreamPtr video_stream = std::static_pointer_cast<VideoStream>(stream_);
|
||||
|
||||
if (video_stream->start_time() != imgseq_start_time_->GetValue()) {
|
||||
new ImageSequenceChangeCommand(video_stream,
|
||||
imgseq_start_time_->GetValue(),
|
||||
imgseq_end_time_->GetValue() - imgseq_start_time_->GetValue(),
|
||||
parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool VideoStreamProperties::SanityCheck()
|
||||
{
|
||||
if (IsImageSequence(stream_.get())) {
|
||||
if (imgseq_start_time_->GetValue() >= imgseq_end_time_->GetValue()) {
|
||||
QMessageBox::critical(this,
|
||||
tr("Invalid Configuration"),
|
||||
tr("Image sequence end index must be a value higher than the start index."),
|
||||
QMessageBox::Ok);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VideoStreamProperties::IsImageSequence(ImageStream *stream)
|
||||
{
|
||||
return (stream->type() == Stream::kVideo && static_cast<VideoStream*>(stream)->is_image_sequence());
|
||||
}
|
||||
|
||||
VideoStreamProperties::VideoStreamChangeCommand::VideoStreamChangeCommand(ImageStreamPtr stream,
|
||||
@@ -81,7 +156,7 @@ VideoStreamProperties::VideoStreamChangeCommand::VideoStreamChangeCommand(ImageS
|
||||
void VideoStreamProperties::VideoStreamChangeCommand::redo_internal()
|
||||
{
|
||||
old_premultiplied_ = stream_->premultiplied_alpha();
|
||||
old_colorspace_ = stream_->colorspace();
|
||||
old_colorspace_ = stream_->colorspace(false);
|
||||
|
||||
stream_->set_premultiplied_alpha(new_premultiplied_);
|
||||
stream_->set_colorspace(new_colorspace_);
|
||||
@@ -92,3 +167,26 @@ void VideoStreamProperties::VideoStreamChangeCommand::undo_internal()
|
||||
stream_->set_premultiplied_alpha(old_premultiplied_);
|
||||
stream_->set_colorspace(old_colorspace_);
|
||||
}
|
||||
|
||||
VideoStreamProperties::ImageSequenceChangeCommand::ImageSequenceChangeCommand(VideoStreamPtr video_stream, int64_t start_index, int64_t duration, QUndoCommand *parent) :
|
||||
UndoCommand(parent),
|
||||
video_stream_(video_stream),
|
||||
new_start_index_(start_index),
|
||||
new_duration_(duration)
|
||||
{
|
||||
}
|
||||
|
||||
void VideoStreamProperties::ImageSequenceChangeCommand::redo_internal()
|
||||
{
|
||||
old_start_index_ = video_stream_->start_time();
|
||||
video_stream_->set_start_time(new_start_index_);
|
||||
|
||||
old_duration_ = video_stream_->duration();
|
||||
video_stream_->set_duration(new_duration_);
|
||||
}
|
||||
|
||||
void VideoStreamProperties::ImageSequenceChangeCommand::undo_internal()
|
||||
{
|
||||
video_stream_->set_start_time(old_start_index_);
|
||||
video_stream_->set_duration(old_duration_);
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "project/item/footage/videostream.h"
|
||||
#include "streamproperties.h"
|
||||
#include "undo/undocommand.h"
|
||||
#include "widget/slider/integerslider.h"
|
||||
|
||||
class VideoStreamProperties : public StreamProperties
|
||||
{
|
||||
@@ -35,7 +36,11 @@ public:
|
||||
|
||||
virtual void Accept(QUndoCommand* parent) override;
|
||||
|
||||
virtual bool SanityCheck() override;
|
||||
|
||||
private:
|
||||
static bool IsImageSequence(ImageStream* stream);
|
||||
|
||||
/**
|
||||
* @brief Attached video stream
|
||||
*/
|
||||
@@ -51,6 +56,16 @@ private:
|
||||
*/
|
||||
QComboBox* video_color_space_;
|
||||
|
||||
/**
|
||||
* @brief Sets the start index for image sequences
|
||||
*/
|
||||
IntegerSlider* imgseq_start_time_;
|
||||
|
||||
/**
|
||||
* @brief Sets the end index for image sequences
|
||||
*/
|
||||
IntegerSlider* imgseq_end_time_;
|
||||
|
||||
class VideoStreamChangeCommand : public UndoCommand {
|
||||
public:
|
||||
VideoStreamChangeCommand(ImageStreamPtr stream,
|
||||
@@ -70,6 +85,29 @@ private:
|
||||
|
||||
bool old_premultiplied_;
|
||||
QString old_colorspace_;
|
||||
|
||||
};
|
||||
|
||||
class ImageSequenceChangeCommand : public UndoCommand {
|
||||
public:
|
||||
ImageSequenceChangeCommand(VideoStreamPtr video_stream,
|
||||
int64_t start_index,
|
||||
int64_t duration,
|
||||
QUndoCommand* parent = nullptr);
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
|
||||
private:
|
||||
VideoStreamPtr video_stream_;
|
||||
|
||||
int64_t new_start_index_;
|
||||
int64_t old_start_index_;
|
||||
|
||||
int64_t new_duration_;
|
||||
int64_t old_duration_;
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -69,22 +69,18 @@ void MediaInput::FootageChanged()
|
||||
return;
|
||||
}
|
||||
|
||||
if (connected_footage_ != nullptr) {
|
||||
if (connected_footage_->type() == Stream::kImage || connected_footage_->type() == Stream::kVideo) {
|
||||
disconnect(connected_footage_.get(), SIGNAL(ColorSpaceChanged()), this, SLOT(FootageColorSpaceChanged()));
|
||||
}
|
||||
if (connected_footage_) {
|
||||
disconnect(connected_footage_.get(), &Stream::ParametersChanged, this, &MediaInput::FootageParametersChanged);
|
||||
}
|
||||
|
||||
connected_footage_ = new_footage;
|
||||
|
||||
if (connected_footage_ != nullptr) {
|
||||
if (connected_footage_->type() == Stream::kImage || connected_footage_->type() == Stream::kVideo) {
|
||||
connect(connected_footage_.get(), SIGNAL(ColorSpaceChanged()), this, SLOT(FootageColorSpaceChanged()));
|
||||
}
|
||||
if (connected_footage_) {
|
||||
connect(connected_footage_.get(), &Stream::ParametersChanged, this, &MediaInput::FootageParametersChanged);
|
||||
}
|
||||
}
|
||||
|
||||
void MediaInput::FootageColorSpaceChanged()
|
||||
void MediaInput::FootageParametersChanged()
|
||||
{
|
||||
InvalidateCache(0, RATIONAL_MAX, footage_input_);
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ protected:
|
||||
private slots:
|
||||
void FootageChanged();
|
||||
|
||||
void FootageColorSpaceChanged();
|
||||
void FootageParametersChanged();
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -91,11 +91,13 @@ bool ImageStream::premultiplied_alpha() const
|
||||
void ImageStream::set_premultiplied_alpha(bool e)
|
||||
{
|
||||
premultiplied_alpha_ = e;
|
||||
|
||||
emit ParametersChanged();
|
||||
}
|
||||
|
||||
const QString &ImageStream::colorspace() const
|
||||
const QString &ImageStream::colorspace(bool default_if_empty) const
|
||||
{
|
||||
if (colorspace_.isEmpty()) {
|
||||
if (colorspace_.isEmpty() && default_if_empty) {
|
||||
return footage()->project()->default_input_colorspace();
|
||||
} else {
|
||||
return colorspace_;
|
||||
@@ -106,7 +108,7 @@ void ImageStream::set_colorspace(const QString &color)
|
||||
{
|
||||
colorspace_ = color;
|
||||
|
||||
emit ColorSpaceChanged();
|
||||
emit ParametersChanged();
|
||||
}
|
||||
|
||||
void ImageStream::ColorConfigChanged()
|
||||
@@ -123,13 +125,13 @@ void ImageStream::ColorConfigChanged()
|
||||
}
|
||||
|
||||
// Either way, the color calculation has likely changed so we signal here
|
||||
emit ColorSpaceChanged();
|
||||
emit ParametersChanged();
|
||||
}
|
||||
|
||||
void ImageStream::DefaultColorSpaceChanged()
|
||||
{
|
||||
// If no colorspace is set, this stream uses the default color space and it's just changed
|
||||
if (colorspace_.isEmpty()) {
|
||||
emit ColorSpaceChanged();
|
||||
emit ParametersChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,12 +43,9 @@ public:
|
||||
bool premultiplied_alpha() const;
|
||||
void set_premultiplied_alpha(bool e);
|
||||
|
||||
const QString& colorspace() const;
|
||||
const QString& colorspace(bool default_if_empty = true) const;
|
||||
void set_colorspace(const QString& color);
|
||||
|
||||
signals:
|
||||
void ColorSpaceChanged();
|
||||
|
||||
protected:
|
||||
virtual void FootageSetEvent(Footage*) override;
|
||||
|
||||
|
||||
@@ -107,6 +107,8 @@ const int64_t &Stream::duration() const
|
||||
void Stream::set_duration(const int64_t &duration)
|
||||
{
|
||||
duration_ = duration;
|
||||
|
||||
emit ParametersChanged();
|
||||
}
|
||||
|
||||
bool Stream::enabled() const
|
||||
|
||||
@@ -115,6 +115,8 @@ protected:
|
||||
signals:
|
||||
void IndexChanged();
|
||||
|
||||
void ParametersChanged();
|
||||
|
||||
private:
|
||||
Footage* footage_;
|
||||
|
||||
|
||||
@@ -27,7 +27,8 @@
|
||||
const int64_t VideoStream::kEndTimestamp = AV_NOPTS_VALUE;
|
||||
|
||||
VideoStream::VideoStream() :
|
||||
start_time_(0)
|
||||
start_time_(0),
|
||||
is_image_sequence_(false)
|
||||
{
|
||||
set_type(kVideo);
|
||||
}
|
||||
@@ -57,6 +58,17 @@ const int64_t &VideoStream::start_time() const
|
||||
void VideoStream::set_start_time(const int64_t &start_time)
|
||||
{
|
||||
start_time_ = start_time;
|
||||
emit ParametersChanged();
|
||||
}
|
||||
|
||||
bool VideoStream::is_image_sequence() const
|
||||
{
|
||||
return is_image_sequence_;
|
||||
}
|
||||
|
||||
void VideoStream::set_image_sequence(bool e)
|
||||
{
|
||||
is_image_sequence_ = e;
|
||||
}
|
||||
|
||||
int64_t VideoStream::get_closest_timestamp_in_frame_index(const rational &time)
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
class VideoStream : public ImageStream
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
VideoStream();
|
||||
|
||||
@@ -43,6 +44,9 @@ public:
|
||||
const int64_t& start_time() const;
|
||||
void set_start_time(const int64_t& start_time);
|
||||
|
||||
bool is_image_sequence() const;
|
||||
void set_image_sequence(bool e);
|
||||
|
||||
int64_t get_closest_timestamp_in_frame_index(const rational& time);
|
||||
int64_t get_closest_timestamp_in_frame_index(int64_t timestamp);
|
||||
void clear_frame_index();
|
||||
@@ -62,6 +66,8 @@ private:
|
||||
|
||||
QMutex index_access_lock_;
|
||||
|
||||
bool is_image_sequence_;
|
||||
|
||||
};
|
||||
|
||||
using VideoStreamPtr = std::shared_ptr<VideoStream>;
|
||||
|
||||
@@ -179,6 +179,8 @@ void VideoRenderWorker::HashNodeRecursively(QCryptographicHash *hash, const Node
|
||||
if (stream->type() == Stream::kVideo) {
|
||||
hash->addData(QStringLiteral("%1/%2").arg(QString::number(input_time.numerator()),
|
||||
QString::number(input_time.denominator())).toUtf8());
|
||||
|
||||
hash->addData(QString::number(static_cast<VideoStream*>(stream.get())->start_time()).toUtf8());
|
||||
/*Decoder::RetrieveState state = decoder->GetRetrieveState(input_time);
|
||||
|
||||
if (state == Decoder::kReady) {
|
||||
|
||||
Reference in New Issue
Block a user