|
|
|
@ -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; |
|
|
|
|