Breaks Decklink capture for a few days...
svn path=/trunk/kdenlive/; revision=5607
simplekeyframes/simplekeyframewidget.cpp
noteswidget.cpp
archivewidget.cpp
+ mltdevicecapture.cpp
+ abstractmonitor.cpp
)
add_definitions(${KDE4_DEFINITIONS})
${kdenlive_SRCS}
v4l/v4lcapture.cpp
v4l/src.c
- v4l/src_v4l2.c
- v4l/dec_bayer.c
- v4l/dec_grey.c
- v4l/dec_jpeg.c
- v4l/dec_rgb.c
- v4l/dec_s561.c
- v4l/dec_yuv.c
)
endif(NOT APPLE AND NOT CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2011 by Jean-Baptiste Mardelle (jb@kdenlive.org) *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
+ ***************************************************************************/
+
+
+#include "abstractmonitor.h"
+
+
+VideoPreviewContainer::VideoPreviewContainer(QWidget *parent) :
+ QFrame(parent),
+ m_image(new QImage())
+{
+ setFrameShape(QFrame::NoFrame);
+ setFocusPolicy(Qt::ClickFocus);
+ setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
+}
+
+
+void VideoPreviewContainer::setImage(QImage img)
+{
+ if (m_image) delete m_image;
+ m_image = new QImage(img);
+ update();
+}
+
+// virtual
+void VideoPreviewContainer::paintEvent(QPaintEvent */*event*/)
+{
+ if (m_image->isNull()) return;
+ QPainter painter(this);
+ double ar = (double) m_image->width() / m_image->height();
+ QRect rect = this->frameRect();
+ int paintW = rect.height() * ar + 0.5;
+ if (paintW > rect.width()) {
+ paintW = rect.width() / ar + 0.5;
+ int diff = (rect.height() - paintW) / 2;
+ rect.adjust(0, diff, 0, 0);
+ rect.setHeight(paintW);
+ }
+ else {
+ int diff = (rect.width() - paintW) / 2;
+ rect.adjust(diff, 0, 0, 0);
+ rect.setWidth(paintW);
+ }
+
+ painter.drawImage(rect, *m_image);
+}
+
+
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2011 by Jean-Baptiste Mardelle (jb@kdenlive.org) *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
+ ***************************************************************************/
+
+#ifndef ABSTRACTMONITOR_H
+#define ABSTRACTMONITOR_H
+
+#include <QObject>
+#include <QVector>
+#include <QWidget>
+#include <QImage>
+#include <QPainter>
+#include <QFrame>
+
+class VideoPreviewContainer : public QFrame
+{
+ Q_OBJECT
+public:
+ VideoPreviewContainer(QWidget *parent = 0);
+
+ void setImage(QImage img);
+
+protected:
+ virtual void paintEvent(QPaintEvent */*event*/);
+
+private:
+ QImage *m_image;
+};
+
+
+
+class AbstractRender: public QObject
+{
+Q_OBJECT public:
+
+ /** @brief Build an abstract 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). */
+ AbstractRender(QWidget *parent = 0):QObject(parent),sendFrameForAnalysis(false) {};
+
+ /** @brief Destroy the MLT Renderer. */
+ virtual ~AbstractRender() {};
+
+ /** @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;
+
+ /** @brief Someone needs us to send again a frame. */
+ virtual void sendFrameUpdate() = 0;
+
+signals:
+ /** @brief The renderer refreshed the current frame. */
+ void frameUpdated(QImage);
+
+ /** @brief This signal contains the audio of the current frame. */
+ void audioSamplesSignal(QVector<int16_t>, int, int, int);
+};
+
+class AbstractMonitor : public QWidget
+{
+ Q_OBJECT
+public:
+ AbstractMonitor(QWidget *parent = 0): QWidget(parent) {};
+ virtual ~AbstractMonitor() {};
+ virtual AbstractRender *abstractRender() = 0;
+ virtual const QString name() const = 0;
+
+public slots:
+ virtual void stop() = 0;
+ virtual void start() = 0;
+};
+
+#endif
#include "abstractgfxscopewidget.h"
#include "renderer.h"
-#include "monitor.h"
+#include "monitormanager.h"
#include <QFuture>
#include <QColor>
const int REALTIME_FPS = 30;
-AbstractGfxScopeWidget::AbstractGfxScopeWidget(Monitor *projMonitor, Monitor *clipMonitor, bool trackMouse, QWidget *parent) :
+AbstractGfxScopeWidget::AbstractGfxScopeWidget(MonitorManager *manager, bool trackMouse, QWidget *parent) :
AbstractScopeWidget(trackMouse, parent),
- m_projMonitor(projMonitor),
- m_clipMonitor(clipMonitor)
-
+ m_manager(manager)
{
- m_activeRender = (m_clipMonitor->isActive()) ? m_clipMonitor->render : m_projMonitor->render;
+ m_activeRender = m_manager->activeRenderer();
bool b = true;
- b &= connect(m_activeRender, SIGNAL(frameUpdated(QImage)), this, SLOT(slotRenderZoneUpdated(QImage)));
+ if (m_activeRender != NULL)
+ b &= connect(m_activeRender, SIGNAL(frameUpdated(QImage)), this, SLOT(slotRenderZoneUpdated(QImage)));
Q_ASSERT(b);
}
+
AbstractGfxScopeWidget::~AbstractGfxScopeWidget() { }
QImage AbstractGfxScopeWidget::renderScope(uint accelerationFactor)
void AbstractGfxScopeWidget::mouseReleaseEvent(QMouseEvent *event)
{
- if (!m_aAutoRefresh->isChecked()) {
+ if (!m_aAutoRefresh->isChecked() && m_activeRender) {
m_activeRender->sendFrameUpdate();
}
AbstractScopeWidget::mouseReleaseEvent(event);
///// Slots /////
-void AbstractGfxScopeWidget::slotActiveMonitorChanged(bool isClipMonitor)
+void AbstractGfxScopeWidget::slotActiveMonitorChanged()
{
+ if (m_activeRender) {
+ bool b = m_activeRender->disconnect(this);
+ Q_ASSERT(b);
+ }
+
+ m_activeRender = m_manager->activeRenderer();
#ifdef DEBUG_AGSW
- qDebug() << "Active monitor has changed in " << widgetName() << ". Is the clip monitor active now? " << isClipMonitor;
+ qDebug() << "Active monitor has changed in " << widgetName() << ". Is the clip monitor active now? " << m_activeRender->name();
#endif
- bool b = m_activeRender->disconnect(this);
- Q_ASSERT(b);
-
- m_activeRender = (isClipMonitor) ? m_clipMonitor->render : m_projMonitor->render;
-
//b &= connect(m_activeRender, SIGNAL(rendererPosition(int)), this, SLOT(slotRenderZoneUpdated()));
- b &= connect(m_activeRender, SIGNAL(frameUpdated(QImage)), this, SLOT(slotRenderZoneUpdated(QImage)));
- Q_ASSERT(b);
+ if (m_activeRender) {
+ bool b = connect(m_activeRender, SIGNAL(frameUpdated(QImage)), this, SLOT(slotRenderZoneUpdated(QImage)));
+ Q_ASSERT(b);
+ }
// Update the scope for the new monitor.
forceUpdate(true);
void AbstractGfxScopeWidget::slotAutoRefreshToggled(bool autoRefresh)
{
- if (autoRefresh) {
+ if (autoRefresh && m_activeRender) {
m_activeRender->sendFrameUpdate();
}
}
#ifndef ABSTRACTGFXSCOPEWIDGET_H
#define ABSTRACTGFXSCOPEWIDGET_H
-
#include <QtCore>
#include <QWidget>
#include "abstractscopewidget.h"
+#include "renderer.h"
class QMenu;
-class Monitor;
-class Render;
+class MonitorManager;
class AbstractGfxScopeWidget : public AbstractScopeWidget
{
Q_OBJECT
public:
- AbstractGfxScopeWidget(Monitor *projMonitor, Monitor *clipMonitor, bool trackMouse = false, QWidget *parent = 0);
+ AbstractGfxScopeWidget(MonitorManager *manager, bool trackMouse = false, QWidget *parent = 0);
virtual ~AbstractGfxScopeWidget(); // Must be virtual because of inheritance, to avoid memory leaks
protected:
///// Variables /////
- Monitor *m_projMonitor;
- Monitor *m_clipMonitor;
- Render *m_activeRender;
+ MonitorManager *m_manager;
+ AbstractRender *m_activeRender;
/** @brief Scope renderer. Must emit signalScopeRenderingFinished()
when calculation has finished, to allow multi-threading.
/** @brief Must be called when the active monitor has shown a new frame.
This slot must be connected in the implementing class, it is *not*
done in this abstract class. */
- void slotActiveMonitorChanged(bool isClipMonitor);
+ void slotActiveMonitorChanged();
protected slots:
virtual void slotAutoRefreshToggled(bool autoRefresh);
#include "histogram.h"
#include "renderer.h"
-Histogram::Histogram(Monitor *projMonitor, Monitor *clipMonitor, QWidget *parent) :
- AbstractGfxScopeWidget(projMonitor, clipMonitor, false, parent)
+Histogram::Histogram(MonitorManager *manager, QWidget *parent) :
+ AbstractGfxScopeWidget(manager, false, parent)
{
ui = new Ui::Histogram_UI();
ui->setupUi(this);
Q_OBJECT
public:
- Histogram(Monitor *projMonitor, Monitor *clipMonitor, QWidget *parent = 0);
+ Histogram(MonitorManager *manager, QWidget *parent = 0);
~Histogram();
QString widgetName() const;
#include "rgbparade.h"
#include "rgbparadegenerator.h"
-RGBParade::RGBParade(Monitor *projMonitor, Monitor *clipMonitor, QWidget *parent) :
- AbstractGfxScopeWidget(projMonitor, clipMonitor, true, parent)
+RGBParade::RGBParade(MonitorManager *manager, QWidget *parent) :
+ AbstractGfxScopeWidget(manager, true, parent)
{
ui = new Ui::RGBParade_UI();
ui->setupUi(this);
class RGBParade : public AbstractGfxScopeWidget
{
public:
- RGBParade(Monitor *projMonitor, Monitor *clipMonitor, QWidget *parent = 0);
+ RGBParade(MonitorManager *manager, QWidget *parent = 0);
~RGBParade();
QString widgetName() const;
const QPointF YPbPr_Yl(-.5, .081);
-Vectorscope::Vectorscope(Monitor *projMonitor, Monitor *clipMonitor, QWidget *parent) :
- AbstractGfxScopeWidget(projMonitor, clipMonitor, true, parent),
+Vectorscope::Vectorscope(MonitorManager *manager, QWidget *parent) :
+ AbstractGfxScopeWidget(manager, true, parent),
m_gain(1)
{
ui = new Ui::Vectorscope_UI();
Q_OBJECT
public:
- Vectorscope(Monitor *projMonitor, Monitor *clipMonitor, QWidget *parent = 0);
+ Vectorscope(MonitorManager *manager, QWidget *parent = 0);
~Vectorscope();
QString widgetName() const;
const QSize Waveform::m_textWidth(35,0);
const int Waveform::m_paddingBottom(20);
-Waveform::Waveform(Monitor *projMonitor, Monitor *clipMonitor, QWidget *parent) :
- AbstractGfxScopeWidget(projMonitor, clipMonitor, true, parent)
+Waveform::Waveform(MonitorManager *manager, QWidget *parent) :
+ AbstractGfxScopeWidget(manager, true, parent)
,ui(NULL)
{
ui = new Ui::Waveform_UI();
Q_OBJECT
public:
- Waveform(Monitor *projMonitor, Monitor *clipMonitor, QWidget *parent = 0);
+ Waveform(MonitorManager *manager, QWidget *parent = 0);
~Waveform();
virtual QString widgetName() const;
void addProjectClip(DocClipBase *, bool getInfo = true);
void signalDeleteProjectClip(const QString &);
void updateClipDisplay(const QString&);
- void deleteTimelineClip(const QString&);
void progressInfo(const QString &, int);
/** @brief Informs that the document status has been changed.
<default>0</default>
</entry>
- <entry name="video4vformat" type="String">
- <label>Default video4linux capture format.</label>
- <default>video4linux2</default>
- </entry>
-
<entry name="video4vdevice" type="String">
<label>Default video4linux capture format.</label>
<default>/dev/video0</default>
</entry>
- <entry name="video4vcodec" type="String">
- <label>Default video4linux video codec.</label>
- <default>mjpeg</default>
+ <entry name="v4l_alsadevice" type="UInt">
+ <label>Audio device for v4l capture.</label>
+ <default></default>
</entry>
- <entry name="video4acodec" type="String">
- <label>Default video4linux audio codec.</label>
- <default>mp2</default>
+ <entry name="v4l_alsadevicename" type="String">
+ <label>Audio device for v4l capture.</label>
+ <default>hw:0,0</default>
</entry>
- <entry name="video4container" type="String">
+ <entry name="v4l_parameters" type="String">
<label>Default video4linux format.</label>
- <default>avi</default>
+ <default>f=mpeg acodec=mp2 ab=128k ar=48000 vcodec=mpeg2video minrate=0 b=4000k bf=2 b_strategy=1 trellis=1</default>
</entry>
- <entry name="video4extension" type="String">
+ <entry name="v4l_extension" type="String">
<label>Default video4linux file extension.</label>
- <default>avi</default>
- </entry>
-
- <entry name="video4aformat" type="String">
- <label>Default video4linux capture format.</label>
- <default>oss</default>
- </entry>
-
- <entry name="video4adevice" type="String">
- <label>Default video4linux capture format.</label>
- <default>/dev/dsp</default>
+ <default>mpeg</default>
</entry>
- <entry name="video4size" type="String">
- <label>Default video4linux capture format.</label>
- <default>320x240</default>
- </entry>
-
- <entry name="video4rate" type="Int">
- <label>Default video4linux capture format.</label>
- <default>15</default>
- </entry>
-
- <entry name="video4capture" type="String">
- <label>ffmpeg arguments for video capture.</label>
- <default></default>
+ <entry name="v4l_format" type="UInt">
+ <label>Selected capture format.</label>
+ <default>0</default>
</entry>
- <entry name="video4encoding" type="String">
- <label>ffmpeg encoding arguments.</label>
- <default>-qscale 1 -ab 224k</default>
+ <entry name="v4l_captureaudio" type="Bool">
+ <label>Should we also capture audio.</label>
+ <default>false</default>
</entry>
<entry name="rmd_capture_audio" type="Bool">
m_shuttleModified(false),
m_mappable_actions(mappable_actions)
{
-
+ KdenliveSettings::setV4l_format(0);
QWidget *p1 = new QWidget;
m_configMisc.setupUi(p1);
m_page1 = addPage(p1, i18n("Misc"), "configure");
m_configCapture.setupUi(p4);
#if !defined(Q_WS_MAC) && !defined(Q_OS_FREEBSD)
- V4lCaptureHandler v4l(NULL);
+ m_configCapture.kcfg_v4l_parameters->setMaximumHeight(QFontMetrics(font()).lineSpacing() * 4);
+
// Video 4 Linux device detection
for (int i = 0; i < 10; i++) {
QString path = "/dev/video" + QString::number(i);
if (QFile::exists(path)) {
- QStringList deviceInfo = v4l.getDeviceName(path);
+ QStringList deviceInfo = V4lCaptureHandler::getDeviceName(path.toUtf8().constData());
if (!deviceInfo.isEmpty()) {
m_configCapture.kcfg_detectedv4ldevices->addItem(deviceInfo.at(0), path);
m_configCapture.kcfg_detectedv4ldevices->setItemData(m_configCapture.kcfg_detectedv4ldevices->count() - 1, deviceInfo.at(1), Qt::UserRole + 1);
}
}
connect(m_configCapture.kcfg_detectedv4ldevices, SIGNAL(currentIndexChanged(int)), this, SLOT(slotUpdatev4lDevice()));
+ connect(m_configCapture.kcfg_v4l_format, SIGNAL(currentIndexChanged(int)), this, SLOT(slotUpdatev4lCaptureProfile()));
+ connect(m_configCapture.kcfg_v4l_captureaudio, SIGNAL(toggled(bool)), m_configCapture.kcfg_v4l_alsadevice, SLOT(setEnabled(bool)));
+
+ slotUpdatev4lDevice();
#endif
m_page4 = addPage(p4, i18n("Capture"), "media-record");
connect(m_configTranscode.button_delete, SIGNAL(clicked()), this, SLOT(slotDeleteTranscode()));
connect(m_configTranscode.profiles_list, SIGNAL(itemChanged(QTreeWidgetItem *, int)), this, SLOT(slotDialogModified()));
- connect(m_configCapture.kcfg_video4vdevice, SIGNAL(editingFinished()), this, SLOT(rebuildVideo4Commands()));
- connect(m_configCapture.kcfg_video4adevice, SIGNAL(editingFinished()), this, SLOT(rebuildVideo4Commands()));
- connect(m_configCapture.kcfg_video4vcodec, SIGNAL(editingFinished()), this, SLOT(rebuildVideo4Commands()));
- connect(m_configCapture.kcfg_video4acodec, SIGNAL(editingFinished()), this, SLOT(rebuildVideo4Commands()));
- connect(m_configCapture.kcfg_video4vformat, SIGNAL(editingFinished()), this, SLOT(rebuildVideo4Commands()));
- connect(m_configCapture.kcfg_video4aformat, SIGNAL(editingFinished()), this, SLOT(rebuildVideo4Commands()));
- connect(m_configCapture.kcfg_video4size, SIGNAL(editingFinished()), this, SLOT(rebuildVideo4Commands()));
- connect(m_configCapture.kcfg_video4rate, SIGNAL(editingFinished()), this, SLOT(rebuildVideo4Commands()));
-
connect(m_configCapture.kcfg_rmd_capture_audio, SIGNAL(clicked(bool)), m_configCapture.audio_group, SLOT(setVisible(bool)));
m_configCapture.audio_group->setVisible(KdenliveSettings::rmd_capture_audio());
if (line.contains("capture")) {
deviceId = line.section(':', 0, 0);
m_configCapture.kcfg_rmd_alsa_device->addItem(line.section(':', 1, 1), "plughw:" + QString::number(deviceId.section('-', 0, 0).toInt()) + ',' + QString::number(deviceId.section('-', 1, 1).toInt()));
+ m_configCapture.kcfg_v4l_alsadevice->addItem(line.section(':', 1, 1), "hw:" + QString::number(deviceId.section('-', 0, 0).toInt()) + ',' + QString::number(deviceId.section('-', 1, 1).toInt()));
}
}
file.close();
m_configSdl.kcfg_audio_device->setCurrentIndex(ix);
KdenliveSettings::setAudio_device(ix);
}
+
if (!KdenliveSettings::rmd_alsadevicename().isEmpty()) {
// Select correct alsa device
int ix = m_configCapture.kcfg_rmd_alsa_device->findData(KdenliveSettings::rmd_alsadevicename());
m_configCapture.kcfg_rmd_alsa_device->setCurrentIndex(ix);
KdenliveSettings::setRmd_alsa_device(ix);
}
+
+ if (!KdenliveSettings::v4l_alsadevicename().isEmpty()) {
+ // Select correct alsa device
+ int ix = m_configCapture.kcfg_v4l_alsadevice->findData(KdenliveSettings::v4l_alsadevicename());
+ m_configCapture.kcfg_v4l_alsadevice->setCurrentIndex(ix);
+ KdenliveSettings::setV4l_alsadevice(ix);
+ }
+
+ loadCurrentV4lProfileInfo();
}
QString device = data.section(':', 1, 1).section(' ', -1);
m_configSdl.kcfg_audio_device->addItem(data.section(':', -1), "plughw:" + card + ',' + device);
m_configCapture.kcfg_rmd_alsa_device->addItem(data.section(':', -1), "plughw:" + card + ',' + device);
+ m_configCapture.kcfg_v4l_alsadevice->addItem(data.section(':', -1), "hw:" + card + ',' + device);
}
}
}
#endif /* NO_JOGSHUTTLE */
-void KdenliveSettingsDialog::rebuildVideo4Commands()
-{
- QString captureCommand;
- if (!m_configCapture.kcfg_video4adevice->text().isEmpty()) captureCommand = "-f " + m_configCapture.kcfg_video4aformat->text() + " -i " + m_configCapture.kcfg_video4adevice->text() + " -acodec " + m_configCapture.kcfg_video4acodec->text();
-
- captureCommand += " -f " + m_configCapture.kcfg_video4vformat->text() + " -s " + m_configCapture.kcfg_video4size->text() + " -r " + QString::number(m_configCapture.kcfg_video4rate->value()) + " -i " + m_configCapture.kcfg_video4vdevice->text() + " -vcodec " + m_configCapture.kcfg_video4vcodec->text();
- m_configCapture.kcfg_video4capture->setText(captureCommand);
-}
void KdenliveSettingsDialog::updateWidgets()
{
// Revert widgets to last saved state (for example when user pressed "Cancel")
updateCapturePath = true;
}
+ if ((uint) m_configCapture.kcfg_v4l_format->currentIndex() != KdenliveSettings::v4l_format()) {
+ saveCurrentV4lProfile();
+ KdenliveSettings::setV4l_format(0);
+ }
+
+
if (updateCapturePath) emit updateCaptureFolder();
QString value = m_configCapture.kcfg_rmd_alsa_device->itemData(m_configCapture.kcfg_rmd_alsa_device->currentIndex()).toString();
KdenliveSettings::setRmd_alsadevicename(value);
}
+ value = m_configCapture.kcfg_v4l_alsadevice->itemData(m_configCapture.kcfg_v4l_alsadevice->currentIndex()).toString();
+ if (value != KdenliveSettings::v4l_alsadevicename()) {
+ KdenliveSettings::setV4l_alsadevicename(value);
+ }
+
value = m_configCapture.kcfg_rmd_audio_freq->itemText(m_configCapture.kcfg_rmd_audio_freq->currentIndex());
kDebug() << "// AUDIO FREQ VALUE: " << value << ", CURRENT: " << KdenliveSettings::rmd_freq() << ", IX: " << m_configCapture.kcfg_rmd_audio_freq->currentIndex();
if (value != KdenliveSettings::rmd_freq()) {
{
QString device = m_configCapture.kcfg_detectedv4ldevices->itemData(m_configCapture.kcfg_detectedv4ldevices->currentIndex()).toString();
if (!device.isEmpty()) m_configCapture.kcfg_video4vdevice->setText(device);
- QString size = m_configCapture.kcfg_detectedv4ldevices->itemData(m_configCapture.kcfg_detectedv4ldevices->currentIndex(), Qt::UserRole + 1).toString();
- if (!size.isEmpty()) m_configCapture.kcfg_video4size->setText(size);
- rebuildVideo4Commands();
+ QString info = m_configCapture.kcfg_detectedv4ldevices->itemData(m_configCapture.kcfg_detectedv4ldevices->currentIndex(), Qt::UserRole + 1).toString();
+
+ m_configCapture.kcfg_v4l_format->blockSignals(true);
+ m_configCapture.kcfg_v4l_format->clear();
+
+ QString vl4ProfilePath = KStandardDirs::locateLocal("appdata", "profiles/video4linux");
+ if (QFile::exists(vl4ProfilePath)) m_configCapture.kcfg_v4l_format->addItem(i18n("Current settings"));
+
+ QStringList pixelformats = info.split(">", QString::SkipEmptyParts);
+ QString itemSize;
+ QString pixelFormat;
+ QStringList itemRates;
+ for (int i = 0; i < pixelformats.count(); i++) {
+ QString format = pixelformats.at(i).section(':', 0, 0);
+ QStringList sizes = pixelformats.at(i).split(":", QString::SkipEmptyParts);
+ pixelFormat = sizes.takeFirst();
+ for (int j = 0; j < sizes.count(); j++) {
+ itemSize = sizes.at(j).section("=", 0, 0);
+ itemRates = sizes.at(j).section("=", 1, 1).split(",", QString::SkipEmptyParts);
+ for (int k = 0; k < itemRates.count(); k++) {
+ m_configCapture.kcfg_v4l_format->addItem("[" + format + "] " + itemSize + " (" + itemRates.at(k) + ")", QStringList() << format << itemSize.section('x', 0, 0) << itemSize.section('x', 1, 1) << itemRates.at(k).section('/', 0, 0) << itemRates.at(k).section('/', 1, 1));
+ }
+ }
+ }
+ m_configCapture.kcfg_v4l_format->blockSignals(false);
+ slotUpdatev4lCaptureProfile();
}
+void KdenliveSettingsDialog::slotUpdatev4lCaptureProfile()
+{
+ QStringList info = m_configCapture.kcfg_v4l_format->itemData(m_configCapture.kcfg_v4l_format->currentIndex(), Qt::UserRole).toStringList();
+ if (info.isEmpty()) {
+ // No auto info, display the current ones
+ loadCurrentV4lProfileInfo();
+ return;
+ }
+ m_configCapture.p_size->setText(info.at(1) + 'x' + info.at(2));
+ m_configCapture.p_fps->setText(info.at(3) + '/' + info.at(4));
+ m_configCapture.p_aspect->setText("1/1");
+ m_configCapture.p_display->setText(info.at(1) + '/' + info.at(2));
+ m_configCapture.p_colorspace->setText(ProfilesDialog::getColorspaceDescription(601));
+ m_configCapture.p_progressive->setText(i18n("Progressive"));
+
+ QString vl4ProfilePath = KStandardDirs::locateLocal("appdata", "profiles/video4linux");
+ if (!QFile::exists(vl4ProfilePath)) saveCurrentV4lProfile();
+}
+
+void KdenliveSettingsDialog::loadCurrentV4lProfileInfo()
+{
+ QString vl4ProfilePath = KStandardDirs::locateLocal("appdata", "profiles/video4linux");
+ MltVideoProfile prof;
+ if (!QFile::exists(vl4ProfilePath)) {
+ // No default formats found, build one
+ prof.width = 320;
+ prof.height = 200;
+ prof.frame_rate_num = 15;
+ prof.frame_rate_den = 1;
+ prof.display_aspect_num = 4;
+ prof.display_aspect_den = 3;
+ prof.sample_aspect_num = 1;
+ prof.sample_aspect_den = 1;
+ prof.progressive = 1;
+ prof.colorspace = 601;
+ ProfilesDialog::saveProfile(prof, vl4ProfilePath);
+ }
+ else prof = ProfilesDialog::getVideoProfile(vl4ProfilePath);
+ m_configCapture.p_size->setText(QString::number(prof.width) + 'x' + QString::number(prof.height));
+ m_configCapture.p_fps->setText(QString::number(prof.frame_rate_num) + '/' + QString::number(prof.frame_rate_den));
+ m_configCapture.p_aspect->setText(QString::number(prof.sample_aspect_num) + '/' + QString::number(prof.sample_aspect_den));
+ m_configCapture.p_display->setText(QString::number(prof.display_aspect_num) + '/' + QString::number(prof.display_aspect_den));
+ m_configCapture.p_colorspace->setText(ProfilesDialog::getColorspaceDescription(prof.colorspace));
+ if (prof.progressive) m_configCapture.p_progressive->setText(i18n("Progressive"));
+}
+
+void KdenliveSettingsDialog::saveCurrentV4lProfile()
+{
+ MltVideoProfile profile;
+ profile.description = "Video4Linux capture";
+ profile.colorspace = ProfilesDialog::getColorspaceFromDescription(m_configCapture.p_colorspace->text());
+ profile.width = m_configCapture.p_size->text().section('x', 0, 0).toInt();
+ profile.height = m_configCapture.p_size->text().section('x', 1, 1).toInt();
+ profile.sample_aspect_num = m_configCapture.p_aspect->text().section('/', 0, 0).toInt();
+ profile.sample_aspect_den = m_configCapture.p_aspect->text().section('/', 1, 1).toInt();
+ profile.display_aspect_num = m_configCapture.p_display->text().section('/', 0, 0).toInt();
+ profile.display_aspect_den = m_configCapture.p_display->text().section('/', 1, 1).toInt();
+ profile.frame_rate_num = m_configCapture.p_fps->text().section('/', 0, 0).toInt();
+ profile.frame_rate_den = m_configCapture.p_fps->text().section('/', 1, 1).toInt();
+ profile.progressive = m_configCapture.p_progressive->text() == i18n("Progressive");
+ QString vl4ProfilePath = KStandardDirs::locateLocal("appdata", "profiles/video4linux");
+ ProfilesDialog::saveProfile(profile, vl4ProfilePath);
+}
#include "kdenlivesettingsdialog.moc"
private slots:
void slotUpdateDisplay();
- void rebuildVideo4Commands();
#ifndef NO_JOGSHUTTLE
void slotCheckShuttle(int state = 0);
void slotUpdateShuttleDevice(int ix = 0);
void slotEnableCaptureFolder();
void slotUpdateHDMIModes();
void slotUpdatev4lDevice();
+ void slotUpdatev4lCaptureProfile();
private:
KPageWidgetItem *m_page1;
void initDevices();
void loadTranscodeProfiles();
void saveTranscodeProfiles();
+ void loadCurrentV4lProfileInfo();
+ void saveCurrentV4lProfile();
signals:
void customChanged();
KXmlGuiWindow(parent),
m_activeDocument(NULL),
m_activeTimeline(NULL),
+ m_recMonitor(NULL),
m_renderWidget(NULL),
#ifndef NO_JOGSHUTTLE
m_jogProcess(NULL),
#ifndef Q_WS_MAC
m_recMonitorDock = new QDockWidget(i18n("Record Monitor"), this);
m_recMonitorDock->setObjectName("record_monitor");
- m_recMonitor = new RecMonitor("record");
+ m_recMonitor = new RecMonitor("record", m_monitorManager);
m_recMonitorDock->setWidget(m_recMonitor);
connect(m_recMonitor, SIGNAL(addProjectClip(KUrl)), this, SLOT(slotAddProjectClip(KUrl)));
connect(m_recMonitor, SIGNAL(showConfigDialog(int, int)), this, SLOT(slotPreferences(int, int)));
#endif
+ m_monitorManager->initMonitors(m_clipMonitor, m_projectMonitor, m_recMonitor);
m_notesDock = new QDockWidget(i18n("Project Notes"), this);
m_notesDock->setObjectName("notes_widget");
m_effectListDock->setWidget(m_effectList);
addDockWidget(Qt::TopDockWidgetArea, m_effectListDock);
- m_vectorscope = new Vectorscope(m_projectMonitor, m_clipMonitor);
+ m_vectorscope = new Vectorscope(m_monitorManager);
m_vectorscopeDock = new QDockWidget(i18n("Vectorscope"), this);
m_vectorscopeDock->setObjectName(m_vectorscope->widgetName());
m_vectorscopeDock->setWidget(m_vectorscope);
connect(m_vectorscope, SIGNAL(requestAutoRefresh(bool)), this, SLOT(slotUpdateGfxScopeFrameRequest()));
m_gfxScopesList.append(m_vectorscopeDock);
- m_waveform = new Waveform(m_projectMonitor, m_clipMonitor);
+ m_waveform = new Waveform(m_monitorManager);
m_waveformDock = new QDockWidget(i18n("Waveform"), this);
m_waveformDock->setObjectName(m_waveform->widgetName());
m_waveformDock->setWidget(m_waveform);
connect(m_waveform, SIGNAL(requestAutoRefresh(bool)), this, SLOT(slotUpdateGfxScopeFrameRequest()));
m_gfxScopesList.append(m_waveformDock);
- m_RGBParade = new RGBParade(m_projectMonitor, m_clipMonitor);
+ m_RGBParade = new RGBParade(m_monitorManager);
m_RGBParadeDock = new QDockWidget(i18n("RGB Parade"), this);
m_RGBParadeDock->setObjectName(m_RGBParade->widgetName());
m_RGBParadeDock->setWidget(m_RGBParade);
connect(m_RGBParade, SIGNAL(requestAutoRefresh(bool)), this, SLOT(slotUpdateGfxScopeFrameRequest()));
m_gfxScopesList.append(m_RGBParadeDock);
- m_histogram = new Histogram(m_projectMonitor, m_clipMonitor);
+ m_histogram = new Histogram(m_monitorManager);
m_histogramDock = new QDockWidget(i18n("Histogram"), this);
m_histogramDock->setObjectName(m_histogram->widgetName());
m_histogramDock->setWidget(m_histogram);
connect(m_projectMonitorDock, SIGNAL(visibilityChanged(bool)), m_projectMonitor, SLOT(refreshMonitor(bool)));
connect(m_clipMonitorDock, SIGNAL(visibilityChanged(bool)), m_clipMonitor, SLOT(refreshMonitor(bool)));
//connect(m_monitorManager, SIGNAL(connectMonitors()), this, SLOT(slotConnectMonitors()));
- connect(m_monitorManager, SIGNAL(raiseClipMonitor(bool)), this, SLOT(slotRaiseMonitor(bool)));
+ connect(m_monitorManager, SIGNAL(raiseMonitor(AbstractMonitor *)), this, SLOT(slotRaiseMonitor(AbstractMonitor *)));
connect(m_monitorManager, SIGNAL(checkColorScopes()), this, SLOT(slotUpdateColorScopes()));
connect(m_effectList, SIGNAL(addEffect(const QDomElement)), this, SLOT(slotAddEffect(const QDomElement)));
connect(m_effectList, SIGNAL(reloadEffects()), this, SLOT(slotReloadEffects()));
- m_monitorManager->initMonitors(m_clipMonitor, m_projectMonitor);
slotConnectMonitors();
// Open or create a file. Command line argument passed in Url has
else m_activeTimeline->projectView()->slotAddEffect(effectToAdd, GenTime(), -1);
}
-void MainWindow::slotRaiseMonitor(bool clipMonitor)
+void MainWindow::slotRaiseMonitor(AbstractMonitor *monitor)
{
- if (clipMonitor) m_clipMonitorDock->raise();
- else m_projectMonitorDock->raise();
+ if (monitor == m_clipMonitor) m_clipMonitorDock->raise();
+ else if (monitor == m_projectMonitor) m_projectMonitorDock->raise();
}
void MainWindow::slotUpdateClip(const QString &id)
disconnect(m_activeDocument, SIGNAL(signalDeleteProjectClip(const QString &)), this, SLOT(slotDeleteClip(const QString &)));
disconnect(m_activeDocument, SIGNAL(updateClipDisplay(const QString &)), m_projectList, SLOT(slotUpdateClip(const QString &)));
disconnect(m_activeDocument, SIGNAL(selectLastAddedClip(const QString &)), m_projectList, SLOT(slotSelectClip(const QString &)));
- disconnect(m_activeDocument, SIGNAL(deleteTimelineClip(const QString &)), m_activeTimeline, SLOT(slotDeleteClip(const QString &)));
disconnect(m_activeTimeline->projectView(), SIGNAL(clipItemSelected(ClipItem*, int, bool)), m_effectStack, SLOT(slotClipItemSelected(ClipItem*, int)));
disconnect(m_activeTimeline->projectView(), SIGNAL(clipItemSelected(ClipItem*, int, bool)), this, SLOT(slotActivateEffectStackView(ClipItem*, int, bool)));
disconnect(m_activeTimeline->projectView(), SIGNAL(clipItemSelected(ClipItem*, int, bool)), m_projectMonitor, SLOT(slotSetSelectedClip(ClipItem*)));
connect(m_projectList, SIGNAL(findInTimeline(const QString&)), this, SLOT(slotClipInTimeline(const QString&)));
- connect(trackView, SIGNAL(cursorMoved()), m_projectMonitor, SLOT(activateMonitor()));
+ //connect(trackView, SIGNAL(cursorMoved()), m_projectMonitor, SLOT(activateMonitor()));
connect(trackView, SIGNAL(insertTrack(int)), this, SLOT(slotInsertTrack(int)));
connect(trackView, SIGNAL(deleteTrack(int)), this, SLOT(slotDeleteTrack(int)));
connect(trackView, SIGNAL(configTrack(int)), this, SLOT(slotConfigTrack(int)));
connect(doc, SIGNAL(updateClipDisplay(const QString &)), m_projectList, SLOT(slotUpdateClip(const QString &)));
connect(doc, SIGNAL(selectLastAddedClip(const QString &)), m_projectList, SLOT(slotSelectClip(const QString &)));
- connect(doc, SIGNAL(deleteTimelineClip(const QString &)), trackView, SLOT(slotDeleteClip(const QString &)));
connect(doc, SIGNAL(docModified(bool)), this, SLOT(slotUpdateDocumentState(bool)));
connect(doc, SIGNAL(guidesUpdated()), this, SLOT(slotGuidesUpdated()));
connect(m_notesWidget, SIGNAL(textChanged()), doc, SLOT(setModified()));
m_projectMonitor->render->sendFrameForAnalysis = false;
}
m_clipMonitor->render->sendFrameForAnalysis = false;
+ m_recMonitor->analyseFrames(false);
} else {
m_projectMonitor->render->sendFrameForAnalysis = true;
m_clipMonitor->render->sendFrameForAnalysis = true;
+ m_recMonitor->analyseFrames(true);
}
}
void MainWindow::slotUpdateColorScopes()
{
bool request = false;
+ kDebug()<<"// UPDATE SCOPES";
for (int i = 0; i < m_gfxScopesList.count(); i++) {
// Check if we need the renderer to send a new frame for update
if (!m_gfxScopesList.at(i)->widget()->visibleRegion().isEmpty() && !(static_cast<AbstractGfxScopeWidget *>(m_gfxScopesList.at(i)->widget())->autoRefreshEnabled())) request = true;
- static_cast<AbstractGfxScopeWidget *>(m_gfxScopesList.at(i)->widget())->slotActiveMonitorChanged(m_clipMonitor->isActive());
+ static_cast<AbstractGfxScopeWidget *>(m_gfxScopesList.at(i)->widget())->slotActiveMonitorChanged();
}
if (request) {
- if (m_clipMonitor->isActive()) m_clipMonitor->render->sendFrameUpdate();
- else m_projectMonitor->render->sendFrameUpdate();
+ m_monitorManager->activeRenderer()->sendFrameUpdate();
}
}
void MainWindow::slotOpenStopmotion()
{
if (m_stopmotion == NULL) {
- m_stopmotion = new StopmotionWidget(m_activeDocument->projectFolder(), m_stopmotion_actions->actions(), this);
+ m_stopmotion = new StopmotionWidget(m_monitorManager, m_activeDocument->projectFolder(), m_stopmotion_actions->actions(), this);
connect(m_stopmotion, SIGNAL(addOrUpdateSequence(const QString)), m_projectList, SLOT(slotAddOrUpdateSequence(const QString)));
- for (int i = 0; i < m_gfxScopesList.count(); i++) {
+ //for (int i = 0; i < m_gfxScopesList.count(); i++) {
// Check if we need the renderer to send a new frame for update
/*if (!m_scopesList.at(i)->widget()->visibleRegion().isEmpty() && !(static_cast<AbstractScopeWidget *>(m_scopesList.at(i)->widget())->autoRefreshEnabled())) request = true;*/
- connect(m_stopmotion, SIGNAL(gotFrame(QImage)), static_cast<AbstractGfxScopeWidget *>(m_gfxScopesList.at(i)->widget()), SLOT(slotRenderZoneUpdated(QImage)));
+ //connect(m_stopmotion, SIGNAL(gotFrame(QImage)), static_cast<AbstractGfxScopeWidget *>(m_gfxScopesList.at(i)->widget()), SLOT(slotRenderZoneUpdated(QImage)));
//static_cast<AbstractScopeWidget *>(m_scopesList.at(i)->widget())->slotMonitorCapture();
- }
+ //}
}
m_stopmotion->show();
}
/** @brief Reflects setting changes to the GUI. */
void updateConfiguration();
void slotConnectMonitors();
- void slotRaiseMonitor(bool clipMonitor);
+ void slotRaiseMonitor(AbstractMonitor *monitor);
void slotUpdateClip(const QString &id);
void slotUpdateMousePosition(int pos);
void slotAddEffect(const QDomElement effect);
--- /dev/null
+/***************************************************************************
+ mltdevicecapture.cpp - description
+ -------------------
+ begin : Sun May 21 2011
+ copyright : (C) 2011 by Jean-Baptiste Mardelle (jb@kdenlive.org)
+
+***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+
+#include "mltdevicecapture.h"
+#include "kdenlivesettings.h"
+#include "definitions.h"
+//#include "recmonitor.h"
+//#include "renderer.h"
+#include "blackmagic/devices.h"
+
+#include <mlt++/Mlt.h>
+
+#include <KDebug>
+#include <KStandardDirs>
+#include <KMessageBox>
+#include <KLocale>
+#include <KTemporaryFile>
+
+#include <QTimer>
+#include <QDir>
+#include <QString>
+#include <QApplication>
+
+#include <cstdlib>
+#include <cstdarg>
+
+#include <QDebug>
+
+
+
+static void consumer_gl_frame_show(mlt_consumer, MltDeviceCapture * self, mlt_frame frame_ptr)
+{
+ // detect if the producer has finished playing. Is there a better way to do it?
+ Mlt::Frame frame(frame_ptr);
+ self->showFrame(frame);
+}
+
+static void rec_consumer_frame_show(mlt_consumer, MltDeviceCapture * self, mlt_frame frame_ptr)
+{
+ Mlt::Frame frame(frame_ptr);
+ if (!frame.is_valid()) return;
+ self->gotCapturedFrame(frame);
+}
+
+static void rec_consumer_frame_preview(mlt_consumer, MltDeviceCapture * self, mlt_frame frame_ptr)
+{
+ Mlt::Frame frame(frame_ptr);
+ if (!frame.is_valid()) return;
+ if (self->sendFrameForAnalysis && frame_ptr->convert_image) {
+ self->emitFrameUpdated(frame);
+ }
+ if (self->doCapture) {
+ self->doCapture = false;
+ self->saveFrame(frame);
+ }
+
+/* if (self->analyseAudio) {
+ 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) {
+ self->pause();
+ self->emitConsumerStopped();
+ }*/
+}
+
+
+MltDeviceCapture::MltDeviceCapture(QString profile, VideoPreviewContainer *surface, QWidget *parent) :
+ AbstractRender(parent),
+ doCapture(false),
+ sendFrameForAnalysis(false),
+ m_mltConsumer(NULL),
+ m_mltProducer(NULL),
+ m_mltProfile(NULL),
+ m_captureDisplayWidget(surface),
+ m_winid((int) surface->winId()),
+ m_analyseAudio(KdenliveSettings::monitor_audio())
+{
+ if (profile.isEmpty()) profile = KdenliveSettings::current_profile();
+ buildConsumer(profile);
+}
+
+MltDeviceCapture::~MltDeviceCapture()
+{
+ if (m_mltConsumer) delete m_mltConsumer;
+ if (m_mltProducer) delete m_mltProducer;
+ if (m_mltProfile) delete m_mltProfile;
+}
+
+void MltDeviceCapture::buildConsumer(const QString &profileName)
+{
+ if (!profileName.isEmpty()) m_activeProfile = profileName;
+
+ if (m_mltProfile) delete m_mltProfile;
+
+ char *tmp = qstrdup(m_activeProfile.toUtf8().constData());
+ setenv("MLT_PROFILE", tmp, 1);
+ m_mltProfile = new Mlt::Profile(tmp);
+ m_mltProfile->get_profile()->is_explicit = 1;
+ delete[] tmp;
+
+ QString videoDriver = KdenliveSettings::videodrivername();
+ if (!videoDriver.isEmpty()) {
+ if (videoDriver == "x11_noaccel") {
+ setenv("SDL_VIDEO_YUV_HWACCEL", "0", 1);
+ videoDriver = "x11";
+ } else {
+ unsetenv("SDL_VIDEO_YUV_HWACCEL");
+ }
+ }
+ setenv("SDL_VIDEO_ALLOW_SCREENSAVER", "1", 1);
+
+ 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");
+ m_mltConsumer->set("window_id", m_winid);
+ }
+ m_mltConsumer->set("resize", 1);
+ //m_mltConsumer->set("terminate_on_pause", 1);
+ m_mltConsumer->set("window_background", KdenliveSettings::window_background().name().toUtf8().constData());
+ m_mltConsumer->set("rescale", "nearest");
+
+ m_mltConsumer->listen("consumer-frame-show", this, (mlt_listener) rec_consumer_frame_preview);
+
+ QString audioDevice = KdenliveSettings::audiodevicename();
+ if (!audioDevice.isEmpty())
+ m_mltConsumer->set("audio_device", audioDevice.toUtf8().constData());
+
+ if (!videoDriver.isEmpty())
+ m_mltConsumer->set("video_driver", videoDriver.toUtf8().constData());
+
+ QString audioDriver = KdenliveSettings::audiodrivername();
+
+ if (!audioDriver.isEmpty())
+ m_mltConsumer->set("audio_driver", audioDriver.toUtf8().constData());
+
+ //m_mltConsumer->set("progressive", 1);
+ //m_mltConsumer->set("buffer", 1);
+ //m_mltConsumer->set("real_time", 0);
+}
+
+void MltDeviceCapture::stop()
+{
+ if (m_mltConsumer) {
+ m_mltConsumer->stop();
+ //if (!m_mltConsumer->is_stopped()) m_mltConsumer->stop();
+ delete m_mltConsumer;
+ m_mltConsumer = NULL;
+ }
+ kDebug()<<"STOPPING cap";
+ if (m_mltProducer) {
+ QList <Mlt::Producer *> prods;
+ Mlt::Service service(m_mltProducer->parent().get_service());
+ mlt_service_lock(service.get_service());
+kDebug()<<"STOPPING cap 2";
+ if (service.type() == tractor_type) {
+ kDebug()<<"STOPPING cap 3";
+ Mlt::Tractor tractor(service);
+ mlt_tractor_close(tractor.get_tractor());
+ Mlt::Field *field = tractor.field();
+ mlt_service nextservice = mlt_service_get_producer(service.get_service());
+ mlt_service nextservicetodisconnect;
+ mlt_properties properties = MLT_SERVICE_PROPERTIES(nextservice);
+ QString mlt_type = mlt_properties_get(properties, "mlt_type");
+ QString resource = mlt_properties_get(properties, "mlt_service");
+ // Delete all transitions
+ while (mlt_type == "transition") {
+ nextservicetodisconnect = nextservice;
+ nextservice = mlt_service_producer(nextservice);
+ mlt_field_disconnect_service(field->get_field(), nextservicetodisconnect);
+ if (nextservice == NULL) break;
+ properties = MLT_SERVICE_PROPERTIES(nextservice);
+ mlt_type = mlt_properties_get(properties, "mlt_type");
+ resource = mlt_properties_get(properties, "mlt_service");
+ }
+ for (int trackNb = tractor.count() - 1; trackNb >= 0; --trackNb) {
+ Mlt::Producer trackProducer(tractor.track(trackNb));
+ Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
+ if (trackPlaylist.type() == playlist_type) {
+ for (int i = 0; i < trackPlaylist.count();i++) {
+ // We need to manually decrease the ref count and close the producer, otherwise
+ // the video4linux device stays open, seems like a bug in MLT that is not cleaning properly
+ mlt_properties props = MLT_PRODUCER_PROPERTIES(trackPlaylist.get_clip(i)->get_parent());
+ while (mlt_properties_ref_count(props) > 0) mlt_properties_dec_ref(props);
+ mlt_producer_close(trackPlaylist.get_clip(i)->get_parent());
+ }
+ mlt_playlist_close(trackPlaylist.get_playlist());
+ //trackPlaylist.clear();
+ }
+ }
+ delete field;
+ field = NULL;
+ }
+ mlt_service_unlock(service.get_service());
+ delete m_mltProducer;
+ kDebug()<<"/// STOP REC PROD";
+ m_mltProducer = NULL;
+ }
+}
+
+
+void MltDeviceCapture::doRefresh()
+{
+ if (m_mltConsumer) m_mltConsumer->set("refresh", 1);
+}
+
+
+void MltDeviceCapture::emitFrameUpdated(Mlt::Frame& frame)
+{
+ mlt_image_format format = mlt_image_rgb24a;
+ int width = 0;
+ int height = 0;
+ const uchar* image = frame.get_image(format, width, height);
+ QImage qimage(width, height, QImage::Format_ARGB32);
+ memcpy(qimage.bits(), image, width * height * 4);
+ emit frameUpdated(qimage.rgbSwapped());
+}
+
+void MltDeviceCapture::showFrame(Mlt::Frame& frame)
+{
+ mlt_image_format format = mlt_image_rgb24a;
+ int width = 0;
+ int height = 0;
+ const uchar* image = frame.get_image(format, width, height);
+ QImage qimage(width, height, QImage::Format_ARGB32_Premultiplied);
+ memcpy(qimage.scanLine(0), image, width * height * 4);
+ emit showImageSignal(qimage);
+ if (m_analyseAudio) showAudio(frame);
+ if (sendFrameForAnalysis && frame.get_frame()->convert_image) {
+ emit frameUpdated(qimage.rgbSwapped());
+ }
+}
+
+void MltDeviceCapture::showAudio(Mlt::Frame& frame)
+{
+ if (!frame.is_valid() || frame.get_int("test_audio") != 0) {
+ return;
+ }
+ mlt_audio_format audio_format = mlt_audio_s16;
+ int freq = 0;
+ int num_channels = 0;
+ int samples = 0;
+ int16_t* data = (int16_t*)frame.get_audio(audio_format, freq, num_channels, samples);
+
+ if (!data) {
+ return;
+ }
+
+ // Data format: [ c00 c10 c01 c11 c02 c12 c03 c13 ... c0{samples-1} c1{samples-1} for 2 channels.
+ // So the vector is of size samples*channels.
+ QVector<int16_t> sampleVector(samples*num_channels);
+ memcpy(sampleVector.data(), data, samples*num_channels*sizeof(int16_t));
+
+ if (samples > 0) {
+ emit audioSamplesSignal(sampleVector, freq, num_channels, samples);
+ }
+}
+
+bool MltDeviceCapture::slotStartPreview(const QString &producer)
+{
+ //stop();
+ if (m_mltConsumer == NULL) buildConsumer();
+ /*if (m_mltConsumer) delete m_mltConsumer;
+ if (m_mltProducer) delete m_mltProducer;
+ if (m_mltProfile) delete m_mltProfile;
+
+ char *tmp = qstrdup(m_activeProfile.toUtf8().constData());
+ setenv("MLT_PROFILE", tmp, 1);
+ m_mltProfile = new Mlt::Profile(tmp);
+ delete[] tmp;
+ m_mltProfile->get_profile()->is_explicit = 1;
+
+ m_mltConsumer = new Mlt::Consumer(*m_mltProfile, "sdl_preview");
+
+ m_mltConsumer->set("window_id", m_winid);
+ m_mltConsumer->set("real_time", 0);
+// m_mltConsumer->set("buffer", 1);
+ m_mltConsumer->set("resize", 1);
+ m_mltConsumer->set("progressive", 1);
+ m_mltConsumer->set("rescale", "nearest");*/
+
+ //char *tmp = qstrdup(QString("avformat-novalidate:video4linux2:%1?frame_rate:%2&width:%3&height:%4").arg(KdenliveSettings::video4vdevice()).arg(m_mltProfile->fps()).arg(m_mltProfile->width()).arg(m_mltProfile->height()).toUtf8().constData());
+
+ char *tmp = qstrdup(producer.toUtf8().constData());
+
+ m_mltProducer = new Mlt::Producer(*m_mltProfile, tmp);
+ delete[] tmp;
+ if (m_mltProducer == NULL || !m_mltProducer->is_valid()) {
+ kDebug()<<"//// ERROR CREATRING PROD";
+ return false;
+ }
+ m_mltConsumer->connect(*m_mltProducer);
+ if (m_mltConsumer->start() == -1) {
+ delete m_mltConsumer;
+ m_mltConsumer = NULL;
+ return 0;
+ }
+ return 1;
+}
+
+void MltDeviceCapture::gotCapturedFrame(Mlt::Frame& frame)
+{
+ mlt_image_format format = mlt_image_rgb24a;
+ int width = 0;
+ int height = 0;
+ const uchar* image = frame.get_image(format, width, height);
+ QImage qimage(width, height, QImage::Format_ARGB32);
+ memcpy(qimage.bits(), image, width * height * 4);
+ m_captureDisplayWidget->setImage(qimage.rgbSwapped());
+}
+
+void MltDeviceCapture::saveFrame(Mlt::Frame& frame)
+{
+ mlt_image_format format = mlt_image_rgb24a;
+ int width = 0;
+ int height = 0;
+ const uchar* image = frame.get_image(format, width, height);
+ QImage qimage(width, height, QImage::Format_ARGB32);
+ memcpy(qimage.bits(), image, width * height * 4);
+ qimage.rgbSwapped().save(m_capturePath);
+ emit frameSaved(m_capturePath);
+ m_capturePath.clear();
+}
+
+void MltDeviceCapture::captureFrame(const QString &path)
+{
+ m_capturePath = path;
+ doCapture = true;
+}
+
+bool MltDeviceCapture::slotStartCapture(const QString ¶ms, const QString &path, const QString &playlist)
+{
+ stop();
+ if (m_mltProfile) delete m_mltProfile;
+ char *tmp = qstrdup(m_activeProfile.toUtf8().constData());
+ m_mltProfile = new Mlt::Profile(tmp);
+ delete[] tmp;
+ m_mltProfile->get_profile()->is_explicit = 1;
+ kDebug()<<"-- CREATING CAP: "<<params<<", PATH: "<<path;
+ tmp = qstrdup(QString("avformat:" + path).toUtf8().constData());
+ m_mltConsumer = new Mlt::Consumer(*m_mltProfile, tmp);
+ m_mltConsumer->set("terminate_on_pause", 1);
+ delete[] tmp;
+
+ QStringList paramList = params.split(" ", QString::SkipEmptyParts);
+ char *tmp2;
+ for (int i = 0; i < paramList.count(); i++) {
+ tmp = qstrdup(paramList.at(i).section("=", 0, 0).toUtf8().constData());
+ tmp2 = qstrdup(paramList.at(i).section("=", 1, 1).toUtf8().constData());
+ m_mltConsumer->set(tmp, tmp2);
+ delete[] tmp;
+ delete[] tmp2;
+ }
+
+ if (m_mltConsumer == NULL || !m_mltConsumer->is_valid()) {
+ if (m_mltConsumer) {
+ delete m_mltConsumer;
+ m_mltConsumer = NULL;
+ }
+ return false;
+ }
+
+ // FIXME: the event object returned by the listen gets leaked...
+ m_mltConsumer->listen("consumer-frame-show", this, (mlt_listener) rec_consumer_frame_show);
+
+ //tmp = qstrdup(QString("avformat-novalidate:video4linux2:%1?frame_rate:%2&width:%3&height:%4").arg(KdenliveSettings::video4vdevice()).arg(m_mltProfile->fps()).arg(m_mltProfile->width()).arg(m_mltProfile->height()).toUtf8().constData());
+ tmp = qstrdup(playlist.toUtf8().constData());
+ m_mltProducer = new Mlt::Producer(*m_mltProfile, "xml-string", tmp);
+ delete[] tmp;
+
+ if (m_mltProducer == NULL || !m_mltProducer->is_valid()) {
+ kDebug()<<"//// ERROR CREATRING PROD";
+ return false;
+ }
+
+ m_mltConsumer->connect(*m_mltProducer);
+ if (m_mltConsumer->start() == -1) {
+ delete m_mltConsumer;
+ m_mltConsumer = NULL;
+ return 0;
+ }
+ return 1;
+}
+
+
--- /dev/null
+/***************************************************************************
+ mltdevicecapture.h - description
+ -------------------
+ begin : Sun May 21 2011
+ copyright : (C) 2011 by Jean-Baptiste Mardelle (jb@kdenlive.org)
+
+***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+/**
+ * @class MltDeviceCapture
+ * @brief Interface for MLT capture.
+ */
+
+#ifndef MLTDEVICECAPTURE_H
+#define MLTDEVICECAPTURE_H
+
+#include "gentime.h"
+#include "definitions.h"
+#include "abstractmonitor.h"
+#include "mlt/framework/mlt_types.h"
+
+namespace Mlt
+{
+class Consumer;
+class Playlist;
+class Tractor;
+class Transition;
+class Frame;
+class Field;
+class Producer;
+class Filter;
+class Profile;
+class Service;
+};
+
+class MltDeviceCapture: public AbstractRender
+{
+Q_OBJECT public:
+
+ enum FailStates { OK = 0,
+ APP_NOEXIST
+ };
+ /** @brief Build a MLT 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 capture (default one will be used if empty). */
+ MltDeviceCapture(QString profile, VideoPreviewContainer *surface, QWidget *parent = 0);
+
+ /** @brief Destroy the MLT Renderer. */
+ ~MltDeviceCapture();
+
+ bool doCapture;
+
+ /** @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;
+
+ /** @brief Someone needs us to send again a frame. */
+ void sendFrameUpdate() {};
+
+ void emitFrameUpdated(Mlt::Frame&);
+ void emitFrameNumber(double position);
+ void emitConsumerStopped();
+ void showFrame(Mlt::Frame&);
+ void showAudio(Mlt::Frame&);
+
+ void saveFrame(Mlt::Frame& frame);
+
+ /** @brief Starts the MLT Video4Linux process.
+ * @param surface The widget onto which the frame should be painted
+ */
+ bool slotStartCapture(const QString ¶ms, const QString &path, const QString &playlist);
+ bool slotStartPreview(const QString &producer);
+ /** @brief A frame arrived from the MLT Video4Linux process. */
+ void gotCapturedFrame(Mlt::Frame& frame);
+ /** @brief Save current frame to file. */
+ void captureFrame(const QString &path);
+ void doRefresh();
+
+private:
+ Mlt::Consumer * m_mltConsumer;
+ Mlt::Producer * m_mltProducer;
+ Mlt::Profile *m_mltProfile;
+ QString m_activeProfile;
+
+ /** @brief The surface onto which the captured frames should be painted. */
+ VideoPreviewContainer *m_captureDisplayWidget;
+
+ /** @brief A human-readable description of this renderer. */
+ int m_winid;
+
+ /** @brief This property is used to decide if the renderer should send audio data for monitoring. */
+ bool m_analyseAudio;
+
+ QString m_capturePath;
+
+ /** @brief Build the MLT Consumer object with initial settings.
+ * @param profileName The MLT profile to use for the consumer */
+ void buildConsumer(const QString &profileName = QString());
+
+private slots:
+
+signals:
+ /** @brief A frame's image has to be shown.
+ *
+ * Used in Mac OS X. */
+ void showImageSignal(QImage);
+
+ /** @brief This signal contains the audio of the current frame. */
+ void audioSamplesSignal(const QVector<int16_t>&, int freq, int num_channels, int num_samples);
+
+ void frameSaved(const QString);
+
+public slots:
+
+ /** @brief Stops the consumer. */
+ void stop();
+};
+
+#endif
#include "monitor.h"
-#include "renderer.h"
-#include "monitormanager.h"
#include "smallruler.h"
#include "docclipbase.h"
#include "abstractclipitem.h"
Monitor::Monitor(QString name, MonitorManager *manager, QString profile, QWidget *parent) :
- QWidget(parent),
+ AbstractMonitor(parent),
render(NULL),
m_name(name),
m_monitorManager(manager),
m_currentClip(NULL),
m_ruler(new SmallRuler(m_monitorManager)),
m_overlay(NULL),
- m_isActive(false),
m_scale(1),
m_length(0),
m_dragStarted(false),
connect(render, SIGNAL(durationChanged(int)), this, SLOT(adjustRulerSize(int)));
connect(render, SIGNAL(rendererStopped(int)), this, SLOT(rendererStopped(int)));
- //render->createVideoXWindow(m_ui.video_frame->winId(), -1);
-
if (name != "clip") {
connect(render, SIGNAL(rendererPosition(int)), this, SIGNAL(renderPosition(int)));
connect(render, SIGNAL(durationChanged(int)), this, SIGNAL(durationChanged(int)));
return m_videoBox;
}
-QString Monitor::name() const
+const QString Monitor::name() const
{
return m_name;
}
bool Monitor::isActive() const
{
- return m_isActive;
+ return m_monitorManager->isActive(m_name);
}
void Monitor::activateMonitor()
{
- if (!m_isActive) {
- m_monitorManager->slotSwitchMonitors(m_name == "clip");
- }
+ m_monitorManager->activateMonitor(m_name);
}
void Monitor::setTimePos(const QString &pos)
void Monitor::slotSeek(int pos)
{
- activateMonitor();
+ //activateMonitor();
if (render == NULL) return;
render->seekToFrame(pos);
}
void Monitor::seekCursor(int pos)
{
- activateMonitor();
+ //activateMonitor();
if (m_ruler->slotNewValue(pos)) {
checkOverlay();
m_timePos->setValue(pos);
void Monitor::stop()
{
- m_isActive = false;
disconnect(render, SIGNAL(rendererPosition(int)), this, SLOT(seekCursor(int)));
if (render) render->stop();
}
void Monitor::start()
{
- m_isActive = true;
if (render) render->start();
connect(render, SIGNAL(rendererPosition(int)), this, SLOT(seekCursor(int)));
}
void Monitor::refreshMonitor(bool visible)
{
- if (visible && render && !m_isActive) {
+ if (visible && render) {
activateMonitor();
render->doRefresh(); //askForRefresh();
}
void Monitor::refreshMonitor()
{
- if (m_isActive) {
+ if (isActive()) {
render->doRefresh();
}
}
m_volumePopup->show();
}
+AbstractRender *Monitor::abstractRender()
+{
+ return render;
+}
+
MonitorRefresh::MonitorRefresh(QWidget* parent) :
QWidget(parent)
, m_renderer(NULL)
#include "gentime.h"
+#include "renderer.h"
#include "timecodedisplay.h"
+#include "abstractmonitor.h"
#if defined(Q_WS_MAC) || defined(USE_OPEN_GL)
#include "videoglwidget.h"
#endif
#include <KAction>
#include <KRestrictedLine>
-
-class MonitorManager;
-class Render;
class SmallRuler;
class DocClipBase;
class AbstractClipItem;
class Transition;
class ClipItem;
class MonitorEditWidget;
-
class Monitor;
+class MonitorManager;
class VideoContainer : public QFrame
{
void editMarker();
};
-class Monitor : public QWidget
+class Monitor : public AbstractMonitor
{
Q_OBJECT
public:
Monitor(QString name, MonitorManager *manager, QString profile = QString(), QWidget *parent = 0);
- virtual ~Monitor();
+ ~Monitor();
Render *render;
+ AbstractRender *abstractRender();
void resetProfile(const QString profile);
- QString name() const;
+ const QString name() const;
void resetSize();
bool isActive() const;
void pause();
DocClipBase *m_currentClip;
SmallRuler *m_ruler;
Overlay *m_overlay;
- bool m_isActive;
double m_scale;
int m_length;
bool m_dragStarted;
QObject(parent),
m_clipMonitor(NULL),
m_projectMonitor(NULL),
+ m_activeMonitor(NULL),
m_blocked(false)
{
}
return m_timecode;
}
-void MonitorManager::initMonitors(Monitor *clipMonitor, Monitor *projectMonitor)
+void MonitorManager::initMonitors(Monitor *clipMonitor, Monitor *projectMonitor, RecMonitor *recMonitor)
{
m_clipMonitor = clipMonitor;
m_projectMonitor = projectMonitor;
+
+ m_monitorsList.append(clipMonitor);
+ m_monitorsList.append(projectMonitor);
+ m_monitorsList.append(recMonitor);
+}
+
+void MonitorManager::appendMonitor(AbstractMonitor *monitor)
+{
+ if (!m_monitorsList.contains(monitor)) m_monitorsList.append(monitor);
+}
+
+void MonitorManager::removeMonitor(AbstractMonitor *monitor)
+{
+ m_monitorsList.removeAll(monitor);
}
void MonitorManager::activateMonitor(QString name)
{
+ kDebug()<<"//ACTIVATING MON: "<<name;
if (m_blocked || m_clipMonitor == NULL || m_projectMonitor == NULL)
return;
- if (m_activeMonitor == name)
+ if (m_activeMonitor && m_activeMonitor->name() == name)
return;
- if (name == "clip") {
- m_projectMonitor->stop();
- m_clipMonitor->start();
- emit raiseClipMonitor(true);
- } else {
- m_clipMonitor->stop();
- m_projectMonitor->start();
- emit raiseClipMonitor(false);
+ m_activeMonitor = NULL;
+ for (int i = 0; i < m_monitorsList.count(); i++) {
+ kDebug()<<"PARSING: "<<m_monitorsList.at(i)->name();
+ if (m_monitorsList.at(i)->name() == name) {
+ m_activeMonitor = m_monitorsList.at(i);
+ emit raiseMonitor(m_activeMonitor);
+ }
+ else m_monitorsList.at(i)->stop();
}
- m_activeMonitor = name;
+ if (m_activeMonitor) m_activeMonitor->start();
emit checkColorScopes();
}
+bool MonitorManager::isActive(const QString name) const
+{
+ return m_activeMonitor ? m_activeMonitor->name() == name: false;
+}
+
void MonitorManager::slotSwitchMonitors(bool activateClip)
{
if (activateClip)
void MonitorManager::stopActiveMonitor()
{
if (m_blocked) return;
- if (m_clipMonitor->isActive()) m_clipMonitor->pause();
+ if (m_activeMonitor == m_clipMonitor) m_clipMonitor->pause();
else m_projectMonitor->pause();
}
void MonitorManager::slotPlay()
{
- if (m_clipMonitor->isActive()) m_clipMonitor->slotPlay();
+ if (m_activeMonitor == m_clipMonitor) m_clipMonitor->slotPlay();
else m_projectMonitor->slotPlay();
}
void MonitorManager::slotPause()
{
- stopActiveMonitor();
+ stopActiveMonitor();
}
void MonitorManager::slotPlayZone()
{
- if (m_clipMonitor->isActive()) m_clipMonitor->slotPlayZone();
+ if (m_activeMonitor == m_clipMonitor) m_clipMonitor->slotPlayZone();
else m_projectMonitor->slotPlayZone();
}
void MonitorManager::slotLoopZone()
{
- if (m_clipMonitor->isActive()) m_clipMonitor->slotLoopZone();
+ if (m_activeMonitor == m_clipMonitor) m_clipMonitor->slotLoopZone();
else m_projectMonitor->slotLoopZone();
}
void MonitorManager::slotRewind(double speed)
{
- if (m_clipMonitor->isActive()) m_clipMonitor->slotRewind(speed);
+ if (m_activeMonitor == m_clipMonitor) m_clipMonitor->slotRewind(speed);
else m_projectMonitor->slotRewind(speed);
}
void MonitorManager::slotForward(double speed)
{
- if (m_clipMonitor->isActive()) m_clipMonitor->slotForward(speed);
+ if (m_activeMonitor == m_clipMonitor) m_clipMonitor->slotForward(speed);
else m_projectMonitor->slotForward(speed);
}
void MonitorManager::slotRewindOneFrame()
{
- if (m_clipMonitor->isActive()) m_clipMonitor->slotRewindOneFrame();
+ if (m_activeMonitor == m_clipMonitor) m_clipMonitor->slotRewindOneFrame();
else m_projectMonitor->slotRewindOneFrame();
}
void MonitorManager::slotForwardOneFrame()
{
- if (m_clipMonitor->isActive()) m_clipMonitor->slotForwardOneFrame();
+ if (m_activeMonitor == m_clipMonitor) m_clipMonitor->slotForwardOneFrame();
else m_projectMonitor->slotForwardOneFrame();
}
void MonitorManager::slotRewindOneSecond()
{
- if (m_clipMonitor->isActive()) m_clipMonitor->slotRewindOneFrame(m_timecode.fps());
+ if (m_activeMonitor == m_clipMonitor) m_clipMonitor->slotRewindOneFrame(m_timecode.fps());
else m_projectMonitor->slotRewindOneFrame(m_timecode.fps());
}
void MonitorManager::slotForwardOneSecond()
{
- if (m_clipMonitor->isActive()) m_clipMonitor->slotForwardOneFrame(m_timecode.fps());
+ if (m_activeMonitor == m_clipMonitor) m_clipMonitor->slotForwardOneFrame(m_timecode.fps());
else m_projectMonitor->slotForwardOneFrame(m_timecode.fps());
}
void MonitorManager::slotStart()
{
- if (m_clipMonitor->isActive()) m_clipMonitor->slotStart();
+ if (m_activeMonitor == m_clipMonitor) m_clipMonitor->slotStart();
else m_projectMonitor->slotStart();
}
void MonitorManager::slotEnd()
{
- if (m_clipMonitor->isActive()) m_clipMonitor->slotEnd();
+ if (m_activeMonitor == m_clipMonitor) m_clipMonitor->slotEnd();
else m_projectMonitor->slotEnd();
}
{
if (m_blocked) return;
if (m_projectMonitor == NULL || m_clipMonitor == NULL) return;
- QString active = m_activeMonitor;
+ QString active = m_activeMonitor ? m_activeMonitor->name() : QString();
activateMonitor("clip");
m_clipMonitor->resetProfile(KdenliveSettings::current_profile());
m_clipMonitor->updateTimecodeFormat();
m_projectMonitor->resetProfile(KdenliveSettings::current_profile());
m_projectMonitor->updateTimecodeFormat();
//m_projectMonitor->refreshMonitor(true);
- activateMonitor(active);
+ if (!active.isEmpty()) activateMonitor(active);
}
void MonitorManager::slotRefreshCurrentMonitor()
{
- if (m_clipMonitor->isActive()) m_clipMonitor->refreshMonitor();
+ if (m_activeMonitor == m_clipMonitor) m_clipMonitor->refreshMonitor();
else m_projectMonitor->refreshMonitor();
}
}
}
+void MonitorManager::updateScopeSource()
+{
+ emit checkColorScopes();
+}
+
+AbstractRender *MonitorManager::activeRenderer()
+{
+ if (m_activeMonitor) return m_activeMonitor->abstractRender();
+ return NULL;
+}
+
#include "monitormanager.moc"
#define MONITORMANAGER_H
#include "monitor.h"
+#include "recmonitor.h"
#include "timecode.h"
-class Monitor;
class MonitorManager : public QObject
{
public:
MonitorManager(QWidget *parent = 0);
- void initMonitors(Monitor *clipMonitor, Monitor *projectMonitor);
+ void initMonitors(Monitor *clipMonitor, Monitor *projectMonitor, RecMonitor *recMonitor);
+ void appendMonitor(AbstractMonitor *monitor);
+ void removeMonitor(AbstractMonitor *monitor);
Timecode timecode();
void resetProfiles(Timecode tc);
void stopActiveMonitor();
+ AbstractRender *activeRenderer();
+ void updateScopeSource();
public slots:
/** @brief Activates a monitor.
* @param name name of the monitor to activate */
void activateMonitor(QString name = QString());
+ bool isActive(const QString name) const;
void slotPlay();
void slotPause();
void slotPlayZone();
private:
Monitor *m_clipMonitor;
Monitor *m_projectMonitor;
- QString m_activeMonitor;
Timecode m_timecode;
+ AbstractMonitor *m_activeMonitor;
bool m_blocked;
+ QList <AbstractMonitor *>m_monitorsList;
signals:
/** @brief Emitted when the active monitor changes */
- void raiseClipMonitor(bool);
+ void raiseMonitor(AbstractMonitor *);
/** @brief When the monitor changed, update the visible color scopes */
void checkColorScopes();
}
// static
-void ProfilesDialog::saveProfile(MltVideoProfile &profile)
+void ProfilesDialog::saveProfile(MltVideoProfile &profile, QString profilePath)
{
- int i = 0;
- QString customName = "profiles/customprofile";
- QString profilePath = KStandardDirs::locateLocal("appdata", customName + QString::number(i));
- kDebug() << " TYING PROFILE FILE: " << profilePath;
- while (KIO::NetAccess::exists(KUrl(profilePath), KIO::NetAccess::SourceSide, 0)) {
- i++;
+ if (profilePath.isEmpty()) {
+ int i = 0;
+ QString customName = "profiles/customprofile";
profilePath = KStandardDirs::locateLocal("appdata", customName + QString::number(i));
+ kDebug() << " TYING PROFILE FILE: " << profilePath;
+ while (KIO::NetAccess::exists(KUrl(profilePath), KIO::NetAccess::SourceSide, 0)) {
+ i++;
+ profilePath = KStandardDirs::locateLocal("appdata", customName + QString::number(i));
+ }
}
QFile file(profilePath);
if (!file.open(QIODevice::WriteOnly)) {
}
}
+//static
+int ProfilesDialog::getColorspaceFromDescription(const QString &description)
+{
+ //TODO: should the descriptions be translated?
+ if (description == "SMPTE240M") return 240;
+ if (description == "ITU-R 709") return 709;
+ return 601;
+}
+
#include "profilesdialog.moc"
static QString getPathFromDescription(const QString profileDesc);
static MltVideoProfile getVideoProfile(QString name);
static QMap <QString, QString> getProfilesInfo();
- static void saveProfile(MltVideoProfile &profile);
+ static void saveProfile(MltVideoProfile &profile, QString profilePath = QString());
static QString existingProfile(MltVideoProfile profile);
static bool existingProfileDescription(const QString &desc);
* @return The string description */
static QString getColorspaceDescription(int colorspace);
+ /** @brief Get the colorspace code (defined by MLT) from a descriptive text
+ * @param desctiption A string description as defined in getColorspaceDescription(int colorspace)
+ * @return The int code */
+ static int getColorspaceFromDescription(const QString &description);
+
protected:
virtual void closeEvent(QCloseEvent *event);
#include "recmonitor.h"
#include "gentime.h"
+#include "mltdevicecapture.h"
#include "kdenlivesettings.h"
#include "managecapturesdialog.h"
+#include "monitormanager.h"
+#include "monitor.h"
+#include "profilesdialog.h"
#include <KDebug>
#include <KLocale>
-#include <QPainter>
#include <KStandardDirs>
#include <KComboBox>
#include <KIO/NetAccess>
#include <QDir>
-RecMonitor::RecMonitor(QString name, QWidget *parent) :
- QWidget(parent),
+RecMonitor::RecMonitor(QString name, MonitorManager *manager, QWidget *parent) :
+ AbstractMonitor(parent),
m_name(name),
- m_isActive(false),
m_isCapturing(false),
m_didCapture(false),
m_isPlaying(false),
m_bmCapture(NULL),
- m_blackmagicCapturing(false)
+ m_blackmagicCapturing(false),
+ m_manager(manager),
+ m_captureDevice(NULL),
+ m_analyse(false)
{
setupUi(this);
device_selector->setCurrentIndex(KdenliveSettings::defaultcapture());
connect(device_selector, SIGNAL(currentIndexChanged(int)), this, SLOT(slotVideoDeviceChanged(int)));
+ // Video widget holder
+ QVBoxLayout *l = new QVBoxLayout;
+ l->setContentsMargins(0, 0, 0, 0);
+ l->setSpacing(0);
+ m_videoBox = new VideoPreviewContainer();
+ m_videoBox->setContentsMargins(0, 0, 0, 0);
+ m_videoBox->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ l->addWidget(m_videoBox);
+ video_frame->setLayout(l);
+
QToolBar *toolbar = new QToolBar(this);
QHBoxLayout *layout = new QHBoxLayout;
layout->setContentsMargins(0, 0, 0, 0);
m_displayProcess->setEnvironment(env);
- if (KdenliveSettings::video4capture().isEmpty()) {
- QString captureCommand;
- if (!KdenliveSettings::video4adevice().isEmpty()) captureCommand = "-f " + KdenliveSettings::video4aformat() + " -i " + KdenliveSettings::video4adevice() + " -acodec " + KdenliveSettings::video4acodec();
-
- captureCommand += " -f " + KdenliveSettings::video4vformat() + " -s " + KdenliveSettings::video4size() + " -r " + QString::number(KdenliveSettings::video4rate()) + " -i " + KdenliveSettings::video4vdevice() + " -vcodec " + KdenliveSettings::video4vcodec();;
- KdenliveSettings::setVideo4capture(captureCommand);
- }
-
kDebug() << "/////// BUILDING MONITOR, ID: " << video_frame->winId();
}
#endif
delete m_captureProcess;
delete m_displayProcess;
+ if (m_captureDevice) delete m_captureDevice;
}
-QString RecMonitor::name() const
+const QString RecMonitor::name() const
{
return m_name;
}
+void RecMonitor::stop()
+{
+ slotStopCapture();
+}
+
+void RecMonitor::start()
+{
+}
+
void RecMonitor::slotConfigure()
{
emit showConfigDialog(4, device_selector->currentIndex());
QString capturename;
video_capture->setHidden(true);
video_frame->setHidden(false);
- m_fwdAction->setVisible(ix != BLACKMAGIC);
- m_discAction->setVisible(ix != BLACKMAGIC);
- m_rewAction->setVisible(ix != BLACKMAGIC);
+ m_fwdAction->setVisible(ix == FIREWIRE);
+ m_discAction->setVisible(ix == FIREWIRE);
+ m_rewAction->setVisible(ix == FIREWIRE);
m_logger.setVisible(ix == BLACKMAGIC);
+ if (m_captureDevice) {
+ // MLT capture still running, abort
+ m_captureDevice->stop();
+ //delete m_captureDevice;
+ //m_captureDevice = NULL;
+ }
switch (ix) {
case SCREENGRAB:
m_discAction->setEnabled(false);
m_isPlaying = false;
break;
case VIDEO4LINUX:
+ if (m_captureDevice) {
+ m_captureDevice->stop();
+ }
+ m_playAction->setEnabled(true);
+ m_stopAction->setEnabled(false);
+ break;
case SCREENGRAB:
m_captureProcess->write("q\n", 3);
QTimer::singleShot(1000, m_captureProcess, SLOT(kill()));
m_displayArgs.clear();
m_isPlaying = false;
QString capturename = KdenliveSettings::dvgrabfilename();
+ QString path;
+ MltVideoProfile profile;
+ QString producer;
QStringList dvargs = KdenliveSettings::dvgrabextra().simplified().split(" ", QString::SkipEmptyParts);
video_capture->setVisible(device_selector->currentIndex() == BLACKMAGIC);
video_frame->setHidden(device_selector->currentIndex() == BLACKMAGIC);
m_discAction->setEnabled(true);
break;
case VIDEO4LINUX:
- m_captureArgs << KdenliveSettings::video4capture().simplified().split(' ') << KdenliveSettings::video4encoding().simplified().split(' ') << "-f" << KdenliveSettings::video4container() << "-";
+ path = KStandardDirs::locateLocal("appdata", "profiles/video4linux");
+ m_manager->activateMonitor("record");
+ if (m_captureDevice == NULL) {
+ m_captureDevice = new MltDeviceCapture(path, m_videoBox, this);
+ m_captureDevice->sendFrameForAnalysis = m_analyse;
+ m_manager->updateScopeSource();
+ }
+ profile = ProfilesDialog::getVideoProfile(path);
+ producer = QString("avformat-novalidate:video4linux2:%1?width:%2&height:%3&frame_rate:%4").arg(KdenliveSettings::video4vdevice()).arg(profile.width).arg(profile.height).arg((double) profile.frame_rate_num / profile.frame_rate_den);
+ kDebug()<< "PROD: "<<producer;
+ if (!m_captureDevice->slotStartPreview(producer)) {
+ // v4l capture failed to start
+ video_frame->setText(i18n("Failed to start Video4Linux,\ncheck your parameters..."));
+ m_videoBox->setHidden(true);
+
+ } else {
+ m_videoBox->setHidden(false);
+ m_playAction->setEnabled(false);
+ m_stopAction->setEnabled(true);
+ }
+
+ /*m_captureArgs << KdenliveSettings::video4capture().simplified().split(' ') << KdenliveSettings::video4encoding().simplified().split(' ') << "-f" << KdenliveSettings::video4container() << "-";
m_displayArgs << "-f" << KdenliveSettings::video4container() << "-x" << QString::number(video_frame->width()) << "-y" << QString::number(video_frame->height()) << "-";
m_captureProcess->setStandardOutputProcess(m_displayProcess);
kDebug() << "Capture: Running ffmpeg " << m_captureArgs.join(" ");
- m_captureProcess->start("ffmpeg", m_captureArgs);
+ m_captureProcess->start("ffmpeg", m_captureArgs);*/
break;
case BLACKMAGIC:
m_bmCapture->startPreview(KdenliveSettings::hdmi_capturedevice(), KdenliveSettings::hdmi_capturemode());
break;
}
- if (device_selector->currentIndex() == FIREWIRE || device_selector->currentIndex() == VIDEO4LINUX) {
+ if (device_selector->currentIndex() == FIREWIRE) {
kDebug() << "Capture: Running ffplay " << m_displayArgs.join(" ");
m_displayProcess->start("ffplay", m_displayArgs);
video_frame->setText(i18n("Initialising..."));
m_recAction->setChecked(false);
break;
case VIDEO4LINUX:
- m_captureProcess->terminate();
slotStopCapture();
- //m_isCapturing = false;
- QTimer::singleShot(1000, this, SLOT(slotStartCapture()));
+ m_isCapturing = false;
+ m_recAction->setChecked(false);
+ if (autoaddbox->isChecked() && QFile::exists(m_captureFile.path())) emit addProjectClip(m_captureFile);
+ //QTimer::singleShot(1000, this, SLOT(slotStartCapture()));
break;
case SCREENGRAB:
//captureProcess->write("q\n", 3);
m_recAction->setChecked(true);
QString extension = "mp4";
if (device_selector->currentIndex() == SCREENGRAB) extension = "ogv"; //KdenliveSettings::screengrabextension();
- else if (device_selector->currentIndex() == VIDEO4LINUX) extension = KdenliveSettings::video4extension();
- QString path = m_capturePath + "/capture0000." + extension;
+ else if (device_selector->currentIndex() == VIDEO4LINUX) extension = KdenliveSettings::v4l_extension();
+ QString path = KUrl(m_capturePath).path(KUrl::AddTrailingSlash) + "capture0000." + extension;
int i = 1;
while (QFile::exists(path)) {
QString num = QString::number(i).rightJustified(4, '0', false);
- path = m_capturePath + "/capture" + num + '.' + extension;
+ path = KUrl(m_capturePath).path(KUrl::AddTrailingSlash) + "capture" + num + '.' + extension;
i++;
}
m_captureFile = KUrl(path);
m_captureArgs.clear();
m_displayArgs.clear();
QString args;
+ QString playlist;
+ MltVideoProfile profile;
QString capturename = KdenliveSettings::dvgrabfilename();
if (capturename.isEmpty()) capturename = "capture";
switch (device_selector->currentIndex()) {
case VIDEO4LINUX:
+ path = KStandardDirs::locateLocal("appdata", "profiles/video4linux");
+ profile = ProfilesDialog::getVideoProfile(path);
+ if (m_captureDevice == NULL) {
+ m_captureDevice = new MltDeviceCapture(path, m_videoBox, this);
+ m_captureDevice->sendFrameForAnalysis = m_analyse;
+ m_manager->updateScopeSource();
+ }
+ playlist = QString("<mlt title=\"capture\"><producer id=\"producer0\" in=\"0\" out=\"99999\"><property name=\"mlt_type\">producer</property><property name=\"length\">100000</property><property name=\"eof\">pause</property><property name=\"resource\">video4linux2:%1?width:%2&height:%3&frame_rate:%4</property><property name=\"mlt_service\">avformat-novalidate</property></producer><playlist id=\"playlist0\"><entry producer=\"producer0\" in=\"0\" out=\"99999\"/></playlist>").arg(KdenliveSettings::video4vdevice()).arg(profile.width).arg(profile.height).arg((double) profile.frame_rate_num / profile.frame_rate_den);
+
+ // Add alsa audio capture
+ if (KdenliveSettings::v4l_captureaudio()) {
+ playlist.append(QString("<producer id=\"producer1\" in=\"0\" out=\"99999\"><property name=\"mlt_type\">producer</property><property name=\"length\">100000</property><property name=\"eof\">pause</property><property name=\"resource\">alsa:%5</property><property name=\"audio_index\">0</property><property name=\"video_index\">-1</property><property name=\"mlt_service\">avformat</property></producer><playlist id=\"playlist1\"><entry producer=\"producer1\" in=\"0\" out=\"99999\"/></playlist>").arg(KdenliveSettings::v4l_alsadevicename()));
+ }
+
+
+ playlist.append("<tractor id=\"tractor0\" title=\"video0\" global_feed=\"1\" in=\"0\" out=\"99999\">");
+
+ playlist.append("<track producer=\"playlist0\"/>");
+
+ // Audio mix
+ if (KdenliveSettings::v4l_captureaudio()) {
+ playlist.append("<track producer=\"playlist1\"/>");
+ playlist.append("<transition id=\"transition0\" in=\"0\" out=\"0\"><property name=\"a_track\">0</property><property name=\"b_track\">1</property><property name=\"mlt_type\">transition</property><property name=\"mlt_service\">mix</property></transition>");
+ }
+
+ playlist.append("</tractor></mlt>");
+
+ if (m_captureDevice->slotStartCapture(KdenliveSettings::v4l_parameters(), m_captureFile.path(), playlist)) {
+ m_videoBox->setHidden(false);
+ m_isCapturing = true;
+ }
+ else {
+ video_frame->setText(i18n("Failed to start Video4Linux,\ncheck your parameters..."));
+ m_videoBox->setHidden(true);
+ m_isCapturing = false;
+ m_recAction->setChecked(false);
+ }
+
+ /*
m_captureArgs << KdenliveSettings::video4capture().simplified().split(' ') << KdenliveSettings::video4encoding().simplified().split(' ') << "-y" << m_captureFile.path() << "-f" << KdenliveSettings::video4container() << "-acodec" << KdenliveSettings::video4acodec() << "-vcodec" << KdenliveSettings::video4vcodec() << "-";
m_displayArgs << "-f" << KdenliveSettings::video4container() << "-x" << QString::number(video_frame->width()) << "-y" << QString::number(video_frame->height()) << "-";
m_captureProcess->setStandardOutputProcess(m_displayProcess);
kDebug() << "Capture: Running ffmpeg " << m_captureArgs.join(" ");
- m_captureProcess->start("ffmpeg", m_captureArgs);
+ m_captureProcess->start("ffmpeg", m_captureArgs);*/
break;
case SCREENGRAB:
switch (KdenliveSettings::rmd_capture_type()) {
}
- if (device_selector->currentIndex() != SCREENGRAB) {
+ if (device_selector->currentIndex() == FIREWIRE) {
m_isCapturing = true;
kDebug() << "Capture: Running ffplay " << m_displayArgs.join(" ");
m_displayProcess->start("ffplay", m_displayArgs);
#endif
}
-void RecMonitor::activateRecMonitor()
-{
- //if (!m_isActive) m_monitorManager->activateRecMonitor(m_name);
-}
-
-void RecMonitor::stop()
-{
- m_isActive = false;
-
-}
-
-void RecMonitor::start()
-{
- m_isActive = true;
-
-}
-
void RecMonitor::refreshRecMonitor(bool visible)
{
if (visible) {
m_dvinfo.updateGeometry();
}
+AbstractRender *RecMonitor::abstractRender()
+{
+ return m_captureDevice;
+}
+
+
+void RecMonitor::analyseFrames(bool analyse)
+{
+ m_analyse = analyse;
+ if (m_captureDevice) m_captureDevice->sendFrameForAnalysis = analyse;
+}
+
+
#include "recmonitor.moc"
#ifndef RECMONITOR_H
#define RECMONITOR_H
+#include "abstractmonitor.h"
#include "blackmagic/capture.h"
#include "ui_recmonitor_ui.h"
#include <kcapacitybar.h>
#endif
-class RecMonitor : public QWidget, public Ui::RecMonitor_UI
+class MonitorManager;
+class MltDeviceCapture;
+class AbstractRender;
+
+class RecMonitor : public AbstractMonitor, public Ui::RecMonitor_UI
{
Q_OBJECT
public:
- explicit RecMonitor(QString name, QWidget *parent = 0);
+ explicit RecMonitor(QString name, MonitorManager *manager, QWidget *parent = 0);
virtual ~RecMonitor();
- QString name() const;
-
+ const QString name() const;
+ AbstractRender *abstractRender();
+ void analyseFrames(bool analyse);
enum CAPTUREDEVICE {FIREWIRE = 0, VIDEO4LINUX = 1, SCREENGRAB = 2, BLACKMAGIC = 3};
protected:
private:
QString m_name;
- bool m_isActive;
KDateTime m_captureTime;
/** @brief Provide feedback about dvgrab operations */
QLabel m_dvinfo;
QAction *m_rewAction;
QAction *m_stopAction;
QAction *m_discAction;
- void checkDeviceAvailability();
- QPixmap mergeSideBySide(const QPixmap& pix, const QString txt);
- void manageCapturedFiles();
+
+
CaptureHandler *m_bmCapture;
/** @brief Indicates whether we are currently capturing from BLACKMAGIC. */
bool m_blackmagicCapturing;
+ MonitorManager *m_manager;
+ MltDeviceCapture *m_captureDevice;
+ VideoPreviewContainer *m_videoBox;
+ bool m_analyse;
+ void checkDeviceAvailability();
+ QPixmap mergeSideBySide(const QPixmap& pix, const QString txt);
+ void manageCapturedFiles();
void createBlackmagicDevice();
private slots:
void slotStartCapture(bool play = true);
- void slotStopCapture();
void slotRecord();
void slotProcessStatus(QProcess::ProcessState status);
void slotVideoDeviceChanged(int ix);
public slots:
void refreshRecMonitor(bool visible);
+ void slotPlay();
void stop();
void start();
- void activateRecMonitor();
- void slotPlay();
+ void slotStopCapture();
void slotUpdateCaptureFolder(const QString currentProjectFolder);
signals:
}
Render::Render(const QString & rendererName, int winid, QString profile, QWidget *parent) :
- QObject(parent),
+ AbstractRender(parent),
m_isBlocked(0),
analyseAudio(KdenliveSettings::monitor_audio()),
- sendFrameForAnalysis(false),
m_name(rendererName),
m_mltConsumer(NULL),
m_mltProducer(NULL),
if (m_mltProducer == NULL) return;
if (m_mltConsumer && !m_mltConsumer->is_stopped()) {
kDebug() << "///////////// RENDER STOPPED: " << m_name;
- m_isBlocked = true;
//m_mltConsumer->set("refresh", 0);
m_mltConsumer->stop();
// delete m_mltConsumer;
#include "gentime.h"
#include "definitions.h"
+#include "abstractmonitor.h"
#include "mlt/framework/mlt_types.h"
#include <kurl.h>
#include <QEvent>
-class Render;
-
class QTimer;
class QPixmap;
QString m_message;
};
-class Render: public QObject
+
+class Render: public AbstractRender
{
Q_OBJECT public:
Render(const QString & rendererName, int winid, QString profile = QString(), QWidget *parent = 0);
/** @brief Destroy the MLT Renderer. */
- ~Render();
+ virtual ~Render();
/** @brief Seeks the renderer clip to the given time. */
void seek(GenTime time);
void showAudio(Mlt::Frame&);
/** @brief This property is used to decide if the renderer should send audio data for monitoring. */
bool analyseAudio;
- /** @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 <int> checkTrackSequence(int);
void sendFrameUpdate();
* Used in Mac OS X. */
void showImageSignal(QImage);
void showAudioSignal(const QByteArray);
- /** @brief The renderer refreshed the current frame, but no seeking was done. */
- void frameUpdated(QImage);
- /** @brief This signal contains the audio of the current frame. */
- void audioSamplesSignal(const QVector<int16_t>&, int freq, int num_channels, int num_samples);
public slots:
#include "../blackmagic/devices.h"
#include "../v4l/v4lcapture.h"
#include "../slideshowclip.h"
+#include "../profilesdialog.h"
+#include "../mltdevicecapture.h"
+#include "../recmonitor.h"
+#include "../monitormanager.h"
#include "ui_smconfig_ui.h"
#include "kdenlivesettings.h"
}
-StopmotionWidget::StopmotionWidget(KUrl projectFolder, QList< QAction* > actions, QWidget* parent) :
+StopmotionMonitor::StopmotionMonitor(QWidget *parent) :
+ AbstractMonitor(parent),
+ m_captureDevice(NULL)
+{
+}
+
+StopmotionMonitor::~StopmotionMonitor()
+{
+}
+
+void StopmotionMonitor::setRender(MltDeviceCapture *render)
+{
+ m_captureDevice = render;
+}
+
+AbstractRender *StopmotionMonitor::abstractRender()
+{
+ return m_captureDevice;
+}
+
+const QString StopmotionMonitor::name() const
+{
+ return QString("stopmotion");
+}
+
+
+void StopmotionMonitor::stop()
+{
+ if (m_captureDevice) m_captureDevice->stop();
+ emit stopCapture();
+}
+
+void StopmotionMonitor::start()
+{
+}
+
+StopmotionWidget::StopmotionWidget(MonitorManager *manager, KUrl projectFolder, QList< QAction* > actions, QWidget* parent) :
QDialog(parent)
, Ui::Stopmotion_UI()
, m_projectFolder(projectFolder)
- , m_bmCapture(NULL)
+ , m_captureDevice(NULL)
, m_sequenceFrame(0)
, m_animatedIndex(-1)
, m_animate(false)
+ , m_manager(manager)
+ , m_monitor(new StopmotionMonitor(this))
{
//setAttribute(Qt::WA_DeleteOnClose);
+ //HACK: the monitor widget is hidden, it is just used to control the capturedevice from monitormanager
+ m_monitor->setHidden(true);
+ connect(m_monitor, SIGNAL(stopCapture()), this, SLOT(slotStopCapture()));
+ m_manager->appendMonitor(m_monitor);
QAction* analyse = new QAction(i18n("Send frames to color scopes"), this);
analyse->setCheckable(true);
analyse->setChecked(KdenliveSettings::analyse_stopmotion());
connect(sequence_name, SIGNAL(textChanged(const QString&)), this, SLOT(sequenceNameChanged(const QString&)));
connect(sequence_name, SIGNAL(currentIndexChanged(int)), live_button, SLOT(setFocus()));
- m_layout = new QVBoxLayout;
+ // Video widget holder
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+ m_videoBox = new VideoPreviewContainer();
+ m_videoBox->setContentsMargins(0, 0, 0, 0);
+ m_videoBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ //m_videoBox->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ m_videoBox->setLineWidth(4);
+ layout->addWidget(m_videoBox);
+
+
if (BMInterface::getBlackMagicDeviceList(capture_device, NULL)) {
// Found a BlackMagic device
- m_bmCapture = new BmdCaptureHandler(m_layout);
- connect(m_bmCapture, SIGNAL(gotMessage(const QString&)), this, SLOT(slotGotHDMIMessage(const QString&)));
+ //m_bmCapture = new BmdCaptureHandler(m_layout);
+ //connect(m_bmCapture, SIGNAL(gotMessage(const QString&)), this, SLOT(slotGotHDMIMessage(const QString&)));
}
if (QFile::exists(KdenliveSettings::video4vdevice())) {
#if !defined(Q_WS_MAC) && !defined(Q_OS_FREEBSD)
- V4lCaptureHandler v4l(NULL);
// Video 4 Linux device detection
for (int i = 0; i < 10; i++) {
QString path = "/dev/video" + QString::number(i);
if (QFile::exists(path)) {
- QStringList deviceInfo = v4l.getDeviceName(path);
+ QStringList deviceInfo = V4lCaptureHandler::getDeviceName(path);
if (!deviceInfo.isEmpty()) {
capture_device->addItem(deviceInfo.at(0), "v4l");
capture_device->setItemData(capture_device->count() - 1, path, Qt::UserRole + 1);
}
}
- /*V4lCaptureHandler v4lhandler(NULL);
- QStringList deviceInfo = v4lhandler.getDeviceName(KdenliveSettings::video4vdevice());
- capture_device->addItem(deviceInfo.at(0), "v4l");
- capture_device->setItemData(capture_device->count() - 1, deviceInfo.at(3), Qt::UserRole + 1);*/
- if (m_bmCapture == NULL) {
- m_bmCapture = new V4lCaptureHandler(m_layout);
- m_bmCapture->setDevice(capture_device->itemData(capture_device->currentIndex(), Qt::UserRole + 1).toString(), capture_device->itemData(capture_device->currentIndex(), Qt::UserRole + 2).toString());
- }
+ //if (m_bmCapture == NULL) {
+
+ //m_captureDevice->sendFrameForAnalysis = m_analyse;
+ /*m_bmCapture = new V4lCaptureHandler(m_layout);
+ m_bmCapture->setDevice(capture_device->itemData(capture_device->currentIndex(), Qt::UserRole + 1).toString(), capture_device->itemData(capture_device->currentIndex(), Qt::UserRole + 2).toString());*/
+ //}
#endif
}
connect(capture_device, SIGNAL(currentIndexChanged(int)), this, SLOT(slotUpdateHandler()));
- if (m_bmCapture) {
+ /*if (m_bmCapture) {
connect(m_bmCapture, SIGNAL(frameSaved(const QString)), this, SLOT(slotNewThumb(const QString)));
connect(m_bmCapture, SIGNAL(gotFrame(QImage)), this, SIGNAL(gotFrame(QImage)));
- } else live_button->setEnabled(false);
+ } else live_button->setEnabled(false);*/
+
m_frame_preview = new MyLabel(this);
connect(m_frame_preview, SIGNAL(seek(bool)), this, SLOT(slotSeekFrame(bool)));
connect(m_frame_preview, SIGNAL(switchToLive()), this, SLOT(slotSwitchLive()));
- m_layout->addWidget(m_frame_preview);
+ layout->addWidget(m_frame_preview);
m_frame_preview->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
- video_preview->setLayout(m_layout);
+ video_preview->setLayout(layout);
+
+ //kDebug()<<video_preview->winId();
+
+ QString path = KStandardDirs::locateLocal("appdata", "profiles/video4linux");
+ m_captureDevice = new MltDeviceCapture(path, m_videoBox, this);
+ m_captureDevice->sendFrameForAnalysis = KdenliveSettings::analyse_stopmotion();
+ m_monitor->setRender(m_captureDevice);
+ connect(m_captureDevice, SIGNAL(frameSaved(const QString)), this, SLOT(slotNewThumb(const QString)));
+
live_button->setChecked(false);
button_addsequence->setEnabled(false);
connect(live_button, SIGNAL(toggled(bool)), this, SLOT(slotLive(bool)));
StopmotionWidget::~StopmotionWidget()
{
- if (m_bmCapture)
- m_bmCapture->stopPreview();
+ /*if (m_bmCapture)
+ m_bmCapture->stopPreview();*/
+ if (m_captureDevice) {
+ m_captureDevice->stop();
+ delete m_captureDevice;
+ m_captureDevice = NULL;
+ }
+
+ delete m_monitor;
}
void StopmotionWidget::slotUpdateOverlayEffect(QAction* act)
void StopmotionWidget::slotUpdateHandler()
{
- QString data = capture_device->itemData(capture_device->currentIndex()).toString();
+ /*QString data = capture_device->itemData(capture_device->currentIndex()).toString();
slotLive(false);
if (m_bmCapture) {
delete m_bmCapture;
if (m_bmCapture) connect(m_bmCapture, SIGNAL(gotMessage(const QString&)), this, SLOT(slotGotHDMIMessage(const QString&)));
}
live_button->setEnabled(m_bmCapture != NULL);
- m_layout->addWidget(m_frame_preview);
+ m_layout->addWidget(m_frame_preview);*/
}
void StopmotionWidget::slotGotHDMIMessage(const QString& message)
void StopmotionWidget::slotSwitchLive()
{
setUpdatesEnabled(false);
- if (m_frame_preview->isHidden()) {
- if (m_bmCapture) m_bmCapture->hidePreview(true);
+ slotLive(!live_button->isChecked());
+ /*if (m_frame_preview->isHidden()) {
+ //if (m_bmCapture) m_bmCapture->hidePreview(true);
+ m_videoBox->setHidden(true);
m_frame_preview->setHidden(false);
} else {
m_frame_preview->setHidden(true);
- if (m_bmCapture) m_bmCapture->hidePreview(false);
+ //if (m_bmCapture) m_bmCapture->hidePreview(false);
+ m_videoBox->setHidden(false);
capture_button->setEnabled(true);
- }
+ }*/
setUpdatesEnabled(true);
}
+void StopmotionWidget::slotStopCapture()
+{
+ slotLive(false);
+}
+
void StopmotionWidget::slotLive(bool isOn)
{
live_button->blockSignals(true);
+ capture_button->setEnabled(false);
+ if (isOn) {
+ m_frame_preview->setHidden(true);
+ m_videoBox->setHidden(false);
+ QString path = KStandardDirs::locateLocal("appdata", "profiles/video4linux");
+
+ kDebug()<<"SURFACE; "<<m_videoBox->width()<<"x"<<m_videoBox->height();
+ if (m_captureDevice == NULL) {
+ m_captureDevice = new MltDeviceCapture(path, m_videoBox, this);
+ m_captureDevice->sendFrameForAnalysis = KdenliveSettings::analyse_stopmotion();
+ m_monitor->setRender(m_captureDevice);
+ connect(m_captureDevice, SIGNAL(frameSaved(const QString)), this, SLOT(slotNewThumb(const QString)));
+ }
+
+ MltVideoProfile profile = ProfilesDialog::getVideoProfile(path);
+ m_manager->activateMonitor("stopmotion");
+ QString producer = QString("avformat-novalidate:video4linux2:%1?width:%2&height:%3&frame_rate:%4").arg(KdenliveSettings::video4vdevice()).arg(profile.width).arg(profile.height).arg((double) profile.frame_rate_num / profile.frame_rate_den);
+ if (m_captureDevice->slotStartPreview(producer)) {
+ kDebug()<<"// STARt CAPTURE GO";
+ capture_button->setEnabled(true);
+ live_button->setChecked(true);
+ log_box->insertItem(-1, i18n("Playing %1x%2 (%3 fps)", profile.width, profile.height, QString::number((double)profile.frame_rate_num/profile.frame_rate_den).rightJustified(2, '0')));
+ log_box->setCurrentIndex(0);
+ }
+ else {
+ kDebug()<<"// problem starting stopmo";
+ log_box->insertItem(-1, i18n("Failed to start device"));
+ log_box->setCurrentIndex(0);
+ }
+ }
+ else {
+ m_frame_preview->setHidden(false);
+ live_button->setChecked(false);
+ if (m_captureDevice) {
+ m_captureDevice->stop();
+ m_videoBox->setHidden(true);
+ log_box->insertItem(-1, i18n("Stopped"));
+ log_box->setCurrentIndex(0);
+ //delete m_captureDevice;
+ //m_captureDevice = NULL;
+ }
+ }
+
+ /*
if (isOn && m_bmCapture) {
//m_frame_preview->setImage(QImage());
m_frame_preview->setHidden(true);
m_frame_preview->setHidden(false);
capture_button->setEnabled(false);
live_button->setChecked(false);
- }
+ }*/
live_button->blockSignals(false);
}
-void StopmotionWidget::slotShowOverlay(bool isOn)
+void StopmotionWidget::slotShowOverlay(bool /*isOn*/)
{
- if (isOn) {
+/* if (isOn) {
if (live_button->isChecked() && m_sequenceFrame > 0) {
slotUpdateOverlay();
}
} else if (m_bmCapture) {
m_bmCapture->hideOverlay();
- }
+ }*/
}
void StopmotionWidget::slotUpdateOverlay()
{
- if (m_bmCapture == NULL) return;
+ if (m_captureDevice == NULL) return;
QString path = getPathForFrame(m_sequenceFrame - 1);
if (!QFile::exists(path)) return;
QImage img(path);
}
#endif
- m_bmCapture->showOverlay(img);
+ //m_bmCapture->showOverlay(img);
}
void StopmotionWidget::sequenceNameChanged(const QString& name)
void StopmotionWidget::slotCaptureFrame()
{
- if (m_bmCapture == NULL) return;
+ if (m_captureDevice == NULL) return;
if (sequence_name->currentText().isEmpty()) {
QString seqName = QInputDialog::getText(this, i18n("Create New Sequence"), i18n("Enter sequence name"));
if (seqName.isEmpty()) {
return;
}
QString currentPath = getPathForFrame(m_sequenceFrame);
- m_bmCapture->captureFrame(currentPath);
+ m_captureDevice->captureFrame(currentPath);
KNotification::event("FrameCaptured", i18n("Frame Captured"), QPixmap(), this);
m_sequenceFrame++;
button_addsequence->setEnabled(true);
capture_button->setEnabled(false);
slotLive(false);
if (!img.isNull()) {
- if (m_bmCapture) m_bmCapture->hidePreview(true);
+ //m_videoBox->setHidden(true);
+
m_frame_preview->setImage(img);
m_frame_preview->setHidden(false);
m_frame_preview->update();
void StopmotionWidget::slotSwitchAnalyse(bool isOn)
{
KdenliveSettings::setAnalyse_stopmotion(isOn);
- m_bmCapture->setAnalyse(isOn);
+ if (m_captureDevice) m_captureDevice->sendFrameForAnalysis = isOn;
+ //m_bmCapture->setAnalyse(isOn);
}
#include <QFuture>
#include <QVBoxLayout>
#include <QTimer>
+#include <abstractmonitor.h>
+
+class MltDeviceCapture;
+class MonitorManager;
+class VideoPreviewContainer;
class MyLabel : public QLabel
{
void switchToLive();
};
-class StopmotionWidget : public QDialog , public Ui::Stopmotion_UI
+
+class StopmotionMonitor : public AbstractMonitor
+{
+ Q_OBJECT
+public:
+ StopmotionMonitor(QWidget *parent);
+ ~StopmotionMonitor();
+ AbstractRender *abstractRender();
+ const QString name() const;
+ void setRender(MltDeviceCapture *render);
+
+private:
+ MltDeviceCapture *m_captureDevice;
+
+public slots:
+ virtual void stop();
+ virtual void start();
+
+signals:
+ void stopCapture();
+};
+
+
+class StopmotionWidget : public QDialog, public Ui::Stopmotion_UI
{
Q_OBJECT
* @param projectFolder The current project folder, where captured files will be stored.
* @param actions The actions for this widget that can have a keyboard shortcut.
* @param parent (optional) parent widget */
- StopmotionWidget(KUrl projectFolder, QList< QAction* > actions, QWidget* parent = 0);
+ StopmotionWidget(MonitorManager *manager, KUrl projectFolder, QList< QAction* > actions, QWidget* parent = 0);
virtual ~StopmotionWidget();
protected:
virtual void closeEvent(QCloseEvent* e);
private:
- /** @brief Widget layout holding video and frame preview. */
- QVBoxLayout* m_layout;
-
/** @brief Current project folder (where the captured frames will be saved). */
KUrl m_projectFolder;
/** @brief Capture holder that will handle all video operation. */
- CaptureHandler* m_bmCapture;
+ MltDeviceCapture *m_captureDevice;
+
+ VideoPreviewContainer *m_videoBox;
+
+ //CaptureHandler* m_bmCapture;
/** @brief Holds the name of the current sequence.
* Files will be saved in project folder with name: sequence001.png */
/** @brief Timer for interval capture. */
QTimer m_intervalTimer;
+ MonitorManager *m_manager;
+
+ StopmotionMonitor *m_monitor;
+
#ifdef QIMAGEBLITZ
int m_effectIndex;
/** @brief Display the live feed from capture device.
@param isOn enable or disable the feature */
void slotLive(bool isOn = true);
+ void slotStopCapture();
private slots:
#include <string.h>
#include <sys/stat.h>
#include <errno.h>
+#include <sys/mman.h>
#include "src.h"
-#ifdef HAVE_V4L2
-extern src_mod_t src_v4l2;
-#endif
-#ifdef HAVE_V4L1
-extern src_mod_t src_v4l1;
-#endif
+#include <sys/ioctl.h>
+
/* Supported palette types. */
src_palette_t src_palette[] = {
};
-int src_open(src_t *src, char *source)
-{
- int i = 0;
- struct stat st;
-
- if(!source)
- {
- fprintf(stderr, "No source was specified.......");
- return(-1);
- }
- src->source = source;
-
- i = 0;
- int r = src_v4l2.flags;
- if(S_ISCHR(st.st_mode) && r & SRC_TYPE_DEVICE) r = -1;
- else if(!S_ISCHR(st.st_mode) && r & SRC_TYPE_FILE) r = -1;
- else r = 0;
- src->type = 0;
- r = src_v4l2.open(src);
- if(r == -2) return(-1);
-
- /*
- int frame;
- for(frame = 0; frame < config->skipframes; frame++)
- if(src_grab(src) == -1) break;*/
-
- return 0;
-}
-const char *src_query(src_t *src, char *source, uint *width, uint *height, char **pixelformatdescription)
+int v4l2_free_mmap(src_t *src)
{
- src->source = source;
- return src_v4l2.query(src, width, height, pixelformatdescription);
-}
+ src_v4l2_t *s = (src_v4l2_t *) src->state;
+ int i;
-int src_close(src_t *src)
-{
- int r;
-
- if(src->captured_frames)
- {
- double seconds =
- (src->tv_last.tv_sec + src->tv_last.tv_usec / 1000000.0) -
- (src->tv_first.tv_sec + src->tv_first.tv_usec / 1000000.0);
-
- /* Display FPS if enough frames where captured. */
- if(src->captured_frames == 1)
- {
- /*MSG("Captured frame in %0.2f seconds.", seconds);*/
- }
- else if(src->captured_frames < 3)
- {
- /*MSG("Captured %i frames in %0.2f seconds.",
- src->captured_frames, seconds);*/
- }
- else
- {
- /*MSG("Captured %i frames in %0.2f seconds. (%i fps)",
- src->captured_frames, seconds,
- (int) (src->captured_frames / seconds));*/
- }
- }
-
- r = src_v4l2.close(src);
-
- if(src->source) free(src->source);
-
- return(r);
-}
+ for(i = 0; i < s->req.count; i++)
+ munmap(s->buffer[i].start, s->buffer[i].length);
-int src_grab(src_t *src)
-{
- int r = src_v4l2.grab(src);
-
- if(!r)
- {
- if(!src->captured_frames) gettimeofday(&src->tv_first, NULL);
- gettimeofday(&src->tv_last, NULL);
-
- src->captured_frames++;
- }
-
- return(r);
+ return(0);
}
-/* Pointers are great things. Terrible things yes, but great. */
-/* These work but are very ugly and will be re-written soon. */
-
-int src_set_option(src_option_t ***options, char *name, char *value)
+static int close_v4l2(src_t *src)
{
- src_option_t **opts, *opt;
- int count;
-
- if(!options) return(-1);
- if(!*options)
- {
- *options = malloc(sizeof(src_option_t *));
- if(!*options)
- {
- /*ERROR("Out of memory.");*/
- return(-1);
- }
-
- *options[0] = NULL;
- }
-
- count = 0;
- opts = *options;
- while(*opts)
- {
- if((*opts)->name) if(!strcasecmp(name, (*opts)->name)) break;
- opts++;
- count++;
- }
-
- if(!*opts)
- {
- void *new;
-
- opt = (src_option_t *) malloc(sizeof(src_option_t));
- if(!opt)
- {
- /*ERROR("Out of memory.");*/
- return(-1);
- }
-
- new = realloc(*options, sizeof(src_option_t *) * (count + 2));
- if(!new)
- {
- free(opt);
- /*ERROR("Out of memory.");*/
- return(-1);
- }
-
- *options = (src_option_t **) new;
- (*options)[count++] = opt;
- (*options)[count++] = NULL;
-
- opt->name = strdup(name);
- opt->value = NULL;
- }
- else opt = *opts;
-
- if(opt->value)
- {
- free(opt->value);
- opt->value = NULL;
- }
- if(value) opt->value = strdup(value);
-
- return(0);
+ src_v4l2_t *s = (src_v4l2_t *) src->state;
+
+ if(s->buffer)
+ {
+ if(!s->map) free(s->buffer[0].start);
+ else v4l2_free_mmap(src);
+ free(s->buffer);
+ }
+ if(s->fd >= 0) close(s->fd);
+ free(s);
+
+ return(0);
}
-int src_get_option_by_number(src_option_t **opt, int number,
- char **name, char **value)
+//static
+const char *query_v4ldevice(src_t *src, char **pixelformatdescription)
{
- int i;
-
- if(!opt || !name || !value) return(-1);
-
- i = 0;
- while(*opt)
- {
- if(i == number)
- {
- *name = (*opt)->name;
- *value = (*opt)->value;
- return(0);
- }
-
- i++;
- }
-
- return(-1);
+ if(!src->source)
+ {
+ /*ERROR("No device name specified.");*/
+ fprintf(stderr, "No device name specified.");
+ return NULL;
+ }
+ src_v4l2_t *s;
+
+ /* Allocate memory for the state structure. */
+ s = calloc(sizeof(src_v4l2_t), 1);
+ if(!s)
+ {
+ fprintf(stderr, "Out of memory.");
+ return NULL;
+ }
+
+ src->state = (void *) s;
+ char value[200];
+ //snprintf( value, sizeof(value), '\0' );
+ //strcpy(*pixelformatdescription, (char*) value);
+ /* Open the device. */
+ s->fd = open(src->source, O_RDWR | O_NONBLOCK);
+ if(s->fd < 0)
+ {
+ fprintf(stderr, "Cannot open device.");
+ free(s);
+ return NULL;
+ }
+
+ if(ioctl(s->fd, VIDIOC_QUERYCAP, &s->cap) < 0) {
+ close_v4l2(src);
+ fprintf(stderr, "Cannot get capabilities.");
+ return NULL;
+ }
+ char *res = strdup((char*) s->cap.card);
+ /*strcpy(res, (char*) s->cap.card);*/
+ if(!s->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) {
+ // Device cannot capture
+ }
+ else {
+ struct v4l2_format format;
+ memset(&format,0,sizeof(format));
+ format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ if (ioctl(s->fd,VIDIOC_G_FMT,&format) < 0) {
+ fprintf(stderr, "Cannot get format.");
+ // Cannot query
+ }
+ struct v4l2_fmtdesc fmt;
+ memset(&fmt,0,sizeof(fmt));
+ fmt.index = 0;
+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ struct v4l2_frmsizeenum sizes;
+ memset(&sizes,0,sizeof(sizes));
+
+ struct v4l2_frmivalenum rates;
+ memset(&rates,0,sizeof(rates));
+
+ while (ioctl(s->fd, VIDIOC_ENUM_FMT, &fmt) != -1)
+ {
+ /*strcpy(*pixelformatdescription, (char *) fmt.description);*/
+ //*pixelformatdescription = strdup((char*)fmt.description);
+ snprintf( value, sizeof(value), ">%c%c%c%c", fmt.pixelformat >> 0, fmt.pixelformat >> 8, fmt.pixelformat >> 16, fmt.pixelformat >> 24 );
+ strcat(*pixelformatdescription, (char *) value);
+ fprintf(stderr, "detected format: %s: %c%c%c%c\n", fmt.description, fmt.pixelformat >> 0, fmt.pixelformat >> 8,
+ fmt.pixelformat >> 16, fmt.pixelformat >> 24);
+
+ sizes.pixel_format = fmt.pixelformat;
+ sizes.index = 0;
+ // Query supported frame size
+ while (ioctl(s->fd, VIDIOC_ENUM_FRAMESIZES, &sizes) != -1) {
+ struct v4l2_frmsize_discrete image_size = sizes.un.discrete;
+ // Query supported frame rates
+ rates.index = 0;
+ rates.pixel_format = fmt.pixelformat;
+ rates.width = image_size.width;
+ rates.height = image_size.height;
+ snprintf( value, sizeof(value), ":%dx%d=", image_size.width, image_size.height );
+ strcat(*pixelformatdescription, (char *) value);
+ fprintf(stderr, "Size: %dx%d: ", image_size.width, image_size.height);
+ while (ioctl(s->fd, VIDIOC_ENUM_FRAMEINTERVALS, &rates) != -1) {
+ snprintf( value, sizeof(value), "%d/%d,", rates.un.discrete.denominator, rates.un.discrete.numerator );
+ strcat(*pixelformatdescription, (char *) value);
+ fprintf(stderr, "%d/%d, ", rates.un.discrete.numerator, rates.un.discrete.denominator);
+ rates.index ++;
+ }
+ fprintf(stderr, "\n");
+ sizes.index++;
+ }
+
+
+ /*[0x%08X] '%c%c%c%c' (%s)", v4l2_pal,
+ fmt.pixelformat,
+ fmt.pixelformat >> 0, fmt.pixelformat >> 8,
+ fmt.pixelformat >> 16, fmt.pixelformat >> 24*/
+ fmt.index++;
+ }
+ /*else {
+ *pixelformatdescription = '\0';
+ }*/
+ }
+ close_v4l2(src);
+ return res;
}
-int src_get_option_by_name(src_option_t **opt, char *name, char **value)
-{
- if(!opt || !name || !value) return(-1);
-
- while(*opt)
- {
- if((*opt)->name)
- {
- if(!strcasecmp(name, (*opt)->name))
- {
- *value = (*opt)->value;
- return(0);
- }
- }
-
- opt++;
- }
-
- return(-1);
-}
-int src_free_options(src_option_t ***options)
-{
- src_option_t **opts;
-
- if(!options || !*options) return(-1);
-
- opts = *options;
- while(*opts)
- {
- if((*opts)->name) free((*opts)->name);
- if((*opts)->value) free((*opts)->value);
-
- free(*opts);
-
- opts++;
- }
-
- free(*options);
- *options = NULL;
-
- return(0);
-}
extern "C" {
#endif
+#ifndef INC_SRC_H
+#define INC_SRC_H
+
#include <stdint.h>
#include <sys/time.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
-#ifndef INC_SRC_H
-#define INC_SRC_H
+#include "videodev2.h"
+
+
typedef unsigned char avgbmp_t;
} src_t;
-typedef struct {
-
- char *name;
-
- uint8_t flags;
-
- int (*open)(src_t *);
- int (*close)(src_t *);
- int (*grab)(src_t *);
- const char *(*query)(src_t *, uint*, uint*, char **);
-
-} src_mod_t;
-
typedef struct {
/* List of options. */
} fswebcam_config_t;
-extern int src_open(src_t *src, char *source);
-extern int src_close(src_t *src);
-extern int src_grab(src_t *src);
-extern const char *src_query(src_t *src, char *source, uint *width, uint *height, char **pixelformatdescription);
-extern int src_set_option(src_option_t ***options, char *name, char *value);
-extern int src_get_option_by_number(src_option_t **opt, int number, char **name, char **value);
-extern int src_get_option_by_name(src_option_t **opt, char *name, char **value);
-extern int src_free_options(src_option_t ***options);
+
+typedef struct {
+ void *start;
+ size_t length;
+} v4l2_buffer_t;
+
+typedef struct {
+
+ int fd;
+ char map;
+
+ struct v4l2_capability cap;
+ struct v4l2_format fmt;
+ struct v4l2_requestbuffers req;
+ struct v4l2_buffer buf;
+
+ v4l2_buffer_t *buffer;
+
+ int pframe;
+
+} src_v4l2_t;
+
+
+const char *query_v4ldevice(src_t *src, char **pixelformatdescription);
#endif
#ifdef HAVE_V4L2
-typedef struct {
- void *start;
- size_t length;
-} v4l2_buffer_t;
-
-typedef struct {
-
- int fd;
- char map;
-
- struct v4l2_capability cap;
- struct v4l2_format fmt;
- struct v4l2_requestbuffers req;
- struct v4l2_buffer buf;
-
- v4l2_buffer_t *buffer;
-
- int pframe;
-
-} src_v4l2_t;
-
-static int src_v4l2_close(src_t *src);
-
-typedef struct {
- uint16_t src;
- uint32_t v4l2;
-} v4l2_palette_t;
-
-v4l2_palette_t v4l2_palette[] = {
- { SRC_PAL_JPEG, V4L2_PIX_FMT_JPEG },
- { SRC_PAL_MJPEG, V4L2_PIX_FMT_MJPEG },
- { SRC_PAL_S561, V4L2_PIX_FMT_SPCA561 },
- { SRC_PAL_RGB24, V4L2_PIX_FMT_RGB24 },
- { SRC_PAL_BGR24, V4L2_PIX_FMT_BGR24 },
- { SRC_PAL_RGB32, V4L2_PIX_FMT_RGB32 },
- { SRC_PAL_BGR32, V4L2_PIX_FMT_BGR32 },
- { SRC_PAL_YUYV, V4L2_PIX_FMT_YUYV },
- { SRC_PAL_UYVY, V4L2_PIX_FMT_UYVY },
- { SRC_PAL_YUV420P, V4L2_PIX_FMT_YUV420 },
- { SRC_PAL_BAYER, V4L2_PIX_FMT_SBGGR8 },
- { SRC_PAL_SGBRG8, V4L2_PIX_FMT_SGBRG8 },
- { SRC_PAL_SGRBG8, V4L2_PIX_FMT_SGRBG8 },
- { SRC_PAL_RGB565, V4L2_PIX_FMT_RGB565 },
- { SRC_PAL_RGB555, V4L2_PIX_FMT_RGB555 },
- { SRC_PAL_Y16, V4L2_PIX_FMT_Y16 },
- { SRC_PAL_GREY, V4L2_PIX_FMT_GREY },
- { 0, 0 }
-};
-
int src_v4l2_get_capability(src_t *src)
{
src_v4l2_t *s = (src_v4l2_t *) src->state;
memset(&fmt,0,sizeof(fmt));
fmt.index = 0;
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- if (ioctl(s->fd, VIDIOC_ENUM_FMT, &fmt) != -1)
+
+ struct v4l2_frmsizeenum sizes;
+ memset(&sizes,0,sizeof(sizes));
+
+ struct v4l2_frmivalenum rates;
+ memset(&rates,0,sizeof(rates));
+ char value[200];
+ *pixelformatdescription = strdup((char *) "result:");
+
+ while (ioctl(s->fd, VIDIOC_ENUM_FMT, &fmt) != -1)
{
/*strcpy(*pixelformatdescription, (char *) fmt.description);*/
- *pixelformatdescription = strdup((char*)fmt.description);
- fprintf(stderr, "format: %s", fmt.description);
+ //*pixelformatdescription = strdup((char*)fmt.description);
+ snprintf( value, sizeof(value), "%c%c%c%c:", fmt.pixelformat >> 0, fmt.pixelformat >> 8, fmt.pixelformat >> 16, fmt.pixelformat >> 24 );
+ strcat(*pixelformatdescription, strdup((char *) value));
+ fprintf(stderr, "detected format: %s: %c%c%c%c\n", fmt.description, fmt.pixelformat >> 0, fmt.pixelformat >> 8,
+ fmt.pixelformat >> 16, fmt.pixelformat >> 24);
+
+ sizes.pixel_format = fmt.pixelformat;
+ sizes.index = 0;
+ // Query supported frame size
+ while (ioctl(s->fd, VIDIOC_ENUM_FRAMESIZES, &sizes) != -1) {
+ struct v4l2_frmsize_discrete image_size = sizes.un.discrete;
+ // Query supported frame rates
+ rates.index = 0;
+ rates.pixel_format = fmt.pixelformat;
+ rates.width = image_size.width;
+ rates.height = image_size.height;
+ snprintf( value, sizeof(value), "%dx%d,", image_size.width, image_size.height );
+ strcat(*pixelformatdescription, strdup((char *) value));
+ fprintf(stderr, "Size: %dx%d: ", image_size.width, image_size.height);
+ while (ioctl(s->fd, VIDIOC_ENUM_FRAMEINTERVALS, &rates) != -1) {
+ snprintf( value, sizeof(value), "%d/%d,", rates.un.discrete.numerator, rates.un.discrete.denominator );
+ strcat(*pixelformatdescription, strdup((char *) value));
+ fprintf(stderr, "%d/%d, ", rates.un.discrete.numerator, rates.un.discrete.denominator);
+ rates.index ++;
+ }
+ fprintf(stderr, "\n");
+ sizes.index++;
+ }
+
+
+ /*[0x%08X] '%c%c%c%c' (%s)", v4l2_pal,
+ fmt.pixelformat,
+ fmt.pixelformat >> 0, fmt.pixelformat >> 8,
+ fmt.pixelformat >> 16, fmt.pixelformat >> 24*/
+ fmt.index++;
}
- else {
+ /*else {
*pixelformatdescription = '\0';
- }
+ }*/
}
src_v4l2_close(src);
return res;
#include "v4lcapture.h"
#include "kdenlivesettings.h"
-#include "dec.h"
-static src_t v4lsrc;
-QImage add_image_png(src_t *src)
+V4lCaptureHandler::V4lCaptureHandler()
{
- QImage im;
- im.loadFromData((uchar *)src->img, src->length, "PNG");
- return im;
-}
-
-QImage add_image_jpeg(src_t *src)
-{
- uint32_t hlength;
- uint8_t *himg = NULL;
- QImage im;
-
- /* MJPEG data may lack the DHT segment required for decoding... */
- verify_jpeg_dht((uint8_t *) src->img, src->length, &himg, &hlength);
-
- im.loadFromData(himg, hlength, "JPG");
- free(himg);
- return im;
-}
-
-class MyDisplay : public QLabel
-{
-public:
- MyDisplay(QWidget *parent = 0);
- void setImage(QImage img);
- virtual void paintEvent(QPaintEvent *);
- virtual void resizeEvent(QResizeEvent *);
-
-private:
- QImage m_img;
- bool m_clear;
-};
-
-MyDisplay::MyDisplay(QWidget *parent):
- QLabel(parent)
- , m_clear(false)
-{
- setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
- setAttribute(Qt::WA_PaintOnScreen);
- setAttribute(Qt::WA_OpaquePaintEvent);
-}
-
-void MyDisplay::resizeEvent(QResizeEvent *)
-{
- m_clear = true;
-}
-
-void MyDisplay::paintEvent(QPaintEvent *)
-{
- QPainter p(this);
- if (m_clear) {
- // widget resized, cleanup
- p.fillRect(0, 0, width(), height(), palette().background());
- m_clear = false;
- }
- if (m_img.isNull()) return;
- QImage img = m_img.scaled(width(), height(), Qt::KeepAspectRatio);
- p.drawImage((width() - img.width()) / 2, (height() - img.height()) / 2, img);
- p.end();
-}
-
-void MyDisplay::setImage(QImage img)
-{
- m_img = img;
- update();
}
-
-
-V4lCaptureHandler::V4lCaptureHandler(QVBoxLayout *lay, QWidget *parent):
- CaptureHandler(lay, parent)
- , m_update(false)
- , m_device(KdenliveSettings::video4vdevice())
- , m_width(-1)
- , m_height(-1)
-{
- if (lay == NULL) return;
- m_display = new MyDisplay;
- lay->addWidget(m_display);
-}
+//static
QStringList V4lCaptureHandler::getDeviceName(QString input)
{
- fswebcam_config_t *config;
- /* Prepare the configuration structure. */
- config = (fswebcam_config_t *) calloc(sizeof(fswebcam_config_t), 1);
- if (!config) {
- /*WARN("Out of memory.");*/
- fprintf(stderr, "Out of MEM....");
- return QStringList() << input;
- }
-
- /* Set the defaults. */
- config->loop = 0;
- config->offset = 0;
- config->background = 0;
- config->pidfile = NULL;
- config->logfile = NULL;
- config->gmt = 0;
- config->start = 0;
- config->device = strdup(input.toUtf8().constData());
- config->input = NULL;
- config->tuner = 0;
- config->frequency = 0;
- config->delay = 0;
- config->use_read = 0;
- config->list = 0;
- if (m_width > 0) config->width = m_width;
- else config->width = 384;
- if (m_height > 0) config->height = m_height;
- else config->height = 288;
- config->fps = 0;
- config->frames = 1;
- config->skipframes = 0;
- config->palette = SRC_PAL_ANY;
- config->option = NULL;
- config->dumpframe = NULL;
- config->jobs = 0;
- config->job = NULL;
-
- /* Set defaults and parse the command line. */
- /*if(fswc_getopts(config, argc, argv)) return(-1);*/
+ src_t v4lsrc;
-
- /* Record the start time. */
- config->start = time(NULL);
/* Set source options... */
memset(&v4lsrc, 0, sizeof(v4lsrc));
- v4lsrc.input = config->input;
- v4lsrc.tuner = config->tuner;
- v4lsrc.frequency = config->frequency;
- v4lsrc.delay = config->delay;
+ v4lsrc.input = NULL;
+ v4lsrc.tuner = 0;
+ v4lsrc.frequency = 0;
+ v4lsrc.delay = 0;
v4lsrc.timeout = 10; /* seconds */
- v4lsrc.use_read = config->use_read;
- v4lsrc.list = config->list;
- v4lsrc.palette = config->palette;
- v4lsrc.width = config->width;
- v4lsrc.height = config->height;
- v4lsrc.fps = config->fps;
- v4lsrc.option = config->option;
- char *source = config->device;
- uint width = 0;
- uint height = 0;
+ v4lsrc.use_read = 0;
+ v4lsrc.list = 0;
+ v4lsrc.palette = SRC_PAL_ANY;
+ v4lsrc.width = 384;
+ v4lsrc.height = 288;
+ v4lsrc.fps = 0;
+ v4lsrc.option = NULL;
+ v4lsrc.source = strdup(input.toUtf8().constData());
char *pixelformatdescription;
- QString deviceName(src_query(&v4lsrc, source, &width, &height, &pixelformatdescription));
- free(config);
+ pixelformatdescription = (char *) calloc(2048, sizeof(char));
+ QString deviceName(query_v4ldevice(&v4lsrc, &pixelformatdescription));
+ QString info(pixelformatdescription);
+ free (pixelformatdescription);
QStringList result;
- result << (deviceName.isEmpty() ? input : deviceName) << (width == 0 ? QString() : QString("%1x%2").arg(width).arg(height)) << QString(pixelformatdescription);
+ result << (deviceName.isEmpty() ? input : deviceName) << info;
return result;
}
-void V4lCaptureHandler::setDevice(const QString input, QString size)
-{
- m_device = input;
- if (!size.isEmpty()) {
- m_width = size.section('x', 0, 0).toInt();
- m_height = size.section('x', -1).toInt();
-
- }
-}
-
-void V4lCaptureHandler::startPreview(int /*deviceId*/, int /*captureMode*/, bool)
-{
- m_display->setHidden(false);
- fswebcam_config_t *config;
- /* Prepare the configuration structure. */
- config = (fswebcam_config_t *) calloc(sizeof(fswebcam_config_t), 1);
- if (!config) {
- /*WARN("Out of memory.");*/
- fprintf(stderr, "Out of MEM....");
- return;
- }
-
- /* Set the defaults. */
- config->loop = 0;
- config->offset = 0;
- config->background = 0;
- config->pidfile = NULL;
- config->logfile = NULL;
- config->gmt = 0;
- config->start = 0;
- config->device = strdup(m_device.toUtf8().constData());
- config->input = NULL;
- config->tuner = 0;
- config->frequency = 0;
- config->delay = 0;
- config->use_read = 0;
- config->list = 0;
- if (m_width > 0) config->width = m_width;
- else config->width = KdenliveSettings::video4size().section("x", 0, 0).toInt();/*384;*/
- if (m_height > 0) config->height = m_height;
- else config->height = KdenliveSettings::video4size().section("x", -1).toInt();/*288;*/
- config->fps = 0;
- config->frames = 1;
- config->skipframes = 0;
- config->palette = SRC_PAL_ANY;
- config->option = NULL;
- config->dumpframe = NULL;
- config->jobs = 0;
- config->job = NULL;
-
- /* Set defaults and parse the command line. */
- /*if(fswc_getopts(config, argc, argv)) return(-1);*/
-
-
- /* Record the start time. */
- config->start = time(NULL);
- /* Set source options... */
- memset(&v4lsrc, 0, sizeof(v4lsrc));
- v4lsrc.input = config->input;
- v4lsrc.tuner = config->tuner;
- v4lsrc.frequency = config->frequency;
- v4lsrc.delay = config->delay;
- v4lsrc.timeout = 10; /* seconds */
- v4lsrc.use_read = config->use_read;
- v4lsrc.list = config->list;
- v4lsrc.palette = config->palette;
- v4lsrc.width = config->width;
- v4lsrc.height = config->height;
- v4lsrc.fps = config->fps;
- v4lsrc.option = config->option;
- char *source = config->device;
-
- if (src_open(&v4lsrc, source) != 0) return;
- m_update = true;
- free(config);
- QTimer::singleShot(200, this, SLOT(slotUpdate()));
-}
-
-V4lCaptureHandler::~V4lCaptureHandler()
-{
- stopCapture();
-}
-
-void V4lCaptureHandler::slotUpdate()
-{
- if (!m_update) return;
- src_grab(&v4lsrc);
- QImage qimg(v4lsrc.width, v4lsrc.height, QImage::Format_RGB888);
- switch (v4lsrc.palette) {
- case SRC_PAL_PNG:
- qimg = add_image_png(&v4lsrc);
- break;
- case SRC_PAL_JPEG:
- case SRC_PAL_MJPEG:
- qimg = add_image_jpeg(&v4lsrc);
- break;
- case SRC_PAL_S561:
- fswc_add_image_s561(qimg.bits(), (uchar *)v4lsrc.img, v4lsrc.length, v4lsrc.width, v4lsrc.height, v4lsrc.palette);
- break;
- case SRC_PAL_RGB32:
- fswc_add_image_rgb32(&v4lsrc, qimg.bits());
- break;
- case SRC_PAL_BGR32:
- fswc_add_image_bgr32(&v4lsrc, qimg.bits());
- break;
- case SRC_PAL_RGB24:
- fswc_add_image_rgb24(&v4lsrc, qimg.bits());
- break;
- case SRC_PAL_BGR24:
- fswc_add_image_bgr24(&v4lsrc, qimg.bits());
- break;
- case SRC_PAL_BAYER:
- case SRC_PAL_SGBRG8:
- case SRC_PAL_SGRBG8:
- fswc_add_image_bayer(qimg.bits(), (uchar *)v4lsrc.img, v4lsrc.length, v4lsrc.width, v4lsrc.height, v4lsrc.palette);
- break;
- case SRC_PAL_YUYV:
- case SRC_PAL_UYVY:
- fswc_add_image_yuyv(&v4lsrc, (avgbmp_t *)qimg.bits());
- break;
- case SRC_PAL_YUV420P:
- fswc_add_image_yuv420p(&v4lsrc, qimg.bits());
- break;
- case SRC_PAL_NV12MB:
- fswc_add_image_nv12mb(&v4lsrc, qimg.bits());
- break;
- case SRC_PAL_RGB565:
- fswc_add_image_rgb565(&v4lsrc, qimg.bits());
- break;
- case SRC_PAL_RGB555:
- fswc_add_image_rgb555(&v4lsrc, qimg.bits());
- break;
- case SRC_PAL_Y16:
- fswc_add_image_y16(&v4lsrc, qimg.bits());
- break;
- case SRC_PAL_GREY:
- fswc_add_image_grey(&v4lsrc, qimg.bits());
- break;
- }
- if (m_analyseFrame) {
- emit gotFrame(qimg);
- }
- if (!m_captureFramePath.isEmpty()) {
- qimg.save(m_captureFramePath);
- emit frameSaved(m_captureFramePath);
- m_captureFramePath.clear();
- }
- if (!m_overlayImage.isNull()) {
- // overlay image
- QPainter p(&qimg);
- p.setOpacity(0.5);
- p.drawImage(0, 0, m_overlayImage);
- p.end();
- }
- m_display->setImage(qimg);
- if (m_update) QTimer::singleShot(50, this, SLOT(slotUpdate()));
-}
-
-void V4lCaptureHandler::startCapture(const QString &/*path*/)
-{
-}
-
-void V4lCaptureHandler::stopCapture()
-{
-}
-
-void V4lCaptureHandler::captureFrame(const QString &fname)
-{
- m_captureFramePath = fname;
-}
-
-void V4lCaptureHandler::showOverlay(QImage img, bool /*transparent*/)
-{
- m_overlayImage = img;
-}
-
-void V4lCaptureHandler::hideOverlay()
-{
- m_overlayImage = QImage();
-}
-
-void V4lCaptureHandler::hidePreview(bool hide)
-{
- m_display->setHidden(hide);
-}
-
-void V4lCaptureHandler::stopPreview()
-{
- m_display->setHidden(true);
- if (!m_update) return;
- m_update = false;
- src_close(&v4lsrc);
-}
#ifndef __V4LCAPTUREHANDLER_H__
#define __V4LCAPTUREHANDLER_H__
-#include "../stopmotion/capturehandler.h"
#include "src.h"
#include <QWidget>
#include <QLayout>
#include <QLabel>
-class MyDisplay;
-
-class V4lCaptureHandler : public CaptureHandler
+class V4lCaptureHandler
{
- Q_OBJECT
-public:
- V4lCaptureHandler(QVBoxLayout *lay, QWidget *parent = 0);
- ~V4lCaptureHandler();
- void startPreview(int deviceId, int captureMode, bool audio = true);
- void stopPreview();
- void startCapture(const QString &path);
- void stopCapture();
- void captureFrame(const QString &fname);
- void showOverlay(QImage img, bool transparent = true);
- void hideOverlay();
- void hidePreview(bool hide);
- QStringList getDeviceName(QString input);
- /** @brief Sets the path to the capture devide and optionnaly the width / height of the capture. */
- void setDevice(const QString input, QString size = QString());
-private:
- bool m_update;
- MyDisplay *m_display;
- QString m_captureFramePath;
- QImage m_overlayImage;
- QString m_device;
- int m_width;
- int m_height;
-
-private slots:
- void slotUpdate();
+public:
+ V4lCaptureHandler();
+ static QStringList getDeviceName(QString input);
};
union { /* Frame size */
struct v4l2_frmsize_discrete discrete;
struct v4l2_frmsize_stepwise stepwise;
- };
+ } un;
__u32 reserved[2]; /* Reserved space for future use */
};
union { /* Frame interval */
struct v4l2_fract discrete;
struct v4l2_frmival_stepwise stepwise;
- };
+ } un;
__u32 reserved[2]; /* Reserved space for future use */
};
<x>0</x>
<y>0</y>
<width>405</width>
- <height>470</height>
+ <height>563</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_8">
</size>
</property>
<property name="currentIndex">
- <number>0</number>
+ <number>1</number>
</property>
<widget class="QWidget" name="tab">
<attribute name="title">
<attribute name="title">
<string>Video4Linux</string>
</attribute>
- <layout class="QGridLayout" name="gridLayout_9">
- <item row="1" column="0" colspan="2">
- <widget class="QGroupBox" name="groupBox">
- <property name="title">
- <string>Video</string>
- </property>
- <layout class="QGridLayout" name="gridLayout">
- <item row="0" column="0">
- <widget class="QLabel" name="label_14">
- <property name="text">
- <string>Device</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="KLineEdit" name="kcfg_video4vdevice">
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="0" column="2">
- <widget class="QLabel" name="label_3">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Format</string>
- </property>
- </widget>
- </item>
- <item row="0" column="3">
- <widget class="KLineEdit" name="kcfg_video4vformat">
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_4">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Image size</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="KLineEdit" name="kcfg_video4size">
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="1" column="2">
- <widget class="QLabel" name="label_6">
- <property name="text">
- <string>Frame rate</string>
- </property>
- </widget>
- </item>
- <item row="1" column="3">
- <widget class="QSpinBox" name="kcfg_video4rate">
- <property name="value">
- <number>15</number>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="label_23">
- <property name="text">
- <string>Codec</string>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="KLineEdit" name="kcfg_video4vcodec"/>
- </item>
- </layout>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_30">
+ <property name="text">
+ <string>Detected devices</string>
+ </property>
</widget>
</item>
- <item row="2" column="0" colspan="2">
- <widget class="QGroupBox" name="groupBox_2">
- <property name="title">
- <string>Audio</string>
+ <item row="0" column="1" colspan="4">
+ <widget class="KComboBox" name="kcfg_detectedv4ldevices"/>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_14">
+ <property name="text">
+ <string>Video device</string>
</property>
- <layout class="QGridLayout" name="gridLayout_6">
- <item row="0" column="0">
- <widget class="QLabel" name="label_16">
- <property name="text">
- <string>Audio device</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="KLineEdit" name="kcfg_video4adevice">
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="0" column="2">
- <widget class="QLabel" name="label_9">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Format</string>
- </property>
- </widget>
- </item>
- <item row="0" column="3">
- <widget class="KLineEdit" name="kcfg_video4aformat">
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_24">
- <property name="text">
- <string>Audio codec</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="KLineEdit" name="kcfg_video4acodec"/>
- </item>
- </layout>
</widget>
</item>
- <item row="3" column="0" colspan="2">
- <widget class="QGroupBox" name="groupBox_3">
- <property name="title">
- <string>Container</string>
+ <item row="1" column="1" colspan="4">
+ <widget class="KLineEdit" name="kcfg_video4vdevice">
+ <property name="text">
+ <string/>
</property>
- <layout class="QGridLayout" name="gridLayout_7">
- <item row="0" column="0">
- <widget class="QLabel" name="label_25">
- <property name="text">
- <string>Format</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="KLineEdit" name="kcfg_video4container"/>
- </item>
- <item row="0" column="2">
- <widget class="QLabel" name="label_26">
- <property name="text">
- <string>Extension</string>
- </property>
- </widget>
- </item>
- <item row="0" column="3">
- <widget class="KLineEdit" name="kcfg_video4extension"/>
- </item>
- </layout>
</widget>
</item>
- <item row="4" column="0">
- <widget class="QLabel" name="label_11">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
+ <item row="3" column="0">
+ <widget class="QLabel" name="label_6">
+ <property name="text">
+ <string>Size:</string>
</property>
+ </widget>
+ </item>
+ <item row="3" column="1" colspan="4">
+ <widget class="QLabel" name="p_size">
<property name="text">
- <string>Capture params</string>
+ <string>720x576</string>
</property>
</widget>
</item>
- <item row="5" column="0" colspan="2">
- <widget class="KLineEdit" name="kcfg_video4capture">
- <property name="sizePolicy">
- <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
+ <item row="4" column="1" colspan="4">
+ <widget class="QLabel" name="p_fps">
+ <property name="text">
+ <string>25/1</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="0">
+ <widget class="QLabel" name="label_23">
+ <property name="text">
+ <string>Pixel aspect ratio:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="1" colspan="4">
+ <widget class="QLabel" name="p_aspect">
+ <property name="text">
+ <string>59/54</string>
</property>
</widget>
</item>
<item row="6" column="0">
+ <widget class="QLabel" name="label_31">
+ <property name="text">
+ <string>Display aspect ratio:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="1" colspan="4">
+ <widget class="QLabel" name="p_display">
+ <property name="text">
+ <string>4/3</string>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="0">
+ <widget class="QLabel" name="label_32">
+ <property name="text">
+ <string>Colorspace</string>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="1" colspan="4">
+ <widget class="QLabel" name="p_colorspace">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="0">
+ <widget class="QLabel" name="p_progressive">
+ <property name="text">
+ <string>Interlaced</string>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="1" colspan="3">
+ <spacer name="horizontalSpacer_5">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>127</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="8" column="4">
+ <widget class="QPushButton" name="pushButton">
+ <property name="text">
+ <string>Edit</string>
+ </property>
+ </widget>
+ </item>
+ <item row="9" column="0" colspan="4">
+ <widget class="Line" name="line">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="12" column="0" colspan="4">
+ <widget class="Line" name="line_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="13" column="0">
<widget class="QLabel" name="label_12">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
</sizepolicy>
</property>
<property name="text">
- <string>Encoding params</string>
+ <string>Encoding parameters</string>
</property>
</widget>
</item>
- <item row="7" column="0" colspan="2">
- <widget class="KLineEdit" name="kcfg_video4encoding"/>
+ <item row="14" column="0" colspan="5">
+ <widget class="QPlainTextEdit" name="kcfg_v4l_parameters">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
</item>
- <item row="8" column="1">
+ <item row="16" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</spacer>
</item>
- <item row="0" column="1">
- <widget class="KComboBox" name="kcfg_detectedv4ldevices">
- <item>
- <property name="text">
- <string>Select device in list</string>
- </property>
- </item>
+ <item row="15" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>File extension</string>
+ </property>
</widget>
</item>
- <item row="0" column="0">
- <widget class="QLabel" name="label_30">
+ <item row="15" column="1" colspan="4">
+ <widget class="QLineEdit" name="kcfg_v4l_extension">
+ <property name="maxLength">
+ <number>5</number>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_9">
<property name="text">
- <string>Detected devices</string>
+ <string>Capture format</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1" colspan="4">
+ <widget class="KComboBox" name="kcfg_v4l_format"/>
+ </item>
+ <item row="4" column="0">
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>Frame rate:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="10" column="0">
+ <widget class="QCheckBox" name="kcfg_v4l_captureaudio">
+ <property name="text">
+ <string>Capture audio (ALSA)</string>
+ </property>
+ </widget>
+ </item>
+ <item row="10" column="1" colspan="4">
+ <widget class="KComboBox" name="kcfg_v4l_alsadevice">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
</property>
</widget>
</item>
<tabstop>kcfg_firewireformat</tabstop>
<tabstop>kcfg_firewireautosplit</tabstop>
<tabstop>kcfg_firewiretimestamp</tabstop>
- <tabstop>kcfg_video4vdevice</tabstop>
- <tabstop>kcfg_video4vformat</tabstop>
- <tabstop>kcfg_video4adevice</tabstop>
- <tabstop>kcfg_video4aformat</tabstop>
- <tabstop>kcfg_video4encoding</tabstop>
<tabstop>kcfg_rmd_capture_audio</tabstop>
<tabstop>radioButton_2</tabstop>
<tabstop>kcfg_rmd_alsa_device</tabstop>
</widget>
</widget>
</item>
- <item row="1" column="9">
- <widget class="KComboBox" name="sequence_name">
- <property name="toolTip">
- <string>Sequence name</string>
+ <item row="1" column="2">
+ <widget class="QToolButton" name="config_button">
+ <property name="whatsThis">
+ <string/>
</property>
- <property name="editable">
- <bool>true</bool>
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="popupMode">
+ <enum>QToolButton::InstantPopup</enum>
</property>
</widget>
</item>
- <item row="1" column="11">
- <widget class="KComboBox" name="capture_device">
+ <item row="1" column="3">
+ <widget class="QToolButton" name="live_button">
<property name="toolTip">
- <string>Capture device</string>
+ <string>Live view</string>
</property>
<property name="whatsThis">
<string/>
</property>
- </widget>
- </item>
- <item row="1" column="12">
- <widget class="KComboBox" name="log_box">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
+ <property name="text">
+ <string>...</string>
</property>
- <property name="maxCount">
- <number>10</number>
+ <property name="checkable">
+ <bool>true</bool>
</property>
- <property name="frame">
- <bool>false</bool>
+ <property name="autoRaise">
+ <bool>true</bool>
</property>
</widget>
</item>
- <item row="1" column="13">
- <widget class="QPushButton" name="button_addsequence">
+ <item row="1" column="4">
+ <widget class="QToolButton" name="capture_button">
+ <property name="toolTip">
+ <string>Capture frame</string>
+ </property>
<property name="text">
- <string>Add to project</string>
+ <string>...</string>
</property>
</widget>
</item>
- <item row="1" column="7">
- <widget class="QToolButton" name="preview_button">
+ <item row="1" column="5">
+ <widget class="QToolButton" name="capture_interval">
<property name="toolTip">
- <string>Preview sequence</string>
- </property>
- <property name="whatsThis">
- <string/>
+ <string>Interval capture</string>
</property>
<property name="text">
<string>...</string>
</property>
</widget>
</item>
- <item row="1" column="2">
- <widget class="QToolButton" name="config_button">
- <property name="whatsThis">
- <string/>
- </property>
+ <item row="1" column="6">
+ <widget class="QToolButton" name="overlay_button">
<property name="text">
<string>...</string>
</property>
- <property name="popupMode">
- <enum>QToolButton::InstantPopup</enum>
- </property>
</widget>
</item>
- <item row="1" column="3">
- <widget class="QToolButton" name="live_button">
+ <item row="1" column="7">
+ <widget class="QToolButton" name="preview_button">
<property name="toolTip">
- <string>Live view</string>
+ <string>Preview sequence</string>
</property>
<property name="whatsThis">
<string/>
<property name="checkable">
<bool>true</bool>
</property>
- <property name="autoRaise">
- <bool>true</bool>
- </property>
</widget>
</item>
<item row="1" column="8">
</property>
</widget>
</item>
- <item row="1" column="6">
- <widget class="QToolButton" name="overlay_button">
- <property name="text">
- <string>...</string>
+ <item row="1" column="9">
+ <widget class="KComboBox" name="sequence_name">
+ <property name="toolTip">
+ <string>Sequence name</string>
+ </property>
+ <property name="editable">
+ <bool>true</bool>
</property>
</widget>
</item>
- <item row="1" column="5">
- <widget class="QToolButton" name="capture_interval">
+ <item row="1" column="11">
+ <widget class="KComboBox" name="capture_device">
<property name="toolTip">
- <string>Interval capture</string>
- </property>
- <property name="text">
- <string>...</string>
+ <string>Capture device</string>
</property>
- <property name="checkable">
- <bool>true</bool>
+ <property name="whatsThis">
+ <string/>
</property>
</widget>
</item>
- <item row="1" column="4">
- <widget class="QToolButton" name="capture_button">
- <property name="toolTip">
- <string>Capture frame</string>
+ <item row="1" column="12">
+ <widget class="KComboBox" name="log_box">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maxCount">
+ <number>10</number>
</property>
+ <property name="frame">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="13">
+ <widget class="QPushButton" name="button_addsequence">
<property name="text">
- <string>...</string>
+ <string>Add to project</string>
</property>
</widget>
</item>
<rect>
<x>0</x>
<y>0</y>
- <width>273</width>
- <height>153</height>
+ <width>279</width>
+ <height>110</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
- <item row="0" column="0" colspan="3">
+ <item row="0" column="0" colspan="4">
<widget class="QLabel" name="label">
<property name="text">
<string>Autodetected capture devices</string>
</property>
</widget>
</item>
- <item row="0" column="3">
+ <item row="0" column="4">
<widget class="QPushButton" name="button_reload">
<property name="text">
<string>Check</string>
</property>
</widget>
</item>
- <item row="1" column="0" colspan="4">
- <widget class="QTreeWidget" name="device_list">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="alternatingRowColors">
- <bool>true</bool>
+ <item row="1" column="0" colspan="5">
+ <widget class="QLabel" name="v4l_status">
+ <property name="text">
+ <string/>
</property>
- <property name="allColumnsShowFocus">
- <bool>true</bool>
+ </widget>
+ </item>
+ <item row="2" column="0" colspan="5">
+ <widget class="KComboBox" name="v4l_devices"/>
+ </item>
+ <item row="3" column="0" colspan="2">
+ <widget class="QLabel" name="label_9">
+ <property name="text">
+ <string>Select capture format</string>
</property>
- <column>
- <property name="text">
- <string>Device Name</string>
- </property>
- </column>
- <column>
- <property name="text">
- <string>Capacities</string>
- </property>
- </column>
</widget>
</item>
- <item row="3" column="1">
+ <item row="3" column="2" colspan="3">
+ <widget class="KComboBox" name="v4l_formats"/>
+ </item>
+ <item row="4" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</spacer>
</item>
- <item row="2" column="0" colspan="4">
- <widget class="QLabel" name="v4l_status">
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
</layout>
</widget>
+ <customwidgets>
+ <customwidget>
+ <class>KComboBox</class>
+ <extends>QComboBox</extends>
+ <header>kcombobox.h</header>
+ </customwidget>
+ </customwidgets>
<resources/>
<connections/>
</ui>
page6->setTitle(i18n("Webcam"));
m_capture.setupUi(page6);
connect(m_capture.button_reload, SIGNAL(clicked()), this, SLOT(slotDetectWebcam()));
- connect(m_capture.device_list, SIGNAL(itemSelectionChanged()), this, SLOT(slotUpdateCaptureParameters()));
+ connect(m_capture.v4l_devices, SIGNAL(currentIndexChanged(int)), this, SLOT(slotUpdateCaptureParameters()));
+ connect(m_capture.v4l_formats, SIGNAL(currentIndexChanged(int)), this, SLOT(slotSaveCaptureFormat()));
m_capture.button_reload->setIcon(KIcon("view-refresh"));
addPage(page6);
void Wizard::slotDetectWebcam()
{
#if !defined(Q_WS_MAC) && !defined(Q_OS_FREEBSD)
- m_capture.device_list->clear();
+ m_capture.v4l_devices->blockSignals(true);
+ m_capture.v4l_devices->clear();
// Video 4 Linux device detection
- V4lCaptureHandler v4l(NULL);
for (int i = 0; i < 10; i++) {
QString path = "/dev/video" + QString::number(i);
if (QFile::exists(path)) {
- QStringList deviceInfo = v4l.getDeviceName(path.toUtf8().constData());
+ QStringList deviceInfo = V4lCaptureHandler::getDeviceName(path.toUtf8().constData());
if (!deviceInfo.isEmpty()) {
- QTreeWidgetItem *item = new QTreeWidgetItem(m_capture.device_list, QStringList() << deviceInfo.at(0) << "(" + deviceInfo.at(1) + ") " + deviceInfo.at(2));
- item->setData(0, Qt::UserRole, path);
- item->setData(0, Qt::UserRole + 1, deviceInfo.at(1));
+ m_capture.v4l_devices->addItem(deviceInfo.at(0), path);
+ m_capture.v4l_devices->setItemData(m_capture.v4l_devices->count() - 1, deviceInfo.at(1), Qt::UserRole + 1);
}
}
}
- if (m_capture.device_list->topLevelItemCount() > 0) {
+ if (m_capture.v4l_devices->count() > 0) {
m_capture.v4l_status->setText(i18n("Select your default video4linux device"));
// select default device
bool found = false;
- for (int i = 0; i < m_capture.device_list->topLevelItemCount(); i++) {
- QTreeWidgetItem * item = m_capture.device_list->topLevelItem(i);
- if (item && item->data(0, Qt::UserRole).toString() == KdenliveSettings::video4vdevice()) {
- m_capture.device_list->setCurrentItem(item);
+ for (int i = 0; i < m_capture.v4l_devices->count(); i++) {
+ QString device = m_capture.v4l_devices->itemData(i).toString();
+ if (device == KdenliveSettings::video4vdevice()) {
+ m_capture.v4l_devices->setCurrentIndex(i);
found = true;
break;
}
}
- if (!found) m_capture.device_list->setCurrentItem(m_capture.device_list->topLevelItem(0));
+ slotUpdateCaptureParameters();
+ if (!found) m_capture.v4l_devices->setCurrentIndex(0);
} else m_capture.v4l_status->setText(i18n("No device found, plug your webcam and refresh."));
+ m_capture.v4l_devices->blockSignals(false);
#endif
}
void Wizard::slotUpdateCaptureParameters()
{
- QTreeWidgetItem * item = m_capture.device_list->currentItem();
- if (!item) return;
- QString device = item->data(0, Qt::UserRole).toString();
+ QString device = m_capture.v4l_devices->itemData(m_capture.v4l_devices->currentIndex()).toString();
if (!device.isEmpty()) KdenliveSettings::setVideo4vdevice(device);
- QString size = item->data(0, Qt::UserRole + 1).toString();
- if (!size.isEmpty()) KdenliveSettings::setVideo4size(size);
+ QString formats = m_capture.v4l_devices->itemData(m_capture.v4l_devices->currentIndex(), Qt::UserRole + 1).toString();
+
+ m_capture.v4l_formats->blockSignals(true);
+ m_capture.v4l_formats->clear();
+
+ QString vl4ProfilePath = KStandardDirs::locateLocal("appdata", "profiles/video4linux");
+ if (QFile::exists(vl4ProfilePath)) {
+ MltVideoProfile profileInfo = ProfilesDialog::getVideoProfile(vl4ProfilePath);
+ m_capture.v4l_formats->addItem(i18n("Current settings (%1x%2, %3/%4fps)", profileInfo.width, profileInfo.height, profileInfo.frame_rate_num, profileInfo.frame_rate_den), QStringList() << QString("unknown") <<QString::number(profileInfo.width)<<QString::number(profileInfo.height)<<QString::number(profileInfo.frame_rate_num)<<QString::number(profileInfo.frame_rate_den));
+ }
+ QStringList pixelformats = formats.split(">", QString::SkipEmptyParts);
+ QString itemSize;
+ QString pixelFormat;
+ QStringList itemRates;
+ for (int i = 0; i < pixelformats.count(); i++) {
+ QString format = pixelformats.at(i).section(':', 0, 0);
+ QStringList sizes = pixelformats.at(i).split(":", QString::SkipEmptyParts);
+ pixelFormat = sizes.takeFirst();
+ for (int j = 0; j < sizes.count(); j++) {
+ itemSize = sizes.at(j).section("=", 0, 0);
+ itemRates = sizes.at(j).section("=", 1, 1).split(",", QString::SkipEmptyParts);
+ for (int k = 0; k < itemRates.count(); k++) {
+ m_capture.v4l_formats->addItem("[" + format + "] " + itemSize + " (" + itemRates.at(k) + ")", QStringList() << format << itemSize.section('x', 0, 0) << itemSize.section('x', 1, 1) << itemRates.at(k).section('/', 0, 0) << itemRates.at(k).section('/', 1, 1));
+ }
+ }
+ }
+ if (!QFile::exists(vl4ProfilePath)) {
+ if (m_capture.v4l_formats->count() > 9) slotSaveCaptureFormat();
+ else {
+ // No existing profile and no autodetected profiles
+ MltVideoProfile profileInfo;
+ profileInfo.width = 320;
+ profileInfo.height = 200;
+ profileInfo.frame_rate_num = 15;
+ profileInfo.frame_rate_den = 1;
+ profileInfo.display_aspect_num = 4;
+ profileInfo.display_aspect_den = 3;
+ profileInfo.sample_aspect_num = 1;
+ profileInfo.sample_aspect_den = 1;
+ profileInfo.progressive = 1;
+ profileInfo.colorspace = 601;
+ ProfilesDialog::saveProfile(profileInfo, vl4ProfilePath);
+ m_capture.v4l_formats->addItem(i18n("Default settings (%1x%2, %3/%4fps)", profileInfo.width, profileInfo.height, profileInfo.frame_rate_num, profileInfo.frame_rate_den), QStringList() << QString("unknown") <<QString::number(profileInfo.width)<<QString::number(profileInfo.height)<<QString::number(profileInfo.frame_rate_num)<<QString::number(profileInfo.frame_rate_den));
+ }
+ }
+ m_capture.v4l_formats->blockSignals(false);
}
void Wizard::checkMltComponents()
KRun::runUrl(KUrl("http://kdenlive.org/discover/" + QString(kdenlive_version).section(' ', 0, 0)), "text/html", this);
}
+void Wizard::slotSaveCaptureFormat()
+{
+ QStringList format = m_capture.v4l_formats->itemData(m_capture.v4l_formats->currentIndex()).toStringList();
+ if (format.isEmpty()) return;
+ MltVideoProfile profile;
+ profile.description = "Video4Linux capture";
+ profile.colorspace = 601;
+ profile.width = format.at(1).toInt();
+ profile.height = format.at(2).toInt();
+ profile.sample_aspect_num = 1;
+ profile.sample_aspect_den = 1;
+ profile.display_aspect_num = format.at(1).toInt();
+ profile.display_aspect_den = format.at(2).toInt();
+ profile.frame_rate_num = format.at(3).toInt();
+ profile.frame_rate_den = format.at(4).toInt();
+ profile.progressive = 1;
+ QString vl4ProfilePath = KStandardDirs::locateLocal("appdata", "profiles/video4linux");
+ ProfilesDialog::saveProfile(profile, vl4ProfilePath);
+}
+
#include "wizard.moc"
void slotShowWebInfos();
void slotDetectWebcam();
void slotUpdateCaptureParameters();
+ void slotSaveCaptureFormat();
};
#endif