[FFmpeg-devel] [PATCH 1/1] avdevice/decklink_dec: Autodetect the video input format
Marton Balint
cus at passwd.hu
Wed Nov 15 21:41:38 EET 2017
On Tue, 7 Nov 2017, Jeyapal, Karthick wrote:
>> On 11/6/17, 6:19 AM, "Marton Balint" <cus at passwd.hu> wrote:
>>
>>> On Fri, 27 Oct 2017, Jeyapal, Karthick wrote:
>>
>>> Please find the patch attached.
>>>
>>
>> Thanks, below some comments:
>
> Thanks a lot for your detailed comments. I have incorporated all your comments in this new patch(es).
> Also, I have split it as two patches as you suggested. Please find them attached.
For the first patch, I think you forgot to call ff_decklink_set_configs in
decklink_enc.
For the second patch here are some comments:
> From 041bed1ef07e59419f1befda3f064f0fe3f8e30b Mon Sep 17 00:00:00 2001
> From: Karthick J <kjeyapal at akamai.com>
> Date: Fri, 27 Oct 2017 12:00:23 +0530
> Subject: [PATCH 2/2] libavdevice/decklink_dec: Autodetect the video input
> format
>
> When -format_code is not specified autodetection will happen
> ---
> doc/indevs.texi | 2 ++
> libavdevice/decklink_common.cpp | 3 --
> libavdevice/decklink_common.h | 1 +
> libavdevice/decklink_common_c.h | 6 ++++
> libavdevice/decklink_dec.cpp | 78 ++++++++++++++++++++++++++++++++++-------
> 5 files changed, 74 insertions(+), 16 deletions(-)
>
> diff --git a/doc/indevs.texi b/doc/indevs.texi
> index d308bbf..56066bf 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 b952e74..6ef2c52 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 4345156..d18b643 100644
> --- a/libavdevice/decklink_common.h
> +++ b/libavdevice/decklink_common.h
> @@ -95,6 +95,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_common_c.h b/libavdevice/decklink_common_c.h
> index 368ac25..4e4c369 100644
> --- a/libavdevice/decklink_common_c.h
> +++ b/libavdevice/decklink_common_c.h
> @@ -23,6 +23,12 @@
> #ifndef AVDEVICE_DECKLINK_COMMON_C_H
> #define AVDEVICE_DECKLINK_COMMON_C_H
>
> +#ifdef _WIN32
> +#define DECKLINK_BOOL BOOL
> +#else
> +#define DECKLINK_BOOL bool
> +#endif
> +
This rather belongs to decklink_common.h.
> typedef enum DecklinkPtsSource {
> PTS_SRC_AUDIO = 1,
> PTS_SRC_VIDEO = 2,
> diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp
> index 242a194..60017e4 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,17 @@ HRESULT decklink_input_callback::VideoInputFrameArrived(
> BMDTimeValue frameDuration;
> int64_t wallclock = 0;
>
> + if (ctx->autodetect) {
> + pthread_mutex_lock(&ctx->mutex);
Do you still need a mutex? VideoInputFrameArrived and
VideoInputFormatChanged are called from the same thread, no?
> + if (videoFrame && !(videoFrame->GetFlags() & bmdFrameHasNoInputSource) &&
> + ctx->bmd_mode == bmdModeUnknown)
> + {
> + ctx->bmd_mode = AUTODETECT_DEFAULT_MODE;
> + }
> + pthread_mutex_unlock(&ctx->mutex);
> + 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 +807,47 @@ HRESULT decklink_input_callback::VideoInputFormatChanged(
> BMDVideoInputFormatChangedEvents events, IDeckLinkDisplayMode *mode,
> BMDDetectedVideoInputFormatFlags)
> {
> + pthread_mutex_lock(&ctx->mutex);
> + ctx->bmd_mode = mode->GetDisplayMode();
> + pthread_mutex_unlock(&ctx->mutex);
> 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;
> +
> +
> + 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;
> + }
> +
> + av_usleep(1000000); // 1 second timeout for any input frames to arrive
Have you considered something like:
for (i = 0; i < 25; i++) {
av_usleep(40000);
if (ctx->bmd_mode != bmdModeUnknown)
break;
}
> +
> + ctx->dli->PauseStreams();
> + ctx->dli->FlushStreams();
> + ctx->autodetect = 0;
> + if (ctx->bmd_mode != bmdModeUnknown) {
> + cctx->format_code = (char *)av_calloc(1, 5);
av_mallocz(5)
Missing failure check.
> + 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" {
> @@ -916,19 +959,30 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx)
> goto error;
> }
>
> + avpacket_queue_init (avctx, &ctx->queue);
> +
> + ctx->input_callback = new decklink_input_callback(avctx);
> + ctx->dli->SetCallback(ctx->input_callback);
> +
I'd rather put these after ff_decklink_set_configs.
> if (ff_decklink_set_configs(avctx, DIRECTION_IN) < 0) {
> av_log(avctx, AV_LOG_ERROR, "Could not set input configuration\n");
> ret = AVERROR(EIO);
> 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);
> + 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
> @@ -1056,9 +1110,7 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx)
> goto error;
> }
>
> - 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;
> --
> 1.9.1
>
Regards,
Marton
More information about the ffmpeg-devel
mailing list