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