diff options
author | Karthick J <kjeyapal@akamai.com> | 2017-10-27 12:00:23 +0530 |
---|---|---|
committer | Marton Balint <cus@passwd.hu> | 2017-11-22 00:08:35 +0100 |
commit | e8e9306b4f0017c3d2ae2a9f02136279c1a105e9 (patch) | |
tree | 87f0e9e5a2980a74b91031452bda64ae4451b710 | |
parent | aa7b0329ff282ea8afb3c26dcbbc64209a280219 (diff) | |
download | ffmpeg-e8e9306b4f0017c3d2ae2a9f02136279c1a105e9.tar.gz |
avdevice/decklink_dec: autodetect the video input format
When -format_code is not specified autodetection will happen.
Signed-off-by: Marton Balint <cus@passwd.hu>
-rw-r--r-- | doc/indevs.texi | 2 | ||||
-rw-r--r-- | libavdevice/decklink_common.cpp | 3 | ||||
-rw-r--r-- | libavdevice/decklink_common.h | 7 | ||||
-rw-r--r-- | libavdevice/decklink_dec.cpp | 81 |
4 files changed, 79 insertions, 14 deletions
diff --git a/doc/indevs.texi b/doc/indevs.texi index d308bbf7de..56066bf23a 100644 --- a/doc/indevs.texi +++ b/doc/indevs.texi @@ -238,6 +238,8 @@ This sets the input video format to the format given by the FourCC. To see the supported values of your device(s) use @option{list_formats}. Note that there is a FourCC @option{'pal '} that can also be used as @option{pal} (3 letters). +Default behavior is autodetection of the input video format, if the hardware +supports it. @item bm_v210 This is a deprecated option, you can use @option{raw_format} instead. diff --git a/libavdevice/decklink_common.cpp b/libavdevice/decklink_common.cpp index b952e74955..6ef2c529f4 100644 --- a/libavdevice/decklink_common.cpp +++ b/libavdevice/decklink_common.cpp @@ -75,7 +75,6 @@ static char *dup_wchar_to_utf8(wchar_t *w) #define DECKLINK_STR OLECHAR * #define DECKLINK_STRDUP dup_wchar_to_utf8 #define DECKLINK_FREE(s) SysFreeString(s) -#define DECKLINK_BOOL BOOL #elif defined(__APPLE__) static char *dup_cfstring_to_utf8(CFStringRef w) { @@ -86,13 +85,11 @@ static char *dup_cfstring_to_utf8(CFStringRef w) #define DECKLINK_STR const __CFString * #define DECKLINK_STRDUP dup_cfstring_to_utf8 #define DECKLINK_FREE(s) CFRelease(s) -#define DECKLINK_BOOL bool #else #define DECKLINK_STR const char * #define DECKLINK_STRDUP av_strdup /* free() is needed for a string returned by the DeckLink SDL. */ #define DECKLINK_FREE(s) free((void *) s) -#define DECKLINK_BOOL bool #endif HRESULT ff_decklink_get_display_name(IDeckLink *This, const char **displayName) diff --git a/libavdevice/decklink_common.h b/libavdevice/decklink_common.h index 4345156d8e..57ee7d1d68 100644 --- a/libavdevice/decklink_common.h +++ b/libavdevice/decklink_common.h @@ -28,6 +28,12 @@ #include "libavutil/thread.h" #include "decklink_common_c.h" +#ifdef _WIN32 +#define DECKLINK_BOOL BOOL +#else +#define DECKLINK_BOOL bool +#endif + class decklink_output_callback; class decklink_input_callback; @@ -95,6 +101,7 @@ struct decklink_ctx { pthread_mutex_t mutex; pthread_cond_t cond; int frames_buffer_available_spots; + int autodetect; int channels; int audio_depth; diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp index 03a049a21e..94dae26003 100644 --- a/libavdevice/decklink_dec.cpp +++ b/libavdevice/decklink_dec.cpp @@ -36,6 +36,7 @@ extern "C" { #include "libavutil/avutil.h" #include "libavutil/common.h" #include "libavutil/imgutils.h" +#include "libavutil/intreadwrite.h" #include "libavutil/time.h" #include "libavutil/mathematics.h" #include "libavutil/reverse.h" @@ -49,6 +50,7 @@ extern "C" { #include "decklink_dec.h" #define MAX_WIDTH_VANC 1920 +const BMDDisplayMode AUTODETECT_DEFAULT_MODE = bmdModeNTSC; typedef struct VANCLineNumber { BMDDisplayMode mode; @@ -634,6 +636,15 @@ HRESULT decklink_input_callback::VideoInputFrameArrived( BMDTimeValue frameDuration; int64_t wallclock = 0; + if (ctx->autodetect) { + if (videoFrame && !(videoFrame->GetFlags() & bmdFrameHasNoInputSource) && + ctx->bmd_mode == bmdModeUnknown) + { + ctx->bmd_mode = AUTODETECT_DEFAULT_MODE; + } + return S_OK; + } + ctx->frameCount++; if (ctx->audio_pts_source == PTS_SRC_WALLCLOCK || ctx->video_pts_source == PTS_SRC_WALLCLOCK) wallclock = av_gettime_relative(); @@ -794,17 +805,56 @@ HRESULT decklink_input_callback::VideoInputFormatChanged( BMDVideoInputFormatChangedEvents events, IDeckLinkDisplayMode *mode, BMDDetectedVideoInputFormatFlags) { + ctx->bmd_mode = mode->GetDisplayMode(); return S_OK; } -static HRESULT decklink_start_input(AVFormatContext *avctx) -{ - struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data; +static int decklink_autodetect(struct decklink_cctx *cctx) { struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx; + DECKLINK_BOOL autodetect_supported = false; + int i; + + if (ctx->attr->GetFlag(BMDDeckLinkSupportsInputFormatDetection, &autodetect_supported) != S_OK) + return -1; + if (autodetect_supported == false) + return -1; + + ctx->autodetect = 1; + ctx->bmd_mode = bmdModeUnknown; + if (ctx->dli->EnableVideoInput(AUTODETECT_DEFAULT_MODE, + bmdFormat8BitYUV, + bmdVideoInputEnableFormatDetection) != S_OK) { + return -1; + } + + if (ctx->dli->StartStreams() != S_OK) { + return -1; + } + + // 1 second timeout + for (i = 0; i < 10; i++) { + av_usleep(100000); + /* Sometimes VideoInputFrameArrived is called without the + * bmdFrameHasNoInputSource flag before VideoInputFormatChanged. + * So don't break for bmd_mode == AUTODETECT_DEFAULT_MODE. */ + if (ctx->bmd_mode != bmdModeUnknown && + ctx->bmd_mode != AUTODETECT_DEFAULT_MODE) + break; + } + + ctx->dli->PauseStreams(); + ctx->dli->FlushStreams(); + ctx->autodetect = 0; + if (ctx->bmd_mode != bmdModeUnknown) { + cctx->format_code = (char *)av_mallocz(5); + if (!cctx->format_code) + return -1; + AV_WB32(cctx->format_code, ctx->bmd_mode); + return 0; + } else { + return -1; + } - ctx->input_callback = new decklink_input_callback(avctx); - ctx->dli->SetCallback(ctx->input_callback); - return ctx->dli->StartStreams(); } extern "C" { @@ -922,13 +972,22 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx) goto error; } - if (mode_num > 0 || cctx->format_code) { - if (ff_decklink_set_format(avctx, DIRECTION_IN, mode_num) < 0) { - av_log(avctx, AV_LOG_ERROR, "Could not set mode number %d or format code %s for %s\n", - mode_num, (cctx->format_code) ? cctx->format_code : "(unset)", fname); + ctx->input_callback = new decklink_input_callback(avctx); + ctx->dli->SetCallback(ctx->input_callback); + + if (mode_num == 0 && !cctx->format_code) { + if (decklink_autodetect(cctx) < 0) { + av_log(avctx, AV_LOG_ERROR, "Cannot Autodetect input stream or No signal\n"); ret = AVERROR(EIO); goto error; } + av_log(avctx, AV_LOG_INFO, "Autodetected the input mode\n"); + } + if (ff_decklink_set_format(avctx, DIRECTION_IN, mode_num) < 0) { + av_log(avctx, AV_LOG_ERROR, "Could not set mode number %d or format code %s for %s\n", + mode_num, (cctx->format_code) ? cctx->format_code : "(unset)", fname); + ret = AVERROR(EIO); + goto error; } #if !CONFIG_LIBZVBI @@ -1058,7 +1117,7 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx) avpacket_queue_init (avctx, &ctx->queue); - if (decklink_start_input (avctx) != S_OK) { + if (ctx->dli->StartStreams() != S_OK) { av_log(avctx, AV_LOG_ERROR, "Cannot start input stream\n"); ret = AVERROR(EIO); goto error; |