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>
pull/272/head
Karthick J 7 years ago committed by Marton Balint
parent aa7b0329ff
commit e8e9306b4f
  1. 2
      doc/indevs.texi
  2. 3
      libavdevice/decklink_common.cpp
  3. 7
      libavdevice/decklink_common.h
  4. 81
      libavdevice/decklink_dec.cpp

@ -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}. the supported values of your device(s) use @option{list_formats}.
Note that there is a FourCC @option{'pal '} that can also be used Note that there is a FourCC @option{'pal '} that can also be used
as @option{pal} (3 letters). as @option{pal} (3 letters).
Default behavior is autodetection of the input video format, if the hardware
supports it.
@item bm_v210 @item bm_v210
This is a deprecated option, you can use @option{raw_format} instead. This is a deprecated option, you can use @option{raw_format} instead.

@ -75,7 +75,6 @@ static char *dup_wchar_to_utf8(wchar_t *w)
#define DECKLINK_STR OLECHAR * #define DECKLINK_STR OLECHAR *
#define DECKLINK_STRDUP dup_wchar_to_utf8 #define DECKLINK_STRDUP dup_wchar_to_utf8
#define DECKLINK_FREE(s) SysFreeString(s) #define DECKLINK_FREE(s) SysFreeString(s)
#define DECKLINK_BOOL BOOL
#elif defined(__APPLE__) #elif defined(__APPLE__)
static char *dup_cfstring_to_utf8(CFStringRef w) 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_STR const __CFString *
#define DECKLINK_STRDUP dup_cfstring_to_utf8 #define DECKLINK_STRDUP dup_cfstring_to_utf8
#define DECKLINK_FREE(s) CFRelease(s) #define DECKLINK_FREE(s) CFRelease(s)
#define DECKLINK_BOOL bool
#else #else
#define DECKLINK_STR const char * #define DECKLINK_STR const char *
#define DECKLINK_STRDUP av_strdup #define DECKLINK_STRDUP av_strdup
/* free() is needed for a string returned by the DeckLink SDL. */ /* free() is needed for a string returned by the DeckLink SDL. */
#define DECKLINK_FREE(s) free((void *) s) #define DECKLINK_FREE(s) free((void *) s)
#define DECKLINK_BOOL bool
#endif #endif
HRESULT ff_decklink_get_display_name(IDeckLink *This, const char **displayName) HRESULT ff_decklink_get_display_name(IDeckLink *This, const char **displayName)

@ -28,6 +28,12 @@
#include "libavutil/thread.h" #include "libavutil/thread.h"
#include "decklink_common_c.h" #include "decklink_common_c.h"
#ifdef _WIN32
#define DECKLINK_BOOL BOOL
#else
#define DECKLINK_BOOL bool
#endif
class decklink_output_callback; class decklink_output_callback;
class decklink_input_callback; class decklink_input_callback;
@ -95,6 +101,7 @@ struct decklink_ctx {
pthread_mutex_t mutex; pthread_mutex_t mutex;
pthread_cond_t cond; pthread_cond_t cond;
int frames_buffer_available_spots; int frames_buffer_available_spots;
int autodetect;
int channels; int channels;
int audio_depth; int audio_depth;

@ -36,6 +36,7 @@ extern "C" {
#include "libavutil/avutil.h" #include "libavutil/avutil.h"
#include "libavutil/common.h" #include "libavutil/common.h"
#include "libavutil/imgutils.h" #include "libavutil/imgutils.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/time.h" #include "libavutil/time.h"
#include "libavutil/mathematics.h" #include "libavutil/mathematics.h"
#include "libavutil/reverse.h" #include "libavutil/reverse.h"
@ -49,6 +50,7 @@ extern "C" {
#include "decklink_dec.h" #include "decklink_dec.h"
#define MAX_WIDTH_VANC 1920 #define MAX_WIDTH_VANC 1920
const BMDDisplayMode AUTODETECT_DEFAULT_MODE = bmdModeNTSC;
typedef struct VANCLineNumber { typedef struct VANCLineNumber {
BMDDisplayMode mode; BMDDisplayMode mode;
@ -634,6 +636,15 @@ HRESULT decklink_input_callback::VideoInputFrameArrived(
BMDTimeValue frameDuration; BMDTimeValue frameDuration;
int64_t wallclock = 0; 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++; ctx->frameCount++;
if (ctx->audio_pts_source == PTS_SRC_WALLCLOCK || ctx->video_pts_source == PTS_SRC_WALLCLOCK) if (ctx->audio_pts_source == PTS_SRC_WALLCLOCK || ctx->video_pts_source == PTS_SRC_WALLCLOCK)
wallclock = av_gettime_relative(); wallclock = av_gettime_relative();
@ -794,17 +805,56 @@ HRESULT decklink_input_callback::VideoInputFormatChanged(
BMDVideoInputFormatChangedEvents events, IDeckLinkDisplayMode *mode, BMDVideoInputFormatChangedEvents events, IDeckLinkDisplayMode *mode,
BMDDetectedVideoInputFormatFlags) BMDDetectedVideoInputFormatFlags)
{ {
ctx->bmd_mode = mode->GetDisplayMode();
return S_OK; return S_OK;
} }
static HRESULT decklink_start_input(AVFormatContext *avctx) static int decklink_autodetect(struct decklink_cctx *cctx) {
{
struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data;
struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx; 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" { extern "C" {
@ -922,13 +972,22 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx)
goto error; goto error;
} }
if (mode_num > 0 || cctx->format_code) { ctx->input_callback = new decklink_input_callback(avctx);
if (ff_decklink_set_format(avctx, DIRECTION_IN, mode_num) < 0) { ctx->dli->SetCallback(ctx->input_callback);
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); 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); ret = AVERROR(EIO);
goto error; 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 #if !CONFIG_LIBZVBI
@ -1058,7 +1117,7 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx)
avpacket_queue_init (avctx, &ctx->queue); 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"); av_log(avctx, AV_LOG_ERROR, "Cannot start input stream\n");
ret = AVERROR(EIO); ret = AVERROR(EIO);
goto error; goto error;

Loading…
Cancel
Save