From 4b24e46624307c866463521b97490c4d211065d0 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Mardelle Date: Sun, 14 Nov 2010 16:14:14 +0000 Subject: [PATCH] First steps to support MLT's new Blackmagic's consumer (means external video display in Kdenlive) svn path=/trunk/kdenlive/; revision=5094 --- src/blackmagic/devices.cpp | 207 ++++++++++++++++++++++++++++++++- src/blackmagic/devices.h | 3 + src/kdenlivesettings.kcfg | 10 +- src/kdenlivesettingsdialog.cpp | 4 + src/profilesdialog.h | 2 +- src/renderer.cpp | 35 +++++- src/widgets/configsdl_ui.ui | 102 ++++++++++------ 7 files changed, 320 insertions(+), 43 deletions(-) diff --git a/src/blackmagic/devices.cpp b/src/blackmagic/devices.cpp index a9bcefa9..8c139b71 100644 --- a/src/blackmagic/devices.cpp +++ b/src/blackmagic/devices.cpp @@ -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; +} + diff --git a/src/blackmagic/devices.h b/src/blackmagic/devices.h index ad95456c..ce77c568 100644 --- a/src/blackmagic/devices.h +++ b/src/blackmagic/devices.h @@ -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 diff --git a/src/kdenlivesettings.kcfg b/src/kdenlivesettings.kcfg index 852e0440..39923e76 100644 --- a/src/kdenlivesettings.kcfg +++ b/src/kdenlivesettings.kcfg @@ -166,7 +166,15 @@ 100 - + + + false + + + + 0 + + diff --git a/src/kdenlivesettingsdialog.cpp b/src/kdenlivesettingsdialog.cpp index e997fa76..86624d55 100644 --- a/src/kdenlivesettingsdialog.cpp +++ b/src/kdenlivesettingsdialog.cpp @@ -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; diff --git a/src/profilesdialog.h b/src/profilesdialog.h index ef4ea086..a9927bab 100644 --- a/src/profilesdialog.h +++ b/src/profilesdialog.h @@ -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 diff --git a/src/renderer.cpp b/src/renderer.cpp index d785dec0..62626128 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -28,6 +28,8 @@ #include "kthumb.h" #include "definitions.h" #include "slideshowclip.h" +#include "profilesdialog.h" +#include "blackmagic/devices.h" #include @@ -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); diff --git a/src/widgets/configsdl_ui.ui b/src/widgets/configsdl_ui.ui index cee49078..200a34c1 100644 --- a/src/widgets/configsdl_ui.ui +++ b/src/widgets/configsdl_ui.ui @@ -7,7 +7,7 @@ 0 0 342 - 241 + 296 @@ -21,6 +21,13 @@ + + + + Use OpenGL for video display (restart Kdenlive to apply) + + + @@ -72,37 +79,6 @@ - - - - - 180 - 180 - 180 - - - - - - - - Qt::Vertical - - - - 20 - 0 - - - - - - - - Monitor background color: - - - @@ -123,13 +99,69 @@ - - + + - Use OpenGL for video display (restart Kdenlive to apply) + Monitor background color: + + + + + 180 + 180 + 180 + + + + + + + + Use external display (Blackmagic card) + + + true + + + false + + + + + + Output device + + + + + + + + 0 + 0 + + + + + + + + + + + Qt::Vertical + + + + 20 + 0 + + + + -- 2.39.2