From cb0ebb24a43193ebc14d150df4f056d7fbed80d2 Mon Sep 17 00:00:00 2001 From: Thomas Wilshaw Date: Thu, 25 Nov 2021 13:18:01 +0000 Subject: [PATCH 1/4] saveotio: Fix external reference available media --- app/task/project/saveotio/saveotio.cpp | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/app/task/project/saveotio/saveotio.cpp b/app/task/project/saveotio/saveotio.cpp index 92af6753b..107e36ec0 100644 --- a/app/task/project/saveotio/saveotio.cpp +++ b/app/task/project/saveotio/saveotio.cpp @@ -135,12 +135,33 @@ OTIO::Track *SaveOTIOTask::SerializeTrack(Track *track) if (dynamic_cast(block)) { auto otio_clip = new OTIO::Clip(block->GetLabel().toStdString()); + auto rate = 0.0; + rational frame_rate = static_cast(block)->connected_viewer()->GetVideoParams().frame_rate(); + if (frame_rate.denominator() == 1) { + rate = frame_rate.numerator(); + } else { + // Handle strange rates + rate = static_cast(frame_rate.numerator()) / + static_cast(frame_rate.denominator()); + } + otio_clip->set_source_range(OTIO::TimeRange(block->in().toRationalTime(), - block->length().toRationalTime())); + block->length().toRationalTime(rate))); QVector media_nodes = block->FindInputNodes(); if (!media_nodes.isEmpty()) { - auto media_ref = new OTIO::ExternalReference(media_nodes.first()->filename().toStdString()); + + OTIO::TimeRange range; + if (otio_track->kind().compare("Video") == 0) { + range = OTIO::TimeRange(OTIO::RationalTime(0, rate), + OTIO::RationalTime(media_nodes.first()->GetVideoParams().duration(), + rate)); + } else if (otio_track->kind().compare("Audio") == 0) { + range = OTIO::TimeRange(OTIO::RationalTime(0, media_nodes.first()->GetAudioParams().sample_rate()), + OTIO::RationalTime(media_nodes.first()->GetAudioParams().duration(), + media_nodes.first()->GetAudioParams().sample_rate())); + } + auto media_ref = new OTIO::ExternalReference(media_nodes.first()->filename().toStdString(), range); otio_clip->set_media_reference(media_ref); } From 516c5cb3b1b3852eb99b31409f88e8b7ff7fd1d4 Mon Sep 17 00:00:00 2001 From: Thomas Wilshaw Date: Fri, 10 Dec 2021 16:46:21 +0000 Subject: [PATCH 2/4] saveotio: Use built in function and check for NaN --- app/task/project/saveotio/saveotio.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/app/task/project/saveotio/saveotio.cpp b/app/task/project/saveotio/saveotio.cpp index 107e36ec0..ecc1497b0 100644 --- a/app/task/project/saveotio/saveotio.cpp +++ b/app/task/project/saveotio/saveotio.cpp @@ -135,14 +135,10 @@ OTIO::Track *SaveOTIOTask::SerializeTrack(Track *track) if (dynamic_cast(block)) { auto otio_clip = new OTIO::Clip(block->GetLabel().toStdString()); - auto rate = 0.0; - rational frame_rate = static_cast(block)->connected_viewer()->GetVideoParams().frame_rate(); - if (frame_rate.denominator() == 1) { - rate = frame_rate.numerator(); - } else { - // Handle strange rates - rate = static_cast(frame_rate.numerator()) / - static_cast(frame_rate.denominator()); + double rate = static_cast(block)->connected_viewer()->GetVideoParams().frame_rate().toDouble(); + if (rate == qSNaN()) { + // We shouldn't ever get here, but catch without crashing if we ever do + goto fail; } otio_clip->set_source_range(OTIO::TimeRange(block->in().toRationalTime(), From dcaf34c69d657c1d8476006b2db8c10864ccd011 Mon Sep 17 00:00:00 2001 From: Thomas Wilshaw Date: Fri, 10 Dec 2021 17:34:51 +0000 Subject: [PATCH 3/4] saveotio: Use qIsNan rather than comparison --- app/task/project/saveotio/saveotio.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/task/project/saveotio/saveotio.cpp b/app/task/project/saveotio/saveotio.cpp index ecc1497b0..3764fc932 100644 --- a/app/task/project/saveotio/saveotio.cpp +++ b/app/task/project/saveotio/saveotio.cpp @@ -136,7 +136,7 @@ OTIO::Track *SaveOTIOTask::SerializeTrack(Track *track) auto otio_clip = new OTIO::Clip(block->GetLabel().toStdString()); double rate = static_cast(block)->connected_viewer()->GetVideoParams().frame_rate().toDouble(); - if (rate == qSNaN()) { + if (qIsNaN(rate)) { // We shouldn't ever get here, but catch without crashing if we ever do goto fail; } From b2b28344f43ac2a47e5cb0b157cd53d1a47f70e3 Mon Sep 17 00:00:00 2001 From: Thomas Wilshaw Date: Fri, 10 Dec 2021 22:25:42 +0000 Subject: [PATCH 4/4] saveotio: Use correct frame rates available_range is the total length of the source clip and is stored using the same frame rate as the source clip. source_range is the length of the clip in the timeline and so is stored using the sequence frame rate. --- app/task/project/saveotio/saveotio.cpp | 38 ++++++++++++++------------ app/task/project/saveotio/saveotio.h | 4 +-- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/app/task/project/saveotio/saveotio.cpp b/app/task/project/saveotio/saveotio.cpp index 3764fc932..76a6d01ed 100644 --- a/app/task/project/saveotio/saveotio.cpp +++ b/app/task/project/saveotio/saveotio.cpp @@ -102,8 +102,13 @@ OTIO::Timeline *SaveOTIOTask::SerializeTimeline(Sequence *sequence) // Suppress unused variable warning Q_UNUSED(timeline_retainer); - if (!SerializeTrackList(sequence->track_list(Track::kVideo), otio_timeline) - || !SerializeTrackList(sequence->track_list(Track::kAudio), otio_timeline)) { + double rate = sequence->GetVideoParams().frame_rate().toDouble(); + if (qIsNaN(rate)) { + return nullptr; + } + + if (!SerializeTrackList(sequence->track_list(Track::kVideo), otio_timeline, rate) + || !SerializeTrackList(sequence->track_list(Track::kAudio), otio_timeline, rate)) { otio_timeline->possibly_delete(); return nullptr; } @@ -111,7 +116,7 @@ OTIO::Timeline *SaveOTIOTask::SerializeTimeline(Sequence *sequence) return otio_timeline; } -OTIO::Track *SaveOTIOTask::SerializeTrack(Track *track) +OTIO::Track *SaveOTIOTask::SerializeTrack(Track *track, double sequence_rate) { auto otio_track = new OTIO::Track(); @@ -135,29 +140,26 @@ OTIO::Track *SaveOTIOTask::SerializeTrack(Track *track) if (dynamic_cast(block)) { auto otio_clip = new OTIO::Clip(block->GetLabel().toStdString()); - double rate = static_cast(block)->connected_viewer()->GetVideoParams().frame_rate().toDouble(); - if (qIsNaN(rate)) { - // We shouldn't ever get here, but catch without crashing if we ever do - goto fail; - } - - otio_clip->set_source_range(OTIO::TimeRange(block->in().toRationalTime(), - block->length().toRationalTime(rate))); + otio_clip->set_source_range(OTIO::TimeRange(block->in().toRationalTime(sequence_rate), + block->length().toRationalTime(sequence_rate))); QVector media_nodes = block->FindInputNodes(); if (!media_nodes.isEmpty()) { - OTIO::TimeRange range; + OTIO::TimeRange available_range; if (otio_track->kind().compare("Video") == 0) { - range = OTIO::TimeRange(OTIO::RationalTime(0, rate), + // OTIO ExternalReference uses the source clips frame rate (or sample rate) as opposed to + // the sequences rate + double source_frame_rate = static_cast(block)->connected_viewer()->GetVideoParams().frame_rate().toDouble(); + available_range = OTIO::TimeRange(OTIO::RationalTime(0, source_frame_rate), OTIO::RationalTime(media_nodes.first()->GetVideoParams().duration(), - rate)); + source_frame_rate)); } else if (otio_track->kind().compare("Audio") == 0) { - range = OTIO::TimeRange(OTIO::RationalTime(0, media_nodes.first()->GetAudioParams().sample_rate()), + available_range = OTIO::TimeRange(OTIO::RationalTime(0, media_nodes.first()->GetAudioParams().sample_rate()), OTIO::RationalTime(media_nodes.first()->GetAudioParams().duration(), media_nodes.first()->GetAudioParams().sample_rate())); } - auto media_ref = new OTIO::ExternalReference(media_nodes.first()->filename().toStdString(), range); + auto media_ref = new OTIO::ExternalReference(media_nodes.first()->filename().toStdString(), available_range); otio_clip->set_media_reference(media_ref); } @@ -198,12 +200,12 @@ fail: return nullptr; } -bool SaveOTIOTask::SerializeTrackList(TrackList *list, OTIO::Timeline* otio_timeline) +bool SaveOTIOTask::SerializeTrackList(TrackList *list, OTIO::Timeline* otio_timeline, double sequence_rate) { OTIO::ErrorStatus es; foreach (Track* track, list->GetTracks()) { - auto otio_track = SerializeTrack(track); + auto otio_track = SerializeTrack(track, sequence_rate); if (!otio_track) { return false; diff --git a/app/task/project/saveotio/saveotio.h b/app/task/project/saveotio/saveotio.h index f71df8151..0239beb4b 100644 --- a/app/task/project/saveotio/saveotio.h +++ b/app/task/project/saveotio/saveotio.h @@ -44,9 +44,9 @@ protected: private: OTIO::Timeline* SerializeTimeline(Sequence* sequence); - OTIO::Track* SerializeTrack(Track* track); + OTIO::Track* SerializeTrack(Track* track, double sequence_rate); - bool SerializeTrackList(TrackList* list, OTIO::Timeline *otio_timeline); + bool SerializeTrackList(TrackList* list, OTIO::Timeline *otio_timeline, double sequence_rate); Project* project_;