X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Frenderer.cpp;h=c1caeed109d17cbcb5fbe2147fbb7697a4e57949;hb=0bd6bcac38586a437a5b5e7b51ff7e6459187cf7;hp=c9c23e29c8688d7bd8a3fd76050bd82d7431f1bb;hpb=d0835d9b0cb148d5d87c1e9037ecb8ae15c93f6f;p=kdenlive diff --git a/src/renderer.cpp b/src/renderer.cpp index c9c23e29..c1caeed1 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -107,6 +107,8 @@ Render::Render(const QString & rendererName, int winid, QString profile, QWidget m_mltConsumer(NULL), m_mltProducer(NULL), m_mltProfile(NULL), + m_showFrameEvent(NULL), + m_pauseEvent(NULL), m_externalConsumer(false), m_isZoneMode(false), m_isLoopMode(false), @@ -119,6 +121,9 @@ Render::Render(const QString & rendererName, int winid, QString profile, QWidget m_mltProducer = m_blackClip->cut(0, 1); m_mltConsumer->connect(*m_mltProducer); m_mltProducer->set_speed(0.0); + m_refreshTimer.setSingleShot(true); + m_refreshTimer.setInterval(50); + connect(&m_refreshTimer, SIGNAL(timeout()), this, SLOT(refresh())); } Render::~Render() @@ -133,6 +138,8 @@ void Render::closeMlt() //delete m_osdTimer; m_requestList.clear(); m_infoThread.waitForFinished(); + if (m_showFrameEvent) delete m_showFrameEvent; + if (m_pauseEvent) delete m_pauseEvent; if (m_mltConsumer) delete m_mltConsumer; if (m_mltProducer) delete m_mltProducer; /*if (m_mltProducer) { @@ -187,7 +194,6 @@ void Render::buildConsumer(const QString &profileName) setenv("MLT_PROFILE", tmp, 1); m_mltProfile = new Mlt::Profile(tmp); m_mltProfile->set_explicit(true); - kDebug()<<"// ********* PROFILE AR: "<dar(); delete[] tmp; m_blackClip = new Mlt::Producer(*m_mltProfile, "colour", "black"); @@ -206,7 +212,7 @@ void Render::buildConsumer(const QString &profileName) delete[] tmp; if (m_mltConsumer->is_valid()) { m_externalConsumer = true; - m_mltConsumer->listen("consumer-frame-show", this, (mlt_listener) consumer_frame_show); + m_showFrameEvent = m_mltConsumer->listen("consumer-frame-show", this, (mlt_listener) consumer_frame_show); m_mltConsumer->set("terminate_on_pause", 0); m_mltConsumer->set("deinterlace_method", "onefield"); m_mltConsumer->set("real_time", KdenliveSettings::mltthreads()); @@ -234,12 +240,11 @@ void Render::buildConsumer(const QString &profileName) m_mltConsumer = new Mlt::Consumer(*m_mltProfile, "sdl_audio"); m_mltConsumer->set("preview_off", 1); m_mltConsumer->set("preview_format", mlt_image_rgb24a); - m_mltConsumer->listen("consumer-frame-show", this, (mlt_listener) consumer_gl_frame_show); + m_showFrameEvent = m_mltConsumer->listen("consumer-frame-show", this, (mlt_listener) consumer_gl_frame_show); } else { m_mltConsumer = new Mlt::Consumer(*m_mltProfile, "sdl_preview"); - // FIXME: the event object returned by the listen gets leaked... - m_mltConsumer->listen("consumer-frame-show", this, (mlt_listener) consumer_frame_show); - m_mltConsumer->listen("consumer-sdl-paused", this, (mlt_listener) consumer_paused); + m_showFrameEvent = m_mltConsumer->listen("consumer-frame-show", this, (mlt_listener) consumer_frame_show); + m_pauseEvent = m_mltConsumer->listen("consumer-sdl-paused", this, (mlt_listener) consumer_paused); m_mltConsumer->set("window_id", m_winid); } m_mltConsumer->set("resize", 1); @@ -289,10 +294,14 @@ Mlt::Producer *Render::invalidProducer(const QString &id) return clip; } +bool Render::hasProfile(const QString &profileName) const +{ + return m_activeProfile == profileName; +} + int Render::resetProfile(const QString &profileName, bool dropSceneList) { - QString scene; - if (!dropSceneList) scene = sceneList(); + m_refreshTimer.stop(); if (m_mltConsumer) { if (m_externalConsumer == KdenliveSettings::external_display()) { if (KdenliveSettings::external_display() && m_activeProfile == profileName) return 1; @@ -310,9 +319,15 @@ int Render::resetProfile(const QString &profileName, bool dropSceneList) if (m_isSplitView) slotSplitView(false); if (!m_mltConsumer->is_stopped()) m_mltConsumer->stop(); m_mltConsumer->purge(); + if (m_showFrameEvent) delete m_showFrameEvent; + m_showFrameEvent = NULL; + if (m_pauseEvent) delete m_pauseEvent; + m_pauseEvent = NULL; delete m_mltConsumer; m_mltConsumer = NULL; } + QString scene; + if (!dropSceneList) scene = sceneList(); int pos = 0; double current_fps = m_mltProfile->fps(); double current_dar = m_mltProfile->dar(); @@ -749,20 +764,30 @@ void Render::processFileProperties() if (info.xml.hasAttribute("templatetext")) producer->set("templatetext", info.xml.attribute("templatetext").toUtf8().constData()); + + int imageWidth = (int)((double) info.imageHeight * m_mltProfile->width() / m_mltProfile->height() + 0.5); + int fullWidth = (int)((double) info.imageHeight * m_mltProfile->dar() + 0.5); + int frameNumber = info.xml.attribute("thumbnail", "-1").toInt(); if ((!info.replaceProducer && info.xml.hasAttribute("file_hash")) || proxyProducer) { // Clip already has all properties - emit replyGetFileProperties(info.clipId, producer, stringMap(), stringMap(), info.replaceProducer, true); + if (proxyProducer) { + // Recreate clip thumb + if (frameNumber > 0) producer->seek(frameNumber); + Mlt::Frame *frame = producer->get_frame(); + if (frame && frame->is_valid()) { + QImage img = KThumb::getFrame(frame, imageWidth, fullWidth, info.imageHeight); + delete frame; + emit replyGetImage(info.clipId, img); + } + } + emit replyGetFileProperties(info.clipId, producer, stringMap(), stringMap(), info.replaceProducer); m_processingClipId.clear(); continue; } - int imageWidth = (int)((double) info.imageHeight * m_mltProfile->width() / m_mltProfile->height() + 0.5); - int fullWidth = (int)((double) info.imageHeight * m_mltProfile->dar() + 0.5); stringMap filePropertyMap; stringMap metadataPropertyMap; - - int frameNumber = info.xml.attribute("thumbnail", "-1").toInt(); if (frameNumber > 0) producer->seek(frameNumber); duration = duration > 0 ? duration : producer->get_playtime(); @@ -973,29 +998,26 @@ void Render::initSceneList() int Render::setProducer(Mlt::Producer *producer, int position) { + m_refreshTimer.stop(); QMutexLocker locker(&m_mutex); QString currentId; int consumerPosition = 0; - if (m_winid == -1) return -1; - if (m_mltConsumer) { - consumerPosition = m_mltConsumer->position(); - if (!m_mltConsumer->is_stopped()) { - m_mltConsumer->stop(); - m_mltConsumer->purge(); - } - m_mltConsumer->set("refresh", 0); - } - else { - return -1; + if (m_winid == -1 || !m_mltConsumer) return -1; + m_mltConsumer->set("refresh", 0); + if (!m_mltConsumer->is_stopped()) { + m_mltConsumer->stop(); } + m_mltConsumer->purge(); + consumerPosition = m_mltConsumer->position(); if (m_mltProducer) { - currentId = m_mltProducer->get("id"); m_mltProducer->set_speed(0); + currentId = m_mltProducer->get("id"); delete m_mltProducer; m_mltProducer = NULL; emit stopped(); } + blockSignals(true); if (producer && producer->is_valid()) { m_mltProducer = producer; @@ -1011,13 +1033,30 @@ int Render::setProducer(Mlt::Producer *producer, int position) m_mltProducer->set("meta.volume", (double)volume / 100); m_fps = m_mltProducer->get_fps(); blockSignals(false); - int error = connectPlaylist(); - if (producer == NULL) { - return error; + m_mltConsumer->connect(*m_mltProducer); + m_mltProducer->set_speed(0); + emit durationChanged(m_mltProducer->get_playtime()); + 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.")); + if (m_showFrameEvent) delete m_showFrameEvent; + m_showFrameEvent = NULL; + if (m_pauseEvent) delete m_pauseEvent; + m_pauseEvent = NULL; + delete m_mltConsumer; + m_mltConsumer = NULL; + return -1; } - emit rendererPosition((int) m_mltProducer->position()); - return error; + position = m_mltProducer->position(); + m_mltConsumer->set("refresh", 1); + // Make sure the first frame is displayed, otherwise if we change producer too fast + // We can crash the avformat producer + Mlt::Event *ev = m_mltConsumer->setup_wait_for("consumer-frame-show"); + m_mltConsumer->wait_for(ev); + delete ev; + emit rendererPosition(position); + return 0; } int Render::setSceneList(QDomDocument list, int position) @@ -1027,6 +1066,8 @@ int Render::setSceneList(QDomDocument list, int position) int Render::setSceneList(QString playlist, int position) { + m_refreshTimer.stop(); + QMutexLocker locker(&m_mutex); if (m_winid == -1) return -1; int error = 0; @@ -1137,10 +1178,11 @@ int Render::setSceneList(QString playlist, int position) } kDebug() << "// NEW SCENE LIST DURATION SET TO: " << m_mltProducer->get_playtime(); - if (error == 0) error = connectPlaylist(); - else connectPlaylist(); + m_mltConsumer->connect(*m_mltProducer); + m_mltProducer->set_speed(0); fillSlowMotionProducers(); blockSignals(false); + emit durationChanged(m_mltProducer->get_playtime()); return error; //kDebug()<<"// SETSCN LST, POS: "<set("refresh", "0"); - m_mltConsumer->connect(*m_mltProducer); - m_mltProducer->set_speed(0); - 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.")); - delete m_mltConsumer; - m_mltConsumer = NULL; - return -1; - } - emit durationChanged(m_mltProducer->get_playtime()); - return 0; - //refresh(); -} - - int Render::volume() const { if (!m_mltConsumer || !m_mltProducer) return -1; @@ -1299,26 +1322,32 @@ void Render::slotOsdTimeout() void Render::start() { + m_refreshTimer.stop(); + QMutexLocker locker(&m_mutex); if (m_winid == -1) { kDebug() << "----- BROKEN MONITOR: " << m_name << ", RESTART"; return; } - - if (m_mltConsumer && m_mltConsumer->is_stopped()) { + if (!m_mltConsumer) return; + if (m_mltConsumer->is_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.")); kDebug(QtWarningMsg) << "/ / / / CANNOT START MONITOR"; } else { - refresh(); + m_mltConsumer->purge(); + m_mltConsumer->set("refresh", 1); } } } void Render::stop() { + m_refreshTimer.stop(); + QMutexLocker locker(&m_mutex); if (m_mltProducer == NULL) return; if (m_mltConsumer && !m_mltConsumer->is_stopped()) { m_mltConsumer->stop(); + m_mltConsumer->purge(); } if (m_mltProducer) { @@ -1329,6 +1358,8 @@ void Render::stop() void Render::stop(const GenTime & startTime) { + m_refreshTimer.stop(); + QMutexLocker locker(&m_mutex); if (m_mltProducer) { if (m_isZoneMode) resetZoneMode(); m_mltProducer->set_speed(0.0); @@ -1350,6 +1381,7 @@ void Render::pause() void Render::switchPlay(bool play) { + QMutexLocker locker(&m_mutex); if (!m_mltProducer || !m_mltConsumer) return; if (m_isZoneMode) resetZoneMode(); @@ -1358,12 +1390,15 @@ void Render::switchPlay(bool play) if (m_mltConsumer->is_stopped()) { m_mltConsumer->start(); } - m_mltConsumer->set("refresh", "1"); m_mltProducer->set_speed(1.0); + m_mltConsumer->set("refresh", "1"); } else if (!play) { + m_mltProducer->set_speed(0.0); m_mltConsumer->set("refresh", 0); m_mltProducer->seek(m_mltConsumer->position()); - stop(); + if (!m_mltConsumer->is_stopped()) m_mltConsumer->stop(); + if (m_isZoneMode) resetZoneMode(); + //emitConsumerStopped(); /*m_mltConsumer->set("refresh", 0); m_mltConsumer->stop(); @@ -1451,15 +1486,12 @@ void Render::seekToFrameDiff(int diff) void Render::doRefresh() { - // Use a Timer so that we don't refresh too much - if (m_mltConsumer) { - if (m_mltConsumer->is_stopped()) m_mltConsumer->start(); - m_mltConsumer->set("refresh", 1); - } + if (m_mltProducer && m_mltProducer->get_speed() == 0) m_refreshTimer.start(); } void Render::refresh() { + QMutexLocker locker(&m_mutex); if (!m_mltProducer) return; if (m_mltConsumer) { @@ -1471,6 +1503,7 @@ void Render::refresh() void Render::setDropFrames(bool show) { + QMutexLocker locker(&m_mutex); if (m_mltConsumer) { int dropFrames = KdenliveSettings::mltthreads(); if (show == false) dropFrames = -dropFrames; @@ -1487,7 +1520,7 @@ void Render::setDropFrames(bool show) } } -double Render::playSpeed() +double Render::playSpeed() const { if (m_mltProducer) return m_mltProducer->get_speed(); return 0.0; @@ -1840,6 +1873,7 @@ void Render::mltCutClip(int track, GenTime position) Mlt::Tractor *Render::lockService() { // we are going to replace some clips, purge consumer + QMutexLocker locker(&m_mutex); if (!m_mltProducer) return NULL; if (m_mltConsumer) { if (!m_mltConsumer->is_stopped()) m_mltConsumer->stop(); @@ -4003,6 +4037,7 @@ void Render::updatePreviewSettings() kDebug() << "////// RESTARTING CONSUMER"; if (!m_mltConsumer || !m_mltProducer) return; if (m_mltProducer->get_playtime() == 0) return; + QMutexLocker locker(&m_mutex); Mlt::Service service(m_mltProducer->parent().get_service()); if (service.type() != tractor_type) return;