// ffmpeg Header files
extern "C" {
-#include <libavformat/avformat.h>
+//#include <libavformat/avformat.h>
}
#include <QTimer>
#include <QDir>
#include "renderer.h"
#include "kdenlivesettings.h"
+#include "kthumb.h"
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 ?
}
//static
-QPixmap Render::frameThumbnail(Mlt::Frame *frame, int width, int height, bool border) {
+/*QPixmap Render::frameThumbnail(Mlt::Frame *frame, int width, int height, bool border) {
QPixmap pix(width, height);
mlt_image_format format = mlt_image_rgb24a;
} else pix.fill(Qt::black);
return pix;
}
-
+*/
QPixmap Render::extractFrame(int frame_position, int width, int height) {
QPixmap pix(width, height);
pix.fill(Qt::black);
return pix;
}
- Mlt::Producer *mlt_producer = m_mltProducer->cut(frame_position, frame_position + 1);
- Mlt::Filter m_convert(*m_mltProfile, "avcolour_space");
+ //Mlt::Producer *mlt_producer = m_mltProducer->cut(frame_position, frame_position + 1);
+ return KThumb::getFrame(m_mltProducer, frame_position, width, height);
+ /*Mlt::Filter m_convert(*m_mltProfile, "avcolour_space");
m_convert.set("forced", mlt_image_rgb24a);
mlt_producer->attach(m_convert);
Mlt::Frame *frame = mlt_producer->get_frame();
delete frame;
} else pix.fill(Qt::black);
delete mlt_producer;
- return pix;
+ return pix;*/
}
QPixmap Render::getImageThumbnail(KUrl url, int width, int height) {
//pixmap = im.scaled(width, height);
return pixmap;
}
-
+/*
//static
QPixmap Render::getVideoThumbnail(char *profile, QString file, int frame_position, int width, int height) {
QPixmap pix(width, height);
if (prof) delete prof;
return pix;
}
-
+*/
/*
void Render::getImage(KUrl url, int frame_position, QPoint size)
{
filePropertyMap["type"] = "video";
// Generate thumbnail for this frame
- QPixmap pixmap = frameThumbnail(frame, width, height, true);
+ QPixmap pixmap = KThumb::getImage(url, 0, width, height);
emit replyGetImage(clipId, 0, pixmap, width, height);
}
/** Create the producer from the Westley QDomDocument */
+#if 0
void Render::initSceneList() {
kDebug() << "-------- INIT SCENE LIST ------_";
QDomDocument doc;
QString tmp = QString("<westley><producer resource=\"colour\" colour=\"red\" id=\"red\" /><tractor><multitrack><playlist></playlist><playlist></playlist><playlist /><playlist /><playlist></playlist></multitrack></tractor></westley>");*/
setSceneList(doc, 0);
}
-
+#endif
/** Create the producer from the Westley QDomDocument */
void Render::setSceneList(QDomDocument list, int position) {
setSceneList(list.toString(), position);
if (m_mltProducer) {
m_mltProducer->set_speed(0.0);
m_mltProducer->set("out", m_mltProducer->get_length() - 1);
+ kDebug() << m_mltProducer->get_length();
}
kDebug() << "///////////// RENDER STOP3-------";
}
void Render::play(double speed, const GenTime & startTime,
const GenTime & stopTime) {
- kDebug() << "///////////// RENDER PLAY3-------" << speed;
+ kDebug() << "///////////// RENDER PLAY3-------" << speed << stopTime.frames(m_fps);
if (!m_mltProducer)
return;
m_mltProducer->set("out", stopTime.frames(m_fps));
int height = 1080;//KdenliveSettings::defaultheight();
int width = 1940; //KdenliveSettings::displaywidth();
-
- QPixmap pix(width, height);
- Mlt::Filter m_convert(*m_mltProfile, "avcolour_space");
- m_convert.set("forced", mlt_image_rgb24a);
- m_mltProducer->attach(m_convert);
- Mlt::Frame * frame = m_mltProducer->get_frame();
- m_mltProducer->detach(m_convert);
- if (frame) {
- pix = frameThumbnail(frame, width, height);
- delete frame;
- }
+ QPixmap pix = KThumb::getFrame(m_mltProducer, -1, width, height);
+ /*
+ QPixmap pix(width, height);
+ Mlt::Filter m_convert(*m_mltProfile, "avcolour_space");
+ m_convert.set("forced", mlt_image_rgb24a);
+ m_mltProducer->attach(m_convert);
+ Mlt::Frame * frame = m_mltProducer->get_frame();
+ m_mltProducer->detach(m_convert);
+ if (frame) {
+ pix = frameThumbnail(frame, width, height);
+ delete frame;
+ }*/
pix.save(url.path(), "PNG");
//if (notify) QApplication::postEvent(qApp->activeWindow(), new UrlEvent(url, 10003));
}
void Render::mltCheckLength() {
//kDebug()<<"checking track length: "<<track<<"..........";
- Mlt::Service service(m_mltProducer->get_service());
- Mlt::Tractor tractor(service);
+ Mlt::Tractor tractor(getTractor());
int trackNb = tractor.count();
double duration = 0;
Mlt::Producer trackProducer(tractor.track(0));
Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
duration = Mlt::Producer(trackPlaylist.get_producer()).get_playtime() - 1;
+ kDebug() << trackNb << " " << duration;
m_mltProducer->set("out", duration);
emit durationChanged(duration);
return;
}
}
+mlt_tractor Render::getTractor() {
+ Mlt::Service s1(m_mltProducer->get_service());
+ Mlt::Playlist pl(s1);
+
+ Mlt::Producer srv(pl.get_clip(0)->parent());
+ Mlt::Tractor tractor(srv);
+ return tractor.get_tractor();
+
+}
void Render::mltInsertClip(int track, GenTime position, QDomElement element) {
if (!m_mltProducer) {
return;
}
m_isBlocked = true;
- Mlt::Service service(parentProd.get_service());
- Mlt::Tractor tractor(service);
+ // Mlt::Service service(parentProd.get_service());
+ //Mlt::Tractor tractor(service);
QDomDocument doc;
doc.appendChild(doc.importNode(element, true));
QString resource = doc.toString();
+ Mlt::Tractor tractor(getTractor());
+
+
kDebug() << "/////// ADDING CLIP TMLNE: " << resource << " ON TRACK: " << track;
- Mlt::Producer trackProducer(tractor.track(track));
+ Mlt::Producer *ptmp = tractor.track(track);
+ kDebug() << ptmp->get("mlt_type") << ptmp->get("id");
+ Mlt::Producer trackProducer(*ptmp);
Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
char *tmp = decodedString(resource);
Mlt::Producer clip(*m_mltProfile, "westley-xml", tmp);
void Render::mltCutClip(int track, GenTime position) {
m_isBlocked = true;
- Mlt::Service service(m_mltProducer->parent().get_service());
- Mlt::Tractor tractor(service);
+ Mlt::Tractor tractor(getTractor());
Mlt::Producer trackProducer(tractor.track(track));
Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
trackPlaylist.split_at(position.frames(m_fps));
void Render::mltRemoveClip(int track, GenTime position) {
m_isBlocked = true;
- Mlt::Service service(m_mltProducer->parent().get_service());
- Mlt::Tractor tractor(service);
+ Mlt::Tractor tractor(getTractor());
Mlt::Producer trackProducer(tractor.track(track));
Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
int clipIndex = trackPlaylist.get_clip_index_at(position.frames(m_fps));
void Render::mltRemoveEffect(int track, GenTime position, QString index, bool doRefresh) {
- Mlt::Service service(m_mltProducer->parent().get_service());
-
- Mlt::Tractor tractor(service);
+ Mlt::Tractor tractor(getTractor());
Mlt::Producer trackProducer(tractor.track(track));
Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
//int clipIndex = trackPlaylist.get_clip_index_at(position.frames(m_fps));
void Render::mltAddEffect(int track, GenTime position, QMap <QString, QString> args, bool doRefresh) {
- Mlt::Service service(m_mltProducer->parent().get_service());
- Mlt::Tractor tractor(service);
+
+ Mlt::Tractor tractor(getTractor());
Mlt::Producer trackProducer(tractor.track(track));
Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
}
m_isBlocked = true;
// create filter
- Mlt::Service service(m_mltProducer->parent().get_service());
- Mlt::Tractor tractor(service);
+ Mlt::Tractor tractor(getTractor());
Mlt::Producer trackProducer(tractor.track(track));
Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
//int clipIndex = trackPlaylist.get_clip_index_at(position.frames(m_fps));
void Render::mltResizeClipEnd(int track, GenTime pos, GenTime in, GenTime out) {
m_isBlocked = true;
- Mlt::Service service(m_mltProducer->parent().get_service());
- Mlt::Tractor tractor(service);
+ Mlt::Tractor tractor(getTractor());
Mlt::Producer trackProducer(tractor.track(track));
Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
if (trackPlaylist.is_blank_at(pos.frames(m_fps) + 1))
}
void Render::mltChangeTrackState(int track, bool mute, bool blind) {
- Mlt::Service service(m_mltProducer->parent().get_service());
- Mlt::Tractor tractor(service);
+ Mlt::Tractor tractor(getTractor());
Mlt::Producer trackProducer(tractor.track(track));
Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
if (mute) {
void Render::mltResizeClipStart(int track, GenTime pos, GenTime moveEnd, GenTime moveStart, GenTime in, GenTime out) {
m_isBlocked = true;
- Mlt::Service service(m_mltProducer->parent().get_service());
+
int moveFrame = (moveEnd - moveStart).frames(m_fps);
- Mlt::Tractor tractor(service);
+ Mlt::Tractor tractor(getTractor());
Mlt::Producer trackProducer(tractor.track(track));
Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
if (trackPlaylist.is_blank_at(pos.frames(m_fps) - 1))
void Render::mltMoveClip(int startTrack, int endTrack, int moveStart, int moveEnd) {
m_isBlocked = true;
//m_mltConsumer->set("refresh", 0);
- Mlt::Service service(m_mltProducer->parent().get_service());
-
- Mlt::Tractor tractor(service);
+ Mlt::Tractor tractor(getTractor());
Mlt::Producer trackProducer(tractor.track(startTrack));
Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
int clipIndex = trackPlaylist.get_clip_index_at(moveStart + 1);
m_isBlocked = false;
}
-void Render::mltAddTransition(QString tag, int a_track, int b_track, GenTime in, GenTime out, QMap <QString, QString> args) {
+void Render::mltUpdateTransition(QString oldTag, QString tag, int a_track, int b_track, GenTime in, GenTime out, QMap <QString, QString> args) {
+ kDebug() << "update transition" << tag;
+
+ mltDeleteTransition(oldTag, a_track, b_track, in, out, args);
+ mltAddTransition(tag, a_track, b_track, in, out, args);
+ m_isBlocked = false;
+}
+typedef struct {
+ int size;
+ int count;
+ mlt_service *in;
+ mlt_service out;
+ int filter_count;
+ int filter_size;
+ mlt_filter *filters;
+ pthread_mutex_t mutex;
+}
+mlt_service_base;
+
+void Render::mltDeleteTransition(QString tag, int a_track, int b_track, GenTime in, GenTime out, QMap <QString, QString> args) {
+
+ Mlt::Tractor tractor(getTractor());
+ for (int track = 0;track < 10;track++) {
+ Mlt::Producer *trackprod = tractor.track(track);
+ if (!trackprod)
+ continue;
+ Mlt::Producer trackProducer(trackprod);
+ Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
+ Mlt::Producer *prod = NULL;
+ int g = 0;
+ do {
+ prod = trackPlaylist.get_clip(g++);
+ if (prod) {
+
+ for (int j = 0;j < prod->count();j++) {
+
+ kDebug() << prod->get_name(j) << " " << prod->get(j);
+ }
+ Mlt::Producer parprod = prod->parent();
+ for (int j = 0;j < parprod.count();j++) {
+
+ kDebug() << " " << parprod.get_name(j) << " " << parprod.get(j);
+ }
+ Mlt::Tractor tractor(parprod);
+ if (tractor.is_valid()) {
+ kDebug() << "---------ja";
+ }
+ }
+ kDebug() << "track=" << track << " " << g << " " << prod;
+
+ /*Mlt::Tractor parent(prod->parent());
+ if (!parent.get_tractor())
+ continue;
+ Mlt::Producer *prod1=parent.track(1);
+ if (!prod1)
+ continue;*/
+ } while (g < 10);
+ }
+
+#if 0
+ return;
m_isBlocked = true;
+ m_mltConsumer->set("refresh", 0);
+ mlt_service serv = m_mltProducer->parent().get_service();
Mlt::Service service(m_mltProducer->parent().get_service());
Mlt::Tractor tractor(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");
+ QString resource = mlt_properties_get(properties, "mlt_service");
+ int old_pos = (in.frames(m_fps) + out.frames(m_fps)) / 2;
+ int trackOffset = 0;
+ int new_in = in.frames(m_fps);
+ int new_out = out.frames(m_fps) - 1;
+ while (mlt_type == "transition") {
+ mlt_transition tr = (mlt_transition) nextservice;
+ int currentTrack = mlt_transition_get_b_track(tr);
+ int currentIn = (int) mlt_transition_get_in(tr);
+ int currentOut = (int) mlt_transition_get_out(tr);
+ kDebug() << "// FOUND EXISTING TRANS, IN: " << currentIn << ", OUT: " << currentOut << ", TRACK: " << currentTrack;
+ //kDebug()<<"// LOOKING FOR IN: "<<old_in<<", OUT: "<<old_out;
+ kDebug() << "// OLD IN: " << in.frames(m_fps) << " // OLD OUT: " << out.frames(m_fps) << ", TRACK: " << a_track << ", MID POS: " << old_pos;
+ if (/*resource == type &&*/ b_track == currentTrack && currentIn <= old_pos && currentOut >= old_pos) {
+ kDebug() << "found transition that matches" << resource;
+ //mlt_transition_set_in_and_out(tr, new_in, new_out);
+ Mlt::Field *field = tractor.field();
+ Mlt::Transition tt(*m_mltProfile, "mix");
+ field->plant_transition(tt, a_track, b_track);
+#if 0
+ mlt_service service = MLT_TRANSITION_SERVICE(tr);
+ mlt_service_base *base = (mlt_service_base*)service->local;
+ for (int i = 0;i < base->count;i++) {
+ kDebug() << base->in[i] << " " << tr << " " << service << nextservice;
+ }
+ mlt_service service1 = MLT_TRACTOR_SERVICE(tractor.get_tractor());
+ mlt_service_base *base1 = (mlt_service_base*)service1->local;
+ for (int i = 0;i < base1->count;i++) {
+ kDebug() << base1->in[i] << " " << tr << " " << service << nextservice;
+ if (base1->in[i] == (mlt_service_s*)tr) {
+ mlt_service_lock(MLT_SERVICE_PROPERTIES(tr));
+ //mlt_properties_dec_ref( MLT_SERVICE_PROPERTIES( tr ) );
+ /*mlt_service_unlock(MLT_SERVICE_PROPERTIES(tr));
+
+
+ mlt_events_disconnect(properties, nextservice);
+ mlt_transition_close(tr);
+ //base1->in[i]=NULL;
+ base1->out = NULL;*/
+ base1->in[i] = NULL;
+
+ base1->count--;
+ mlt_service_base *basetr = (mlt_service_base*)service1->local;
+ basetr->out = NULL;
+ return;
+ }
+ }
+
+ //service->child=NULL;
+ ///mlt_properties properties = MLT_TRANSITION_PROPERTIES(tr);
+ ///mlt_properties_set ( properties , "active" , 0 );
+ ///7mlt_events_disconnect(properties, nextservice);
+ //mlt_events_fire(MLT_SERVICE_PROPERTIES(nextservice), "service-changed", NULL);
+ //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);
+ //}
+#endif
+ break;
+ }
+ nextservice = mlt_service_producer(nextservice);
+ properties = MLT_SERVICE_PROPERTIES(nextservice);
+ mlt_type = mlt_properties_get(properties, "mlt_type");
+ resource = mlt_properties_get(properties, "mlt_service");
+ }
+ m_isBlocked = false;
+#endif
+}
+
+void Render::mltAddTransition(QString tag, int a_track, int b_track, GenTime in, GenTime out, QMap <QString, QString> args) {
+#if 0
+
+ Mlt::Tractor tractor(getTractor());
+ for (int track = 0;track < 10;track++) {
+ Mlt::Producer *trackprod = tractor.track(track);
+ if (!trackprod)
+ continue;
+ Mlt::Producer trackProducer(trackprod);
+ Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
+
+ int clipindex = trackPlaylist.get_clip_index_at(in.frames(m_fps));
+ if (clipindex != 0 && track == 5) {
+ Mlt::Transition *transition = new Mlt::Transition(*m_mltProfile, decodedString(tag));
+ if (!transition || !transition->get_transition())
+ return;
+ transition->set_in_and_out((int) in.frames(m_fps), (int) out.frames(m_fps));
+ QMap<QString, QString>::Iterator it;
+ QString key;
+
+ kDebug() << " ------ ADDING TRANSITION PARAMs: " << args.count() << "on track " << track;
+
+ for (it = args.begin(); it != args.end(); ++it) {
+ key = it.key();
+ char *name = decodedString(key);
+ char *value = decodedString(it.value());
+ transition->set(name, value);
+ kDebug() << " ------ ADDING TRANS PARAM: " << name << ": " << value;
+ //filter->set("kdenlive_id", id);
+ delete[] name;
+ delete[] value;
+ }
+ Mlt::Producer *left = trackPlaylist.get_clip(clipindex - 1);
+ Mlt::Producer *right = trackPlaylist.get_clip(clipindex);
+ kDebug() << "left=" << left << " right=" << right;
+ Mlt::Tractor mixer;
+ Mlt::Playlist track0;
+ mixer.set_track(track0, 0);
+ /** read from track down */
+ Mlt::Producer *trackprod2 = tractor.track(4);
+ Mlt::Producer trackProducer2(trackprod2);
+ Mlt::Playlist trackPlaylist2((mlt_playlist) trackProducer2.get_service());
+
+ int clipindex2 = trackPlaylist2.get_clip_index_at(in.frames(m_fps));
+ kDebug() << clipindex2;
+ left = trackPlaylist2.get_clip(clipindex2);
+ //left->cut(40,left->get_playtime() );
+ Mlt::Producer *lastleft = left->cut(left->get_in() + left->get_playtime() - 20, left->get_in() + left->get_playtime());
+ mixer.set_track(*lastleft, 0);
+ //track0.repeat(0, 20);
+ mixer.set_track(*right, 1);
+ transition->set_in_and_out(0, 20 - 1);
+ mixer.plant_transition(transition);
+ trackPlaylist.insert(mixer, clipindex, 0, mixer.get_playtime());
+ trackPlaylist.remove(clipindex + 1);
+ }
+ }
+ mltSavePlaylist();
+#else
+ m_isBlocked = true;
+ Mlt::Tractor tractor(getTractor());
Mlt::Field *field = tractor.field();
char *transId = decodedString(tag);
Mlt::Transition *transition = new Mlt::Transition(*m_mltProfile, transId);
+ if (!transition || !transition->get_transition())
+ return;
transition->set_in_and_out((int) in.frames(m_fps), (int) out.frames(m_fps));
QMap<QString, QString>::Iterator it;
QString key;
delete[] transId;
m_isBlocked = false;
refresh();
-
+ mltSavePlaylist();
+#endif
}
void Render::mltSavePlaylist() {
kWarning() << "// UPDATING PLAYLIST TO DISK++++++++++++++++";
Mlt::Consumer *fileConsumer = new Mlt::Consumer(*m_mltProfile, "westley");
- fileConsumer->set("resource", "/home/one/playlist.xml");
+ fileConsumer->set("resource", "/tmp/playlist.westley");
Mlt::Service service(m_mltProducer->get_service());
- Mlt::Tractor tractor(service);
-
fileConsumer->connect(service);
fileConsumer->start();