ffmpeg: Support setting the hardware device to use when filtering

This only supports one device globally, but more can be used by
passing them with input streams in hw_frames_ctx or by deriving new
devices inside a filter graph with hwmap.

(cherry picked from commit e669db7610)
pull/262/head
Mark Thompson 8 years ago
parent 3882063174
commit 7ce47090ce
  1. 11
      doc/ffmpeg.texi
  2. 1
      ffmpeg.h
  3. 10
      ffmpeg_filter.c
  4. 17
      ffmpeg_opt.c

@ -765,6 +765,17 @@ deriving it from the existing device with the name @var{source}.
@item -init_hw_device list @item -init_hw_device list
List all hardware device types supported in this build of ffmpeg. List all hardware device types supported in this build of ffmpeg.
@item -filter_hw_device @var{name}
Pass the hardware device called @var{name} to all filters in any filter graph.
This can be used to set the device to upload to with the @code{hwupload} filter,
or the device to map to with the @code{hwmap} filter. Other filters may also
make use of this parameter when they require a hardware device. Note that this
is typically only required when the input is not already in hardware frames -
when it is, filters will derive the device they require from the context of the
frames they receive as input.
This is a global setting, so all filters will receive the same device.
@item -hwaccel[:@var{stream_specifier}] @var{hwaccel} (@emph{input,per-stream}) @item -hwaccel[:@var{stream_specifier}] @var{hwaccel} (@emph{input,per-stream})
Use hardware acceleration to decode the matching stream(s). The allowed values Use hardware acceleration to decode the matching stream(s). The allowed values
of @var{hwaccel} are: of @var{hwaccel} are:

@ -628,6 +628,7 @@ extern AVBufferRef *hw_device_ctx;
#if CONFIG_QSV #if CONFIG_QSV
extern char *qsv_device; extern char *qsv_device;
#endif #endif
extern HWDevice *filter_hw_device;
void term_init(void); void term_init(void);

@ -1046,9 +1046,15 @@ int configure_filtergraph(FilterGraph *fg)
if ((ret = avfilter_graph_parse2(fg->graph, graph_desc, &inputs, &outputs)) < 0) if ((ret = avfilter_graph_parse2(fg->graph, graph_desc, &inputs, &outputs)) < 0)
goto fail; goto fail;
if (hw_device_ctx) { if (filter_hw_device || hw_device_ctx) {
AVBufferRef *device = filter_hw_device ? filter_hw_device->device_ref
: hw_device_ctx;
for (i = 0; i < fg->graph->nb_filters; i++) { for (i = 0; i < fg->graph->nb_filters; i++) {
fg->graph->filters[i]->hw_device_ctx = av_buffer_ref(hw_device_ctx); fg->graph->filters[i]->hw_device_ctx = av_buffer_ref(device);
if (!fg->graph->filters[i]->hw_device_ctx) {
ret = AVERROR(ENOMEM);
goto fail;
}
} }
} }

@ -98,6 +98,7 @@ const HWAccel hwaccels[] = {
}; };
int hwaccel_lax_profile_check = 0; int hwaccel_lax_profile_check = 0;
AVBufferRef *hw_device_ctx; AVBufferRef *hw_device_ctx;
HWDevice *filter_hw_device;
char *vstats_filename; char *vstats_filename;
char *sdp_filename; char *sdp_filename;
@ -495,6 +496,20 @@ static int opt_init_hw_device(void *optctx, const char *opt, const char *arg)
} }
} }
static int opt_filter_hw_device(void *optctx, const char *opt, const char *arg)
{
if (filter_hw_device) {
av_log(NULL, AV_LOG_ERROR, "Only one filter device can be used.\n");
return AVERROR(EINVAL);
}
filter_hw_device = hw_device_get_by_name(arg);
if (!filter_hw_device) {
av_log(NULL, AV_LOG_ERROR, "Invalid filter device %s.\n", arg);
return AVERROR(EINVAL);
}
return 0;
}
/** /**
* Parse a metadata specifier passed as 'arg' parameter. * Parse a metadata specifier passed as 'arg' parameter.
* @param arg metadata string to parse * @param arg metadata string to parse
@ -3708,6 +3723,8 @@ const OptionDef options[] = {
{ "init_hw_device", HAS_ARG | OPT_EXPERT, { .func_arg = opt_init_hw_device }, { "init_hw_device", HAS_ARG | OPT_EXPERT, { .func_arg = opt_init_hw_device },
"initialise hardware device", "args" }, "initialise hardware device", "args" },
{ "filter_hw_device", HAS_ARG | OPT_EXPERT, { .func_arg = opt_filter_hw_device },
"set hardware device used when filtering", "device" },
{ NULL, }, { NULL, },
}; };

Loading…
Cancel
Save