diff options
Diffstat (limited to 'src/encoder/video')
| -rw-r--r-- | src/encoder/video/nvenc.c | 20 | ||||
| -rw-r--r-- | src/encoder/video/software.c | 7 | ||||
| -rw-r--r-- | src/encoder/video/vaapi.c | 40 | ||||
| -rw-r--r-- | src/encoder/video/vulkan.c | 69 |
4 files changed, 82 insertions, 54 deletions
diff --git a/src/encoder/video/nvenc.c b/src/encoder/video/nvenc.c index dd877c5..594416c 100644 --- a/src/encoder/video/nvenc.c +++ b/src/encoder/video/nvenc.c @@ -1,4 +1,5 @@ #include "../../../include/encoder/video/nvenc.h" +#include "../../../include/log.h" #include "../../../include/egl.h" #include "../../../include/cuda.h" #include "../../../include/utils.h" @@ -25,7 +26,7 @@ typedef struct { static bool gsr_video_encoder_nvenc_setup_context(gsr_video_encoder_nvenc *self, AVCodecContext *video_codec_context) { self->device_ctx = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_CUDA); if(!self->device_ctx) { - fprintf(stderr, "gsr error: gsr_video_encoder_nvenc_setup_context failed: failed to create hardware device context\n"); + gsr_log(GSR_LOG_LEVEL_ERROR, "gsr_video_encoder_nvenc_setup_context failed: failed to create hardware device context"); return false; } @@ -33,14 +34,14 @@ static bool gsr_video_encoder_nvenc_setup_context(gsr_video_encoder_nvenc *self, AVCUDADeviceContext *cuda_device_context = (AVCUDADeviceContext*)hw_device_context->hwctx; cuda_device_context->cuda_ctx = self->cuda.cu_ctx; if(av_hwdevice_ctx_init(self->device_ctx) < 0) { - fprintf(stderr, "gsr error: gsr_video_encoder_nvenc_setup_context failed: failed to create hardware device context\n"); + gsr_log(GSR_LOG_LEVEL_ERROR, "gsr_video_encoder_nvenc_setup_context failed: failed to create hardware device context"); av_buffer_unref(&self->device_ctx); return false; } AVBufferRef *frame_context = av_hwframe_ctx_alloc(self->device_ctx); if(!frame_context) { - fprintf(stderr, "gsr error: gsr_video_encoder_nvenc_setup_context failed: failed to create hwframe context\n"); + gsr_log(GSR_LOG_LEVEL_ERROR, "gsr_video_encoder_nvenc_setup_context failed: failed to create hwframe context"); av_buffer_unref(&self->device_ctx); return false; } @@ -53,8 +54,7 @@ static bool gsr_video_encoder_nvenc_setup_context(gsr_video_encoder_nvenc *self, hw_frame_context->device_ctx = (AVHWDeviceContext*)self->device_ctx->data; if (av_hwframe_ctx_init(frame_context) < 0) { - fprintf(stderr, "gsr error: gsr_video_encoder_nvenc_setup_context failed: failed to initialize hardware frame context " - "(note: ffmpeg version needs to be > 4.0)\n"); + gsr_log(GSR_LOG_LEVEL_ERROR, "gsr_video_encoder_nvenc_setup_context failed: failed to initialize hardware frame context (note: ffmpeg version needs to be > 4.0)"); av_buffer_unref(&self->device_ctx); //av_buffer_unref(&frame_context); return false; @@ -72,7 +72,7 @@ static bool cuda_register_opengl_texture(gsr_cuda *cuda, CUgraphicsResource *cud if (res != CUDA_SUCCESS) { const char *err_str = "unknown"; cuda->cuGetErrorString(res, &err_str); - fprintf(stderr, "gsr error: cuda_register_opengl_texture: cuGraphicsGLRegisterImage failed, error: %s, texture " "id: %u\n", err_str, texture_id); + gsr_log(GSR_LOG_LEVEL_ERROR, "cuda_register_opengl_texture: cuGraphicsGLRegisterImage failed, error: %s, texture id: %u", err_str, texture_id); return false; } @@ -86,7 +86,7 @@ static bool cuda_register_opengl_texture(gsr_cuda *cuda, CUgraphicsResource *cud static bool gsr_video_encoder_nvenc_setup_textures(gsr_video_encoder_nvenc *self, AVCodecContext *video_codec_context, AVFrame *frame) { const int res = av_hwframe_get_buffer(video_codec_context->hw_frames_ctx, frame, 0); if(res < 0) { - fprintf(stderr, "gsr error: gsr_video_encoder_nvenc_setup_textures: av_hwframe_get_buffer failed: %d\n", res); + gsr_log(GSR_LOG_LEVEL_ERROR, "gsr_video_encoder_nvenc_setup_textures: av_hwframe_get_buffer failed: %d", res); return false; } @@ -99,7 +99,7 @@ static bool gsr_video_encoder_nvenc_setup_textures(gsr_video_encoder_nvenc *self self->target_texture_size[i] = (vec2i){ video_codec_context->width / div[i], video_codec_context->height / div[i] }; self->target_textures[i] = gl_create_texture(self->params.egl, self->target_texture_size[i].x, self->target_texture_size[i].y, self->params.color_depth == GSR_COLOR_DEPTH_8_BITS ? internal_formats_nv12[i] : internal_formats_p010[i], formats[i], GL_NEAREST); if(self->target_textures[i] == 0) { - fprintf(stderr, "gsr error: gsr_video_encoder_nvenc_setup_textures: failed to create opengl texture\n"); + gsr_log(GSR_LOG_LEVEL_ERROR, "gsr_video_encoder_nvenc_setup_textures: failed to create opengl texture"); return false; } @@ -117,7 +117,7 @@ static bool gsr_video_encoder_nvenc_start(gsr_video_encoder *encoder, AVCodecCon gsr_video_encoder_nvenc *self = encoder->priv; if(!gsr_cuda_load(&self->cuda)) { - fprintf(stderr, "gsr error: gsr_video_encoder_nvenc_start: failed to load cuda\n"); + gsr_log(GSR_LOG_LEVEL_ERROR, "gsr_video_encoder_nvenc_start: failed to load cuda"); gsr_video_encoder_nvenc_stop(self, video_codec_context); return false; } @@ -152,7 +152,7 @@ void gsr_video_encoder_nvenc_stop(gsr_video_encoder_nvenc *self, AVCodecContext self->target_textures[0] = 0; self->target_textures[1] = 0; - if(video_codec_context->hw_frames_ctx) + if(video_codec_context && video_codec_context->hw_frames_ctx) av_buffer_unref(&video_codec_context->hw_frames_ctx); if(self->device_ctx) av_buffer_unref(&self->device_ctx); diff --git a/src/encoder/video/software.c b/src/encoder/video/software.c index b473bb9..5ee3ab9 100644 --- a/src/encoder/video/software.c +++ b/src/encoder/video/software.c @@ -1,4 +1,5 @@ #include "../../../include/encoder/video/software.h" +#include "../../../include/log.h" #include "../../../include/egl.h" #include "../../../include/utils.h" @@ -19,13 +20,13 @@ typedef struct { static bool gsr_video_encoder_software_setup_textures(gsr_video_encoder_software *self, AVCodecContext *video_codec_context, AVFrame *frame) { int res = av_frame_get_buffer(frame, LINESIZE_ALIGNMENT); if(res < 0) { - fprintf(stderr, "gsr error: gsr_video_encoder_software_setup_textures: av_frame_get_buffer failed: %d\n", res); + gsr_log(GSR_LOG_LEVEL_ERROR, "gsr_video_encoder_software_setup_textures: av_frame_get_buffer failed: %d", res); return false; } res = av_frame_make_writable(frame); if(res < 0) { - fprintf(stderr, "gsr error: gsr_video_encoder_software_setup_textures: av_frame_make_writable failed: %d\n", res); + gsr_log(GSR_LOG_LEVEL_ERROR, "gsr_video_encoder_software_setup_textures: av_frame_make_writable failed: %d", res); return false; } @@ -38,7 +39,7 @@ static bool gsr_video_encoder_software_setup_textures(gsr_video_encoder_software self->texture_sizes[i] = (vec2i){ video_codec_context->width / div[i], video_codec_context->height / div[i] }; self->target_textures[i] = gl_create_texture(self->params.egl, self->texture_sizes[i].x, self->texture_sizes[i].y, self->params.color_depth == GSR_COLOR_DEPTH_8_BITS ? internal_formats_nv12[i] : internal_formats_p010[i], formats[i], GL_NEAREST); if(self->target_textures[i] == 0) { - fprintf(stderr, "gsr error: gsr_capture_kms_setup_cuda_textures: failed to create opengl texture\n"); + gsr_log(GSR_LOG_LEVEL_ERROR, "gsr_capture_kms_setup_cuda_textures: failed to create opengl texture"); return false; } } diff --git a/src/encoder/video/vaapi.c b/src/encoder/video/vaapi.c index 449fb1d..12dd3d7 100644 --- a/src/encoder/video/vaapi.c +++ b/src/encoder/video/vaapi.c @@ -1,4 +1,5 @@ #include "../../../include/encoder/video/vaapi.h" +#include "../../../include/log.h" #include "../../../include/utils.h" #include "../../../include/egl.h" @@ -28,18 +29,18 @@ typedef struct { static bool gsr_video_encoder_vaapi_setup_context(gsr_video_encoder_vaapi *self, AVCodecContext *video_codec_context) { char render_path[128]; if(!gsr_card_path_get_render_path(self->params.egl->card_path, render_path)) { - fprintf(stderr, "gsr error: gsr_video_encoder_vaapi_setup_context: failed to get /dev/dri/renderDXXX file from %s\n", self->params.egl->card_path); + gsr_log(GSR_LOG_LEVEL_ERROR, "gsr_video_encoder_vaapi_setup_context: failed to get /dev/dri/renderDXXX file from %s", self->params.egl->card_path); return false; } if(av_hwdevice_ctx_create(&self->device_ctx, AV_HWDEVICE_TYPE_VAAPI, render_path, NULL, 0) < 0) { - fprintf(stderr, "gsr error: gsr_video_encoder_vaapi_setup_context: failed to create hardware device context\n"); + gsr_log(GSR_LOG_LEVEL_ERROR, "gsr_video_encoder_vaapi_setup_context: failed to create hardware device context"); return false; } AVBufferRef *frame_context = av_hwframe_ctx_alloc(self->device_ctx); if(!frame_context) { - fprintf(stderr, "gsr error: gsr_video_encoder_vaapi_setup_context: failed to create hwframe context\n"); + gsr_log(GSR_LOG_LEVEL_ERROR, "gsr_video_encoder_vaapi_setup_context: failed to create hwframe context"); av_buffer_unref(&self->device_ctx); return false; } @@ -57,8 +58,7 @@ static bool gsr_video_encoder_vaapi_setup_context(gsr_video_encoder_vaapi *self, self->va_dpy = vactx->display; if (av_hwframe_ctx_init(frame_context) < 0) { - fprintf(stderr, "gsr error: gsr_video_encoder_vaapi_setup_context: failed to initialize hardware frame context " - "(note: ffmpeg version needs to be > 4.0)\n"); + gsr_log(GSR_LOG_LEVEL_ERROR, "gsr_video_encoder_vaapi_setup_context: failed to initialize hardware frame context (note: ffmpeg version needs to be > 4.0)"); av_buffer_unref(&self->device_ctx); //av_buffer_unref(&frame_context); return false; @@ -76,7 +76,7 @@ static uint32_t fourcc(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { static bool gsr_video_encoder_vaapi_setup_textures(gsr_video_encoder_vaapi *self, AVCodecContext *video_codec_context, AVFrame *frame) { const int res = av_hwframe_get_buffer(video_codec_context->hw_frames_ctx, frame, 0); if(res < 0) { - fprintf(stderr, "gsr error: gsr_video_encoder_vaapi_setup_textures: av_hwframe_get_buffer failed: %d\n", res); + gsr_log(GSR_LOG_LEVEL_ERROR, "gsr_video_encoder_vaapi_setup_textures: av_hwframe_get_buffer failed: %d", res); return false; } @@ -84,7 +84,7 @@ static bool gsr_video_encoder_vaapi_setup_textures(gsr_video_encoder_vaapi *self VAStatus va_status = vaExportSurfaceHandle(self->va_dpy, target_surface_id, VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2, VA_EXPORT_SURFACE_WRITE_ONLY | VA_EXPORT_SURFACE_SEPARATE_LAYERS, &self->prime); if(va_status != VA_STATUS_SUCCESS) { - fprintf(stderr, "gsr error: gsr_video_encoder_vaapi_setup_textures: vaExportSurfaceHandle failed, error: %d\n", va_status); + gsr_log(GSR_LOG_LEVEL_ERROR, "gsr_video_encoder_vaapi_setup_textures: vaExportSurfaceHandle failed, error: %d", va_status); return false; } vaSyncSurface(self->va_dpy, target_surface_id); @@ -120,7 +120,7 @@ static bool gsr_video_encoder_vaapi_setup_textures(gsr_video_encoder_vaapi *self while(self->params.egl->eglGetError() != EGL_SUCCESS){} EGLImage image = self->params.egl->eglCreateImage(self->params.egl->egl_display, 0, EGL_LINUX_DMA_BUF_EXT, NULL, img_attr); if(!image) { - fprintf(stderr, "gsr error: gsr_video_encoder_vaapi_setup_textures: failed to create egl image from drm fd for output drm fd, error: %d\n", self->params.egl->eglGetError()); + gsr_log(GSR_LOG_LEVEL_ERROR, "gsr_video_encoder_vaapi_setup_textures: failed to create egl image from drm fd for output drm fd, error: %d", self->params.egl->eglGetError()); return false; } @@ -133,7 +133,7 @@ static bool gsr_video_encoder_vaapi_setup_textures(gsr_video_encoder_vaapi *self self->params.egl->glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); if(self->params.egl->glGetError() != 0 || self->params.egl->eglGetError() != EGL_SUCCESS) { // TODO: Get the error properly - fprintf(stderr, "gsr error: gsr_video_encoder_vaapi_setup_textures: failed to bind egl image to gl texture, error: %d\n", self->params.egl->eglGetError()); + gsr_log(GSR_LOG_LEVEL_ERROR, "gsr_video_encoder_vaapi_setup_textures: failed to bind egl image to gl texture, error: %d", self->params.egl->eglGetError()); self->params.egl->eglDestroyImage(self->params.egl->egl_display, image); self->params.egl->glBindTexture(GL_TEXTURE_2D, 0); return false; @@ -145,7 +145,7 @@ static bool gsr_video_encoder_vaapi_setup_textures(gsr_video_encoder_vaapi *self return true; } else { - fprintf(stderr, "gsr error: gsr_video_encoder_vaapi_setup_textures: unexpected fourcc %u for output drm fd, expected nv12 or p010\n", self->prime.fourcc); + gsr_log(GSR_LOG_LEVEL_ERROR, "gsr_video_encoder_vaapi_setup_textures: unexpected fourcc %u for output drm fd, expected nv12 or p010", self->prime.fourcc); return false; } } @@ -165,26 +165,26 @@ static bool supports_hevc_without_padding(const char *card_path) { 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); + gsr_log(GSR_LOG_LEVEL_ERROR, "supports_hevc_without_padding: failed to get /dev/dri/renderDXXX file from %s", 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); + gsr_log(GSR_LOG_LEVEL_ERROR, "supports_hevc_without_padding: failed to open device %s", 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); + gsr_log(GSR_LOG_LEVEL_ERROR, "supports_hevc_without_padding: failed to get vaapi display for device %s", render_path); goto done; } vaSetInfoCallback(va_dpy, NULL, NULL); if(vaInitialize(va_dpy, &va_major, &va_minor) != VA_STATUS_SUCCESS) { - fprintf(stderr, "gsr error: supports_hevc_without_padding: vaInitialize failed\n"); + gsr_log(GSR_LOG_LEVEL_ERROR, "supports_hevc_without_padding: vaInitialize failed"); goto done; } initialized = true; @@ -193,26 +193,26 @@ static bool supports_hevc_without_padding(const char *card_path) { 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); + gsr_log(GSR_LOG_LEVEL_ERROR, "supports_hevc_without_padding: failed to create hevc vaapi config, error: %s (%d)", 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); + gsr_log(GSR_LOG_LEVEL_ERROR, "supports_hevc_without_padding: failed to query vaapi surface attributes size, error: %s (%d)", 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); + gsr_log(GSR_LOG_LEVEL_ERROR, "supports_hevc_without_padding: failed to allocate memory for %u vaapi surface attributes, error: %s (%d)", 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); + gsr_log(GSR_LOG_LEVEL_ERROR, "supports_hevc_without_padding: failed to query vaapi surface attributes data, error: %s (%d)", vaErrorStr(va_status), va_status); goto done; } @@ -264,7 +264,7 @@ static bool gsr_video_encoder_vaapi_start(gsr_video_encoder *encoder, AVCodecCon } if(FFALIGN(video_codec_context->width, 2) != FFALIGN(frame->width, 2) || FFALIGN(video_codec_context->height, 2) != FFALIGN(frame->height, 2)) { - fprintf(stderr, "gsr warning: gsr_video_encoder_vaapi_start: black bars have been added to the video because of a bug in AMD drivers/hardware. Record with h264/hevc codec instead (-k h264) to get around this issue\n"); + gsr_log(GSR_LOG_LEVEL_WARNING, "gsr_video_encoder_vaapi_start: black bars have been added to the video because of a bug in AMD drivers/hardware. Record with h264/hevc codec instead (-k h264) to get around this issue"); } if(video_codec_context->width < 128) @@ -294,7 +294,7 @@ void gsr_video_encoder_vaapi_stop(gsr_video_encoder_vaapi *self, AVCodecContext self->target_textures[0] = 0; self->target_textures[1] = 0; - if(video_codec_context->hw_frames_ctx) + if(video_codec_context && video_codec_context->hw_frames_ctx) av_buffer_unref(&video_codec_context->hw_frames_ctx); if(self->device_ctx) av_buffer_unref(&self->device_ctx); diff --git a/src/encoder/video/vulkan.c b/src/encoder/video/vulkan.c index 3b7c567..232a37d 100644 --- a/src/encoder/video/vulkan.c +++ b/src/encoder/video/vulkan.c @@ -1,4 +1,5 @@ #include "../../../include/encoder/video/vulkan.h" +#include "../../../include/log.h" #include "../../../include/utils.h" #include "../../../include/egl.h" @@ -36,6 +37,7 @@ typedef struct { PFN_vkResetFences vkResetFences; PFN_vkWaitForFences vkWaitForFences; PFN_vkGetDeviceQueue vkGetDeviceQueue; + PFN_vkGetDeviceQueue2 vkGetDeviceQueue2; PFN_vkQueueSubmit vkQueueSubmit; PFN_vkResetCommandBuffer vkResetCommandBuffer; PFN_vkCreateSemaphore vkCreateSemaphore; @@ -73,12 +75,12 @@ typedef struct { static bool gsr_vk_funcs_load(gsr_vk_funcs *vk, PFN_vkGetInstanceProcAddr get_inst_proc, VkInstance inst, VkDevice dev) { PFN_vkGetDeviceProcAddr get_dev_proc = (PFN_vkGetDeviceProcAddr)get_inst_proc(inst, "vkGetDeviceProcAddr"); if(!get_dev_proc) { - fprintf(stderr, "gsr error: gsr_vk_funcs_load: failed to load vkGetDeviceProcAddr\n"); + gsr_log(GSR_LOG_LEVEL_ERROR, "gsr_vk_funcs_load: failed to load vkGetDeviceProcAddr"); return false; } -#define LOAD_INST(name) vk->name = (PFN_##name)get_inst_proc(inst, #name); if(!vk->name) { fprintf(stderr, "gsr error: gsr_vk_funcs_load: failed to load " #name "\n"); return false; } -#define LOAD_DEV(name) vk->name = (PFN_##name)get_dev_proc(dev, #name); if(!vk->name) { fprintf(stderr, "gsr error: gsr_vk_funcs_load: failed to load " #name "\n"); return false; } +#define LOAD_INST(name) vk->name = (PFN_##name)get_inst_proc(inst, #name); if(!vk->name) { gsr_log(GSR_LOG_LEVEL_ERROR, "gsr_vk_funcs_load: failed to load " #name); return false; } +#define LOAD_DEV(name) vk->name = (PFN_##name)get_dev_proc(dev, #name); if(!vk->name) { gsr_log(GSR_LOG_LEVEL_ERROR, "gsr_vk_funcs_load: failed to load " #name); return false; } LOAD_INST(vkGetPhysicalDeviceMemoryProperties) LOAD_DEV(vkCreateImage) @@ -100,6 +102,7 @@ static bool gsr_vk_funcs_load(gsr_vk_funcs *vk, PFN_vkGetInstanceProcAddr get_in LOAD_DEV(vkResetFences) LOAD_DEV(vkWaitForFences) LOAD_DEV(vkGetDeviceQueue) + LOAD_DEV(vkGetDeviceQueue2) LOAD_DEV(vkQueueSubmit) LOAD_DEV(vkResetCommandBuffer) LOAD_DEV(vkCreateSemaphore) @@ -118,13 +121,13 @@ static bool gsr_video_encoder_vulkan_setup_context(gsr_video_encoder_vulkan *sel snprintf(device_index_str, sizeof(device_index_str), "%d", self->params.egl->vulkan_device_index); if(av_hwdevice_ctx_create(&self->device_ctx, AV_HWDEVICE_TYPE_VULKAN, device_index_str, options, 0) < 0) { - fprintf(stderr, "gsr error: gsr_video_encoder_vulkan_setup_context: failed to create hardware device context\n"); + gsr_log(GSR_LOG_LEVEL_ERROR, "gsr_video_encoder_vulkan_setup_context: failed to create hardware device context"); return false; } AVBufferRef *frame_context = av_hwframe_ctx_alloc(self->device_ctx); if(!frame_context) { - fprintf(stderr, "gsr error: gsr_video_encoder_vulkan_setup_context: failed to create hwframe context\n"); + gsr_log(GSR_LOG_LEVEL_ERROR, "gsr_video_encoder_vulkan_setup_context: failed to create hwframe context"); av_buffer_unref(&self->device_ctx); return false; } @@ -137,8 +140,7 @@ static bool gsr_video_encoder_vulkan_setup_context(gsr_video_encoder_vulkan *sel hw_frame_context->device_ctx = (AVHWDeviceContext*)self->device_ctx->data; if (av_hwframe_ctx_init(frame_context) < 0) { - fprintf(stderr, "gsr error: gsr_video_encoder_vulkan_setup_context: failed to initialize hardware frame context " - "(note: ffmpeg version needs to be > 4.0)\n"); + gsr_log(GSR_LOG_LEVEL_ERROR, "gsr_video_encoder_vulkan_setup_context: failed to initialize hardware frame context (note: ffmpeg version needs to be > 4.0)"); av_buffer_unref(&self->device_ctx); return false; } @@ -162,6 +164,16 @@ static AVVulkanDeviceContext* video_codec_context_get_vulkan_data(AVCodecContext return (AVVulkanDeviceContext*)device_context->hwctx; } +/* The flags that FFmpeg created the device queues with, which vkGetDeviceQueue2 has to be given to return the queue */ +static VkDeviceQueueCreateFlags get_device_queue_create_flags(AVVulkanDeviceContext *vv) { +#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(61, 1, 100) + return vv->queue_flags; +#else + (void)vv; + return 0; +#endif +} + static int get_graphics_queue_family(AVVulkanDeviceContext *vv) { #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(59, 39, 100) for(int i = 0; i < vv->nb_qf; i++) { @@ -230,7 +242,7 @@ static bool create_exportable_image( }; if(vk->vkCreateImage(dev, &img_info, NULL, out_image) != VK_SUCCESS) { - fprintf(stderr, "gsr error: create_exportable_image: vkCreateImage failed\n"); + gsr_log(GSR_LOG_LEVEL_ERROR, "create_exportable_image: vkCreateImage failed"); return false; } @@ -240,7 +252,7 @@ static bool create_exportable_image( uint32_t mem_type_idx = get_memory_type_idx(phys_dev, &mem_reqs, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, vk->vkGetPhysicalDeviceMemoryProperties); if(mem_type_idx == UINT32_MAX) { - fprintf(stderr, "gsr error: create_exportable_image: no suitable memory type\n"); + gsr_log(GSR_LOG_LEVEL_ERROR, "create_exportable_image: no suitable memory type"); vk->vkDestroyImage(dev, *out_image, NULL); *out_image = VK_NULL_HANDLE; return false; @@ -263,14 +275,14 @@ static bool create_exportable_image( }; if(vk->vkAllocateMemory(dev, &mem_alloc_info, NULL, out_memory) != VK_SUCCESS) { - fprintf(stderr, "gsr error: create_exportable_image: vkAllocateMemory failed\n"); + gsr_log(GSR_LOG_LEVEL_ERROR, "create_exportable_image: vkAllocateMemory failed"); vk->vkDestroyImage(dev, *out_image, NULL); *out_image = VK_NULL_HANDLE; return false; } if(vk->vkBindImageMemory(dev, *out_image, *out_memory, 0) != VK_SUCCESS) { - fprintf(stderr, "gsr error: create_exportable_image: vkBindImageMemory failed\n"); + gsr_log(GSR_LOG_LEVEL_ERROR, "create_exportable_image: vkBindImageMemory failed"); vk->vkFreeMemory(dev, *out_memory, NULL); vk->vkDestroyImage(dev, *out_image, NULL); *out_memory = VK_NULL_HANDLE; @@ -285,7 +297,7 @@ static bool create_exportable_image( static bool gsr_video_encoder_vulkan_setup_textures(gsr_video_encoder_vulkan *self, AVCodecContext *video_codec_context, AVFrame *frame) { const int res = av_hwframe_get_buffer(video_codec_context->hw_frames_ctx, frame, 0); if(res < 0) { - fprintf(stderr, "gsr error: gsr_video_encoder_vulkan_setup_textures: av_hwframe_get_buffer failed: %d\n", res); + gsr_log(GSR_LOG_LEVEL_ERROR, "gsr_video_encoder_vulkan_setup_textures: av_hwframe_get_buffer failed: %d", res); return false; } @@ -293,7 +305,7 @@ static bool gsr_video_encoder_vulkan_setup_textures(gsr_video_encoder_vulkan *se AVVulkanDeviceContext *vv = video_codec_context_get_vulkan_data(video_codec_context); if(!vv) { - fprintf(stderr, "gsr error: gsr_video_encoder_vulkan_setup_textures: failed to get vulkan device context\n"); + gsr_log(GSR_LOG_LEVEL_ERROR, "gsr_video_encoder_vulkan_setup_textures: failed to get vulkan device context"); return false; } @@ -327,7 +339,7 @@ static bool gsr_video_encoder_vulkan_setup_textures(gsr_video_encoder_vulkan *se }; int fd = -1; if(self->vk.vkGetMemoryFdKHR(vv->act_dev, &fd_info, &fd) != VK_SUCCESS) { - fprintf(stderr, "gsr error: gsr_video_encoder_vulkan_setup_textures: vkGetMemoryFdKHR failed for plane %d\n", i); + gsr_log(GSR_LOG_LEVEL_ERROR, "gsr_video_encoder_vulkan_setup_textures: vkGetMemoryFdKHR failed for plane %d", i); return false; } @@ -338,7 +350,7 @@ static bool gsr_video_encoder_vulkan_setup_textures(gsr_video_encoder_vulkan *se self->params.egl->glImportMemoryFdEXT(self->gl_memory_objects[i], self->export_memory_size[i], GL_HANDLE_TYPE_OPAQUE_FD_EXT, fd); if(!self->params.egl->glIsMemoryObjectEXT(self->gl_memory_objects[i])) { - fprintf(stderr, "gsr error: gsr_video_encoder_vulkan_setup_textures: failed to import memory FD for plane %d\n", i); + gsr_log(GSR_LOG_LEVEL_ERROR, "gsr_video_encoder_vulkan_setup_textures: failed to import memory FD for plane %d", i); return false; } } @@ -370,7 +382,7 @@ static bool gsr_video_encoder_vulkan_setup_textures(gsr_video_encoder_vulkan *se .queueFamilyIndex = (uint32_t)get_graphics_queue_family(vv), }; if(self->vk.vkCreateCommandPool(vv->act_dev, &pool_info, NULL, &self->command_pool) != VK_SUCCESS) { - fprintf(stderr, "gsr error: gsr_video_encoder_vulkan_setup_textures: vkCreateCommandPool failed\n"); + gsr_log(GSR_LOG_LEVEL_ERROR, "gsr_video_encoder_vulkan_setup_textures: vkCreateCommandPool failed"); return false; } @@ -381,7 +393,7 @@ static bool gsr_video_encoder_vulkan_setup_textures(gsr_video_encoder_vulkan *se .commandBufferCount = 1, }; if(self->vk.vkAllocateCommandBuffers(vv->act_dev, &cb_alloc_info, &self->command_buffer) != VK_SUCCESS) { - fprintf(stderr, "gsr error: gsr_video_encoder_vulkan_setup_textures: vkAllocateCommandBuffers failed\n"); + gsr_log(GSR_LOG_LEVEL_ERROR, "gsr_video_encoder_vulkan_setup_textures: vkAllocateCommandBuffers failed"); return false; } @@ -389,11 +401,26 @@ static bool gsr_video_encoder_vulkan_setup_textures(gsr_video_encoder_vulkan *se .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, }; if(self->vk.vkCreateFence(vv->act_dev, &fence_info, NULL, &self->fence) != VK_SUCCESS) { - fprintf(stderr, "gsr error: gsr_video_encoder_vulkan_setup_textures: vkCreateFence failed\n"); + gsr_log(GSR_LOG_LEVEL_ERROR, "gsr_video_encoder_vulkan_setup_textures: vkCreateFence failed"); return false; } - self->vk.vkGetDeviceQueue(vv->act_dev, (uint32_t)get_graphics_queue_family(vv), 0, &self->vk_queue); + /* + The queues have to be retrieved with vkGetDeviceQueue2 because vkGetDeviceQueue only works for queues that + were created without flags, and FFmpeg creates them with VK_DEVICE_QUEUE_CREATE_INTERNALLY_SYNCHRONIZED_BIT_KHR + when the driver supports it. vkGetDeviceQueue returns a NULL queue in that case, which crashes when it's used. + */ + VkDeviceQueueInfo2 queue_info = { + .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2, + .flags = get_device_queue_create_flags(vv), + .queueFamilyIndex = (uint32_t)get_graphics_queue_family(vv), + .queueIndex = 0, + }; + self->vk.vkGetDeviceQueue2(vv->act_dev, &queue_info, &self->vk_queue); + if(!self->vk_queue) { + gsr_log(GSR_LOG_LEVEL_ERROR, "gsr_video_encoder_vulkan_setup_textures: vkGetDeviceQueue2 failed"); + return false; + } /* Transition export images UNDEFINED → GENERAL so GL can use them */ VkCommandBufferBeginInfo begin_info = { @@ -484,7 +511,7 @@ static bool gsr_video_encoder_vulkan_start(gsr_video_encoder *encoder, AVCodecCo } if(FFALIGN(video_codec_context->width, 2) != FFALIGN(frame->width, 2) || FFALIGN(video_codec_context->height, 2) != FFALIGN(frame->height, 2)) { - fprintf(stderr, "gsr warning: gsr_video_encoder_vulkan_start: black bars have been added to the video because of a bug in AMD drivers/hardware. Record with h264/hevc vulkan codec instead (-k h264_vulkan) to get around this issue\n"); + gsr_log(GSR_LOG_LEVEL_WARNING, "gsr_video_encoder_vulkan_start: black bars have been added to the video because of a bug in AMD drivers/hardware. Record with h264/hevc vulkan codec instead (-k h264_vulkan) to get around this issue"); } if(video_codec_context->width < 128) @@ -835,7 +862,7 @@ void gsr_video_encoder_vulkan_stop(gsr_video_encoder_vulkan *self, AVCodecContex } } - if(video_codec_context->hw_frames_ctx) + if(video_codec_context && video_codec_context->hw_frames_ctx) av_buffer_unref(&video_codec_context->hw_frames_ctx); if(self->device_ctx) av_buffer_unref(&self->device_ctx); |
