[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [kdenlive/Applications/15.08] src: Fix webcam capture
From:       Jean-Baptiste Mardelle <jb () kdenlive ! org>
Date:       2015-07-26 11:03:59
Message-ID: E1ZJJip-0007lE-AG () scm ! kde ! org
[Download RAW message or body]

Git commit a4784c6fed0fb006bca8e92af12a5235e7801eb8 by Jean-Baptiste Mardelle.
Committed on 26/07/2015 at 11:03.
Pushed by mardelle into branch 'Applications/15.08'.

Fix webcam capture

M  +110  -39   src/monitor/glwidget.cpp
M  +6    -2    src/monitor/glwidget.h
M  +28   -4    src/monitor/monitor.cpp
M  +4    -0    src/monitor/monitor.h
M  +134  -16   src/monitor/recmanager.cpp
M  +10   -1    src/monitor/recmanager.h
M  +33   -0    src/renderer.cpp
M  +1    -0    src/renderer.h

http://commits.kde.org/kdenlive/a4784c6fed0fb006bca8e92af12a5235e7801eb8

diff --git a/src/monitor/glwidget.cpp b/src/monitor/glwidget.cpp
index 16751dc..695a9be 100644
--- a/src/monitor/glwidget.cpp
+++ b/src/monitor/glwidget.cpp
@@ -566,7 +566,7 @@ void GLWidget::slotSwitchAudioOverlay(bool enable)
     }
 }
 
-int GLWidget::setProducer(Mlt::Producer* producer, bool isMulti)
+int GLWidget::setProducer(Mlt::Producer* producer, bool reconfig)
 {
     int error = 0;//Controller::setProducer(producer, isMulti);
     /*if (m_producer) {
@@ -574,8 +574,9 @@ int GLWidget::setProducer(Mlt::Producer* producer, bool isMulti)
         m_producer = NULL;
     }*/
     m_producer = producer;
+    if (!reconfig) return 0;
     if (!error && producer) {
-        error = reconfigure(isMulti);
+        error = reconfigure();
         if (!error) {
             // The profile display aspect ratio may have changed.
             resizeGL(width(), height());
@@ -668,29 +669,105 @@ void GLWidget::adjustAudioOverlay(bool isAudio)
     }
 }
 
+void GLWidget::stopCapture()
+{
+    if (strcmp(m_consumer->get("mlt_service"), "multi") == 0) {
+	m_consumer->set("refresh", 0);
+        m_consumer->purge();
+        m_consumer->stop();
+    }
+}
 
-int GLWidget::reconfigure(bool isMulti)
+int GLWidget::reconfigureMulti(QString params, QString path, Mlt::Profile *profile)
+{
+    QString serviceName = property("mlt_service").toString();
+    if (!m_consumer || !m_consumer->is_valid() || \
strcmp(m_consumer->get("mlt_service"), "multi") != 0) { +	if (m_consumer) {
+	    m_consumer->purge();
+	    m_consumer->stop();
+	    delete m_consumer;
+	}
+	m_consumer = new Mlt::FilteredConsumer(*profile, "multi");
+	        delete m_threadStartEvent;
+        m_threadStartEvent = 0;
+        delete m_threadStopEvent;
+        m_threadStopEvent = 0;
+
+        delete m_threadCreateEvent;
+        delete m_threadJoinEvent;
+        if (m_consumer) {
+            m_threadCreateEvent = m_consumer->listen("consumer-thread-create", this, \
(mlt_listener) onThreadCreate); +            m_threadJoinEvent = \
m_consumer->listen("consumer-thread-join", this, (mlt_listener) onThreadJoin); +      \
} +    }
+    if (m_consumer->is_valid()) {
+	// buid sub consumers
+	//m_consumer->set("mlt_image_format", "yuv422");
+	reloadProfile(*profile);
+	int volume = KdenliveSettings::volume();
+	m_consumer->set("0", serviceName.toUtf8().constData());
+        m_consumer->set("0.mlt_image_format", "yuv422");
+        m_consumer->set("0.terminate_on_pause", 0);
+	//m_consumer->set("0.preview_off", 1);
+	m_consumer->set("0.real_time", 0);
+	m_consumer->set("0.volume", (double)volume / 100);
+	    
+	if (serviceName == "sdl_audio") {
+#ifdef Q_OS_WIN
+	    m_consumer->set("0.audio_buffer", 2048);
+#else
+	    m_consumer->set("0.audio_buffer", 512);
+#endif
+	}
+	    
+	m_consumer->set("1", "avformat");
+	m_consumer->set("1.target", path.toUtf8().constData());
+	//m_consumer->set("1.real_time", -KdenliveSettings::mltthreads());
+	m_consumer->set("terminate_on_pause", 0);
+	m_consumer->set("1.terminate_on_pause", 0);
+	//m_consumer->set("1.terminate_on_pause", 0);// was commented out. restoring it  \
fixes mantis#3415 - FFmpeg recording freezes +	QStringList paramList = params.split(' \
', QString::SkipEmptyParts); +	for (int i = 0; i < paramList.count(); ++i) {
+	    QString key = "1." + paramList.at(i).section('=', 0, 0);
+	    QString value = paramList.at(i).section('=', 1, 1);
+	    if (value == "%threads") value = QString::number(QThread::idealThreadCount());
+	    m_consumer->set(key.toUtf8().constData(), value.toUtf8().constData());
+	}	
+	
+        // Connect the producer to the consumer - tell it to "run" later
+	delete m_displayEvent;
+	m_displayEvent = m_consumer->listen("consumer-frame-show", this, (mlt_listener) \
on_frame_show); +        m_consumer->connect(*m_producer);
+	m_consumer->start();
+	return 0;
+    }
+    else return -1;
+}
+
+int GLWidget::reconfigure(Mlt::Profile *profile)
 {
     int error = 0;
     // use SDL for audio, OpenGL for video
     QString serviceName = property("mlt_service").toString();
-    if (!m_consumer || !m_consumer->is_valid()) {
+    if (profile) reloadProfile(*profile);
+    if (!m_consumer || !m_consumer->is_valid() || \
strcmp(m_consumer->get("mlt_service"),"multi") == 0) { +	if (m_consumer) {
+	    m_consumer->purge();
+	    m_consumer->stop();
+	    delete m_consumer;
+	}
         if (serviceName.isEmpty()) {
             m_consumer = new Mlt::FilteredConsumer(*m_monitorProfile, "sdl_audio");
             if (m_consumer->is_valid())
                 serviceName = "sdl_audio";
             else {
                 serviceName = "rtaudio";
-                delete m_consumer;
-                m_consumer = NULL;
             }
+            delete m_consumer;
+            m_consumer = NULL;
             setProperty("mlt_service", serviceName);
         }
-        if (isMulti)
-            m_consumer = new Mlt::FilteredConsumer(*m_monitorProfile, "multi");
-        else if (!m_consumer)
-            m_consumer = new Mlt::FilteredConsumer(*m_monitorProfile, \
                serviceName.toLatin1().constData());
-
+        m_consumer = new Mlt::FilteredConsumer(*m_monitorProfile, \
serviceName.toLatin1().constData());  delete m_threadStartEvent;
         m_threadStartEvent = 0;
         delete m_threadStopEvent;
@@ -707,37 +784,17 @@ int GLWidget::reconfigure(bool isMulti)
         }
     }
     if (m_consumer->is_valid()) {
-        //m_consumer->stop();
         // Connect the producer to the consumer - tell it to "run" later
-        m_consumer->connect(*m_producer);
+        if (m_producer) m_consumer->connect(*m_producer);
         delete m_displayEvent;
         if (!m_glslManager) {
-            m_consumer->set("mlt_image_format", "yuv422");
             // Make an event handler for when a frame's image should be displayed
             m_displayEvent = m_consumer->listen("consumer-frame-show", this, \
(mlt_listener) on_frame_show); +	    m_consumer->set("mlt_image_format", "yuv422");
         } else {
             m_displayEvent = m_consumer->listen("consumer-frame-show", this, \
(mlt_listener) on_gl_frame_show);  }
-        if (isMulti) {
-            m_consumer->set("terminate_on_pause", 0);
-            m_consumer->set("0", serviceName.toLatin1().constData());
-            if (serviceName == "sdl_audio")
-#ifdef Q_OS_WIN
-                m_consumer->set("0.audio_buffer", 2048);
-#else
-                m_consumer->set("0.audio_buffer", 512);
-#endif
-            /*if (!m_monitorProfile->progressive())
-                m_consumer->set("0.progressive", \
                property("progressive").toBool());*/
-            
-            m_consumer->set("0.deinterlace_method", \
                KdenliveSettings::mltdeinterlacer().toUtf8().constData());
-            m_consumer->set("0.rescale", \
                KdenliveSettings::mltinterpolation().toUtf8().constData());
-            m_consumer->set("0.buffer", 25);
-            m_consumer->set("0.prefill", 1);
-            if (property("keyer").isValid())
-                m_consumer->set("0.keyer", property("keyer").toInt());
-        }
-        else {
+        int volume = KdenliveSettings::volume();
             if (serviceName == "sdl_audio")
 #ifdef Q_OS_WIN
                 m_consumer->set("audio_buffer", 2048);
@@ -746,6 +803,7 @@ int GLWidget::reconfigure(bool isMulti)
 #endif
             /*if (!m_monitorProfile->progressive())
                 m_consumer->set("progressive", property("progressive").toBool());*/
+	    m_consumer->set("volume", (double)volume / 100);
             m_consumer->set("progressive", 1);
             m_consumer->set("rescale", \
                KdenliveSettings::mltinterpolation().toUtf8().constData());
             m_consumer->set("deinterlace_method", \
KdenliveSettings::mltdeinterlacer().toUtf8().constData()); @@ -760,16 +818,14 @@ int \
GLWidget::reconfigure(bool isMulti)  }
             /*if (property("keyer").isValid())
                 m_consumer->set("keyer", property("keyer").toInt());*/
-        }
-        int volume = KdenliveSettings::volume();
-        m_consumer->set("volume", (double)volume / 100);
+        
     
         if (m_glslManager) {
             if (!m_threadStartEvent)
                 m_threadStartEvent = m_consumer->listen("consumer-thread-started", \
this, (mlt_listener) onThreadStarted);  if (!m_threadStopEvent)
                 m_threadStopEvent = m_consumer->listen("consumer-thread-stopped", \
                this, (mlt_listener) onThreadStopped);
-            if (!serviceName.startsWith("decklink") && !isMulti)
+            if (!serviceName.startsWith("decklink"))
                 m_consumer->set("mlt_image_format", "glsl");
         } else {
             emit started();
@@ -830,6 +886,21 @@ void GLWidget::resetProfile(MltVideoProfile profile)
     m_monitorProfile->set_explicit(true);
 }
 
+void GLWidget::reloadProfile(Mlt::Profile &profile)
+{
+    m_monitorProfile->get_profile()->description = qstrdup(profile.description());
+    m_monitorProfile->set_colorspace(profile.colorspace());
+    m_monitorProfile->set_frame_rate(profile.frame_rate_num(), \
profile.frame_rate_den()); +    m_monitorProfile->set_height(profile.height());
+    m_monitorProfile->set_width(profile.width());
+    m_monitorProfile->set_progressive(profile.progressive());
+    m_monitorProfile->set_sample_aspect(profile.sample_aspect_num(), \
profile.sample_aspect_den()); +    \
m_monitorProfile->set_display_aspect(profile.display_aspect_num(), \
profile.display_aspect_den()); +    m_monitorProfile->set_explicit(true);
+    // The profile display aspect ratio may have changed.
+    resizeGL(width(), height());
+}
+
 QSize GLWidget::profileSize() const
 {
     return QSize(m_monitorProfile->width(), m_monitorProfile->height());
@@ -905,7 +976,7 @@ Mlt::Consumer *GLWidget::consumer()
 
 void GLWidget::updateGamma()
 {
-    reconfigure(false);
+    reconfigure();
 }
 
 void GLWidget::updateTexture(GLuint yName, GLuint uName, GLuint vName)
diff --git a/src/monitor/glwidget.h b/src/monitor/glwidget.h
index fac1e40..b7d139b 100644
--- a/src/monitor/glwidget.h
+++ b/src/monitor/glwidget.h
@@ -62,8 +62,11 @@ public:
     void createThread(RenderThread** thread, thread_function_t function, void* \
data);  void startGlsl();
     void stopGlsl();
-    int setProducer(Mlt::Producer*, bool isMulti = false);
-    int reconfigure(bool isMulti);
+    /** @brief Update producer, should ONLY be called from renderer.cpp */
+    int setProducer(Mlt::Producer*, bool reconfig = true);
+    int reconfigureMulti(QString params, QString path, Mlt::Profile *profile);
+    void stopCapture();
+    int reconfigure(Mlt::Profile *profile = NULL);
     void clearFrameRenderer();
 
     int displayWidth() const { return m_rect.width(); }
@@ -84,6 +87,7 @@ public:
     void updateGamma();
     Mlt::Profile *profile();
     void resetProfile(MltVideoProfile profile);
+    void reloadProfile(Mlt::Profile &profile);
 
 protected:
     void mouseReleaseEvent(QMouseEvent * event);
diff --git a/src/monitor/monitor.cpp b/src/monitor/monitor.cpp
index 43c1ebf..f594dc1 100644
--- a/src/monitor/monitor.cpp
+++ b/src/monitor/monitor.cpp
@@ -1010,7 +1010,8 @@ void Monitor::slotLoopClip()
 void Monitor::updateClipProducer(Mlt::Producer *prod)
 {
     if (render == NULL) return;
-    render->setProducer(prod, render->seekFramePosition(), true);
+    render->setProducer(prod, -1, false);
+    prod->set_speed(1.0);
 }
 
 void Monitor::updateClipProducer(const QString &playlist)
@@ -1030,6 +1031,10 @@ void Monitor::openClip(ClipController *controller)
         loadMasterQml();
     }
     if (controller) {
+	if (m_recManager->toolbar()->isVisible()) {
+	      // we are in record mode, don't display clip
+	      return;
+	}
         updateMarkers();
         render->setProducer(m_controller->masterProducer(), -1, isActive());
     }
@@ -1360,6 +1365,11 @@ QString Monitor::getMarkerThumb(GenTime pos)
     return QString();
 }
 
+const QString Monitor::projectFolder() const
+{
+      return m_monitorManager->getProjectFolder();
+}
+
 void Monitor::setPalette ( const QPalette & p)
 {
     QWidget::setPalette(p);
@@ -1482,9 +1492,23 @@ void Monitor::slotSwitchRec(bool enable)
         m_toolbar->setVisible(false);
         m_recManager->toolbar()->setVisible(true);
     }
-    else {
-        m_recManager->stopCapture();
-        m_recManager->toolbar()->setVisible(false);
+    else if (m_recManager->toolbar()->isVisible()) {
+        m_recManager->stop();
         m_toolbar->setVisible(true);
     }
 }
+
+bool Monitor::startCapture(const QString &params, const QString &path, Mlt::Producer \
*p, bool livePreview) +{
+    render->updateProducer(p);
+    m_glMonitor->reconfigureMulti(params, path, p->profile());
+    return true;
+}
+
+bool Monitor::stopCapture()
+{
+    m_glMonitor->stopCapture();
+    openClip(NULL);
+    m_glMonitor->reconfigure(m_monitorManager->profile());
+    return true;
+}
diff --git a/src/monitor/monitor.h b/src/monitor/monitor.h
index 3f1a706..11659ff 100644
--- a/src/monitor/monitor.h
+++ b/src/monitor/monitor.h
@@ -85,6 +85,8 @@ public:
     double fps() const;
     /** @brief Get url for the clip's thumbnail */
     QString getMarkerThumb(GenTime pos);
+    /** @brief Get current project's folder */
+    const QString projectFolder() const;
     /** @brief Get the project's profile info*/
     ProfileInfo profileInfo() const;
     /** @brief Get the project's Mlt profile */
@@ -99,6 +101,8 @@ public:
     void switchDropFrames(bool drop);
     void updateMonitorGamma();
     void mute(bool, bool updateIconOnly = false);
+    bool startCapture(const QString &params, const QString &path, Mlt::Producer *p, \
bool livePreview); +    bool stopCapture();
 
 protected:
     void mousePressEvent(QMouseEvent * event);
diff --git a/src/monitor/recmanager.cpp b/src/monitor/recmanager.cpp
index 66d5f1c..76803b0 100644
--- a/src/monitor/recmanager.cpp
+++ b/src/monitor/recmanager.cpp
@@ -52,6 +52,13 @@ RecManager::RecManager(int iconSize, Monitor *parent) :
     m_recAction = m_recToolbar->addAction(QIcon::fromTheme("media-record"), \
i18n("Record"));  m_recAction->setCheckable(true);
     connect(m_recAction, &QAction::toggled, this, &RecManager::slotRecord);
+    
+    m_recVideo = new QCheckBox(i18n("Video"));
+    m_recAudio = new QCheckBox(i18n("Audio"));
+    m_recToolbar->addWidget(m_recVideo);
+    m_recToolbar->addWidget(m_recAudio);
+    m_recAudio->setChecked(KdenliveSettings::v4l_captureaudio());
+    m_recVideo->setChecked(KdenliveSettings::v4l_capturevideo());
 
     // Check number of monitors for FFmpeg screen capture
     int screens = QApplication::desktop()->screenCount();
@@ -68,8 +75,11 @@ RecManager::RecManager(int iconSize, Monitor *parent) :
     spacer->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
     m_recToolbar->addWidget(spacer);
     m_device_selector = new QComboBox(parent);
-    m_device_selector->addItems(QStringList() << i18n("Firewire") << i18n("Webcam") \
                << i18n("Screen Grab") << i18n("Blackmagic Decklink"));
-    m_device_selector->setCurrentIndex(KdenliveSettings::defaultcapture());
+    //TODO: re-implement firewire / decklink capture
+    //m_device_selector->addItems(QStringList() << i18n("Firewire") << \
i18n("Webcam") << i18n("Screen Grab") << i18n("Blackmagic Decklink")); +    \
m_device_selector->addItem(i18n("Webcam"), Video4Linux);  +    \
m_device_selector->addItem(i18n("Screen Grab"), ScreenGrab); +    \
m_device_selector->setCurrentIndex(m_device_selector->findData(KdenliveSettings::defaultcapture()));
                
     connect(m_device_selector, SIGNAL(currentIndexChanged(int)), this, \
SLOT(slotVideoDeviceChanged(int)));  m_recToolbar->addWidget(m_device_selector);
     QAction *configureRec = m_recToolbar->addAction(QIcon::fromTheme("configure"), \
i18n("Configure Recording")); @@ -79,7 +89,7 @@ RecManager::RecManager(int iconSize, \
Monitor *parent) :  m_switchRec->setCheckable(true);
     connect(m_switchRec, &QAction::toggled, m_monitor, &Monitor::slotSwitchRec);
     m_recToolbar->setVisible(false);
-    slotVideoDeviceChanged(m_device_selector->currentIndex());
+    slotVideoDeviceChanged();
 }
 
 RecManager::~RecManager()
@@ -88,8 +98,7 @@ RecManager::~RecManager()
 
 void RecManager::showRecConfig()
 {
-    qDebug()<<"+ + +SHOW CONFIG + + +";
-    m_monitor->showConfigDialog(4, m_device_selector->currentIndex());
+    m_monitor->showConfigDialog(4, m_device_selector->currentData().toInt());
 }
 
 QToolBar *RecManager::toolbar() const
@@ -109,15 +118,83 @@ void RecManager::stopCapture()
     }
 }
 
+void RecManager::stop()
+{
+      stopCapture();
+      toolbar()->setVisible(false); 
+      m_switchRec->setChecked(false);
+}
+
 
 void RecManager::slotRecord(bool record)
 {
-    if (!record) {
+    if (m_device_selector->currentData().toInt() == Video4Linux) {
+	if (record) {
+	    QDir captureFolder;
+	    if (KdenliveSettings::capturetoprojectfolder()) captureFolder = \
QDir(m_monitor->projectFolder()); +	    else captureFolder = \
QDir(KdenliveSettings::capturefolder()); +	    QString extension;
+	    if (!m_recVideo->isChecked()) extension = "wav";
+            else extension = KdenliveSettings::v4l_extension();
+	    QString path = captureFolder.absoluteFilePath("capture0000." + extension);
+	    int i = 1;
+	    while (QFile::exists(path)) {
+		QString num = QString::number(i).rightJustified(4, '0', false);
+		path = captureFolder.absoluteFilePath("capture" + num + '.' + extension);
+		++i;
+	    }
+	     
+	    QString v4lparameters = KdenliveSettings::v4l_parameters();
+
+            // TODO: when recording audio only, allow param configuration?
+            if (!m_recVideo->isChecked()) {
+		  v4lparameters.clear();
+		  
+	    }
+
+            // Add alsa audio capture
+            if (!m_recAudio->isChecked()) {
+                // if we do not want audio, make sure that we don't have audio \
encoding parameters +                // this is required otherwise the MLT avformat \
consumer will not close properly +                if \
(v4lparameters.contains("acodec")) { +                    QString endParam = \
v4lparameters.section("acodec", 1); +                    int vcodec = \
endParam.indexOf(" vcodec"); +                    int format = endParam.indexOf(" \
f="); +                    int cutPosition = -1;
+                    if (vcodec > -1) {
+                        if (format  > -1) {
+                            cutPosition = qMin(vcodec, format);
+                        }
+                        else cutPosition = vcodec;
+                    }
+                    else if (format  > -1) {
+                        cutPosition = format;
+                    }
+                    else {
+                        // nothing interesting in end params
+                        endParam.clear();
+                    }
+                    if (cutPosition > -1) {
+                        endParam.remove(0, cutPosition);
+                    }
+                    v4lparameters = QString(v4lparameters.section("acodec", 0, 0) + \
"an=1 " + endParam).simplified(); +                }
+            }
+	    m_monitor->startCapture(v4lparameters, path, createV4lProducer(), true);
+	    m_captureFile = QUrl::fromLocalFile(path);
+	}
+	else {
+	    m_monitor->stopCapture();
+	    emit addClipToProject(m_captureFile);
+	}
+	return;
+    }
+     if (!record) {
         if (!m_captureProcess) return;
         m_captureProcess->terminate();
         QTimer::singleShot(1500, m_captureProcess, SLOT(kill()));
         return;
-    }
+    }   
     if (m_captureProcess) return;
     m_recError.clear();
     m_captureProcess = new QProcess;
@@ -207,9 +284,12 @@ void RecManager::slotReadProcessInfo()
 }
 
 
-void RecManager::slotVideoDeviceChanged(int ix)
+void RecManager::slotVideoDeviceChanged(int)
 {
-    switch (ix) {
+    int currentItem = m_device_selector->currentData().toInt();
+    qDebug()<<"// changed to: "<<currentItem;
+    KdenliveSettings::setDefaultcapture(currentItem);
+    switch (currentItem) {
       case Video4Linux:
         m_playAction->setEnabled(true);
         break;
@@ -245,14 +325,52 @@ void RecManager::slotVideoDeviceChanged(int ix)
     */
 }
 
-void RecManager::slotPreview(bool record)
+Mlt::Producer *RecManager::createV4lProducer()
+{
+    QString profilePath = \
QStandardPaths::writableLocation(QStandardPaths::DataLocation) + \
"/profiles/video4linux"; +    Mlt::Profile *vidProfile = new \
Mlt::Profile(profilePath.toUtf8().constData()); +    Mlt::Producer *prod = NULL;
+    if (m_recVideo->isChecked()) {
+	prod = new Mlt::Producer(*vidProfile, \
QString("video4linux2:%1").arg(KdenliveSettings::video4vdevice()).toUtf8().constData());
 +	prod->set("width", vidProfile->width());
+	prod->set("height", vidProfile->height());
+	prod->set("framerate", vidProfile->fps());
+	/*p->set("standard", ui->v4lStandardCombo->currentText().toLatin1().constData());
+	p->set("channel", ui->v4lChannelSpinBox->value());
+	p->set("audio_ix", ui->v4lAudioComboBox->currentIndex());*/
+	prod->set("force_seekable", 0);
+    }
+    if (m_recAudio->isChecked()) {
+	// Add audio track
+	Mlt::Producer* audio = new Mlt::Producer(*vidProfile, \
QString("alsa:%1?channels=%2").arg(KdenliveSettings::v4l_alsadevicename()).arg(KdenliveSettings::alsachannels()).toUtf8().constData());
 +	audio->set("mlt_service", "avformat-novalidate");
+	audio->set("audio_index", 0);
+	audio->set("video_index", -1);
+	if (prod) {
+	    Mlt::Tractor* tractor = new Mlt::Tractor(*vidProfile);
+	    tractor->set_track(*prod, 0);
+	    delete prod;
+	    tractor->set_track(*audio, 1);
+	    delete audio;
+	    prod = new Mlt::Producer(tractor->get_producer());
+	    delete tractor;
+	}
+	else prod = audio;
+    }
+    return prod;
+}
+
+
+void RecManager::slotPreview(bool preview)
 {
-    //TODO:
-    if (m_device_selector->currentIndex() == Video4Linux) {
-        QString path = \
QStandardPaths::writableLocation(QStandardPaths::DataLocation) + \
                "/profiles/video4linux";
-        MltVideoProfile profile = ProfilesDialog::getVideoProfile(path);
-        QString playlist \
=QString("video4linux2:%1?width:%2&amp;height:%3&amp;frame_rate:%4").arg(KdenliveSettings::video4vdevice()).arg(profile.width).arg(profile.height).arg((double) \
                profile.frame_rate_num / profile.frame_rate_den);
-        m_monitor->updateClipProducer(playlist);
+    if (m_device_selector->currentData().toInt() == Video4Linux) {
+	if (preview) {
+	    Mlt::Producer *prod = createV4lProducer();
+	    m_monitor->updateClipProducer(prod);
+	}
+	else {
+	    m_monitor->openClip(NULL);
+	}        
     }
       
       
diff --git a/src/monitor/recmanager.h b/src/monitor/recmanager.h
index c45db21..fa9a218 100644
--- a/src/monitor/recmanager.h
+++ b/src/monitor/recmanager.h
@@ -37,7 +37,11 @@ class Monitor;
 class QAction;
 class QToolBar;
 class QComboBox;
+class QCheckBox;
 
+namespace Mlt {
+    class Producer;
+}
 
 class RecManager : public QObject
 {
@@ -56,6 +60,8 @@ public:
     QToolBar *toolbar() const;
     void stopCapture();
     QAction *switchAction() const;
+    /** @brief: stop capture and hide rec panel **/
+    void stop();
 
 private:
     Monitor *m_monitor;
@@ -69,6 +75,9 @@ private:
     QToolBar *m_recToolbar;
     QComboBox *m_screenCombo;
     QComboBox *m_device_selector;
+    QCheckBox *m_recVideo;
+    QCheckBox *m_recAudio;
+    Mlt::Producer *createV4lProducer();
 
 private slots:
     void slotRecord(bool record);
@@ -76,7 +85,7 @@ private slots:
     void slotProcessStatus(QProcess::ProcessState status);
     void slotReadProcessInfo();
     void showRecConfig();
-    void slotVideoDeviceChanged(int ix);
+    void slotVideoDeviceChanged(int ix = -1);
 
 signals:
     void addClipToProject(QUrl);
diff --git a/src/renderer.cpp b/src/renderer.cpp
index 7c4dc6e..43f264f 100644
--- a/src/renderer.cpp
+++ b/src/renderer.cpp
@@ -1118,6 +1118,39 @@ int Render::setMonitorProducer(const QString &id, int \
position)  return setProducer(prod, position, true);
 }
 
+int Render::updateProducer(Mlt::Producer *producer)
+{
+    if (m_mltProducer) {
+        if (strcmp(m_mltProducer->get("resource"), "<tractor>") == 0) {
+            // We need to make some cleanup
+            Mlt::Tractor trac(*m_mltProducer);
+            for (int i = 0; i < trac.count(); i++) {
+                trac.set_track(*m_blackClip, i);
+            }
+        }
+        delete m_mltProducer;
+        m_mltProducer = NULL;
+    }
+    if (m_mltConsumer) {
+        if (!m_mltConsumer->is_stopped()) {
+            m_mltConsumer->stop();
+        }
+    }
+    if (!producer || !producer->is_valid()) {
+        if (producer) delete producer;
+        producer = m_blackClip->cut(0, 1);
+        producer->set("id", "black");
+	return -1;
+    }
+    m_fps = producer->get_fps();
+    m_mltProducer = producer;
+    if (m_qmlView) {
+        m_qmlView->setProducer(producer, false);
+        m_mltConsumer = m_qmlView->consumer();
+    }
+    return 0;
+}
+
 int Render::setProducer(Mlt::Producer *producer, int position, bool isActive)
 {
     m_refreshTimer.stop();
diff --git a/src/renderer.h b/src/renderer.h
index 8af1007..1705d4d 100644
--- a/src/renderer.h
+++ b/src/renderer.h
@@ -131,6 +131,7 @@ class Render: public AbstractRender
      * Creates the producer from the text playlist. */
     int setSceneList(QString playlist, int position = 0);
     int setMonitorProducer(const QString &id, int position);
+    int updateProducer(Mlt::Producer *producer);
     int setProducer(Mlt::Producer *producer, int position, bool isActive);
 
     /** @brief Get the current MLT producer playlist.


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic