[FFmpeg-devel] [PATCH 2/4] libavdevice/decklink: add support for -sources and -sinks arguments
Marton Balint
cus at passwd.hu
Sat Sep 30 23:02:51 EEST 2017
On Tue, 26 Sep 2017, Devin Heitmueller wrote:
> Add support for enumerating the sources/sinks via the ffmpeg
> command line options, as opposed to having to create a real pipeline
> and use the "-list_devices" option which does exit() after dumping
> out the options.
>
> Note that this patch preserves the existing "-list_devices" option,
> but now shares common code for the actual enumeration.
>
> Signed-off-by: Devin Heitmueller <dheitmueller at ltnglobal.com>
> ---
> libavdevice/decklink_common.cpp | 52 +++++++++++++++++++++++++++++++++++++----
> libavdevice/decklink_common.h | 2 +-
> libavdevice/decklink_dec.cpp | 22 ++++++++++++++++-
> libavdevice/decklink_dec.h | 1 +
> libavdevice/decklink_dec_c.c | 1 +
> libavdevice/decklink_enc.cpp | 22 ++++++++++++++++-
> libavdevice/decklink_enc.h | 1 +
> libavdevice/decklink_enc_c.c | 1 +
> 8 files changed, 95 insertions(+), 7 deletions(-)
>
> diff --git a/libavdevice/decklink_common.cpp b/libavdevice/decklink_common.cpp
> index 7745575d0e..86d6fbb74b 100644
> --- a/libavdevice/decklink_common.cpp
> +++ b/libavdevice/decklink_common.cpp
> @@ -37,6 +37,7 @@ extern "C" {
> #include "libavutil/imgutils.h"
> #include "libavutil/intreadwrite.h"
> #include "libavutil/bswap.h"
> +#include "avdevice.h"
> }
>
> #include "decklink_common.h"
> @@ -261,24 +262,67 @@ int ff_decklink_set_format(AVFormatContext *avctx, decklink_direction_t directio
> return ff_decklink_set_format(avctx, 0, 0, 0, 0, AV_FIELD_UNKNOWN, direction, num);
> }
>
> -int ff_decklink_list_devices(AVFormatContext *avctx)
> +int ff_decklink_list_devices(AVFormatContext *avctx,
> + struct AVDeviceInfoList *device_list,
> + int show_inputs, int show_outputs)
> {
> IDeckLink *dl = NULL;
> IDeckLinkIterator *iter = CreateDeckLinkIteratorInstance();
> + int ret = 0;
> +
> if (!iter) {
> av_log(avctx, AV_LOG_ERROR, "Could not create DeckLink iterator\n");
> return AVERROR(EIO);
> }
> - av_log(avctx, AV_LOG_INFO, "Blackmagic DeckLink devices:\n");
> +
> while (iter->Next(&dl) == S_OK) {
This probably needs an additional && ret == 0 condition, if there was an
ENOMEM error, you want to return instantly instead of trying with the next
device, and ignoring the ENOMEM.
> + IDeckLinkOutput *output_config;
> + IDeckLinkInput *input_config;
> const char *displayName;
> + AVDeviceInfo *new_device = NULL;
> + int add = 0;
> +
> ff_decklink_get_display_name(dl, &displayName);
> - av_log(avctx, AV_LOG_INFO, "\t'%s'\n", displayName);
> +
> + if (show_outputs) {
> + if (dl->QueryInterface(IID_IDeckLinkOutput, (void **)&output_config) == S_OK) {
> + output_config->Release();
> + add = 1;
> + }
> + }
> +
> + if (show_inputs) {
> + if (dl->QueryInterface(IID_IDeckLinkInput, (void **)&input_config) == S_OK) {
> + input_config->Release();
> + add = 1;
> + }
> + }
> +
> + if (add == 1) {
> + new_device = (AVDeviceInfo *) av_mallocz(sizeof(AVDeviceInfo));
> + if (!new_device) {
> + ret = AVERROR(ENOMEM);
> + goto next;
> + }
> + new_device->device_name = av_strdup(displayName);
> + new_device->device_description = av_strdup(displayName);
> + if (!new_device->device_description || !new_device->device_name) {
you might leak device_name here.
> + ret = AVERROR(ENOMEM);
> + goto next;
> + }
> +
> + if ((ret = av_dynarray_add_nofree(&device_list->devices,
> + &device_list->nb_devices, new_device)) < 0) {
you should free the struct on error here I think
> + goto next;
> + }
> + }
> +
> + next:
> av_free((void *) displayName);
av_freep
> dl->Release();
> }
> iter->Release();
> - return 0;
> + return ret;
> }
>
> int ff_decklink_list_formats(AVFormatContext *avctx, decklink_direction_t direction)
> diff --git a/libavdevice/decklink_common.h b/libavdevice/decklink_common.h
> index 749eb0f8b8..f81b33ada4 100644
> --- a/libavdevice/decklink_common.h
> +++ b/libavdevice/decklink_common.h
> @@ -135,7 +135,7 @@ static const BMDVideoConnection decklink_video_connection_map[] = {
> HRESULT ff_decklink_get_display_name(IDeckLink *This, const char **displayName);
> 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);
> -int ff_decklink_list_devices(AVFormatContext *avctx);
> +int ff_decklink_list_devices(AVFormatContext *avctx, struct AVDeviceInfoList *device_list, int show_inputs, int show_outputs);
> int ff_decklink_list_formats(AVFormatContext *avctx, decklink_direction_t direction = DIRECTION_OUT);
> void ff_decklink_cleanup(AVFormatContext *avctx);
> int ff_decklink_init_device(AVFormatContext *avctx, const char* name);
> diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp
> index c271ff3639..cb282055c6 100644
> --- a/libavdevice/decklink_dec.cpp
> +++ b/libavdevice/decklink_dec.cpp
> @@ -38,6 +38,7 @@ extern "C" {
> #include "libavutil/time.h"
> #include "libavutil/mathematics.h"
> #include "libavutil/reverse.h"
> +#include "avdevice.h"
> #if CONFIG_LIBZVBI
> #include <libzvbi.h>
> #endif
> @@ -647,7 +648,21 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx)
>
> /* List available devices. */
> if (ctx->list_devices) {
> - ff_decklink_list_devices(avctx);
> + struct AVDeviceInfoList *device_list = NULL;
> + int ret;
> +
> + device_list = (struct AVDeviceInfoList *) av_mallocz(sizeof(AVDeviceInfoList));
> + if (!device_list)
> + return AVERROR(ENOMEM);
> +
> + ret = ff_decklink_list_devices(avctx, device_list, 1, 0);
> + if (ret == 0) {
> + av_log(avctx, AV_LOG_INFO, "Blackmagic DeckLink input devices:\n");
> + 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);
> + }
> + }
> + avdevice_free_list_devices(&device_list);
> return AVERROR_EXIT;
> }
>
> @@ -810,4 +825,9 @@ int ff_decklink_read_packet(AVFormatContext *avctx, AVPacket *pkt)
> return 0;
> }
>
> +int ff_decklink_list_input_devices(AVFormatContext *avctx, struct AVDeviceInfoList *device_list)
> +{
> + return ff_decklink_list_devices(avctx, device_list, 1, 0);
> +}
> +
> } /* extern "C" */
> diff --git a/libavdevice/decklink_dec.h b/libavdevice/decklink_dec.h
> index 9b71870deb..fbfbe6280e 100644
> --- a/libavdevice/decklink_dec.h
> +++ b/libavdevice/decklink_dec.h
> @@ -29,6 +29,7 @@ extern "C" {
> int ff_decklink_read_header(AVFormatContext *avctx);
> int ff_decklink_read_packet(AVFormatContext *avctx, AVPacket *pkt);
> int ff_decklink_read_close(AVFormatContext *avctx);
> +int ff_decklink_list_input_devices(AVFormatContext *avctx, struct AVDeviceInfoList *device_list);
>
> #ifdef __cplusplus
> } /* extern "C" */
> diff --git a/libavdevice/decklink_dec_c.c b/libavdevice/decklink_dec_c.c
> index e2118a619c..992c21a160 100644
> --- a/libavdevice/decklink_dec_c.c
> +++ b/libavdevice/decklink_dec_c.c
> @@ -83,6 +83,7 @@ AVInputFormat ff_decklink_demuxer = {
> .flags = AVFMT_NOFILE,
> .priv_class = &decklink_demuxer_class,
> .priv_data_size = sizeof(struct decklink_cctx),
> + .get_device_list = ff_decklink_list_input_devices,
> .read_header = ff_decklink_read_header,
> .read_packet = ff_decklink_read_packet,
> .read_close = ff_decklink_read_close,
> diff --git a/libavdevice/decklink_enc.cpp b/libavdevice/decklink_enc.cpp
> index 25ce7d026c..0f654faa19 100644
> --- a/libavdevice/decklink_enc.cpp
> +++ b/libavdevice/decklink_enc.cpp
> @@ -33,6 +33,7 @@ extern "C" {
> extern "C" {
> #include "libavformat/avformat.h"
> #include "libavutil/imgutils.h"
> +#include "avdevice.h"
> }
>
> #include "decklink_common.h"
> @@ -337,7 +338,21 @@ av_cold int ff_decklink_write_header(AVFormatContext *avctx)
>
> /* List available devices. */
> if (ctx->list_devices) {
> - ff_decklink_list_devices(avctx);
> + struct AVDeviceInfoList *device_list = NULL;
> + int ret;
> +
> + device_list = (struct AVDeviceInfoList *) av_mallocz(sizeof(AVDeviceInfoList));
> + if (!device_list)
> + return AVERROR(ENOMEM);
> +
> + ret = ff_decklink_list_devices(avctx, device_list, 0, 1);
> + if (ret == 0) {
> + av_log(avctx, AV_LOG_INFO, "Blackmagic DeckLink output devices:\n");
> + 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);
> + }
> + }
> + avdevice_free_list_devices(&device_list);
This code can be factorized among input and output.
> return AVERROR_EXIT;
> }
>
> @@ -400,4 +415,9 @@ int ff_decklink_write_packet(AVFormatContext *avctx, AVPacket *pkt)
> return AVERROR(EIO);
> }
>
> +int ff_decklink_list_output_devices(AVFormatContext *avctx, struct AVDeviceInfoList *device_list)
> +{
> + return ff_decklink_list_devices(avctx, device_list, 0, 1);
> +}
> +
> } /* extern "C" */
> diff --git a/libavdevice/decklink_enc.h b/libavdevice/decklink_enc.h
> index 5ffc05cd68..39237673b4 100644
> --- a/libavdevice/decklink_enc.h
> +++ b/libavdevice/decklink_enc.h
> @@ -29,6 +29,7 @@ extern "C" {
> int ff_decklink_write_header(AVFormatContext *avctx);
> int ff_decklink_write_packet(AVFormatContext *avctx, AVPacket *pkt);
> int ff_decklink_write_trailer(AVFormatContext *avctx);
> +int ff_decklink_list_output_devices(AVFormatContext *avctx, struct AVDeviceInfoList *device_list);
>
> #ifdef __cplusplus
> } /* extern "C" */
> diff --git a/libavdevice/decklink_enc_c.c b/libavdevice/decklink_enc_c.c
> index 03734f8507..360535cfda 100644
> --- a/libavdevice/decklink_enc_c.c
> +++ b/libavdevice/decklink_enc_c.c
> @@ -49,6 +49,7 @@ AVOutputFormat ff_decklink_muxer = {
> .video_codec = AV_CODEC_ID_WRAPPED_AVFRAME,
> .subtitle_codec = AV_CODEC_ID_NONE,
> .flags = AVFMT_NOFILE,
> + .get_device_list = ff_decklink_list_output_devices,
> .priv_class = &decklink_muxer_class,
> .priv_data_size = sizeof(struct decklink_cctx),
> .write_header = ff_decklink_write_header,
> --
> 2.13.2
>
Regards,
Marton
More information about the ffmpeg-devel
mailing list