avdevice/decklink: add support for audio and video input selection
authorMarton Balint <cus@passwd.hu>
Sat, 18 Jun 2016 10:04:15 +0000 (12:04 +0200)
committerMarton Balint <cus@passwd.hu>
Sun, 26 Jun 2016 17:18:02 +0000 (19:18 +0200)
Reviewed-by: Deti Fliegl <deti@fliegl.de>
Signed-off-by: Marton Balint <cus@passwd.hu>
doc/indevs.texi
libavdevice/decklink_common.cpp
libavdevice/decklink_common.h
libavdevice/decklink_common_c.h
libavdevice/decklink_dec.cpp
libavdevice/decklink_dec_c.c

index 479932a..5239287 100644 (file)
@@ -255,6 +255,16 @@ Defaults to @samp{2}.
 Sets the decklink device duplex mode. Must be @samp{unset}, @samp{half} or @samp{full}.
 Defaults to @samp{unset}.
 
+@item video_input
+Sets the video input source. Must be @samp{unset}, @samp{sdi}, @samp{hdmi},
+@samp{optical_sdi}, @samp{component}, @samp{composite} or @samp{s_video}.
+Defaults to @samp{unset}.
+
+@item audio_input
+Sets the audio input source. Must be @samp{unset}, @samp{embedded},
+@samp{aes_ebu}, @samp{analog}, @samp{analog_xlr}, @samp{analog_rca} or
+@samp{microphone}. Defaults to @samp{unset}.
+
 @end table
 
 @subsection Examples
index b6a2c96..3625673 100644 (file)
@@ -98,6 +98,35 @@ HRESULT ff_decklink_get_display_name(IDeckLink *This, const char **displayName)
     return hr;
 }
 
+static int decklink_select_input(AVFormatContext *avctx, BMDDeckLinkConfigurationID cfg_id)
+{
+    struct decklink_cctx *cctx = (struct decklink_cctx *) avctx->priv_data;
+    struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx;
+    BMDDeckLinkAttributeID attr_id = (cfg_id == bmdDeckLinkConfigAudioInputConnection) ? BMDDeckLinkAudioInputConnections : BMDDeckLinkVideoInputConnections;
+    int64_t bmd_input              = (cfg_id == bmdDeckLinkConfigAudioInputConnection) ? ctx->audio_input : ctx->video_input;
+    const char *type_name          = (cfg_id == bmdDeckLinkConfigAudioInputConnection) ? "audio" : "video";
+    int64_t supported_connections = 0;
+    HRESULT res;
+
+    if (bmd_input) {
+        res = ctx->attr->GetInt(attr_id, &supported_connections);
+        if (res != S_OK) {
+            av_log(avctx, AV_LOG_ERROR, "Failed to query supported %s inputs.\n", type_name);
+            return AVERROR_EXTERNAL;
+        }
+        if ((supported_connections & bmd_input) != bmd_input) {
+            av_log(avctx, AV_LOG_ERROR, "Device does not support selected %s input.\n", type_name);
+            return AVERROR(ENOSYS);
+        }
+        res = ctx->cfg->SetInt(cfg_id, bmd_input);
+        if (res != S_OK) {
+            av_log(avctx, AV_LOG_ERROR, "Failed to select %s input.\n", type_name);
+            return AVERROR_EXTERNAL;
+        }
+    }
+    return 0;
+}
+
 int ff_decklink_set_format(AVFormatContext *avctx,
                                int width, int height,
                                int tb_num, int tb_den,
@@ -129,6 +158,13 @@ int ff_decklink_set_format(AVFormatContext *avctx,
     }
 
     if (direction == DIRECTION_IN) {
+        int ret;
+        ret = decklink_select_input(avctx, bmdDeckLinkConfigAudioInputConnection);
+        if (ret < 0)
+            return ret;
+        ret = decklink_select_input(avctx, bmdDeckLinkConfigVideoInputConnection);
+        if (ret < 0)
+            return ret;
         res = ctx->dli->GetDisplayModeIterator (&itermode);
     } else {
         res = ctx->dlo->GetDisplayModeIterator (&itermode);
@@ -224,6 +260,13 @@ int ff_decklink_list_formats(AVFormatContext *avctx, decklink_direction_t direct
     HRESULT res;
 
     if (direction == DIRECTION_IN) {
+        int ret;
+        ret = decklink_select_input(avctx, bmdDeckLinkConfigAudioInputConnection);
+        if (ret < 0)
+            return ret;
+        ret = decklink_select_input(avctx, bmdDeckLinkConfigVideoInputConnection);
+        if (ret < 0)
+            return ret;
         res = ctx->dli->GetDisplayModeIterator (&itermode);
     } else {
         res = ctx->dlo->GetDisplayModeIterator (&itermode);
index 201eb15..44edf19 100644 (file)
@@ -53,6 +53,8 @@ struct decklink_ctx {
     BMDTimeValue bmd_tb_den;
     BMDTimeValue bmd_tb_num;
     BMDDisplayMode bmd_mode;
+    BMDVideoConnection video_input;
+    BMDAudioConnection audio_input;
     int bmd_width;
     int bmd_height;
     int bmd_field_dominance;
@@ -102,6 +104,25 @@ IDeckLinkIterator *CreateDeckLinkIteratorInstance(void);
 typedef uint32_t buffercount_type;
 #endif
 
+static const BMDAudioConnection decklink_audio_connection_map[] = {
+    0,
+    bmdAudioConnectionEmbedded,
+    bmdAudioConnectionAESEBU,
+    bmdAudioConnectionAnalog,
+    bmdAudioConnectionAnalogXLR,
+    bmdAudioConnectionAnalogRCA,
+    bmdAudioConnectionMicrophone,
+};
+
+static const BMDVideoConnection decklink_video_connection_map[] = {
+    0,
+    bmdVideoConnectionSDI,
+    bmdVideoConnectionHDMI,
+    bmdVideoConnectionOpticalSDI,
+    bmdVideoConnectionComponent,
+    bmdVideoConnectionComposite,
+    bmdVideoConnectionSVideo,
+};
 
 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, decklink_direction_t direction = DIRECTION_OUT, int num = 0);
index f24f8f0..8de853d 100644 (file)
@@ -35,6 +35,8 @@ struct decklink_cctx {
     int v210;
     int audio_channels;
     int duplex_mode;
+    int audio_input;
+    int video_input;
 };
 
 #endif /* AVDEVICE_DECKLINK_COMMON_C_H */
index fc9633f..7f45224 100644 (file)
@@ -28,6 +28,7 @@ extern "C" {
 #include "config.h"
 #include "libavformat/avformat.h"
 #include "libavformat/internal.h"
+#include "libavutil/common.h"
 #include "libavutil/imgutils.h"
 #if CONFIG_LIBZVBI
 #include <libzvbi.h>
@@ -446,6 +447,10 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx)
     ctx->teletext_lines = cctx->teletext_lines;
     ctx->preroll      = cctx->preroll;
     ctx->duplex_mode  = cctx->duplex_mode;
+    if (cctx->video_input > 0 && (unsigned int)cctx->video_input < FF_ARRAY_ELEMS(decklink_video_connection_map))
+        ctx->video_input = decklink_video_connection_map[cctx->video_input];
+    if (cctx->audio_input > 0 && (unsigned int)cctx->audio_input < FF_ARRAY_ELEMS(decklink_audio_connection_map))
+        ctx->audio_input = decklink_audio_connection_map[cctx->audio_input];
     cctx->ctx = ctx;
 
 #if !CONFIG_LIBZVBI
index 72baa7d..06281fb 100644 (file)
@@ -40,6 +40,22 @@ static const AVOption options[] = {
     { "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"},
+    { "video_input",  "video input",              OFFSET(video_input),    AV_OPT_TYPE_INT,   { .i64 = 0}, 0, 6,    DEC, "video_input"},
+    { "unset",         NULL,                                          0,  AV_OPT_TYPE_CONST, { .i64 = 0}, 0, 0,    DEC, "video_input"},
+    { "sdi",           NULL,                                          0,  AV_OPT_TYPE_CONST, { .i64 = 1}, 0, 0,    DEC, "video_input"},
+    { "hdmi",          NULL,                                          0,  AV_OPT_TYPE_CONST, { .i64 = 2}, 0, 0,    DEC, "video_input"},
+    { "optical_sdi",   NULL,                                          0,  AV_OPT_TYPE_CONST, { .i64 = 3}, 0, 0,    DEC, "video_input"},
+    { "component",     NULL,                                          0,  AV_OPT_TYPE_CONST, { .i64 = 4}, 0, 0,    DEC, "video_input"},
+    { "composite",     NULL,                                          0,  AV_OPT_TYPE_CONST, { .i64 = 5}, 0, 0,    DEC, "video_input"},
+    { "s_video",       NULL,                                          0,  AV_OPT_TYPE_CONST, { .i64 = 6}, 0, 0,    DEC, "video_input"},
+    { "audio_input",  "audio input",              OFFSET(audio_input),    AV_OPT_TYPE_INT,   { .i64 = 0}, 0, 6,    DEC, "audio_input"},
+    { "unset",         NULL,                                          0,  AV_OPT_TYPE_CONST, { .i64 = 0}, 0, 0,    DEC, "audio_input"},
+    { "embedded",      NULL,                                          0,  AV_OPT_TYPE_CONST, { .i64 = 1}, 0, 0,    DEC, "audio_input"},
+    { "aes_ebu",       NULL,                                          0,  AV_OPT_TYPE_CONST, { .i64 = 2}, 0, 0,    DEC, "audio_input"},
+    { "analog",        NULL,                                          0,  AV_OPT_TYPE_CONST, { .i64 = 3}, 0, 0,    DEC, "audio_input"},
+    { "analog_xlr",    NULL,                                          0,  AV_OPT_TYPE_CONST, { .i64 = 4}, 0, 0,    DEC, "audio_input"},
+    { "analog_rca",    NULL,                                          0,  AV_OPT_TYPE_CONST, { .i64 = 5}, 0, 0,    DEC, "audio_input"},
+    { "microphone",    NULL,                                          0,  AV_OPT_TYPE_CONST, { .i64 = 6}, 0, 0,    DEC, "audio_input"},
     { NULL },
 };