#include "renderer.h"
#include "kdenlivesettings.h"
#include "kthumb.h"
-//#include <ffmpeg/avformat.h>
+
#include <mlt++/Mlt.h>
+#if LIBAVCODEC_VERSION_MAJOR > 51 || (LIBAVCODEC_VERSION_MAJOR > 50 && LIBAVCODEC_VERSION_MINOR > 54)
+// long_name was added in FFmpeg avcodec version 51.55
+#define ENABLE_FFMPEG_CODEC_DESCRIPTION 1
+#endif
+
static void consumer_frame_show(mlt_consumer, Render * self, mlt_frame frame_ptr) {
// detect if the producer has finished playing. Is there a better way to do it ?
//if (self->isBlocked) return;
else
filePropertyMap["type"] = "video";
- // Generate thumbnail for this frame
- QPixmap pixmap = KThumb::getFrame(&producer, 0, width, height);
- emit replyGetImage(clipId, 0, pixmap, width, height);
+ QPixmap pix(width, height);
+ mlt_image_format format = mlt_image_rgb24a;
+ const uint8_t *thumb = frame->get_image(format, width, height);
+ QImage image(thumb, width, height, QImage::Format_ARGB32);
+ if (!image.isNull()) {
+ pix = pix.fromImage(image);
+ } else pix.fill(Qt::black);
+ emit replyGetImage(clipId, 0, pix, width, height);
} else if (frame->get_int("test_audio") == 0) {
QPixmap pixmap(KStandardDirs::locate("appdata", "graphics/music.png"));
if (context != NULL) {
// Get the video_index
int index = mlt_properties_get_int(properties, "video_index");
- if (context->streams && context->streams [index] && context->streams[ index ]->codec && context->streams[ index ]->codec->codec->name)
- filePropertyMap["videocodec"] = context->streams[ index ]->codec->codec->name;
+
+#if ENABLE_FFMPEG_CODEC_DESCRIPTION
+ if (context->streams && context->streams [index] && context->streams[ index ]->codec && context->streams[ index ]->codec->codec->long_name)
+ filePropertyMap["videocodec"] = context->streams[ index ]->codec->codec->long_name;
+ else
+#endif
+ if (context->streams && context->streams [index] && context->streams[ index ]->codec && context->streams[ index ]->codec->codec->name)
+ filePropertyMap["videocodec"] = context->streams[ index ]->codec->codec->name;
}
context = (AVFormatContext *) mlt_properties_get_data(properties, "audio_context", NULL);
if (context != NULL) {
// Get the video_index
int index = mlt_properties_get_int(properties, "audio_index");
- if (context->streams && context->streams [index] && context->streams[ index ]->codec && context->streams[ index ]->codec->codec->name)
- filePropertyMap["audiocodec"] = context->streams[ index ]->codec->codec->name;
+
+#if ENABLE_FFMPEG_CODEC_DESCRIPTION
+ if (context->streams && context->streams [index] && context->streams[ index ]->codec && context->streams[ index ]->codec->codec->long_name)
+ filePropertyMap["audiocodec"] = context->streams[ index ]->codec->codec->long_name;
+ else
+#endif
+ if (context->streams && context->streams [index] && context->streams[ index ]->codec && context->streams[ index ]->codec->codec->name)
+ filePropertyMap["audiocodec"] = context->streams[ index ]->codec->codec->name;
}
#endif
// metadata
if (m_winid == -1) return;
m_generateScenelist = true;
- //kWarning() << "////// RENDER, SET SCENE LIST: " << playlist;
+ // kWarning() << "////// RENDER, SET SCENE LIST: " << playlist;
/*
Mlt::Producer blackTrackProducer(tractor.track(0));
Mlt::Playlist blackTrackPlaylist((mlt_playlist) blackTrackProducer.get_service());
double blackDuration = Mlt::Producer(blackTrackPlaylist.get_producer()).get_playtime() - 1;
- kDebug() << " / / /DURATON FOR TRACK 0 = " << blackDuration;
+
if (blackDuration != duration) {
blackTrackPlaylist.remove_region(0, (int)blackDuration);
int i = 0;
QDomElement black = doc.createElement("producer");
black.setAttribute("mlt_service", "colour");
black.setAttribute("colour", "black");
+ //black.setAttribute("id", "black");
black.setAttribute("in", "0");
black.setAttribute("out", "13999");
- while (dur > 14000) { // <producer mlt_service=\"colour\" colour=\"black\" in=\"0\" out=\"13999\" />
+ while (dur > 14000) {
mltInsertClip(0, GenTime(i * 14000, m_fps), black);
dur = dur - 14000;
i++;
}
- black.setAttribute("out", QString::number(dur));
- mltInsertClip(0, GenTime(), black);
-
- m_mltProducer->set("out", duration);
+ if (dur > 0) {
+ black.setAttribute("out", QString::number(dur));
+ mltInsertClip(0, GenTime(i * 14000, m_fps), black);
+ }
+ //m_mltProducer->set("out", duration);
emit durationChanged((int)duration);
}
}
kDebug() << "PLAYLIST BROKEN, CANNOT INSERT CLIP //////";
return;
}
+
Mlt::Service service(parentProd.get_service());
Mlt::Tractor tractor(service);
-
+ mlt_service_lock(service.get_service());
Mlt::Producer trackProducer(tractor.track(track));
Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
Mlt::Producer clip(*m_mltProfile, "westley-xml", tmp);
//clip.set_in_and_out(in.frames(m_fps), out.frames(m_fps));
delete[] tmp;
-
trackPlaylist.insert_at((int) position.frames(m_fps), clip, 1);
+ mlt_service_unlock(service.get_service());
if (track != 0) mltCheckLength();
- tractor.multitrack()->refresh();
- tractor.refresh();
+ //tractor.multitrack()->refresh();
+ //tractor.refresh();
}
void Render::mltCutClip(int track, GenTime position) {
if (!filter) {
kDebug() << "WARINIG, FILTER FOR EDITING NOT FOUND, ADDING IT!!!!!";
- // filter was not found, it was probably a disabled filter, so add it to the correct place...
- int ct = 0;
- filter = clipService.filter(ct);
- QList <Mlt::Filter *> filtersList;
- while (filter) {
- if (QString(filter->get("kdenlive_ix")).toInt() > index.toInt()) {
- filtersList.append(filter);
- clipService.detach(*filter);
- } else ct++;
- filter = clipService.filter(ct);
- }
+ // filter was not found, it was probably a disabled filter, so add it to the correct place...
+ int ct = 0;
+ filter = clipService.filter(ct);
+ QList <Mlt::Filter *> filtersList;
+ while (filter) {
+ if (QString(filter->get("kdenlive_ix")).toInt() > index.toInt()) {
+ filtersList.append(filter);
+ clipService.detach(*filter);
+ } else ct++;
+ filter = clipService.filter(ct);
+ }
mltAddEffect(track, position, args);
- for (int i = 0; i < filtersList.count(); i++) {
- clipService.attach(*(filtersList.at(i)));
- }
+ for (int i = 0; i < filtersList.count(); i++) {
+ clipService.attach(*(filtersList.at(i)));
+ }
m_isBlocked = false;
return;
void Render::mltMoveEffect(int track, GenTime position, int oldPos, int newPos) {
- kDebug() << "MOVING EFFECT FROM " << oldPos<< ", TO: " << newPos;
+ kDebug() << "MOVING EFFECT FROM " << oldPos << ", TO: " << newPos;
Mlt::Service service(m_mltProducer->parent().get_service());
Mlt::Tractor tractor(service);
Mlt::Filter *filter = clipService.filter(ct);
bool found = false;
if (newPos > oldPos) {
- while (filter) {
- if (!found && QString(filter->get("kdenlive_ix")).toInt() == oldPos) {
- filter->set("kdenlive_ix", newPos);
- filtersList.append(filter);
- clipService.detach(*filter);
- filter = clipService.filter(ct);
- while (filter && QString(filter->get("kdenlive_ix")).toInt() <= newPos) {
- filter->set("kdenlive_ix", QString(filter->get("kdenlive_ix")).toInt() - 1);
- ct++;
- filter = clipService.filter(ct);
- }
- found = true;
- }
- if (filter && QString(filter->get("kdenlive_ix")).toInt() > newPos) {
- filtersList.append(filter);
- clipService.detach(*filter);
- } else ct++;
- filter = clipService.filter(ct);
- }
- }
- else {
- while (filter) {
- if (QString(filter->get("kdenlive_ix")).toInt() == oldPos) {
- filter->set("kdenlive_ix", newPos);
- filtersList.append(filter);
- clipService.detach(*filter);
- } else ct++;
- filter = clipService.filter(ct);
- }
-
- ct = 0;
- filter = clipService.filter(ct);
- while (filter) {
- int pos = QString(filter->get("kdenlive_ix")).toInt();
- if (pos >= newPos) {
- if (pos < oldPos) filter->set("kdenlive_ix", QString(filter->get("kdenlive_ix")).toInt() + 1);
- filtersList.append(filter);
- clipService.detach(*filter);
- } else ct++;
- filter = clipService.filter(ct);
- }
+ while (filter) {
+ if (!found && QString(filter->get("kdenlive_ix")).toInt() == oldPos) {
+ filter->set("kdenlive_ix", newPos);
+ filtersList.append(filter);
+ clipService.detach(*filter);
+ filter = clipService.filter(ct);
+ while (filter && QString(filter->get("kdenlive_ix")).toInt() <= newPos) {
+ filter->set("kdenlive_ix", QString(filter->get("kdenlive_ix")).toInt() - 1);
+ ct++;
+ filter = clipService.filter(ct);
+ }
+ found = true;
+ }
+ if (filter && QString(filter->get("kdenlive_ix")).toInt() > newPos) {
+ filtersList.append(filter);
+ clipService.detach(*filter);
+ } else ct++;
+ filter = clipService.filter(ct);
+ }
+ } else {
+ while (filter) {
+ if (QString(filter->get("kdenlive_ix")).toInt() == oldPos) {
+ filter->set("kdenlive_ix", newPos);
+ filtersList.append(filter);
+ clipService.detach(*filter);
+ } else ct++;
+ filter = clipService.filter(ct);
+ }
+
+ ct = 0;
+ filter = clipService.filter(ct);
+ while (filter) {
+ int pos = QString(filter->get("kdenlive_ix")).toInt();
+ if (pos >= newPos) {
+ if (pos < oldPos) filter->set("kdenlive_ix", QString(filter->get("kdenlive_ix")).toInt() + 1);
+ filtersList.append(filter);
+ clipService.detach(*filter);
+ } else ct++;
+ filter = clipService.filter(ct);
+ }
}
-
+
for (int i = 0; i < filtersList.count(); i++) {
- clipService.attach(*(filtersList.at(i)));
+ clipService.attach(*(filtersList.at(i)));
}
m_isBlocked = false;
Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
int clipIndex = trackPlaylist.get_clip_index_at(moveStart + 1);
- Mlt::Producer clipProducer(trackPlaylist.replace_with_blank(clipIndex));
- trackPlaylist.consolidate_blanks(0);
- //mlt_events_block( MLT_PRODUCER_PROPERTIES(clipProducer.get_producer()), NULL );
-
if (endTrack == startTrack) {
+ mlt_service_lock(service.get_service());
+ Mlt::Producer clipProducer(trackPlaylist.replace_with_blank(clipIndex));
+ trackPlaylist.consolidate_blanks(0);
if (!trackPlaylist.is_blank_at(moveEnd)) {
kWarning() << "// ERROR, CLIP COLLISION----------";
int ix = trackPlaylist.get_clip_index_at(moveEnd);
}
trackPlaylist.insert_at(moveEnd, clipProducer, 1);
trackPlaylist.consolidate_blanks(0);
+ mlt_service_unlock(service.get_service());
} else {
+ Mlt::Producer clipProducer(trackPlaylist.replace_with_blank(clipIndex));
trackPlaylist.consolidate_blanks(0);
+
Mlt::Producer destTrackProducer(tractor.track(endTrack));
Mlt::Playlist destTrackPlaylist((mlt_playlist) destTrackProducer.get_service());
destTrackPlaylist.consolidate_blanks(1);
destTrackPlaylist.insert_at(moveEnd, clipProducer, 1);
destTrackPlaylist.consolidate_blanks(0);
}
-
mltCheckLength();
m_isBlocked = false;
m_mltConsumer->set("refresh", 1);
- //mlt_events_unblock( MLT_PRODUCER_PROPERTIES(clipProducer.get_producer()), NULL );
}
-void Render::mltMoveTransition(QString type, int startTrack, int trackOffset, GenTime oldIn, GenTime oldOut, GenTime newIn, GenTime newOut) {
- m_isBlocked = true;
+void Render::mltMoveTransition(QString type, int startTrack, int newTrack, int newTransitionTrack, GenTime oldIn, GenTime oldOut, GenTime newIn, GenTime newOut) {
+
Mlt::Service service(m_mltProducer->parent().get_service());
Mlt::Tractor tractor(service);
Mlt::Field *field = tractor.field();
+ mlt_service_lock(service.get_service());
m_mltConsumer->set("refresh", 0);
- mlt_service serv = m_mltProducer->parent().get_service();
+ m_isBlocked = true;
+ mlt_service serv = m_mltProducer->parent().get_service();
mlt_service nextservice = mlt_service_get_producer(serv);
mlt_properties properties = MLT_SERVICE_PROPERTIES(nextservice);
QString mlt_type = mlt_properties_get(properties, "mlt_type");
int old_pos = (int)(oldIn.frames(m_fps) + oldOut.frames(m_fps)) / 2;
int new_in = (int)newIn.frames(m_fps);
- int new_out = (int)newOut.frames(m_fps) - 1;
+ int new_out = (int)newOut.frames(m_fps);
while (mlt_type == "transition") {
mlt_transition tr = (mlt_transition) nextservice;
if (resource == type && startTrack == currentTrack && currentIn <= old_pos && currentOut >= old_pos) {
mlt_transition_set_in_and_out(tr, new_in, new_out);
- if (trackOffset != 0) {
+ if (newTrack - startTrack != 0) {
+ kDebug() << "///// TRANSITION CHANGE TRACK. CUrrent (b): " << currentTrack << "x" << mlt_transition_get_a_track(tr) << ", NEw: " << newTrack << "x" << newTransitionTrack;
+
mlt_properties properties = MLT_TRANSITION_PROPERTIES(tr);
- mlt_properties_set_int(properties, "a_track", mlt_transition_get_a_track(tr) + trackOffset);
- mlt_properties_set_int(properties, "b_track", mlt_transition_get_b_track(tr) + trackOffset);
+ mlt_properties_set_int(properties, "a_track", newTransitionTrack);
+ mlt_properties_set_int(properties, "b_track", newTrack);
//kDebug() << "set new start & end :" << new_in << new_out<< "TR OFFSET: "<<trackOffset<<", TRACKS: "<<mlt_transition_get_a_track(tr)<<"x"<<mlt_transition_get_b_track(tr);
}
-
break;
}
nextservice = mlt_service_producer(nextservice);
+ if (nextservice == NULL) break;
properties = MLT_SERVICE_PROPERTIES(nextservice);
mlt_type = mlt_properties_get(properties, "mlt_type");
resource = mlt_properties_get(properties, "mlt_service");
}
m_isBlocked = false;
+ mlt_service_unlock(service.get_service());
m_mltConsumer->set("refresh", 1);
}
int currentIn = (int) mlt_transition_get_in(tr);
int currentOut = (int) mlt_transition_get_out(tr);
+ // kDebug()<<"Looking for transition : " << currentIn <<"x"<<currentOut<< ", OLD oNE: "<<in_pos<<"x"<<out_pos;
+
if (resource == type && b_track == currentTrack && currentIn == in_pos && currentOut == out_pos) {
QMap<QString, QString> map = mltGetTransitionParamsFromXml(xml);
QMap<QString, QString>::Iterator it;
break;
}
nextservice = mlt_service_producer(nextservice);
+ if (nextservice == NULL) break;
properties = MLT_SERVICE_PROPERTIES(nextservice);
mlt_type = mlt_properties_get(properties, "mlt_type");
resource = mlt_properties_get(properties, "mlt_service");
break;
}
nextservice = mlt_service_producer(nextservice);
+ if (nextservice == NULL) break;
properties = MLT_SERVICE_PROPERTIES(nextservice);
mlt_type = mlt_properties_get(properties, "mlt_type");
resource = mlt_properties_get(properties, "mlt_service");