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" 
<ffmpeg-devel-boun...@ffmpeg.org on behalf of patrick.f...@echostar.com> 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" 
><ffmpeg-devel-boun...@ffmpeg.org on behalf of patrick.f...@echostar.com> 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" 
>><ffmpeg-devel-boun...@ffmpeg.org on behalf of a...@fem.tu-ilmenau.de> 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
>>>ffmpeg-devel@ffmpeg.org
>>>http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>>
>>_______________________________________________
>>ffmpeg-devel mailing list
>>ffmpeg-devel@ffmpeg.org
>>http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
>_______________________________________________
>ffmpeg-devel mailing list
>ffmpeg-devel@ffmpeg.org
>http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Reply via email to