aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-Baptiste Mardelle <[email protected]>2015-07-26 13:03:33 +0200
committerJean-Baptiste Mardelle <[email protected]>2015-07-26 13:03:33 +0200
commita4784c6fed0fb006bca8e92af12a5235e7801eb8 (patch)
tree52add2eb9d6dbf38ae4954b5d6baa09311ad34e8
parente0a58e749f2ae05e516e628d156d0452cbddd7ad (diff)
Fix webcam capture
-rw-r--r--src/monitor/glwidget.cpp149
-rw-r--r--src/monitor/glwidget.h8
-rw-r--r--src/monitor/monitor.cpp32
-rw-r--r--src/monitor/monitor.h4
-rw-r--r--src/monitor/recmanager.cpp150
-rw-r--r--src/monitor/recmanager.h11
-rw-r--r--src/renderer.cpp33
-rw-r--r--src/renderer.h1
8 files changed, 326 insertions, 62 deletions
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.