diff --git a/doc/encoders.texi b/doc/encoders.texi index 0696a7acd2..fe6c6ae124 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 313f55118e..f838ee5bd5 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -974,70 +974,252 @@ 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 nb_components; + 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; + const char *profile_string, *entrypoint_string; + 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"); + 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->nb_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; + +#if VA_CHECK_VERSION(1, 0, 0) + profile_string = vaProfileStr(profile->va_profile); +#else + profile_string = "(no profile names)"; +#endif + + 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); + continue; + } + + ctx->profile = profile; + break; } - if (i >= n) { - av_log(ctx, AV_LOG_ERROR, "Encoding profile not found (%d).\n", - ctx->va_profile); + if (!ctx->profile) { + av_log(avctx, AV_LOG_ERROR, "No usable encoding profile found.\n"); err = AVERROR(ENOSYS); goto fail; } + avctx->profile = profile->av_profile; + ctx->va_profile = profile->va_profile; + av_log(avctx, AV_LOG_VERBOSE, "Using VAAPI profile %s (%d).\n", + profile_string, ctx->va_profile); + 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 " - "profile %u: %d (%s).\n", ctx->va_profile, - vas, vaErrorStr(vas)); - err = AVERROR(ENOSYS); + av_log(avctx, AV_LOG_ERROR, "Failed to query entrypoints for " + "profile %s (%d): %d (%s).\n", profile_string, + ctx->va_profile, vas, vaErrorStr(vas)); + 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 %s (%d).\n", profile_string, ctx->va_profile); err = AVERROR(ENOSYS); goto fail; } + ctx->va_entrypoint = va_entrypoints[i]; +#if VA_CHECK_VERSION(1, 0, 0) + entrypoint_string = vaEntrypointStr(ctx->va_entrypoint); +#else + entrypoint_string = "(no entrypoint names)"; +#endif + av_log(avctx, AV_LOG_VERBOSE, "Using VAAPI entrypoint %s (%d).\n", + entrypoint_string, ctx->va_entrypoint); + + 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->nb_components == profile->nb_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 %s (%d) entrypoint %s (%d).\n", + profile_string, ctx->va_profile, + entrypoint_string, ctx->va_entrypoint); + 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); + } 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 %s (%d) entrypoint %s (%d).\n", + rt_format->name, profile_string, ctx->va_profile, + entrypoint_string, 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)); @@ -1057,20 +1239,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 @@ -1089,8 +1257,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) { @@ -1106,8 +1273,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 " @@ -1139,11 +1305,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) @@ -1398,6 +1560,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 c7370a17e2..0da8e356f0 100644 --- a/libavcodec/vaapi_encode.h +++ b/libavcodec/vaapi_encode.h @@ -23,6 +23,10 @@ #include +#if VA_CHECK_VERSION(1, 0, 0) +#include +#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 nb_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 b65c9943e5..456806032b 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" },