]> git.sesse.net Git - kdenlive/commitdiff
Improved performance for blackmagic picture grab and various usability improvements...
authorJean-Baptiste Mardelle <jb@kdenlive.org>
Mon, 25 Oct 2010 21:58:06 +0000 (21:58 +0000)
committerJean-Baptiste Mardelle <jb@kdenlive.org>
Mon, 25 Oct 2010 21:58:06 +0000 (21:58 +0000)
svn path=/trunk/kdenlive/; revision=5052

src/blackmagic/capture.cpp
src/blackmagic/capture.h
src/stopmotion/capturehandler.h
src/stopmotion/stopmotion.cpp
src/stopmotion/stopmotion.h
src/v4l/v4lcapture.cpp
src/v4l/v4lcapture.h

index 6aa13cadfc155c5399825ad0a5e56eda18f09a19..8afb4d25aede8fd4b89b558fdb6c3396ab8936d9 100644 (file)
@@ -315,6 +315,29 @@ ULONG DeckLinkCaptureDelegate::Release(void)
     return (ULONG)m_refCount;
 }
 
+void DeckLinkCaptureDelegate::slotProcessFrame()
+{
+    if (m_framesList.isEmpty()) return;
+    IDeckLinkVideoInputFrame* videoFrame = m_framesList.takeFirst();
+    QString capturePath = m_framePath.takeFirst();
+    void *frameBytes;
+    videoFrame->GetBytes(&frameBytes);
+    if (capturePath.endsWith("raw")) {
+        // Save as raw uyvy422 imgage
+        videoOutputFile = open(capturePath.toUtf8().constData(), O_WRONLY | O_CREAT/*|O_TRUNC*/, 0664);
+        write(videoOutputFile, frameBytes, videoFrame->GetRowBytes() * videoFrame->GetHeight());
+        close(videoOutputFile);
+        emit frameSaved(capturePath);
+    } else {
+        QImage image(videoFrame->GetWidth(), videoFrame->GetHeight(), QImage::Format_ARGB32_Premultiplied);
+        //convert from uyvy422 to rgba
+        CaptureHandler::yuv2rgb((uchar *)frameBytes, (uchar *)image.bits(), videoFrame->GetWidth(), videoFrame->GetHeight());
+        image.save(capturePath);
+        emit frameSaved(capturePath);
+    }
+    videoFrame->Release();
+}
+
 HRESULT DeckLinkCaptureDelegate::VideoInputFrameArrived(IDeckLinkVideoInputFrame* videoFrame, IDeckLinkAudioInputPacket* audioFrame)
 {
     IDeckLinkVideoFrame*                    rightEyeFrame = NULL;
@@ -354,21 +377,11 @@ HRESULT DeckLinkCaptureDelegate::VideoInputFrameArrived(IDeckLinkVideoInputFrame
                 free((void*)timecodeString);
 
             if (!doCaptureFrame.isEmpty()) {
-                videoFrame->GetBytes(&frameBytes);
-                if (doCaptureFrame.endsWith("raw")) {
-                    // Save as raw uyvy422 imgage
-                    videoOutputFile = open(doCaptureFrame.toUtf8().constData(), O_WRONLY | O_CREAT/*|O_TRUNC*/, 0664);
-                    write(videoOutputFile, frameBytes, videoFrame->GetRowBytes() * videoFrame->GetHeight());
-                    close(videoOutputFile);
-                    emit frameSaved(doCaptureFrame);
-                } else {
-                    QImage image(videoFrame->GetWidth(), videoFrame->GetHeight(), QImage::Format_ARGB32_Premultiplied);
-                    //convert from uyvy422 to rgba
-                    CaptureHandler::yuv2rgb((uchar *)frameBytes, (uchar *)image.bits(), videoFrame->GetWidth(), videoFrame->GetHeight());
-                    image.save(doCaptureFrame);
-                    emit frameSaved(doCaptureFrame);
-                }
+                videoFrame->AddRef();
+                m_framesList.append(videoFrame);
+                m_framePath.append(doCaptureFrame);
                 doCaptureFrame.clear();
+                QtConcurrent::run(this, &DeckLinkCaptureDelegate::slotProcessFrame);
             }
 
             if (videoOutputFile != -1) {
@@ -484,7 +497,7 @@ QString BmdCaptureHandler::getDeviceName(QString)
     return QString();
 }
 
-void BmdCaptureHandler::startPreview(int deviceId, int captureMode)
+void BmdCaptureHandler::startPreview(int deviceId, int captureMode, bool audio)
 {
     deckLinkIterator = CreateDeckLinkIteratorInstance();
     BMDVideoInputFlags          inputFlags = 0;
@@ -693,10 +706,12 @@ void BmdCaptureHandler::startPreview(int deviceId, int captureMode)
         return;
     }
 
-    result = deckLinkInput->EnableAudioInput(bmdAudioSampleRate48kHz, g_audioSampleDepth, g_audioChannels);
-    if (result != S_OK) {
-        stopCapture();
-        return;
+    if (audio) {
+        result = deckLinkInput->EnableAudioInput(bmdAudioSampleRate48kHz, g_audioSampleDepth, g_audioChannels);
+        if (result != S_OK) {
+            stopCapture();
+            return;
+        }
     }
     deckLinkInput->SetScreenPreviewCallback(previewView);
     result = deckLinkInput->StartStreams();
index dcf68f81fb62d3fadfed73d1e1e6691edade4cf5..b58b40c1383ce11be798cb5c265394bbf2e20a65 100644 (file)
@@ -32,6 +32,12 @@ public:
 private:
     ULONG               m_refCount;
     pthread_mutex_t     m_mutex;
+    QList <IDeckLinkVideoInputFrame*> m_framesList;
+    QStringList m_framePath;
+
+private slots:
+    void slotProcessFrame();
+
 signals:
     void gotTimeCode(ulong);
     void gotMessage(const QString &);
@@ -45,7 +51,7 @@ public:
     BmdCaptureHandler(QVBoxLayout *lay, QWidget *parent = 0);
     ~BmdCaptureHandler();
     CDeckLinkGLWidget *previewView;
-    void startPreview(int deviceId, int captureMode);
+    void startPreview(int deviceId, int captureMode, bool audio = true);
     void stopPreview();
     void startCapture(const QString &path);
     void stopCapture();
index e8b755ba3318423f7eeabfbec3008b299562e987..c91a5d5ff555dcba4e874b6d3f391949e9889a10 100644 (file)
@@ -30,7 +30,7 @@ class CaptureHandler : public QObject
 public:
     CaptureHandler(QVBoxLayout *lay, QWidget *parent = 0);
     ~CaptureHandler();
-    virtual void startPreview(int deviceId, int captureMode) = 0;
+    virtual void startPreview(int deviceId, int captureMode, bool audio = true) = 0;
     virtual void stopPreview() = 0;
     virtual void startCapture(const QString &path) = 0;
     virtual void stopCapture();
index a3c2413331d55e13a348da30d464482732a857e4..2094396e7bfca0b1145a8ad2fe68f330074cf5c0 100644 (file)
@@ -61,6 +61,12 @@ void MyLabel::wheelEvent(QWheelEvent * event)
     else emit seek(false);
 }
 
+//virtual
+void MyLabel::mousePressEvent(QMouseEvent *)
+{
+    emit switchToLive();
+}
+
 //virtual
 void MyLabel::paintEvent(QPaintEvent * event)
 {
@@ -153,8 +159,8 @@ StopmotionWidget::StopmotionWidget(KUrl projectFolder, const QList< QAction * >
     connect(showThumbs, SIGNAL(triggered(bool)), this, SLOT(slotShowThumbs(bool)));
 
     QAction *removeCurrent = new QAction(KIcon("edit-delete"), i18n("Delete current frame"), this);
-    //TODO: implement frame deletion
-    //connect(removeCurrent, SIGNAL(triggered()), this, SLOT(slotRemoveFrame()));
+    removeCurrent->setShortcut(Qt::Key_Delete);
+    connect(removeCurrent, SIGNAL(triggered()), this, SLOT(slotRemoveFrame()));
 
     QAction *capInterval = new QAction(KIcon(), i18n("Set capture interval"), this);
     connect(capInterval, SIGNAL(triggered()), this, SLOT(slotSetCaptureInterval()));
@@ -175,6 +181,8 @@ StopmotionWidget::StopmotionWidget(KUrl projectFolder, const QList< QAction * >
     capture_button->setMenu(capMenu);
 
     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;
     if (BMInterface::getBlackMagicDeviceList(capture_device, NULL)) {
         // Found a BlackMagic device
@@ -190,6 +198,7 @@ StopmotionWidget::StopmotionWidget(KUrl projectFolder, const QList< QAction * >
     connect(capture_device, SIGNAL(currentIndexChanged(int)), this, SLOT(slotUpdateHandler()));
     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);
     m_frame_preview->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
     video_preview->setLayout(m_layout);
@@ -199,8 +208,11 @@ StopmotionWidget::StopmotionWidget(KUrl projectFolder, const QList< QAction * >
     connect(button_addsequence, SIGNAL(clicked(bool)), this, SLOT(slotAddSequence()));
     connect(preview_button, SIGNAL(clicked(bool)), this, SLOT(slotPlayPreview(bool)));
     connect(frame_list, SIGNAL(currentRowChanged(int)), this, SLOT(slotShowSelectedFrame()));
+    connect(frame_list, SIGNAL(itemClicked(QListWidgetItem *)), this, SLOT(slotShowSelectedFrame()));
     connect(this, SIGNAL(doCreateThumbs(QImage, int)), this, SLOT(slotCreateThumbs(QImage, int)));
 
+    frame_list->addAction(removeCurrent);
+    frame_list->setContextMenuPolicy(Qt::ActionsContextMenu);
     frame_list->setHidden(!KdenliveSettings::showstopmotionthumbs());
     parseExistingSequences();
 }
@@ -304,7 +316,7 @@ void StopmotionWidget::slotLive(bool isOn)
     if (isOn) {
         //m_frame_preview->setImage(QImage());
         m_frame_preview->setHidden(true);
-        m_bmCapture->startPreview(KdenliveSettings::hdmi_capturedevice(), KdenliveSettings::hdmi_capturemode());
+        m_bmCapture->startPreview(KdenliveSettings::hdmi_capturedevice(), KdenliveSettings::hdmi_capturemode(), false);
         capture_button->setEnabled(true);
     } else {
         m_bmCapture->stopPreview();
@@ -404,7 +416,6 @@ void StopmotionWidget::slotCaptureFrame()
     }
     //capture_button->setEnabled(false);
     QString currentPath = getPathForFrame(m_sequenceFrame);
-    kDebug() << "Capture FRame NB: " << m_sequenceFrame;
     m_bmCapture->captureFrame(currentPath);
     KNotification::event("FrameCaptured");
     m_sequenceFrame++;
@@ -450,6 +461,9 @@ void StopmotionWidget::slotCreateThumbs(QImage img, int ix)
     QListWidgetItem *item = new QListWidgetItem(icon, QString(), frame_list);
     item->setToolTip(getPathForFrame(ix, sequence_name->currentText()));
     item->setData(Qt::UserRole, ix);
+    frame_list->blockSignals(true);
+    frame_list->setCurrentItem(item);
+    frame_list->blockSignals(false);
     m_future = QtConcurrent::run(this, &StopmotionWidget::slotPrepareThumbs);
 }
 
@@ -509,11 +523,11 @@ void StopmotionWidget::slotAnimate()
         //TODO: loop
         if (frame_list->currentRow() < (frame_list->count() - 1)) {
             frame_list->setCurrentRow(frame_list->currentRow() + 1);
-            QTimer::singleShot(200, this, SLOT(slotAnimate()));
+            QTimer::singleShot(100, this, SLOT(slotAnimate()));
         } else preview_button->setChecked(false);
     } else if (!m_animationList.isEmpty()) {
         slotShowFrame(m_animationList.takeFirst());
-        QTimer::singleShot(200, this, SLOT(slotAnimate()));
+        QTimer::singleShot(100, this, SLOT(slotAnimate()));
     } else preview_button->setChecked(false);
 
 }
@@ -568,4 +582,14 @@ void StopmotionWidget::slotSeekFrame(bool forward)
     } else if (ix > 0) frame_list->setCurrentRow(ix - 1);
 }
 
-
+void StopmotionWidget::slotRemoveFrame()
+{
+    if (frame_list->currentItem() == NULL) return;
+    QString path = frame_list->currentItem()->toolTip();
+    if (KMessageBox::questionYesNo(this, i18n("Delete frame %1 from disk?", path), i18n("Delete Frame")) != KMessageBox::Yes) return;
+    QFile f(path);
+    if (f.remove()) {
+        QListWidgetItem *item = frame_list->takeItem(frame_list->currentRow());
+        delete item;
+    }
+}
index 0f3f27bbca4bfbe1d6361cd0304a849eee1c7ddf..bd74a5217a6838820ebd0a814962625b0cca98e1 100644 (file)
@@ -36,6 +36,7 @@ public:
 protected:
     virtual void paintEvent(QPaintEvent * event);
     virtual void wheelEvent(QWheelEvent * event);
+    virtual void mousePressEvent(QMouseEvent *);
 
 private:
     QImage m_img;
@@ -44,6 +45,9 @@ signals:
     /** @brief Seek to next or previous frame.
      *  @param forward set to true to go to next frame, fals to go to previous frame */
     void seek(bool forward);
+
+    /** @brief Switch to live view. */
+    void switchToLive();
 };
 
 class StopmotionWidget : public QDialog , public Ui::Stopmotion_UI
@@ -185,8 +189,12 @@ private slots:
     /** @brief Set the effect to be applied to overlay frame. */
     void slotUpdateOverlayEffect(QAction *act);
 
-    /** @brief Switch between live view / currently selected fram. */
+    /** @brief Switch between live view / currently selected frame. */
     void slotSwitchLive();
+
+    /** @brief Delete current frame from disk. */
+    void slotRemoveFrame();
+
 signals:
     /** @brief Ask to add sequence to current project. */
     void addOrUpdateSequence(const QString);
index 51b1993d2c0c286a42dda7700e2bed3ed19a8e60..8ede6e3fc426254256af8fd1ffb1c7fa56fb98e4 100644 (file)
@@ -160,7 +160,7 @@ QString V4lCaptureHandler::getDeviceName(QString input)
     return deviceName.isEmpty() ? input : deviceName;
 }
 
-void V4lCaptureHandler::startPreview(int /*deviceId*/, int /*captureMode*/)
+void V4lCaptureHandler::startPreview(int /*deviceId*/, int /*captureMode*/, bool)
 {
     m_display->setHidden(false);
     fswebcam_config_t *config;
index bbcbf8833116a7cfb04c3345d76f76a8eb2fccea..a1778b3b23da3ea673ebc5a3ea1a5bb5947ac973 100644 (file)
@@ -36,7 +36,7 @@ class V4lCaptureHandler : public CaptureHandler
 public:
     V4lCaptureHandler(QVBoxLayout *lay, QWidget *parent = 0);
     ~V4lCaptureHandler();
-    void startPreview(int deviceId, int captureMode);
+    void startPreview(int deviceId, int captureMode, bool audio = true);
     void stopPreview();
     void startCapture(const QString &path);
     void stopCapture();