Reviewed-by: Deti Fliegl <deti@fliegl.de> Signed-off-by: Marton Balint <cus@passwd.hu>tags/n3.2
| @@ -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 | |||
| @@ -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); | |||
| @@ -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); | |||
| @@ -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 */ | |||
| @@ -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 | |||
| @@ -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 }, | |||
| }; | |||