From c0a5ce56ffa7b53ee2ecc7a3b57ff4e6200b5cc9 Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Tue, 1 Dec 2015 16:45:27 +0100 Subject: [PATCH] Decklink cap.: added input conversion --- src/video_capture/decklink.cpp | 101 ++++++++++++++++++++++++--------- 1 file changed, 74 insertions(+), 27 deletions(-) diff --git a/src/video_capture/decklink.cpp b/src/video_capture/decklink.cpp index ee5d076a4..4aa806c1f 100644 --- a/src/video_capture/decklink.cpp +++ b/src/video_capture/decklink.cpp @@ -88,6 +88,13 @@ #define STDMETHODCALLTYPE #endif +/** + * @todo + * The input conversion doesn't seem to work right now. After fixing, remove this + * macro (and related ifdefs). + */ +#define IN_CONV_BROKEN 1 + using namespace std; using namespace std::chrono; @@ -126,6 +133,7 @@ struct vidcap_decklink_state { unsigned int use_timecode:1; /* use timecode when grabbing from multiple inputs */ BMDVideoConnection connection; int audio_consumer_levels; ///< 0 false, 1 true, -1 default + BMDVideoInputConversionMode conversion_mode; struct timeval t0; }; @@ -372,9 +380,49 @@ decklink_help() HRESULT result; printf("\nDecklink options:\n"); - printf("\t-t decklink[:[::[:3D][:timecode][:connection=]][:audioConsumerLevels={true|false}]\\n"); - printf("\t\t(You can omit device index, mode and color space provided that your cards supports format autodetection.)\n"); - + printf("\t-t decklink[:[::[:3D][:timecode][:connection=][:audioConsumerLevels={true|false}]" +#ifndef IN_CONV_BROKEN + "[:conversion=]" +#endif + "]\n"); + printf("\t\tor\n"); + printf("\t-t decklink{:mode=|:dev=|:codec=...=}*\n"); + printf("\t(Mode specification is mandatory if your card does not support format autodetection.)\n"); + printf("\n"); + + printf("Available Colorspaces:\n"); + printf("\tUYVY\n"); + printf("\tv210\n"); + printf("\tRGBA\n"); + printf("\tR10k\n"); + printf("\n"); + + printf("3D\n"); + printf("\tUse this to capture 3D from supported card (eg. DeckLink HD 3D Extreme).\n"); + printf("\tDo not use it for eg. Quad or Duo. Availability of the mode is indicated\n"); + printf("\tin video format listing above (\"supports 3D\").\n"); + + printf("\n"); + printf("timecode\n"); + printf("\tTry to synchronize inputs based on timecode (for multiple inputs, eg. tiled 4K)\n"); + printf("\n"); + + printf("audioConsumerLevels\n"); + printf("\tIf set true the analog audio levels are set to maximum gain on audio input.\n"); + printf("\tIf set false the selected analog input gain levels are used.\n"); + printf("\n"); + +#ifndef IN_CONV_BROKEN + printf("conversion\n"); + printf("\tnone - No video input conversion\n"); + printf("\t10lb - HD1080 to SD video input down conversion\n"); + printf("\t10am - Anamorphic from HD1080 to SD video input down conversion\n"); + printf("\t72lb - Letter box from HD720 to SD video input down conversion\n"); + printf("\t72ab - Letterbox video input up conversion\n"); + printf("\tamup - Anamorphic video input up conversion\n"); + printf("\n"); +#endif + // Create an IDeckLinkIterator object to enumerate all DeckLink cards in the system deckLinkIterator = create_decklink_iterator(); if (deckLinkIterator == NULL) { @@ -396,7 +444,7 @@ decklink_help() release_bmd_api_str(deviceNameString); free((void *)deviceNameCString); } else { - printf("\ndevice: %d.) (unable to get name)\n\n",numDevices); + printf("\ndevice: %d.) (unable to get name)\n\n", numDevices); } // Increment the total number of DeckLink cards found @@ -442,36 +490,17 @@ decklink_help() // If no DeckLink cards were found in the system, inform the user if (numDevices == 0) { - printf("\nNo Blackmagic Design devices were found.\n"); - return 0; - } else { - printf("\n\n"); - printf("Available Colorspaces:\n"); - printf("\tUYVY\n"); - printf("\tv210\n"); - printf("\tRGBA\n"); - printf("\tR10k\n"); + log_msg(LOG_LEVEL_ERROR, "No Blackmagic Design devices were found.\n"); } - printf("\n"); - printf("3D\n"); - printf("\tUse this to capture 3D from supported card (eg. DeckLink HD 3D Extreme).\n"); - printf("\tDo not use it for eg. Quad or Duo. Availability of the mode is indicated\n"); - printf("\tin video format listing above (\"supports 3D\").\n"); - - printf("\n"); - printf("timecode\n"); - printf("\tTry to synchronize inputs based on timecode (for multiple inputs, eg. tiled 4K)\n"); - - printf("audioConsumerLevels\n"); - printf("\tIf set true the analog audio levels are set to maximum gain on audio input.\n"); - printf("\tIf set false the selected analog input gain levels are used.\n\n"); + printf("\n"); printf("Examples:\n"); printf("\t%s -t decklink # captures autodetected video from first DeckLink in system\n", uv_argv[0]); printf("\t%s -t decklink:0:Hi50:UYVY # captures 1080i50, 8-bit yuv\n", uv_argv[0]); printf("\t%s -t decklink:0:10:v210:connection=HDMI # captures 10th format from a card (alternative syntax), 10-bit YUV, from HDMI\n", uv_argv[0]); - printf("\t%s -t decklink:mode=23ps:dev=0:codec=UYVY # captures 1080p24, 8-bit yuv from frist device\n", uv_argv[0]); + printf("\t%s -t decklink:mode=23ps # captures 1080p24, 8-bit yuv from frist device\n", uv_argv[0]); + printf("\t%s -t decklink:mode=Hp30:codec=v210:dev=2 # captures 1080p30, 10-bit yuv from 3rd BMD device\n", uv_argv[0]); printf("\n"); @@ -528,6 +557,16 @@ static bool parse_option(struct vidcap_decklink_state *s, const char *opt) } else { s->audio_consumer_levels = 1; } + } else if(strncasecmp(opt, "conversion=", + strlen("conversion=")) == 0) { + const char *conversion_mode = opt + strlen("conversion="); + + union { + uint32_t fourcc; + char tmp[4]; + }; + memcpy(tmp, conversion_mode, max(strlen(conversion_mode), sizeof(tmp))); + s->conversion_mode = htonl(fourcc); } else if(strncasecmp(opt, "dev=", strlen("dev=")) == 0) { const char *devices = opt + strlen("dev="); @@ -812,6 +851,7 @@ vidcap_decklink_init(const struct vidcap_params *params, void **state) s->connection = (BMDVideoConnection) 0; s->flags = 0; s->audio_consumer_levels = -1; + s->conversion_mode = bmdNoVideoInputConversion; // SET UP device and mode char *tmp_fmt = strdup(vidcap_params_get_fmt(params)); @@ -1100,6 +1140,13 @@ vidcap_decklink_init(const struct vidcap_params *params, void **state) } } + + result = deckLinkConfiguration->SetInt(bmdDeckLinkConfigVideoInputConversionMode, s->conversion_mode); + if(result != S_OK) { + log_msg(LOG_LEVEL_ERROR, "[DeckLink capture] Unable to set conversion mode.\n"); + goto error; + } + // set Callback which returns frames s->state[i].delegate = new VideoDelegate(); s->state[i].delegate->set_device_state(s, i);