#include <stdlib.h>
+
+
+static void kdenlive_callback(void* /*ptr*/, int level, const char* fmt, va_list vl)
+{
+ if (level > MLT_LOG_ERROR) return;
+ QString error;
+ QApplication::postEvent(qApp->activeWindow() , new MltErrorEvent(error.vsprintf(fmt, vl).simplified()));
+}
+
+
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?
// FIXME: the event object returned by the listen gets leaked...
m_mltConsumer->listen("consumer-frame-show", this, (mlt_listener) consumer_frame_show);
m_mltConsumer->set("rescale", "nearest");
+ mlt_log_set_callback(kdenlive_callback);
QString audioDevice = KdenliveSettings::audiodevicename();
if (!audioDevice.isEmpty()) {
}
QString audioDriver = KdenliveSettings::audiodrivername();
+
+ /*
+ // Disabled because the "auto" detected driver was sometimes wrong
if (audioDriver.isEmpty())
audioDriver = KdenliveSettings::autoaudiodrivername();
+ */
+
if (!audioDriver.isEmpty()) {
tmp = decodedString(audioDriver);
m_mltConsumer->set("audio_driver", tmp);
{
if (!m_mltProducer)
return;
- m_isBlocked = 0;
+ m_isBlocked = false;
m_mltProducer->seek((int)(time.frames(m_fps)));
refresh();
}
else
filePropertyMap["type"] = "video";
- mlt_image_format format = mlt_image_yuv422;
- int frame_width = 0;
- int frame_height = 0;
- //frame->set("rescale.interp", "hyper");
- frame->set("normalised_height", height);
- frame->set("normalised_width", width);
+ mlt_image_format format = mlt_image_rgb24a;
+ int frame_width = width;
+ int frame_height = height;
QPixmap pix(width, height);
-
uint8_t *data = frame->get_image(format, frame_width, frame_height, 0);
- uint8_t *new_image = (uint8_t *)mlt_pool_alloc(frame_width * (frame_height + 1) * 4);
- mlt_convert_yuv422_to_rgb24a((uint8_t *)data, new_image, frame_width * frame_height);
- QImage image((uchar *)new_image, frame_width, frame_height, QImage::Format_ARGB32);
+ QImage image((uchar *)data, frame_width, frame_height, QImage::Format_ARGB32);
if (!image.isNull()) {
pix = QPixmap::fromImage(image.rgbSwapped());
} else
pix.fill(Qt::black);
- mlt_pool_release(new_image);
emit replyGetImage(clipId, pix);
} else if (frame->get_int("test_audio") == 0) {
/** Create the producer from the MLT XML QDomDocument */
-void Render::setProducer(Mlt::Producer *producer, int position)
+int Render::setProducer(Mlt::Producer *producer, int position)
{
- if (m_winid == -1) return;
+ if (m_winid == -1) return -1;
if (m_mltConsumer) {
m_mltConsumer->stop();
- } else return;
+ } else return -1;
m_mltConsumer->purge();
if (!m_mltProducer || !m_mltProducer->is_valid()) kDebug() << " WARNING - - - - -INVALID PLAYLIST: ";
m_fps = m_mltProducer->get_fps();
- connectPlaylist();
+ int error = connectPlaylist();
if (position != -1) {
m_mltProducer->seek(position);
emit rendererPosition(position);
}
m_isBlocked = false;
+ return error;
}
/** Create the producer from the MLT XML QDomDocument */
-void Render::setSceneList(QDomDocument list, int position)
+int Render::setSceneList(QDomDocument list, int position)
{
- setSceneList(list.toString(), position);
+ return setSceneList(list.toString(), position);
}
/** Create the producer from the MLT XML QDomDocument */
-void Render::setSceneList(QString playlist, int position)
+int Render::setSceneList(QString playlist, int position)
{
- if (m_winid == -1) return;
+ if (m_winid == -1) return -1;
m_isBlocked = true;
+ int error;
qDeleteAll(m_slowmotionProducers.values());
m_slowmotionProducers.clear();
if (m_mltConsumer == NULL) {
kWarning() << "/////// ERROR, TRYING TO USE NULL MLT CONSUMER";
m_isBlocked = false;
- return;
+ return -1;
}
if (!m_mltConsumer->is_stopped()) {
}
kDebug() << "// NEW SCENE LIST DURATION SET TO: " << m_mltProducer->get_playtime();
- connectPlaylist();
+ error = connectPlaylist();
fillSlowMotionProducers();
m_isBlocked = false;
blockSignals(false);
emit refreshDocumentProducers();
+ return error;
//kDebug()<<"// SETSCN LST, POS: "<<position;
//if (position != 0) emit rendererPosition(position);
}
return m_fps;
}
-void Render::connectPlaylist()
+int Render::connectPlaylist()
{
- if (!m_mltConsumer) return;
+ if (!m_mltConsumer) return -1;
//m_mltConsumer->set("refresh", "0");
m_mltConsumer->connect(*m_mltProducer);
m_mltProducer->set_speed(0);
- m_mltConsumer->start();
+ if (m_mltConsumer->start() == -1) {
+ // ARGH CONSUMER BROKEN!!!!
+ KMessageBox::error(qApp->activeWindow(), i18n("Could not create the video preview window.\nThere is something wrong with your Kdenlive install or your driver settings, please fix it."));
+ emit blockMonitors();
+ delete m_mltProducer;
+ m_mltProducer = NULL;
+ return -1;
+ }
emit durationChanged(m_mltProducer->get_playtime());
+ return 0;
//refresh();
- /*
- if (m_mltConsumer->start() == -1) {
- KMessageBox::error(qApp->activeWindow(), i18n("Could not create the video preview window.\nThere is something wrong with your Kdenlive install or your driver settings, please fix it."));
- delete m_mltConsumer;
- m_mltConsumer = NULL;
- }
- else {
- refresh();
- }*/
}
void Render::refreshDisplay()
kDebug() << "----- BROKEN MONITOR: " << m_name << ", RESTART";
return;
}
-
if (m_mltConsumer && m_mltConsumer->is_stopped()) {
kDebug() << "----- MONITOR: " << m_name << " WAS STOPPED";
if (m_mltConsumer->start() == -1) {
KMessageBox::error(qApp->activeWindow(), i18n("Could not create the video preview window.\nThere is something wrong with your Kdenlive install or your driver settings, please fix it."));
- delete m_mltConsumer;
- m_mltConsumer = NULL;
- return;
+ emit blockMonitors();
+ delete m_mltProducer;
+ m_mltProducer = NULL;
} else {
kDebug() << "----- MONITOR: " << m_name << " REFRESH";
m_isBlocked = false;
void Render::stop()
{
+ if (m_mltProducer == NULL) return;
if (m_mltConsumer && !m_mltConsumer->is_stopped()) {
kDebug() << "///////////// RENDER STOPPED: " << m_name;
m_isBlocked = true;
refresh();
}
+void Render::seekToFrameDiff(int diff)
+{
+ //kDebug()<<" ********* RENDER SEEK TO POS";
+ if (!m_mltProducer)
+ return;
+ m_isBlocked = false;
+ resetZoneMode();
+ m_mltProducer->seek(m_mltProducer->position() + diff);
+ refresh();
+}
+
void Render::askForRefresh()
{
// Use a Timer so that we don't refresh too much
if (show == false) dropFrames = 0;
m_mltConsumer->stop();
m_mltConsumer->set("play.real_time", dropFrames);
- m_mltConsumer->start();
+ if (m_mltConsumer->start() == -1) {
+ emit blockMonitors();
+ delete m_mltProducer;
+ m_mltProducer = NULL;
+ }
+
}
}
else return GenTime();
}
+int Render::seekFramePosition() const
+{
+ if (m_mltProducer) return (int) m_mltProducer->position();
+ return 0;
+}
const QString & Render::rendererName() const
{
Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
int clipIndex = trackPlaylist.get_clip_index_at((int) position.frames(m_fps));
- /* // Display playlist info
- kDebug()<<"//// BEFORE";
- for (int i = 0; i < trackPlaylist.count(); i++) {
+ // Display playlist info
+ //kDebug() << "//// BEFORE -( " << position.frames(m_fps) << " )-------------------------------";
+ /*for (int i = 0; i < trackPlaylist.count(); i++) {
int blankStart = trackPlaylist.clip_start(i);
int blankDuration = trackPlaylist.clip_length(i) - 1;
QString blk;
}*/
if (trackPlaylist.is_blank(clipIndex)) {
kDebug() << "// WARNING, TRYING TO REMOVE A BLANK: " << position.frames(25);
+ mlt_service_unlock(service.get_service());
return false;
}
+ //kDebug()<<"//// Deleting at: "<< (int) position.frames(m_fps) <<" --------------------------------------";
m_isBlocked = true;
trackPlaylist.replace_with_blank(clipIndex);
trackPlaylist.consolidate_blanks(0);
m_mltConsumer->set("refresh", 1);
}
+
+void Render::mltPasteEffects(Mlt::Producer *source, Mlt::Producer *dest)
+{
+ Mlt::Service sourceService(source->get_service());
+ Mlt::Service destService(dest->get_service());
+
+ // move all effects to the correct producer
+ int ct = 0;
+ Mlt::Filter *filter = sourceService.filter(ct);
+ while (filter) {
+ if (filter->get("kdenlive_ix") != 0) {
+ sourceService.detach(*filter);
+ destService.attach(*filter);
+ } else ct++;
+ filter = sourceService.filter(ct);
+ }
+}
+
int Render::mltChangeClipSpeed(ItemInfo info, double speed, double oldspeed, Mlt::Producer *prod)
{
m_isBlocked = true;
delete clip;
return -1;
}
- delete clip;
+
QString serv = clipparent.get("mlt_service");
QString id = clipparent.get("id");
//kDebug() << "CLIP SERVICE: " << serv;
GenTime maxLength = GenTime(blankEnd, m_fps) - info.startPos;
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.frames(m_fps) + clipLength) / speed - 1));
+
+ // move all effects to the correct producer
+ mltPasteEffects(clip, cut);
+
trackPlaylist.insert_at(startPos, *cut, 1);
clipIndex = trackPlaylist.get_clip_index_at(startPos);
newLength = trackPlaylist.clip_length(clipIndex);
GenTime maxLength = GenTime(blankEnd, m_fps) - info.startPos;
cut = prod->cut((int)(info.cropStart.frames(m_fps)), (int)(info.cropStart.frames(m_fps) + maxLength.frames(m_fps) - 1));
} else cut = prod->cut((int)(info.cropStart.frames(m_fps)), (int)((info.cropStart + newDuration).frames(m_fps)) - 1);
+
+ // move all effects to the correct producer
+ mltPasteEffects(clip, cut);
+
trackPlaylist.insert_at(startPos, *cut, 1);
clipIndex = trackPlaylist.get_clip_index_at(startPos);
newLength = trackPlaylist.clip_length(clipIndex);
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));
+ // move all effects to the correct producer
+ mltPasteEffects(clip, cut);
+
trackPlaylist.insert_at(startPos, *cut, 1);
clipIndex = trackPlaylist.get_clip_index_at(startPos);
newLength = trackPlaylist.clip_length(clipIndex);
mlt_service_unlock(service.get_service());
}
+
+ delete clip;
if (clipIndex + 1 == trackPlaylist.count()) mltCheckLength();
m_isBlocked = false;
return newLength;
return success;
}
- // create filter
+ // find filter
Mlt::Service service(m_mltProducer->parent().get_service());
Mlt::Tractor tractor(service);
m_isBlocked = false;
return success;
}
-
+ mlt_service_lock(service.get_service());
for (int j = 0; j < params.count(); j++) {
char *name = decodedString(params.at(j).name());
char *value = decodedString(params.at(j).value());
delete[] name;
delete[] value;
}
+ mlt_service_unlock(service.get_service());
m_isBlocked = false;
refresh();
Mlt::Producer *clip = prod->cut(clipProducer.get_in(), clipProducer.get_out());
// move all effects to the correct producer
- Mlt::Service clipService(clipProducer.get_service());
- Mlt::Service newClipService(clip->get_service());
-
- int ct = 0;
- Mlt::Filter *filter = clipService.filter(ct);
- while (filter) {
- if (filter->get("kdenlive_ix") != 0) {
- clipService.detach(*filter);
- newClipService.attach(*filter);
- } else ct++;
- filter = clipService.filter(ct);
- }
+ mltPasteEffects(&clipProducer, clip);
trackPlaylist.insert_at(pos, clip, 1);
mlt_service_unlock(m_mltConsumer->get_service());
}
// move all effects to the correct producer
- Mlt::Service clipService(clipProducer.get_service());
- Mlt::Service newClipService(clip->get_service());
-
- int ct = 0;
- Mlt::Filter *filter = clipService.filter(ct);
- while (filter) {
- if (filter->get("kdenlive_ix") != 0) {
- clipService.detach(*filter);
- newClipService.attach(*filter);
- } else ct++;
- filter = clipService.filter(ct);
- }
+ mltPasteEffects(&clipProducer, clip);
int newIndex = destTrackPlaylist.insert_at(moveEnd, clip, 1);
destTrackPlaylist.consolidate_blanks(0);
}
mlt_service_unlock(serv);
m_isBlocked--;
- //askForRefresh();
+ refresh();
//if (m_isBlocked == 0) m_mltConsumer->set("refresh", 1);
return true;
}
if (oldTag == tag) mltUpdateTransitionParams(tag, a_track, b_track, in, out, xml);
else {
mltDeleteTransition(oldTag, a_track, b_track, in, out, xml, false);
- mltAddTransition(tag, a_track, b_track, in, out, xml);
+ mltAddTransition(tag, a_track, b_track, in, out, xml, false);
}
+ refresh();
//mltSavePlaylist();
}
mlt_service_lock(serv);
m_isBlocked++;
-
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 key;
mlt_properties transproperties = MLT_TRANSITION_PROPERTIES(tr);
mlt_properties_set_int(transproperties, "force_track", xml.attribute("force_track").toInt());
+ // update the transition id in case it uses the same MLT service but different Kdenlive id
+ char *tmp = decodedString(xml.attribute("id"));
+ mlt_properties_set(transproperties, "kdenlive_id", tmp);
+ delete[] tmp;
if (currentBTrack != a_track) {
mlt_properties_set_int(properties, "a_track", a_track);
}
}
-bool Render::mltAddTransition(QString tag, int a_track, int b_track, GenTime in, GenTime out, QDomElement xml, bool /*do_refresh*/)
+bool Render::mltAddTransition(QString tag, int a_track, int b_track, GenTime in, GenTime out, QDomElement xml, bool do_refresh)
{
if (in >= out) return false;
QMap<QString, QString> args = mltGetTransitionParamsFromXml(xml);
// attach filter to the clip
field->plant_transition(*transition, a_track, b_track);
delete[] transId;
- refresh();
+ if (do_refresh) refresh();
return true;
}
QList <Mlt::Producer *> Render::producersList()
{
QList <Mlt::Producer *> prods;
+ if (m_mltProducer == NULL) return prods;
Mlt::Service service(m_mltProducer->parent().get_service());
if (service.type() != tractor_type) return prods;
Mlt::Tractor tractor(service);
void Render::fillSlowMotionProducers()
{
+ if (m_mltProducer == NULL) return;
Mlt::Service service(m_mltProducer->parent().get_service());
if (service.type() != tractor_type) return;