Signed-off-by: Michael Riedl <michael.ri...@nativewaves.com>
---
doc/indevs.texi | 16 ++++++++++++++++
libavdevice/decklink_common.h | 1 +
libavdevice/decklink_common_c.h | 7 +++++++
libavdevice/decklink_dec.cpp | 23 ++++++++++++++++++++++-
libavdevice/decklink_dec_c.c | 6 +++++-
5 files changed, 51 insertions(+), 2 deletions(-)
diff --git a/doc/indevs.texi b/doc/indevs.texi
index 734fc657523..cdf44a66382 100644
--- a/doc/indevs.texi
+++ b/doc/indevs.texi
@@ -396,6 +396,22 @@ Defaults to @samp{audio}.
@item draw_bars
If set to @samp{true}, color bars are drawn in the event of a signal loss.
Defaults to @samp{true}.
+This option is deprecated, please use the @code{signal_loss_action} option.
+
+@item signal_loss_action
+Sets the action to take in the event of a signal loss. Accepts one of the
+following values:
+
+@table @option
+@item 1, none
+Do nothing on signal loss. This usually results in black frames.
+@item 2, bars
+Draw color bars on signal loss. Only supported for 8-bit input signals.
+@item 3, repeat
+Repeat the last video frame on signal loss.
+@end table
+
+Defaults to @samp{bars}.
@item queue_size
Sets maximum input buffer size in bytes. If the buffering reaches this value,
diff --git a/libavdevice/decklink_common.h b/libavdevice/decklink_common.h
index c54a635876c..6b32dc2d09c 100644
--- a/libavdevice/decklink_common.h
+++ b/libavdevice/decklink_common.h
@@ -147,6 +147,7 @@ struct decklink_ctx {
DecklinkPtsSource video_pts_source;
int draw_bars;
BMDPixelFormat raw_format;
+ DecklinkSignalLossAction signal_loss_action;
int frames_preroll;
int frames_buffer;
diff --git a/libavdevice/decklink_common_c.h b/libavdevice/decklink_common_c.h
index 9c55d891494..53d2c583e7e 100644
--- a/libavdevice/decklink_common_c.h
+++ b/libavdevice/decklink_common_c.h
@@ -37,6 +37,12 @@ typedef enum DecklinkPtsSource {
PTS_SRC_NB
} DecklinkPtsSource;
+typedef enum DecklinkSignalLossAction {
+ SIGNAL_LOSS_NONE = 1,
+ SIGNAL_LOSS_REPEAT = 2,
+ SIGNAL_LOSS_BARS = 3
+} DecklinkSignalLossAction;
+
struct decklink_cctx {
const AVClass *cclass;
@@ -68,6 +74,7 @@ struct decklink_cctx {
int64_t timestamp_align;
int timing_offset;
int wait_for_tc;
+ DecklinkSignalLossAction signal_loss_action;
};
#endif /* AVDEVICE_DECKLINK_COMMON_C_H */
diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp
index 671573853ba..1c2d08ea9fc 100644
--- a/libavdevice/decklink_dec.cpp
+++ b/libavdevice/decklink_dec.cpp
@@ -593,6 +593,7 @@ private:
int no_video;
int64_t initial_video_pts;
int64_t initial_audio_pts;
+ IDeckLinkVideoInputFrame* last_video_frame;
};
decklink_input_callback::decklink_input_callback(AVFormatContext *_avctx) :
_refs(1)
@@ -602,10 +603,13 @@
decklink_input_callback::decklink_input_callback(AVFormatContext *_avctx) : _ref
ctx = (struct decklink_ctx *)cctx->ctx;
no_video = 0;
initial_audio_pts = initial_video_pts = AV_NOPTS_VALUE;
+ last_video_frame = nullptr;
}
decklink_input_callback::~decklink_input_callback()
{
+ if (last_video_frame)
+ last_video_frame->Release();
}
ULONG decklink_input_callback::AddRef(void)
@@ -773,7 +777,7 @@ HRESULT decklink_input_callback::VideoInputFrameArrived(
ctx->video_st->time_base.den);
if (videoFrame->GetFlags() & bmdFrameHasNoInputSource) {
- if (ctx->draw_bars && videoFrame->GetPixelFormat() ==
bmdFormat8BitYUV) {
+ if (ctx->signal_loss_action == SIGNAL_LOSS_BARS &&
videoFrame->GetPixelFormat() == bmdFormat8BitYUV) {
unsigned bars[8] = {
0xEA80EA80, 0xD292D210, 0xA910A9A5, 0x90229035,
0x6ADD6ACA, 0x51EF515A, 0x286D28EF, 0x10801080 };
@@ -785,6 +789,8 @@ HRESULT decklink_input_callback::VideoInputFrameArrived(
for (int x = 0; x < width; x += 2)
*p++ = bars[(x * 8) / width];
}
+ } else if (ctx->signal_loss_action == SIGNAL_LOSS_REPEAT) {
+ last_video_frame->GetBytes(&frameBytes);
}
if (!no_video) {
@@ -793,6 +799,12 @@ HRESULT decklink_input_callback::VideoInputFrameArrived(
}
no_video = 1;
} else {
+ if (ctx->signal_loss_action == SIGNAL_LOSS_REPEAT) {
+ if (last_video_frame)
+ last_video_frame->Release();
+ last_video_frame = videoFrame;
+ last_video_frame->AddRef();
+ }
if (no_video) {
av_log(avctx, AV_LOG_WARNING, "Frame received (#%lu) - Input
returned "
"- Frames dropped %u\n", ctx->frameCount,
++ctx->dropped);
@@ -1074,6 +1086,15 @@ av_cold int ff_decklink_read_header(AVFormatContext
*avctx)
ctx->audio_pts_source = cctx->audio_pts_source;
ctx->video_pts_source = cctx->video_pts_source;
ctx->draw_bars = cctx->draw_bars;
+ ctx->signal_loss_action = cctx->signal_loss_action;
+ if (!ctx->draw_bars && ctx->signal_loss_action == SIGNAL_LOSS_BARS) {
+ ctx->signal_loss_action = SIGNAL_LOSS_NONE;
+ av_log(avctx, AV_LOG_WARNING, "Setting signal_loss_action to none because
draw_bars is false\n");
+ }
+ if (!ctx->draw_bars && ctx->signal_loss_action != SIGNAL_LOSS_NONE) {
+ av_log(avctx, AV_LOG_ERROR, "options draw_bars and signal_loss_action are
mutually exclusive\n");
+ return AVERROR(EINVAL);
+ }
ctx->audio_depth = cctx->audio_depth;
if (cctx->raw_format > 0 && (unsigned int)cctx->raw_format <
FF_ARRAY_ELEMS(decklink_raw_format_map))
ctx->raw_format = decklink_raw_format_map[cctx->raw_format];
diff --git a/libavdevice/decklink_dec_c.c b/libavdevice/decklink_dec_c.c
index e211c9d3f4e..b8cdb7bd8e1 100644
--- a/libavdevice/decklink_dec_c.c
+++ b/libavdevice/decklink_dec_c.c
@@ -95,12 +95,16 @@ static const AVOption options[] = {
{ "reference", NULL, 0,
AV_OPT_TYPE_CONST, { .i64 = PTS_SRC_REFERENCE}, 0, 0, DEC, .unit = "pts_source"},
{ "wallclock", NULL, 0,
AV_OPT_TYPE_CONST, { .i64 = PTS_SRC_WALLCLOCK}, 0, 0, DEC, .unit = "pts_source"},
{ "abs_wallclock", NULL, 0,
AV_OPT_TYPE_CONST, { .i64 = PTS_SRC_ABS_WALLCLOCK}, 0, 0, DEC, .unit = "pts_source"},
- { "draw_bars", "draw bars on signal loss" , OFFSET(draw_bars),
AV_OPT_TYPE_BOOL, { .i64 = 1}, 0, 1, DEC },
+ { "draw_bars", "use option signal_loss_action instead" ,
OFFSET(draw_bars), AV_OPT_TYPE_BOOL, { .i64 = 1}, 0, 1, DEC | AV_OPT_FLAG_DEPRECATED },
{ "queue_size", "input queue buffer size", OFFSET(queue_size),
AV_OPT_TYPE_INT64, { .i64 = (1024 * 1024 * 1024)}, 0, INT64_MAX, DEC },
{ "audio_depth", "audio bitdepth (16 or 32)", OFFSET(audio_depth),
AV_OPT_TYPE_INT, { .i64 = 16}, 16, 32, DEC },
{ "decklink_copyts", "copy timestamps, do not remove the initial offset",
OFFSET(copyts), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, DEC },
{ "timestamp_align", "capture start time alignment (in seconds)",
OFFSET(timestamp_align), AV_OPT_TYPE_DURATION, { .i64 = 0 }, 0, INT_MAX, DEC },
{ "wait_for_tc", "drop frames till a frame with timecode is received. TC
format must be set", OFFSET(wait_for_tc), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, DEC },
+ { "signal_loss_action", "action on signal loss", OFFSET(signal_loss_action),
AV_OPT_TYPE_INT, { .i64 = SIGNAL_LOSS_BARS }, SIGNAL_LOSS_NONE, SIGNAL_LOSS_BARS, DEC, .unit =
"signal_loss_action" },
+ { "none", "do not do anything (usually leads to black frames)", 0,
AV_OPT_TYPE_CONST, { .i64 = SIGNAL_LOSS_NONE }, 0, 0, DEC, .unit = "signal_loss_action"},
+ { "bars", "draw color bars (only supported for 8-bit signals)", 0,
AV_OPT_TYPE_CONST, { .i64 = SIGNAL_LOSS_BARS }, 0, 0, DEC, .unit = "signal_loss_action"},
+ { "repeat", "repeat the last video frame", 0, AV_OPT_TYPE_CONST, { .i64 =
SIGNAL_LOSS_REPEAT }, 0, 0, DEC, .unit = "signal_loss_action"},
{ NULL },
};
--
2.43.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".