* commit '2bfa067d0b636e7b2004fb0ad5a53d0d48c6de32':
vaapi_encode: Check config attributes before creating config
Merged-by: Hendrik Leppkes <h.leppkes@gmail.com>
... | ... |
@@ -20,6 +20,7 @@ |
20 | 20 |
#include <string.h> |
21 | 21 |
|
22 | 22 |
#include "libavutil/avassert.h" |
23 |
+#include "libavutil/common.h" |
|
23 | 24 |
#include "libavutil/log.h" |
24 | 25 |
#include "libavutil/pixdesc.h" |
25 | 26 |
|
... | ... |
@@ -887,6 +888,122 @@ fail: |
887 | 887 |
return err; |
888 | 888 |
} |
889 | 889 |
|
890 |
+static av_cold int vaapi_encode_check_config(AVCodecContext *avctx) |
|
891 |
+{ |
|
892 |
+ VAAPIEncodeContext *ctx = avctx->priv_data; |
|
893 |
+ VAStatus vas; |
|
894 |
+ int i, n, err; |
|
895 |
+ VAProfile *profiles = NULL; |
|
896 |
+ VAEntrypoint *entrypoints = NULL; |
|
897 |
+ VAConfigAttrib attr[] = { |
|
898 |
+ { VAConfigAttribRateControl }, |
|
899 |
+ { VAConfigAttribEncMaxRefFrames }, |
|
900 |
+ }; |
|
901 |
+ |
|
902 |
+ n = vaMaxNumProfiles(ctx->hwctx->display); |
|
903 |
+ profiles = av_malloc_array(n, sizeof(VAProfile)); |
|
904 |
+ if (!profiles) { |
|
905 |
+ err = AVERROR(ENOMEM); |
|
906 |
+ goto fail; |
|
907 |
+ } |
|
908 |
+ vas = vaQueryConfigProfiles(ctx->hwctx->display, profiles, &n); |
|
909 |
+ if (vas != VA_STATUS_SUCCESS) { |
|
910 |
+ av_log(ctx, AV_LOG_ERROR, "Failed to query profiles: %d (%s).\n", |
|
911 |
+ vas, vaErrorStr(vas)); |
|
912 |
+ err = AVERROR(ENOSYS); |
|
913 |
+ goto fail; |
|
914 |
+ } |
|
915 |
+ for (i = 0; i < n; i++) { |
|
916 |
+ if (profiles[i] == ctx->va_profile) |
|
917 |
+ break; |
|
918 |
+ } |
|
919 |
+ if (i >= n) { |
|
920 |
+ av_log(ctx, AV_LOG_ERROR, "Encoding profile not found (%d).\n", |
|
921 |
+ ctx->va_profile); |
|
922 |
+ err = AVERROR(ENOSYS); |
|
923 |
+ goto fail; |
|
924 |
+ } |
|
925 |
+ |
|
926 |
+ n = vaMaxNumEntrypoints(ctx->hwctx->display); |
|
927 |
+ entrypoints = av_malloc_array(n, sizeof(VAEntrypoint)); |
|
928 |
+ if (!entrypoints) { |
|
929 |
+ err = AVERROR(ENOMEM); |
|
930 |
+ goto fail; |
|
931 |
+ } |
|
932 |
+ vas = vaQueryConfigEntrypoints(ctx->hwctx->display, ctx->va_profile, |
|
933 |
+ entrypoints, &n); |
|
934 |
+ if (vas != VA_STATUS_SUCCESS) { |
|
935 |
+ av_log(ctx, AV_LOG_ERROR, "Failed to query entrypoints for " |
|
936 |
+ "profile %u: %d (%s).\n", ctx->va_profile, |
|
937 |
+ vas, vaErrorStr(vas)); |
|
938 |
+ err = AVERROR(ENOSYS); |
|
939 |
+ goto fail; |
|
940 |
+ } |
|
941 |
+ for (i = 0; i < n; i++) { |
|
942 |
+ if (entrypoints[i] == ctx->va_entrypoint) |
|
943 |
+ break; |
|
944 |
+ } |
|
945 |
+ if (i >= n) { |
|
946 |
+ av_log(ctx, AV_LOG_ERROR, "Encoding entrypoint not found " |
|
947 |
+ "(%d / %d).\n", ctx->va_profile, ctx->va_entrypoint); |
|
948 |
+ err = AVERROR(ENOSYS); |
|
949 |
+ goto fail; |
|
950 |
+ } |
|
951 |
+ |
|
952 |
+ vas = vaGetConfigAttributes(ctx->hwctx->display, |
|
953 |
+ ctx->va_profile, ctx->va_entrypoint, |
|
954 |
+ attr, FF_ARRAY_ELEMS(attr)); |
|
955 |
+ if (vas != VA_STATUS_SUCCESS) { |
|
956 |
+ av_log(avctx, AV_LOG_ERROR, "Failed to fetch config " |
|
957 |
+ "attributes: %d (%s).\n", vas, vaErrorStr(vas)); |
|
958 |
+ return AVERROR(EINVAL); |
|
959 |
+ } |
|
960 |
+ |
|
961 |
+ for (i = 0; i < FF_ARRAY_ELEMS(attr); i++) { |
|
962 |
+ if (attr[i].value == VA_ATTRIB_NOT_SUPPORTED) { |
|
963 |
+ // Unfortunately we have to treat this as "don't know" and hope |
|
964 |
+ // for the best, because the Intel MJPEG encoder returns this |
|
965 |
+ // for all the interesting attributes. |
|
966 |
+ continue; |
|
967 |
+ } |
|
968 |
+ switch (attr[i].type) { |
|
969 |
+ case VAConfigAttribRateControl: |
|
970 |
+ if (!(ctx->va_rc_mode & attr[i].value)) { |
|
971 |
+ av_log(avctx, AV_LOG_ERROR, "Rate control mode is not " |
|
972 |
+ "supported: %x\n", attr[i].value); |
|
973 |
+ err = AVERROR(EINVAL); |
|
974 |
+ goto fail; |
|
975 |
+ } |
|
976 |
+ break; |
|
977 |
+ case VAConfigAttribEncMaxRefFrames: |
|
978 |
+ { |
|
979 |
+ unsigned int ref_l0 = attr[i].value & 0xffff; |
|
980 |
+ unsigned int ref_l1 = (attr[i].value >> 16) & 0xffff; |
|
981 |
+ |
|
982 |
+ if (avctx->gop_size > 1 && ref_l0 < 1) { |
|
983 |
+ av_log(avctx, AV_LOG_ERROR, "P frames are not " |
|
984 |
+ "supported (%x).\n", attr[i].value); |
|
985 |
+ err = AVERROR(EINVAL); |
|
986 |
+ goto fail; |
|
987 |
+ } |
|
988 |
+ if (avctx->max_b_frames > 0 && ref_l1 < 1) { |
|
989 |
+ av_log(avctx, AV_LOG_ERROR, "B frames are not " |
|
990 |
+ "supported (%x).\n", attr[i].value); |
|
991 |
+ err = AVERROR(EINVAL); |
|
992 |
+ goto fail; |
|
993 |
+ } |
|
994 |
+ } |
|
995 |
+ break; |
|
996 |
+ } |
|
997 |
+ } |
|
998 |
+ |
|
999 |
+ err = 0; |
|
1000 |
+fail: |
|
1001 |
+ av_freep(&profiles); |
|
1002 |
+ av_freep(&entrypoints); |
|
1003 |
+ return err; |
|
1004 |
+} |
|
1005 |
+ |
|
890 | 1006 |
av_cold int ff_vaapi_encode_init(AVCodecContext *avctx, |
891 | 1007 |
const VAAPIEncodeType *type) |
892 | 1008 |
{ |
... | ... |
@@ -907,6 +1024,9 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx, |
907 | 907 |
ctx->codec = type; |
908 | 908 |
ctx->codec_options = ctx->codec_options_data; |
909 | 909 |
|
910 |
+ ctx->va_config = VA_INVALID_ID; |
|
911 |
+ ctx->va_context = VA_INVALID_ID; |
|
912 |
+ |
|
910 | 913 |
ctx->priv_data = av_mallocz(type->priv_data_size); |
911 | 914 |
if (!ctx->priv_data) { |
912 | 915 |
err = AVERROR(ENOMEM); |
... | ... |
@@ -932,6 +1052,10 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx, |
932 | 932 |
if (err < 0) |
933 | 933 |
goto fail; |
934 | 934 |
|
935 |
+ err = vaapi_encode_check_config(avctx); |
|
936 |
+ if (err < 0) |
|
937 |
+ goto fail; |
|
938 |
+ |
|
935 | 939 |
vas = vaCreateConfig(ctx->hwctx->display, |
936 | 940 |
ctx->va_profile, ctx->va_entrypoint, |
937 | 941 |
ctx->config_attributes, ctx->nb_config_attributes, |
... | ... |
@@ -1088,11 +1212,15 @@ av_cold int ff_vaapi_encode_close(AVCodecContext *avctx) |
1088 | 1088 |
vaapi_encode_free(avctx, pic); |
1089 | 1089 |
} |
1090 | 1090 |
|
1091 |
- if (ctx->va_context != VA_INVALID_ID) |
|
1091 |
+ if (ctx->va_context != VA_INVALID_ID) { |
|
1092 | 1092 |
vaDestroyContext(ctx->hwctx->display, ctx->va_context); |
1093 |
+ ctx->va_context = VA_INVALID_ID; |
|
1094 |
+ } |
|
1093 | 1095 |
|
1094 |
- if (ctx->va_config != VA_INVALID_ID) |
|
1096 |
+ if (ctx->va_config != VA_INVALID_ID) { |
|
1095 | 1097 |
vaDestroyConfig(ctx->hwctx->display, ctx->va_config); |
1098 |
+ ctx->va_config = VA_INVALID_ID; |
|
1099 |
+ } |
|
1096 | 1100 |
|
1097 | 1101 |
if (ctx->codec->close) |
1098 | 1102 |
ctx->codec->close(avctx); |