[multimedia/kdenlive/release/26.08] src: Fix crash on time remap title clip
Jean-Baptiste Mardelle <[email protected]>
| Newsgroups | gmane.comp.kde.cvs |
|---|---|
| Message-ID | <[email protected]> |
Git commit f34d29cd1a394199d41833221b971b86b8ddef29 by Jean-Baptiste Mardelle.
Committed on 21/07/2026 at 07:51.
Pushed by mardelle into branch 'release/26.08'.
Fix crash on time remap title clip
BUG: 523277
FIXED-IN: 26.08.0
M +53 -47 src/dialogs/timeremap.cpp
M +0 -4 src/timeline2/model/clipmodel.cpp
M +1 -3 src/timeline2/model/timelinemodel.cpp
https://invent.kde.org/multimedia/kdenlive/-/commit/f34d29cd1a394199d41833221b971b86b8ddef29
diff --git a/src/dialogs/timeremap.cpp b/src/dialogs/timeremap.cpp
index 95bbf49f4e..9923c30d75 100644
--- a/src/dialogs/timeremap.cpp
+++ b/src/dialogs/timeremap.cpp
@@ -1739,69 +1739,75 @@ void TimeRemap::selectedClip(int cid, const QUuid uuid)
m_lastLength = pCore->getItemDuration(oid);
m_view->m_startPos = pCore->getItemPosition(oid);
model->requestClipTimeRemap(cid);
+ prod = model->getClipProducer(cid);
+ if (prod->parent().type() != mlt_service_chain_type) {
+ m_binId.clear();
+ m_view->setDuration(nullptr, -1);
+ remap_box->setEnabled(false);
+ return;
+ }
connect(model.get(), &TimelineItemModel::dataChanged, this, &TimeRemap::checkClipUpdate);
m_view->m_maxLength = prod->get_length();
+
m_in->setRange(0, m_view->m_maxLength - prod->get_in());
// m_in->setRange(0, m_lastLength - 1);
m_out->setRange(0, INT_MAX);
m_view->setDuration(prod, m_lastLength, prod->parent().get_length());
bool remapFound = false;
- if (prod->parent().type() == mlt_service_chain_type) {
- Mlt::Chain fromChain(prod->parent());
- int count = fromChain.link_count();
- QScopedPointer<Mlt::Link> fromLink;
- for (int i = 0; i < count; i++) {
- fromLink.reset(fromChain.link(i));
- if (fromLink && fromLink->is_valid() && fromLink->get("mlt_service")) {
- if (fromLink->get("mlt_service") == QLatin1String("timeremap")) {
- // Found a timeremap effect, read params
- if (!fromLink->property_exists("time_map")) {
- fromLink->set("time_map", fromLink->get("map"));
- }
- QString mapData(fromLink->get("time_map"));
- m_remapLink.reset(fromChain.link(i));
- m_view->m_remapProps.inherit(*m_remapLink.get());
- // This is a fake query to force the animation to be parsed
- (void)m_view->m_remapProps.anim_get_double("time_map", 0, m_lastLength + prod->get_in());
- m_view->loadKeyframes(mapData);
- if (mapData.isEmpty()) {
- // We are just adding the remap effect, set default params
- if (model->clipIsAudio(cid)) {
- fromLink->set("pitch", 1);
- }
- fromLink->set("image_mode", "nearest");
+ Mlt::Chain fromChain(prod->parent());
+ int count = fromChain.link_count();
+ QScopedPointer<Mlt::Link> fromLink;
+ for (int i = 0; i < count; i++) {
+ fromLink.reset(fromChain.link(i));
+ if (fromLink && fromLink->is_valid() && fromLink->get("mlt_service")) {
+ if (fromLink->get("mlt_service") == QLatin1String("timeremap")) {
+ // Found a timeremap effect, read params
+ if (!fromLink->property_exists("time_map")) {
+ fromLink->set("time_map", fromLink->get("map"));
+ }
+ QString mapData(fromLink->get("time_map"));
+ m_remapLink.reset(fromChain.link(i));
+ m_view->m_remapProps.inherit(*m_remapLink.get());
+ // This is a fake query to force the animation to be parsed
+ (void)m_view->m_remapProps.anim_get_double("time_map", 0, m_lastLength + prod->get_in());
+ qDebug() << ":::: LOADING KF CASE B...";
+ m_view->loadKeyframes(mapData);
+ if (mapData.isEmpty()) {
+ // We are just adding the remap effect, set default params
+ if (model->clipIsAudio(cid)) {
+ fromLink->set("pitch", 1);
}
- remapFound = true;
- break;
+ fromLink->set("image_mode", "nearest");
}
+ remapFound = true;
+ break;
}
}
- if (remapFound && m_splitId > -1) {
- std::shared_ptr<Mlt::Producer> prod2 = model->getClipProducer(m_splitId);
- if (prod2->parent().type() == mlt_service_chain_type) {
- Mlt::Chain fromChain2(prod2->parent());
- count = fromChain2.link_count();
- for (int j = 0; j < count; j++) {
- QScopedPointer<Mlt::Link> fromLink2(fromChain2.link(j));
- if (fromLink2 && fromLink2->is_valid() && fromLink2->get("mlt_service")) {
- if (fromLink2->get("mlt_service") == QLatin1String("timeremap")) {
- m_splitRemap.reset(fromChain2.link(j));
- break;
- }
+ }
+ if (remapFound && m_splitId > -1) {
+ std::shared_ptr<Mlt::Producer> prod2 = model->getClipProducer(m_splitId);
+ if (prod2->parent().type() == mlt_service_chain_type) {
+ Mlt::Chain fromChain2(prod2->parent());
+ count = fromChain2.link_count();
+ for (int j = 0; j < count; j++) {
+ QScopedPointer<Mlt::Link> fromLink2(fromChain2.link(j));
+ if (fromLink2 && fromLink2->is_valid() && fromLink2->get("mlt_service")) {
+ if (fromLink2->get("mlt_service") == QLatin1String("timeremap")) {
+ m_splitRemap.reset(fromChain2.link(j));
+ break;
}
}
}
}
- if (remapFound) {
- QSignalBlocker bk(pitch_compensate);
- QSignalBlocker bk2(frame_blending);
- pitch_compensate->setChecked(m_remapLink->get_int("pitch") == 1 || (m_splitRemap && m_splitRemap->get_int("pitch")));
- frame_blending->setChecked(m_remapLink->get("image_mode") != QLatin1String("nearest"));
- remap_box->setEnabled(true);
- }
- } else {
- qDebug() << "/// PRODUCER IS NOT A CHAIN!!!!";
}
+ if (remapFound) {
+ QSignalBlocker bk(pitch_compensate);
+ QSignalBlocker bk2(frame_blending);
+ pitch_compensate->setChecked(m_remapLink->get_int("pitch") == 1 || (m_splitRemap && m_splitRemap->get_int("pitch")));
+ frame_blending->setChecked(m_remapLink->get("image_mode") != QLatin1String("nearest"));
+ remap_box->setEnabled(true);
+ }
+
if (!m_binId.isEmpty() && pCore->getMonitor(Kdenlive::ClipMonitor)->activeClipId() == m_binId) {
connect(pCore->getMonitor(Kdenlive::ClipMonitor), &Monitor::seekPosition, pCore->getMonitor(Kdenlive::ClipMonitor), &Monitor::seekRemap,
Qt::UniqueConnection);
diff --git a/src/timeline2/model/clipmodel.cpp b/src/timeline2/model/clipmodel.cpp
index bd9d4dce87..dbbef954d4 100644
--- a/src/timeline2/model/clipmodel.cpp
+++ b/src/timeline2/model/clipmodel.cpp
@@ -998,10 +998,6 @@ void ClipModel::refreshProducerFromBin(int trackId)
bool ClipModel::useTimeRemapProducer(bool enable, Fun &undo, Fun &redo)
{
- if (m_endlessResize) {
- // no timewarp for endless producers
- return false;
- }
std::function<bool(void)> local_undo = []() { return true; };
std::function<bool(void)> local_redo = []() { return true; };
int audioStream = getIntProperty(QStringLiteral("audio_index"));
diff --git a/src/timeline2/model/timelinemodel.cpp b/src/timeline2/model/timelinemodel.cpp
index 5f762e684c..3a8df7d359 100644
--- a/src/timeline2/model/timelinemodel.cpp
+++ b/src/timeline2/model/timelinemodel.cpp
@@ -7257,9 +7257,7 @@ bool TimelineModel::requestClipTimeRemap(int clipId, bool enable, Fun &undo, Fun
if (trackId != -1) {
success = success && getTrackById(trackId)->requestClipDeletion(clipId, true, true, local_undo, local_redo, false, false);
}
- if (success) {
- success = m_allClips[clipId]->useTimeRemapProducer(enable, local_undo, local_redo);
- }
+ success = success && m_allClips[clipId]->useTimeRemapProducer(enable, local_undo, local_redo);
if (trackId != -1) {
success = success && getTrackById(trackId)->requestClipInsertion(clipId, oldPos, true, true, local_undo, local_redo, false, false);
if (success && !enable && previousDuration > 0) {