use frame rate and timebase less interchangeably
This commit is contained in:
@@ -219,7 +219,7 @@ void FFmpegEncoder::WriteAudio(AudioParams pcm_info, QIODevice* file)
|
|||||||
// If not, use another frame size
|
// If not, use another frame size
|
||||||
if (params().video_enabled()) {
|
if (params().video_enabled()) {
|
||||||
// If we're encoding video, use enough samples to cover roughly one frame of video
|
// If we're encoding video, use enough samples to cover roughly one frame of video
|
||||||
maximum_frame_samples = params().audio_params().time_to_samples(params().video_params().time_base());
|
maximum_frame_samples = params().audio_params().time_to_samples(params().video_params().frame_rate_as_time_base());
|
||||||
} else {
|
} else {
|
||||||
// If no video, just use an arbitrary number
|
// If no video, just use an arbitrary number
|
||||||
maximum_frame_samples = 256;
|
maximum_frame_samples = 256;
|
||||||
@@ -484,7 +484,7 @@ bool FFmpegEncoder::InitializeStream(AVMediaType type, AVStream** stream_ptr, AV
|
|||||||
codec_ctx->width = params().video_params().width();
|
codec_ctx->width = params().video_params().width();
|
||||||
codec_ctx->height = params().video_params().height();
|
codec_ctx->height = params().video_params().height();
|
||||||
codec_ctx->sample_aspect_ratio = params().video_params().pixel_aspect_ratio().toAVRational();
|
codec_ctx->sample_aspect_ratio = params().video_params().pixel_aspect_ratio().toAVRational();
|
||||||
codec_ctx->time_base = params().video_params().time_base().toAVRational();
|
codec_ctx->time_base = params().video_params().frame_rate_as_time_base().toAVRational();
|
||||||
codec_ctx->pix_fmt = av_get_pix_fmt(params().video_pix_fmt().toUtf8());
|
codec_ctx->pix_fmt = av_get_pix_fmt(params().video_pix_fmt().toUtf8());
|
||||||
|
|
||||||
if (params().video_params().interlacing() != VideoParams::kInterlaceNone) {
|
if (params().video_params().interlacing() != VideoParams::kInterlaceNone) {
|
||||||
|
|||||||
@@ -281,11 +281,19 @@ int64_t Timecode::time_to_timestamp(const double &time, const rational &timebase
|
|||||||
|
|
||||||
int64_t Timecode::rescale_timestamp(const int64_t &ts, const rational &source, const rational &dest)
|
int64_t Timecode::rescale_timestamp(const int64_t &ts, const rational &source, const rational &dest)
|
||||||
{
|
{
|
||||||
|
if (source == dest) {
|
||||||
|
return ts;
|
||||||
|
}
|
||||||
|
|
||||||
return qRound64(static_cast<double>(ts) * source.toDouble() / dest.toDouble());
|
return qRound64(static_cast<double>(ts) * source.toDouble() / dest.toDouble());
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t Timecode::rescale_timestamp_ceil(const int64_t &ts, const rational &source, const rational &dest)
|
int64_t Timecode::rescale_timestamp_ceil(const int64_t &ts, const rational &source, const rational &dest)
|
||||||
{
|
{
|
||||||
|
if (source == dest) {
|
||||||
|
return ts;
|
||||||
|
}
|
||||||
|
|
||||||
return qCeil(static_cast<double>(ts) * source.toDouble() / dest.toDouble());
|
return qCeil(static_cast<double>(ts) * source.toDouble() / dest.toDouble());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -195,7 +195,7 @@ ExportDialog::ExportDialog(ViewerOutput *viewer_node, QWidget *parent) :
|
|||||||
video_tab_->width_slider()->SetDefaultValue(vp.width());
|
video_tab_->width_slider()->SetDefaultValue(vp.width());
|
||||||
video_tab_->height_slider()->SetValue(vp.height());
|
video_tab_->height_slider()->SetValue(vp.height());
|
||||||
video_tab_->height_slider()->SetDefaultValue(vp.height());
|
video_tab_->height_slider()->SetDefaultValue(vp.height());
|
||||||
video_tab_->frame_rate_combobox()->SetFrameRate(vp.time_base().flipped());
|
video_tab_->frame_rate_combobox()->SetFrameRate(vp.frame_rate());
|
||||||
video_tab_->pixel_aspect_combobox()->SetPixelAspectRatio(vp.pixel_aspect_ratio());
|
video_tab_->pixel_aspect_combobox()->SetPixelAspectRatio(vp.pixel_aspect_ratio());
|
||||||
video_tab_->pixel_format_field()->SetPixelFormat(static_cast<VideoParams::Format>(Config::Current()["OnlinePixelFormat"].toInt()));
|
video_tab_->pixel_format_field()->SetPixelFormat(static_cast<VideoParams::Format>(Config::Current()["OnlinePixelFormat"].toInt()));
|
||||||
video_tab_->interlaced_combobox()->SetInterlaceMode(vp.interlacing());
|
video_tab_->interlaced_combobox()->SetInterlaceMode(vp.interlacing());
|
||||||
|
|||||||
@@ -92,30 +92,13 @@ QString ViewerOutput::Description() const
|
|||||||
|
|
||||||
QString ViewerOutput::duration() const
|
QString ViewerOutput::duration() const
|
||||||
{
|
{
|
||||||
/*rational timeline_length = GetLength();
|
|
||||||
|
|
||||||
rational timebase = GetVideoParams().time_base();
|
|
||||||
|
|
||||||
int64_t timestamp = Timecode::time_to_timestamp(timeline_length, timebase);
|
|
||||||
|
|
||||||
return Timecode::timestamp_to_timecode(timestamp, timebase, Core::instance()->GetTimecodeDisplay());*/
|
|
||||||
// Try video first
|
// Try video first
|
||||||
VideoParams video = GetFirstEnabledVideoStream();
|
VideoParams video = GetFirstEnabledVideoStream();
|
||||||
|
|
||||||
if (video.is_valid() && video.video_type() != VideoParams::kVideoTypeStill) {
|
if (video.is_valid() && video.video_type() != VideoParams::kVideoTypeStill) {
|
||||||
int64_t duration = video.duration();
|
rational frame_rate_timebase = video.frame_rate_as_time_base();
|
||||||
|
|
||||||
rational frame_rate_timebase = video.frame_rate().flipped();
|
return Timecode::timestamp_to_timecode(Timecode::rescale_timestamp_ceil(video.duration(), video.time_base(), frame_rate_timebase),
|
||||||
if (frame_rate_timebase.isNull()) {
|
|
||||||
frame_rate_timebase = video.time_base();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (video.time_base() != frame_rate_timebase) {
|
|
||||||
// Convert from timebase to frame rate
|
|
||||||
duration = Timecode::rescale_timestamp_ceil(duration, video.time_base(), frame_rate_timebase);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Timecode::timestamp_to_timecode(duration,
|
|
||||||
frame_rate_timebase,
|
frame_rate_timebase,
|
||||||
Core::instance()->GetTimecodeDisplay());
|
Core::instance()->GetTimecodeDisplay());
|
||||||
}
|
}
|
||||||
@@ -147,13 +130,7 @@ QString ViewerOutput::rate() const
|
|||||||
VideoParams video_stream = GetFirstEnabledVideoStream();
|
VideoParams video_stream = GetFirstEnabledVideoStream();
|
||||||
|
|
||||||
if (video_stream.video_type() != VideoParams::kVideoTypeStill) {
|
if (video_stream.video_type() != VideoParams::kVideoTypeStill) {
|
||||||
rational using_tb = video_stream.frame_rate();
|
return tr("%1 FPS").arg(video_stream.frame_rate().toDouble());
|
||||||
|
|
||||||
if (using_tb.isNull()) {
|
|
||||||
using_tb = video_stream.time_base().flipped();
|
|
||||||
}
|
|
||||||
|
|
||||||
return tr("%1 FPS").arg(using_tb.toDouble());
|
|
||||||
}
|
}
|
||||||
} else if (HasEnabledAudioStreams()) {
|
} else if (HasEnabledAudioStreams()) {
|
||||||
// No video streams, return audio
|
// No video streams, return audio
|
||||||
@@ -414,7 +391,7 @@ void ViewerOutput::InputValueChangedEvent(const QString &input, int element)
|
|||||||
VideoParams new_video_params = GetVideoParams();
|
VideoParams new_video_params = GetVideoParams();
|
||||||
|
|
||||||
bool size_changed = cached_video_params_.width() != new_video_params.width() || cached_video_params_.height() != new_video_params.height();
|
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 frame_rate_changed = cached_video_params_.frame_rate() != new_video_params.frame_rate();
|
||||||
bool pixel_aspect_changed = cached_video_params_.pixel_aspect_ratio() != new_video_params.pixel_aspect_ratio();
|
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();
|
bool interlacing_changed = cached_video_params_.interlacing() != new_video_params.interlacing();
|
||||||
|
|
||||||
@@ -430,9 +407,9 @@ void ViewerOutput::InputValueChangedEvent(const QString &input, int element)
|
|||||||
emit InterlacingChanged(new_video_params.interlacing());
|
emit InterlacingChanged(new_video_params.interlacing());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timebase_changed) {
|
if (frame_rate_changed) {
|
||||||
video_frame_cache_.SetTimebase(new_video_params.time_base());
|
video_frame_cache_.SetTimebase(new_video_params.frame_rate_as_time_base());
|
||||||
emit TimebaseChanged(new_video_params.time_base());
|
emit FrameRateChanged(new_video_params.frame_rate());
|
||||||
}
|
}
|
||||||
|
|
||||||
emit VideoParamsChanged();
|
emit VideoParamsChanged();
|
||||||
@@ -479,7 +456,7 @@ void ViewerOutput::set_parameters_from_footage(const QVector<ViewerOutput *> foo
|
|||||||
// prioritize
|
// prioritize
|
||||||
using_timebase = GetVideoParams().time_base();
|
using_timebase = GetVideoParams().time_base();
|
||||||
} else {
|
} else {
|
||||||
using_timebase = s.frame_rate().flipped();
|
using_timebase = s.frame_rate_as_time_base();
|
||||||
found_video_params = true;
|
found_video_params = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ public:
|
|||||||
static const uint64_t kVideoParamEditMask;
|
static const uint64_t kVideoParamEditMask;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void TimebaseChanged(const rational&);
|
void FrameRateChanged(const rational&);
|
||||||
|
|
||||||
void LengthChanged(const rational& length);
|
void LengthChanged(const rational& length);
|
||||||
|
|
||||||
|
|||||||
@@ -123,6 +123,39 @@ void Footage::InputValueChangedEvent(const QString &input, int element)
|
|||||||
AddStream(Track::kVideo, QVariant::fromValue(footage_info.GetVideoStreams().at(i)));
|
AddStream(Track::kVideo, QVariant::fromValue(footage_info.GetVideoStreams().at(i)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!footage_info.GetVideoStreams().isEmpty()) {
|
||||||
|
// FIXME: This will break on multiple video streams. Currently we don't have
|
||||||
|
// infrastructure for different properties per element. We'll see if this becomes
|
||||||
|
// a problem.
|
||||||
|
VideoParams vp = footage_info.GetVideoStreams().first();
|
||||||
|
|
||||||
|
uint64_t video_param_mask = 0;
|
||||||
|
|
||||||
|
video_param_mask |= VideoParamEdit::kEnabled;
|
||||||
|
video_param_mask |= VideoParamEdit::kColorspace;
|
||||||
|
video_param_mask |= VideoParamEdit::kPixelAspect;
|
||||||
|
video_param_mask |= VideoParamEdit::kInterlacing;
|
||||||
|
video_param_mask |= VideoParamEdit::kFrameRateIsArbitrary;
|
||||||
|
|
||||||
|
if (vp.channel_count() == VideoParams::kRGBAChannelCount) {
|
||||||
|
// Add premultiplied setting if this footage has an alpha channel
|
||||||
|
video_param_mask |= VideoParamEdit::kPremultipliedAlpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vp.video_type() == VideoParams::kVideoTypeVideo) {
|
||||||
|
// This is video, ensure that the frame rate does not overwrite the timebase
|
||||||
|
video_param_mask |= VideoParamEdit::kFrameRateIsNotTimebase;
|
||||||
|
} else {
|
||||||
|
// This is not a video, so it's either a still image or an image sequence
|
||||||
|
video_param_mask |= VideoParamEdit::kIsImageSequence;
|
||||||
|
video_param_mask |= VideoParamEdit::kStartTime;
|
||||||
|
video_param_mask |= VideoParamEdit::kEndTime;
|
||||||
|
video_param_mask |= VideoParamEdit::kFrameRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetInputProperty(kVideoParamsInput, QStringLiteral("mask"), QVariant::fromValue(video_param_mask));
|
||||||
|
}
|
||||||
|
|
||||||
for (int i=0; i<footage_info.GetAudioStreams().size(); i++) {
|
for (int i=0; i<footage_info.GetAudioStreams().size(); i++) {
|
||||||
AddStream(Track::kAudio, QVariant::fromValue(footage_info.GetAudioStreams().at(i)));
|
AddStream(Track::kAudio, QVariant::fromValue(footage_info.GetAudioStreams().at(i)));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ public:
|
|||||||
format_(format)
|
format_(format)
|
||||||
{
|
{
|
||||||
set_default_footage_parameters();
|
set_default_footage_parameters();
|
||||||
|
timebase_ = sample_rate_as_time_base();
|
||||||
}
|
}
|
||||||
|
|
||||||
int sample_rate() const
|
int sample_rate() const
|
||||||
@@ -98,11 +99,7 @@ public:
|
|||||||
|
|
||||||
rational time_base() const
|
rational time_base() const
|
||||||
{
|
{
|
||||||
if (timebase_.isNull()) {
|
return timebase_;
|
||||||
return rational(1, sample_rate());
|
|
||||||
} else {
|
|
||||||
return timebase_;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_time_base(const rational& timebase)
|
void set_time_base(const rational& timebase)
|
||||||
@@ -110,6 +107,11 @@ public:
|
|||||||
timebase_ = timebase;
|
timebase_ = timebase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rational sample_rate_as_time_base() const
|
||||||
|
{
|
||||||
|
return rational(1, sample_rate());
|
||||||
|
}
|
||||||
|
|
||||||
Format format() const
|
Format format() const
|
||||||
{
|
{
|
||||||
return format_;
|
return format_;
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ void FrameHashCache::SetHash(const rational &time, const QByteArray &hash, const
|
|||||||
if (job.range.Contains(time)
|
if (job.range.Contains(time)
|
||||||
&& job_time < job.job_time) {
|
&& job_time < job.job_time) {
|
||||||
// Hash here has changed since this frame started rendering, discard it
|
// Hash here has changed since this frame started rendering, discard it
|
||||||
|
qDebug() << "Discarded hash because old";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -71,6 +72,7 @@ void FrameHashCache::SetHash(const rational &time, const QByteArray &hash, const
|
|||||||
|
|
||||||
void FrameHashCache::SetTimebase(const rational &tb)
|
void FrameHashCache::SetTimebase(const rational &tb)
|
||||||
{
|
{
|
||||||
|
qDebug() << "Hello timebase" << tb;
|
||||||
timebase_ = tb;
|
timebase_ = tb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ void RenderProcessor::Run()
|
|||||||
NodeOutput texture_output = viewer->GetConnectedTextureOutput();
|
NodeOutput texture_output = viewer->GetConnectedTextureOutput();
|
||||||
if (texture_output.IsValid()) {
|
if (texture_output.IsValid()) {
|
||||||
table = GenerateTable(texture_output.node(), texture_output.output(),
|
table = GenerateTable(texture_output.node(), texture_output.output(),
|
||||||
TimeRange(time, time + video_params.time_base()));
|
TimeRange(time, time + video_params.frame_rate_as_time_base()));
|
||||||
}
|
}
|
||||||
|
|
||||||
TexturePtr texture = table.Get(NodeValue::kTexture).value<TexturePtr>();
|
TexturePtr texture = table.Get(NodeValue::kTexture).value<TexturePtr>();
|
||||||
|
|||||||
@@ -112,7 +112,8 @@ VideoParams::VideoParams(int width, int height, const rational &time_base, Forma
|
|||||||
channel_count_(nb_channels),
|
channel_count_(nb_channels),
|
||||||
pixel_aspect_ratio_(pixel_aspect_ratio),
|
pixel_aspect_ratio_(pixel_aspect_ratio),
|
||||||
interlacing_(interlacing),
|
interlacing_(interlacing),
|
||||||
divider_(divider)
|
divider_(divider),
|
||||||
|
frame_rate_(time_base.flipped())
|
||||||
{
|
{
|
||||||
calculate_effective_size();
|
calculate_effective_size();
|
||||||
validate_pixel_aspect_ratio();
|
validate_pixel_aspect_ratio();
|
||||||
|
|||||||
@@ -122,6 +122,11 @@ public:
|
|||||||
time_base_ = r;
|
time_base_ = r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rational frame_rate_as_time_base() const
|
||||||
|
{
|
||||||
|
return frame_rate_.flipped();
|
||||||
|
}
|
||||||
|
|
||||||
int divider() const
|
int divider() const
|
||||||
{
|
{
|
||||||
return divider_;
|
return divider_;
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ void ExportTask::FrameDownloaded(FramePtr f, const QByteArray &hash, const QVect
|
|||||||
|
|
||||||
forever {
|
forever {
|
||||||
rational real_time = Timecode::timestamp_to_time(frame_time_,
|
rational real_time = Timecode::timestamp_to_time(frame_time_,
|
||||||
viewer()->GetVideoParams().time_base());
|
viewer()->GetVideoParams().frame_rate_as_time_base());
|
||||||
|
|
||||||
if (!time_map_.contains(real_time)) {
|
if (!time_map_.contains(real_time)) {
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ bool RenderTask::Render(ColorManager* manager,
|
|||||||
|
|
||||||
double progress_counter = 0;
|
double progress_counter = 0;
|
||||||
double total_length = 0;
|
double total_length = 0;
|
||||||
double video_frame_sz = video_params().time_base().toDouble();
|
double video_frame_sz = video_params().frame_rate_as_time_base().toDouble();
|
||||||
|
|
||||||
// Store real time before any rendering takes place
|
// Store real time before any rendering takes place
|
||||||
qint64 job_time = QDateTime::currentMSecsSinceEpoch();
|
qint64 job_time = QDateTime::currentMSecsSinceEpoch();
|
||||||
|
|||||||
@@ -74,46 +74,58 @@ ViewerOutput *TimeBasedWidget::GetConnectedNode() const
|
|||||||
|
|
||||||
void TimeBasedWidget::ConnectViewerNode(ViewerOutput *node)
|
void TimeBasedWidget::ConnectViewerNode(ViewerOutput *node)
|
||||||
{
|
{
|
||||||
|
// Ignore no-op
|
||||||
if (viewer_node_ == node) {
|
if (viewer_node_ == node) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (viewer_node_) {
|
if (viewer_node_) {
|
||||||
|
// Call potential derivative functions for disconnecting the viewer node
|
||||||
DisconnectNodeInternal(viewer_node_);
|
DisconnectNodeInternal(viewer_node_);
|
||||||
|
|
||||||
|
// Disconnect length changed signal
|
||||||
disconnect(viewer_node_, &ViewerOutput::LengthChanged, this, &TimeBasedWidget::UpdateMaximumScroll);
|
disconnect(viewer_node_, &ViewerOutput::LengthChanged, this, &TimeBasedWidget::UpdateMaximumScroll);
|
||||||
disconnect(viewer_node_, &ViewerOutput::TimebaseChanged, this, &TimeBasedWidget::SetTimebase);
|
|
||||||
|
|
||||||
if (auto_set_timebase_) {
|
// Reset timebase to null
|
||||||
SetTimebase(rational());
|
SetTimebase(rational());
|
||||||
}
|
|
||||||
|
|
||||||
|
// Disconnect ruler and scrollbar from timeline points
|
||||||
ruler()->ConnectTimelinePoints(nullptr);
|
ruler()->ConnectTimelinePoints(nullptr);
|
||||||
scrollbar_->ConnectTimelinePoints(nullptr);
|
scrollbar_->ConnectTimelinePoints(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set viewer node
|
||||||
viewer_node_ = node;
|
viewer_node_ = node;
|
||||||
|
|
||||||
|
// Call derivatives
|
||||||
ConnectedNodeChanged(viewer_node_);
|
ConnectedNodeChanged(viewer_node_);
|
||||||
|
|
||||||
if (viewer_node_) {
|
if (viewer_node_) {
|
||||||
|
// Connect length changed signal
|
||||||
connect(viewer_node_, &ViewerOutput::LengthChanged, this, &TimeBasedWidget::UpdateMaximumScroll);
|
connect(viewer_node_, &ViewerOutput::LengthChanged, this, &TimeBasedWidget::UpdateMaximumScroll);
|
||||||
|
|
||||||
|
// Connect ruler and scrollbar to timeline points
|
||||||
ruler()->ConnectTimelinePoints(viewer_node_->GetTimelinePoints());
|
ruler()->ConnectTimelinePoints(viewer_node_->GetTimelinePoints());
|
||||||
scrollbar_->ConnectTimelinePoints(viewer_node_->GetTimelinePoints());
|
scrollbar_->ConnectTimelinePoints(viewer_node_->GetTimelinePoints());
|
||||||
|
|
||||||
|
// If we're setting the timebase, set it automatically based on the video and audio parameters
|
||||||
if (auto_set_timebase_) {
|
if (auto_set_timebase_) {
|
||||||
if (!viewer_node_->GetVideoParams().time_base().isNull()) {
|
rational video_tb = viewer_node_->GetVideoParams().frame_rate_as_time_base();
|
||||||
SetTimebase(viewer_node_->GetVideoParams().time_base());
|
|
||||||
} else if (viewer_node_->GetAudioParams().sample_rate() > 0) {
|
|
||||||
SetTimebase(viewer_node_->GetAudioParams().time_base());
|
|
||||||
} else {
|
|
||||||
SetTimebase(rational());
|
|
||||||
}
|
|
||||||
|
|
||||||
connect(viewer_node_, &ViewerOutput::TimebaseChanged, this, &TimeBasedWidget::SetTimebase);
|
if (!video_tb.isNull()) {
|
||||||
|
SetTimebase(video_tb);
|
||||||
|
} else {
|
||||||
|
rational audio_tb = viewer_node_->GetAudioParams().sample_rate_as_time_base();
|
||||||
|
|
||||||
|
if (!audio_tb.isNull()) {
|
||||||
|
SetTimebase(audio_tb);
|
||||||
|
} else {
|
||||||
|
SetTimebase(rational());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Call derivatives
|
||||||
ConnectNodeInternal(viewer_node_);
|
ConnectNodeInternal(viewer_node_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -224,11 +224,10 @@ void TimelineWidget::ConnectNodeInternal(ViewerOutput *n)
|
|||||||
|
|
||||||
connect(s, &Sequence::TrackAdded, this, &TimelineWidget::AddTrack);
|
connect(s, &Sequence::TrackAdded, this, &TimelineWidget::AddTrack);
|
||||||
connect(s, &Sequence::TrackRemoved, this, &TimelineWidget::RemoveTrack);
|
connect(s, &Sequence::TrackRemoved, this, &TimelineWidget::RemoveTrack);
|
||||||
connect(n, &ViewerOutput::TimebaseChanged, this, &TimelineWidget::SetTimebase);
|
|
||||||
|
|
||||||
ruler()->SetPlaybackCache(n->video_frame_cache());
|
ruler()->SetPlaybackCache(n->video_frame_cache());
|
||||||
|
|
||||||
SetTimebase(n->GetVideoParams().time_base());
|
SetTimebase(n->GetVideoParams().frame_rate_as_time_base());
|
||||||
|
|
||||||
for (int i=0;i<views_.size();i++) {
|
for (int i=0;i<views_.size();i++) {
|
||||||
Track::Type track_type = static_cast<Track::Type>(i);
|
Track::Type track_type = static_cast<Track::Type>(i);
|
||||||
@@ -253,7 +252,6 @@ void TimelineWidget::DisconnectNodeInternal(ViewerOutput *n)
|
|||||||
|
|
||||||
disconnect(s, &Sequence::TrackAdded, this, &TimelineWidget::AddTrack);
|
disconnect(s, &Sequence::TrackAdded, this, &TimelineWidget::AddTrack);
|
||||||
disconnect(s, &Sequence::TrackRemoved, this, &TimelineWidget::RemoveTrack);
|
disconnect(s, &Sequence::TrackRemoved, this, &TimelineWidget::RemoveTrack);
|
||||||
disconnect(n, &ViewerOutput::TimebaseChanged, this, &TimelineWidget::SetTimebase);
|
|
||||||
|
|
||||||
DeselectAll();
|
DeselectAll();
|
||||||
|
|
||||||
|
|||||||
@@ -281,7 +281,7 @@ void ImportTool::PrepGhosts(const rational& frame, const int& track_index)
|
|||||||
if (parent()->GetConnectedNode()) {
|
if (parent()->GetConnectedNode()) {
|
||||||
FootageToGhosts(frame,
|
FootageToGhosts(frame,
|
||||||
dragged_footage_,
|
dragged_footage_,
|
||||||
parent()->timebase(),
|
parent()->GetConnectedNode()->GetVideoParams().time_base(),
|
||||||
track_index);
|
track_index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -97,6 +97,10 @@ VideoParamEdit::VideoParamEdit(QWidget* parent) :
|
|||||||
connect(frame_rate_combobox_, static_cast<void (FrameRateComboBox::*)(int)>(&FrameRateComboBox::currentIndexChanged), this, &VideoParamEdit::Changed);
|
connect(frame_rate_combobox_, static_cast<void (FrameRateComboBox::*)(int)>(&FrameRateComboBox::currentIndexChanged), this, &VideoParamEdit::Changed);
|
||||||
layout->addWidget(frame_rate_combobox_, row, 1);
|
layout->addWidget(frame_rate_combobox_, row, 1);
|
||||||
|
|
||||||
|
frame_rate_slider_ = new FloatSlider();
|
||||||
|
connect(frame_rate_slider_, &FloatSlider::ValueChanged, this, &VideoParamEdit::Changed);
|
||||||
|
layout->addWidget(frame_rate_slider_, row, 1);
|
||||||
|
|
||||||
row++;
|
row++;
|
||||||
|
|
||||||
// Pixel Aspect Ratio
|
// Pixel Aspect Ratio
|
||||||
@@ -215,7 +219,8 @@ void VideoParamEdit::SetParameterMask(uint64_t mask)
|
|||||||
depth_slider_->setVisible(mask & kDepth);
|
depth_slider_->setVisible(mask & kDepth);
|
||||||
|
|
||||||
frame_rate_lbl_->setVisible(mask & kFrameRate);
|
frame_rate_lbl_->setVisible(mask & kFrameRate);
|
||||||
frame_rate_combobox_->setVisible(mask & kFrameRate);
|
frame_rate_combobox_->setVisible((mask & kFrameRate) && (mask & ~kFrameRateIsArbitrary));
|
||||||
|
frame_rate_slider_->setVisible((mask & kFrameRate) && (mask & kFrameRateIsArbitrary));
|
||||||
|
|
||||||
pixel_aspect_lbl_->setVisible(mask & kPixelAspect);
|
pixel_aspect_lbl_->setVisible(mask & kPixelAspect);
|
||||||
pixel_aspect_combobox_->setVisible(mask & kPixelAspect);
|
pixel_aspect_combobox_->setVisible(mask & kPixelAspect);
|
||||||
@@ -263,12 +268,22 @@ VideoParams VideoParamEdit::GetVideoParams() const
|
|||||||
p.set_height(height_slider_->GetValue());
|
p.set_height(height_slider_->GetValue());
|
||||||
p.set_depth(depth_slider_->GetValue());
|
p.set_depth(depth_slider_->GetValue());
|
||||||
|
|
||||||
p.set_frame_rate(frame_rate_combobox_->GetFrameRate());
|
{
|
||||||
if (mask_ & kFrameRateIsNotTimebase) {
|
rational using_frame_rate;
|
||||||
// Frame rate editor will only edit the frame rate
|
|
||||||
p.set_time_base(timebase_temp_);
|
if (mask_ & kFrameRateIsArbitrary) {
|
||||||
} else {
|
using_frame_rate = rational::fromDouble(frame_rate_slider_->GetValue());
|
||||||
p.set_time_base(frame_rate_combobox_->GetFrameRate().flipped());
|
} else {
|
||||||
|
using_frame_rate = frame_rate_combobox_->GetFrameRate();
|
||||||
|
}
|
||||||
|
|
||||||
|
p.set_frame_rate(using_frame_rate);
|
||||||
|
if (mask_ & kFrameRateIsNotTimebase) {
|
||||||
|
// Frame rate editor will only edit the frame rate
|
||||||
|
p.set_time_base(timebase_temp_);
|
||||||
|
} else {
|
||||||
|
p.set_time_base(using_frame_rate.flipped());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p.set_pixel_aspect_ratio(pixel_aspect_combobox_->GetPixelAspectRatio());
|
p.set_pixel_aspect_ratio(pixel_aspect_combobox_->GetPixelAspectRatio());
|
||||||
@@ -295,14 +310,9 @@ void VideoParamEdit::SetVideoParams(const VideoParams &p)
|
|||||||
height_slider_->SetValue(p.height());
|
height_slider_->SetValue(p.height());
|
||||||
depth_slider_->SetValue(p.depth());
|
depth_slider_->SetValue(p.depth());
|
||||||
|
|
||||||
if (mask_ & kFrameRateIsNotTimebase) {
|
frame_rate_combobox_->SetFrameRate(p.frame_rate());
|
||||||
// Frame rate editor will only edit the frame rate
|
frame_rate_slider_->SetValue(p.frame_rate().toDouble());
|
||||||
frame_rate_combobox_->SetFrameRate(p.frame_rate());
|
timebase_temp_ = p.time_base();
|
||||||
timebase_temp_ = p.time_base();
|
|
||||||
} else {
|
|
||||||
// Frame rate editor will edit both frame rate and time base
|
|
||||||
frame_rate_combobox_->SetFrameRate(p.time_base().flipped());
|
|
||||||
}
|
|
||||||
|
|
||||||
pixel_aspect_combobox_->SetPixelAspectRatio(p.pixel_aspect_ratio());
|
pixel_aspect_combobox_->SetPixelAspectRatio(p.pixel_aspect_ratio());
|
||||||
interlaced_combobox_->SetInterlaceMode(p.interlacing());
|
interlaced_combobox_->SetInterlaceMode(p.interlacing());
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include "render/colormanager.h"
|
#include "render/colormanager.h"
|
||||||
#include "render/videoparams.h"
|
#include "render/videoparams.h"
|
||||||
|
#include "widget/slider/floatslider.h"
|
||||||
#include "widget/slider/integerslider.h"
|
#include "widget/slider/integerslider.h"
|
||||||
#include "widget/standardcombos/frameratecombobox.h"
|
#include "widget/standardcombos/frameratecombobox.h"
|
||||||
#include "widget/standardcombos/interlacedcombobox.h"
|
#include "widget/standardcombos/interlacedcombobox.h"
|
||||||
@@ -60,6 +61,7 @@ public:
|
|||||||
kPremultipliedAlpha = 0x2000,
|
kPremultipliedAlpha = 0x2000,
|
||||||
kColorspace = 0x4000,
|
kColorspace = 0x4000,
|
||||||
kFrameRateIsNotTimebase = 0x8000,
|
kFrameRateIsNotTimebase = 0x8000,
|
||||||
|
kFrameRateIsArbitrary = 0x10000
|
||||||
};
|
};
|
||||||
|
|
||||||
void SetParameterMask(uint64_t mask);
|
void SetParameterMask(uint64_t mask);
|
||||||
@@ -143,6 +145,7 @@ private:
|
|||||||
IntegerSlider* depth_slider_;
|
IntegerSlider* depth_slider_;
|
||||||
QLabel* frame_rate_lbl_;
|
QLabel* frame_rate_lbl_;
|
||||||
FrameRateComboBox* frame_rate_combobox_;
|
FrameRateComboBox* frame_rate_combobox_;
|
||||||
|
FloatSlider* frame_rate_slider_;
|
||||||
QLabel* pixel_aspect_lbl_;
|
QLabel* pixel_aspect_lbl_;
|
||||||
PixelAspectRatioComboBox* pixel_aspect_combobox_;
|
PixelAspectRatioComboBox* pixel_aspect_combobox_;
|
||||||
QLabel* interlaced_lbl_;
|
QLabel* interlaced_lbl_;
|
||||||
|
|||||||
@@ -71,10 +71,13 @@ ViewerWidget::ViewerWidget(QWidget *parent) :
|
|||||||
stack_->addWidget(sizer_);
|
stack_->addWidget(sizer_);
|
||||||
|
|
||||||
display_widget_ = new ViewerDisplayWidget();
|
display_widget_ = new ViewerDisplayWidget();
|
||||||
|
display_widget_->setAcceptDrops(true);
|
||||||
connect(display_widget_, &ViewerDisplayWidget::customContextMenuRequested, this, &ViewerWidget::ShowContextMenu);
|
connect(display_widget_, &ViewerDisplayWidget::customContextMenuRequested, this, &ViewerWidget::ShowContextMenu);
|
||||||
connect(display_widget_, &ViewerDisplayWidget::CursorColor, this, &ViewerWidget::CursorColor);
|
connect(display_widget_, &ViewerDisplayWidget::CursorColor, this, &ViewerWidget::CursorColor);
|
||||||
connect(display_widget_, &ViewerDisplayWidget::ColorProcessorChanged, this, &ViewerWidget::ColorProcessorChanged);
|
connect(display_widget_, &ViewerDisplayWidget::ColorProcessorChanged, this, &ViewerWidget::ColorProcessorChanged);
|
||||||
connect(display_widget_, &ViewerDisplayWidget::ColorManagerChanged, this, &ViewerWidget::ColorManagerChanged);
|
connect(display_widget_, &ViewerDisplayWidget::ColorManagerChanged, this, &ViewerWidget::ColorManagerChanged);
|
||||||
|
connect(display_widget_, &ViewerDisplayWidget::DragEntered, this, &ViewerWidget::DragEntered);
|
||||||
|
connect(display_widget_, &ViewerDisplayWidget::Dropped, this, &ViewerWidget::Dropped);
|
||||||
connect(sizer_, &ViewerSizer::RequestScale, display_widget_, &ViewerDisplayWidget::SetMatrixZoom);
|
connect(sizer_, &ViewerSizer::RequestScale, display_widget_, &ViewerDisplayWidget::SetMatrixZoom);
|
||||||
connect(sizer_, &ViewerSizer::RequestTranslate, display_widget_, &ViewerDisplayWidget::SetMatrixTranslate);
|
connect(sizer_, &ViewerSizer::RequestTranslate, display_widget_, &ViewerDisplayWidget::SetMatrixTranslate);
|
||||||
connect(display_widget_, &ViewerDisplayWidget::HandDragMoved, sizer_, &ViewerSizer::HandDragMove);
|
connect(display_widget_, &ViewerDisplayWidget::HandDragMoved, sizer_, &ViewerSizer::HandDragMove);
|
||||||
@@ -118,6 +121,8 @@ ViewerWidget::ViewerWidget(QWidget *parent) :
|
|||||||
SetAutoMaxScrollBar(true);
|
SetAutoMaxScrollBar(true);
|
||||||
|
|
||||||
instances_.append(this);
|
instances_.append(this);
|
||||||
|
|
||||||
|
setAcceptDrops(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
ViewerWidget::~ViewerWidget()
|
ViewerWidget::~ViewerWidget()
|
||||||
@@ -1214,4 +1219,37 @@ void ViewerWidget::ViewerShiftedRange(const rational &from, const rational &to)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ViewerWidget::DragEntered(QDragEnterEvent* event)
|
||||||
|
{
|
||||||
|
if (event->mimeData()->formats().contains(QStringLiteral("application/x-oliveprojectitemdata"))) {
|
||||||
|
event->accept();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ViewerWidget::Dropped(QDropEvent *event)
|
||||||
|
{
|
||||||
|
QByteArray mimedata = event->mimeData()->data(QStringLiteral("application/x-oliveprojectitemdata"));
|
||||||
|
QDataStream stream(&mimedata, QIODevice::ReadOnly);
|
||||||
|
|
||||||
|
// Variables to deserialize into
|
||||||
|
quintptr item_ptr = 0;
|
||||||
|
QVector<Track::Reference> enabled_streams;
|
||||||
|
|
||||||
|
while (!stream.atEnd()) {
|
||||||
|
stream >> enabled_streams >> item_ptr;
|
||||||
|
|
||||||
|
// We only need the one item
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item_ptr) {
|
||||||
|
Node* item = reinterpret_cast<Node*>(item_ptr);
|
||||||
|
ViewerOutput* viewer = dynamic_cast<ViewerOutput*>(item);
|
||||||
|
|
||||||
|
if (viewer) {
|
||||||
|
ConnectViewerNode(viewer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -288,6 +288,10 @@ private slots:
|
|||||||
|
|
||||||
void TimeChangedFromWaveform(qint64 t);
|
void TimeChangedFromWaveform(qint64 t);
|
||||||
|
|
||||||
|
void DragEntered(QDragEnterEvent* event);
|
||||||
|
|
||||||
|
void Dropped(QDropEvent* event);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -278,20 +278,29 @@ void ViewerDisplayWidget::mouseReleaseEvent(QMouseEvent *event)
|
|||||||
|
|
||||||
void ViewerDisplayWidget::dragEnterEvent(QDragEnterEvent *event)
|
void ViewerDisplayWidget::dragEnterEvent(QDragEnterEvent *event)
|
||||||
{
|
{
|
||||||
emit DragEntered();
|
emit DragEntered(event);
|
||||||
super::dragEnterEvent(event);
|
|
||||||
|
if (!event->isAccepted()) {
|
||||||
|
super::dragEnterEvent(event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViewerDisplayWidget::dragLeaveEvent(QDragLeaveEvent *event)
|
void ViewerDisplayWidget::dragLeaveEvent(QDragLeaveEvent *event)
|
||||||
{
|
{
|
||||||
emit DragLeft();
|
emit DragLeft(event);
|
||||||
super::dragLeaveEvent(event);
|
|
||||||
|
if (!event->isAccepted()) {
|
||||||
|
super::dragLeaveEvent(event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViewerDisplayWidget::dropEvent(QDropEvent *event)
|
void ViewerDisplayWidget::dropEvent(QDropEvent *event)
|
||||||
{
|
{
|
||||||
emit Dropped();
|
emit Dropped(event);
|
||||||
super::dropEvent(event);
|
|
||||||
|
if (!event->isAccepted()) {
|
||||||
|
super::dropEvent(event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViewerDisplayWidget::OnPaint()
|
void ViewerDisplayWidget::OnPaint()
|
||||||
@@ -345,7 +354,7 @@ void ViewerDisplayWidget::OnPaint()
|
|||||||
rational node_time = GetGizmoTime();
|
rational node_time = GetGizmoTime();
|
||||||
|
|
||||||
gizmo_db_ = gt.GenerateDatabase(gizmos_, TimeRange(node_time,
|
gizmo_db_ = gt.GenerateDatabase(gizmos_, TimeRange(node_time,
|
||||||
node_time + gizmo_params_.time_base()));
|
node_time + gizmo_params_.frame_rate_as_time_base()));
|
||||||
|
|
||||||
QPainter p(inner_widget());
|
QPainter p(inner_widget());
|
||||||
p.setWorldTransform(GenerateGizmoTransform());
|
p.setWorldTransform(GenerateGizmoTransform());
|
||||||
|
|||||||
@@ -170,11 +170,11 @@ signals:
|
|||||||
*/
|
*/
|
||||||
void CursorColor(const Color& reference, const Color& display);
|
void CursorColor(const Color& reference, const Color& display);
|
||||||
|
|
||||||
void DragEntered();
|
void DragEntered(QDragEnterEvent* event);
|
||||||
|
|
||||||
void DragLeft();
|
void DragLeft(QDragLeaveEvent* event);
|
||||||
|
|
||||||
void Dropped();
|
void Dropped(QDropEvent* event);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user