Complete rewrite of the video4linux capture to use MLT, in progress.

Breaks Decklink capture for a few days...

svn path=/trunk/kdenlive/; revision=5607
parent 13caa29b
......@@ -282,6 +282,8 @@ set(kdenlive_SRCS
simplekeyframes/simplekeyframewidget.cpp
noteswidget.cpp
archivewidget.cpp
mltdevicecapture.cpp
abstractmonitor.cpp
)
add_definitions(${KDE4_DEFINITIONS})
......@@ -302,13 +304,6 @@ if(NOT APPLE AND NOT CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
${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")
......
/***************************************************************************
* 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);
}
/***************************************************************************
* 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
......@@ -12,7 +12,7 @@
#include "abstractgfxscopewidget.h"
#include "renderer.h"
#include "monitor.h"
#include "monitormanager.h"
#include <QFuture>
#include <QColor>
......@@ -29,18 +29,18 @@
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)
......@@ -50,7 +50,7 @@ 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);
......@@ -59,20 +59,23 @@ void AbstractGfxScopeWidget::mouseReleaseEvent(QMouseEvent *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);
......@@ -86,7 +89,7 @@ void AbstractGfxScopeWidget::slotRenderZoneUpdated(QImage frame)
void AbstractGfxScopeWidget::slotAutoRefreshToggled(bool autoRefresh)
{
if (autoRefresh) {
if (autoRefresh && m_activeRender) {
m_activeRender->sendFrameUpdate();
}
}
......
......@@ -11,31 +11,29 @@
#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.
......@@ -53,7 +51,7 @@ public slots:
/** @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);
......
......@@ -14,8 +14,8 @@
#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);
......
......@@ -20,7 +20,7 @@ class Histogram : public AbstractGfxScopeWidget {
Q_OBJECT
public:
Histogram(Monitor *projMonitor, Monitor *clipMonitor, QWidget *parent = 0);
Histogram(MonitorManager *manager, QWidget *parent = 0);
~Histogram();
QString widgetName() const;
......
......@@ -16,8 +16,8 @@
#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);
......
......@@ -23,7 +23,7 @@ class RGBParadeGenerator;
class RGBParade : public AbstractGfxScopeWidget
{
public:
RGBParade(Monitor *projMonitor, Monitor *clipMonitor, QWidget *parent = 0);
RGBParade(MonitorManager *manager, QWidget *parent = 0);
~RGBParade();
QString widgetName() const;
......
......@@ -42,8 +42,8 @@ const QPointF YPbPr_Mg(.331, .419);
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();
......
......@@ -28,7 +28,7 @@ class Vectorscope : public AbstractGfxScopeWidget {
Q_OBJECT
public:
Vectorscope(Monitor *projMonitor, Monitor *clipMonitor, QWidget *parent = 0);
Vectorscope(MonitorManager *manager, QWidget *parent = 0);
~Vectorscope();
QString widgetName() const;
......
......@@ -25,8 +25,8 @@
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();
......
......@@ -22,7 +22,7 @@ class Waveform : public AbstractGfxScopeWidget {
Q_OBJECT
public:
Waveform(Monitor *projMonitor, Monitor *clipMonitor, QWidget *parent = 0);
Waveform(MonitorManager *manager, QWidget *parent = 0);
~Waveform();
virtual QString widgetName() const;
......
......@@ -224,7 +224,6 @@ signals:
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.
......
......@@ -312,64 +312,39 @@
<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">
......
This diff is collapsed.
......@@ -53,7 +53,6 @@ protected slots:
private slots:
void slotUpdateDisplay();
void rebuildVideo4Commands();
#ifndef NO_JOGSHUTTLE
void slotCheckShuttle(int state = 0);
void slotUpdateShuttleDevice(int ix = 0);
......@@ -71,6 +70,7 @@ private slots:
void slotEnableCaptureFolder();
void slotUpdateHDMIModes();
void slotUpdatev4lDevice();
void slotUpdatev4lCaptureProfile();
private:
KPageWidgetItem *m_page1;
......@@ -99,6 +99,8 @@ private:
void initDevices();
void loadTranscodeProfiles();
void saveTranscodeProfiles();
void loadCurrentV4lProfileInfo();
void saveCurrentV4lProfile();
signals:
void customChanged();
......
This diff is collapsed.
......@@ -345,7 +345,7 @@ private slots:
/** @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);
......
This diff is collapsed.
/***************************************************************************
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 &params, 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.
*