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

Marton Balint cus at passwd.hu
Thu Aug 12 23:05:47 EEST 2021



On Tue, 10 Aug 2021, lance.lmwang at gmail.com wrote:

> From: Limin Wang <lance.lmwang at gmail.com>
>
> Signed-off-by: Limin Wang <lance.lmwang at gmail.com>
> ---
> doc/indevs.texi                 | 16 +++++++++++++++-
> doc/outdevs.texi                | 16 +++++++++++++++-
> libavdevice/decklink_common.cpp |  4 ++--
> libavdevice/decklink_common.h   | 11 +++++++++++
> libavdevice/decklink_dec_c.c    | 10 ++++++++++
> libavdevice/decklink_enc_c.c    | 10 ++++++++++
> 6 files changed, 63 insertions(+), 4 deletions(-)
>
> diff --git a/doc/indevs.texi b/doc/indevs.texi
> index b377924..c2ec0f4 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 mode for DeckLink 8K Pro(Updated DeckLink SDK to >= 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 mode 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..47dd913 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 mode for DeckLink 8K Pro(Updated DeckLink SDK to >= 11.0):

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 mode for DeckLink Quad 2 and DeckLink Duo 2:

modes

> + 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..8e77f4d 100644
> --- a/libavdevice/decklink_common.cpp
> +++ b/libavdevice/decklink_common.cpp
> @@ -182,7 +182,7 @@ 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 = decklink_profile_id_map[ctx->duplex_mode];

I'd rather check if ctx->duplex_mode is not out of the array indexes and 
return EINVAL if it is. Should not happen, but in other places we check 
it so, let's check it here as well for consistencty.

>             res = manager->GetProfile(bmd_profile_id, &profile);
>             if (res == S_OK) {
>                 res = profile->SetActive();
> @@ -195,7 +195,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");

stray space before ||

>         } 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..d86ba1f 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 >= 0x0b020000

I guess this also supposed to be 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"},

This also needs a micro bump. Or, if you push these four patches at once, 
then it is also OK (I think) to only bump in the last patch.

Thanks,
Marton


More information about the ffmpeg-devel mailing list