bump
On 5/12/16, 4:07 PM, "ffmpeg-devel on behalf of Felt, Patrick"
<[email protected] on behalf of [email protected]> wrote:
>I hang my head in shame. I neglected to notice that time wasn’t already
>included and so I had to modify the patch. Apologies for the noise.
>
>-- Add input mode autodetect to the decklink module. Previously users had to
>supply the input format like this 'DeckLink Device@modenum'. This patch
>allows users to either leave it off completely, or supply 0 or negative number
>to indicate autodetect is requested. Autodetect only works the first time so
>if the mode changes mid stream you'll die
>
>---
> libavdevice/decklink_common.cpp | 110 ++++++++++++++++++++++++++++++++++++++++
> libavdevice/decklink_common.h | 5 ++
> libavdevice/decklink_common_c.h | 1 +
> libavdevice/decklink_dec.cpp | 86 +++++++++++++++++++++++++------
> libavdevice/decklink_dec_c.c | 1 +
> 5 files changed, 188 insertions(+), 15 deletions(-)
>
>diff --git a/libavdevice/decklink_common.cpp b/libavdevice/decklink_common.cpp
>index ac7964c..1d51294 100644
>--- a/libavdevice/decklink_common.cpp
>+++ b/libavdevice/decklink_common.cpp
>@@ -98,6 +98,90 @@ HRESULT ff_decklink_get_display_name(IDeckLink *This, const
>char **displayName)
> return hr;
> }
>
>+long ff_decklink_mode_to_bm(AVFormatContext *avctx,
>+ decklink_direction_t direction,
>+ int ffmpeg_mode,
>+ IDeckLinkDisplayMode **mode)
>+{
>+ struct decklink_cctx *cctx = (struct decklink_cctx *) avctx->priv_data;
>+ struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx;
>+ IDeckLinkDisplayModeIterator *itermode;
>+ IDeckLinkDisplayMode *internal_mode;
>+
>+ int result=0;
>+ HRESULT res;
>+
>+ if (direction == DIRECTION_IN) {
>+ res = ctx->dli->GetDisplayModeIterator (&itermode);
>+ } else {
>+ res = ctx->dlo->GetDisplayModeIterator (&itermode);
>+ }
>+
>+ if (res != S_OK) {
>+ av_log(avctx, AV_LOG_ERROR, "Could not get the mode iterator\n");
>+ return -1;
>+ }
>+
>+ while (itermode->Next(&internal_mode) == S_OK) {
>+ if (++result == ffmpeg_mode) {
>+ break;
>+ }
>+
>+ internal_mode->Release();
>+ }
>+
>+ itermode->Release();
>+ if (internal_mode) {
>+ result = internal_mode->GetDisplayMode();
>+ if (mode) {
>+ *mode = internal_mode;
>+ } else {
>+ internal_mode->Release();
>+ }
>+
>+ return result;
>+ }
>+
>+ return 0;
>+}
>+
>+int ff_decklink_mode_to_ffmpeg(AVFormatContext *avctx,
>+ decklink_direction_t direction,
>+ IDeckLinkDisplayMode **mode)
>+{
>+ struct decklink_cctx *cctx = (struct decklink_cctx *) avctx->priv_data;
>+ struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx;
>+ IDeckLinkDisplayModeIterator *itermode;
>+ IDeckLinkDisplayMode *internal_mode;
>+ long bdm_mode_number = (*mode)->GetDisplayMode();
>+ int result=1, found=0;
>+ HRESULT res;
>+
>+ if (direction == DIRECTION_IN) {
>+ res = ctx->dli->GetDisplayModeIterator (&itermode);
>+ } else {
>+ res = ctx->dlo->GetDisplayModeIterator (&itermode);
>+ }
>+
>+ if (res != S_OK) {
>+ av_log(avctx, AV_LOG_ERROR, "Could not get the mode iterator\n");
>+ return -1;
>+ }
>+
>+ while (itermode->Next(&internal_mode) == S_OK) {
>+ if (internal_mode->GetDisplayMode() == bdm_mode_number) {
>+ internal_mode->Release();
>+ found = 1;
>+ break;
>+ }
>+ internal_mode->Release();
>+ result++;
>+ }
>+
>+ itermode->Release();
>+ return (found) ? result : -1;
>+}
>+
> int ff_decklink_set_format(AVFormatContext *avctx,
> int width, int height,
> int tb_num, int tb_den,
>@@ -197,6 +281,29 @@ int ff_decklink_list_devices(AVFormatContext *avctx)
> return 0;
> }
>
>+int ff_decklink_device_autodetect(AVFormatContext *avctx)
>+{
>+ HRESULT res;
>+ struct decklink_cctx *cctx = (struct decklink_cctx *) avctx->priv_data;
>+ struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx;
>+ IDeckLinkAttributes *attrs = NULL;
>+ bool auto_detect;
>+
>+ res = ctx->dl->QueryInterface(IID_IDeckLinkAttributes, (void**)&attrs);
>+ if (res != S_OK) {
>+ av_log(avctx, AV_LOG_ERROR, "Could not get decklink attributes\n");
>+ return -1;
>+ }
>+
>+ res = attrs->GetFlag(BMDDeckLinkSupportsInputFormatDetection,
>&auto_detect);
>+ if (res != S_OK) {
>+ av_log(avctx, AV_LOG_ERROR, "Attribute fetch failed\n");
>+ return -1;
>+ }
>+
>+ return (auto_detect) ? 1 : 0;
>+}
>+
> int ff_decklink_list_formats(AVFormatContext *avctx, decklink_direction_t
> direction)
> {
> struct decklink_cctx *cctx = (struct decklink_cctx *) avctx->priv_data;
>@@ -219,6 +326,9 @@ int ff_decklink_list_formats(AVFormatContext *avctx,
>decklink_direction_t direct
>
> av_log(avctx, AV_LOG_INFO, "Supported formats for '%s':\n",
> avctx->filename);
>+ if (ff_decklink_device_autodetect(avctx)) {
>+ av_log(avctx, AV_LOG_INFO, "\t-1\tAuto detection supported\n");
>+ }
> while (itermode->Next(&mode) == S_OK) {
> BMDTimeValue tb_num, tb_den;
> mode->GetFrameRate(&tb_num, &tb_den);
>diff --git a/libavdevice/decklink_common.h b/libavdevice/decklink_common.h
>index dff4fc1..cbe8de2 100644
>--- a/libavdevice/decklink_common.h
>+++ b/libavdevice/decklink_common.h
>@@ -84,6 +84,8 @@ struct decklink_ctx {
> sem_t semaphore;
>
> int channels;
>+ int mode_num;
>+ int auto_detect;
> };
>
> typedef enum { DIRECTION_IN, DIRECTION_OUT} decklink_direction_t;
>@@ -105,5 +107,8 @@ int ff_decklink_set_format(AVFormatContext *avctx, int
>width, int height, int tb
> int ff_decklink_set_format(AVFormatContext *avctx, decklink_direction_t
> direction, int num);
> int ff_decklink_list_devices(AVFormatContext *avctx);
> int ff_decklink_list_formats(AVFormatContext *avctx, decklink_direction_t
> direction = DIRECTION_OUT);
>+int ff_decklink_device_autodetect(AVFormatContext *avctx);
>+int ff_decklink_mode_to_ffmpeg(AVFormatContext *avctx, decklink_direction_t
>direction, IDeckLinkDisplayMode **mode);
>+long ff_decklink_mode_to_bm(AVFormatContext *avctx, decklink_direction_t
>direction, int ffmpeg_mode, IDeckLinkDisplayMode **mode);
>
> #endif /* AVDEVICE_DECKLINK_COMMON_H */
>diff --git a/libavdevice/decklink_common_c.h b/libavdevice/decklink_common_c.h
>index 2b5d92f..0d365be 100644
>--- a/libavdevice/decklink_common_c.h
>+++ b/libavdevice/decklink_common_c.h
>@@ -34,6 +34,7 @@ struct decklink_cctx {
> double preroll;
> int v210;
> int audio_channels;
>+ int autodetect_delay;
> };
>
> #endif /* AVDEVICE_DECKLINK_COMMON_C_H */
>diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp
>index 1c305f3..7f33909 100644
>--- a/libavdevice/decklink_dec.cpp
>+++ b/libavdevice/decklink_dec.cpp
>@@ -1,5 +1,5 @@
> /*
>- * Blackmagic DeckLink output
>+ * Blackmagic DeckLink input
> * Copyright (c) 2013-2014 Luca Barbato, Deti Fliegl
> *
> * This file is part of FFmpeg.
>@@ -32,6 +32,7 @@ extern "C" {
> #if CONFIG_LIBZVBI
> #include <libzvbi.h>
> #endif
>+#include "libavutil/time.h"
> }
>
> #include "decklink_common.h"
>@@ -244,6 +245,12 @@ HRESULT decklink_input_callback::VideoInputFrameArrived(
> BMDTimeValue frameTime;
> BMDTimeValue frameDuration;
>
>+ /* if we don't have video, we are in the autodetect phase. skip
>everything and let
>+ * autodetect do its magic */
>+ if (!ctx->video) {
>+ return S_OK;
>+ }
>+
> ctx->frameCount++;
>
> // Handle Video Frame
>@@ -393,6 +400,14 @@ HRESULT decklink_input_callback::VideoInputFormatChanged(
> BMDVideoInputFormatChangedEvents events, IDeckLinkDisplayMode *mode,
> BMDDetectedVideoInputFormatFlags)
> {
>+
>+ /* undo all the autodetect stuff so we can move on with life */
>+ ctx->dli->PauseStreams();
>+ ctx->dli->FlushStreams();
>+
>+ ctx->mode_num = ff_decklink_mode_to_ffmpeg(avctx, DIRECTION_IN, &mode);
>+ ctx->video = 1;
>+
> return S_OK;
> }
>
>@@ -435,14 +450,14 @@ av_cold int ff_decklink_read_header(AVFormatContext
>*avctx)
> {
> struct decklink_cctx *cctx = (struct decklink_cctx *) avctx->priv_data;
> struct decklink_ctx *ctx;
>- IDeckLinkDisplayModeIterator *itermode;
> IDeckLinkIterator *iter;
> IDeckLink *dl = NULL;
> AVStream *st;
> HRESULT result;
> char fname[1024];
> char *tmp;
>- int mode_num = 0;
>+ int auto_detect = 0;
>+ unsigned int autodetect_delay = cctx->autodetect_delay;
>
> ctx = (struct decklink_ctx *) av_mallocz(sizeof(struct decklink_ctx));
> if (!ctx)
>@@ -486,7 +501,7 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx)
> strcpy (fname, avctx->filename);
> tmp=strchr (fname, '@');
> if (tmp != NULL) {
>- mode_num = atoi (tmp+1);
>+ ctx->mode_num = atoi (tmp+1);
> *tmp = 0;
> }
>
>@@ -510,34 +525,74 @@ av_cold int ff_decklink_read_header(AVFormatContext
>*avctx)
>
> /* Get input device. */
> if (ctx->dl->QueryInterface(IID_IDeckLinkInput, (void **) &ctx->dli) !=
> S_OK) {
>- av_log(avctx, AV_LOG_ERROR, "Could not open output device from
>'%s'\n",
>+ av_log(avctx, AV_LOG_ERROR, "Could not open input device from '%s'\n",
> avctx->filename);
> ctx->dl->Release();
> return AVERROR(EIO);
> }
>
>+ auto_detect = ff_decklink_device_autodetect(avctx);
>+
> /* List supported formats. */
>- if (ctx->list_formats) {
>+ if (ctx->list_formats || (ctx->mode_num <= 0 && !auto_detect)) {
> ff_decklink_list_formats(avctx, DIRECTION_IN);
> ctx->dli->Release();
> ctx->dl->Release();
> return AVERROR_EXIT;
> }
>
>- if (ctx->dli->GetDisplayModeIterator(&itermode) != S_OK) {
>- av_log(avctx, AV_LOG_ERROR, "Could not get Display Mode Iterator\n");
>- ctx->dl->Release();
>- return AVERROR(EIO);
>- }
>+ if (ctx->mode_num <= 0 && auto_detect) {
>+ /* the user is wanting to auto detect the mode. we need to fake out
>the api and not start ffmpeg fully in this mode!*/
>+ ctx->auto_detect = 1;
>+ ctx->mode_num = 1; /* it is assumed that there is at least one mode
>supported on a decklink card. */
>+
>+ if (ff_decklink_set_format(avctx, DIRECTION_IN, ctx->mode_num) < 0) {
>+ av_log(avctx, AV_LOG_ERROR, "Could not set mode %d\n",
>ctx->mode_num);
>+ goto error;
>+ }
>
>- if (mode_num > 0) {
>- if (ff_decklink_set_format(avctx, DIRECTION_IN, mode_num) < 0) {
>- av_log(avctx, AV_LOG_ERROR, "Could not set mode %d for %s\n",
>mode_num, fname);
>+ ctx->bmd_mode = ff_decklink_mode_to_bm(avctx, DIRECTION_IN,
>ctx->mode_num, NULL);
>+ result = ctx->dli->EnableVideoInput(ctx->bmd_mode,
>+ cctx->v210 ? bmdFormat10BitYUV :
>bmdFormat8BitYUV,
>+ bmdVideoInputFlagDefault |
>bmdVideoInputEnableFormatDetection);
>+ if (result != S_OK) {
>+ av_log(avctx, AV_LOG_ERROR, "Could not enable video in the
>pre-startup autodectect mode\n");
> goto error;
> }
>+
>+ result = ctx->dli->EnableAudioInput(bmdAudioSampleRate48kHz,
>bmdAudioSampleType16bitInteger, cctx->audio_channels);
>+ if (result != S_OK) {
>+ av_log(avctx, AV_LOG_ERROR, "Could not enable audio in the
>pre-startup autodetect mode\n");
>+ goto error;
>+ }
>+
>+ result = decklink_start_input(avctx);
>+ if (result != S_OK) {
>+ av_log(avctx, AV_LOG_ERROR, "Could not start input in the
>pre-startup autodetect mode\n");
>+ goto error;
>+ }
>+
>+ /* we need to give the auto detect code some time to figure out what
>mode we are really in */
>+ autodetect_delay = cctx->autodetect_delay;
>+ while (!ctx->video) {
>+ if (autodetect_delay--) {
>+ /* this could indicate we are in the right mode. let's
>assume so */
>+ break;
>+ }
>+ /* sleep for 1 second */
>+ av_usleep(100000);
>+ }
> }
>
>- itermode->Release();
>+ /* regardless as to if we did autodetect or not, we should now be in a
>position to
>+ * continue on as before with all the right setup to ensure we get the
>right mode */
>+ ctx->video = 1;
>+ if (ctx->mode_num > 0) {
>+ if (ff_decklink_set_format(avctx, DIRECTION_IN, ctx->mode_num) < 0) {
>+ av_log(avctx, AV_LOG_ERROR, "Could not set mode %d for %s\n",
>ctx->mode_num, fname);
>+ goto error;
>+ }
>+ }
>
> /* Setup streams. */
> st = avformat_new_stream(avctx, NULL);
>@@ -618,6 +673,7 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx)
>
> return 0;
>
>+
> error:
>
> ctx->dli->Release();
>diff --git a/libavdevice/decklink_dec_c.c b/libavdevice/decklink_dec_c.c
>index 40c21a7..3f83f8f 100644
>--- a/libavdevice/decklink_dec_c.c
>+++ b/libavdevice/decklink_dec_c.c
>@@ -36,6 +36,7 @@ static const AVOption options[] = {
> { "standard", NULL, 0,
> AV_OPT_TYPE_CONST, { .i64 = 0x7fff9fffeLL}, 0, 0, DEC, "teletext_lines"},
> { "all", NULL, 0,
> AV_OPT_TYPE_CONST, { .i64 = 0x7ffffffffLL}, 0, 0, DEC, "teletext_lines"},
> { "channels", "number of audio channels", OFFSET(audio_channels),
> AV_OPT_TYPE_INT , { .i64 = 2 }, 2, 16, DEC },
>+ { "autodetect_delay", "number of seconds to wait for autodetect to
>complete", OFFSET(autodetect_delay), AV_OPT_TYPE_INT , { .i64 = 5 }, 1, 30,
>DEC },
> { NULL },
> };
>
>--
>2.7.4
>
>
>
>On 5/12/16, 3:21 PM, "ffmpeg-devel on behalf of Felt, Patrick"
><[email protected] on behalf of [email protected]> wrote:
>
>>-- Add input mode autodetect to the decklink module. Previously users had to
>>supply the input format like this 'DeckLink Device@modenum'. This patch
>>allows users to either leave it off completely, or supply 0 or negative
>>number to indicate autodetect is requested. Autodetect only works the first
>>time so if the mode changes mid stream you'll die
>>
>>
>>---
>> libavdevice/decklink_common.cpp | 110
>> ++++++++++++++++++++++++++++++++++++++++
>> libavdevice/decklink_common.h | 5 ++
>> libavdevice/decklink_common_c.h | 1 +
>> libavdevice/decklink_dec.cpp | 85 +++++++++++++++++++++++++------
>> libavdevice/decklink_dec_c.c | 1 +
>> 5 files changed, 187 insertions(+), 15 deletions(-)
>>
>>diff --git a/libavdevice/decklink_common.cpp b/libavdevice/decklink_common.cpp
>>index ac7964c..1d51294 100644
>>--- a/libavdevice/decklink_common.cpp
>>+++ b/libavdevice/decklink_common.cpp
>>@@ -98,6 +98,90 @@ HRESULT ff_decklink_get_display_name(IDeckLink *This,
>>const char **displayName)
>> return hr;
>> }
>>
>>+long ff_decklink_mode_to_bm(AVFormatContext *avctx,
>>+ decklink_direction_t direction,
>>+ int ffmpeg_mode,
>>+ IDeckLinkDisplayMode **mode)
>>+{
>>+ struct decklink_cctx *cctx = (struct decklink_cctx *) avctx->priv_data;
>>+ struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx;
>>+ IDeckLinkDisplayModeIterator *itermode;
>>+ IDeckLinkDisplayMode *internal_mode;
>>+
>>+ int result=0;
>>+ HRESULT res;
>>+
>>+ if (direction == DIRECTION_IN) {
>>+ res = ctx->dli->GetDisplayModeIterator (&itermode);
>>+ } else {
>>+ res = ctx->dlo->GetDisplayModeIterator (&itermode);
>>+ }
>>+
>>+ if (res != S_OK) {
>>+ av_log(avctx, AV_LOG_ERROR, "Could not get the mode iterator\n");
>>+ return -1;
>>+ }
>>+
>>+ while (itermode->Next(&internal_mode) == S_OK) {
>>+ if (++result == ffmpeg_mode) {
>>+ break;
>>+ }
>>+
>>+ internal_mode->Release();
>>+ }
>>+
>>+ itermode->Release();
>>+ if (internal_mode) {
>>+ result = internal_mode->GetDisplayMode();
>>+ if (mode) {
>>+ *mode = internal_mode;
>>+ } else {
>>+ internal_mode->Release();
>>+ }
>>+
>>+ return result;
>>+ }
>>+
>>+ return 0;
>>+}
>>+
>>+int ff_decklink_mode_to_ffmpeg(AVFormatContext *avctx,
>>+ decklink_direction_t direction,
>>+ IDeckLinkDisplayMode **mode)
>>+{
>>+ struct decklink_cctx *cctx = (struct decklink_cctx *) avctx->priv_data;
>>+ struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx;
>>+ IDeckLinkDisplayModeIterator *itermode;
>>+ IDeckLinkDisplayMode *internal_mode;
>>+ long bdm_mode_number = (*mode)->GetDisplayMode();
>>+ int result=1, found=0;
>>+ HRESULT res;
>>+
>>+ if (direction == DIRECTION_IN) {
>>+ res = ctx->dli->GetDisplayModeIterator (&itermode);
>>+ } else {
>>+ res = ctx->dlo->GetDisplayModeIterator (&itermode);
>>+ }
>>+
>>+ if (res != S_OK) {
>>+ av_log(avctx, AV_LOG_ERROR, "Could not get the mode iterator\n");
>>+ return -1;
>>+ }
>>+
>>+ while (itermode->Next(&internal_mode) == S_OK) {
>>+ if (internal_mode->GetDisplayMode() == bdm_mode_number) {
>>+ internal_mode->Release();
>>+ found = 1;
>>+ break;
>>+ }
>>+ internal_mode->Release();
>>+ result++;
>>+ }
>>+
>>+ itermode->Release();
>>+ return (found) ? result : -1;
>>+}
>>+
>> int ff_decklink_set_format(AVFormatContext *avctx,
>> int width, int height,
>> int tb_num, int tb_den,
>>@@ -197,6 +281,29 @@ int ff_decklink_list_devices(AVFormatContext *avctx)
>> return 0;
>> }
>>
>>+int ff_decklink_device_autodetect(AVFormatContext *avctx)
>>+{
>>+ HRESULT res;
>>+ struct decklink_cctx *cctx = (struct decklink_cctx *) avctx->priv_data;
>>+ struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx;
>>+ IDeckLinkAttributes *attrs = NULL;
>>+ bool auto_detect;
>>+
>>+ res = ctx->dl->QueryInterface(IID_IDeckLinkAttributes, (void**)&attrs);
>>+ if (res != S_OK) {
>>+ av_log(avctx, AV_LOG_ERROR, "Could not get decklink attributes\n");
>>+ return -1;
>>+ }
>>+
>>+ res = attrs->GetFlag(BMDDeckLinkSupportsInputFormatDetection,
>>&auto_detect);
>>+ if (res != S_OK) {
>>+ av_log(avctx, AV_LOG_ERROR, "Attribute fetch failed\n");
>>+ return -1;
>>+ }
>>+
>>+ return (auto_detect) ? 1 : 0;
>>+}
>>+
>> int ff_decklink_list_formats(AVFormatContext *avctx, decklink_direction_t
>> direction)
>> {
>> struct decklink_cctx *cctx = (struct decklink_cctx *) avctx->priv_data;
>>@@ -219,6 +326,9 @@ int ff_decklink_list_formats(AVFormatContext *avctx,
>>decklink_direction_t direct
>>
>> av_log(avctx, AV_LOG_INFO, "Supported formats for '%s':\n",
>> avctx->filename);
>>+ if (ff_decklink_device_autodetect(avctx)) {
>>+ av_log(avctx, AV_LOG_INFO, "\t-1\tAuto detection supported\n");
>>+ }
>> while (itermode->Next(&mode) == S_OK) {
>> BMDTimeValue tb_num, tb_den;
>> mode->GetFrameRate(&tb_num, &tb_den);
>>diff --git a/libavdevice/decklink_common.h b/libavdevice/decklink_common.h
>>index dff4fc1..cbe8de2 100644
>>--- a/libavdevice/decklink_common.h
>>+++ b/libavdevice/decklink_common.h
>>@@ -84,6 +84,8 @@ struct decklink_ctx {
>> sem_t semaphore;
>>
>> int channels;
>>+ int mode_num;
>>+ int auto_detect;
>> };
>>
>> typedef enum { DIRECTION_IN, DIRECTION_OUT} decklink_direction_t;
>>@@ -105,5 +107,8 @@ int ff_decklink_set_format(AVFormatContext *avctx, int
>>width, int height, int tb
>> int ff_decklink_set_format(AVFormatContext *avctx, decklink_direction_t
>> direction, int num);
>> int ff_decklink_list_devices(AVFormatContext *avctx);
>> int ff_decklink_list_formats(AVFormatContext *avctx, decklink_direction_t
>> direction = DIRECTION_OUT);
>>+int ff_decklink_device_autodetect(AVFormatContext *avctx);
>>+int ff_decklink_mode_to_ffmpeg(AVFormatContext *avctx, decklink_direction_t
>>direction, IDeckLinkDisplayMode **mode);
>>+long ff_decklink_mode_to_bm(AVFormatContext *avctx, decklink_direction_t
>>direction, int ffmpeg_mode, IDeckLinkDisplayMode **mode);
>>
>> #endif /* AVDEVICE_DECKLINK_COMMON_H */
>>diff --git a/libavdevice/decklink_common_c.h b/libavdevice/decklink_common_c.h
>>index 2b5d92f..0d365be 100644
>>--- a/libavdevice/decklink_common_c.h
>>+++ b/libavdevice/decklink_common_c.h
>>@@ -34,6 +34,7 @@ struct decklink_cctx {
>> double preroll;
>> int v210;
>> int audio_channels;
>>+ int autodetect_delay;
>> };
>>
>> #endif /* AVDEVICE_DECKLINK_COMMON_C_H */
>>diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp
>>index 1c305f3..552edc2 100644
>>--- a/libavdevice/decklink_dec.cpp
>>+++ b/libavdevice/decklink_dec.cpp
>>@@ -1,5 +1,5 @@
>> /*
>>- * Blackmagic DeckLink output
>>+ * Blackmagic DeckLink input
>> * Copyright (c) 2013-2014 Luca Barbato, Deti Fliegl
>> *
>> * This file is part of FFmpeg.
>>@@ -244,6 +244,12 @@ HRESULT decklink_input_callback::VideoInputFrameArrived(
>> BMDTimeValue frameTime;
>> BMDTimeValue frameDuration;
>>
>>+ /* if we don't have video, we are in the autodetect phase. skip
>>everything and let
>>+ * autodetect do its magic */
>>+ if (!ctx->video) {
>>+ return S_OK;
>>+ }
>>+
>> ctx->frameCount++;
>>
>> // Handle Video Frame
>>@@ -393,6 +399,14 @@ HRESULT decklink_input_callback::VideoInputFormatChanged(
>> BMDVideoInputFormatChangedEvents events, IDeckLinkDisplayMode *mode,
>> BMDDetectedVideoInputFormatFlags)
>> {
>>+
>>+ /* undo all the autodetect stuff so we can move on with life */
>>+ ctx->dli->PauseStreams();
>>+ ctx->dli->FlushStreams();
>>+
>>+ ctx->mode_num = ff_decklink_mode_to_ffmpeg(avctx, DIRECTION_IN, &mode);
>>+ ctx->video = 1;
>>+
>> return S_OK;
>> }
>>
>>@@ -435,14 +449,14 @@ av_cold int ff_decklink_read_header(AVFormatContext
>>*avctx)
>> {
>> struct decklink_cctx *cctx = (struct decklink_cctx *) avctx->priv_data;
>> struct decklink_ctx *ctx;
>>- IDeckLinkDisplayModeIterator *itermode;
>> IDeckLinkIterator *iter;
>> IDeckLink *dl = NULL;
>> AVStream *st;
>> HRESULT result;
>> char fname[1024];
>> char *tmp;
>>- int mode_num = 0;
>>+ int auto_detect = 0;
>>+ unsigned int autodetect_delay = cctx->autodetect_delay;
>>
>> ctx = (struct decklink_ctx *) av_mallocz(sizeof(struct decklink_ctx));
>> if (!ctx)
>>@@ -486,7 +500,7 @@ av_cold int ff_decklink_read_header(AVFormatContext
>>*avctx)
>> strcpy (fname, avctx->filename);
>> tmp=strchr (fname, '@');
>> if (tmp != NULL) {
>>- mode_num = atoi (tmp+1);
>>+ ctx->mode_num = atoi (tmp+1);
>> *tmp = 0;
>> }
>>
>>@@ -510,34 +524,74 @@ av_cold int ff_decklink_read_header(AVFormatContext
>>*avctx)
>>
>> /* Get input device. */
>> if (ctx->dl->QueryInterface(IID_IDeckLinkInput, (void **) &ctx->dli) !=
>> S_OK) {
>>- av_log(avctx, AV_LOG_ERROR, "Could not open output device from
>>'%s'\n",
>>+ av_log(avctx, AV_LOG_ERROR, "Could not open input device from
>>'%s'\n",
>> avctx->filename);
>> ctx->dl->Release();
>> return AVERROR(EIO);
>> }
>>
>>+ auto_detect = ff_decklink_device_autodetect(avctx);
>>+
>> /* List supported formats. */
>>- if (ctx->list_formats) {
>>+ if (ctx->list_formats || (ctx->mode_num <= 0 && !auto_detect)) {
>> ff_decklink_list_formats(avctx, DIRECTION_IN);
>> ctx->dli->Release();
>> ctx->dl->Release();
>> return AVERROR_EXIT;
>> }
>>
>>- if (ctx->dli->GetDisplayModeIterator(&itermode) != S_OK) {
>>- av_log(avctx, AV_LOG_ERROR, "Could not get Display Mode Iterator\n");
>>- ctx->dl->Release();
>>- return AVERROR(EIO);
>>- }
>>+ if (ctx->mode_num <= 0 && auto_detect) {
>>+ /* the user is wanting to auto detect the mode. we need to fake out
>>the api and not start ffmpeg fully in this mode!*/
>>+ ctx->auto_detect = 1;
>>+ ctx->mode_num = 1; /* it is assumed that there is at least one mode
>>supported on a decklink card. */
>>+
>>+ if (ff_decklink_set_format(avctx, DIRECTION_IN, ctx->mode_num) < 0) {
>>+ av_log(avctx, AV_LOG_ERROR, "Could not set mode %d\n",
>>ctx->mode_num);
>>+ goto error;
>>+ }
>>
>>- if (mode_num > 0) {
>>- if (ff_decklink_set_format(avctx, DIRECTION_IN, mode_num) < 0) {
>>- av_log(avctx, AV_LOG_ERROR, "Could not set mode %d for %s\n",
>>mode_num, fname);
>>+ ctx->bmd_mode = ff_decklink_mode_to_bm(avctx, DIRECTION_IN,
>>ctx->mode_num, NULL);
>>+ result = ctx->dli->EnableVideoInput(ctx->bmd_mode,
>>+ cctx->v210 ? bmdFormat10BitYUV :
>>bmdFormat8BitYUV,
>>+ bmdVideoInputFlagDefault |
>>bmdVideoInputEnableFormatDetection);
>>+ if (result != S_OK) {
>>+ av_log(avctx, AV_LOG_ERROR, "Could not enable video in the
>>pre-startup autodectect mode\n");
>> goto error;
>> }
>>+
>>+ result = ctx->dli->EnableAudioInput(bmdAudioSampleRate48kHz,
>>bmdAudioSampleType16bitInteger, cctx->audio_channels);
>>+ if (result != S_OK) {
>>+ av_log(avctx, AV_LOG_ERROR, "Could not enable audio in the
>>pre-startup autodetect mode\n");
>>+ goto error;
>>+ }
>>+
>>+ result = decklink_start_input(avctx);
>>+ if (result != S_OK) {
>>+ av_log(avctx, AV_LOG_ERROR, "Could not start input in the
>>pre-startup autodetect mode\n");
>>+ goto error;
>>+ }
>>+
>>+ /* we need to give the auto detect code some time to figure out what
>>mode we are really in */
>>+ autodetect_delay = cctx->autodetect_delay;
>>+ while (!ctx->video) {
>>+ if (autodetect_delay--) {
>>+ /* this could indicate we are in the right mode. let's
>>assume so */
>>+ break;
>>+ }
>>+ /* sleep for 1 second */
>>+ av_usleep(100000);
>>+ }
>> }
>>
>>- itermode->Release();
>>+ /* regardless as to if we did autodetect or not, we should now be in a
>>position to
>>+ * continue on as before with all the right setup to ensure we get the
>>right mode */
>>+ ctx->video = 1;
>>+ if (ctx->mode_num > 0) {
>>+ if (ff_decklink_set_format(avctx, DIRECTION_IN, ctx->mode_num) < 0) {
>>+ av_log(avctx, AV_LOG_ERROR, "Could not set mode %d for %s\n",
>>ctx->mode_num, fname);
>>+ goto error;
>>+ }
>>+ }
>>
>> /* Setup streams. */
>> st = avformat_new_stream(avctx, NULL);
>>@@ -618,6 +672,7 @@ av_cold int ff_decklink_read_header(AVFormatContext
>>*avctx)
>>
>> return 0;
>>
>>+
>> error:
>>
>> ctx->dli->Release();
>>diff --git a/libavdevice/decklink_dec_c.c b/libavdevice/decklink_dec_c.c
>>index 40c21a7..3f83f8f 100644
>>--- a/libavdevice/decklink_dec_c.c
>>+++ b/libavdevice/decklink_dec_c.c
>>@@ -36,6 +36,7 @@ static const AVOption options[] = {
>> { "standard", NULL, 0,
>> AV_OPT_TYPE_CONST, { .i64 = 0x7fff9fffeLL}, 0, 0, DEC, "teletext_lines"},
>> { "all", NULL, 0,
>> AV_OPT_TYPE_CONST, { .i64 = 0x7ffffffffLL}, 0, 0, DEC, "teletext_lines"},
>> { "channels", "number of audio channels", OFFSET(audio_channels),
>> AV_OPT_TYPE_INT , { .i64 = 2 }, 2, 16, DEC },
>>+ { "autodetect_delay", "number of seconds to wait for autodetect to
>>complete", OFFSET(autodetect_delay), AV_OPT_TYPE_INT , { .i64 = 5 }, 1, 30,
>>DEC },
>> { NULL },
>> };
>>
>>--
>>2.7.4
>>
>>
>>
>>
>>On 5/12/16, 3:10 PM, "ffmpeg-devel on behalf of Felt, Patrick"
>><[email protected] on behalf of [email protected]>
>>wrote:
>>
>>>Ah… I see a bug. I should either be setting ctx->video in the if block or
>>>I should be breaking instead of continuing. Good catch!
>>>
>>>
>>>On 5/12/16, 1:32 PM, "ffmpeg-devel on behalf of Matthias Hunstock"
>>><[email protected] on behalf of [email protected]> wrote:
>>>
>>>>Am 12.05.2016 um 19:16 schrieb Felt, Patrick:
>>>>> + while (!ctx->video) {
>>>>> + if (autodetect_delay--) {
>>>>> + /* this could indicate we are in the right mode. let's
>>>>> assume so */
>>>>> + continue;
>>>>> + }
>>>>> + sleep(1);
>>>>> + }
>>>>
>>>>I don't get it. How does this loop sleep for autodetect_delay seconds? I
>>>>read it like "spin-loop for autodetect_delay times and then probe
>>>>ctx->video each second, possibly forever".
>>>>
>>>>
>>>>
>>>>_______________________________________________
>>>>ffmpeg-devel mailing list
>>>>[email protected]
>>>>http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>>>
>>>_______________________________________________
>>>ffmpeg-devel mailing list
>>>[email protected]
>>>http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>>
>>_______________________________________________
>>ffmpeg-devel mailing list
>>[email protected]
>>http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
>_______________________________________________
>ffmpeg-devel mailing list
>[email protected]
>http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
_______________________________________________
ffmpeg-devel mailing list
[email protected]
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel