[vlc-devel] [PATCH 2/2] Make decklink input/output modules build on OSX

Devin Heitmueller dheitmueller at ltnglobal.com
Thu Sep 6 22:16:07 CEST 2018


The Decklink SDK has platform-specific implementations for various
calls which return strings.  Add some portability macros to
properly handle those calls and then normalize the result down to
a C char * as we would typically see in VLC.

Signed-off-by: Devin Heitmueller <dheitmueller at ltnglobal.com>
---
 configure.ac                            |  3 ++
 include/vlc_decklink.h                  | 65 +++++++++++++++++++++++++++++++++
 modules/access/decklink.cpp             | 33 +++++++++++++----
 modules/stream_out/sdi/DBMSDIOutput.cpp | 11 +++++-
 modules/stream_out/sdi/DBMSDIOutput.hpp |  3 +-
 modules/video_output/decklink.cpp       | 19 +++++++---
 6 files changed, 117 insertions(+), 17 deletions(-)
 create mode 100644 include/vlc_decklink.h

diff --git a/configure.ac b/configure.ac
index 9700ec121e..43ab9ec31b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1903,6 +1903,9 @@ then
   AC_LANG_PUSH(C++)
   AC_CHECK_HEADERS(DeckLinkAPIDispatch.cpp, [
       have_decklink=yes
+      AS_IF([test "${SYS}" = "darwin"], [
+        VLC_ADD_LIBS([decklink decklinkoutput],[-Wl,-framework,CoreFoundation])
+      ])
   ], [
       AC_MSG_WARN(Blackmagic DeckLink SDI include files not found, decklink disabled)
   ])
diff --git a/include/vlc_decklink.h b/include/vlc_decklink.h
new file mode 100644
index 0000000000..846ab43a68
--- /dev/null
+++ b/include/vlc_decklink.h
@@ -0,0 +1,65 @@
+/*****************************************************************************
+ * vlc_decklink.h: Decklink Common includes
+ *****************************************************************************
+ * Copyright (C) 2018 LTN Global Communications
+ *
+ * Authors: Devin Heitmueller <dheitmueller at ltnglobal.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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 VLC_DECKLINK_H
+#define VLC_DECKLINK_H 1
+
+/**
+ * \file
+ * This file defines Decklink portability macros and other functions
+ */
+
+#include <DeckLinkAPI.h>
+
+/* Portability code to deal with differences how the Blackmagic SDK
+   handles strings on various platforms */
+#ifdef _WIN32
+static char *dup_wchar_to_utf8(wchar_t *w)
+{
+    char *s = NULL;
+    int l = WideCharToMultiByte(CP_UTF8, 0, w, -1, 0, 0, 0, 0);
+    s = (char *) av_malloc(l);
+    if (s)
+        WideCharToMultiByte(CP_UTF8, 0, w, -1, s, l, 0, 0);
+    return s;
+}
+#define DECKLINK_STR    OLECHAR *
+#define DECKLINK_STRDUP dup_wchar_to_utf8
+#define DECKLINK_FREE(s) SysFreeString(s)
+#elif defined(__APPLE__)
+static char *dup_cfstring_to_utf8(CFStringRef w)
+{
+    char s[256];
+    CFStringGetCString(w, s, 255, kCFStringEncodingUTF8);
+    return strdup(s);
+}
+#define DECKLINK_STR    const __CFString *
+#define DECKLINK_STRDUP dup_cfstring_to_utf8
+#define DECKLINK_FREE(s) CFRelease(s)
+#else
+#define DECKLINK_STR    const char *
+#define DECKLINK_STRDUP strdup
+#define DECKLINK_FREE(s) free((void *) s)
+#endif
+
+#endif /* VLC_DECKLINK_H */
+
diff --git a/modules/access/decklink.cpp b/modules/access/decklink.cpp
index 2412750c31..6d1c1364d3 100644
--- a/modules/access/decklink.cpp
+++ b/modules/access/decklink.cpp
@@ -29,12 +29,12 @@
 #include <vlc_common.h>
 #include <vlc_plugin.h>
 #include <vlc_demux.h>
+#include <vlc_decklink.h>
 
 #ifdef HAVE_ARPA_INET_H
 #include <arpa/inet.h>
 #endif
 
-#include <DeckLinkAPI.h>
 #include <DeckLinkAPIDispatch.cpp>
 
 #include "sdi.h"
@@ -260,11 +260,17 @@ public:
         if( !(events & bmdVideoInputDisplayModeChanged ))
             return S_OK;
 
-        const char *mode_name;
-        if (mode->GetName(&mode_name) != S_OK)
-            mode_name = "unknown";
+        DECKLINK_STR tmp_name;
+        char *mode_name;
+        if (mode->GetName(&tmp_name) != S_OK) {
+            mode_name = strdup("unknown");
+        } else {
+            mode_name = DECKLINK_STRDUP(tmp_name);
+            DECKLINK_STRDUP(tmp_name);
+        }
 
         msg_Dbg(demux_, "Video input format changed to %s", mode_name);
+        free(mode_name);
         if (!sys->autodetect) {
             msg_Err(demux_, "Video format detection disabled");
             return S_OK;
@@ -531,11 +537,17 @@ static int Open(vlc_object_t *p_this)
         }
     }
 
-    const char *model_name;
-    if (sys->card->GetModelName(&model_name) != S_OK)
-        model_name = "unknown";
+    DECKLINK_STR tmp_name;
+    char *model_name;
+    if (sys->card->GetModelName(&tmp_name) != S_OK) {
+        model_name = strdup("unknown");
+    } else {
+        model_name = DECKLINK_STRDUP(tmp_name);
+        DECKLINK_FREE(tmp_name);
+    }
 
     msg_Dbg(demux, "Opened DeckLink PCI card %d (%s)", card_index, model_name);
+    free(model_name);
 
     if (sys->card->QueryInterface(IID_IDeckLinkInput, (void**)&sys->input) != S_OK) {
         msg_Err(demux, "Card has no inputs");
@@ -612,9 +624,14 @@ static int Open(vlc_object_t *p_this)
         uint32_t field_flags;
         const char *field = GetFieldDominance(m->GetFieldDominance(), &field_flags);
         BMDDisplayMode id = ntohl(m->GetDisplayMode());
+        DECKLINK_STR tmp_name;
 
-        if (m->GetName(&mode_name) != S_OK)
+        if (m->GetName(&tmp_name) != S_OK) {
             mode_name = "unknown";
+        } else {
+            mode_name = DECKLINK_STRDUP(tmp_name);
+            DECKLINK_FREE(tmp_name);
+        }
         if (m->GetFrameRate(&frame_duration, &time_scale) != S_OK) {
             time_scale = 0;
             frame_duration = 1;
diff --git a/modules/stream_out/sdi/DBMSDIOutput.cpp b/modules/stream_out/sdi/DBMSDIOutput.cpp
index 0818e4fc03..785d391c9b 100644
--- a/modules/stream_out/sdi/DBMSDIOutput.cpp
+++ b/modules/stream_out/sdi/DBMSDIOutput.cpp
@@ -107,11 +107,15 @@ IDeckLinkDisplayMode * DBMSDIOutput::MatchDisplayMode(const video_format_t *fmt,
                 BMDTimeValue frameduration;
                 BMDTimeScale timescale;
                 const char *psz_mode_name;
+                DECKLINK_STR tmp_name;
 
                 if(p_mode->GetFrameRate(&frameduration, &timescale) == S_OK &&
-                        p_mode->GetName(&psz_mode_name) == S_OK)
+                        p_mode->GetName(&tmp_name) == S_OK)
                 {
                     BMDDisplayMode modenl = htonl(mode_id);
+                    psz_mode_name = DECKLINK_STRDUP(tmp_name);
+                    DECKLINK_FREE(tmp_name);
+
                     if(i==0)
                     {
                         BMDFieldDominance field = htonl(p_mode->GetFieldDominance());
@@ -239,9 +243,12 @@ int DBMSDIOutput::Open()
         CHECK("Card not found");
     }
 
+    DECKLINK_STR tmp_name;
     const char *psz_model_name;
-    result = p_card->GetModelName(&psz_model_name);
+    result = p_card->GetModelName(&tmp_name);
     CHECK("Unknown model name");
+    psz_model_name = DECKLINK_STRDUP(tmp_name);
+    DECKLINK_FREE(tmp_name);
 
     msg_Dbg(p_stream, "Opened DeckLink PCI card %s", psz_model_name);
 
diff --git a/modules/stream_out/sdi/DBMSDIOutput.hpp b/modules/stream_out/sdi/DBMSDIOutput.hpp
index 13a65fd29f..42ae69638b 100644
--- a/modules/stream_out/sdi/DBMSDIOutput.hpp
+++ b/modules/stream_out/sdi/DBMSDIOutput.hpp
@@ -24,8 +24,7 @@
 #include "SDIOutput.hpp"
 
 #include <vlc_es.h>
-
-#include <DeckLinkAPI.h>
+#include <vlc_decklink.h>
 
 namespace sdi_sout
 {
diff --git a/modules/video_output/decklink.cpp b/modules/video_output/decklink.cpp
index 3e6a291b7a..9e7cea72c7 100644
--- a/modules/video_output/decklink.cpp
+++ b/modules/video_output/decklink.cpp
@@ -43,11 +43,11 @@
 #include <vlc_block.h>
 #include <vlc_image.h>
 #include <vlc_aout.h>
+#include <vlc_decklink.h>
 #ifdef HAVE_ARPA_INET_H
 #include <arpa/inet.h>
 #endif
 
-#include <DeckLinkAPI.h>
 #include <DeckLinkAPIDispatch.cpp>
 
 #define FRAME_SIZE 1920
@@ -490,12 +490,16 @@ static IDeckLinkDisplayMode * MatchDisplayMode(vout_display_t *vd,
                 BMDDisplayMode mode_id = p_mode->GetDisplayMode();
                 BMDTimeValue frameduration;
                 BMDTimeScale timescale;
-                const char *psz_mode_name;
+                char *psz_mode_name;
 
+                DECKLINK_STR tmp_name;
                 if(p_mode->GetFrameRate(&frameduration, &timescale) == S_OK &&
-                        p_mode->GetName(&psz_mode_name) == S_OK)
+                        p_mode->GetName(&tmp_name) == S_OK)
                 {
                     BMDDisplayMode modenl = htonl(mode_id);
+                    psz_mode_name = DECKLINK_STRDUP(tmp_name);
+                    DECKLINK_FREE(tmp_name);
+
                     if(i==0)
                     {
                         BMDFieldDominance field = htonl(p_mode->GetFieldDominance());
@@ -506,6 +510,7 @@ static IDeckLinkDisplayMode * MatchDisplayMode(vout_display_t *vd,
                                 double(timescale) / frameduration,
                                 timescale, frameduration);
                     }
+		    free(psz_mode_name);
                 }
                 else
                 {
@@ -620,11 +625,15 @@ static int OpenDecklink(vout_display_t *vd, decklink_sys_t *sys)
         CHECK("Card not found");
     }
 
-    const char *psz_model_name;
-    result = p_card->GetModelName(&psz_model_name);
+    DECKLINK_STR tmp_name;
+    char *psz_model_name;
+    result = p_card->GetModelName(&tmp_name);
     CHECK("Unknown model name");
+    psz_model_name = DECKLINK_STRDUP(tmp_name);
+    DECKLINK_FREE(tmp_name);
 
     msg_Dbg(vd, "Opened DeckLink PCI card %s", psz_model_name);
+    free(psz_model_name);
 
     /* Read attributes */
 
-- 
2.13.2



More information about the vlc-devel mailing list