[FFmpeg-devel] [PATCH 2/2] fftools/ffmpeg: supply hw_device_ctx to filters before initializing them
Anton Khirnov
anton at khirnov.net
Fri Mar 17 14:42:30 EET 2023
This is more correct, but was not possible before the recently-added
filtergraph parsing API.
Also, only pass hw devices to filters that are flagged as capable of
using them.
---
fftools/ffmpeg.h | 7 ++++++-
fftools/ffmpeg_filter.c | 24 ++++++++++++++++++------
fftools/ffmpeg_hw.c | 21 +++++----------------
3 files changed, 29 insertions(+), 23 deletions(-)
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 4d4433f5bad..2020770312f 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -802,7 +802,12 @@ void hw_device_free_all(void);
int hw_device_setup_for_decode(InputStream *ist);
int hw_device_setup_for_encode(OutputStream *ost);
-int hw_device_setup_for_filter(FilterGraph *fg);
+/**
+ * Get a hardware device to be used with this filtergraph.
+ * The returned reference is owned by the callee, the caller
+ * must ref it explicitly for long-term use.
+ */
+AVBufferRef *hw_device_for_filter(FilterGraph *fg);
int hwaccel_decode_init(AVCodecContext *avctx);
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 3504a3cc0ae..8f924a74538 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -440,7 +440,8 @@ static int graph_opts_apply(AVFilterGraphSegment *seg)
}
static int graph_parse(AVFilterGraph *graph, const char *desc,
- AVFilterInOut **inputs, AVFilterInOut **outputs)
+ AVFilterInOut **inputs, AVFilterInOut **outputs,
+ AVBufferRef *hw_device)
{
AVFilterGraphSegment *seg;
int ret;
@@ -453,6 +454,18 @@ static int graph_parse(AVFilterGraph *graph, const char *desc,
if (ret < 0)
goto fail;
+ if (hw_device) {
+ for (int i = 0; i < graph->nb_filters; i++) {
+ AVFilterContext *f = graph->filters[i];
+
+ if (!(f->filter->flags & AVFILTER_FLAG_HWDEVICE))
+ continue;
+ f->hw_device_ctx = av_buffer_ref(hw_device);
+ if (!f->hw_device_ctx)
+ return AVERROR(ENOMEM);
+ }
+ }
+
ret = graph_opts_apply(seg);
if (ret < 0)
goto fail;
@@ -477,7 +490,7 @@ int init_complex_filtergraph(FilterGraph *fg)
return AVERROR(ENOMEM);
graph->nb_threads = 1;
- ret = graph_parse(graph, fg->graph_desc, &inputs, &outputs);
+ ret = graph_parse(graph, fg->graph_desc, &inputs, &outputs, NULL);
if (ret < 0)
goto fail;
@@ -1111,6 +1124,7 @@ static int graph_is_meta(AVFilterGraph *graph)
int configure_filtergraph(FilterGraph *fg)
{
+ AVBufferRef *hw_device;
AVFilterInOut *inputs, *outputs, *cur;
int ret, i, simple = filtergraph_is_simple(fg);
const char *graph_desc = simple ? fg->outputs[0]->ost->avfilter :
@@ -1154,11 +1168,9 @@ int configure_filtergraph(FilterGraph *fg)
fg->graph->nb_threads = filter_complex_nbthreads;
}
- if ((ret = graph_parse(fg->graph, graph_desc, &inputs, &outputs)) < 0)
- goto fail;
+ hw_device = hw_device_for_filter(fg);
- ret = hw_device_setup_for_filter(fg);
- if (ret < 0)
+ if ((ret = graph_parse(fg->graph, graph_desc, &inputs, &outputs, hw_device)) < 0)
goto fail;
if (simple && (!inputs || inputs->next || !outputs || outputs->next)) {
diff --git a/fftools/ffmpeg_hw.c b/fftools/ffmpeg_hw.c
index 88fa7824701..a3351d98b59 100644
--- a/fftools/ffmpeg_hw.c
+++ b/fftools/ffmpeg_hw.c
@@ -548,17 +548,14 @@ int hwaccel_decode_init(AVCodecContext *avctx)
return 0;
}
-int hw_device_setup_for_filter(FilterGraph *fg)
+AVBufferRef *hw_device_for_filter(FilterGraph *fg)
{
- HWDevice *dev;
- int i;
-
// Pick the last hardware device if the user doesn't pick the device for
// filters explicitly with the filter_hw_device option.
if (filter_hw_device)
- dev = filter_hw_device;
+ return filter_hw_device->device_ref;
else if (nb_hw_devices > 0) {
- dev = hw_devices[nb_hw_devices - 1];
+ HWDevice *dev = hw_devices[nb_hw_devices - 1];
if (nb_hw_devices > 1)
av_log(NULL, AV_LOG_WARNING, "There are %d hardware devices. device "
@@ -567,17 +564,9 @@ int hw_device_setup_for_filter(FilterGraph *fg)
"%s is not usable for filters.\n",
nb_hw_devices, dev->name,
av_hwdevice_get_type_name(dev->type), dev->name);
- } else
- dev = NULL;
- if (dev) {
- for (i = 0; i < fg->graph->nb_filters; i++) {
- fg->graph->filters[i]->hw_device_ctx =
- av_buffer_ref(dev->device_ref);
- if (!fg->graph->filters[i]->hw_device_ctx)
- return AVERROR(ENOMEM);
- }
+ return dev->device_ref;
}
- return 0;
+ return NULL;
}
--
2.39.1
More information about the ffmpeg-devel
mailing list