[FFmpeg-cvslog] avdevice/decklink_dec: autodetect the video input format
Karthick J
git at videolan.org
Wed Nov 22 01:34:07 EET 2017
ffmpeg | branch: master | Karthick J <kjeyapal at akamai.com> | Fri Oct 27 12:18:23 2017 +0530| [e8e9306b4f0017c3d2ae2a9f02136279c1a105e9] | committer: Marton Balint
avdevice/decklink_dec: autodetect the video input format
When -format_code is not specified autodetection will happen.
Signed-off-by: Marton Balint <cus at passwd.hu>
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=e8e9306b4f0017c3d2ae2a9f02136279c1a105e9
---
doc/indevs.texi | 2 +
libavdevice/decklink_common.cpp | 3 --
libavdevice/decklink_common.h | 7 ++++
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;
More information about the ffmpeg-cvslog
mailing list