buildConsumer();
- Mlt::Producer *producer = new Mlt::Producer(*m_mltProfile , "colour", "black");
- m_mltProducer = producer;
- if (m_blackClip) delete m_blackClip;
- m_blackClip = new Mlt::Producer(*m_mltProfile , "colour", "black");
- m_blackClip->set("id", "black");
+ m_mltProducer = m_blackClip->cut(0, 50);
m_mltConsumer->connect(*m_mltProducer);
m_mltProducer->set_speed(0.0);
}
m_activeProfile = KdenliveSettings::current_profile();
tmp = decodedString(m_activeProfile);
setenv("MLT_PROFILE", tmp, 1);
+ if (m_blackClip) delete m_blackClip;
+ m_blackClip = NULL;
+
m_mltProfile = new Mlt::Profile(tmp);
delete[] tmp;
m_mltConsumer->set("resize", 1);
m_mltConsumer->set("window_id", m_winid);
m_mltConsumer->set("terminate_on_pause", 1);
+ m_mltConsumer->set("window_background", decodedString(KdenliveSettings::window_background().name()));
m_mltConsumer->listen("consumer-frame-show", this, (mlt_listener) consumer_frame_show);
m_mltConsumer->set("rescale", "nearest");
m_mltConsumer->set("progressive", 1);
m_mltConsumer->set("audio_buffer", 1024);
m_mltConsumer->set("frequency", 48000);
+
+ m_blackClip = new Mlt::Producer(*m_mltProfile , "colour", "black");
+ m_blackClip->set("id", "black");
+
}
int Render::resetProfile() {
}
}
-void Render::getFileProperties(const QDomElement &xml, const QString &clipId) {
+void Render::getFileProperties(const QDomElement &xml, const QString &clipId, bool replaceProducer) {
int height = 50;
int width = (int)(height * m_mltProfile->dar());
QMap < QString, QString > filePropertyMap;
KUrl url = KUrl(xml.attribute("resource", QString::null));
Mlt::Producer *producer = NULL;
if (xml.attribute("type").toInt() == TEXT && !QFile::exists(url.path())) {
- emit replyGetFileProperties(clipId, producer, filePropertyMap, metadataPropertyMap);
+ emit replyGetFileProperties(clipId, producer, filePropertyMap, metadataPropertyMap, replaceProducer);
return;
}
if (xml.attribute("type").toInt() == COLOR) {
pix.fill(Qt::black);
mlt_pool_release(new_image);
- emit replyGetImage(clipId, 0, pix, width, height);
+ emit replyGetImage(clipId, pix);
} else if (frame->get_int("test_audio") == 0) {
QPixmap pixmap = KIcon("audio-x-generic").pixmap(QSize(width, height));
- emit replyGetImage(clipId, 0, pixmap, width, height);
+ emit replyGetImage(clipId, pixmap);
filePropertyMap["type"] = "audio";
}
}
if (producer->get(property))
filePropertyMap["videocodec"] = producer->get(property);
}
+
+ if (KdenliveSettings::dropbframes()) {
+ kDebug() << "// LOOKING FOR H264 on: " << default_video;
+ snprintf(property, sizeof(property), "meta.media.%d.codec.name", default_video);
+ kDebug() << "PROP: " << property << " = " << producer->get(property);
+ if (producer->get(property) && strcmp(producer->get(property), "h264") == 0) {
+ kDebug() << "// GOT H264 CLIP, SETTING FAST PROPS";
+ producer->set("skip_loop_filter", "all");
+ producer->set("skip_frame", "bidir");
+ }
+ }
+
} else kDebug() << " / / / / /WARNING, VIDEO CONTEXT IS NULL!!!!!!!!!!!!!!";
if (producer->get_int("audio_index") > -1) {
// Get the audio_index
metadataPropertyMap[ name.section(".", 0, -2)] = value;
}
- emit replyGetFileProperties(clipId, producer, filePropertyMap, metadataPropertyMap);
+ emit replyGetFileProperties(clipId, producer, filePropertyMap, metadataPropertyMap, replaceProducer);
kDebug() << "REquested fuile info for: " << url.path();
if (frame) delete frame;
//if (producer) delete producer;
m_mltConsumer->stop();
} else return;
+ m_mltConsumer->purge();
+
m_isBlocked = true;
if (m_mltProducer) {
m_mltProducer->set_speed(0);
m_mltProducer = NULL;
emit stopped();
}
- if (producer) m_mltProducer = new Mlt::Producer(producer->get_producer());
- else m_mltProducer = new Mlt::Producer();
+ if (producer) {
+ m_mltProducer = new Mlt::Producer(producer->get_producer());
+ } else m_mltProducer = m_blackClip->cut(0, 50);
+ /*if (KdenliveSettings::dropbframes()) {
+ m_mltProducer->set("skip_loop_filter", "all");
+ m_mltProducer->set("skip_frame", "bidir");
+ }*/
if (!m_mltProducer || !m_mltProducer->is_valid()) kDebug() << " WARNING - - - - -INVALID PLAYLIST: ";
m_fps = m_mltProducer->get_fps();
void Render::setSceneList(QString playlist, int position) {
if (m_winid == -1) return;
m_isBlocked = true;
+ m_slowmotionProducers.clear();
//kWarning() << "////// RENDER, SET SCENE LIST: " << playlist;
char *tmp = decodedString(playlist);
m_mltProducer = new Mlt::Producer(*m_mltProfile, "westley-xml", tmp);
delete[] tmp;
- if (m_blackClip) delete m_blackClip;
- m_blackClip = new Mlt::Producer(*m_mltProfile , "colour", "black");
- m_blackClip->set("id", "black");
+
if (!m_mltProducer || !m_mltProducer->is_valid()) {
kDebug() << " WARNING - - - - -INVALID PLAYLIST: " << tmp;
}
m_fps = m_mltProducer->get_fps();
kDebug() << "// NEW SCENE LIST DURATION SET TO: " << m_mltProducer->get_playtime();
connectPlaylist();
+ fillSlowMotionProducers();
if (position != 0) {
//TODO: seek to correct place after opening project.
// Needs to be done from another place since it crashes here.
}
/** Create the producer from the Westley QDomDocument */
-QString Render::sceneList() {
+const QString Render::sceneList() {
QString playlist;
Mlt::Consumer westleyConsumer(*m_mltProfile , "westley:kdenlive_playlist");
m_mltProducer->optimise();
if (m_mltConsumer && !m_mltConsumer->is_stopped()) {
kDebug() << "///////////// RENDER STOPPED: " << m_name;
m_isBlocked = true;
- m_mltConsumer->set("refresh", 0);
+ //m_mltConsumer->set("refresh", 0);
m_mltConsumer->stop();
// delete m_mltConsumer;
// m_mltConsumer = NULL;
if (!m_mltProducer || !m_mltConsumer)
return;
m_isBlocked = false;
+ if (!m_isZoneMode) m_originalOut = m_mltProducer->get_playtime() - 1;
m_mltProducer->set("out", stopTime.frames(m_fps));
m_mltProducer->seek((int)(startTime.frames(m_fps)));
m_mltProducer->set_speed(1.0);
}
void Render::resetZoneMode() {
- m_mltProducer->set("out", m_mltProducer->get_length() - 1);
+ if (!m_isZoneMode && !m_isLoopMode) return;
+ m_mltProducer->set("out", m_originalOut);
//m_mltProducer->set("eof", "pause");
m_isZoneMode = false;
m_isLoopMode = false;
Mlt::Producer trackProducer(tractor.track(info.track));
Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
//kDebug()<<"/// INSERT cLIP: "<<info.cropStart.frames(m_fps)<<", "<<info.startPos.frames(m_fps)<<"-"<<info.endPos.frames(m_fps);
+
+ if (element.attribute("speed", "1.0").toDouble() != 1.0) {
+ // We want a slowmotion producer
+ double speed = element.attribute("speed", "1.0").toDouble();
+ QString url = prod->get("resource");
+ url.append("?" + QString::number(speed));
+ Mlt::Producer *slowprod = m_slowmotionProducers.value(url);
+ if (!slowprod || slowprod->get_producer() == NULL) {
+ char *tmp = decodedString(url);
+ slowprod = new Mlt::Producer(*m_mltProfile, "framebuffer", tmp);
+ delete[] tmp;
+ QString id = prod->get("id");
+ if (id.contains('_')) id = id.section('_', 0, 0);
+ QString producerid = "slowmotion:" + id + ":" + QString::number(speed);
+ tmp = decodedString(producerid);
+ slowprod->set("id", tmp);
+ delete[] tmp;
+ m_slowmotionProducers.insert(url, slowprod);
+ }
+ prod = slowprod;
+ }
+
Mlt::Producer *clip = prod->cut((int) info.cropStart.frames(m_fps), (int)(info.endPos - info.startPos + info.cropStart).frames(m_fps) - 1);
int newIndex = trackPlaylist.insert_at((int) info.startPos.frames(m_fps), *clip, 1);
int newLength = 0;
Mlt::Service service(m_mltProducer->parent().get_service());
if (service.type() != tractor_type) kWarning() << "// TRACTOR PROBLEM";
- kDebug() << "Changing clip speed, set in and out: " << info.cropStart.frames(m_fps) << " to " << (info.endPos - info.startPos).frames(m_fps) - 1;
+ //kDebug() << "Changing clip speed, set in and out: " << info.cropStart.frames(m_fps) << " to " << (info.endPos - info.startPos).frames(m_fps) - 1;
Mlt::Tractor tractor(service);
Mlt::Producer trackProducer(tractor.track(info.track));
Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
int clipLength = trackPlaylist.clip_length(clipIndex);
Mlt::Producer clip(trackPlaylist.get_clip(clipIndex));
- QString serv = clip.parent().get("mlt_service");
- QString id = clip.parent().get("id");
- kDebug() << "CLIP SERVICE: " << clip.parent().get("mlt_service");
+ if (!clip.is_valid() || clip.is_blank()) {
+ // invalid clip
+ return -1;
+ }
+ Mlt::Producer clipparent = clip.parent();
+ if (!clipparent.is_valid() || clipparent.is_blank()) {
+ // invalid clip
+ return -1;
+ }
+ QString serv = clipparent.get("mlt_service");
+ QString id = clipparent.get("id");
+ //kDebug() << "CLIP SERVICE: " << serv;
if (serv == "avformat" && speed != 1.0) {
mlt_service_lock(service.get_service());
- QString url = clip.parent().get("resource");
+ QString url = clipparent.get("resource");
url.append("?" + QString::number(speed));
Mlt::Producer *slowprod = m_slowmotionProducers.value(url);
if (!slowprod || slowprod->get_producer() == NULL) {
} else if (serv == "framebuffer") {
mlt_service_lock(service.get_service());
- QString url = clip.parent().get("resource");
+ QString url = clipparent.get("resource");
url = url.section("?", 0, 0);
url.append("?" + QString::number(speed));
Mlt::Producer *slowprod = m_slowmotionProducers.value(url);
Mlt::Producer *cut;
if (clipIndex + 1 < trackPlaylist.count() && (info.startPos + newDuration).frames(m_fps) > blankEnd) {
GenTime maxLength = GenTime(blankEnd, m_fps) - info.startPos;
- cut = slowprod->cut((int)(info.cropStart.frames(m_fps)), (int)(info.cropStart.frames(m_fps) + maxLength.frames(m_fps) - 1));
+ cut = slowprod->cut((int)(info.cropStart.frames(m_fps) / speed), (int)(info.cropStart.frames(m_fps) / speed + maxLength.frames(m_fps) - 1));
} else cut = slowprod->cut((int)(info.cropStart.frames(m_fps) / speed), (int)((info.cropStart / speed + newDuration).frames(m_fps) - 1));
trackPlaylist.insert_at(startPos, *cut, 1);
return newLength;
}
-bool Render::mltRemoveEffect(int track, GenTime position, QString index, bool doRefresh) {
-
+bool Render::mltRemoveEffect(int track, GenTime position, QString index, bool updateIndex, bool doRefresh) {
+ kDebug() << "// TRYing to remove effect at: " << index;
Mlt::Service service(m_mltProducer->parent().get_service());
bool success = false;
Mlt::Tractor tractor(service);
if ((index == "-1" && filter->get("kdenlive_id") != "") || filter->get("kdenlive_ix") == index) {// && filter->get("kdenlive_id") == id) {
if (clipService.detach(*filter) == 0) success = true;
kDebug() << " / / / DLEETED EFFECT: " << ct;
- } else {
+ } else if (updateIndex) {
+ // Adjust the other effects index
if (QString(filter->get("kdenlive_ix")).toInt() > index.toInt()) filter->set("kdenlive_ix", QString(filter->get("kdenlive_ix")).toInt() - 1);
ct++;
- }
+ } else ct++;
filter = clipService.filter(ct);
}
m_isBlocked = false;
if (!params.paramValue("keyframes").isEmpty() || /*it.key().startsWith("#") || */tag.startsWith("ladspa") || tag == "sox" || tag == "autotrack_rectangle") {
// This is a keyframe effect, to edit it, we remove it and re-add it.
- mltRemoveEffect(track, position, index);
+ mltRemoveEffect(track, position, index, true);
bool success = mltAddEffect(track, position, params);
return success;
}
int previousDuration = trackPlaylist.clip_length(clipIndex) - 1;
int newDuration = (int) clipDuration.frames(m_fps) - 1;
trackPlaylist.resize_clip(clipIndex, previousStart, newDuration + previousStart);
- //trackPlaylist.consolidate_blanks(0);
+ trackPlaylist.consolidate_blanks(0);
// skip to next clip
clipIndex++;
int diff = newDuration - previousDuration;
- kDebug() << "//////// RESIZE CLIP: " << clipIndex << "( pos: " << info.startPos.frames(25) << "), DIFF: " << diff << ", CURRENT DUR: " << previousDuration << ", NEW DUR: " << newDuration;
+ kDebug() << "//////// RESIZE CLIP: " << clipIndex << "( pos: " << info.startPos.frames(25) << "), DIFF: " << diff << ", CURRENT DUR: " << previousDuration << ", NEW DUR: " << newDuration << ", IX: " << clipIndex << ", MAX: " << trackPlaylist.count();
if (diff > 0) {
// clip was made longer, trim next blank if there is one.
- if (trackPlaylist.is_blank(clipIndex)) {
- int blankStart = trackPlaylist.clip_start(clipIndex);
- int blankDuration = trackPlaylist.clip_length(clipIndex) - 1;
- if (diff - blankDuration == 1) {
- trackPlaylist.remove(clipIndex);
- } else trackPlaylist.resize_clip(clipIndex, blankStart, blankStart + blankDuration - diff);
- } else {
- kDebug() << "/// RESIZE ERROR, NXT CLIP IS NOT BLK: " << clipIndex;
+ if (clipIndex < trackPlaylist.count()) {
+ // If this is not the last clip in playlist
+ if (trackPlaylist.is_blank(clipIndex)) {
+ int blankStart = trackPlaylist.clip_start(clipIndex);
+ int blankDuration = trackPlaylist.clip_length(clipIndex) - 1;
+ if (diff > blankDuration) kDebug() << "// ERROR blank clip is not large enough to get back required space!!!";
+ if (diff - blankDuration == 1) {
+ trackPlaylist.remove(clipIndex);
+ } else trackPlaylist.remove_region(blankStart, diff - 1);
+ } else {
+ kDebug() << "/// RESIZE ERROR, NXT CLIP IS NOT BLK: " << clipIndex;
+ }
}
} else trackPlaylist.insert_blank(clipIndex, 0 - diff - 1);
refresh();
}
+
+bool Render::mltResizeClipCrop(ItemInfo info, GenTime diff) {
+ Mlt::Service service(m_mltProducer->parent().get_service());
+ int frameOffset = (int) diff.frames(m_fps);
+ Mlt::Tractor tractor(service);
+ Mlt::Producer trackProducer(tractor.track(info.track));
+ Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
+ if (trackPlaylist.is_blank_at(info.startPos.frames(m_fps))) {
+ kDebug() << "//////// ERROR RSIZING BLANK CLIP!!!!!!!!!!!";
+ return false;
+ }
+ mlt_service_lock(service.get_service());
+ int clipIndex = trackPlaylist.get_clip_index_at(info.startPos.frames(m_fps));
+ Mlt::Producer *clip = trackPlaylist.get_clip(clipIndex);
+ if (clip == NULL) {
+ kDebug() << "//////// ERROR RSIZING NULL CLIP!!!!!!!!!!!";
+ mlt_service_unlock(service.get_service());
+ return false;
+ }
+ int previousStart = clip->get_in();
+ int previousDuration = trackPlaylist.clip_length(clipIndex) - 1;
+ m_isBlocked = true;
+ trackPlaylist.resize_clip(clipIndex, previousStart + frameOffset, previousStart + previousDuration + frameOffset);
+ m_isBlocked = false;
+ mlt_service_unlock(service.get_service());
+ m_mltConsumer->set("refresh", 1);
+ return true;
+}
+
bool Render::mltResizeClipStart(ItemInfo info, GenTime diff) {
//kDebug() << "//////// RSIZING CLIP from: "<<info.startPos.frames(25)<<" to "<<diff.frames(25);
Mlt::Service service(m_mltProducer->parent().get_service());
}
mlt_service_lock(service.get_service());
int clipIndex = trackPlaylist.get_clip_index_at(info.startPos.frames(m_fps));
- /*int previousStart = trackPlaylist.clip_start(clipIndex);
- int previousDuration = trackPlaylist.clip_length(clipIndex) - 1;*/
- //kDebug() << " ** RESIZING CLIP START:" << clipIndex << " on track:" << track << ", mid pos: " << pos.frames(25) << ", moving: " << moveFrame << ", in: " << in.frames(25) << ", out: " << out.frames(25);
Mlt::Producer *clip = trackPlaylist.get_clip(clipIndex);
if (clip == NULL) {
kDebug() << "//////// ERROR RSIZING NULL CLIP!!!!!!!!!!!";
mlt_service_unlock(service.get_service());
return false;
}
- //m_mltConsumer->set("refresh", 0);
int previousStart = clip->get_in();
int previousDuration = trackPlaylist.clip_length(clipIndex) - 1;
m_isBlocked = true;
void Render::mltUpdateClipProducer(int track, int pos, Mlt::Producer *prod) {
+ if (prod == NULL || !prod->is_valid()) {
+ kDebug() << "// Warning, CLIP on track " << track << ", at: " << pos << " is invalid, cannot update it!!!";
+ return;
+ }
kDebug() << "NEW PROD ID: " << prod->get("id");
m_mltConsumer->set("refresh", 0);
kDebug() << "// TRYING TO UPDATE CLIP at: " << pos << ", TK: " << track;
QList <Mlt::Producer *> Render::producersList() {
QList <Mlt::Producer *> prods = QList <Mlt::Producer *> ();
- QStringList ids;
Mlt::Service service(m_mltProducer->parent().get_service());
+ if (service.type() != tractor_type) return prods;
Mlt::Tractor tractor(service);
+ QStringList ids;
int trackNb = tractor.count();
for (int t = 1; t < trackNb; t++) {
Mlt::Producer trackProducer(tractor.track(t));
Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
int clipNb = trackPlaylist.count();
- kDebug() << "// PARSING SCENE TRACK: " << t << ", CLIPS: " << clipNb;
+ //kDebug() << "// PARSING SCENE TRACK: " << t << ", CLIPS: " << clipNb;
for (int i = 0; i < clipNb; i++) {
- Mlt::Producer *prod = trackPlaylist.get_clip(i);
- Mlt::Producer *nprod = new Mlt::Producer(prod->get_parent());
- //kDebug()<<"PROD: "<<nprod->get("producer")<<", ID: "<<nprod->get("id")<<nprod->get("resource");
+ Mlt::Producer *nprod = new Mlt::Producer(trackPlaylist.get_clip(i)->get_parent());
if (nprod && !nprod->is_blank() && !ids.contains(nprod->get("id"))) {
ids.append(nprod->get("id"));
prods.append(nprod);
return prods;
}
+void Render::fillSlowMotionProducers() {
+ Mlt::Service service(m_mltProducer->parent().get_service());
+ if (service.type() != tractor_type) return;
+
+ Mlt::Tractor tractor(service);
+
+ int trackNb = tractor.count();
+ for (int t = 1; t < trackNb; t++) {
+ Mlt::Producer trackProducer(tractor.track(t));
+ Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
+ int clipNb = trackPlaylist.count();
+ for (int i = 0; i < clipNb; i++) {
+ Mlt::Producer *nprod = new Mlt::Producer(trackPlaylist.get_clip(i)->get_parent());
+ if (nprod && !nprod->is_blank()) {
+ QString id = nprod->get("id");
+ if (id.startsWith("slowmotion:")) {
+ // this is a slowmotion producer, add it to the list
+ QString url = nprod->get("resource");
+ if (!m_slowmotionProducers.contains(url)) {
+ m_slowmotionProducers.insert(url, nprod);
+ }
+ }
+ }
+ }
+ }
+}
+
void Render::mltInsertTrack(int ix, bool videoTrack) {
blockSignals(true);
m_isBlocked = true;
}
tractor.removeChild(track);
setSceneList(doc.toString(), m_framePosition);
+ mltCheckLength();
return;
blockSignals(true);
void Render::updatePreviewSettings() {
kDebug() << "////// RESTARTING CONSUMER";
+ if (!m_mltConsumer || !m_mltProducer) return;
+ if (m_mltProducer->get_playtime() == 0) return;
+ Mlt::Service service(m_mltProducer->parent().get_service());
+ if (service.type() != tractor_type) return;
+
+ //m_mltConsumer->set("refresh", 0);
if (!m_mltConsumer->is_stopped()) m_mltConsumer->stop();
m_mltConsumer->purge();
QString scene = sceneList();