[FFmpeg-devel] [PATCH] avdevice/decklink: add support for selecting devices based on their unique ID
Jeyapal, Karthick
kjeyapal at akamai.com
Fri Sep 21 07:48:38 EEST 2018
On 9/21/18 3:35 AM, Marton Balint wrote:
> Also bump the API version requirement to 10.9.5, because on olders versions
> there were some reports of crashes using the undocumented, yet available
> BMDDeckLinkDeviceHandle.
If we are using an undocumented API feature, then there is a higher risk of this feature not working in some future versions of DeckLink drivers as well.
I would suggest using this undocumented API call under an 'if' condition, which is controlled by a command line option for selecting based on unique ID. In that way setups which prefers stability can choose to not use this feature.
>
> Signed-off-by: Marton Balint <cus at passwd.hu>
> ---
> configure | 2 +-
> doc/indevs.texi | 3 ++-
> doc/outdevs.texi | 3 ++-
> libavdevice/decklink_common.cpp | 59 ++++++++++++++++++++++++++++-------------
> libavdevice/decklink_common.h | 1 -
> 5 files changed, 45 insertions(+), 23 deletions(-)
>
> diff --git a/configure b/configure
> index 25120337de..64a519a8b3 100755
> --- a/configure
> +++ b/configure
> @@ -6043,7 +6043,7 @@ done
> enabled cuda_sdk && require cuda_sdk cuda.h cuCtxCreate -lcuda
> enabled chromaprint && require chromaprint chromaprint.h chromaprint_get_version -lchromaprint
> enabled decklink && { require_headers DeckLinkAPI.h &&
> - { test_cpp_condition DeckLinkAPIVersion.h "BLACKMAGIC_DECKLINK_API_VERSION >= 0x0a060100" || die "ERROR: Decklink API version must be >= 10.6.1."; } }
> + { test_cpp_condition DeckLinkAPIVersion.h "BLACKMAGIC_DECKLINK_API_VERSION >= 0x0a090500" || die "ERROR: Decklink API version must be >= 10.9.5."; } }
> enabled libndi_newtek && require_headers Processing.NDI.Lib.h
> enabled frei0r && require_headers frei0r.h
> enabled gmp && require gmp gmp.h mpz_export -lgmp
> diff --git a/doc/indevs.texi b/doc/indevs.texi
> index 5d4c02c597..ed2784be9f 100644
> --- a/doc/indevs.texi
> +++ b/doc/indevs.texi
> @@ -267,7 +267,8 @@ audio track.
>
> @item list_devices
> If set to @option{true}, print a list of devices and exit.
> -Defaults to @option{false}.
> +Defaults to @option{false}. Alternatively you can use the @code{-sources}
> +option of ffmpeg to list the available input devices.
>
> @item list_formats
> If set to @option{true}, print a list of supported formats and exit.
> diff --git a/doc/outdevs.texi b/doc/outdevs.texi
> index 34c508a970..2518f9b559 100644
> --- a/doc/outdevs.texi
> +++ b/doc/outdevs.texi
> @@ -140,7 +140,8 @@ device with @command{-list_formats 1}. Audio sample rate is always 48 kHz.
>
> @item list_devices
> If set to @option{true}, print a list of devices and exit.
> -Defaults to @option{false}.
> +Defaults to @option{false}. Alternatively you can use the @code{-sinks}
> +option of ffmpeg to list the available output devices.
>
> @item list_formats
> If set to @option{true}, print a list of supported formats and exit.
> diff --git a/libavdevice/decklink_common.cpp b/libavdevice/decklink_common.cpp
> index 503417bb35..b88d6c6219 100644
> --- a/libavdevice/decklink_common.cpp
> +++ b/libavdevice/decklink_common.cpp
> @@ -77,15 +77,25 @@ static IDeckLinkIterator *decklink_create_iterator(AVFormatContext *avctx)
> return iter;
> }
>
> -HRESULT ff_decklink_get_display_name(IDeckLink *This, const char **displayName)
> +int decklink_get_attr_string(IDeckLink *dl, BMDDeckLinkAttributeID cfg_id, const char **s)
> {
> - DECKLINK_STR tmpDisplayName;
> - HRESULT hr = This->GetDisplayName(&tmpDisplayName);
> - if (hr != S_OK)
> - return hr;
> - *displayName = DECKLINK_STRDUP(tmpDisplayName);
> - DECKLINK_FREE(tmpDisplayName);
> - return hr;
> + DECKLINK_STR tmp;
> + HRESULT hr;
> + IDeckLinkAttributes *attr;
> + *s = NULL;
> + if (dl->QueryInterface(IID_IDeckLinkAttributes, (void **)&attr) != S_OK)
> + return AVERROR_EXTERNAL;
> + hr = attr->GetString(cfg_id, &tmp);
> + attr->Release();
> + if (hr == S_OK) {
> + *s = DECKLINK_STRDUP(tmp);
> + DECKLINK_FREE(tmp);
> + if (!*s)
> + return AVERROR(ENOMEM);
> + } else if (hr == E_FAIL) {
> + return AVERROR_EXTERNAL;
> + }
> + return 0;
> }
>
> static int decklink_select_input(AVFormatContext *avctx, BMDDeckLinkConfigurationID cfg_id)
> @@ -276,11 +286,17 @@ int ff_decklink_list_devices(AVFormatContext *avctx,
> while (ret == 0 && iter->Next(&dl) == S_OK) {
> IDeckLinkOutput *output_config;
> IDeckLinkInput *input_config;
> - const char *displayName;
> + const char *display_name = NULL;
> + const char *unique_name = NULL;
> AVDeviceInfo *new_device = NULL;
> int add = 0;
>
> - ff_decklink_get_display_name(dl, &displayName);
> + ret = decklink_get_attr_string(dl, BMDDeckLinkDisplayName, &display_name);
> + if (ret < 0)
> + goto next;
> + ret = decklink_get_attr_string(dl, BMDDeckLinkDeviceHandle, &unique_name);
> + if (ret < 0)
> + goto next;
>
> if (show_outputs) {
> if (dl->QueryInterface(IID_IDeckLinkOutput, (void **)&output_config) == S_OK) {
> @@ -303,8 +319,8 @@ int ff_decklink_list_devices(AVFormatContext *avctx,
> goto next;
> }
>
> - new_device->device_name = av_strdup(displayName);
> - new_device->device_description = av_strdup(displayName);
> + new_device->device_name = av_strdup(unique_name ? unique_name : display_name);
> + new_device->device_description = av_strdup(display_name);
>
> if (!new_device->device_name ||
> !new_device->device_description ||
> @@ -318,7 +334,8 @@ int ff_decklink_list_devices(AVFormatContext *avctx,
> }
>
> next:
> - av_freep(&displayName);
> + av_freep(&display_name);
> + av_freep(&unique_name);
> dl->Release();
> }
> iter->Release();
> @@ -343,7 +360,7 @@ void ff_decklink_list_devices_legacy(AVFormatContext *avctx,
> av_log(avctx, AV_LOG_INFO, "Blackmagic DeckLink %s devices:\n",
> show_inputs ? "input" : "output");
> for (int i = 0; i < device_list->nb_devices; i++) {
> - av_log(avctx, AV_LOG_INFO, "\t'%s'\n", device_list->devices[i]->device_name);
> + av_log(avctx, AV_LOG_INFO, "\t'%s'\n", device_list->devices[i]->device_description);
> }
> }
> avdevice_free_list_devices(&device_list);
> @@ -427,14 +444,18 @@ int ff_decklink_init_device(AVFormatContext *avctx, const char* name)
> return AVERROR_EXTERNAL;
>
> while (iter->Next(&dl) == S_OK) {
> - const char *displayName;
> - ff_decklink_get_display_name(dl, &displayName);
> - if (!strcmp(name, displayName)) {
> - av_free((void *)displayName);
> + const char *display_name = NULL;
> + const char *unique_name = NULL;
> + decklink_get_attr_string(dl, BMDDeckLinkDisplayName, &display_name);
> + decklink_get_attr_string(dl, BMDDeckLinkDeviceHandle, &unique_name);
> + if (display_name && !strcmp(name, display_name) || unique_name && !strcmp(name, unique_name)) {
> + av_free((void *)unique_name);
> + av_free((void *)display_name);
> ctx->dl = dl;
> break;
> }
> - av_free((void *)displayName);
> + av_free((void *)display_name);
> + av_free((void *)unique_name);
> dl->Release();
> }
> iter->Release();
> diff --git a/libavdevice/decklink_common.h b/libavdevice/decklink_common.h
> index 128144f50d..d2fc3f79d5 100644
> --- a/libavdevice/decklink_common.h
> +++ b/libavdevice/decklink_common.h
> @@ -191,7 +191,6 @@ static const BMDTimecodeFormat decklink_timecode_format_map[] = {
> bmdTimecodeSerial,
> };
>
> -HRESULT ff_decklink_get_display_name(IDeckLink *This, const char **displayName);
> 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 num = 0);
> int ff_decklink_set_format(AVFormatContext *avctx, decklink_direction_t direction, int num);
More information about the ffmpeg-devel
mailing list