mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
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>
This commit is contained in:
parent
aa7b0329ff
commit
e8e9306b4f
@ -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,14 +972,23 @@ 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);
|
||||||
|
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) {
|
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",
|
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);
|
mode_num, (cctx->format_code) ? cctx->format_code : "(unset)", fname);
|
||||||
ret = AVERROR(EIO);
|
ret = AVERROR(EIO);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#if !CONFIG_LIBZVBI
|
#if !CONFIG_LIBZVBI
|
||||||
if (ctx->teletext_lines && ctx->bmd_mode == bmdModePAL) {
|
if (ctx->teletext_lines && ctx->bmd_mode == bmdModePAL) {
|
||||||
@ -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…
Reference in New Issue
Block a user