aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDevin Heitmueller <dheitmueller@ltnglobal.com>2017-10-06 08:55:43 -0400
committerMarton Balint <cus@passwd.hu>2017-10-10 20:07:25 +0200
commit278588cd0bf788df0194f74e62745f68559616f9 (patch)
tree6b45e4f085055a103d796dbf7dccf938de348579
parentff6de6b180fd7c931410f81fb404ab3dbf30d40b (diff)
downloadffmpeg-278588cd0bf788df0194f74e62745f68559616f9.tar.gz
libavdevice/decklink: add support for -sources and -sinks arguments
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. Updated to reflect feedback from Marton Balint <cus@passwd.hu>. Signed-off-by: Devin Heitmueller <dheitmueller@ltnglobal.com> Signed-off-by: Marton Balint <cus@passwd.hu>
-rw-r--r--libavdevice/decklink_common.cpp89
-rw-r--r--libavdevice/decklink_common.h3
-rw-r--r--libavdevice/decklink_dec.cpp8
-rw-r--r--libavdevice/decklink_dec.h1
-rw-r--r--libavdevice/decklink_dec_c.c1
-rw-r--r--libavdevice/decklink_enc.cpp10
-rw-r--r--libavdevice/decklink_enc.h1
-rw-r--r--libavdevice/decklink_enc_c.c1
8 files changed, 104 insertions, 10 deletions
diff --git a/libavdevice/decklink_common.cpp b/libavdevice/decklink_common.cpp
index c782171f2c..2bd63ac820 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,100 @@ 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) {
+
+ while (ret == 0 && iter->Next(&dl) == S_OK) {
+ 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);
- av_free((void *) 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);
+ if (!new_device->device_name) {
+ ret = AVERROR(ENOMEM);
+ goto next;
+ }
+
+ new_device->device_description = av_strdup(displayName);
+ if (!new_device->device_description) {
+ av_freep(&new_device->device_name);
+ ret = AVERROR(ENOMEM);
+ goto next;
+ }
+
+ if ((ret = av_dynarray_add_nofree(&device_list->devices,
+ &device_list->nb_devices, new_device)) < 0) {
+ av_freep(&new_device->device_name);
+ av_freep(&new_device->device_description);
+ av_freep(&new_device);
+ goto next;
+ }
+ }
+
+ next:
+ av_freep(&displayName);
dl->Release();
}
iter->Release();
- return 0;
+ return ret;
+}
+
+/* This is a wrapper around the ff_decklink_list_devices() which dumps the
+ output to av_log() and exits (for backward compatibility with the
+ "-list_devices" argument). */
+void ff_decklink_list_devices_legacy(AVFormatContext *avctx,
+ int show_inputs, int show_outputs)
+{
+ struct AVDeviceInfoList *device_list = NULL;
+ int ret;
+
+ device_list = (struct AVDeviceInfoList *) av_mallocz(sizeof(AVDeviceInfoList));
+ if (!device_list)
+ return;
+
+ ret = ff_decklink_list_devices(avctx, device_list, show_inputs, show_outputs);
+ if (ret == 0) {
+ 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);
+ }
+ }
+ avdevice_free_list_devices(&device_list);
}
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..6b2525fb53 100644
--- a/libavdevice/decklink_common.h
+++ b/libavdevice/decklink_common.h
@@ -135,7 +135,8 @@ 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);
+void ff_decklink_list_devices_legacy(AVFormatContext *avctx, 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 6f796e4941..d9ac01ac91 100644
--- a/libavdevice/decklink_dec.cpp
+++ b/libavdevice/decklink_dec.cpp
@@ -39,6 +39,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
@@ -868,7 +869,7 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx)
/* List available devices. */
if (ctx->list_devices) {
- ff_decklink_list_devices(avctx);
+ ff_decklink_list_devices_legacy(avctx, 1, 0);
return AVERROR_EXIT;
}
@@ -1063,4 +1064,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 8b6ff067bc..1127d23ada 100644
--- a/libavdevice/decklink_dec_c.c
+++ b/libavdevice/decklink_dec_c.c
@@ -89,6 +89,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..0776741812 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"
@@ -335,9 +336,9 @@ av_cold int ff_decklink_write_header(AVFormatContext *avctx)
ctx->preroll = cctx->preroll;
cctx->ctx = ctx;
- /* List available devices. */
+ /* List available devices and exit. */
if (ctx->list_devices) {
- ff_decklink_list_devices(avctx);
+ ff_decklink_list_devices_legacy(avctx, 0, 1);
return AVERROR_EXIT;
}
@@ -400,4 +401,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,