[FFmpeg-devel] [PATCH v2 11/36] vaapi_encode: Choose profiles dynamically
Xiang, Haihao
haihao.xiang at intel.com
Tue Jun 12 10:22:39 EEST 2018
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, "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, &n);
> + vas = vaQueryConfigProfiles(ctx->hwctx->display, va_profiles, &n);
> if (vas != VA_STATUS_SUCCESS) {
> - av_log(ctx, AV_LOG_ERROR, "Failed to query profiles: %d (%s).\n",
> + av_log(avctx, AV_LOG_ERROR, "Failed to query profiles: %d (%s).\n",
> vas, vaErrorStr(vas));
> - err = AVERROR(ENOSYS);
> + err = AVERROR_EXTERNAL;
> goto fail;
> }
> - for (i = 0; i < n; i++) {
> - if (profiles[i] == ctx->va_profile)
> - break;
> +
> + av_assert0(ctx->codec->profiles);
> + for (i = 0; (ctx->codec->profiles[i].av_profile !=
> + FF_PROFILE_UNKNOWN); i++) {
> + profile = &ctx->codec->profiles[i];
> + if (depth != profile->depth ||
> + desc->nb_components != profile->components)
> + continue;
> + if (desc->nb_components > 1 &&
> + (desc->log2_chroma_w != profile->log2_chroma_w ||
> + desc->log2_chroma_h != profile->log2_chroma_h))
> + continue;
> + if (avctx->profile != profile->av_profile &&
> + avctx->profile != FF_PROFILE_UNKNOWN)
> + continue;
> +
> + for (j = 0; j < n; j++) {
> + if (va_profiles[j] == profile->va_profile)
> + break;
> + }
> + if (j >= n) {
> + av_log(avctx, AV_LOG_VERBOSE, "Matching profile %d is "
> + "not supported by driver.\n", profile->va_profile);
Is it possible to report the profile string in the log as what you did below?
> + continue;
> + }
> +
> + ctx->profile = profile;
> + break;
> }
> - if (i >= n) {
> - av_log(ctx, AV_LOG_ERROR, "Encoding profile not found (%d).\n",
> - ctx->va_profile);
> - err = AVERROR(ENOSYS);
> - goto fail;
> + if (!ctx->profile) {
> + av_log(avctx, AV_LOG_ERROR, "No usable encoding profile found.\n");
> + return AVERROR(ENOSYS);
Set err to AVERROR(ENOSYS) then goto fail, otherwise it will result in memory
leak.
> }
>
> + avctx->profile = profile->av_profile;
> + ctx->va_profile = profile->va_profile;
> +#if VA_CHECK_VERSION(1, 0, 0)
> + av_log(avctx, AV_LOG_VERBOSE, "Using VAAPI profile %s (%d).\n",
> + vaProfileStr(ctx->va_profile), ctx->va_profile);
> +#else
> + av_log(avctx, AV_LOG_VERBOSE, "Using VAAPI profile %d.\n",
> + ctx->va_profile);
> +#endif
> +
> n = vaMaxNumEntrypoints(ctx->hwctx->display);
> - entrypoints = av_malloc_array(n, sizeof(VAEntrypoint));
> - if (!entrypoints) {
> + va_entrypoints = av_malloc_array(n, sizeof(VAEntrypoint));
> + if (!va_entrypoints) {
> err = AVERROR(ENOMEM);
> goto fail;
> }
> vas = vaQueryConfigEntrypoints(ctx->hwctx->display, ctx->va_profile,
> - entrypoints, &n);
> + va_entrypoints, &n);
> if (vas != VA_STATUS_SUCCESS) {
> - av_log(ctx, AV_LOG_ERROR, "Failed to query entrypoints for "
> + av_log(avctx, AV_LOG_ERROR, "Failed to query entrypoints for "
> "profile %u: %d (%s).\n", ctx->va_profile,
Log profile string?
> vas, vaErrorStr(vas));
> - err = AVERROR(ENOSYS);
> + err = AVERROR_EXTERNAL;
> goto fail;
> }
> +
> for (i = 0; i < n; i++) {
> - if (entrypoints[i] == ctx->va_entrypoint)
> + for (j = 0; usable_entrypoints[j]; j++) {
> + if (va_entrypoints[i] == usable_entrypoints[j])
> + break;
> + }
> + if (usable_entrypoints[j])
> break;
> }
> if (i >= n) {
> - av_log(ctx, AV_LOG_ERROR, "Encoding entrypoint not found "
> - "(%d / %d).\n", ctx->va_profile, ctx->va_entrypoint);
> + av_log(avctx, AV_LOG_ERROR, "No usable encoding entrypoint found "
> + "for profile %d.\n", ctx->va_profile);
Log profile string?
> + err = AVERROR(ENOSYS);
> + goto fail;
> + }
> +
> + ctx->va_entrypoint = va_entrypoints[i];
> +#if VA_CHECK_VERSION(1, 0, 0)
> + av_log(avctx, AV_LOG_VERBOSE, "Using VAAPI entrypoint %s (%d).\n",
> + vaEntrypointStr(ctx->va_entrypoint), ctx->va_entrypoint);
> +#else
> + av_log(avctx, AV_LOG_VERBOSE, "Using VAAPI entrypoint %d.\n",
> + ctx->va_entrypoint);
> +#endif
> +
> + for (i = 0; i < FF_ARRAY_ELEMS(vaapi_encode_rt_formats); i++) {
> + rt_format = &vaapi_encode_rt_formats[i];
> + if (rt_format->depth == depth &&
> + rt_format->components == profile->components &&
> + rt_format->log2_chroma_w == profile->log2_chroma_w &&
> + rt_format->log2_chroma_h == profile->log2_chroma_h)
> + break;
> + }
> + if (i >= FF_ARRAY_ELEMS(vaapi_encode_rt_formats)) {
> + av_log(avctx, AV_LOG_ERROR, "No usable render target format "
> + "found for profile %d entrypoint %d.\n",
> + ctx->va_profile, ctx->va_entrypoint);
Log profile and entrypoint strings?
> err = AVERROR(ENOSYS);
> goto fail;
> }
>
> + rt_format_attr = (VAConfigAttrib) { VAConfigAttribRTFormat };
> + vas = vaGetConfigAttributes(ctx->hwctx->display,
> + ctx->va_profile, ctx->va_entrypoint,
> + &rt_format_attr, 1);
> + if (vas != VA_STATUS_SUCCESS) {
> + av_log(avctx, AV_LOG_ERROR, "Failed to query RT format "
> + "config attribute: %d (%s).\n", vas, vaErrorStr(vas));
> + err = AVERROR_EXTERNAL;
> + goto fail;
> + }
> +
> + if (rt_format_attr.value == VA_ATTRIB_NOT_SUPPORTED) {
> + av_log(avctx, AV_LOG_VERBOSE, "RT format config attribute not "
> + "supported by driver: assuming surface RT format %s "
> + "is valid.\n", rt_format->name);
I think it would be better to log it as a warning.
> + } else if (!(rt_format_attr.value & rt_format->value)) {
> + av_log(avctx, AV_LOG_ERROR, "Surface RT format %s not supported "
> + "by driver for encoding profile %d entrypoint %d.\n",
> + rt_format->name, ctx->va_profile, ctx->va_entrypoint);
> + err = AVERROR(ENOSYS);
> + goto fail;
> + } else {
> + av_log(avctx, AV_LOG_VERBOSE, "Using VAAPI render target "
> + "format %s (%#x).\n", rt_format->name, rt_format->value);
> + ctx->config_attributes[ctx->nb_config_attributes++] =
> + (VAConfigAttrib) {
> + .type = VAConfigAttribRTFormat,
> + .value = rt_format->value,
> + };
> + }
> +
> + err = 0;
> +fail:
> + av_freep(&va_profiles);
> + av_freep(&va_entrypoints);
> + return err;
> +}
> +
> +static av_cold int vaapi_encode_config_attributes(AVCodecContext *avctx)
> +{
> + VAAPIEncodeContext *ctx = avctx->priv_data;
> + VAStatus vas;
> + int i;
> +
> + VAConfigAttrib attr[] = {
> + { VAConfigAttribRateControl },
> + { VAConfigAttribEncMaxRefFrames },
> + { VAConfigAttribEncPackedHeaders },
> + };
> +
> vas = vaGetConfigAttributes(ctx->hwctx->display,
> ctx->va_profile, ctx->va_entrypoint,
> attr, FF_ARRAY_ELEMS(attr));
> @@ -1066,20 +1243,6 @@ static av_cold int
> vaapi_encode_config_attributes(AVCodecContext *avctx)
> continue;
> }
> switch (attr[i].type) {
> - case VAConfigAttribRTFormat:
> - if (!(ctx->va_rt_format & attr[i].value)) {
> - av_log(avctx, AV_LOG_ERROR, "Surface RT format %#x "
> - "is not supported (mask %#x).\n",
> - ctx->va_rt_format, attr[i].value);
> - err = AVERROR(EINVAL);
> - goto fail;
> - }
> - ctx->config_attributes[ctx->nb_config_attributes++] =
> - (VAConfigAttrib) {
> - .type = VAConfigAttribRTFormat,
> - .value = ctx->va_rt_format,
> - };
> - break;
> case VAConfigAttribRateControl:
> // Hack for backward compatibility: CBR was the only
> // usable RC mode for a long time, so old drivers will
> @@ -1098,8 +1261,7 @@ static av_cold int
> vaapi_encode_config_attributes(AVCodecContext *avctx)
> av_log(avctx, AV_LOG_ERROR, "Rate control mode %#x "
> "is not supported (mask: %#x).\n",
> ctx->va_rc_mode, attr[i].value);
> - err = AVERROR(EINVAL);
> - goto fail;
> + return AVERROR(EINVAL);
> }
> ctx->config_attributes[ctx->nb_config_attributes++] =
> (VAConfigAttrib) {
> @@ -1115,8 +1277,7 @@ static av_cold int
> vaapi_encode_config_attributes(AVCodecContext *avctx)
> if (avctx->gop_size > 1 && ref_l0 < 1) {
> av_log(avctx, AV_LOG_ERROR, "P frames are not "
> "supported (%#x).\n", attr[i].value);
> - err = AVERROR(EINVAL);
> - goto fail;
> + return AVERROR(EINVAL);
> }
> if (avctx->max_b_frames > 0 && ref_l1 < 1) {
> av_log(avctx, AV_LOG_WARNING, "B frames are not "
> @@ -1148,11 +1309,7 @@ static av_cold int
> vaapi_encode_config_attributes(AVCodecContext *avctx)
> }
> }
>
> - err = 0;
> -fail:
> - av_freep(&profiles);
> - av_freep(&entrypoints);
> - return err;
> + return 0;
> }
>
> static av_cold int vaapi_encode_init_rate_control(AVCodecContext *avctx)
> @@ -1407,6 +1564,10 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx)
> ctx->device = (AVHWDeviceContext*)ctx->device_ref->data;
> ctx->hwctx = ctx->device->hwctx;
>
> + err = vaapi_encode_profile_entrypoint(avctx);
> + if (err < 0)
> + goto fail;
> +
> err = vaapi_encode_config_attributes(avctx);
> if (err < 0)
> goto fail;
> diff --git a/libavcodec/vaapi_encode.h b/libavcodec/vaapi_encode.h
> index 54dc4a475e..212ab6726d 100644
> --- a/libavcodec/vaapi_encode.h
> +++ b/libavcodec/vaapi_encode.h
> @@ -23,6 +23,10 @@
>
> #include <va/va.h>
>
> +#if VA_CHECK_VERSION(1, 0, 0)
> +#include <va/va_str.h>
> +#endif
> +
> #include "libavutil/hwcontext.h"
> #include "libavutil/hwcontext_vaapi.h"
>
> @@ -86,18 +90,32 @@ typedef struct VAAPIEncodePicture {
> VAAPIEncodeSlice *slices;
> } VAAPIEncodePicture;
>
> +typedef struct VAAPIEncodeProfile {
> + // lavc profile value (FF_PROFILE_*).
> + int av_profile;
> + // Supported bit depth.
> + int depth;
> + // Number of components.
> + int components;
> + // Chroma subsampling in width dimension.
> + int log2_chroma_w;
> + // Chroma subsampling in height dimension.
> + int log2_chroma_h;
> + // VAAPI profile value.
> + VAProfile va_profile;
> +} VAAPIEncodeProfile;
> +
> typedef struct VAAPIEncodeContext {
> const AVClass *class;
>
> // Codec-specific hooks.
> const struct VAAPIEncodeType *codec;
>
> - // Encoding profile (VAProfileXXX).
> - VAProfile va_profile;
> - // Encoding entrypoint (usually VAEntryointEncSlice).
> - VAEntrypoint va_entrypoint;
> - // Surface colour/sampling format (usually VA_RT_FORMAT_YUV420).
> - unsigned int va_rt_format;
> + // Global options.
> +
> + // Use low power encoding mode.
> + int low_power;
> +
> // Rate control mode.
> unsigned int va_rc_mode;
> // Supported packed headers (initially the desired set, modified
> @@ -113,6 +131,14 @@ typedef struct VAAPIEncodeContext {
> // Everything above this point must be set before calling
> // ff_vaapi_encode_init().
>
> + // Chosen encoding profile details.
> + const VAAPIEncodeProfile *profile;
> +
> + // Encoding profile (VAProfile*).
> + VAProfile va_profile;
> + // Encoding entrypoint (VAEntryoint*).
> + VAEntrypoint va_entrypoint;
> +
> // Configuration attributes to use when creating va_config.
> VAConfigAttrib config_attributes[MAX_CONFIG_ATTRIBUTES];
> int nb_config_attributes;
> @@ -204,8 +230,11 @@ typedef struct VAAPIEncodeContext {
> int end_of_stream;
> } VAAPIEncodeContext;
>
> -
> typedef struct VAAPIEncodeType {
> + // List of supported profiles and corresponding VAAPI profiles.
> + // (Must end with FF_PROFILE_UNKNOWN.)
> + const VAAPIEncodeProfile *profiles;
> +
> // Perform any extra codec-specific configuration after the
> // codec context is initialised (set up the private data and
> // add any necessary global parameters).
> diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c
> index 8f999b2311..ab8bf13ef3 100644
> --- a/libavcodec/vaapi_encode_h264.c
> +++ b/libavcodec/vaapi_encode_h264.c
> @@ -866,7 +866,17 @@ static av_cold int
> vaapi_encode_h264_configure(AVCodecContext *avctx)
> return 0;
> }
>
> +static const VAAPIEncodeProfile vaapi_encode_h264_profiles[] = {
> + { FF_PROFILE_H264_HIGH, 8, 3, 1, 1, VAProfileH264High },
> + { FF_PROFILE_H264_MAIN, 8, 3, 1, 1, VAProfileH264Main },
> + { FF_PROFILE_H264_CONSTRAINED_BASELINE,
> + 8, 3, 1, 1, VAProfileH264ConstrainedBaseline },
> + { FF_PROFILE_UNKNOWN }
> +};
> +
> static const VAAPIEncodeType vaapi_encode_type_h264 = {
> + .profiles = vaapi_encode_h264_profiles,
> +
> .configure = &vaapi_encode_h264_configure,
>
> .sequence_params_size = sizeof(VAEncSequenceParameterBufferH264),
> @@ -899,30 +909,17 @@ static av_cold int vaapi_encode_h264_init(AVCodecContext
> *avctx)
> if (avctx->level == FF_LEVEL_UNKNOWN)
> avctx->level = priv->level;
>
> + // Reject unsupported profiles.
> switch (avctx->profile) {
> case FF_PROFILE_H264_BASELINE:
> av_log(avctx, AV_LOG_WARNING, "H.264 baseline profile is not "
> "supported, using constrained baseline profile instead.\n");
> avctx->profile = FF_PROFILE_H264_CONSTRAINED_BASELINE;
> - case FF_PROFILE_H264_CONSTRAINED_BASELINE:
> - ctx->va_profile = VAProfileH264ConstrainedBaseline;
> - if (avctx->max_b_frames != 0) {
> - avctx->max_b_frames = 0;
> - av_log(avctx, AV_LOG_WARNING, "H.264 constrained baseline profile
> "
> - "doesn't support encoding with B frames, disabling
> them.\n");
> - }
> - break;
> - case FF_PROFILE_H264_MAIN:
> - ctx->va_profile = VAProfileH264Main;
> break;
> case FF_PROFILE_H264_EXTENDED:
> av_log(avctx, AV_LOG_ERROR, "H.264 extended profile "
> "is not supported.\n");
> return AVERROR_PATCHWELCOME;
> - case FF_PROFILE_UNKNOWN:
> - case FF_PROFILE_H264_HIGH:
> - ctx->va_profile = VAProfileH264High;
> - break;
> case FF_PROFILE_H264_HIGH_10:
> case FF_PROFILE_H264_HIGH_10_INTRA:
> av_log(avctx, AV_LOG_ERROR, "H.264 10-bit profiles "
> @@ -937,25 +934,9 @@ static av_cold int vaapi_encode_h264_init(AVCodecContext
> *avctx)
> av_log(avctx, AV_LOG_ERROR, "H.264 non-4:2:0 profiles "
> "are not supported.\n");
> return AVERROR_PATCHWELCOME;
> - default:
> - av_log(avctx, AV_LOG_ERROR, "Unknown H.264 profile %d.\n",
> - avctx->profile);
> - return AVERROR(EINVAL);
> - }
> - if (priv->low_power) {
> -#if VA_CHECK_VERSION(0, 39, 2)
> - ctx->va_entrypoint = VAEntrypointEncSliceLP;
> -#else
> - av_log(avctx, AV_LOG_ERROR, "Low-power encoding is not "
> - "supported with this VAAPI version.\n");
> - return AVERROR(EINVAL);
> -#endif
> - } else {
> - ctx->va_entrypoint = VAEntrypointEncSlice;
> }
>
> - // Only 8-bit encode is supported.
> - ctx->va_rt_format = VA_RT_FORMAT_YUV420;
> + ctx->low_power = priv->low_power;
>
> if (avctx->bit_rate > 0) {
> if (avctx->rc_max_rate == avctx->bit_rate)
> @@ -1022,7 +1003,7 @@ static const AVOption vaapi_encode_h264_options[] = {
>
> { "profile", "Set profile (profile_idc and constraint_set*_flag)",
> OFFSET(profile), AV_OPT_TYPE_INT,
> - { .i64 = FF_PROFILE_H264_HIGH }, 0x0000, 0xffff, FLAGS, "profile" },
> + { .i64 = FF_PROFILE_UNKNOWN }, FF_PROFILE_UNKNOWN, 0xffff, FLAGS,
> "profile" },
>
> #define PROFILE(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \
> { .i64 = value }, 0, 0, FLAGS, "profile"
> diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c
> index 8f191efc4b..9fa16593d0 100644
> --- a/libavcodec/vaapi_encode_h265.c
> +++ b/libavcodec/vaapi_encode_h265.c
> @@ -1025,7 +1025,17 @@ static av_cold int
> vaapi_encode_h265_configure(AVCodecContext *avctx)
> return 0;
> }
>
> +static const VAAPIEncodeProfile vaapi_encode_h265_profiles[] = {
> + { FF_PROFILE_HEVC_MAIN, 8, 3, 1, 1, VAProfileHEVCMain },
> +#if VA_CHECK_VERSION(0, 37, 0)
> + { FF_PROFILE_HEVC_MAIN_10, 10, 3, 1, 1, VAProfileHEVCMain10 },
> +#endif
> + { FF_PROFILE_UNKNOWN }
> +};
> +
> static const VAAPIEncodeType vaapi_encode_type_h265 = {
> + .profiles = vaapi_encode_h265_profiles,
> +
> .configure = &vaapi_encode_h265_configure,
>
> .sequence_params_size = sizeof(VAEncSequenceParameterBufferHEVC),
> @@ -1058,29 +1068,6 @@ static av_cold int
> vaapi_encode_h265_init(AVCodecContext *avctx)
> if (avctx->level == FF_LEVEL_UNKNOWN)
> avctx->level = priv->level;
>
> - switch (avctx->profile) {
> - case FF_PROFILE_HEVC_MAIN:
> - case FF_PROFILE_UNKNOWN:
> - ctx->va_profile = VAProfileHEVCMain;
> - ctx->va_rt_format = VA_RT_FORMAT_YUV420;
> - break;
> - case FF_PROFILE_HEVC_MAIN_10:
> -#ifdef VA_RT_FORMAT_YUV420_10BPP
> - ctx->va_profile = VAProfileHEVCMain10;
> - ctx->va_rt_format = VA_RT_FORMAT_YUV420_10BPP;
> - break;
> -#else
> - av_log(avctx, AV_LOG_ERROR, "10-bit encoding is not "
> - "supported with this VAAPI version.\n");
> - return AVERROR(ENOSYS);
> -#endif
> - default:
> - av_log(avctx, AV_LOG_ERROR, "Unknown H.265 profile %d.\n",
> - avctx->profile);
> - return AVERROR(EINVAL);
> - }
> - ctx->va_entrypoint = VAEntrypointEncSlice;
> -
> if (avctx->bit_rate > 0) {
> if (avctx->rc_max_rate == avctx->bit_rate)
> ctx->va_rc_mode = VA_RC_CBR;
> @@ -1120,7 +1107,7 @@ static const AVOption vaapi_encode_h265_options[] = {
>
> { "profile", "Set profile (general_profile_idc)",
> OFFSET(profile), AV_OPT_TYPE_INT,
> - { .i64 = FF_PROFILE_HEVC_MAIN }, 0x00, 0xff, FLAGS, "profile" },
> + { .i64 = FF_PROFILE_UNKNOWN }, FF_PROFILE_UNKNOWN, 0xff, FLAGS,
> "profile" },
>
> #define PROFILE(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \
> { .i64 = value }, 0, 0, FLAGS, "profile"
> diff --git a/libavcodec/vaapi_encode_mjpeg.c b/libavcodec/vaapi_encode_mjpeg.c
> index 481981a71c..b328beaa09 100644
> --- a/libavcodec/vaapi_encode_mjpeg.c
> +++ b/libavcodec/vaapi_encode_mjpeg.c
> @@ -359,7 +359,15 @@ static av_cold int
> vaapi_encode_mjpeg_configure(AVCodecContext *avctx)
> return 0;
> }
>
> +static const VAAPIEncodeProfile vaapi_encode_mjpeg_profiles[] = {
> + { FF_PROFILE_MJPEG_HUFFMAN_BASELINE_DCT,
> + 8, 3, 1, 1, VAProfileJPEGBaseline },
> + { FF_PROFILE_UNKNOWN }
> +};
> +
> static const VAAPIEncodeType vaapi_encode_type_mjpeg = {
> + .profiles = vaapi_encode_mjpeg_profiles,
> +
> .configure = &vaapi_encode_mjpeg_configure,
>
> .picture_params_size = sizeof(VAEncPictureParameterBufferJPEG),
> @@ -380,11 +388,6 @@ static av_cold int vaapi_encode_mjpeg_init(AVCodecContext
> *avctx)
>
> ctx->codec = &vaapi_encode_type_mjpeg;
>
> - ctx->va_profile = VAProfileJPEGBaseline;
> - ctx->va_entrypoint = VAEntrypointEncPicture;
> -
> - ctx->va_rt_format = VA_RT_FORMAT_YUV420;
> -
> ctx->va_rc_mode = VA_RC_CQP;
>
> // The JPEG image header - see note above.
> diff --git a/libavcodec/vaapi_encode_mpeg2.c b/libavcodec/vaapi_encode_mpeg2.c
> index 5577fa9e04..7f6c7833da 100644
> --- a/libavcodec/vaapi_encode_mpeg2.c
> +++ b/libavcodec/vaapi_encode_mpeg2.c
> @@ -552,7 +552,15 @@ static av_cold int
> vaapi_encode_mpeg2_configure(AVCodecContext *avctx)
> return 0;
> }
>
> +static const VAAPIEncodeProfile vaapi_encode_mpeg2_profiles[] = {
> + { FF_PROFILE_MPEG2_MAIN, 8, 3, 1, 1, VAProfileMPEG2Main },
> + { FF_PROFILE_MPEG2_SIMPLE, 8, 3, 1, 1, VAProfileMPEG2Simple },
> + { FF_PROFILE_UNKNOWN }
> +};
> +
> static const VAAPIEncodeType vaapi_encode_type_mpeg2 = {
> + .profiles = vaapi_encode_mpeg2_profiles,
> +
> .configure = &vaapi_encode_mpeg2_configure,
>
> .sequence_params_size = sizeof(VAEncSequenceParameterBufferMPEG2),
> @@ -577,31 +585,6 @@ static av_cold int vaapi_encode_mpeg2_init(AVCodecContext
> *avctx)
>
> ctx->codec = &vaapi_encode_type_mpeg2;
>
> - switch (avctx->profile) {
> - case FF_PROFILE_MPEG2_SIMPLE:
> - ctx->va_profile = VAProfileMPEG2Simple;
> - break;
> - case FF_PROFILE_MPEG2_MAIN:
> - ctx->va_profile = VAProfileMPEG2Main;
> - break;
> - case FF_PROFILE_MPEG2_422:
> - av_log(avctx, AV_LOG_ERROR, "MPEG-2 4:2:2 profile "
> - "is not supported.\n");
> - return AVERROR_PATCHWELCOME;
> - case FF_PROFILE_MPEG2_HIGH:
> - av_log(avctx, AV_LOG_ERROR, "MPEG-2 high profile "
> - "is not supported.\n");
> - return AVERROR_PATCHWELCOME;
> - case FF_PROFILE_MPEG2_SS:
> - case FF_PROFILE_MPEG2_SNR_SCALABLE:
> - av_log(avctx, AV_LOG_ERROR, "MPEG-2 scalable profiles "
> - "are not supported.\n");
> - return AVERROR_PATCHWELCOME;
> - default:
> - av_log(avctx, AV_LOG_ERROR, "Unknown MPEG-2 profile %d.\n",
> - avctx->profile);
> - return AVERROR(EINVAL);
> - }
> switch (avctx->level) {
> case 4: // High
> case 6: // High 1440
> @@ -620,8 +603,6 @@ static av_cold int vaapi_encode_mpeg2_init(AVCodecContext
> *avctx)
> return AVERROR(EINVAL);
> }
>
> - ctx->va_entrypoint = VAEntrypointEncSlice;
> - ctx->va_rt_format = VA_RT_FORMAT_YUV420;
> ctx->va_rc_mode = VA_RC_CQP;
>
> ctx->va_packed_headers = VA_ENC_PACKED_HEADER_SEQUENCE |
> @@ -643,7 +624,6 @@ static av_cold int vaapi_encode_mpeg2_close(AVCodecContext
> *avctx)
> }
>
> static const AVCodecDefault vaapi_encode_mpeg2_defaults[] = {
> - { "profile", "4" },
> { "level", "4" },
> { "bf", "1" },
> { "g", "120" },
> diff --git a/libavcodec/vaapi_encode_vp8.c b/libavcodec/vaapi_encode_vp8.c
> index 6cdd30abda..a502df7885 100644
> --- a/libavcodec/vaapi_encode_vp8.c
> +++ b/libavcodec/vaapi_encode_vp8.c
> @@ -175,7 +175,14 @@ static av_cold int
> vaapi_encode_vp8_configure(AVCodecContext *avctx)
> return 0;
> }
>
> +static const VAAPIEncodeProfile vaapi_encode_vp8_profiles[] = {
> + { 0 /* VP8 has no profiles */, 8, 3, 1, 1, VAProfileVP8Version0_3 },
> + { FF_PROFILE_UNKNOWN }
> +};
> +
> static const VAAPIEncodeType vaapi_encode_type_vp8 = {
> + .profiles = vaapi_encode_vp8_profiles,
> +
> .configure = &vaapi_encode_vp8_configure,
>
> .sequence_params_size = sizeof(VAEncSequenceParameterBufferVP8),
> @@ -198,10 +205,6 @@ static av_cold int vaapi_encode_vp8_init(AVCodecContext
> *avctx)
>
> ctx->codec = &vaapi_encode_type_vp8;
>
> - ctx->va_profile = VAProfileVP8Version0_3;
> - ctx->va_entrypoint = VAEntrypointEncSlice;
> - ctx->va_rt_format = VA_RT_FORMAT_YUV420;
> -
> if (avctx->flags & AV_CODEC_FLAG_QSCALE) {
> ctx->va_rc_mode = VA_RC_CQP;
> } else if (avctx->bit_rate > 0) {
> diff --git a/libavcodec/vaapi_encode_vp9.c b/libavcodec/vaapi_encode_vp9.c
> index bf99597e4c..88c0ce3b0a 100644
> --- a/libavcodec/vaapi_encode_vp9.c
> +++ b/libavcodec/vaapi_encode_vp9.c
> @@ -203,7 +203,15 @@ static av_cold int
> vaapi_encode_vp9_configure(AVCodecContext *avctx)
> return 0;
> }
>
> +static const VAAPIEncodeProfile vaapi_encode_vp9_profiles[] = {
> + { FF_PROFILE_VP9_0, 8, 3, 1, 1, VAProfileVP9Profile0 },
> + { FF_PROFILE_VP9_2, 10, 3, 1, 1, VAProfileVP9Profile2 },
> + { FF_PROFILE_UNKNOWN }
> +};
> +
> static const VAAPIEncodeType vaapi_encode_type_vp9 = {
> + .profiles = vaapi_encode_vp9_profiles,
> +
> .configure = &vaapi_encode_vp9_configure,
>
> .sequence_params_size = sizeof(VAEncSequenceParameterBufferVP9),
> @@ -219,31 +227,6 @@ static av_cold int vaapi_encode_vp9_init(AVCodecContext
> *avctx)
>
> ctx->codec = &vaapi_encode_type_vp9;
>
> - switch (avctx->profile) {
> - case FF_PROFILE_VP9_0:
> - case FF_PROFILE_UNKNOWN:
> - ctx->va_profile = VAProfileVP9Profile0;
> - ctx->va_rt_format = VA_RT_FORMAT_YUV420;
> - break;
> - case FF_PROFILE_VP9_1:
> - av_log(avctx, AV_LOG_ERROR, "VP9 profile 1 is not "
> - "supported.\n");
> - return AVERROR_PATCHWELCOME;
> - case FF_PROFILE_VP9_2:
> - ctx->va_profile = VAProfileVP9Profile2;
> - ctx->va_rt_format = VA_RT_FORMAT_YUV420_10BPP;
> - break;
> - case FF_PROFILE_VP9_3:
> - av_log(avctx, AV_LOG_ERROR, "VP9 profile 3 is not "
> - "supported.\n");
> - return AVERROR_PATCHWELCOME;
> - default:
> - av_log(avctx, AV_LOG_ERROR, "Unknown VP9 profile %d.\n",
> - avctx->profile);
> - return AVERROR(EINVAL);
> - }
> - ctx->va_entrypoint = VAEntrypointEncSlice;
> -
> if (avctx->flags & AV_CODEC_FLAG_QSCALE) {
> ctx->va_rc_mode = VA_RC_CQP;
> } else if (avctx->bit_rate > 0) {
> @@ -276,7 +259,6 @@ static const AVOption vaapi_encode_vp9_options[] = {
> };
>
> static const AVCodecDefault vaapi_encode_vp9_defaults[] = {
> - { "profile", "0" },
> { "b", "0" },
> { "bf", "0" },
> { "g", "250" },
More information about the ffmpeg-devel
mailing list