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 + src/main.cpp | 102 +++++++++++++++++--------- 5 files changed, 277 insertions(+), 36 deletions(-) (limited to 'src') 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); diff --git a/src/main.cpp b/src/main.cpp index 88eb536..20b3e85 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1686,6 +1686,39 @@ static int init_filter_graph(AVCodecContext *audio_codec_context, AVFilterGraph return 0; } +static gsr_video_encoder* create_video_encoder(gsr_egl *egl, bool overclock, gsr_color_depth color_depth, bool use_software_video_encoder) { + gsr_video_encoder *video_encoder = nullptr; + + if(use_software_video_encoder) { + gsr_video_encoder_software_params params; + params.egl = egl; + params.color_depth = color_depth; + video_encoder = gsr_video_encoder_software_create(¶ms); + return video_encoder; + } + + switch(egl->gpu_info.vendor) { + case GSR_GPU_VENDOR_AMD: + case GSR_GPU_VENDOR_INTEL: { + gsr_video_encoder_vaapi_params params; + params.egl = egl; + params.color_depth = color_depth; + video_encoder = gsr_video_encoder_vaapi_create(¶ms); + break; + } + case GSR_GPU_VENDOR_NVIDIA: { + gsr_video_encoder_cuda_params params; + params.egl = egl; + params.overclock = overclock; + params.color_depth = color_depth; + video_encoder = gsr_video_encoder_cuda_create(¶ms); + break; + } + } + + return video_encoder; +} + static void xwayland_check_callback(const gsr_monitor *monitor, void *userdata) { bool *xwayland_found = (bool*)userdata; if(monitor->name_len >= 8 && strncmp(monitor->name, "XWAYLAND", 8) == 0) @@ -1735,6 +1768,7 @@ static void list_gpu_info(gsr_egl *egl) { } static void list_supported_video_codecs(gsr_egl *egl, bool wayland) { +#if 1 if(find_h264_encoder(egl->gpu_info.vendor, egl->card_path)) puts("h264"); if(find_h264_software_encoder()) @@ -1755,6 +1789,34 @@ static void list_supported_video_codecs(gsr_egl *egl, bool wayland) { puts("vp8"); if(find_vp9_encoder(egl->gpu_info.vendor, egl->card_path)) puts("vp9"); +#else + // Dont clean it up on purpose to increase shutdown speed + gsr_video_encoder *video_encoder = create_video_encoder(egl, false, GSR_COLOR_DEPTH_8_BITS, false); + if(!video_encoder) + return; + + const gsr_supported_video_codecs supported_video_codecs = gsr_video_encoder_get_supported_codecs(video_encoder, false); + if(supported_video_codecs.h264) + puts("h264"); + if(find_h264_software_encoder()) + puts("h264_software"); + if(supported_video_codecs.hevc) { + puts("hevc"); + if(wayland) + puts("hevc_hdr"); // TODO: Verify if it's actually supported + puts("hevc_10bit"); // TODO: Verify if it's actually supported + } + if(supported_video_codecs.av1) { + puts("av1"); + if(wayland) + puts("av1_hdr"); // TODO: Verify if it's actually supported + puts("av1_10bit"); // TODO: Verify if it's actually supported + } + if(supported_video_codecs.vp8) + puts("vp8"); + if(supported_video_codecs.vp9) + puts("vp9"); +#endif } static bool monitor_capture_use_drm(gsr_egl *egl, bool wayland) { @@ -1870,9 +1932,10 @@ static void info_command() { fflush(stdout); - gsr_egl_unload(&egl); - if(dpy) - XCloseDisplay(dpy); + // Not needed as this will just slow down shutdown + //gsr_egl_unload(&egl); + //if(dpy) + // XCloseDisplay(dpy); _exit(0); } @@ -2066,39 +2129,6 @@ static gsr_capture* create_capture_impl(const char *window_str, const char *scre return capture; } -static gsr_video_encoder* create_video_encoder(gsr_egl *egl, bool overclock, gsr_color_depth color_depth, bool use_software_video_encoder) { - gsr_video_encoder *video_encoder = nullptr; - - if(use_software_video_encoder) { - gsr_video_encoder_software_params params; - params.egl = egl; - params.color_depth = color_depth; - video_encoder = gsr_video_encoder_software_create(¶ms); - return video_encoder; - } - - switch(egl->gpu_info.vendor) { - case GSR_GPU_VENDOR_AMD: - case GSR_GPU_VENDOR_INTEL: { - gsr_video_encoder_vaapi_params params; - params.egl = egl; - params.color_depth = color_depth; - video_encoder = gsr_video_encoder_vaapi_create(¶ms); - break; - } - case GSR_GPU_VENDOR_NVIDIA: { - gsr_video_encoder_cuda_params params; - params.egl = egl; - params.overclock = overclock; - params.color_depth = color_depth; - video_encoder = gsr_video_encoder_cuda_create(¶ms); - break; - } - } - - return video_encoder; -} - static AVPixelFormat get_pixel_format(gsr_gpu_vendor vendor, bool use_software_video_encoder) { if(use_software_video_encoder) { return AV_PIX_FMT_NV12; -- cgit v1.2.3