]> git.sesse.net Git - kdenlive/commitdiff
First steps to support MLT's new Blackmagic's consumer (means external video display...
authorJean-Baptiste Mardelle <jb@kdenlive.org>
Sun, 14 Nov 2010 16:14:14 +0000 (16:14 +0000)
committerJean-Baptiste Mardelle <jb@kdenlive.org>
Sun, 14 Nov 2010 16:14:14 +0000 (16:14 +0000)
svn path=/trunk/kdenlive/; revision=5094

src/blackmagic/devices.cpp
src/blackmagic/devices.h
src/kdenlivesettings.kcfg
src/kdenlivesettingsdialog.cpp
src/profilesdialog.h
src/renderer.cpp
src/widgets/configsdl_ui.ui

index a9bcefa9de13b4604e9a3d207c4ecc3eadd6f6a6..8c139b71abc3c80dfc7a9efa1fc12a2a464a897f 100644 (file)
@@ -141,4 +141,209 @@ bool BMInterface::getBlackMagicDeviceList(KComboBox *devicelist, KComboBox *mode
         modelist->insertItems(0, modes);
     }
     return found;
-}
\ No newline at end of file
+}
+
+//static
+bool BMInterface::getBlackMagicOutputDeviceList(KComboBox *devicelist)
+{
+    IDeckLinkIterator* deckLinkIterator;
+    IDeckLink* deckLink;
+    int numDevices = 0;
+    HRESULT result;
+    bool found = false;
+
+    // Create an IDeckLinkIterator object to enumerate all DeckLink cards in the system
+    deckLinkIterator = CreateDeckLinkIteratorInstance();
+    if(deckLinkIterator == NULL) {
+        kDebug() << "A DeckLink iterator could not be created.  The DeckLink drivers may not be installed.";
+        return found;
+    }
+
+    // Enumerate all cards in this system
+    while(deckLinkIterator->Next(&deckLink) == S_OK) {
+        char *      deviceNameString = NULL;
+
+        // Increment the total number of DeckLink cards found
+        numDevices++;
+        //if (numDevices > 1)
+        kDebug() << "// FOUND a BM device\n\n+++++++++++++++++++++++++++++++++++++";
+
+        // *** Print the model name of the DeckLink card
+        result = deckLink->GetModelName((const char **) &deviceNameString);
+        if(result == S_OK) {
+            QString deviceName(deviceNameString);
+            free(deviceNameString);
+
+            IDeckLinkOutput*                 deckLinkOutput = NULL;
+            IDeckLinkDisplayModeIterator*       displayModeIterator = NULL;
+            IDeckLinkDisplayMode*               displayMode = NULL;
+            HRESULT                             result;
+
+            // Query the DeckLink for its configuration interface
+            result = deckLink->QueryInterface(IID_IDeckLinkInput, (void**)&deckLinkOutput);
+            if(result != S_OK) {
+                kDebug() << "Could not obtain the IDeckLinkInput interface - result = " << result;
+                return found;
+            }
+
+            // Obtain an IDeckLinkDisplayModeIterator to enumerate the display modes supported on output
+            result = deckLinkOutput->GetDisplayModeIterator(&displayModeIterator);
+            if(result != S_OK) {
+                kDebug() << "Could not obtain the video input display mode iterator - result = " << result;
+                return found;
+            }
+            /*QStringList availableModes;
+            // List all supported output display modes
+            while(displayModeIterator->Next(&displayMode) == S_OK) {
+                char *          displayModeString = NULL;
+
+                result = displayMode->GetName((const char **) &displayModeString);
+                if(result == S_OK) {
+                    //char                  modeName[64];
+                    int                     modeWidth;
+                    int                     modeHeight;
+                    BMDTimeValue            frameRateDuration;
+                    BMDTimeScale            frameRateScale;
+                    //int                       pixelFormatIndex = 0; // index into the gKnownPixelFormats / gKnownFormatNames arrays
+                    //BMDDisplayModeSupport displayModeSupport;
+
+
+                    // Obtain the display mode's properties
+                    modeWidth = displayMode->GetWidth();
+                    modeHeight = displayMode->GetHeight();
+                    displayMode->GetFrameRate(&frameRateDuration, &frameRateScale);
+                    QString description = QString(displayModeString) + " (" + QString::number(modeWidth) + "x" + QString::number(modeHeight) + " - " + QString::number((double)frameRateScale / (double)frameRateDuration) + i18n("fps") + ")";
+                   description.append(" " + QString::number(modeWidth) + ":" + QString::number(modeHeight) + ":" + QString::number(frameRateScale) + ":" + QString::number(frameRateDuration) + ":" + QString::number(displayMode->GetFieldDominance() == bmdProgressiveFrame));
+                    availableModes << description;
+                    free(displayModeString);
+                }
+
+                // Release the IDeckLinkDisplayMode object to prevent a leak
+                displayMode->Release();
+            }*/
+            devicelist->addItem(deviceName);
+            found = true;
+        }
+
+        // Release the IDeckLink instance when we've finished with it to prevent leaks
+        deckLink->Release();
+    }
+
+    deckLinkIterator->Release();
+    return found;
+}
+
+//static
+bool BMInterface::isSupportedProfile(int card, QMap< QString, QString > properties)
+{
+    IDeckLinkIterator* deckLinkIterator;
+    IDeckLink* deckLink;
+    HRESULT result;
+    bool found = false;
+
+    // Create an IDeckLinkIterator object to enumerate all DeckLink cards in the system
+    deckLinkIterator = CreateDeckLinkIteratorInstance();
+    if(deckLinkIterator == NULL) {
+        kDebug() << "A DeckLink iterator could not be created.  The DeckLink drivers may not be installed.";
+        return false;
+    }
+
+    while(card >= 0 && deckLinkIterator->Next(&deckLink) == S_OK) {
+       card --;
+    }
+
+    IDeckLinkOutput*                 deckLinkOutput = NULL;
+    IDeckLinkDisplayModeIterator*       displayModeIterator = NULL;
+    IDeckLinkDisplayMode*               displayMode = NULL;
+
+    // Query the DeckLink for its configuration interface
+    result = deckLink->QueryInterface(IID_IDeckLinkInput, (void**)&deckLinkOutput);
+    if(result != S_OK) {
+        kDebug() << "Could not obtain the IDeckLinkInput interface - result = " << result;
+        return false;
+    }
+
+    // Obtain an IDeckLinkDisplayModeIterator to enumerate the display modes supported on output
+    result = deckLinkOutput->GetDisplayModeIterator(&displayModeIterator);
+    if(result != S_OK) {
+       kDebug() << "Could not obtain the video input display mode iterator - result = " << result;
+        return false;
+    }
+    // List all supported output display modes
+    BMDTimeValue            frameRateDuration;
+    BMDTimeScale            frameRateScale;
+    
+    while(displayModeIterator->Next(&displayMode) == S_OK) {
+       if (displayMode->GetWidth() == properties.value("width").toInt() && displayMode->GetHeight() == properties.value("height").toInt()) {
+           int progressive = displayMode->GetFieldDominance() == bmdProgressiveFrame;
+           if (progressive == properties.value("progressive").toInt()) {
+               displayMode->GetFrameRate(&frameRateDuration, &frameRateScale);
+               if (frameRateScale / properties.value("frame_rate_num").toDouble() * properties.value("frame_rate_den").toDouble() == frameRateDuration) {
+                   found = true;
+                   break;
+               }
+           }
+       }
+       displayMode->Release();
+    }
+
+    deckLink->Release();
+    deckLinkIterator->Release();
+    return found;
+}
+
+
+//static
+QStringList BMInterface::supportedModes(int card)
+{
+    IDeckLinkIterator* deckLinkIterator;
+    IDeckLink* deckLink;
+    HRESULT result;
+    QStringList modes;
+
+    // Create an IDeckLinkIterator object to enumerate all DeckLink cards in the system
+    deckLinkIterator = CreateDeckLinkIteratorInstance();
+    if(deckLinkIterator == NULL) {
+        kDebug() << "A DeckLink iterator could not be created.  The DeckLink drivers may not be installed.";
+        return modes;
+    }
+
+    while(card >= 0 && deckLinkIterator->Next(&deckLink) == S_OK) {
+       card --;
+    }
+
+    IDeckLinkOutput*                 deckLinkOutput = NULL;
+    IDeckLinkDisplayModeIterator*       displayModeIterator = NULL;
+    IDeckLinkDisplayMode*               displayMode = NULL;
+
+    // Query the DeckLink for its configuration interface
+    result = deckLink->QueryInterface(IID_IDeckLinkInput, (void**)&deckLinkOutput);
+    if(result != S_OK) {
+        kDebug() << "Could not obtain the IDeckLinkInput interface - result = " << result;
+        return modes;
+    }
+
+    // Obtain an IDeckLinkDisplayModeIterator to enumerate the display modes supported on output
+    result = deckLinkOutput->GetDisplayModeIterator(&displayModeIterator);
+    if(result != S_OK) {
+       kDebug() << "Could not obtain the video input display mode iterator - result = " << result;
+        return modes;
+    }
+
+    while(displayModeIterator->Next(&displayMode) == S_OK) {
+        char *          displayModeString = NULL;
+        result = displayMode->GetName((const char **) &displayModeString);
+       if(result == S_OK) {
+           QString description = QString(displayModeString);
+           modes.append(description);
+           free(displayModeString);
+       }
+       // Release the IDeckLinkDisplayMode object to prevent a leak
+       displayMode->Release();
+    }
+
+    deckLink->Release();
+    deckLinkIterator->Release();
+    return modes;
+}
+
index ad95456cd23004a495292ac1e2581c804ba1d2e4..ce77c568233a0d4f8ba32286beafa021dddac1cc 100644 (file)
@@ -13,6 +13,9 @@ public:
     BMInterface();
     ~BMInterface();
     static bool getBlackMagicDeviceList(KComboBox *devicelist, KComboBox *modelist);
+    static bool getBlackMagicOutputDeviceList(KComboBox *devicelist);
+    static bool isSupportedProfile(int card, QMap< QString, QString > properties);
+    static QStringList supportedModes(int card);
 };
 
 #endif
\ No newline at end of file
index 852e04406194fbb0003068c4b49d5e195f0bb38d..39923e76ba63c3891a12fa37faee2d1e0f0087b0 100644 (file)
       <default>100</default>
     </entry>
 
-  </group>
+    <entry name="external_display" type="Bool">
+      <label>Use Blackmagic device for video out.</label>
+      <default>false</default>
+    </entry>
+    <entry name="blackmagic_output_device" type="UInt">
+      <label>Blackmagic video output device.</label>
+      <default>0</default>
+    </entry>
+</group>
 
   <group name="env">
     <entry name="activate_nepomuk" type="Bool">
index e997fa76fab527a423d20a99c4f663667a64f854..86624d5503697592f6d87df490834853838be133 100644 (file)
@@ -187,6 +187,10 @@ KdenliveSettingsDialog::KdenliveSettingsDialog(QWidget * parent) :
     BMInterface::getBlackMagicDeviceList(m_configCapture.kcfg_hdmi_capturedevice, m_configCapture.kcfg_hdmi_capturemode);
     connect(m_configCapture.kcfg_hdmi_capturedevice, SIGNAL(currentIndexChanged(int)), this, SLOT(slotUpdateHDMIModes()));
 
+    if (BMInterface::getBlackMagicOutputDeviceList(m_configSdl.kcfg_blackmagic_output_device)) {
+        // Found blackmagic card
+    } else m_configSdl.kcfg_external_display->setEnabled(false);
+
     double dvgrabVersion = 0;
     if (!KdenliveSettings::dvgrab_path().isEmpty()) {
         QProcess *versionCheck = new QProcess;
index ef4ea0865972f7eeca04b44d05ea0791a8915220..a9927babaa901bfda785a0054e3cc248a7cc3885 100644 (file)
@@ -52,7 +52,7 @@ public:
      *  @return true if properties match profile */
     static bool matchProfile(int width, int height, double fps, double par, bool isImage, MltVideoProfile profile);
 
-    /** @brief Find a profile to match parameter properties:
+    /** @brief Find profiles that match parameter properties:
      *  @param width The profile frame width
      *  @param height The profile frame height
      *  @param fps The profile fps
index d785dec093dd3185541add7cd4b6cdfbb07b739b..62626128766907a52070ee26fb12e62e97709ba3 100644 (file)
@@ -28,6 +28,8 @@
 #include "kthumb.h"
 #include "definitions.h"
 #include "slideshowclip.h"
+#include "profilesdialog.h"
+#include "blackmagic/devices.h"
 
 #include <mlt++/Mlt.h>
 
@@ -181,6 +183,29 @@ void Render::buildConsumer(const QString profileName)
     m_mltProfile->get_profile()->is_explicit = 1;
     delete[] tmp;
 
+    m_blackClip = new Mlt::Producer(*m_mltProfile, "colour", "black");
+    m_blackClip->set("id", "black");
+    m_blackClip->set("mlt_type", "producer");
+
+    if (KdenliveSettings::external_display() && m_name != "clip") {
+        // Use blackmagic card for video output
+        QMap< QString, QString > profileProperties = ProfilesDialog::getSettingsFromFile(profileName);
+        if (BMInterface::isSupportedProfile(KdenliveSettings::blackmagic_output_device(), profileProperties)) {
+            QString decklink = "decklink:" + QString::number(KdenliveSettings::blackmagic_output_device());
+            tmp = qstrdup(decklink.toUtf8().constData());
+            m_mltConsumer = new Mlt::Consumer(*m_mltProfile, tmp);
+            delete[] tmp;
+            if (m_mltConsumer) {
+                m_mltConsumer->listen("consumer-frame-show", this, (mlt_listener) consumer_frame_show);
+                m_mltConsumer->set("terminate_on_pause", 0);
+                m_mltConsumer->set("audio_buffer", 1024);
+                m_mltConsumer->set("frequency", 48000);
+                mlt_log_set_callback(kdenlive_callback);
+            }
+            if (m_mltConsumer && m_mltConsumer->is_valid()) return;
+        } else KMessageBox::informationList(qApp->activeWindow(), i18n("Your project's profile %1 is not compatible with the blackmagic output card. Please see supported profiles below. Switching to normal video display.", m_mltProfile->description()), BMInterface::supportedModes(KdenliveSettings::blackmagic_output_device()));
+    }
+
     QString videoDriver = KdenliveSettings::videodrivername();
     if (!videoDriver.isEmpty()) {
         if (videoDriver == "x11_noaccel") {
@@ -232,10 +257,6 @@ void Render::buildConsumer(const QString profileName)
     m_mltConsumer->set("progressive", 1);
     m_mltConsumer->set("audio_buffer", 1024);
     m_mltConsumer->set("frequency", 48000);
-
-    m_blackClip = new Mlt::Producer(*m_mltProfile, "colour", "black");
-    m_blackClip->set("id", "black");
-    m_blackClip->set("mlt_type", "producer");
 }
 
 Mlt::Producer *Render::invalidProducer(const QString &id)
@@ -249,6 +270,7 @@ Mlt::Producer *Render::invalidProducer(const QString &id)
 int Render::resetProfile(const QString profileName)
 {
     if (m_mltConsumer) {
+        if (KdenliveSettings::external_display() && m_activeProfile == profileName) return 1;
         QString videoDriver = KdenliveSettings::videodrivername();
         QString currentDriver = m_mltConsumer->get("video_driver");
         if (getenv("SDL_VIDEO_YUV_HWACCEL") != NULL && currentDriver == "x11") currentDriver = "x11_noaccel";
@@ -536,7 +558,7 @@ void Render::getFileProperties(const QDomElement xml, const QString &clipId, int
         int aspectNumerator = xml.attribute("force_aspect_num").toInt();
         int aspectDenominator = xml.attribute("force_aspect_den").toInt();
         if (aspectDenominator != 0 && width != 0)
-            producer->set("force_aspect_ratio", double(height) * aspectNumerator / aspectDenominator / width );
+            producer->set("force_aspect_ratio", double(height) * aspectNumerator / aspectDenominator / width);
     }
 
     if (xml.hasAttribute("force_fps")) {
@@ -1197,17 +1219,20 @@ void Render::pause()
 
 void Render::switchPlay()
 {
+    kDebug() << "// SWITCH PLAY";
     if (!m_mltProducer || !m_mltConsumer)
         return;
     if (m_isZoneMode) resetZoneMode();
     if (m_mltProducer->get_speed() == 0.0) {
         m_isBlocked = false;
+        kDebug() << "// SWITCH PLAY, set spped to 1";
         if (m_name == "clip" && m_framePosition == (int) m_mltProducer->get_out()) m_mltProducer->seek(0);
         m_mltProducer->set_speed(1.0);
         m_mltConsumer->set("refresh", 1);
     } else {
         m_isBlocked = true;
         m_mltConsumer->set("refresh", 0);
+        kDebug() << "// SWITCH PLAY, set spped to 0";
         m_mltProducer->set_speed(0.0);
         //emit rendererPosition(m_framePosition);
         m_mltProducer->seek(m_framePosition);
index cee49078449593c6587e5444c4133bd99c761159..200a34c1a862e4f8d43b10d807dc72451feb8fbb 100644 (file)
@@ -7,7 +7,7 @@
     <x>0</x>
     <y>0</y>
     <width>342</width>
-    <height>241</height>
+    <height>296</height>
    </rect>
   </property>
   <layout class="QGridLayout" name="gridLayout_2">
      </property>
     </widget>
    </item>
+   <item row="1" column="0" colspan="3">
+    <widget class="QCheckBox" name="kcfg_openglmonitors">
+     <property name="text">
+      <string>Use OpenGL for video display (restart Kdenlive to apply)</string>
+     </property>
+    </widget>
+   </item>
    <item row="2" column="0">
     <widget class="QLabel" name="textLabel1_2_2">
      <property name="sizePolicy">
    <item row="4" column="1" colspan="2">
     <widget class="KComboBox" name="kcfg_audio_device"/>
    </item>
-   <item row="6" column="2">
-    <widget class="KColorButton" name="kcfg_window_background">
-     <property name="defaultColor">
-      <color>
-       <red>180</red>
-       <green>180</green>
-       <blue>180</blue>
-      </color>
-     </property>
-    </widget>
-   </item>
-   <item row="8" column="1" colspan="2">
-    <spacer name="verticalSpacer">
-     <property name="orientation">
-      <enum>Qt::Vertical</enum>
-     </property>
-     <property name="sizeHint" stdset="0">
-      <size>
-       <width>20</width>
-       <height>0</height>
-      </size>
-     </property>
-    </spacer>
-   </item>
-   <item row="6" column="0" colspan="2">
-    <widget class="QLabel" name="label">
-     <property name="text">
-      <string>Monitor background color:</string>
-     </property>
-    </widget>
-   </item>
    <item row="5" column="0" colspan="2">
     <widget class="QLabel" name="label_3">
      <property name="text">
      </property>
     </widget>
    </item>
-   <item row="1" column="0" colspan="3">
-    <widget class="QCheckBox" name="kcfg_openglmonitors">
+   <item row="6" column="0" colspan="2">
+    <widget class="QLabel" name="label">
      <property name="text">
-      <string>Use OpenGL for video display (restart Kdenlive to apply)</string>
+      <string>Monitor background color:</string>
      </property>
     </widget>
    </item>
+   <item row="6" column="2">
+    <widget class="KColorButton" name="kcfg_window_background">
+     <property name="defaultColor">
+      <color>
+       <red>180</red>
+       <green>180</green>
+       <blue>180</blue>
+      </color>
+     </property>
+    </widget>
+   </item>
+   <item row="7" column="0" colspan="3">
+    <widget class="QGroupBox" name="kcfg_external_display">
+     <property name="title">
+      <string>Use external display (Blackmagic card)</string>
+     </property>
+     <property name="checkable">
+      <bool>true</bool>
+     </property>
+     <property name="checked">
+      <bool>false</bool>
+     </property>
+     <layout class="QGridLayout" name="gridLayout">
+      <item row="0" column="0">
+       <widget class="QLabel" name="label_5">
+        <property name="text">
+         <string>Output device</string>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="1">
+       <widget class="KComboBox" name="kcfg_blackmagic_output_device">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item row="8" column="1" colspan="2">
+    <spacer name="verticalSpacer">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>20</width>
+       <height>0</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
   </layout>
  </widget>
  <customwidgets>