Browse code

avdevice/decklink: add support for setting duplex mode

This patch also makes BlackMagic drivers v10.6.1 a hard requirement.

Reviewed-by: Deti Fliegl <deti@fliegl.de>
Signed-off-by: Marton Balint <cus@passwd.hu>

Marton Balint authored on 2016/06/11 20:41:29
Showing 7 changed files
... ...
@@ -5625,7 +5625,8 @@ enabled cuvid             && { check_lib cuviddec.h cuvidCreateDecoder -lnvcuvid
5625 5625
 enabled chromaprint       && require chromaprint chromaprint.h chromaprint_get_version -lchromaprint
5626 5626
 enabled coreimage_filter  && { check_header_objcc QuartzCore/CoreImage.h || disable coreimage_filter; }
5627 5627
 enabled coreimagesrc_filter && { check_header_objcc QuartzCore/CoreImage.h || disable coreimagesrc_filter; }
5628
-enabled decklink          && { check_header DeckLinkAPI.h || die "ERROR: DeckLinkAPI.h header not found"; }
5628
+enabled decklink          && { { check_header DeckLinkAPI.h || die "ERROR: DeckLinkAPI.h header not found"; } &&
5629
+                               { check_cpp_condition DeckLinkAPIVersion.h "BLACKMAGIC_DECKLINK_API_VERSION >= 0x0a060100" || die "ERROR: Decklink API version must be >= 10.6.1."; } }
5629 5630
 enabled frei0r            && { check_header frei0r.h || die "ERROR: frei0r.h header not found"; }
5630 5631
 enabled gmp               && require2 gmp gmp.h mpz_export -lgmp
5631 5632
 enabled gnutls            && require_pkg_config gnutls gnutls/gnutls.h gnutls_global_init
... ...
@@ -251,6 +251,10 @@ To use this option, ffmpeg needs to be compiled with @code{--enable-libzvbi}.
251 251
 Defines number of audio channels to capture. Must be @samp{2}, @samp{8} or @samp{16}.
252 252
 Defaults to @samp{2}.
253 253
 
254
+@item duplex_mode
255
+Sets the decklink device duplex mode. Must be @samp{unset}, @samp{half} or @samp{full}.
256
+Defaults to @samp{unset}.
257
+
254 258
 @end table
255 259
 
256 260
 @subsection Examples
... ...
@@ -111,6 +111,23 @@ int ff_decklink_set_format(AVFormatContext *avctx,
111 111
     int i = 1;
112 112
     HRESULT res;
113 113
 
114
+    if (ctx->duplex_mode) {
115
+        bool duplex_supported = false;
116
+
117
+        if (ctx->attr->GetFlag(BMDDeckLinkSupportsDuplexModeConfiguration, &duplex_supported) != S_OK)
118
+            duplex_supported = false;
119
+
120
+        if (duplex_supported) {
121
+            res = ctx->cfg->SetInt(bmdDeckLinkConfigDuplexMode, ctx->duplex_mode == 2 ? bmdDuplexModeFull : bmdDuplexModeHalf);
122
+            if (res != S_OK)
123
+                av_log(avctx, AV_LOG_WARNING, "Setting duplex mode failed.\n");
124
+            else
125
+                av_log(avctx, AV_LOG_VERBOSE, "Succesfully set duplex mode to %s duplex.\n", ctx->duplex_mode == 2 ? "full" : "half");
126
+        } else {
127
+            av_log(avctx, AV_LOG_WARNING, "Unable to set duplex mode, because it is not supported.\n");
128
+        }
129
+    }
130
+
114 131
     if (direction == DIRECTION_IN) {
115 132
         res = ctx->dli->GetDisplayModeIterator (&itermode);
116 133
     } else {
... ...
@@ -249,6 +266,10 @@ void ff_decklink_cleanup(AVFormatContext *avctx)
249 249
         ctx->dli->Release();
250 250
     if (ctx->dlo)
251 251
         ctx->dlo->Release();
252
+    if (ctx->attr)
253
+        ctx->attr->Release();
254
+    if (ctx->cfg)
255
+        ctx->cfg->Release();
252 256
     if (ctx->dl)
253 257
         ctx->dl->Release();
254 258
 }
... ...
@@ -279,5 +300,17 @@ int ff_decklink_init_device(AVFormatContext *avctx, const char* name)
279 279
     if (!ctx->dl)
280 280
         return AVERROR(ENXIO);
281 281
 
282
+    if (ctx->dl->QueryInterface(IID_IDeckLinkConfiguration, (void **)&ctx->cfg) != S_OK) {
283
+        av_log(avctx, AV_LOG_ERROR, "Could not get configuration interface for '%s'\n", name);
284
+        ff_decklink_cleanup(avctx);
285
+        return AVERROR_EXTERNAL;
286
+    }
287
+
288
+    if (ctx->dl->QueryInterface(IID_IDeckLinkAttributes, (void **)&ctx->attr) != S_OK) {
289
+        av_log(avctx, AV_LOG_ERROR, "Could not get attributes interface for '%s'\n", name);
290
+        ff_decklink_cleanup(avctx);
291
+        return AVERROR_EXTERNAL;
292
+    }
293
+
282 294
     return 0;
283 295
 }
... ...
@@ -44,6 +44,8 @@ struct decklink_ctx {
44 44
     IDeckLink *dl;
45 45
     IDeckLinkOutput *dlo;
46 46
     IDeckLinkInput *dli;
47
+    IDeckLinkConfiguration *cfg;
48
+    IDeckLinkAttributes *attr;
47 49
     decklink_output_callback *output_callback;
48 50
     decklink_input_callback *input_callback;
49 51
 
... ...
@@ -77,6 +79,7 @@ struct decklink_ctx {
77 77
     int list_formats;
78 78
     int64_t teletext_lines;
79 79
     double preroll;
80
+    int duplex_mode;
80 81
 
81 82
     int frames_preroll;
82 83
     int frames_buffer;
... ...
@@ -34,6 +34,7 @@ struct decklink_cctx {
34 34
     double preroll;
35 35
     int v210;
36 36
     int audio_channels;
37
+    int duplex_mode;
37 38
 };
38 39
 
39 40
 #endif /* AVDEVICE_DECKLINK_COMMON_C_H */
... ...
@@ -445,6 +445,7 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx)
445 445
     ctx->list_formats = cctx->list_formats;
446 446
     ctx->teletext_lines = cctx->teletext_lines;
447 447
     ctx->preroll      = cctx->preroll;
448
+    ctx->duplex_mode  = cctx->duplex_mode;
448 449
     cctx->ctx = ctx;
449 450
 
450 451
 #if !CONFIG_LIBZVBI
... ...
@@ -36,6 +36,10 @@ static const AVOption options[] = {
36 36
     { "standard",     NULL,                                           0,  AV_OPT_TYPE_CONST, { .i64 = 0x7fff9fffeLL}, 0, 0,    DEC, "teletext_lines"},
37 37
     { "all",          NULL,                                           0,  AV_OPT_TYPE_CONST, { .i64 = 0x7ffffffffLL}, 0, 0,    DEC, "teletext_lines"},
38 38
     { "channels",     "number of audio channels", OFFSET(audio_channels), AV_OPT_TYPE_INT , { .i64 = 2   }, 2, 16, DEC },
39
+    { "duplex_mode",  "duplex mode",              OFFSET(duplex_mode),    AV_OPT_TYPE_INT,   { .i64 = 0}, 0, 2,    DEC, "duplex_mode"},
40
+    { "unset",         NULL,                                          0,  AV_OPT_TYPE_CONST, { .i64 = 0}, 0, 0,    DEC, "duplex_mode"},
41
+    { "half",          NULL,                                          0,  AV_OPT_TYPE_CONST, { .i64 = 1}, 0, 0,    DEC, "duplex_mode"},
42
+    { "full",          NULL,                                          0,  AV_OPT_TYPE_CONST, { .i64 = 2}, 0, 0,    DEC, "duplex_mode"},
39 43
     { NULL },
40 44
 };
41 45