diff --git a/doc/filters.texi b/doc/filters.texi index 4a5412c91d..dd7ee1394a 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -26531,6 +26531,22 @@ Horizontal offset of the captured video. @item offset_y Vertical offset of the captured video. +@item output_fmt +Desired filter output format. +Defaults to 8 Bit BGRA. + +It accepts the following values: +@table @samp +@item auto +Passes all supported output formats to DDA and returns what DDA decides to use. +@item 8bit +@item bgra +8 Bit formats always work, and DDA will convert to them if neccesary. +@item 10bit +@item x2bgr10 +Filter initialization will fail if 10 bit format is requested but unavailable. +@end table + @end table @subsection Examples diff --git a/libavfilter/vsrc_ddagrab.c b/libavfilter/vsrc_ddagrab.c index 2f33a40f6f..5300d46fc1 100644 --- a/libavfilter/vsrc_ddagrab.c +++ b/libavfilter/vsrc_ddagrab.c @@ -97,6 +97,7 @@ typedef struct DdagrabContext { int height; int offset_x; int offset_y; + int out_fmt; } DdagrabContext; #define OFFSET(x) offsetof(DdagrabContext, x) @@ -108,6 +109,12 @@ static const AVOption ddagrab_options[] = { { "video_size", "set video frame size", OFFSET(width), AV_OPT_TYPE_IMAGE_SIZE, { .str = NULL }, 0, 0, FLAGS }, { "offset_x", "capture area x offset", OFFSET(offset_x), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, FLAGS }, { "offset_y", "capture area y offset", OFFSET(offset_y), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, FLAGS }, + { "output_fmt", "desired output format", OFFSET(out_fmt), AV_OPT_TYPE_INT, { .i64 = DXGI_FORMAT_B8G8R8A8_UNORM }, 0, INT_MAX, FLAGS, "output_fmt" }, + { "auto", "let dda pick its preferred format", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, INT_MAX, FLAGS, "output_fmt" }, + { "8bit", "only output default 8 Bit format", 0, AV_OPT_TYPE_CONST, { .i64 = DXGI_FORMAT_B8G8R8A8_UNORM }, 0, INT_MAX, FLAGS, "output_fmt" }, + { "bgra", "only output 8 Bit BGRA", 0, AV_OPT_TYPE_CONST, { .i64 = DXGI_FORMAT_B8G8R8A8_UNORM }, 0, INT_MAX, FLAGS, "output_fmt" }, + { "10bit", "only output default 10 Bit format", 0, AV_OPT_TYPE_CONST, { .i64 = DXGI_FORMAT_R10G10B10A2_UNORM }, 0, INT_MAX, FLAGS, "output_fmt" }, + { "x2bgr10", "only output 10 Bit X2BGR10", 0, AV_OPT_TYPE_CONST, { .i64 = DXGI_FORMAT_R10G10B10A2_UNORM }, 0, INT_MAX, FLAGS, "output_fmt" }, { NULL } }; @@ -208,6 +215,16 @@ static av_cold int init_dxgi_dda(AVFilterContext *avctx) DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM }; + int nb_formats = FF_ARRAY_ELEMS(formats); + + if(dda->out_fmt == DXGI_FORMAT_B8G8R8A8_UNORM) { + formats[0] = DXGI_FORMAT_B8G8R8A8_UNORM; + nb_formats = 1; + } else if (dda->out_fmt) { + formats[0] = dda->out_fmt; + formats[1] = DXGI_FORMAT_B8G8R8A8_UNORM; + nb_formats = 2; + } IDXGIOutput_Release(dxgi_output); dxgi_output = NULL; @@ -219,7 +236,7 @@ static av_cold int init_dxgi_dda(AVFilterContext *avctx) hr = IDXGIOutput5_DuplicateOutput1(dxgi_output5, (IUnknown*)dda->device_hwctx->device, 0, - FF_ARRAY_ELEMS(formats), + nb_formats, formats, &dda->dxgi_outdupl); IDXGIOutput5_Release(dxgi_output5); @@ -242,6 +259,11 @@ static av_cold int init_dxgi_dda(AVFilterContext *avctx) #else { #endif + if (dda->out_fmt && dda->out_fmt != DXGI_FORMAT_B8G8R8A8_UNORM) { + av_log(avctx, AV_LOG_ERROR, "Only 8 bit output supported with legacy API\n"); + return AVERROR(ENOTSUP); + } + hr = IDXGIOutput_QueryInterface(dxgi_output, &IID_IDXGIOutput1, (void**)&dxgi_output1); IDXGIOutput_Release(dxgi_output); dxgi_output = NULL; @@ -704,6 +726,11 @@ static int ddagrab_config_props(AVFilterLink *outlink) if (ret < 0) return ret; + if (dda->out_fmt && dda->raw_format != dda->out_fmt) { + av_log(avctx, AV_LOG_ERROR, "Requested output format unavailable.\n"); + return AVERROR(ENOTSUP); + } + dda->width -= FFMAX(dda->width - dda->raw_width + dda->offset_x, 0); dda->height -= FFMAX(dda->height - dda->raw_height + dda->offset_y, 0);