[FFmpeg-devel] [PATCH v4 4/4] avdevice/decklink: support for more duplex mode for Decklink 8K Pro

Marton Balint cus at passwd.hu
Mon Aug 16 01:23:40 EEST 2021



On Fri, 13 Aug 2021, lance.lmwang at gmail.com wrote:

> From: Limin Wang <lance.lmwang at gmail.com>
>
> Reviewed-by: Marton Balint <cus at passwd.hu>
> Signed-off-by: Limin Wang <lance.lmwang at gmail.com>
> ---
> doc/indevs.texi                 | 16 +++++++++++++++-
> doc/outdevs.texi                | 16 +++++++++++++++-
> libavdevice/decklink_common.cpp |  8 ++++++--
> libavdevice/decklink_common.h   | 11 +++++++++++
> libavdevice/decklink_dec_c.c    | 10 ++++++++++
> libavdevice/decklink_enc_c.c    | 10 ++++++++++
> libavdevice/version.h           |  2 +-
> 7 files changed, 68 insertions(+), 5 deletions(-)
>
> diff --git a/doc/indevs.texi b/doc/indevs.texi
> index b377924..5be647f 100644
> --- a/doc/indevs.texi
> +++ b/doc/indevs.texi
> @@ -344,9 +344,23 @@ Defines number of audio channels to capture. Must be @samp{2}, @samp{8} or @samp
> Defaults to @samp{2}.
>
> @item duplex_mode
> -Sets the decklink device duplex mode. Must be @samp{unset}, @samp{half} or @samp{full}.
> +Sets the decklink device duplex/profile mode. Must be @samp{unset}, @samp{half}, @samp{full},
> + at samp{one_sub_device_full}, @samp{one_sub_device_half}, @samp{two_sub_device_full},
> + at samp{four_sub_device_half}
> Defaults to @samp{unset}.
>
> +Note: DeckLink SDK 11.0 have replaced the duplex property by a profile property.
> +For the DeckLink Duo 2 and DeckLink Quad 2, a profile is shared between any 2
> +sub-devices that utilize the same connectors. For the DeckLink 8K Pro, a profile
> +is shared between all 4 sub-devices. So DeckLink 8K Pro support four profiles.
> +
> +Valid profile modes for DeckLink 8K Pro(with DeckLink SDK >= 11.0):
> + at samp{one_sub_device_full}, @samp{one_sub_device_half}, @samp{two_sub_device_full},
> + at samp{four_sub_device_half}
> +
> +Valid profile modes for DeckLink Quad 2 and DeckLink Duo 2:
> + at samp{half}, @samp{full}
> +
> @item timecode_format
> Timecode type to include in the frame and video stream metadata. Must be
> @samp{none}, @samp{rp188vitc}, @samp{rp188vitc2}, @samp{rp188ltc},
> diff --git a/doc/outdevs.texi b/doc/outdevs.texi
> index cc0c94a..aa41e29 100644
> --- a/doc/outdevs.texi
> +++ b/doc/outdevs.texi
> @@ -198,9 +198,23 @@ Amount of time to preroll video in seconds.
> Defaults to @option{0.5}.
>
> @item duplex_mode
> -Sets the decklink device duplex mode. Must be @samp{unset}, @samp{half} or @samp{full}.
> +Sets the decklink device duplex/profile mode. Must be @samp{unset}, @samp{half}, @samp{full},
> + at samp{one_sub_device_full}, @samp{one_sub_device_half}, @samp{two_sub_device_full},
> + at samp{four_sub_device_half}
> Defaults to @samp{unset}.
>
> +Note: DeckLink SDK 11.0 have replaced the duplex property by a profile property.
> +For the DeckLink Duo 2 and DeckLink Quad 2, a profile is shared between any 2
> +sub-devices that utilize the same connectors. For the DeckLink 8K Pro, a profile
> +is shared between all 4 sub-devices. So DeckLink 8K Pro support four profiles.
> +
> +Valid profile modes for DeckLink 8K Pro(with DeckLink SDK >= 11.0):
> + at samp{one_sub_device_full}, @samp{one_sub_device_half}, @samp{two_sub_device_full},
> + at samp{four_sub_device_half}
> +
> +Valid profile modes for DeckLink Quad 2 and DeckLink Duo 2:
> + at samp{half}, @samp{full}
> +
> @item timing_offset
> Sets the genlock timing pixel offset on the used output.
> Defaults to @samp{unset}.
> diff --git a/libavdevice/decklink_common.cpp b/libavdevice/decklink_common.cpp
> index 0569462..380c6e5 100644
> --- a/libavdevice/decklink_common.cpp
> +++ b/libavdevice/decklink_common.cpp
> @@ -182,7 +182,11 @@ int ff_decklink_set_configs(AVFormatContext *avctx,
>         if (duplex_supported) {
> #if BLACKMAGIC_DECKLINK_API_VERSION >= 0x0b000000
>             IDeckLinkProfile *profile = NULL;
> -            BMDProfileID bmd_profile_id = ctx->duplex_mode == 2 ? bmdProfileOneSubDeviceFullDuplex : bmdProfileTwoSubDevicesHalfDuplex;
> +            BMDProfileID bmd_profile_id = NULL;

You don't have to initialize this, even if you do, not to NULL...

> +
> +            if (ctx->duplex_mode >= FF_ARRAY_ELEMS(decklink_profile_id_map))

if (ctx->duplex_mode < 0 || ctx->duplex_mode >= FF_ARRAY_ELEMS(decklink_profile_id_map))

> +                return EINVAL;
> +            bmd_profile_id = decklink_profile_id_map[ctx->duplex_mode];
>             res = manager->GetProfile(bmd_profile_id, &profile);
>             if (res == S_OK) {
>                 res = profile->SetActive();
> @@ -195,7 +199,7 @@ int ff_decklink_set_configs(AVFormatContext *avctx,
>             if (res != S_OK)
>                 av_log(avctx, AV_LOG_WARNING, "Setting duplex mode failed.\n");
>             else
> -                av_log(avctx, AV_LOG_VERBOSE, "Successfully set duplex mode to %s duplex.\n", ctx->duplex_mode == 2 ? "full" : "half");
> +                av_log(avctx, AV_LOG_VERBOSE, "Successfully set duplex mode to %s duplex.\n", ctx->duplex_mode == 2 || ctx->duplex_mode == 4 ? "full" : "half");
>         } else {
>             av_log(avctx, AV_LOG_WARNING, "Unable to set duplex mode, because it is not supported.\n");
>         }
> diff --git a/libavdevice/decklink_common.h b/libavdevice/decklink_common.h
> index ad8b33c..5b11dcd 100644
> --- a/libavdevice/decklink_common.h
> +++ b/libavdevice/decklink_common.h
> @@ -208,6 +208,17 @@ static const BMDLinkConfiguration decklink_link_conf_map[] = {
>     bmdLinkConfigurationQuadLink
> };
>
> +#if BLACKMAGIC_DECKLINK_API_VERSION >= 0x0b000000
> +static const BMDProfileID decklink_profile_id_map[] = {
> +    (BMDProfileID)0,
> +    bmdProfileTwoSubDevicesHalfDuplex,
> +    bmdProfileOneSubDeviceFullDuplex,
> +    bmdProfileOneSubDeviceHalfDuplex,
> +    bmdProfileTwoSubDevicesFullDuplex,
> +    bmdProfileFourSubDevicesHalfDuplex,
> +};
> +#endif
> +
> int ff_decklink_set_configs(AVFormatContext *avctx, decklink_direction_t direction);
> int ff_decklink_set_format(AVFormatContext *avctx, int width, int height, int tb_num, int tb_den, enum AVFieldOrder field_order, decklink_direction_t direction = DIRECTION_OUT);
> int ff_decklink_set_format(AVFormatContext *avctx, decklink_direction_t direction);
> diff --git a/libavdevice/decklink_dec_c.c b/libavdevice/decklink_dec_c.c
> index 1d93e8b..2159702 100644
> --- a/libavdevice/decklink_dec_c.c
> +++ b/libavdevice/decklink_dec_c.c
> @@ -45,10 +45,20 @@ 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 },
> +#if BLACKMAGIC_DECKLINK_API_VERSION >= 0x0b000000
> +    { "duplex_mode",  "duplex mode",              OFFSET(duplex_mode),    AV_OPT_TYPE_INT,   { .i64 = 0}, 0, 5,    DEC, "duplex_mode"},
> +#else
>     { "duplex_mode",  "duplex mode",              OFFSET(duplex_mode),    AV_OPT_TYPE_INT,   { .i64 = 0}, 0, 2,    DEC, "duplex_mode"},
> +#endif
>     { "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"},
> +#if BLACKMAGIC_DECKLINK_API_VERSION >= 0x0b000000
> +    { "one_sub_device_full",      NULL,                               0,  AV_OPT_TYPE_CONST, { .i64 = 2}, 0, 0,    DEC, "duplex_mode"},
> +    { "one_sub_device_half",      NULL,                               0,  AV_OPT_TYPE_CONST, { .i64 = 3}, 0, 0,    DEC, "duplex_mode"},
> +    { "two_sub_device_full",      NULL,                               0,  AV_OPT_TYPE_CONST, { .i64 = 4}, 0, 0,    DEC, "duplex_mode"},
> +    { "four_sub_device_half",     NULL,                               0,  AV_OPT_TYPE_CONST, { .i64 = 5}, 0, 0,    DEC, "duplex_mode"},
> +#endif
>     { "timecode_format", "timecode format",           OFFSET(tc_format),  AV_OPT_TYPE_INT,   { .i64 = 0}, 0, 8,    DEC, "tc_format"},
>     { "none",          NULL,                                          0,  AV_OPT_TYPE_CONST, { .i64 = 0}, 0, 0,    DEC, "tc_format"},
>     { "rp188vitc",     NULL,                                          0,  AV_OPT_TYPE_CONST, { .i64 = 1}, 0, 0,    DEC, "tc_format"},
> diff --git a/libavdevice/decklink_enc_c.c b/libavdevice/decklink_enc_c.c
> index 559f078..990fbb8 100644
> --- a/libavdevice/decklink_enc_c.c
> +++ b/libavdevice/decklink_enc_c.c
> @@ -31,10 +31,20 @@ static const AVOption options[] = {
>     { "list_devices", "use ffmpeg -sinks decklink instead", OFFSET(list_devices), AV_OPT_TYPE_BOOL, { .i64 = 0   }, 0, 1, ENC | AV_OPT_FLAG_DEPRECATED},
>     { "list_formats", "list supported formats"  , OFFSET(list_formats), AV_OPT_TYPE_INT   , { .i64 = 0   }, 0, 1, ENC },
>     { "preroll"     , "video preroll in seconds", OFFSET(preroll     ), AV_OPT_TYPE_DOUBLE, { .dbl = 0.5 }, 0, 5, ENC },
> +#if BLACKMAGIC_DECKLINK_API_VERSION >= 0x0b000000
> +    { "duplex_mode" , "duplex mode"             , OFFSET(duplex_mode ), AV_OPT_TYPE_INT   , { .i64 = 0   }, 0, 5, ENC, "duplex_mode"},
> +#else
>     { "duplex_mode" , "duplex mode"             , OFFSET(duplex_mode ), AV_OPT_TYPE_INT   , { .i64 = 0   }, 0, 2, ENC, "duplex_mode"},
> +#endif
>     { "unset"       ,  NULL                     , 0                   , AV_OPT_TYPE_CONST , { .i64 = 0   }, 0, 0, ENC, "duplex_mode"},
>     { "half"        ,  NULL                     , 0                   , AV_OPT_TYPE_CONST , { .i64 = 1   }, 0, 0, ENC, "duplex_mode"},
>     { "full"        ,  NULL                     , 0                   , AV_OPT_TYPE_CONST , { .i64 = 2   }, 0, 0, ENC, "duplex_mode"},
> +#if BLACKMAGIC_DECKLINK_API_VERSION >= 0x0b000000
> +    { "one_sub_device_full",      NULL           ,0                   , AV_OPT_TYPE_CONST , { .i64 = 2   }, 0, 0, ENC, "duplex_mode"},
> +    { "one_sub_device_half",      NULL           ,0                   , AV_OPT_TYPE_CONST , { .i64 = 3   }, 0, 0, ENC, "duplex_mode"},
> +    { "two_sub_device_full",      NULL           ,0                   , AV_OPT_TYPE_CONST , { .i64 = 4   }, 0, 0, ENC, "duplex_mode"},
> +    { "four_sub_device_half",     NULL           ,0                   , AV_OPT_TYPE_CONST , { .i64 = 5   }, 0, 0, ENC, "duplex_mode"},
> +#endif
>     { "link" ,         "single/dual/quad SDI link configuration", OFFSET(link), AV_OPT_TYPE_INT, { .i64 = 0   }, 0, 3, ENC, "link"},
>     { "unset"       ,  NULL                     , 0                   , AV_OPT_TYPE_CONST , { .i64 = 0   }, 0, 0, ENC, "link"},
>     { "single"      ,  NULL                     , 0                   , AV_OPT_TYPE_CONST , { .i64 = 1   }, 0, 0, ENC, "link"},
> diff --git a/libavdevice/version.h b/libavdevice/version.h
> index 6021a0d..8daeb00 100644
> --- a/libavdevice/version.h
> +++ b/libavdevice/version.h
> @@ -29,7 +29,7 @@
>
> #define LIBAVDEVICE_VERSION_MAJOR  59
> #define LIBAVDEVICE_VERSION_MINOR   0
> -#define LIBAVDEVICE_VERSION_MICRO 100
> +#define LIBAVDEVICE_VERSION_MICRO 101
>
> #define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \
>                                                LIBAVDEVICE_VERSION_MINOR, \

Otherwise LGTM for the whole patchset. Maybe the commit messages should be 
slightly clarified, e.g. instead of

add sqd configure

something like

add sqd configuration option

Thanks,
Marton


More information about the ffmpeg-devel mailing list