aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/encoder
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2025-10-05 12:54:53 +0200
committerdec05eba <dec05eba@protonmail.com>2025-10-05 12:57:58 +0200
commitf9f0074f293abdc60a8ec18648962a85c2f4145a (patch)
tree836d12533bf07cf6bea9eba90ac6b6199798e903 /src/encoder
parent50fbee2b2f1eda89145869d7d5fa67f27c084b73 (diff)
Update for ffmpeg 8: remove hevc vaapi padding (black bars), fix garbage output (workaround ffmpeg 8 issue)
Diffstat (limited to 'src/encoder')
-rw-r--r--src/encoder/video/vaapi.c95
1 files changed, 92 insertions, 3 deletions
diff --git a/src/encoder/video/vaapi.c b/src/encoder/video/vaapi.c
index 9cf4def..f9b39be 100644
--- a/src/encoder/video/vaapi.c
+++ b/src/encoder/video/vaapi.c
@@ -6,6 +6,8 @@
#include <libavutil/hwcontext_vaapi.h>
#include <libavutil/intreadwrite.h>
+#include <va/va.h>
+#include <va/va_drm.h>
#include <va/va_drmcommon.h>
#include <stdlib.h>
@@ -150,13 +152,100 @@ static bool gsr_video_encoder_vaapi_setup_textures(gsr_video_encoder_vaapi *self
static void gsr_video_encoder_vaapi_stop(gsr_video_encoder_vaapi *self, AVCodecContext *video_codec_context);
+static bool supports_hevc_without_padding(const char *card_path) {
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(61, 28, 100) && VA_CHECK_VERSION(1, 21, 0)
+ VAStatus va_status;
+ VAConfigID va_config = 0;
+ unsigned int num_surface_attr = 0;
+ VASurfaceAttrib *surface_attr_list = NULL;
+ bool supports_surface_attrib_alignment_size = false;
+ int va_major = 0;
+ int va_minor = 0;
+ bool initialized = false;
+
+ char render_path[128];
+ if(!gsr_card_path_get_render_path(card_path, render_path)) {
+ fprintf(stderr, "gsr error: supports_hevc_without_padding: failed to get /dev/dri/renderDXXX file from %s\n", card_path);
+ return false;
+ }
+
+ const int drm_fd = open(render_path, O_RDWR);
+ if(drm_fd == -1) {
+ fprintf(stderr, "gsr error: supports_hevc_without_padding: failed to open device %s\n", render_path);
+ return false;
+ }
+
+ const VADisplay va_dpy = vaGetDisplayDRM(drm_fd);
+ if(!va_dpy) {
+ fprintf(stderr, "gsr error: supports_hevc_without_padding: failed to get vaapi display for device %s\n", render_path);
+ goto done;
+ }
+
+ if(vaInitialize(va_dpy, &va_major, &va_minor) != VA_STATUS_SUCCESS) {
+ fprintf(stderr, "gsr error: supports_hevc_without_padding: vaInitialize failed\n");
+ goto done;
+ }
+ initialized = true;
+
+ va_status = vaCreateConfig(va_dpy, VAProfileHEVCMain, VAEntrypointEncSlice, NULL, 0, &va_config);
+ if(va_status != VA_STATUS_SUCCESS) {
+ va_status = vaCreateConfig(va_dpy, VAProfileHEVCMain, VAEntrypointEncSliceLP, NULL, 0, &va_config);
+ if(va_status != VA_STATUS_SUCCESS) {
+ fprintf(stderr, "gsr error: supports_hevc_without_padding: failed to create hevc vaapi config, error: %s (%d)\n", vaErrorStr(va_status), va_status);
+ return false;
+ }
+ }
+
+ va_status = vaQuerySurfaceAttributes(va_dpy, va_config, 0, &num_surface_attr);
+ if(va_status != VA_STATUS_SUCCESS) {
+ fprintf(stderr, "gsr error: supports_hevc_without_padding: failed to query vaapi surface attributes size, error: %s (%d)\n", vaErrorStr(va_status), va_status);
+ goto done;
+ }
+
+ surface_attr_list = malloc(num_surface_attr * sizeof(VASurfaceAttrib));
+ if(!surface_attr_list) {
+ fprintf(stderr, "gsr error: supports_hevc_without_padding: failed to allocate memory for %u vaapi surface attributes, error: %s (%d)\n", num_surface_attr, vaErrorStr(va_status), va_status);
+ goto done;
+ }
+
+ va_status = vaQuerySurfaceAttributes(va_dpy, va_config, surface_attr_list, &num_surface_attr);
+ if(va_status != VA_STATUS_SUCCESS) {
+ fprintf(stderr, "gsr error: supports_hevc_without_padding: failed to query vaapi surface attributes data, error: %s (%d)\n", vaErrorStr(va_status), va_status);
+ goto done;
+ }
+
+ for(unsigned int i = 0; i < num_surface_attr; ++i) {
+ if(surface_attr_list[i].type == VASurfaceAttribAlignmentSize) {
+ supports_surface_attrib_alignment_size = true;
+ break;
+ }
+ }
+
+ done:
+ free(surface_attr_list);
+ if(va_config > 0)
+ vaDestroyConfig(va_dpy, va_config);
+ if(initialized)
+ vaTerminate(va_dpy);
+ if(drm_fd > 0)
+ close(drm_fd);
+ return supports_surface_attrib_alignment_size;
+#else
+ return false;
+#endif
+}
+
static bool gsr_video_encoder_vaapi_start(gsr_video_encoder *encoder, AVCodecContext *video_codec_context, AVFrame *frame) {
gsr_video_encoder_vaapi *self = encoder->priv;
if(self->params.egl->gpu_info.vendor == GSR_GPU_VENDOR_AMD && video_codec_context->codec_id == AV_CODEC_ID_HEVC) {
- // TODO: dont do this if using ffmpeg reports that this is not needed (AMD driver bug that was fixed recently)
- video_codec_context->width = FFALIGN(video_codec_context->width, 64);
- video_codec_context->height = FFALIGN(video_codec_context->height, 16);
+ if(supports_hevc_without_padding(self->params.egl->card_path)) {
+ video_codec_context->width = FFALIGN(video_codec_context->width, 2);
+ video_codec_context->height = FFALIGN(video_codec_context->height, 2);
+ } else {
+ video_codec_context->width = FFALIGN(video_codec_context->width, 64);
+ video_codec_context->height = FFALIGN(video_codec_context->height, 16);
+ }
} else if(self->params.egl->gpu_info.vendor == GSR_GPU_VENDOR_AMD && video_codec_context->codec_id == AV_CODEC_ID_AV1) {
// TODO: Dont do this for VCN 5 and forward which should fix this hardware bug
video_codec_context->width = FFALIGN(video_codec_context->width, 64);