Message ID | e9ad0342-3656-6292-9120-4803203a9e50@jkqxz.net |
---|---|
State | New |
Headers | show |
> -----Original Message----- > From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@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
On 14/11/18 00:50, Fu, Linjie wrote: >> -----Original Message----- >> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@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? If this option is set then get_format will never choose a format not on the list you provide, so it shouldn't be able to use software decode unless a software format is on the list. > 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). Can you give an example? With -v debug there will be output saying exactly what happened in ff_get_format(). - Mark
> -----Original Message----- > From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On Behalf > Of Mark Thompson > Sent: Wednesday, November 14, 2018 09:11 > To: ffmpeg-devel@ffmpeg.org > Subject: Re: [FFmpeg-devel] [PATCH v2] ffmpeg: Add option to force a > specific decode format > > On 14/11/18 00:50, Fu, Linjie wrote: > >> -----Original Message----- > >> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@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? > > If this option is set then get_format will never choose a format not on the list > you provide, so it shouldn't be able to use software decode unless a > software format is on the list. > > > 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). > > Can you give an example? With -v debug there will be output saying exactly > what happened in ff_get_format(). > > - Mark Got information like this: [hevc @ 0x55b87457dbc0] Unknown HEVC profile: 0 [hevc @ 0x55b87457dbc0] Decoding SPS [hevc @ 0x55b87457dbc0] Unknown HEVC profile: 0 [hevc @ 0x55b87457dbc0] Decoding PPS [hevc @ 0x55b87457dbc0] Format vaapi_vld chosen by get_format(). [hevc @ 0x55b87457dbc0] Format vaapi_vld requires hwaccel initialisation. [hevc @ 0x55b87457dbc0] Codec hevc profile 0 not supported for hardware decode. [hevc @ 0x55b87457dbc0] Failed setup for format vaapi_vld: hwaccel initialisation returned error. [hevc @ 0x55b87457dbc0] Format vaapi_vld not usable, retrying get_format() without it. [hevc @ 0x55b87457dbc0] Error parsing NAL unit #3. cur_dts is invalid (this is harmless if it occurs once at the start per stream) [hevc @ 0x55b87458b7c0] nal_unit_type: 1(TRAIL_R), nuh_layer_id: 0, temporal_id: 0 [hevc @ 0x55b87458b7c0] Could not find ref with POC 0 See the attached report file for more details. Thanks, - Linjie
On 14/11/18 01:35, Fu, Linjie wrote: >> -----Original Message----- >> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On Behalf >> Of Mark Thompson >> Sent: Wednesday, November 14, 2018 09:11 >> To: ffmpeg-devel@ffmpeg.org >> Subject: Re: [FFmpeg-devel] [PATCH v2] ffmpeg: Add option to force a >> specific decode format >> >> On 14/11/18 00:50, Fu, Linjie wrote: >>>> -----Original Message----- >>>> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@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? >> >> If this option is set then get_format will never choose a format not on the list >> you provide, so it shouldn't be able to use software decode unless a >> software format is on the list. >> >>> 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). >> >> Can you give an example? With -v debug there will be output saying exactly >> what happened in ff_get_format(). >> >> - Mark > > > Got information like this: > > [hevc @ 0x55b87457dbc0] Unknown HEVC profile: 0 > [hevc @ 0x55b87457dbc0] Decoding SPS > [hevc @ 0x55b87457dbc0] Unknown HEVC profile: 0 > [hevc @ 0x55b87457dbc0] Decoding PPS > [hevc @ 0x55b87457dbc0] Format vaapi_vld chosen by get_format(). > [hevc @ 0x55b87457dbc0] Format vaapi_vld requires hwaccel initialisation. > [hevc @ 0x55b87457dbc0] Codec hevc profile 0 not supported for hardware decode. > [hevc @ 0x55b87457dbc0] Failed setup for format vaapi_vld: hwaccel initialisation returned error. > [hevc @ 0x55b87457dbc0] Format vaapi_vld not usable, retrying get_format() without it. > [hevc @ 0x55b87457dbc0] Error parsing NAL unit #3. > cur_dts is invalid (this is harmless if it occurs once at the start per stream) > [hevc @ 0x55b87458b7c0] nal_unit_type: 1(TRAIL_R), nuh_layer_id: 0, temporal_id: 0 > [hevc @ 0x55b87458b7c0] Could not find ref with POC 0 > > See the attached report file for more details. This is a decoder bug - get_format() is not correctly called again after it fails, and the decoder then uses the software pixfmt derived from the SPS on subsequent frames. (I did pretty much all of my testing with H.264, which does not have this problem.) - Mark
> -----Original Message----- > From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On Behalf > Of Mark Thompson > Sent: Thursday, November 15, 2018 05:48 > To: ffmpeg-devel@ffmpeg.org > Subject: Re: [FFmpeg-devel] [PATCH v2] ffmpeg: Add option to force a > specific decode format > > On 14/11/18 01:35, Fu, Linjie wrote: > >> -----Original Message----- > >> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On > Behalf > >> Of Mark Thompson > >> Sent: Wednesday, November 14, 2018 09:11 > >> To: ffmpeg-devel@ffmpeg.org > >> Subject: Re: [FFmpeg-devel] [PATCH v2] ffmpeg: Add option to force a > >> specific decode format > >> > >> On 14/11/18 00:50, Fu, Linjie wrote: > >>>> -----Original Message----- > >>>> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@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? > >> > >> If this option is set then get_format will never choose a format not on the > list > >> you provide, so it shouldn't be able to use software decode unless a > >> software format is on the list. > >> > >>> 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). > >> > >> Can you give an example? With -v debug there will be output saying > exactly > >> what happened in ff_get_format(). > >> > >> - Mark > > > > > > Got information like this: > > > > [hevc @ 0x55b87457dbc0] Unknown HEVC profile: 0 > > [hevc @ 0x55b87457dbc0] Decoding SPS > > [hevc @ 0x55b87457dbc0] Unknown HEVC profile: 0 > > [hevc @ 0x55b87457dbc0] Decoding PPS > > [hevc @ 0x55b87457dbc0] Format vaapi_vld chosen by get_format(). > > [hevc @ 0x55b87457dbc0] Format vaapi_vld requires hwaccel initialisation. > > [hevc @ 0x55b87457dbc0] Codec hevc profile 0 not supported for hardware > decode. > > [hevc @ 0x55b87457dbc0] Failed setup for format vaapi_vld: hwaccel > initialisation returned error. > > [hevc @ 0x55b87457dbc0] Format vaapi_vld not usable, retrying > get_format() without it. > > [hevc @ 0x55b87457dbc0] Error parsing NAL unit #3. > > cur_dts is invalid (this is harmless if it occurs once at the start per stream) > > [hevc @ 0x55b87458b7c0] nal_unit_type: 1(TRAIL_R), nuh_layer_id: 0, > temporal_id: 0 > > [hevc @ 0x55b87458b7c0] Could not find ref with POC 0 > > > > See the attached report file for more details. > > This is a decoder bug - get_format() is not correctly called again after it fails, > and the decoder then uses the software pixfmt derived from the SPS on > subsequent frames. > > (I did pretty much all of my testing with H.264, which does not have this > problem.) > Works for me on forcing hwaccel in HEVC vaapi decoding after applying the hevcdec patch. Thanks for answering my questions. - Linjie
> -----Original Message----- > From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On Behalf > Of Fu, Linjie > Sent: Friday, November 16, 2018 16:37 > To: FFmpeg development discussions and patches <ffmpeg- > devel@ffmpeg.org> > Subject: Re: [FFmpeg-devel] [PATCH v2] ffmpeg: Add option to force a > specific decode format > > > -----Original Message----- > > From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On > Behalf > > Of Mark Thompson > > Sent: Thursday, November 15, 2018 05:48 > > To: ffmpeg-devel@ffmpeg.org > > Subject: Re: [FFmpeg-devel] [PATCH v2] ffmpeg: Add option to force a > > specific decode format > > > > On 14/11/18 01:35, Fu, Linjie wrote: > > >> -----Original Message----- > > >> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On > > Behalf > > >> Of Mark Thompson > > >> Sent: Wednesday, November 14, 2018 09:11 > > >> To: ffmpeg-devel@ffmpeg.org > > >> Subject: Re: [FFmpeg-devel] [PATCH v2] ffmpeg: Add option to force a > > >> specific decode format > > >> > > >> On 14/11/18 00:50, Fu, Linjie wrote: > > >>>> -----Original Message----- > > >>>> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@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? > > >> > > >> If this option is set then get_format will never choose a format not on > the > > list > > >> you provide, so it shouldn't be able to use software decode unless a > > >> software format is on the list. > > >> > > >>> 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). > > >> > > >> Can you give an example? With -v debug there will be output saying > > exactly > > >> what happened in ff_get_format(). > > >> > > >> - Mark > > > > > > > > > Got information like this: > > > > > > [hevc @ 0x55b87457dbc0] Unknown HEVC profile: 0 > > > [hevc @ 0x55b87457dbc0] Decoding SPS > > > [hevc @ 0x55b87457dbc0] Unknown HEVC profile: 0 > > > [hevc @ 0x55b87457dbc0] Decoding PPS > > > [hevc @ 0x55b87457dbc0] Format vaapi_vld chosen by get_format(). > > > [hevc @ 0x55b87457dbc0] Format vaapi_vld requires hwaccel initialisation. > > > [hevc @ 0x55b87457dbc0] Codec hevc profile 0 not supported for > hardware > > decode. > > > [hevc @ 0x55b87457dbc0] Failed setup for format vaapi_vld: hwaccel > > initialisation returned error. > > > [hevc @ 0x55b87457dbc0] Format vaapi_vld not usable, retrying > > get_format() without it. > > > [hevc @ 0x55b87457dbc0] Error parsing NAL unit #3. > > > cur_dts is invalid (this is harmless if it occurs once at the start per stream) > > > [hevc @ 0x55b87458b7c0] nal_unit_type: 1(TRAIL_R), nuh_layer_id: 0, > > temporal_id: 0 > > > [hevc @ 0x55b87458b7c0] Could not find ref with POC 0 > > > > > > See the attached report file for more details. > > > > This is a decoder bug - get_format() is not correctly called again after it fails, > > and the decoder then uses the software pixfmt derived from the SPS on > > subsequent frames. > > > > (I did pretty much all of my testing with H.264, which does not have this > > problem.) > > > Works for me on forcing hwaccel in HEVC vaapi decoding after applying the > hevcdec patch. > Thanks for answering my questions. > Ping? Can this be merged? https://trac.ffmpeg.org/ticket/7519#comment:4 --- Linjie
On Tue, Nov 13, 2018 at 11:43:31PM +0000, Mark Thompson wrote: > Fixes #7519. > --- > doc/ffmpeg.texi | 13 ++++++++++++ > fftools/ffmpeg.c | 10 ++++++++++ > fftools/ffmpeg.h | 4 ++++ > fftools/ffmpeg_opt.c | 47 ++++++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 74 insertions(+) i did already "LGTM" this IIRC, but as its being pinged ... LGTM thx [...]
On 18/02/2019 05:05, Fu, Linjie wrote: >> -----Original Message----- >> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On Behalf >> Of Fu, Linjie >> Sent: Friday, November 16, 2018 16:37 >> To: FFmpeg development discussions and patches <ffmpeg- >> devel@ffmpeg.org> >> Subject: Re: [FFmpeg-devel] [PATCH v2] ffmpeg: Add option to force a >> specific decode format >> >>> -----Original Message----- >>> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On >> Behalf >>> Of Mark Thompson >>> Sent: Thursday, November 15, 2018 05:48 >>> To: ffmpeg-devel@ffmpeg.org >>> Subject: Re: [FFmpeg-devel] [PATCH v2] ffmpeg: Add option to force a >>> specific decode format >>> >>> On 14/11/18 01:35, Fu, Linjie wrote: >>>>> -----Original Message----- >>>>> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On >>> Behalf >>>>> Of Mark Thompson >>>>> Sent: Wednesday, November 14, 2018 09:11 >>>>> To: ffmpeg-devel@ffmpeg.org >>>>> Subject: Re: [FFmpeg-devel] [PATCH v2] ffmpeg: Add option to force a >>>>> specific decode format >>>>> >>>>> On 14/11/18 00:50, Fu, Linjie wrote: >>>>>>> -----Original Message----- >>>>>>> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@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? >>>>> >>>>> If this option is set then get_format will never choose a format not on >> the >>> list >>>>> you provide, so it shouldn't be able to use software decode unless a >>>>> software format is on the list. >>>>> >>>>>> 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). >>>>> >>>>> Can you give an example? With -v debug there will be output saying >>> exactly >>>>> what happened in ff_get_format(). >>>>> >>>>> - Mark >>>> >>>> >>>> Got information like this: >>>> >>>> [hevc @ 0x55b87457dbc0] Unknown HEVC profile: 0 >>>> [hevc @ 0x55b87457dbc0] Decoding SPS >>>> [hevc @ 0x55b87457dbc0] Unknown HEVC profile: 0 >>>> [hevc @ 0x55b87457dbc0] Decoding PPS >>>> [hevc @ 0x55b87457dbc0] Format vaapi_vld chosen by get_format(). >>>> [hevc @ 0x55b87457dbc0] Format vaapi_vld requires hwaccel initialisation. >>>> [hevc @ 0x55b87457dbc0] Codec hevc profile 0 not supported for >> hardware >>> decode. >>>> [hevc @ 0x55b87457dbc0] Failed setup for format vaapi_vld: hwaccel >>> initialisation returned error. >>>> [hevc @ 0x55b87457dbc0] Format vaapi_vld not usable, retrying >>> get_format() without it. >>>> [hevc @ 0x55b87457dbc0] Error parsing NAL unit #3. >>>> cur_dts is invalid (this is harmless if it occurs once at the start per stream) >>>> [hevc @ 0x55b87458b7c0] nal_unit_type: 1(TRAIL_R), nuh_layer_id: 0, >>> temporal_id: 0 >>>> [hevc @ 0x55b87458b7c0] Could not find ref with POC 0 >>>> >>>> See the attached report file for more details. >>> >>> This is a decoder bug - get_format() is not correctly called again after it fails, >>> and the decoder then uses the software pixfmt derived from the SPS on >>> subsequent frames. >>> >>> (I did pretty much all of my testing with H.264, which does not have this >>> problem.) >>> >> Works for me on forcing hwaccel in HEVC vaapi decoding after applying the >> hevcdec patch. >> Thanks for answering my questions. >> > Ping? > Can this be merged? > https://trac.ffmpeg.org/ticket/7519#comment:4 I think this got lost because I was feeling it loosely depended on <https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2018-November/236376.html> in order to actually work in the intended use-case. I wasn't particularly confident in that patch being the best way to do it and it isn't my code, so I was hoping for any thoughts from someone more familiar with it. Shall I apply this part anyway? Thanks, - Mark
*bump* > -----Original Message----- > From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On Behalf Of Mark Thompson > Sent: Wednesday, February 20, 2019 1:52 PM > To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org> > Subject: Re: [FFmpeg-devel] [PATCH v2] ffmpeg: Add option to force a specific decode format > > On 18/02/2019 05:05, Fu, Linjie wrote: > >> -----Original Message----- > >> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On Behalf > >> Of Fu, Linjie > >> Sent: Friday, November 16, 2018 16:37 > >> To: FFmpeg development discussions and patches <ffmpeg- > >> devel@ffmpeg.org> > >> Subject: Re: [FFmpeg-devel] [PATCH v2] ffmpeg: Add option to force a > >> specific decode format > >> > >>> -----Original Message----- > >>> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On > >> Behalf > >>> Of Mark Thompson > >>> Sent: Thursday, November 15, 2018 05:48 > >>> To: ffmpeg-devel@ffmpeg.org > >>> Subject: Re: [FFmpeg-devel] [PATCH v2] ffmpeg: Add option to force a > >>> specific decode format > >>> > >>> On 14/11/18 01:35, Fu, Linjie wrote: > >>>>> -----Original Message----- > >>>>> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On > >>> Behalf > >>>>> Of Mark Thompson > >>>>> Sent: Wednesday, November 14, 2018 09:11 > >>>>> To: ffmpeg-devel@ffmpeg.org > >>>>> Subject: Re: [FFmpeg-devel] [PATCH v2] ffmpeg: Add option to force a > >>>>> specific decode format > >>>>> > >>>>> On 14/11/18 00:50, Fu, Linjie wrote: > >>>>>>> -----Original Message----- > >>>>>>> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@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? > >>>>> > >>>>> If this option is set then get_format will never choose a format not on > >> the > >>> list > >>>>> you provide, so it shouldn't be able to use software decode unless a > >>>>> software format is on the list. > >>>>> > >>>>>> 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). > >>>>> > >>>>> Can you give an example? With -v debug there will be output saying > >>> exactly > >>>>> what happened in ff_get_format(). > >>>>> > >>>>> - Mark > >>>> > >>>> > >>>> Got information like this: > >>>> > >>>> [hevc @ 0x55b87457dbc0] Unknown HEVC profile: 0 > >>>> [hevc @ 0x55b87457dbc0] Decoding SPS > >>>> [hevc @ 0x55b87457dbc0] Unknown HEVC profile: 0 > >>>> [hevc @ 0x55b87457dbc0] Decoding PPS > >>>> [hevc @ 0x55b87457dbc0] Format vaapi_vld chosen by get_format(). > >>>> [hevc @ 0x55b87457dbc0] Format vaapi_vld requires hwaccel initialisation. > >>>> [hevc @ 0x55b87457dbc0] Codec hevc profile 0 not supported for > >> hardware > >>> decode. > >>>> [hevc @ 0x55b87457dbc0] Failed setup for format vaapi_vld: hwaccel > >>> initialisation returned error. > >>>> [hevc @ 0x55b87457dbc0] Format vaapi_vld not usable, retrying > >>> get_format() without it. > >>>> [hevc @ 0x55b87457dbc0] Error parsing NAL unit #3. > >>>> cur_dts is invalid (this is harmless if it occurs once at the start per stream) > >>>> [hevc @ 0x55b87458b7c0] nal_unit_type: 1(TRAIL_R), nuh_layer_id: 0, > >>> temporal_id: 0 > >>>> [hevc @ 0x55b87458b7c0] Could not find ref with POC 0 > >>>> > >>>> See the attached report file for more details. > >>> > >>> This is a decoder bug - get_format() is not correctly called again after it fails, > >>> and the decoder then uses the software pixfmt derived from the SPS on > >>> subsequent frames. > >>> > >>> (I did pretty much all of my testing with H.264, which does not have this > >>> problem.) > >>> > >> Works for me on forcing hwaccel in HEVC vaapi decoding after applying the > >> hevcdec patch. > >> Thanks for answering my questions. > >> > > Ping? > > Can this be merged? > > https://trac.ffmpeg.org/ticket/7519#comment:4 > > I think this got lost because I was feeling it loosely depended on <https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2018- > November/236376.html> in order to actually work in the intended use-case. I wasn't particularly confident in that patch being the > best way to do it and it isn't my code, so I was hoping for any thoughts from someone more familiar with it. > > Shall I apply this part anyway? > > Thanks, > > - Mark > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
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" },