> -----Original Message----- > From: ffmpeg-devel [mailto:ffmpeg-devel-boun...@ffmpeg.org] On Behalf > Of Mark Thompson > Sent: Wednesday, November 14, 2018 07:44 > To: ffmpeg-devel@ffmpeg.org > Subject: [FFmpeg-devel] [PATCH v2] ffmpeg: Add option to force a specific > decode format > > Fixes #7519. > --- > doc/ffmpeg.texi | 13 ++++++++++++ > fftools/ffmpeg.c | 10 ++++++++++ > fftools/ffmpeg.h | 4 ++++ > fftools/ffmpeg_opt.c | 47 > ++++++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 74 insertions(+) > > diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi > index 3717f22d42..d127bc0f0d 100644 > --- a/doc/ffmpeg.texi > +++ b/doc/ffmpeg.texi > @@ -920,6 +920,19 @@ would be more efficient. > When doing stream copy, copy also non-key frames found at the > beginning. > > +@item -decode_format[:@var{stream_specifier}] > @var{pixfmt}[,@var{pixfmt}...] (@emph{input,per-stream}) > +Set the possible output formats to be used by the decoder for this stream. > +If the decoder does not natively support any format in the given list for > +the input stream then decoding will fail rather than continuing with a > +different format. > + > +In general this should not be set - the decoder will select an output > +format based on the input stream parameters and available components, > and > +that will be automatically converted to whatever the output requires. It > +may be useful to force a hardware decoder supporting output in multiple > +different memory types to pick a desired one, or to ensure that a hardware > +decoder is used when software fallback is also available. > + > @item -init_hw_device > @var{type}[=@var{name}][:@var{device}[,@var{key=value}...]] > Initialise a new hardware device of type @var{type} called @var{name}, > using the > given device parameters. > diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c > index 38c21e944a..c651c8d3a8 100644 > --- a/fftools/ffmpeg.c > +++ b/fftools/ffmpeg.c > @@ -598,6 +598,7 @@ static void ffmpeg_cleanup(int ret) > avsubtitle_free(&ist->prev_sub.subtitle); > av_frame_free(&ist->sub2video.frame); > av_freep(&ist->filters); > + av_freep(&ist->decode_formats); > av_freep(&ist->hwaccel_device); > av_freep(&ist->dts_buffer); > > @@ -2800,6 +2801,15 @@ static enum AVPixelFormat > get_format(AVCodecContext *s, const enum AVPixelFormat > const AVCodecHWConfig *config = NULL; > int i; > > + if (ist->decode_formats) { > + for (i = 0; ist->decode_formats[i] != AV_PIX_FMT_NONE; i++) { > + if (ist->decode_formats[i] == *p) > + break; > + } > + if (ist->decode_formats[i] != *p) > + continue; > + } > + > if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) > break; > > diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h > index eb1eaf6363..b06fd18b1c 100644 > --- a/fftools/ffmpeg.h > +++ b/fftools/ffmpeg.h > @@ -125,6 +125,8 @@ typedef struct OptionsContext { > int nb_ts_scale; > SpecifierOpt *dump_attachment; > int nb_dump_attachment; > + SpecifierOpt *decode_formats; > + int nb_decode_formats; > SpecifierOpt *hwaccels; > int nb_hwaccels; > SpecifierOpt *hwaccel_devices; > @@ -334,6 +336,8 @@ typedef struct InputStream { > int top_field_first; > int guess_layout_max; > > + enum AVPixelFormat *decode_formats; > + > int autorotate; > > int fix_sub_duration; > diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c > index d4851a2cd8..63bb05053b 100644 > --- a/fftools/ffmpeg_opt.c > +++ b/fftools/ffmpeg_opt.c > @@ -701,6 +701,7 @@ static void add_input_streams(OptionsContext *o, > AVFormatContext *ic) > AVStream *st = ic->streams[i]; > AVCodecParameters *par = st->codecpar; > InputStream *ist = av_mallocz(sizeof(*ist)); > + char *decode_formats = NULL; > char *framerate = NULL, *hwaccel_device = NULL; > const char *hwaccel = NULL; > char *hwaccel_output_format = NULL; > @@ -797,6 +798,49 @@ static void add_input_streams(OptionsContext *o, > AVFormatContext *ic) > ist->top_field_first = -1; > MATCH_PER_STREAM_OPT(top_field_first, i, ist->top_field_first, > ic, > st); > > + MATCH_PER_STREAM_OPT(decode_formats, str, decode_formats, ic, > st); > + if (decode_formats) { > + const char *p, *q; > + int i, nb_formats; > + char tmp[32]; > + > + nb_formats = 0; > + for (p = decode_formats; p; p = strchr(p + 1, ',')) > + ++nb_formats; > + > + ist->decode_formats = > + av_malloc_array(nb_formats + 1, > sizeof(*ist->decode_formats)); > + if (!ist->decode_formats) > + exit_program(1); > + > + p = decode_formats; > + for (i = 0; i < nb_formats; i++) { > + q = strchr(p, ','); > + if (!q) { > + ist->decode_formats[i] = av_get_pix_fmt(p); > + if (ist->decode_formats[i] == AV_PIX_FMT_NONE) > + break; > + continue; > + } > + if (q - p > sizeof(tmp) - 1) > + break; > + memcpy(tmp, p, q - p); > + tmp[q - p] = 0; > + ist->decode_formats[i] = av_get_pix_fmt(tmp); > + if (ist->decode_formats[i] == AV_PIX_FMT_NONE) > + break; > + p = q + 1; > + } > + if (i < nb_formats) { > + av_log(NULL, AV_LOG_FATAL, > + "Unrecognised decode format: %s.\n", p); > + exit_program(1); > + } > + ist->decode_formats[nb_formats] = AV_PIX_FMT_NONE; > + } else { > + ist->decode_formats = NULL; > + } > + > MATCH_PER_STREAM_OPT(hwaccels, str, hwaccel, ic, st); > if (hwaccel) { > // The NVDEC hwaccels use a CUDA device, so remap the name > here. > @@ -3583,6 +3627,9 @@ const OptionDef options[] = { > "audio bitrate (please use -b:a)", "bitrate" }, > { "b", OPT_VIDEO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, > { .func_arg = opt_bitrate }, > "video bitrate (please use -b:v)", "bitrate" }, > + { "decode_format", OPT_VIDEO | OPT_STRING | HAS_ARG | > OPT_EXPERT | > + OPT_SPEC | OPT_INPUT, > { .off = > OFFSET(decode_formats) }, > + "set output format(s) to be used by decoder, fail if none of these > formats are available", "format" }, > { "hwaccel", OPT_VIDEO | OPT_STRING | HAS_ARG | OPT_EXPERT | > OPT_SPEC | OPT_INPUT, > { .off = > OFFSET(hwaccels) }, > "use HW accelerated decoding", "hwaccel name" }, > -- > 2.19.1 >
Is there any other conditions which will cause the hwaccel failed and fallback to software path? Like profile was not supported by hardware? I applied the patch and tested some cases, like yuv422 VAAPI decoding (currently not supported), HEVC decoding with unsupported profile. It reports an error like "hwaccel initialization returned error", and continue to decode and produce less frames than expected. (which I thought fallback still happened). Thanks, - Linjie _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel