From dfe2b176487ee7937aec7ef3b9134ff7fa97dfa1 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Thu, 29 Aug 2024 22:22:46 +0200 Subject: Prepare for video codec query, cleanup readme, add libva-drm as dependency --- src/encoder/video/cuda.c | 19 +++++ src/encoder/video/software.c | 17 +++++ src/encoder/video/vaapi.c | 171 +++++++++++++++++++++++++++++++++++++++++++ src/encoder/video/video.c | 4 + 4 files changed, 211 insertions(+) (limited to 'src/encoder/video') diff --git a/src/encoder/video/cuda.c b/src/encoder/video/cuda.c index 4142e97..53abe78 100644 --- a/src/encoder/video/cuda.c +++ b/src/encoder/video/cuda.c @@ -122,6 +122,24 @@ static bool gsr_video_encoder_cuda_setup_textures(gsr_video_encoder_cuda *self, return true; } +static gsr_supported_video_codecs gsr_video_encoder_cuda_get_supported_codecs(gsr_video_encoder *encoder, bool cleanup) { + (void)encoder; + (void)cleanup; + //gsr_video_encoder_cuda *encoder_cuda = encoder->priv; + // TODO: Query support + return (gsr_supported_video_codecs) { + .h264 = true, + .hevc = true, + .hevc_hdr = true, + .hevc_10bit = true, + .av1 = true, + .av1_hdr = true, + .av1_10bit = true, + .vp8 = false, + .vp9 = false + }; +} + static void gsr_video_encoder_cuda_stop(gsr_video_encoder_cuda *self, AVCodecContext *video_codec_context); static bool gsr_video_encoder_cuda_start(gsr_video_encoder *encoder, AVCodecContext *video_codec_context, AVFrame *frame) { @@ -225,6 +243,7 @@ gsr_video_encoder* gsr_video_encoder_cuda_create(const gsr_video_encoder_cuda_pa encoder_cuda->params = *params; *encoder = (gsr_video_encoder) { + .get_supported_codecs = gsr_video_encoder_cuda_get_supported_codecs, .start = gsr_video_encoder_cuda_start, .copy_textures_to_frame = gsr_video_encoder_cuda_copy_textures_to_frame, .get_textures = gsr_video_encoder_cuda_get_textures, diff --git a/src/encoder/video/software.c b/src/encoder/video/software.c index 192be17..89b2cf0 100644 --- a/src/encoder/video/software.c +++ b/src/encoder/video/software.c @@ -58,6 +58,22 @@ static bool gsr_video_encoder_software_setup_textures(gsr_video_encoder_software return true; } +static gsr_supported_video_codecs gsr_video_encoder_software_get_supported_codecs(gsr_video_encoder *encoder, bool cleanup) { + (void)encoder; + (void)cleanup; + return (gsr_supported_video_codecs) { + .h264 = true, + .hevc = false, + .hevc_hdr = false, + .hevc_10bit = false, + .av1 = false, + .av1_hdr = false, + .av1_10bit = false, + .vp8 = false, + .vp9 = false + }; +} + static void gsr_video_encoder_software_stop(gsr_video_encoder_software *self, AVCodecContext *video_codec_context); static bool gsr_video_encoder_software_start(gsr_video_encoder *encoder, AVCodecContext *video_codec_context, AVFrame *frame) { @@ -126,6 +142,7 @@ gsr_video_encoder* gsr_video_encoder_software_create(const gsr_video_encoder_sof encoder_software->params = *params; *encoder = (gsr_video_encoder) { + .get_supported_codecs = gsr_video_encoder_software_get_supported_codecs, .start = gsr_video_encoder_software_start, .copy_textures_to_frame = gsr_video_encoder_software_copy_textures_to_frame, .get_textures = gsr_video_encoder_software_get_textures, 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 #include +#include #include #include +#include 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, diff --git a/src/encoder/video/video.c b/src/encoder/video/video.c index 9b0def0..daaf537 100644 --- a/src/encoder/video/video.c +++ b/src/encoder/video/video.c @@ -1,6 +1,10 @@ #include "../../../include/encoder/video/video.h" #include +gsr_supported_video_codecs gsr_video_encoder_get_supported_codecs(gsr_video_encoder *encoder, bool cleanup) { + return encoder->get_supported_codecs(encoder, cleanup); +} + bool gsr_video_encoder_start(gsr_video_encoder *encoder, AVCodecContext *video_codec_context, AVFrame *frame) { assert(!encoder->started); bool res = encoder->start(encoder, video_codec_context, frame); -- cgit v1.2.3