From: Jean-Baptiste Mardelle Date: Mon, 27 Sep 2010 23:32:44 +0000 (+0000) Subject: *Allow users to choose between SDL and OpenGL for monitor display X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=7893afa29547c481ca7e58363a7e82bdb824ebf8;p=kdenlive *Allow users to choose between SDL and OpenGL for monitor display *Some documentation effort *Put Audio Vu meter in it's own container svn path=/trunk/kdenlive/; revision=4946 --- diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2c48801b..5dbd65b1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -16,6 +16,8 @@ endif (Q_WS_X11) if (APPLE) find_package(OpenGL) set(QT_USE_QTOPENGL TRUE) +else (APPLE) + macro_optional_find_package(OpenGL) endif (APPLE) include_directories ( @@ -231,9 +233,10 @@ else(APPLE OR CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" OR NO_JOGSHUTTLE) set(kdenlive_SRCS jogshuttle.cpp ${kdenlive_SRCS}) endif(APPLE OR CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" OR NO_JOGSHUTTLE) -if (APPLE) +if (APPLE OR OPENGL_FOUND) + add_definitions(-DUSE_OPEN_GL) set(kdenlive_SRCS videoglwidget.cpp ${kdenlive_SRCS}) -endif (APPLE) +endif (APPLE OR OPENGL_FOUND) kde4_add_kcfg_files(kdenlive_SRCS kdenlivesettings.kcfgc ) QT4_ADD_DBUS_ADAPTOR(kdenlive_SRCS org.kdenlive.MainWindow.xml mainwindow.h MainWindow) @@ -265,6 +268,11 @@ if (APPLE) target_link_libraries(kdenlive ${SDL_LIBRARY}) target_link_libraries(kdenlive ${QT_QTOPENGL_LIBRARY}) target_link_libraries(kdenlive ${OPENGL_LIBRARIES}) +else (APPLE) + if (OPENGL_FOUND) + target_link_libraries(kdenlive ${QT_QTOPENGL_LIBRARY}) + target_link_libraries(kdenlive ${OPENGL_LIBRARIES}) + endif (OPENGL_FOUND) endif (APPLE) install(TARGETS kdenlive DESTINATION ${BIN_INSTALL_DIR}) diff --git a/src/audiosignal.cpp b/src/audiosignal.cpp index f35db088..64a59c92 100644 --- a/src/audiosignal.cpp +++ b/src/audiosignal.cpp @@ -7,43 +7,43 @@ #include -AudioSignal::AudioSignal(QWidget *parent):QWidget(parent) +AudioSignal::AudioSignal(QWidget *parent): QWidget(parent) { - //QVBoxLayout *vbox=new QVBoxLayout(this); - //label=new QLabel(); - //vbox->addWidget(label); - setMaximumHeight(12); - col << Qt::green << Qt::green << Qt::green << Qt::green << Qt::green << Qt::green << Qt::green << Qt::green << Qt::green << Qt::green ; - col << Qt::yellow << Qt::yellow << Qt::yellow << Qt::yellow << Qt::yellow ; - col << Qt::darkYellow << Qt::darkYellow << Qt::darkYellow; - col << Qt::red << Qt::red; + //QVBoxLayout *vbox=new QVBoxLayout(this); + //label=new QLabel(); + //vbox->addWidget(label); + setMinimumHeight(10); + col << Qt::green << Qt::green << Qt::green << Qt::green << Qt::green << Qt::green << Qt::green << Qt::green << Qt::green << Qt::green ; + col << Qt::yellow << Qt::yellow << Qt::yellow << Qt::yellow << Qt::yellow ; + col << Qt::darkYellow << Qt::darkYellow << Qt::darkYellow; + col << Qt::red << Qt::red; } -void AudioSignal::showAudio(QByteArray arr) +void AudioSignal::showAudio(const QByteArray arr) { - channels=arr; - update(); + channels = arr; + update(); } -void AudioSignal::paintEvent(QPaintEvent* e) +void AudioSignal::paintEvent(QPaintEvent* /*e*/) { QPainter p(this); //p.begin(); - //p.fillRect(0,0,(unsigned char)channels[0]*width()/255,height()/2,QBrush(Qt::SolidPattern)); - //p.fillRect(0,height()/2,(unsigned char)channels[1]*width()/255,height()/2,QBrush(Qt::SolidPattern)); - int numchan=channels.size(); - for (int i=0;i0){ - p.fillRect(x*xdelta,y1,maxx>xdelta?xdelta-1:maxx-1,_h,QBrush(col.at(x),Qt::SolidPattern)); - maxx-=xdelta; - } - } - } + //p.fillRect(0,0,(unsigned char)channels[0]*width()/255,height()/2,QBrush(Qt::SolidPattern)); + //p.fillRect(0,height()/2,(unsigned char)channels[1]*width()/255,height()/2,QBrush(Qt::SolidPattern)); + int numchan = channels.size(); + for (int i = 0; i < numchan; i++) { + int maxx = (unsigned char)channels[i] * width() / 255; + int xdelta = width() / 20; + int y1 = height() * i / numchan; + int _h = height() / numchan - 1; + for (int x = 0; x < 20; x++) { + if (maxx > 0) { + p.fillRect(x * xdelta, y1, maxx > xdelta ? xdelta - 1 : maxx - 1, _h, QBrush(col.at(x), Qt::SolidPattern)); + maxx -= xdelta; + } + } + } p.end(); } #include "audiosignal.moc" diff --git a/src/audiosignal.h b/src/audiosignal.h index d0ab44c2..18ed05d5 100644 --- a/src/audiosignal.h +++ b/src/audiosignal.h @@ -7,19 +7,19 @@ class QLabel; #include -class AudioSignal : public QWidget +class AudioSignal : public QWidget { - Q_OBJECT - public: - AudioSignal (QWidget *parent=0); - private: - QLabel* label; - QByteArray channels; - QList col; - protected: - void paintEvent(QPaintEvent* ); - public slots: - void showAudio(QByteArray); + Q_OBJECT +public: + AudioSignal(QWidget *parent = 0); +private: + QLabel* label; + QByteArray channels; + QList col; +protected: + void paintEvent(QPaintEvent*); +public slots: + void showAudio(const QByteArray); }; diff --git a/src/kdenlivesettings.kcfg b/src/kdenlivesettings.kcfg index f2ceeb6b..3998787f 100644 --- a/src/kdenlivesettings.kcfg +++ b/src/kdenlivesettings.kcfg @@ -121,6 +121,11 @@ + + + false + + 0 diff --git a/src/kdenlivesettingsdialog.cpp b/src/kdenlivesettingsdialog.cpp index 31ec0d9e..56b9709d 100644 --- a/src/kdenlivesettingsdialog.cpp +++ b/src/kdenlivesettingsdialog.cpp @@ -105,6 +105,9 @@ KdenliveSettingsDialog::KdenliveSettingsDialog(QWidget * parent) : // Disable drop B frames, see Kdenlive issue #1330 m_configSdl.groupBox->setHidden(true); +#if not defined(Q_WS_MAC) && not defined(USE_OPEN_GL) + m_configSdl.kcfg_openglmonitors->setHidden(true); +#endif m_page6 = addPage(p6, i18n("Playback"), "media-playback-start"); diff --git a/src/monitor.cpp b/src/monitor.cpp index f61ba571..0c5b46a6 100644 --- a/src/monitor.cpp +++ b/src/monitor.cpp @@ -49,7 +49,7 @@ Monitor::Monitor(QString name, MonitorManager *manager, QString profile, QWidget *parent) : QWidget(parent), render(NULL), - m_audiosignal(NULL), + m_audiosignal(NULL), m_name(name), m_monitorManager(manager), m_currentClip(NULL), @@ -59,10 +59,12 @@ Monitor::Monitor(QString name, MonitorManager *manager, QString profile, QWidget m_scale(1), m_length(0), m_dragStarted(false), + m_monitorRefresh(NULL), m_effectScene(NULL), m_effectView(NULL), m_selectedClip(NULL), m_loopClipTransition(true) + { m_ui.setupUi(this); QVBoxLayout *layout = new QVBoxLayout; @@ -139,25 +141,29 @@ Monitor::Monitor(QString name, MonitorManager *manager, QString profile, QWidget QVBoxLayout *rendererBox = new QVBoxLayout(m_ui.video_frame); rendererBox->setContentsMargins(0, 0, 0, 0); + bool monitorCreated = false; #ifdef Q_WS_MAC - m_glWidget = new VideoGLWidget(m_ui.video_frame); - rendererBox->addWidget(m_glWidget); - render = new Render(m_name, (int) m_ui.video_frame->winId(), -1, profile, this); - m_glWidget->setImageAspectRatio(render->dar()); - m_glWidget->setBackgroundColor(KdenliveSettings::window_background()); - m_glWidget->resize(m_ui.video_frame->size()); - connect(render, SIGNAL(showImageSignal(QImage)), m_glWidget, SLOT(showImage(QImage))); - m_monitorRefresh = 0; -#else - m_monitorRefresh = new MonitorRefresh(m_ui.video_frame); - rendererBox->addWidget(m_monitorRefresh); - render = new Render(m_name, (int) m_monitorRefresh->winId(), -1, profile, this); - m_monitorRefresh->setRenderer(render); + createOpenGlWidget(rendererBox, profile); + monitorCreated = true; + //m_glWidget->setFixedSize(width, height); +#elif defined (USE_OPEN_GL) + if (KdenliveSettings::openglmonitors()) { + monitorCreated = createOpenGlWidget(rendererBox, profile); + } #endif - m_audiosignal= new AudioSignal(this); - rendererBox->addWidget(m_audiosignal); - connect(render, SIGNAL(showAudioSignal(QByteArray)), m_audiosignal, SLOT(showAudio(QByteArray))); - + if (!monitorCreated) { + m_monitorRefresh = new MonitorRefresh(m_ui.video_frame); + rendererBox->addWidget(m_monitorRefresh); + render = new Render(m_name, (int) m_monitorRefresh->winId(), profile, this); + m_monitorRefresh->setRenderer(render); + } + + QVBoxLayout *audioBox = new QVBoxLayout; + audioBox->setContentsMargins(0, 0, 0, 0); + m_audiosignal = new AudioSignal(); + audioBox->addWidget(m_audiosignal); + m_ui.audio_monitor->setLayout(audioBox); + connect(render, SIGNAL(showAudioSignal(const QByteArray)), m_audiosignal, SLOT(showAudio(const QByteArray))); connect(m_ruler, SIGNAL(seekRenderer(int)), this, SLOT(slotSeek(int))); connect(render, SIGNAL(durationChanged(int)), this, SLOT(adjustRulerSize(int))); connect(render, SIGNAL(rendererStopped(int)), this, SLOT(rendererStopped(int))); @@ -171,9 +177,8 @@ Monitor::Monitor(QString name, MonitorManager *manager, QString profile, QWidget } else { connect(m_ruler, SIGNAL(zoneChanged(QPoint)), this, SLOT(setClipZone(QPoint))); } -#ifndef Q_WS_MAC - m_monitorRefresh->show(); -#endif + + if (m_monitorRefresh) m_monitorRefresh->show(); if (name == "project") { m_effectScene = new MonitorScene(render); @@ -185,8 +190,6 @@ Monitor::Monitor(QString name, MonitorManager *manager, QString profile, QWidget m_effectScene->setUp(); m_effectView->hide(); } - - kDebug() << "/////// BUILDING MONITOR, ID: " << m_ui.video_frame->winId(); } Monitor::~Monitor() @@ -207,6 +210,23 @@ QString Monitor::name() const return m_name; } +#if defined(Q_WS_MAC) || defined(USE_OPEN_GL) +bool Monitor::createOpenGlWidget(QVBoxLayout *rendererBox, const QString profile) +{ + render = new Render(m_name, 0, profile, this); + m_glWidget = new VideoGLWidget(m_ui.video_frame); + if (m_glWidget == NULL) { + // Creation failed, we are in trouble... + return false; + } + rendererBox->addWidget(m_glWidget); + m_glWidget->setImageAspectRatio(render->dar()); + m_glWidget->setBackgroundColor(KdenliveSettings::window_background()); + connect(render, SIGNAL(showImageSignal(QImage)), m_glWidget, SLOT(showImage(QImage))); + return true; +} +#endif + void Monitor::setupMenu(QMenu *goMenu, QAction *playZone, QAction *loopZone, QMenu *markerMenu, QAction *loopClip) { m_contextMenu = new QMenu(this); @@ -232,7 +252,10 @@ void Monitor::setupMenu(QMenu *goMenu, QAction *playZone, QAction *loopZone, QMe m_contextMenu->addAction(extractFrame); if (m_name != "clip") { -#ifndef Q_WS_MAC +#if defined(Q_WS_MAC) || defined(USE_OPEN_GL) + // TODO: why disable in OpenGL? + // Don't show split action +#else QAction *splitView = m_contextMenu->addAction(KIcon("view-split-left-right"), i18n("Split view"), render, SLOT(slotSplitView(bool))); splitView->setCheckable(true); m_configMenu->addAction(splitView); @@ -656,19 +679,6 @@ void Monitor::rendererStopped(int pos) m_playAction->setIcon(m_playIcon); } -void Monitor::initMonitor() -{ - kDebug() << "/////// INITING MONITOR, ID: " << m_ui.video_frame->winId(); -} - -// virtual -/*void Monitor::resizeEvent(QResizeEvent * event) { - QWidget::resizeEvent(event); - adjustRulerSize(-1); - if (render && m_isActive) render->doRefresh(); - // -}*/ - void Monitor::adjustRulerSize(int length) { if (length > 0) m_length = length; @@ -839,13 +849,16 @@ void Monitor::slotSwitchMonitorInfo(bool show) KdenliveSettings::setDisplayMonitorInfo(show); if (show) { if (m_overlay) return; -#ifndef Q_WS_MAC - m_overlay = new Overlay(m_monitorRefresh); - m_overlay->raise(); - m_overlay->setHidden(true); -#else - m_overlay = new Overlay(m_glWidget); + if (m_monitorRefresh == NULL) { + // Using OpenGL display +#if defined(Q_WS_MAC) || defined(USE_OPEN_GL) + m_overlay = new Overlay(m_glWidget); #endif + } else { + m_overlay = new Overlay(m_monitorRefresh); + m_overlay->raise(); + m_overlay->setHidden(true); + } } else { delete m_overlay; m_overlay = NULL; @@ -880,7 +893,7 @@ void Monitor::slotSetSelectedClip(AbstractClipItem* item) void Monitor::slotSetSelectedClip(ClipItem* item) { if (item || (!item && !m_loopClipTransition)) { - m_loopClipTransition = false; + m_loopClipTransition = false; slotSetSelectedClip((AbstractClipItem*)item); } } @@ -897,11 +910,13 @@ void Monitor::slotSetSelectedClip(Transition* item) void Monitor::slotEffectScene(bool show) { if (m_name == "project") { -#ifdef Q_WS_MAC - m_glWidget->setVisible(!show); -#else - m_monitorRefresh->setVisible(!show); + if (m_monitorRefresh) { + m_monitorRefresh->setVisible(!show); + } else { +#if defined(Q_WS_MAC) || defined(USE_OPEN_GL) + m_glWidget->setVisible(!show); #endif + } m_effectView->setVisible(show); emit requestFrameForAnalysis(show); if (show) { diff --git a/src/monitor.h b/src/monitor.h index ddfe2804..7f7a7ba6 100644 --- a/src/monitor.h +++ b/src/monitor.h @@ -17,7 +17,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * ***************************************************************************/ - #ifndef MONITOR_H #define MONITOR_H @@ -31,7 +30,7 @@ #include "gentime.h" #include "ui_monitor_ui.h" #include "timecodedisplay.h" -#ifdef Q_WS_MAC +#if defined(Q_WS_MAC) || defined(USE_OPEN_GL) #include "videoglwidget.h" #endif @@ -112,6 +111,7 @@ protected: private: Ui::Monitor_UI m_ui; + AudioSignal *m_audiosignal; QString m_name; MonitorManager *m_monitorManager; DocClipBase *m_currentClip; @@ -140,10 +140,10 @@ private: /** true if selected clip is transition, false = selected clip is clip. * Necessary because sometimes we get two signals, e.g. we get a clip and we get selected transition = NULL. */ bool m_loopClipTransition; -#ifdef Q_WS_MAC +#if defined(Q_WS_MAC) || defined(USE_OPEN_GL) VideoGLWidget *m_glWidget; + bool createOpenGlWidget(QVBoxLayout *rendererBox, const QString profile); #endif - AudioSignal *m_audiosignal; GenTime getSnapForPos(bool previous); @@ -164,7 +164,6 @@ private slots: public slots: void slotOpenFile(const QString &); void slotSetXml(DocClipBase *clip, QPoint zone = QPoint(), const int position = -1); - void initMonitor(); void refreshMonitor(bool visible = true); void slotSeek(int pos); void stop(); diff --git a/src/renderer.cpp b/src/renderer.cpp index 80ae7c38..2f554c90 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -61,14 +61,12 @@ 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->m_isBlocked) return; Mlt::Frame frame(frame_ptr); -#ifdef Q_WS_MAC - self->showFrame(frame); -#endif - self->showAudio(frame); + if (!frame.is_valid()) return; self->emitFrameNumber(mlt_frame_get_position(frame_ptr)); if (self->sendFrameForAnalysis && frame_ptr->convert_image) { self->emitFrameUpdated(frame); } + self->showAudio(frame); if (frame.get_double("_speed") == 0.0) { self->emitConsumerStopped(); } else if (frame.get_double("_speed") < 0.0 && mlt_frame_get_position(frame_ptr) <= 0) { @@ -77,24 +75,34 @@ static void consumer_frame_show(mlt_consumer, Render * self, mlt_frame frame_ptr } } +static void consumer_gl_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->m_isBlocked) return; + Mlt::Frame frame(frame_ptr); + self->showFrame(frame); + if (frame.get_double("_speed") == 0.0) { + self->emitConsumerStopped(); + } else if (frame.get_double("_speed") < 0.0 && mlt_frame_get_position(frame_ptr) <= 0) { + self->pause(); + self->emitConsumerStopped(); + } +} -Render::Render(const QString & rendererName, int winid, int /* extid */, QString profile, QWidget *parent) : - QObject(parent), - m_isBlocked(0), - sendFrameForAnalysis(false), - m_name(rendererName), - m_mltConsumer(NULL), - m_mltProducer(NULL), - m_mltProfile(NULL), - m_framePosition(0), - m_isZoneMode(false), - m_isLoopMode(false), - m_isSplitView(false), - m_blackClip(NULL), - m_winid(winid) -#ifdef Q_WS_MAC - , m_glWidget(0) -#endif +Render::Render(const QString & rendererName, int winid, QString profile, QWidget *parent) : + QObject(parent), + m_isBlocked(0), + sendFrameForAnalysis(false), + m_name(rendererName), + m_mltConsumer(NULL), + m_mltProducer(NULL), + m_mltProfile(NULL), + m_framePosition(0), + m_isZoneMode(false), + m_isLoopMode(false), + m_isSplitView(false), + m_blackClip(NULL), + m_winid(winid) { /*if (rendererName == "project") m_monitorId = 10000; else m_monitorId = 10001;*/ @@ -188,20 +196,21 @@ void Render::buildConsumer(const QString profileName) setenv("SDL_VIDEO_ALLOW_SCREENSAVER", "1", 1); //m_mltConsumer->set("fullscreen", 1); -#ifdef Q_WS_MAC - m_mltConsumer = new Mlt::Consumer(*m_mltProfile, "sdl_audio"); - m_mltConsumer->set("preview_off", 1); - m_mltConsumer->set("preview_format", mlt_image_rgb24a); -#else - m_mltConsumer = new Mlt::Consumer(*m_mltProfile, "sdl_preview"); -#endif + if (m_winid == 0) { + // OpenGL monitor + 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); + } 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->set("window_id", m_winid); + } m_mltConsumer->set("resize", 1); - m_mltConsumer->set("window_id", m_winid); m_mltConsumer->set("terminate_on_pause", 1); m_mltConsumer->set("window_background", KdenliveSettings::window_background().name().toUtf8().constData()); - - // 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); @@ -233,7 +242,6 @@ void Render::buildConsumer(const QString profileName) m_blackClip = new Mlt::Producer(*m_mltProfile, "colour", "black"); m_blackClip->set("id", "black"); m_blackClip->set("mlt_type", "producer"); - } Mlt::Producer *Render::invalidProducer(const QString &id) @@ -287,7 +295,6 @@ int Render::resetProfile(const QString profileName) delete m_mltProducer; } m_mltProducer = NULL; - buildConsumer(profileName); double new_fps = m_mltProfile->fps(); if (current_fps != new_fps) { @@ -394,94 +401,6 @@ 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); - Mlt::Profile *prof = new Mlt::Profile(profile); - Mlt::Producer m_producer(*prof, file.toUtf8().constData()); - if (m_producer.is_blank()) { - pix.fill(Qt::black); - return pix; - } - - Mlt::Filter m_convert(*prof, "avcolour_space"); - m_convert.set("forced", mlt_image_rgb24a); - m_producer.attach(m_convert); - m_producer.seek(frame_position); - Mlt::Frame * frame = m_producer.get_frame(); - if (frame) { - pix = frameThumbnail(frame, width, height, true); - delete frame; - } - if (prof) delete prof; - return pix; -} -*/ -/* -void Render::getImage(KUrl url, int frame_position, QPoint size) -{ - Mlt::Producer m_producer(url.path().toUtf8().constData()); - if (m_producer.is_blank()) { - return; - } - Mlt::Filter m_convert("avcolour_space"); - m_convert.set("forced", mlt_image_rgb24a); - m_producer.attach(m_convert); - m_producer.seek(frame_position); - - Mlt::Frame * frame = m_producer.get_frame(); - - if (frame) { - QPixmap pix = frameThumbnail(frame, size.x(), size.y(), true); - delete frame; - emit replyGetImage(url, frame_position, pix, size.x(), size.y()); - } -}*/ - -/* Create thumbnail for color */ -/*void Render::getImage(int id, QString color, QPoint size) -{ - QPixmap pixmap(size.x() - 2, size.y() - 2); - color = color.replace(0, 2, "#"); - color = color.left(7); - pixmap.fill(QColor(color)); - QPixmap result(size.x(), size.y()); - result.fill(Qt::black); - //copyBlt(&result, 1, 1, &pixmap, 0, 0, size.x() - 2, size.y() - 2); - emit replyGetImage(id, result, size.x(), size.y()); - -}*/ - -/* Create thumbnail for image */ -/*void Render::getImage(KUrl url, QPoint size) -{ - QImage im; - QPixmap pixmap; - if (url.fileName().startsWith(".all.")) { // check for slideshow - QString fileType = url.fileName().right(3); - QStringList more; - QStringList::Iterator it; - - QDir dir( url.directory() ); - more = dir.entryList( QDir::Files ); - for ( it = more.begin() ; it != more.end() ; ++it ) { - if ((*it).endsWith("."+fileType, Qt::CaseInsensitive)) { - if (!im.load(url.directory() + '/' + *it)) - kDebug()<<"++ ERROR LOADIN IMAGE: "<dar(); } + void Render::slotSplitView(bool doit) { m_isSplitView = doit; @@ -1384,11 +1304,11 @@ void Render::setDropFrames(bool show) int dropFrames = 1; if (show == false) dropFrames = 0; m_mltConsumer->stop(); -#ifdef Q_WS_MAC - m_mltConsumer->set("real_time", dropFrames); -#else - m_mltConsumer->set("play.real_time", dropFrames); -#endif + if (m_winid == 0) + m_mltConsumer->set("real_time", dropFrames); + else + m_mltConsumer->set("play.real_time", dropFrames); + if (m_mltConsumer->start() == -1) { kDebug(QtWarningMsg) << "ERROR, Cannot start monitor"; } @@ -1480,9 +1400,11 @@ void Render::exportCurrentFrame(KUrl url, bool /*notify*/) //if (notify) QApplication::postEvent(qApp->activeWindow(), new UrlEvent(url, 10003)); } -#ifdef Q_WS_MAC + void Render::showFrame(Mlt::Frame& frame) { + m_framePosition = qMax(frame.get_int("_position"), 0); + emit rendererPosition((int) m_framePosition); mlt_image_format format = mlt_image_rgb24a; int width = 0; int height = 0; @@ -1490,49 +1412,54 @@ void Render::showFrame(Mlt::Frame& frame) QImage qimage(width, height, QImage::Format_ARGB32_Premultiplied); memcpy(qimage.scanLine(0), image, width * height * 4); emit showImageSignal(qimage); + showAudio(frame); + if (sendFrameForAnalysis && frame.get_frame()->convert_image) { + emit frameUpdated(qimage.rgbSwapped()); + } } -#endif void Render::showAudio(Mlt::Frame& frame) { - mlt_audio_format audio_format=mlt_audio_pcm; - int freq,num_channels,samples; - uint8_t* data=(uint8_t*)frame.get_audio(audio_format,freq,num_channels,samples); - if (!data) - return; - int value=0; - QByteArray channels; - - for (int i=0;i> 8 ); - break; - case 2: - value=( ((uint32_t*)data) [i] >> 16 ); - break; - case 3: - value=( ((float*)data) [i]*255); - break; - default: - value=0; - } - */ - long val=0; - int num_samples=20; - for (int s=0;s0) - emit showAudioSignal(channels); + if (!frame.is_valid() || frame.get_int("test_audio") != 0) return; + mlt_audio_format audio_format = mlt_audio_pcm; + int freq = 0; + int num_channels = 0; + int samples = 0; + uint8_t* data = (uint8_t*)frame.get_audio(audio_format, freq, num_channels, samples); + if (!data) + return; + int value = 0; + QByteArray channels; + for (int i = 0; i < num_channels; i++) { + /* switch (audio_format) + { + case 0: + value=( ( (uint8_t*)data) [i] ); + break; + case 1: + value=( ( (uint16_t*)data) [i] >> 8 ); + break; + case 2: + value=( ((uint32_t*)data) [i] >> 16 ); + break; + case 3: + value=( ((float*)data) [i]*255); + break; + default: + value=0; + } + */ + long val = 0; + int num_samples = 20; + for (int s = 0; s < samples; s += samples / num_samples) { + val += (data[i+s*num_channels] - 127); + } + channels.append(val / num_samples); + } + + + if (samples > 0) + emit showAudioSignal(channels); } /* diff --git a/src/renderer.h b/src/renderer.h index 60b9ed9e..303b0fd1 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -2,8 +2,9 @@ krender.h - description ------------------- begin : Fri Nov 22 2002 - copyright : (C) 2002 by Jason Wood - email : jasonwood@blueyonder.co.uk + copyright : (C) 2002 by Jason Wood (jasonwood@blueyonder.co.uk) + copyright : (C) 2010 by Jean-Baptiste Mardelle (jb@kdenlive.org) + ***************************************************************************/ /*************************************************************************** @@ -17,7 +18,6 @@ /** * @class Render - * @author Jason Wood * @brief Client side of the interface to a renderer. * * From Kdenlive's point of view, you treat the Render object as the renderer, @@ -40,9 +40,6 @@ #include #include -#ifdef Q_WS_MAC -#include "videoglwidget.h" -#endif class Render; @@ -82,8 +79,13 @@ Q_OBJECT public: enum FailStates { OK = 0, APP_NOEXIST }; + /** @brief Build a MLT Renderer + * @param rendererName A unique identifier for this renderer + * @param winid The parent widget identifier (required for SDL display). Set to 0 for OpenGL rendering + * @param profile The MLT profile used for the renderer (default one will be used if empty). */ + Render(const QString & rendererName, int winid, QString profile = QString(), QWidget *parent = 0); - Render(const QString & rendererName, int winid, int extid, QString profile = QString(), QWidget *parent = 0); + /** @brief Destroy the MLT Renderer. */ ~Render(); /** @brief Seeks the renderer clip to the given time. */ @@ -92,33 +94,24 @@ Q_OBJECT public: void seekToFrameDiff(int diff); int m_isBlocked; - //static QPixmap getVideoThumbnail(char *profile, QString file, int frame, int width, int height); QPixmap getImageThumbnail(KUrl url, int width, int height); - /* Return thumbnail for color clip - void getImage(int id, QString color, QPoint size);*/ - - // static QPixmap frameThumbnail(Mlt::Frame *frame, int width, int height, bool border = false); - - /* Return thumbnail for image clip - void getImage(KUrl url, QPoint size);*/ - - /* Requests a particular frame from the given file. - * - * The pixmap will be returned by emitting the replyGetImage() signal. - void getImage(KUrl url, int frame, QPoint size);*/ - + /** @brief Sets the current MLT producer playlist. + * @param list The xml describing the playlist + * @param position (optional) time to seek to */ int setSceneList(QDomDocument list, int position = 0); - /** @brief Sets the current scene list. - * @param list new scene list + /** @brief Sets the current MLT producer playlist. + * @param list new playlist * @param position (optional) time to seek to * @return 0 when it has success, different from 0 otherwise * - * Creates the producer from the MLT XML QDomDocument. Wraps the VEML - * command of the same name. */ + * Creates the producer from the text playlist. */ int setSceneList(QString playlist, int position = 0); int setProducer(Mlt::Producer *producer, int position); + + /** @brief Get the current MLT producer playlist. + * @return A string describing the playlist */ const QString sceneList(); bool saveSceneList(QString path, QDomElement kdenliveData = QDomElement()); @@ -126,8 +119,7 @@ Q_OBJECT public: * @param speed speed to play the scene to * * The speed is relative to normal playback, e.g. 1.0 is normal speed, 0.0 - * is paused, -1.0 means play backwards. It does not specify start/stop - * times for playback. Wraps the VEML command of the same name. */ + * is paused, -1.0 means play backwards. It does not specify start/stop */ void play(double speed); void switchPlay(); void pause(); @@ -140,9 +132,7 @@ Q_OBJECT public: QImage extractFrame(int frame_position, int width = -1, int height = -1); /** @brief Plays the scene starting from a specific time. - * @param startTime time to start playing the scene from - * - * Wraps the VEML command of the same name. */ + * @param startTime time to start playing the scene from */ void play(const GenTime & startTime); void playZone(const GenTime & startTime, const GenTime & stopTime); void loopZone(const GenTime & startTime, const GenTime & stopTime); @@ -259,10 +249,9 @@ Q_OBJECT public: void updatePreviewSettings(); void setDropFrames(bool show); QString updateSceneListFps(double current_fps, double new_fps, QString scene); -#ifdef Q_WS_MAC void showFrame(Mlt::Frame&); -#endif - void showAudio(Mlt::Frame&); + + void showAudio(Mlt::Frame&); /** @brief This property is used to decide if the renderer should convert it's frames to QImage for use in other Kdenlive widgets. */ bool sendFrameForAnalysis; QList checkTrackSequence(int); @@ -301,14 +290,14 @@ private: /** @brief A human-readable description of this renderer. */ int m_winid; -#ifdef Q_WS_MAC - VideoGLWidget *m_glWidget; -#endif void closeMlt(); void mltCheckLength(Mlt::Tractor *tractor); void mltPasteEffects(Mlt::Producer *source, Mlt::Producer *dest); QMap mltGetTransitionParamsFromXml(QDomElement xml); QMap m_slowmotionProducers; + + /** @brief Build the MLT Consumer object with initial settings. + * @param profileName The MLT profile to use for the consumer */ void buildConsumer(const QString profileName); void resetZoneMode(); void fillSlowMotionProducers(); @@ -358,7 +347,7 @@ signals: * * Used in Mac OS X. */ void showImageSignal(QImage); - void showAudioSignal(QByteArray); + void showAudioSignal(const QByteArray); /** @brief The renderer refreshed the current frame, but no seeking was done. */ void frameUpdated(QImage); diff --git a/src/widgets/configsdl_ui.ui b/src/widgets/configsdl_ui.ui index 49fc26d5..6e78e329 100644 --- a/src/widgets/configsdl_ui.ui +++ b/src/widgets/configsdl_ui.ui @@ -6,8 +6,8 @@ 0 0 - 352 - 239 + 353 + 247 @@ -21,7 +21,7 @@ - + @@ -37,10 +37,10 @@ - + - + @@ -56,10 +56,10 @@ - + - + Audio device: @@ -69,10 +69,10 @@ - + - + @@ -83,7 +83,7 @@ - + Qt::Vertical @@ -96,7 +96,7 @@ - + Monitor Preview Speedup Settings @@ -112,21 +112,21 @@ - + Monitor background color: - + Preview volume: - + % @@ -139,6 +139,13 @@ + + + + Use OpenGL for video display (restart Kdenlive to apply) + + + diff --git a/src/widgets/monitor_ui.ui b/src/widgets/monitor_ui.ui index 9a15a100..72e043b0 100644 --- a/src/widgets/monitor_ui.ui +++ b/src/widgets/monitor_ui.ui @@ -6,8 +6,8 @@ 0 0 - 237 - 177 + 391 + 242 @@ -17,7 +17,26 @@ 0 - + + + + + 0 + 0 + + + + QFrame::NoFrame + + + QFrame::Plain + + + 0 + + + + @@ -29,7 +48,7 @@ - + @@ -54,7 +73,7 @@ - +