Re: [FFmpeg-devel] [PATCH v2 11/36] vaapi_encode: Choose profiles dynamically

2018-06-17 Thread Mark Thompson
On 14/06/18 05:51, Xiang, Haihao wrote:
> On Wed, 2018-06-13 at 23:27 +0100, Mark Thompson wrote:
>> On 12/06/18 08:22, Xiang, Haihao wrote:
>>> On Fri, 2018-06-08 at 00:43 +0100, Mark Thompson wrote:
 Previously there was one fixed choice for each codec (e.g. H.265 -> Main
 profile), and using anything else then required an explicit option from
 the user.  This changes to selecting the profile based on the input format
 and the set of profiles actually supported by the driver (e.g. P010 input
 will choose Main 10 profile for H.265 if the driver supports it).

 The entrypoint and render target format are also chosen dynamically in the
 same way, removing those explicit selections from the per-codec code.
 ---
  doc/encoders.texi   |   3 +
  libavcodec/vaapi_encode.c   | 271 ---
 
 -
  libavcodec/vaapi_encode.h   |  43 +--
  libavcodec/vaapi_encode_h264.c  |  45 ++-
  libavcodec/vaapi_encode_h265.c  |  35 ++
  libavcodec/vaapi_encode_mjpeg.c |  13 +-
  libavcodec/vaapi_encode_mpeg2.c |  36 ++
  libavcodec/vaapi_encode_vp8.c   |  11 +-
  libavcodec/vaapi_encode_vp9.c   |  34 ++---
  9 files changed, 310 insertions(+), 181 deletions(-)

 ...
 +static av_cold int vaapi_encode_profile_entrypoint(AVCodecContext *avctx)
  {
 -VAAPIEncodeContext *ctx = avctx->priv_data;
 +VAAPIEncodeContext  *ctx = avctx->priv_data;
 +VAProfile*va_profiles= NULL;
 +VAEntrypoint *va_entrypoints = NULL;
  VAStatus vas;
 -int i, n, err;
 -VAProfile*profiles= NULL;
 -VAEntrypoint *entrypoints = NULL;
 -VAConfigAttrib attr[] = {
 -{ VAConfigAttribRTFormat },
 -{ VAConfigAttribRateControl  },
 -{ VAConfigAttribEncMaxRefFrames  },
 -{ VAConfigAttribEncPackedHeaders },
 -};
 +const VAEntrypoint *usable_entrypoints;
 +const VAAPIEncodeProfile *profile;
 +const AVPixFmtDescriptor *desc;
 +VAConfigAttrib rt_format_attr;
 +const VAAPIEncodeRTFormat *rt_format;
 +int i, j, n, depth, err;
 +
 +
 +if (ctx->low_power) {
 +#if VA_CHECK_VERSION(0, 39, 2)
 +usable_entrypoints = vaapi_encode_entrypoints_low_power;
 +#else
 +av_log(avctx, AV_LOG_ERROR, "Low-power encoding is not "
 +   "supported with this VAAPI version.\n");
>>>
>>> Is it possible to report the minimal VAAPI version in the log in case user
>>> doesn't know the requirement on vaapi version 0.39.2?
>>
>> The VAAPI version is pretty much useless to users (without reading any source
>> code, how would you find what VAAPI version 0.39.2 means?).
>>
> 
> Ok, I agree it is useless to user.
> 
>> Maybe libva version?  That's still not quite right, though, because it's more
>> "not supported in this build" (and will continue to not be supported if you
>> upgrade libva but don't rebuild with the new headers).
>>
> 
> May we ask user to rebuild ffmpeg once user upgrades libva in the log?

On further thought, I don't think a recommendation is useful here.  You end up 
having to suggest upgrading everything (libva, driver, ffmpeg), and even then 
it still may not be there (if you are using a driver or codec which doesn't 
expose this option).

So, I think it's most sensible to keep the simple text as originally written.  
If you have a string opinion then feel free to suggest your own patch for how 
this should work.  (And it should probably be consistent with other similar 
cases, such as the quality-speed tradeoff option.)

 +return AVERROR(EINVAL);
 +#endif
 +} else {
 +usable_entrypoints = vaapi_encode_entrypoints_normal;
 +}
 +
 +desc = av_pix_fmt_desc_get(ctx->input_frames->sw_format);
 +if (!desc) {
 +av_log(avctx, AV_LOG_ERROR, "Invalid input pixfmt (%d).\n",
 +   ctx->input_frames->sw_format);
 +return AVERROR(EINVAL);
 +}
 +depth = desc->comp[0].depth;
 +for (i = 1; i < desc->nb_components; i++) {
 +if (desc->comp[i].depth != depth) {
 +av_log(avctx, AV_LOG_ERROR, "Invalid input pixfmt (%s).\n",
 +   desc->name);
 +return AVERROR(EINVAL);
 +}
 +}
 +av_log(avctx, AV_LOG_VERBOSE, "Input surface format is %s.\n",
 +   desc->name);
  
  n = vaMaxNumProfiles(ctx->hwctx->display);
 -profiles = av_malloc_array(n, sizeof(VAProfile));
 -if (!profiles) {
 +va_profiles = av_malloc_array(n, sizeof(VAProfile));
 +if (!va_profiles) {
  err = AVERROR(ENOMEM);
  goto fail;
  }
 -vas = vaQueryConfigProfiles(ctx->hwctx->display, profiles, );
 +vas = 

Re: [FFmpeg-devel] [PATCH v2 11/36] vaapi_encode: Choose profiles dynamically

2018-06-13 Thread Xiang, Haihao
On Wed, 2018-06-13 at 23:27 +0100, Mark Thompson wrote:
> On 12/06/18 08:22, Xiang, Haihao wrote:
> > On Fri, 2018-06-08 at 00:43 +0100, Mark Thompson wrote:
> > > Previously there was one fixed choice for each codec (e.g. H.265 -> Main
> > > profile), and using anything else then required an explicit option from
> > > the user.  This changes to selecting the profile based on the input format
> > > and the set of profiles actually supported by the driver (e.g. P010 input
> > > will choose Main 10 profile for H.265 if the driver supports it).
> > > 
> > > The entrypoint and render target format are also chosen dynamically in the
> > > same way, removing those explicit selections from the per-codec code.
> > > ---
> > >  doc/encoders.texi   |   3 +
> > >  libavcodec/vaapi_encode.c   | 271 ---
> > > 
> > > -
> > >  libavcodec/vaapi_encode.h   |  43 +--
> > >  libavcodec/vaapi_encode_h264.c  |  45 ++-
> > >  libavcodec/vaapi_encode_h265.c  |  35 ++
> > >  libavcodec/vaapi_encode_mjpeg.c |  13 +-
> > >  libavcodec/vaapi_encode_mpeg2.c |  36 ++
> > >  libavcodec/vaapi_encode_vp8.c   |  11 +-
> > >  libavcodec/vaapi_encode_vp9.c   |  34 ++---
> > >  9 files changed, 310 insertions(+), 181 deletions(-)
> > > 
> > > ...
> > > diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c
> > > index 27ce792fbe..6104470b31 100644
> > > --- a/libavcodec/vaapi_encode.c
> > > +++ b/libavcodec/vaapi_encode.c
> > > @@ -983,70 +983,247 @@ static av_cold void
> > > vaapi_encode_add_global_param(AVCodecContext *avctx,
> > >  ++ctx->nb_global_params;
> > >  }
> > >  
> > > -static av_cold int vaapi_encode_config_attributes(AVCodecContext *avctx)
> > > +typedef struct VAAPIEncodeRTFormat {
> > > +const char *name;
> > > +unsigned int value;
> > > +int depth;
> > > +int components;
> > 
> > How about adding a prefix of 'nb_' to this field? I think nb_components is
> > more
> > readable. 
> 
> Sure.  It should match the one in VAAPIEncodeProfile, so I'll change it there
> too.
> 
> > > +int log2_chroma_w;
> > > +int log2_chroma_h;
> > > +} VAAPIEncodeRTFormat;
> > > +
> > > +static const VAAPIEncodeRTFormat vaapi_encode_rt_formats[] = {
> > > +{ "YUV400",VA_RT_FORMAT_YUV400,8, 1,  },
> > > +{ "YUV420",VA_RT_FORMAT_YUV420,8, 3, 1, 1 },
> > > +{ "YUV422",VA_RT_FORMAT_YUV422,8, 3, 1, 0 },
> > > +{ "YUV444",VA_RT_FORMAT_YUV444,8, 3, 0, 0 },
> > > +{ "YUV411",VA_RT_FORMAT_YUV411,8, 3, 2, 0 },
> > > +#if VA_CHECK_VERSION(0, 38, 1)
> > > +{ "YUV420_10", VA_RT_FORMAT_YUV420_10BPP, 10, 3, 1, 1 },
> > > +#endif
> > > +};
> > > +
> > > +static const VAEntrypoint vaapi_encode_entrypoints_normal[] = {
> > > +VAEntrypointEncSlice,
> > > +VAEntrypointEncPicture,
> > > +#if VA_CHECK_VERSION(0, 39, 2)
> > > +VAEntrypointEncSliceLP,
> > > +#endif
> > > +0
> > > +};
> > > +#if VA_CHECK_VERSION(0, 39, 2)
> > > +static const VAEntrypoint vaapi_encode_entrypoints_low_power[] = {
> > > +VAEntrypointEncSliceLP,
> > > +0
> > > +};
> > > +#endif
> > > +
> > > +static av_cold int vaapi_encode_profile_entrypoint(AVCodecContext *avctx)
> > >  {
> > > -VAAPIEncodeContext *ctx = avctx->priv_data;
> > > +VAAPIEncodeContext  *ctx = avctx->priv_data;
> > > +VAProfile*va_profiles= NULL;
> > > +VAEntrypoint *va_entrypoints = NULL;
> > >  VAStatus vas;
> > > -int i, n, err;
> > > -VAProfile*profiles= NULL;
> > > -VAEntrypoint *entrypoints = NULL;
> > > -VAConfigAttrib attr[] = {
> > > -{ VAConfigAttribRTFormat },
> > > -{ VAConfigAttribRateControl  },
> > > -{ VAConfigAttribEncMaxRefFrames  },
> > > -{ VAConfigAttribEncPackedHeaders },
> > > -};
> > > +const VAEntrypoint *usable_entrypoints;
> > > +const VAAPIEncodeProfile *profile;
> > > +const AVPixFmtDescriptor *desc;
> > > +VAConfigAttrib rt_format_attr;
> > > +const VAAPIEncodeRTFormat *rt_format;
> > > +int i, j, n, depth, err;
> > > +
> > > +
> > > +if (ctx->low_power) {
> > > +#if VA_CHECK_VERSION(0, 39, 2)
> > > +usable_entrypoints = vaapi_encode_entrypoints_low_power;
> > > +#else
> > > +av_log(avctx, AV_LOG_ERROR, "Low-power encoding is not "
> > > +   "supported with this VAAPI version.\n");
> > 
> > Is it possible to report the minimal VAAPI version in the log in case user
> > doesn't know the requirement on vaapi version 0.39.2?
> 
> The VAAPI version is pretty much useless to users (without reading any source
> code, how would you find what VAAPI version 0.39.2 means?).
> 

Ok, I agree it is useless to user.

> Maybe libva version?  That's still not quite right, though, because it's more
> "not supported in this build" (and will continue to not be supported if you
> upgrade libva but don't rebuild with the new headers).
> 

May 

Re: [FFmpeg-devel] [PATCH v2 11/36] vaapi_encode: Choose profiles dynamically

2018-06-13 Thread Mark Thompson
On 12/06/18 08:22, Xiang, Haihao wrote:
> On Fri, 2018-06-08 at 00:43 +0100, Mark Thompson wrote:
>> Previously there was one fixed choice for each codec (e.g. H.265 -> Main
>> profile), and using anything else then required an explicit option from
>> the user.  This changes to selecting the profile based on the input format
>> and the set of profiles actually supported by the driver (e.g. P010 input
>> will choose Main 10 profile for H.265 if the driver supports it).
>>
>> The entrypoint and render target format are also chosen dynamically in the
>> same way, removing those explicit selections from the per-codec code.
>> ---
>>  doc/encoders.texi   |   3 +
>>  libavcodec/vaapi_encode.c   | 271 
>> ---
>> -
>>  libavcodec/vaapi_encode.h   |  43 +--
>>  libavcodec/vaapi_encode_h264.c  |  45 ++-
>>  libavcodec/vaapi_encode_h265.c  |  35 ++
>>  libavcodec/vaapi_encode_mjpeg.c |  13 +-
>>  libavcodec/vaapi_encode_mpeg2.c |  36 ++
>>  libavcodec/vaapi_encode_vp8.c   |  11 +-
>>  libavcodec/vaapi_encode_vp9.c   |  34 ++---
>>  9 files changed, 310 insertions(+), 181 deletions(-)
>>
>> ...
>> diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c
>> index 27ce792fbe..6104470b31 100644
>> --- a/libavcodec/vaapi_encode.c
>> +++ b/libavcodec/vaapi_encode.c
>> @@ -983,70 +983,247 @@ static av_cold void
>> vaapi_encode_add_global_param(AVCodecContext *avctx,
>>  ++ctx->nb_global_params;
>>  }
>>  
>> -static av_cold int vaapi_encode_config_attributes(AVCodecContext *avctx)
>> +typedef struct VAAPIEncodeRTFormat {
>> +const char *name;
>> +unsigned int value;
>> +int depth;
>> +int components;
> 
> How about adding a prefix of 'nb_' to this field? I think nb_components is 
> more
> readable. 

Sure.  It should match the one in VAAPIEncodeProfile, so I'll change it there 
too.

>> +int log2_chroma_w;
>> +int log2_chroma_h;
>> +} VAAPIEncodeRTFormat;
>> +
>> +static const VAAPIEncodeRTFormat vaapi_encode_rt_formats[] = {
>> +{ "YUV400",VA_RT_FORMAT_YUV400,8, 1,  },
>> +{ "YUV420",VA_RT_FORMAT_YUV420,8, 3, 1, 1 },
>> +{ "YUV422",VA_RT_FORMAT_YUV422,8, 3, 1, 0 },
>> +{ "YUV444",VA_RT_FORMAT_YUV444,8, 3, 0, 0 },
>> +{ "YUV411",VA_RT_FORMAT_YUV411,8, 3, 2, 0 },
>> +#if VA_CHECK_VERSION(0, 38, 1)
>> +{ "YUV420_10", VA_RT_FORMAT_YUV420_10BPP, 10, 3, 1, 1 },
>> +#endif
>> +};
>> +
>> +static const VAEntrypoint vaapi_encode_entrypoints_normal[] = {
>> +VAEntrypointEncSlice,
>> +VAEntrypointEncPicture,
>> +#if VA_CHECK_VERSION(0, 39, 2)
>> +VAEntrypointEncSliceLP,
>> +#endif
>> +0
>> +};
>> +#if VA_CHECK_VERSION(0, 39, 2)
>> +static const VAEntrypoint vaapi_encode_entrypoints_low_power[] = {
>> +VAEntrypointEncSliceLP,
>> +0
>> +};
>> +#endif
>> +
>> +static av_cold int vaapi_encode_profile_entrypoint(AVCodecContext *avctx)
>>  {
>> -VAAPIEncodeContext *ctx = avctx->priv_data;
>> +VAAPIEncodeContext  *ctx = avctx->priv_data;
>> +VAProfile*va_profiles= NULL;
>> +VAEntrypoint *va_entrypoints = NULL;
>>  VAStatus vas;
>> -int i, n, err;
>> -VAProfile*profiles= NULL;
>> -VAEntrypoint *entrypoints = NULL;
>> -VAConfigAttrib attr[] = {
>> -{ VAConfigAttribRTFormat },
>> -{ VAConfigAttribRateControl  },
>> -{ VAConfigAttribEncMaxRefFrames  },
>> -{ VAConfigAttribEncPackedHeaders },
>> -};
>> +const VAEntrypoint *usable_entrypoints;
>> +const VAAPIEncodeProfile *profile;
>> +const AVPixFmtDescriptor *desc;
>> +VAConfigAttrib rt_format_attr;
>> +const VAAPIEncodeRTFormat *rt_format;
>> +int i, j, n, depth, err;
>> +
>> +
>> +if (ctx->low_power) {
>> +#if VA_CHECK_VERSION(0, 39, 2)
>> +usable_entrypoints = vaapi_encode_entrypoints_low_power;
>> +#else
>> +av_log(avctx, AV_LOG_ERROR, "Low-power encoding is not "
>> +   "supported with this VAAPI version.\n");
> 
> Is it possible to report the minimal VAAPI version in the log in case user
> doesn't know the requirement on vaapi version 0.39.2?

The VAAPI version is pretty much useless to users (without reading any source 
code, how would you find what VAAPI version 0.39.2 means?).

Maybe libva version?  That's still not quite right, though, because it's more 
"not supported in this build" (and will continue to not be supported if you 
upgrade libva but don't rebuild with the new headers).

>> +return AVERROR(EINVAL);
>> +#endif
>> +} else {
>> +usable_entrypoints = vaapi_encode_entrypoints_normal;
>> +}
>> +
>> +desc = av_pix_fmt_desc_get(ctx->input_frames->sw_format);
>> +if (!desc) {
>> +av_log(avctx, AV_LOG_ERROR, "Invalid input pixfmt (%d).\n",
>> +   ctx->input_frames->sw_format);
>> +return AVERROR(EINVAL);
>> +}
>> +depth = 

Re: [FFmpeg-devel] [PATCH v2 11/36] vaapi_encode: Choose profiles dynamically

2018-06-12 Thread Xiang, Haihao
On Fri, 2018-06-08 at 00:43 +0100, Mark Thompson wrote:
> Previously there was one fixed choice for each codec (e.g. H.265 -> Main
> profile), and using anything else then required an explicit option from
> the user.  This changes to selecting the profile based on the input format
> and the set of profiles actually supported by the driver (e.g. P010 input
> will choose Main 10 profile for H.265 if the driver supports it).
> 
> The entrypoint and render target format are also chosen dynamically in the
> same way, removing those explicit selections from the per-codec code.
> ---
>  doc/encoders.texi   |   3 +
>  libavcodec/vaapi_encode.c   | 271 ---
> -
>  libavcodec/vaapi_encode.h   |  43 +--
>  libavcodec/vaapi_encode_h264.c  |  45 ++-
>  libavcodec/vaapi_encode_h265.c  |  35 ++
>  libavcodec/vaapi_encode_mjpeg.c |  13 +-
>  libavcodec/vaapi_encode_mpeg2.c |  36 ++
>  libavcodec/vaapi_encode_vp8.c   |  11 +-
>  libavcodec/vaapi_encode_vp9.c   |  34 ++---
>  9 files changed, 310 insertions(+), 181 deletions(-)
> 
> diff --git a/doc/encoders.texi b/doc/encoders.texi
> index 7b095754d1..16be6359b3 100644
> --- a/doc/encoders.texi
> +++ b/doc/encoders.texi
> @@ -2565,6 +2565,9 @@ The following standard libavcodec options are used:
>  @option{bf} / @option{max_b_frames}
>  @item
>  @option{profile}
> +
> +If not set, this will be determined automatically from the format of the
> input
> +frames and the profiles supported by the driver.
>  @item
>  @option{level}
>  @item
> diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c
> index 27ce792fbe..6104470b31 100644
> --- a/libavcodec/vaapi_encode.c
> +++ b/libavcodec/vaapi_encode.c
> @@ -983,70 +983,247 @@ static av_cold void
> vaapi_encode_add_global_param(AVCodecContext *avctx,
>  ++ctx->nb_global_params;
>  }
>  
> -static av_cold int vaapi_encode_config_attributes(AVCodecContext *avctx)
> +typedef struct VAAPIEncodeRTFormat {
> +const char *name;
> +unsigned int value;
> +int depth;
> +int components;

How about adding a prefix of 'nb_' to this field? I think nb_components is more
readable. 

> +int log2_chroma_w;
> +int log2_chroma_h;
> +} VAAPIEncodeRTFormat;
> +
> +static const VAAPIEncodeRTFormat vaapi_encode_rt_formats[] = {
> +{ "YUV400",VA_RT_FORMAT_YUV400,8, 1,  },
> +{ "YUV420",VA_RT_FORMAT_YUV420,8, 3, 1, 1 },
> +{ "YUV422",VA_RT_FORMAT_YUV422,8, 3, 1, 0 },
> +{ "YUV444",VA_RT_FORMAT_YUV444,8, 3, 0, 0 },
> +{ "YUV411",VA_RT_FORMAT_YUV411,8, 3, 2, 0 },
> +#if VA_CHECK_VERSION(0, 38, 1)
> +{ "YUV420_10", VA_RT_FORMAT_YUV420_10BPP, 10, 3, 1, 1 },
> +#endif
> +};
> +
> +static const VAEntrypoint vaapi_encode_entrypoints_normal[] = {
> +VAEntrypointEncSlice,
> +VAEntrypointEncPicture,
> +#if VA_CHECK_VERSION(0, 39, 2)
> +VAEntrypointEncSliceLP,
> +#endif
> +0
> +};
> +#if VA_CHECK_VERSION(0, 39, 2)
> +static const VAEntrypoint vaapi_encode_entrypoints_low_power[] = {
> +VAEntrypointEncSliceLP,
> +0
> +};
> +#endif
> +
> +static av_cold int vaapi_encode_profile_entrypoint(AVCodecContext *avctx)
>  {
> -VAAPIEncodeContext *ctx = avctx->priv_data;
> +VAAPIEncodeContext  *ctx = avctx->priv_data;
> +VAProfile*va_profiles= NULL;
> +VAEntrypoint *va_entrypoints = NULL;
>  VAStatus vas;
> -int i, n, err;
> -VAProfile*profiles= NULL;
> -VAEntrypoint *entrypoints = NULL;
> -VAConfigAttrib attr[] = {
> -{ VAConfigAttribRTFormat },
> -{ VAConfigAttribRateControl  },
> -{ VAConfigAttribEncMaxRefFrames  },
> -{ VAConfigAttribEncPackedHeaders },
> -};
> +const VAEntrypoint *usable_entrypoints;
> +const VAAPIEncodeProfile *profile;
> +const AVPixFmtDescriptor *desc;
> +VAConfigAttrib rt_format_attr;
> +const VAAPIEncodeRTFormat *rt_format;
> +int i, j, n, depth, err;
> +
> +
> +if (ctx->low_power) {
> +#if VA_CHECK_VERSION(0, 39, 2)
> +usable_entrypoints = vaapi_encode_entrypoints_low_power;
> +#else
> +av_log(avctx, AV_LOG_ERROR, "Low-power encoding is not "
> +   "supported with this VAAPI version.\n");

Is it possible to report the minimal VAAPI version in the log in case user
doesn't know the requirement on vaapi version 0.39.2?

> +return AVERROR(EINVAL);
> +#endif
> +} else {
> +usable_entrypoints = vaapi_encode_entrypoints_normal;
> +}
> +
> +desc = av_pix_fmt_desc_get(ctx->input_frames->sw_format);
> +if (!desc) {
> +av_log(avctx, AV_LOG_ERROR, "Invalid input pixfmt (%d).\n",
> +   ctx->input_frames->sw_format);
> +return AVERROR(EINVAL);
> +}
> +depth = desc->comp[0].depth;
> +for (i = 1; i < desc->nb_components; i++) {
> +if (desc->comp[i].depth != depth) {
> +av_log(avctx, AV_LOG_ERROR,