aboutsummaryrefslogtreecommitdiff
path: root/src/encoder/video/vaapi.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/encoder/video/vaapi.c')
-rw-r--r--src/encoder/video/vaapi.c171
1 files changed, 171 insertions, 0 deletions
diff --git a/src/encoder/video/vaapi.c b/src/encoder/video/vaapi.c
index 9470e76..2185ebc 100644
--- a/src/encoder/video/vaapi.c
+++ b/src/encoder/video/vaapi.c
@@ -6,9 +6,11 @@
#include <libavutil/hwcontext_vaapi.h>
#include <va/va_drmcommon.h>
+#include <va/va_drm.h>
#include <stdlib.h>
#include <unistd.h>
+#include <fcntl.h>
typedef struct {
gsr_video_encoder_vaapi_params params;
@@ -147,6 +149,174 @@ static bool gsr_video_encoder_vaapi_setup_textures(gsr_video_encoder_vaapi *self
}
}
+static bool profile_is_h264(VAProfile profile) {
+ switch(profile) {
+ case 5: // VAProfileH264Baseline
+ case VAProfileH264Main:
+ case VAProfileH264High:
+ case VAProfileH264ConstrainedBaseline:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool profile_is_hevc_8bit(VAProfile profile) {
+ switch(profile) {
+ case VAProfileHEVCMain:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool profile_is_hevc_10bit(VAProfile profile) {
+ switch(profile) {
+ case VAProfileHEVCMain10:
+ //case VAProfileHEVCMain12:
+ //case VAProfileHEVCMain422_10:
+ //case VAProfileHEVCMain422_12:
+ //case VAProfileHEVCMain444:
+ //case VAProfileHEVCMain444_10:
+ //case VAProfileHEVCMain444_12:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool profile_is_av1(VAProfile profile) {
+ switch(profile) {
+ case VAProfileAV1Profile0:
+ case VAProfileAV1Profile1:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool profile_is_vp8(VAProfile profile) {
+ switch(profile) {
+ case VAProfileVP8Version0_3:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool profile_is_vp9(VAProfile profile) {
+ switch(profile) {
+ case VAProfileVP9Profile0:
+ case VAProfileVP9Profile1:
+ case VAProfileVP9Profile2:
+ case VAProfileVP9Profile3:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool profile_supports_video_encoding(VADisplay va_dpy, VAProfile profile) {
+ int num_entrypoints = vaMaxNumEntrypoints(va_dpy);
+ if(num_entrypoints <= 0)
+ return false;
+
+ VAEntrypoint *entrypoint_list = calloc(num_entrypoints, sizeof(VAEntrypoint));
+ if(!entrypoint_list)
+ return false;
+
+ bool supported = false;
+ if(vaQueryConfigEntrypoints(va_dpy, profile, entrypoint_list, &num_entrypoints) == VA_STATUS_SUCCESS) {
+ for(int i = 0; i < num_entrypoints; ++i) {
+ if(entrypoint_list[i] == VAEntrypointEncSlice) {
+ supported = true;
+ break;
+ }
+ }
+ }
+
+ free(entrypoint_list);
+ return supported;
+}
+
+static bool get_supported_video_codecs(VADisplay va_dpy, gsr_supported_video_codecs *video_codecs, bool cleanup) {
+ *video_codecs = (gsr_supported_video_codecs){0};
+ bool success = false;
+ VAProfile *profile_list = NULL;
+
+ int va_major = 0;
+ int va_minor = 0;
+ if(vaInitialize(va_dpy, &va_major, &va_minor) != VA_STATUS_SUCCESS)
+ return false;
+
+ int num_profiles = vaMaxNumProfiles(va_dpy);
+ if(num_profiles <= 0)
+ goto done;
+
+ profile_list = calloc(num_profiles, sizeof(VAProfile));
+ if(!profile_list || vaQueryConfigProfiles(va_dpy, profile_list, &num_profiles) != VA_STATUS_SUCCESS)
+ goto done;
+
+ for(int i = 0; i < num_profiles; ++i) {
+ if(profile_is_h264(profile_list[i])) {
+ if(profile_supports_video_encoding(va_dpy, profile_list[i]))
+ video_codecs->h264 = true;
+ } else if(profile_is_hevc_8bit(profile_list[i])) {
+ if(profile_supports_video_encoding(va_dpy, profile_list[i]))
+ video_codecs->hevc = true;
+ } else if(profile_is_hevc_10bit(profile_list[i])) {
+ if(profile_supports_video_encoding(va_dpy, profile_list[i])) {
+ video_codecs->hevc_hdr = true;
+ video_codecs->hevc_10bit = true;
+ }
+ } else if(profile_is_av1(profile_list[i])) {
+ if(profile_supports_video_encoding(va_dpy, profile_list[i])) {
+ video_codecs->av1 = true;
+ video_codecs->av1_hdr = true;
+ video_codecs->av1_10bit = true;
+ }
+ } else if(profile_is_vp8(profile_list[i])) {
+ if(profile_supports_video_encoding(va_dpy, profile_list[i]))
+ video_codecs->vp8 = true;
+ } else if(profile_is_vp9(profile_list[i])) {
+ if(profile_supports_video_encoding(va_dpy, profile_list[i]))
+ video_codecs->vp9 = true;
+ }
+ }
+
+ success = true;
+ done:
+ if(profile_list)
+ free(profile_list);
+
+ if(cleanup)
+ vaTerminate(va_dpy);
+
+ return success;
+}
+
+static gsr_supported_video_codecs gsr_video_encoder_vaapi_get_supported_codecs(gsr_video_encoder *encoder, bool cleanup) {
+ gsr_video_encoder_vaapi *encoder_vaapi = encoder->priv;
+ gsr_supported_video_codecs supported_video_codecs = {0};
+
+ const int drm_fd = open(encoder_vaapi->params.egl->card_path, O_RDWR);
+ if(drm_fd == -1) {
+ fprintf(stderr, "gsr error: gsr_video_encoder_vaapi_get_supported_codecs: failed to open device %s\n", encoder_vaapi->params.egl->card_path);
+ return supported_video_codecs;
+ }
+
+ VADisplay va_dpy = vaGetDisplayDRM(drm_fd);
+ if(va_dpy) {
+ if(!get_supported_video_codecs(va_dpy, &supported_video_codecs, cleanup))
+ fprintf(stderr, "gsr error: gsr_video_encoder_vaapi_get_supported_codecs: failed to query supported video codecs for device %s\n", encoder_vaapi->params.egl->card_path);
+ }
+
+ if(cleanup)
+ close(drm_fd);
+
+ return supported_video_codecs;
+}
+
static void gsr_video_encoder_vaapi_stop(gsr_video_encoder_vaapi *self, AVCodecContext *video_codec_context);
static bool gsr_video_encoder_vaapi_start(gsr_video_encoder *encoder, AVCodecContext *video_codec_context, AVFrame *frame) {
@@ -234,6 +404,7 @@ gsr_video_encoder* gsr_video_encoder_vaapi_create(const gsr_video_encoder_vaapi_
encoder_vaapi->params = *params;
*encoder = (gsr_video_encoder) {
+ .get_supported_codecs = gsr_video_encoder_vaapi_get_supported_codecs,
.start = gsr_video_encoder_vaapi_start,
.copy_textures_to_frame = NULL,
.get_textures = gsr_video_encoder_vaapi_get_textures,