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_;