[FFmpeg-devel] [PATCH] avdevice/decklink: add support for setting duplex mode

Marton Balint cus at passwd.hu
Sat Jun 11 16:01:20 CEST 2016


Signed-off-by: Marton Balint <cus at passwd.hu>
---
 configure                       |  3 ++-
 doc/indevs.texi                 |  4 ++++
 libavdevice/decklink_common.cpp | 37 +++++++++++++++++++++++++++++++++++++
 libavdevice/decklink_common.h   |  4 ++++
 libavdevice/decklink_common_c.h |  1 +
 libavdevice/decklink_dec.cpp    | 10 ++++++++++
 libavdevice/decklink_dec_c.c    |  4 ++++
 7 files changed, 62 insertions(+), 1 deletion(-)

diff --git a/configure b/configure
index a220fa1..ec2e5e6 100755
--- a/configure
+++ b/configure
@@ -5618,7 +5618,8 @@ enabled cuvid             && { check_lib cuviddec.h cuvidCreateDecoder -lnvcuvid
 enabled chromaprint       && require chromaprint chromaprint.h chromaprint_get_version -lchromaprint
 enabled coreimage_filter  && { check_header_objcc QuartzCore/CoreImage.h || disable coreimage_filter; }
 enabled coreimagesrc_filter && { check_header_objcc QuartzCore/CoreImage.h || disable coreimagesrc_filter; }
-enabled decklink          && { check_header DeckLinkAPI.h || die "ERROR: DeckLinkAPI.h header not found"; }
+enabled decklink          && { { check_header DeckLinkAPI.h || die "ERROR: DeckLinkAPI.h header not found"; } &&
+                               { check_cpp_condition DeckLinkAPIVersion.h "BLACKMAGIC_DECKLINK_API_VERSION >= 0x0a060100" || die "ERROR: Decklink API version must be >= 10.6.1."; } }
 enabled frei0r            && { check_header frei0r.h || die "ERROR: frei0r.h header not found"; }
 enabled gmp               && require2 gmp gmp.h mpz_export -lgmp
 enabled gnutls            && require_pkg_config gnutls gnutls/gnutls.h gnutls_global_init
diff --git a/doc/indevs.texi b/doc/indevs.texi
index 3fb852b..479932a 100644
--- a/doc/indevs.texi
+++ b/doc/indevs.texi
@@ -251,6 +251,10 @@ To use this option, ffmpeg needs to be compiled with @code{--enable-libzvbi}.
 Defines number of audio channels to capture. Must be @samp{2}, @samp{8} or @samp{16}.
 Defaults to @samp{2}.
 
+ at item duplex_mode
+Sets the decklink device duplex mode. Must be @samp{unset}, @samp{half} or @samp{full}.
+Defaults to @samp{unset}.
+
 @end table
 
 @subsection Examples
diff --git a/libavdevice/decklink_common.cpp b/libavdevice/decklink_common.cpp
index ac7964c..24d0d09 100644
--- a/libavdevice/decklink_common.cpp
+++ b/libavdevice/decklink_common.cpp
@@ -111,6 +111,23 @@ int ff_decklink_set_format(AVFormatContext *avctx,
     int i = 1;
     HRESULT res;
 
+    if (ctx->duplex_mode) {
+        bool duplex_supported = false;
+
+        if (ctx->attr->GetFlag(BMDDeckLinkSupportsDuplexModeConfiguration, &duplex_supported) != S_OK)
+            duplex_supported = false;
+
+        if (duplex_supported) {
+            res = ctx->cfg->SetInt(bmdDeckLinkConfigDuplexMode, ctx->duplex_mode == 2 ? bmdDuplexModeFull : bmdDuplexModeHalf);
+            if (res != S_OK)
+                av_log(avctx, AV_LOG_WARNING, "Setting duplex mode failed.\n");
+            else
+                av_log(avctx, AV_LOG_VERBOSE, "Succesfully set duplex mode to %s duplex.\n", ctx->duplex_mode == 2 ? "full" : "half");
+        } else {
+            av_log(avctx, AV_LOG_WARNING, "Unable to set duplex mode, because it is not supported.\n");
+        }
+    }
+
     if (direction == DIRECTION_IN) {
         res = ctx->dli->GetDisplayModeIterator (&itermode);
     } else {
@@ -239,3 +256,23 @@ int ff_decklink_list_formats(AVFormatContext *avctx, decklink_direction_t direct
 
     return 0;
 }
+
+int ff_decklink_init_interfaces(AVFormatContext *avctx)
+{
+    struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data;
+    struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx;
+
+    if (ctx->dl->QueryInterface(IID_IDeckLinkConfiguration, (void **)&ctx->cfg) != S_OK) {
+        av_log(avctx, AV_LOG_ERROR, "Could not get configuration interface for '%s'\n", avctx->filename);
+        return AVERROR_EXTERNAL;
+    }
+
+    if (ctx->dl->QueryInterface(IID_IDeckLinkAttributes, (void **)&ctx->attr) != S_OK) {
+        av_log(avctx, AV_LOG_ERROR, "Could not get attributes interaface for '%s'\n", avctx->filename);
+        ctx->cfg->Release();
+        ctx->cfg = NULL;
+        return AVERROR_EXTERNAL;
+    }
+
+    return 0;
+}
diff --git a/libavdevice/decklink_common.h b/libavdevice/decklink_common.h
index dff4fc1..3d8caad 100644
--- a/libavdevice/decklink_common.h
+++ b/libavdevice/decklink_common.h
@@ -44,6 +44,8 @@ struct decklink_ctx {
     IDeckLink *dl;
     IDeckLinkOutput *dlo;
     IDeckLinkInput *dli;
+    IDeckLinkConfiguration *cfg;
+    IDeckLinkAttributes *attr;
     decklink_output_callback *output_callback;
     decklink_input_callback *input_callback;
 
@@ -77,6 +79,7 @@ struct decklink_ctx {
     int list_formats;
     int64_t teletext_lines;
     double preroll;
+    int duplex_mode;
 
     int frames_preroll;
     int frames_buffer;
@@ -105,5 +108,6 @@ int ff_decklink_set_format(AVFormatContext *avctx, int width, int height, int tb
 int ff_decklink_set_format(AVFormatContext *avctx, decklink_direction_t direction, int num);
 int ff_decklink_list_devices(AVFormatContext *avctx);
 int ff_decklink_list_formats(AVFormatContext *avctx, decklink_direction_t direction = DIRECTION_OUT);
+int ff_decklink_init_interfaces(AVFormatContext *avctx);
 
 #endif /* AVDEVICE_DECKLINK_COMMON_H */
diff --git a/libavdevice/decklink_common_c.h b/libavdevice/decklink_common_c.h
index 2b5d92f..f24f8f0 100644
--- a/libavdevice/decklink_common_c.h
+++ b/libavdevice/decklink_common_c.h
@@ -34,6 +34,7 @@ struct decklink_cctx {
     double preroll;
     int v210;
     int audio_channels;
+    int duplex_mode;
 };
 
 #endif /* AVDEVICE_DECKLINK_COMMON_C_H */
diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp
index 1c305f3..282814d 100644
--- a/libavdevice/decklink_dec.cpp
+++ b/libavdevice/decklink_dec.cpp
@@ -421,6 +421,10 @@ av_cold int ff_decklink_read_close(AVFormatContext *avctx)
 
     if (ctx->dli)
         ctx->dli->Release();
+    if (ctx->attr)
+        ctx->attr->Release();
+    if (ctx->cfg)
+        ctx->cfg->Release();
     if (ctx->dl)
         ctx->dl->Release();
 
@@ -443,6 +447,7 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx)
     char fname[1024];
     char *tmp;
     int mode_num = 0;
+    int ret;
 
     ctx = (struct decklink_ctx *) av_mallocz(sizeof(struct decklink_ctx));
     if (!ctx)
@@ -451,6 +456,7 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx)
     ctx->list_formats = cctx->list_formats;
     ctx->teletext_lines = cctx->teletext_lines;
     ctx->preroll      = cctx->preroll;
+    ctx->duplex_mode  = cctx->duplex_mode;
     cctx->ctx = ctx;
 
 #if !CONFIG_LIBZVBI
@@ -508,6 +514,10 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx)
         return AVERROR(EIO);
     }
 
+    ret = ff_decklink_init_interfaces(avctx);
+    if (ret < 0)
+        return ret;
+
     /* Get input device. */
     if (ctx->dl->QueryInterface(IID_IDeckLinkInput, (void **) &ctx->dli) != S_OK) {
         av_log(avctx, AV_LOG_ERROR, "Could not open output device from '%s'\n",
diff --git a/libavdevice/decklink_dec_c.c b/libavdevice/decklink_dec_c.c
index 40c21a7..72baa7d 100644
--- a/libavdevice/decklink_dec_c.c
+++ b/libavdevice/decklink_dec_c.c
@@ -36,6 +36,10 @@ static const AVOption options[] = {
     { "standard",     NULL,                                           0,  AV_OPT_TYPE_CONST, { .i64 = 0x7fff9fffeLL}, 0, 0,    DEC, "teletext_lines"},
     { "all",          NULL,                                           0,  AV_OPT_TYPE_CONST, { .i64 = 0x7ffffffffLL}, 0, 0,    DEC, "teletext_lines"},
     { "channels",     "number of audio channels", OFFSET(audio_channels), AV_OPT_TYPE_INT , { .i64 = 2   }, 2, 16, DEC },
+    { "duplex_mode",  "duplex mode",              OFFSET(duplex_mode),    AV_OPT_TYPE_INT,   { .i64 = 0}, 0, 2,    DEC, "duplex_mode"},
+    { "unset",         NULL,                                          0,  AV_OPT_TYPE_CONST, { .i64 = 0}, 0, 0,    DEC, "duplex_mode"},
+    { "half",          NULL,                                          0,  AV_OPT_TYPE_CONST, { .i64 = 1}, 0, 0,    DEC, "duplex_mode"},
+    { "full",          NULL,                                          0,  AV_OPT_TYPE_CONST, { .i64 = 2}, 0, 0,    DEC, "duplex_mode"},
     { NULL },
 };
 
-- 
2.6.6



More information about the ffmpeg-devel mailing list