#endif
#include <KDebug>
+#include <KLocale>
#include "capture.h"
#include "kdenlivesettings.h"
static int g_videoModeIndex = -1;
static int g_audioChannels = 2;
static int g_audioSampleDepth = 16;
-const char * g_videoOutputFile = NULL;
-const char * g_audioOutputFile = NULL;
static int g_maxFrames = -1;
static QString doCaptureFrame;
static double g_aspect_ratio = 16.0 / 9.0;
if (videoFrame->GetFlags() & bmdFrameHasNoInputSource)
{
+ emit gotMessage(i18n("Frame (%1) - No input signal", frameCount));
fprintf(stderr, "Frame received (#%lu) - No input signal detected\n", frameCount);
}
else
timecode->GetString(&timecodeString);
}
}
-
+ // There seems to be No timecode with HDMI... Using frame number
+ emit gotTimeCode(frameCount);
/*fprintf(stderr, "Frame received (#%lu) [%s] - %s - Size: %li bytes\n",
frameCount,
timecodeString != NULL ? timecodeString : "No timecode",
if (!deckLinkIterator)
{
+ emit gotMessage(i18n("This application requires the DeckLink drivers installed."));
fprintf(stderr, "This application requires the DeckLink drivers installed.\n");
stopCapture();
return;
if (result != S_OK)
{
fprintf(stderr, "No DeckLink PCI cards found.\n");
+ emit gotMessage(i18n("No DeckLink PCI cards found."));
stopCapture();
return;
}
}
delegate = new DeckLinkCaptureDelegate();
+ connect(delegate, SIGNAL(gotTimeCode(ulong)), this, SIGNAL(gotTimeCode(ulong)));
+ connect(delegate, SIGNAL(gotMessage(const QString &)), this, SIGNAL(gotMessage(const QString &)));
deckLinkInput->SetCallback(delegate);
previewView = new CDeckLinkGLWidget(deckLinkInput, m_parent);
result = deckLinkInput->GetDisplayModeIterator(&displayModeIterator);
if (result != S_OK)
{
+ emit gotMessage(i18n("Could not obtain the video output display mode iterator - result = ", result));
fprintf(stderr, "Could not obtain the video output display mode iterator - result = %08x\n", result);
stopCapture();
return;
if (g_videoModeIndex < 0)
{
+ emit gotMessage(i18n("No video mode specified"));
fprintf(stderr, "No video mode specified\n");
stopCapture();
return;
}
- //g_videoOutputFile="/home/one/bm.raw";
- if (g_videoOutputFile != NULL)
+
+ /*if (g_videoOutputFile != NULL)
{
videoOutputFile = open(g_videoOutputFile, O_WRONLY|O_CREAT|O_TRUNC, 0664);
if (videoOutputFile < 0)
{
+ emit gotMessage(i18n("Could not open video output file %1", g_videoOutputFile));
fprintf(stderr, "Could not open video output file \"%s\"\n", g_videoOutputFile);
stopCapture();
}
audioOutputFile = open(g_audioOutputFile, O_WRONLY|O_CREAT|O_TRUNC, 0664);
if (audioOutputFile < 0)
{
+ emit gotMessage(i18n("Could not open audio output file %1", g_audioOutputFile));
fprintf(stderr, "Could not open audio output file \"%s\"\n", g_audioOutputFile);
stopCapture();
}
- }
+ }*/
while (displayModeIterator->Next(&displayMode) == S_OK)
{
if (result == bmdDisplayModeNotSupported)
{
+ emit gotMessage(i18n("The display mode %1 is not supported with the selected pixel format", displayModeName));
fprintf(stderr, "The display mode %s is not supported with the selected pixel format\n", displayModeName);
stopCapture();
return;
{
if (!(displayMode->GetFlags() & bmdDisplayModeSupports3D))
{
+ emit gotMessage(i18n("The display mode %1 is not supported with 3D", displayModeName));
fprintf(stderr, "The display mode %s is not supported with 3D\n", displayModeName);
stopCapture();
return;
if (!foundDisplayMode)
{
+ emit gotMessage(i18n("Invalid mode %1 specified", g_videoModeIndex));
fprintf(stderr, "Invalid mode %d specified\n", g_videoModeIndex);
stopCapture();
return;
result = deckLinkInput->EnableVideoInput(selectedDisplayMode, pixelFormat, inputFlags);
if(result != S_OK)
{
+ emit gotMessage(i18n("Failed to enable video input. Is another application using the card?"));
fprintf(stderr, "Failed to enable video input. Is another application using the card?\n");
stopCapture();
return;
if(result != S_OK)
{
qDebug()<<"/// CAPTURE FAILED....";
+ emit gotMessage(i18n("Capture failed"));
}
// All Okay.
stopCapture();
}
-void CaptureHandler::startCapture()
+void CaptureHandler::startCapture(const QString &path)
{
+ int i = 0;
+ QString videopath = path + "_video_" + QString::number(i).rightJustified(4, '0', false) + ".raw";
+ QString audiopath = path + "_audio_" + QString::number(i).rightJustified(4, '0', false) + ".raw";
+ while (QFile::exists(videopath) || QFile::exists(audiopath)) {
+ i++;
+ videopath = path + "_video_" + QString::number(i).rightJustified(4, '0', false) + ".raw";
+ audiopath = path + "_audio_" + QString::number(i).rightJustified(4, '0', false) + ".raw";
+ }
+ videoOutputFile = open(videopath.toUtf8().constData(), O_WRONLY|O_CREAT|O_TRUNC, 0664);
+ if (videoOutputFile < 0)
+ {
+ emit gotMessage(i18n("Could not open video output file %1", videopath));
+ fprintf(stderr, "Could not open video output file \"%s\"\n", videopath.toUtf8().constData());
+ return;
+ }
+ if (KdenliveSettings::hdmicaptureaudio()) {
+ audioOutputFile = open(audiopath.toUtf8().constData(), O_WRONLY|O_CREAT|O_TRUNC, 0664);
+ if (audioOutputFile < 0)
+ {
+ emit gotMessage(i18n("Could not open audio output file %1", audiopath));
+ fprintf(stderr, "Could not open video output file \"%s\"\n", audiopath.toUtf8().constData());
+ return;
+ }
+ }
}
void CaptureHandler::stopCapture()
{
+ if (videoOutputFile)
+ close(videoOutputFile);
+ if (audioOutputFile)
+ close(audioOutputFile);
+ videoOutputFile = -1;
+ audioOutputFile = -1;
}
void CaptureHandler::captureFrame(const QString &fname)
class CDeckLinkGLWidget;
class PlaybackDelegate;
-class DeckLinkCaptureDelegate : public IDeckLinkInputCallback
+class DeckLinkCaptureDelegate : public QObject, public IDeckLinkInputCallback
{
+Q_OBJECT
public:
DeckLinkCaptureDelegate();
virtual ~DeckLinkCaptureDelegate();
private:
ULONG m_refCount;
pthread_mutex_t m_mutex;
+signals:
+ void gotTimeCode(ulong);
+ void gotMessage(const QString &);
};
-class CaptureHandler
+class CaptureHandler : public QObject
{
+ Q_OBJECT
public:
CaptureHandler(QVBoxLayout *lay, QWidget *parent = 0);
~CaptureHandler();
CDeckLinkGLWidget *previewView;
void startPreview(int deviceId, int captureMode);
void stopPreview();
- void startCapture();
+ void startCapture(const QString &path);
void stopCapture();
void captureFrame(const QString &fname);
void showOverlay(QImage img, bool transparent = true);
IDeckLinkDisplayModeIterator *displayModeIterator;
QVBoxLayout *m_layout;
QWidget *m_parent;
+
+signals:
+ void gotTimeCode(ulong);
+ void gotMessage(const QString &);
};
<label>default HDMI capture mode.</label>
<default>0</default>
</entry>
+
+ <entry name="hdmifilename" type="String">
+ <label>default HDMI capture filename.</label>
+ <default>capture</default>
+ </entry>
+
+ <entry name="hdmicaptureaudio" type="Bool">
+ <label>Should we capture HDMI audio.</label>
+ <default>true</default>
+ </entry>
+
</group>
m_isActive(false),
m_isCapturing(false),
m_didCapture(false),
- m_isPlaying(false)
+ m_isPlaying(false),
+ m_bmCapture(NULL),
+ m_hdmiCapturing(false)
{
setupUi(this);
device_selector->setCurrentIndex(KdenliveSettings::defaultcapture());
connect(device_selector, SIGNAL(currentIndexChanged(int)), this, SLOT(slotVideoDeviceChanged(int)));
-
-
QToolBar *toolbar = new QToolBar(name, this);
QHBoxLayout *layout = new QHBoxLayout;
layout->setContentsMargins(0, 0, 0, 0);
configAction->setCheckable(false);
layout->addWidget(toolbar);
-
+ layout->addWidget(&m_logger);
layout->addWidget(&m_dvinfo);
+ m_logger.setMaxCount(10);
+ m_logger.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ m_logger.setFrame(false);
+ //m_logger.setInsertPolicy(QComboBox::InsertAtTop);
#if KDE_IS_VERSION(4,2,0)
m_freeSpace = new KCapacityBar(KCapacityBar::DrawTextInline, this);
void RecMonitor::slotVideoDeviceChanged(int ix)
{
+ QString capturefile;
+ QString capturename;
+ m_fwdAction->setVisible(ix != HDMI);
+ m_discAction->setVisible(ix != HDMI);
+ m_rewAction->setVisible(ix != HDMI);
+ m_logger.setVisible(ix == HDMI);
switch (ix) {
case SCREENGRAB:
m_discAction->setEnabled(false);
m_playAction->setEnabled(true);
checkDeviceAvailability();
break;
+ case HDMI:
+ createHDMIDevice();
+ m_recAction->setEnabled(false);
+ m_stopAction->setEnabled(false);
+ m_playAction->setEnabled(true);
+ video_capture->setHidden(true);
+ video_frame->setHidden(false);
+
+ capturefile = m_capturePath;
+ if (!capturefile.endsWith("/")) capturefile.append("/");
+ capturename = KdenliveSettings::hdmifilename();
+ capturename.append("xxx.raw");
+ capturefile.append(capturename);
+ video_frame->setPixmap(mergeSideBySide(KIcon("camera-photo").pixmap(QSize(50, 50)), i18n("Plug your camcorder and\npress play button\nto start preview.\nFiles will be saved in:\n%1", capturefile)));
+ break;
default: // FIREWIRE
m_discAction->setEnabled(true);
m_recAction->setEnabled(false);
else KdenliveSettings::setDvgrab_path(dvgrabpath);
} else {
// Show capture info
- QString capturefile = m_capturePath;
+ capturefile = m_capturePath;
if (!capturefile.endsWith("/")) capturefile.append("/");
- QString capturename = KdenliveSettings::dvgrabfilename();
+ capturename = KdenliveSettings::dvgrabfilename();
if (capturename.isEmpty()) capturename = "capture";
QString extension;
switch (KdenliveSettings::firewireformat()) {
}
}
+void RecMonitor::createHDMIDevice()
+{
+ //video_capture->setVisible(true);
+ if (m_bmCapture == NULL) {
+ QVBoxLayout *lay = new QVBoxLayout;
+ m_bmCapture = new CaptureHandler(lay);
+ connect(m_bmCapture, SIGNAL(gotTimeCode(ulong)), this, SLOT(slotGotHDMIFrameNumber(ulong)));
+ connect(m_bmCapture, SIGNAL(gotMessage(const QString &)), this, SLOT(slotGotHDMIMessage(const QString &)));
+ video_capture->setLayout(lay);
+ }
+}
+
+void RecMonitor::slotGotHDMIFrameNumber(ulong ix)
+{
+ m_dvinfo.setText(QString::number(ix));
+}
+
+void RecMonitor::slotGotHDMIMessage(const QString &message)
+{
+ m_logger.insertItem(0, message);
+}
+
QPixmap RecMonitor::mergeSideBySide(const QPixmap& pix, const QString txt)
{
QPainter p;
m_captureProcess->write("q\n", 3);
QTimer::singleShot(1000, m_captureProcess, SLOT(kill()));
break;
+ case HDMI:
+ video_capture->setHidden(true);
+ video_frame->setHidden(false);
+ m_bmCapture->stopPreview();
+ m_playAction->setEnabled(true);
+ m_stopAction->setEnabled(false);
+ m_recAction->setEnabled(false);
+ break;
default:
break;
}
kDebug() << "Capture: Running ffmpeg " << m_captureArgs.join(" ");
m_captureProcess->start("ffmpeg", m_captureArgs);
break;
+ case HDMI:
+ video_capture->setVisible(true);
+ video_frame->setHidden(true);
+ m_bmCapture->startPreview(KdenliveSettings::hdmicapturedevice(), KdenliveSettings::hdmicapturemode());
+ m_playAction->setEnabled(false);
+ m_stopAction->setEnabled(true);
+ m_recAction->setEnabled(true);
+ break;
default:
break;
}
- if (device_selector->currentIndex() != SCREENGRAB) {
+ if (device_selector->currentIndex() == FIREWIRE || device_selector->currentIndex() == VIDEO4LINUX) {
kDebug() << "Capture: Running ffplay " << m_displayArgs.join(" ");
m_displayProcess->start("ffplay", m_displayArgs);
video_frame->setText(i18n("Initialising..."));
void RecMonitor::slotRecord()
{
+ if (device_selector->currentIndex() == HDMI) {
+ if (m_hdmiCapturing) {
+ // We are capturing, stop it
+ m_bmCapture->stopCapture();
+ m_hdmiCapturing = false;
+ }
+ else {
+ // Start capture, get capture filename first
+ QString path = m_capturePath;
+ if (!path.endsWith("/")) path.append("/");
+ path.append(KdenliveSettings::hdmifilename());
+ m_bmCapture->startCapture(path);
+ m_hdmiCapturing = true;
+ }
+ return;
+ }
+
if (m_captureProcess->state() == QProcess::NotRunning && device_selector->currentIndex() == FIREWIRE) {
slotStartCapture();
}
#ifndef RECMONITOR_H
#define RECMONITOR_H
+#include "blackmagic/capture.h"
#include "ui_recmonitor_ui.h"
#include <QToolBar>
#include <KRestrictedLine>
#include <KDateTime>
#include <kdeversion.h>
+#include <KComboBox>
#if KDE_IS_VERSION(4,2,0)
#include <kcapacitybar.h>
QString name() const;
- enum CAPTUREDEVICE {FIREWIRE = 0, VIDEO4LINUX = 1, SCREENGRAB = 2};
+ enum CAPTUREDEVICE {FIREWIRE = 0, VIDEO4LINUX = 1, SCREENGRAB = 2, HDMI = 3};
protected:
virtual void mousePressEvent(QMouseEvent * event);
QString m_name;
bool m_isActive;
KDateTime m_captureTime;
+ /** @brief Provide feedback about dvgrab operations */
QLabel m_dvinfo;
+
+ /** @brief Keeps a brief (max ten items) history of warning or error messages
+ * (currently only used for HDMI). */
+ KComboBox m_logger;
QString m_capturePath;
#if KDE_IS_VERSION(4,2,0)
void checkDeviceAvailability();
QPixmap mergeSideBySide(const QPixmap& pix, const QString txt);
void manageCapturedFiles();
+ CaptureHandler *m_bmCapture;
+ /** @brief Indicates whether we are currently capturing from HDMI. */
+ bool m_hdmiCapturing;
+ void createHDMIDevice();
private slots:
void slotStartCapture(bool play = true);
void slotConfigure();
void slotReadDvgrabInfo();
void slotUpdateFreeSpace();
+ void slotGotHDMIFrameNumber(ulong ix);
+ void slotGotHDMIMessage(const QString &message);
public slots:
void refreshRecMonitor(bool visible);
BMInterface::getBlackMagicDeviceList(capture_device, NULL);
QVBoxLayout *lay = new QVBoxLayout;
m_bmCapture = new CaptureHandler(lay);
+ connect(m_bmCapture, SIGNAL(gotMessage(const QString &)), this, SLOT(slotGotHDMIMessage(const QString &)));
m_frame_preview = new MyLabel(this);
connect(m_frame_preview, SIGNAL(seek(bool)), this, SLOT(slotSeekFrame(bool)));
lay->addWidget(m_frame_preview);
m_bmCapture->stopPreview();
}
+void StopmotionWidget::slotGotHDMIMessage(const QString &message)
+{
+ log_box->insertItem(0, message);
+}
+
void StopmotionWidget::parseExistingSequences()
{
sequence_name->clear();
* @param forward set to true for next frame, false for previous one. */
void slotSeekFrame(bool forward);
+ /** @brief Display warning / error message from capture backend. */
+ void slotGotHDMIMessage(const QString &message);
+
+ /** @brief Create thumbnails for existing sequence frames. */
void slotCreateThumbs(QImage img, int ix);
+
+ /** @brief Prepare thumbnails creation. */
void slotPrepareThumbs();
signals:
<item row="1" column="1">
<widget class="KComboBox" name="hdmi_capturemode"/>
</item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_29">
+ <property name="text">
+ <string>Capture file name</string>
+ </property>
+ </widget>
+ </item>
<item row="2" column="1">
+ <widget class="QLineEdit" name="kcfg_hdmifilename"/>
+ </item>
+ <item row="4" column="1">
<spacer name="verticalSpacer_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</spacer>
</item>
+ <item row="3" column="0" colspan="2">
+ <widget class="QCheckBox" name="kcfg_hdmicaptureaudio">
+ <property name="text">
+ <string>Capture audio</string>
+ </property>
+ </widget>
+ </item>
</layout>
</widget>
</widget>
-<ui version="4.0" >
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
<class>RecMonitor_UI</class>
- <widget class="QWidget" name="RecMonitor_UI" >
- <property name="geometry" >
+ <widget class="QWidget" name="RecMonitor_UI">
+ <property name="geometry">
<rect>
<x>0</x>
<y>0</y>
- <width>306</width>
- <height>242</height>
+ <width>293</width>
+ <height>250</height>
</rect>
</property>
- <layout class="QGridLayout" name="gridLayout_2" >
- <item row="0" column="0" colspan="2" >
- <widget class="QLabel" name="video_frame" >
- <property name="text" >
+ <layout class="QGridLayout" name="gridLayout">
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item row="0" column="0" colspan="3">
+ <widget class="QFrame" name="video_capture">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Plain</enum>
+ </property>
+ <property name="lineWidth">
+ <number>0</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLabel" name="video_frame">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
<string>Not connected</string>
</property>
- <property name="alignment" >
+ <property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
- <item row="1" column="0" colspan="2" >
- <widget class="QFrame" name="control_frame_firewire" >
- <property name="sizePolicy" >
- <sizepolicy vsizetype="Maximum" hsizetype="Preferred" >
+ <item row="2" column="0" colspan="3">
+ <widget class="QFrame" name="control_frame_firewire">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <property name="minimumSize" >
+ <property name="minimumSize">
<size>
<width>0</width>
<height>15</height>
</size>
</property>
- <property name="frameShape" >
+ <property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
- <property name="frameShadow" >
+ <property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
</widget>
</item>
- <item row="2" column="0" >
- <widget class="QCheckBox" name="autoaddbox" >
- <property name="text" >
+ <item row="3" column="0">
+ <widget class="QCheckBox" name="autoaddbox">
+ <property name="text">
<string>Auto add</string>
</property>
- <property name="checked" >
+ <property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
- <item row="2" column="1" >
- <widget class="KComboBox" name="device_selector" >
+ <item row="3" column="2">
+ <widget class="KComboBox" name="device_selector">
<item>
- <property name="text" >
+ <property name="text">
<string>Firewire</string>
</property>
</item>
<item>
- <property name="text" >
+ <property name="text">
<string>Video4Linux</string>
</property>
</item>
<item>
- <property name="text" >
+ <property name="text">
<string>Screen grab</string>
</property>
</item>
+ <item>
+ <property name="text">
+ <string>HDMI</string>
+ </property>
+ </item>
</widget>
</item>
</layout>
<rect>
<x>0</x>
<y>0</y>
- <width>619</width>
- <height>434</height>
+ <width>643</width>
+ <height>395</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QGridLayout" name="gridLayout">
- <item row="0" column="0" colspan="10">
+ <item row="0" column="0" colspan="11">
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
- <item row="1" column="8">
+ <item row="1" column="9">
<widget class="QPushButton" name="button_addsequence">
<property name="text">
- <string>Add sequence to project</string>
+ <string>Add to project</string>
</property>
</widget>
</item>
- <item row="1" column="9">
+ <item row="1" column="10">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
</property>
</widget>
</item>
+ <item row="1" column="8">
+ <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>
</layout>
</widget>
<customwidgets>