diff --git a/src/gdvapivideostream_class.cpp b/src/gdvapivideostream_class.cpp index 5c368d7..9542639 100644 --- a/src/gdvapivideostream_class.cpp +++ b/src/gdvapivideostream_class.cpp @@ -4,9 +4,9 @@ #include "godot_cpp/classes/rd_texture_view.hpp" #include "godot_cpp/classes/rendering_device.hpp" #include "godot_cpp/classes/rendering_server.hpp" -#include "godot_cpp/variant/utility_functions.hpp" #include "godot_cpp/variant/color.hpp" #include "godot_cpp/variant/rect2.hpp" +#include "godot_cpp/variant/utility_functions.hpp" #include "vaapi_decoder.h" #include "vk_image_import.h" @@ -25,55 +25,53 @@ extern "C" { using namespace godot; enum HWMode { HW_NONE, - HW_VULKAN, - HW_VAAPI }; + HW_VULKAN, + HW_VAAPI }; static HWMode active_hw_mode = HW_NONE; void GDVAPIVideoStream::_bind_methods() { + ClassDB::bind_method(D_METHOD("begin", "source"), &GDVAPIVideoStream::begin); + ClassDB::bind_method(D_METHOD("get_texture"), &GDVAPIVideoStream::get_texture); + ClassDB::bind_method(D_METHOD("get_desired_width"), &GDVAPIVideoStream::get_desired_width); + ClassDB::bind_method(D_METHOD("set_desired_width", "v"), &GDVAPIVideoStream::set_desired_width); + ClassDB::bind_method(D_METHOD("get_desired_height"), &GDVAPIVideoStream::get_desired_height); + ClassDB::bind_method(D_METHOD("set_desired_height", "v"), &GDVAPIVideoStream::set_desired_height); - ClassDB::bind_method(D_METHOD("begin", "source"), &GDVAPIVideoStream::begin); - ClassDB::bind_method(D_METHOD("get_texture"), &GDVAPIVideoStream::get_texture); - ClassDB::bind_method(D_METHOD("get_desired_width"), &GDVAPIVideoStream::get_desired_width); - ClassDB::bind_method(D_METHOD("set_desired_width", "v"), &GDVAPIVideoStream::set_desired_width); - ClassDB::bind_method(D_METHOD("get_desired_height"), &GDVAPIVideoStream::get_desired_height); - ClassDB::bind_method(D_METHOD("set_desired_height", "v"), &GDVAPIVideoStream::set_desired_height); + ADD_PROPERTY(PropertyInfo(Variant::INT, "desired_width"), "set_desired_width", "get_desired_width"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "desired_height"), "set_desired_height", "get_desired_height"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "desired_width"), "set_desired_width", "get_desired_width"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "desired_height"), "set_desired_height", "get_desired_height"); + ClassDB::bind_method(D_METHOD("set_reorder_buffer_ms", "v"), &GDVAPIVideoStream::set_reorder_buffer_ms); + ClassDB::bind_method(D_METHOD("get_reorder_buffer_ms"), &GDVAPIVideoStream::get_reorder_buffer_ms); + ClassDB::bind_method(D_METHOD("set_demux_fifo_bytes", "v"), &GDVAPIVideoStream::set_demux_fifo_bytes); + ClassDB::bind_method(D_METHOD("get_demux_fifo_bytes"), &GDVAPIVideoStream::get_demux_fifo_bytes); + ClassDB::bind_method(D_METHOD("set_socket_buffer_bytes", "v"), &GDVAPIVideoStream::set_socket_buffer_bytes); + ClassDB::bind_method(D_METHOD("get_socket_buffer_bytes"), &GDVAPIVideoStream::get_socket_buffer_bytes); + ClassDB::bind_method(D_METHOD("set_reorder_queue_size", "v"), &GDVAPIVideoStream::set_reorder_queue_size); + ClassDB::bind_method(D_METHOD("get_reorder_queue_size"), &GDVAPIVideoStream::get_reorder_queue_size); + ClassDB::bind_method(D_METHOD("set_io_timeout_ms", "v"), &GDVAPIVideoStream::set_io_timeout_ms); + ClassDB::bind_method(D_METHOD("get_io_timeout_ms"), &GDVAPIVideoStream::get_io_timeout_ms); + ClassDB::bind_method(D_METHOD("set_queue_depth", "v"), &GDVAPIVideoStream::set_queue_depth); + ClassDB::bind_method(D_METHOD("get_queue_depth"), &GDVAPIVideoStream::get_queue_depth); + ClassDB::bind_method(D_METHOD("set_frame_latency_ms", "v"), &GDVAPIVideoStream::set_frame_latency_ms); + ClassDB::bind_method(D_METHOD("get_frame_latency_ms"), &GDVAPIVideoStream::get_frame_latency_ms); + ClassDB::bind_method(D_METHOD("set_vpp_half_res", "v"), &GDVAPIVideoStream::set_vpp_half_res); + ClassDB::bind_method(D_METHOD("get_vpp_half_res"), &GDVAPIVideoStream::get_vpp_half_res); - ClassDB::bind_method(D_METHOD("set_reorder_buffer_ms", "v"), &GDVAPIVideoStream::set_reorder_buffer_ms); - ClassDB::bind_method(D_METHOD("get_reorder_buffer_ms"), &GDVAPIVideoStream::get_reorder_buffer_ms); - ClassDB::bind_method(D_METHOD("set_demux_fifo_bytes", "v"), &GDVAPIVideoStream::set_demux_fifo_bytes); - ClassDB::bind_method(D_METHOD("get_demux_fifo_bytes"), &GDVAPIVideoStream::get_demux_fifo_bytes); - ClassDB::bind_method(D_METHOD("set_socket_buffer_bytes", "v"), &GDVAPIVideoStream::set_socket_buffer_bytes); - ClassDB::bind_method(D_METHOD("get_socket_buffer_bytes"), &GDVAPIVideoStream::get_socket_buffer_bytes); - ClassDB::bind_method(D_METHOD("set_reorder_queue_size", "v"), &GDVAPIVideoStream::set_reorder_queue_size); - ClassDB::bind_method(D_METHOD("get_reorder_queue_size"), &GDVAPIVideoStream::get_reorder_queue_size); - ClassDB::bind_method(D_METHOD("set_io_timeout_ms", "v"), &GDVAPIVideoStream::set_io_timeout_ms); - ClassDB::bind_method(D_METHOD("get_io_timeout_ms"), &GDVAPIVideoStream::get_io_timeout_ms); - ClassDB::bind_method(D_METHOD("set_queue_depth", "v"), &GDVAPIVideoStream::set_queue_depth); - ClassDB::bind_method(D_METHOD("get_queue_depth"), &GDVAPIVideoStream::get_queue_depth); - ClassDB::bind_method(D_METHOD("set_frame_latency_ms", "v"), &GDVAPIVideoStream::set_frame_latency_ms); - ClassDB::bind_method(D_METHOD("get_frame_latency_ms"), &GDVAPIVideoStream::get_frame_latency_ms); - ClassDB::bind_method(D_METHOD("set_vpp_half_res", "v"), &GDVAPIVideoStream::set_vpp_half_res); - ClassDB::bind_method(D_METHOD("get_vpp_half_res"), &GDVAPIVideoStream::get_vpp_half_res); + ADD_PROPERTY(PropertyInfo(Variant::INT, "reorder_buffer_ms"), "set_reorder_buffer_ms", "get_reorder_buffer_ms"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "demux_fifo_bytes"), "set_demux_fifo_bytes", "get_demux_fifo_bytes"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "socket_buffer_bytes"), "set_socket_buffer_bytes", "get_socket_buffer_bytes"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "reorder_queue_size"), "set_reorder_queue_size", "get_reorder_queue_size"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "io_timeout_ms"), "set_io_timeout_ms", "get_io_timeout_ms"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "queue_depth"), "set_queue_depth", "get_queue_depth"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "frame_latency_ms"), "set_frame_latency_ms", "get_frame_latency_ms"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "vpp_half_res"), "set_vpp_half_res", "get_vpp_half_res"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "reorder_buffer_ms"), "set_reorder_buffer_ms", "get_reorder_buffer_ms"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "demux_fifo_bytes"), "set_demux_fifo_bytes", "get_demux_fifo_bytes"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "socket_buffer_bytes"), "set_socket_buffer_bytes", "get_socket_buffer_bytes"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "reorder_queue_size"), "set_reorder_queue_size", "get_reorder_queue_size"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "io_timeout_ms"), "set_io_timeout_ms", "get_io_timeout_ms"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "queue_depth"), "set_queue_depth", "get_queue_depth"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "frame_latency_ms"), "set_frame_latency_ms", "get_frame_latency_ms"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "vpp_half_res"), "set_vpp_half_res", "get_vpp_half_res"); - - ClassDB::bind_method(D_METHOD("get_frame_count"), &GDVAPIVideoStream::get_frame_count); - ClassDB::bind_method(D_METHOD("has_frame"), &GDVAPIVideoStream::has_frame); - ClassDB::bind_method(D_METHOD("get_stream_width"), &GDVAPIVideoStream::get_stream_width); - ClassDB::bind_method(D_METHOD("get_stream_height"), &GDVAPIVideoStream::get_stream_height); + ClassDB::bind_method(D_METHOD("get_frame_count"), &GDVAPIVideoStream::get_frame_count); + ClassDB::bind_method(D_METHOD("has_frame"), &GDVAPIVideoStream::has_frame); + ClassDB::bind_method(D_METHOD("get_stream_width"), &GDVAPIVideoStream::get_stream_width); + ClassDB::bind_method(D_METHOD("get_stream_height"), &GDVAPIVideoStream::get_stream_height); } - static enum AVPixelFormat get_hw_format(AVCodecContext *ctx, const enum AVPixelFormat *formats) { for (const enum AVPixelFormat *p = formats; *p != -1; p++) { if (active_hw_mode == HW_VULKAN && *p == AV_PIX_FMT_VULKAN) @@ -105,8 +103,7 @@ void GDVAPIVideoStream::_process(double delta) { } wall_base = std::chrono::steady_clock::now(); String uri = stream_source; - if (uri.ends_with(".sdp") || uri.ends_with(".mp4") - || uri.ends_with(".mov") || uri.begins_with("/")) + if (uri.ends_with(".sdp") || uri.ends_with(".mp4") || uri.ends_with(".mov") || uri.begins_with("/")) worker_src = uri.utf8().get_data(); else { const char *sdp = "/tmp/gdvapi_live.sdp"; @@ -114,12 +111,15 @@ void GDVAPIVideoStream::_process(double delta) { if (uri.begins_with("udp://")) { String rest = uri.substr(6); int c = rest.find(":"); - if (c > 0) { host = rest.substr(0, c); port = rest.substr(c + 1); } + if (c > 0) { + host = rest.substr(0, c); + port = rest.substr(c + 1); + } } FILE *f = fopen(sdp, "w"); if (f) { fprintf(f, "v=0\no=- 0 0 IN IP4 %s\ns=Live\nc=IN IP4 %s\nt=0 0\n" - "m=video %s RTP/AVP 96\na=rtpmap:96 H265/90000\n", + "m=video %s RTP/AVP 96\na=rtpmap:96 H265/90000\n", host.utf8().get_data(), host.utf8().get_data(), port.utf8().get_data()); fclose(f); @@ -299,9 +299,7 @@ void GDVAPIVideoStream::consume_ready() { if (rf.pts_sec > 0.0) { if (pts_base < 0.0) { pts_base = rf.pts_sec; - wall_base = std::chrono::steady_clock::now() - - std::chrono::duration_cast( - std::chrono::duration(rf.pts_sec)); + wall_base = std::chrono::steady_clock::now() - std::chrono::duration_cast(std::chrono::duration(rf.pts_sec)); elapsed = 0.0; } const double stream_pos = rf.pts_sec - pts_base; @@ -369,8 +367,8 @@ void GDVAPIVideoStream::consume_ready() { fmt->set_array_layers(1); fmt->set_mipmaps(1); fmt->set_usage_bits(RenderingDevice::TEXTURE_USAGE_SAMPLING_BIT | - RenderingDevice::TEXTURE_USAGE_CAN_COPY_TO_BIT | - RenderingDevice::TEXTURE_USAGE_CAN_COPY_FROM_BIT); + RenderingDevice::TEXTURE_USAGE_CAN_COPY_TO_BIT | + RenderingDevice::TEXTURE_USAGE_CAN_COPY_FROM_BIT); Ref v; v.instantiate(); out_tex[i] = rd->texture_create(fmt, v, TypedArray()); @@ -391,9 +389,9 @@ void GDVAPIVideoStream::consume_ready() { const int w = (draw_idx + 1) % 2; if (wrap.is_valid()) { rd->texture_copy(wrap, out_tex[w], - godot::Vector3(0, 0, 0), godot::Vector3(0, 0, 0), - godot::Vector3(rf.w, rf.h, 1), - 0, 0, 0, 0); + godot::Vector3(0, 0, 0), godot::Vector3(0, 0, 0), + godot::Vector3(rf.w, rf.h, 1), + 0, 0, 0, 0); rd->free_rid(wrap); } if (!draw_tex[w].is_valid()) { @@ -402,7 +400,8 @@ void GDVAPIVideoStream::consume_ready() { } draw_idx = w; present_wall_sec = std::chrono::duration( - std::chrono::steady_clock::now() - wall_base).count(); + std::chrono::steady_clock::now() - wall_base) + .count(); if (!have_presentable) { have_presentable = true; } @@ -447,28 +446,26 @@ void GDVAPIVideoStream::cleanup() { stream_eof = true; godot_texture.unref(); - } void GDVAPIVideoStream::set_desired_width(const int v) { - if (desiredWidth != v) { - desiredWidth = v; - } + if (desiredWidth != v) { + desiredWidth = v; + } } void GDVAPIVideoStream::set_desired_height(const int v) { - if (desiredHeight != v) { - desiredHeight = v; - } + if (desiredHeight != v) { + desiredHeight = v; + } } - int GDVAPIVideoStream::get_desired_width() const { - return desiredWidth; + return desiredWidth; } int GDVAPIVideoStream::get_desired_height() const { - return desiredHeight; + return desiredHeight; } void GDVAPIVideoStream::set_reorder_buffer_ms(const int v) { @@ -521,22 +518,20 @@ bool GDVAPIVideoStream::get_vpp_half_res() const { return decoder_opts.vpp_div == 2; } - - void GDVAPIVideoStream::_ready() { - UtilityFunctions::print("_ready called"); + UtilityFunctions::print("_ready called"); - RenderingDevice *rd = RenderingServer::get_singleton()->get_rendering_device(); - if (rd) { - uint64_t vk_dev = rd->get_driver_resource( - RenderingDevice::DRIVER_RESOURCE_LOGICAL_DEVICE, RID(), 0); - uint64_t vk_phys = rd->get_driver_resource( - RenderingDevice::DRIVER_RESOURCE_PHYSICAL_DEVICE, RID(), 0); - uint64_t vk_inst = rd->get_driver_resource( - RenderingDevice::DRIVER_RESOURCE_VULKAN_INSTANCE, RID(), 0); - UtilityFunctions::print("[gdvapi] VkDevice=", vk_dev, - " VkPhysicalDevice=", vk_phys, - " VkInstance=", vk_inst); - } else - UtilityFunctions::print("[gdvapi] no RenderingDevice"); + RenderingDevice *rd = RenderingServer::get_singleton()->get_rendering_device(); + if (rd) { + uint64_t vk_dev = rd->get_driver_resource( + RenderingDevice::DRIVER_RESOURCE_LOGICAL_DEVICE, RID(), 0); + uint64_t vk_phys = rd->get_driver_resource( + RenderingDevice::DRIVER_RESOURCE_PHYSICAL_DEVICE, RID(), 0); + uint64_t vk_inst = rd->get_driver_resource( + RenderingDevice::DRIVER_RESOURCE_VULKAN_INSTANCE, RID(), 0); + UtilityFunctions::print("[gdvapi] VkDevice=", vk_dev, + " VkPhysicalDevice=", vk_phys, + " VkInstance=", vk_inst); + } else + UtilityFunctions::print("[gdvapi] no RenderingDevice"); } diff --git a/src/gdvapivideostream_class.h b/src/gdvapivideostream_class.h index 15d7935..ba83864 100644 --- a/src/gdvapivideostream_class.h +++ b/src/gdvapivideostream_class.h @@ -39,17 +39,17 @@ private: std::condition_variable q_cv; std::deque ready_q; std::atomic slot_acked[gdvapi::VAAPIDecoder::kRgbaPool] = {}; - int queue_max = 4; // bounded FIFO depth + int queue_max = 4; // bounded FIFO depth double max_frame_latency = 0.5; // drop frames older than this bool worker_stop = false; bool worker_finished = false; std::chrono::steady_clock::time_point wall_base; double worker_fps = 30.0; - bool source_live = false; // RTP/SDP: retry on gaps instead of EOF + bool source_live = false; // RTP/SDP: retry on gaps instead of EOF gdvapi::VAAPIDecoder va_decoder; gdvapi::DecoderOptions decoder_opts; - int vpp_slot = 0; // rotates 0..kRgbaPool-1 + int vpp_slot = 0; // rotates 0..kRgbaPool-1 std::string worker_src; VkDevice vk_dev = VK_NULL_HANDLE; @@ -61,8 +61,8 @@ private: Ref draw_tex[2]; int draw_idx = 0; double present_wall_sec = -1.0; // for debug overlay - double last_pts = -1.0; // monotonic order gate - double pts_base = -1.0; // first-presented PTS + double last_pts = -1.0; // monotonic order gate + double pts_base = -1.0; // first-presented PTS bool stream_started = false; bool stream_eof = false; @@ -93,31 +93,38 @@ public: void begin(const Variant &source); Ref get_texture() const { return draw_tex[draw_idx]; } - void set_reorder_buffer_ms(const int v); int get_reorder_buffer_ms() const; - void set_demux_fifo_bytes(const int v); int get_demux_fifo_bytes() const; - void set_socket_buffer_bytes(const int v);int get_socket_buffer_bytes() const; - void set_reorder_queue_size(const int v); int get_reorder_queue_size() const; - void set_io_timeout_ms(const int v); int get_io_timeout_ms() const; - void set_queue_depth(const int v); int get_queue_depth() const; - void set_frame_latency_ms(const int v); int get_frame_latency_ms() const; - void set_vpp_half_res(const bool v); bool get_vpp_half_res() const; + void set_reorder_buffer_ms(const int v); + int get_reorder_buffer_ms() const; + void set_demux_fifo_bytes(const int v); + int get_demux_fifo_bytes() const; + void set_socket_buffer_bytes(const int v); + int get_socket_buffer_bytes() const; + void set_reorder_queue_size(const int v); + int get_reorder_queue_size() const; + void set_io_timeout_ms(const int v); + int get_io_timeout_ms() const; + void set_queue_depth(const int v); + int get_queue_depth() const; + void set_frame_latency_ms(const int v); + int get_frame_latency_ms() const; + void set_vpp_half_res(const bool v); + bool get_vpp_half_res() const; int get_frame_count() const { return present_count; } bool has_frame() const { return have_presentable; } int get_stream_width() const { return pending_w; } int get_stream_height() const { return pending_h; } - void _process(double delta) override; void _notification(int p_what); void _ready() override; void set_desired_width(const int v); - int get_desired_width() const; + int get_desired_width() const; - void set_desired_height(const int v); - int get_desired_height() const; + void set_desired_height(const int v); + int get_desired_height() const; }; -} +} //namespace godot diff --git a/src/register_types.cpp b/src/register_types.cpp index 5b1c548..34c660a 100644 --- a/src/register_types.cpp +++ b/src/register_types.cpp @@ -22,7 +22,6 @@ void initialize_gdextension_types(ModuleInitializationLevel p_level) { GDREGISTER_RUNTIME_CLASS(GDVAPIVideoStream); } - void uninitialize_gdextension_types(ModuleInitializationLevel p_level) { if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) return; diff --git a/src/vaapi_decoder.cpp b/src/vaapi_decoder.cpp index 4323403..dbd3027 100644 --- a/src/vaapi_decoder.cpp +++ b/src/vaapi_decoder.cpp @@ -13,7 +13,7 @@ extern "C" { namespace gdvapi { static enum AVPixelFormat get_hw_format(AVCodecContext *ctx, - const enum AVPixelFormat *pix_fmts) { + const enum AVPixelFormat *pix_fmts) { (void)ctx; for (const enum AVPixelFormat *p = pix_fmts; *p != -1; p++) if (*p == AV_PIX_FMT_VAAPI) @@ -88,14 +88,14 @@ bool VAAPIDecoder::open(const char *path, const DecoderOptions &o) { return false; } if (avcodec_parameters_to_context(codec_ctx, - fmt_ctx->streams[video_stream_idx]->codecpar) < 0) { + fmt_ctx->streams[video_stream_idx]->codecpar) < 0) { fprintf(stderr, "[gdvapi] params->ctx failed\n"); close(); return false; } if (av_hwdevice_ctx_create(&hw_device_ctx, AV_HWDEVICE_TYPE_VAAPI, - nullptr, nullptr, 0) < 0) { + nullptr, nullptr, 0) < 0) { fprintf(stderr, "[gdvapi] vaapi device create failed\n"); close(); return false; @@ -234,7 +234,6 @@ bool VAAPIDecoder::next_frame(AVFrame *&out_frame) { return false; } - static void fill_dma_out(const VADRMPRIMESurfaceDescriptor &desc, DecodedFrame &out) { out.width = desc.width; out.height = desc.height; @@ -266,7 +265,7 @@ bool VAAPIDecoder::vpp_init() { VAConfigAttrib rt = { VAConfigAttribRTFormat, VA_RT_FORMAT_RGB32 }; VAStatus st = vaCreateConfig(dpy, VAProfileNone, VAEntrypointVideoProc, - &rt, 1, &vpp_config); + &rt, 1, &vpp_config); if (st != VA_STATUS_SUCCESS) { fprintf(stderr, "[gdvapi] vpp vaCreateConfig failed: %d (%s)\n", st, vaErrorStr(st)); @@ -275,17 +274,19 @@ bool VAAPIDecoder::vpp_init() { int vpp_div = vpp_div_ > 0 ? vpp_div_ : 1; vpp_out_w = video_width / vpp_div; vpp_out_h = video_height / vpp_div; - if (vpp_out_w < 1) vpp_out_w = 1; - if (vpp_out_h < 1) vpp_out_h = 1; + if (vpp_out_w < 1) + vpp_out_w = 1; + if (vpp_out_h < 1) + vpp_out_h = 1; st = vaCreateContext(dpy, vpp_config, vpp_out_w, vpp_out_h, - VA_PROGRESSIVE, 0, 0, &vpp_ctx); + VA_PROGRESSIVE, 0, 0, &vpp_ctx); if (st != VA_STATUS_SUCCESS) { fprintf(stderr, "[gdvapi] vpp vaCreateContext failed: %d (%s)\n", st, vaErrorStr(st)); return false; } st = vaCreateSurfaces(dpy, VA_RT_FORMAT_RGB32, - vpp_out_w, vpp_out_h, rgba_pool, kRgbaPool, nullptr, 0); + vpp_out_w, vpp_out_h, rgba_pool, kRgbaPool, nullptr, 0); if (st != VA_STATUS_SUCCESS) { fprintf(stderr, "[gdvapi] vpp vaCreateSurfaces failed: %d (%s)\n", st, vaErrorStr(st)); @@ -298,9 +299,9 @@ bool VAAPIDecoder::vpp_init() { } bool VAAPIDecoder::convert_frame_to_rgba_slot(const AVFrame *nv12_frame, - int slot, DecodedFrame &out) { + int slot, DecodedFrame &out) { if (!nv12_frame || nv12_frame->format != AV_PIX_FMT_VAAPI || - slot < 0 || slot >= kRgbaPool) + slot < 0 || slot >= kRgbaPool) return false; if (video_width == 0 || video_height == 0) { video_width = nv12_frame->width; @@ -317,14 +318,14 @@ bool VAAPIDecoder::convert_frame_to_rgba_slot(const AVFrame *nv12_frame, VAProcPipelineParameterBuffer param; memset(¶m, 0, sizeof(param)); - param.surface = src_surf; // src (NV12) - param.surface_region = nullptr; // whole source + param.surface = src_surf; // src (NV12) + param.surface_region = nullptr; // whole source VARectangle out_reg = { 0, 0, (uint16_t)vpp_out_w, (uint16_t)vpp_out_h }; - param.output_region = &out_reg; // whole target (RGB32) + param.output_region = &out_reg; // whole target (RGB32) VABufferID buf = VA_INVALID_ID; VAStatus st = vaCreateBuffer(dpy, vpp_ctx, VAProcPipelineParameterBufferType, - sizeof(param), 1, ¶m, &buf); + sizeof(param), 1, ¶m, &buf); if (st != VA_STATUS_SUCCESS) { fprintf(stderr, "[gdvapi] vpp vaCreateBuffer failed: %d (%s)\n", st, vaErrorStr(st)); @@ -346,9 +347,9 @@ bool VAAPIDecoder::convert_frame_to_rgba_slot(const AVFrame *nv12_frame, VADRMPRIMESurfaceDescriptor desc; st = vaExportSurfaceHandle(dpy, rgba_pool[slot], - VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2, - VA_EXPORT_SURFACE_READ_ONLY | VA_EXPORT_SURFACE_COMPOSED_LAYERS, - &desc); + VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2, + VA_EXPORT_SURFACE_READ_ONLY | VA_EXPORT_SURFACE_COMPOSED_LAYERS, + &desc); if (st != VA_STATUS_SUCCESS) { fprintf(stderr, "[gdvapi] vpp export failed: %d (%s)\n", st, vaErrorStr(st)); return false; @@ -376,9 +377,9 @@ bool VAAPIDecoder::export_surface(const AVFrame *f, DecodedFrame &out) { VADRMPRIMESurfaceDescriptor desc; VAStatus st = vaExportSurfaceHandle(dpy, surf, - VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2, - VA_EXPORT_SURFACE_READ_ONLY | VA_EXPORT_SURFACE_COMPOSED_LAYERS, - &desc); + VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2, + VA_EXPORT_SURFACE_READ_ONLY | VA_EXPORT_SURFACE_COMPOSED_LAYERS, + &desc); if (st != VA_STATUS_SUCCESS) { fprintf(stderr, "[gdvapi] vaExportSurfaceHandle(%u) failed: %d (%s)\n", (unsigned)surf, st, vaErrorStr(st)); @@ -415,8 +416,14 @@ void VAAPIDecoder::close() { rgba_pool[i] = VA_INVALID_ID; } } - if (vpp_ctx != VA_INVALID_ID) { vaDestroyContext(dpy, vpp_ctx); vpp_ctx = VA_INVALID_ID; } - if (vpp_config != VA_INVALID_ID) { vaDestroyConfig(dpy, vpp_config); vpp_config = VA_INVALID_ID; } + if (vpp_ctx != VA_INVALID_ID) { + vaDestroyContext(dpy, vpp_ctx); + vpp_ctx = VA_INVALID_ID; + } + if (vpp_config != VA_INVALID_ID) { + vaDestroyConfig(dpy, vpp_config); + vpp_config = VA_INVALID_ID; + } vpp_ready = false; } if (frame) { @@ -439,4 +446,4 @@ void VAAPIDecoder::close() { eof = false; } -} +} //namespace gdvapi diff --git a/src/vaapi_decoder.h b/src/vaapi_decoder.h index 1be2dcc..c732473 100644 --- a/src/vaapi_decoder.h +++ b/src/vaapi_decoder.h @@ -14,27 +14,27 @@ extern "C" { namespace gdvapi { struct DecoderOptions { - int io_timeout_us = 1000000; // avio block timeout (dead-stream detection) - int analyze_duration_us = 500000; // find_stream_info analysis cap - int probe_bytes = 1000000; // probe-size cap - int demux_fifo_bytes = 33554432; // rtbufsize: 32 MB demux FIFO (keyframe bursts) + int io_timeout_us = 1000000; // avio block timeout (dead-stream detection) + int analyze_duration_us = 500000; // find_stream_info analysis cap + int probe_bytes = 1000000; // probe-size cap + int demux_fifo_bytes = 33554432; // rtbufsize: 32 MB demux FIFO (keyframe bursts) int socket_buffer_bytes = 8388608; // kernel SO_RCVBUF: 8 MB (RTP burst headroom) - int max_delay_us = 200000; // RTP reorder/jitter window (optimum on rig) - int reorder_queue_size = 2048; // RTP demuxer reorder queue (packets) - int vpp_div = 1; // VPP output downscale (1 = full res, 2 = bench) + int max_delay_us = 200000; // RTP reorder/jitter window (optimum on rig) + int reorder_queue_size = 2048; // RTP demuxer reorder queue (packets) + int vpp_div = 1; // VPP output downscale (1 = full res, 2 = bench) }; struct DecodedFrame { int width = 0; int height = 0; - int fd = -1; // DRM dma-buf fd + int fd = -1; // DRM dma-buf fd uint32_t fourcc = 0; uint32_t drm_fourcc = 0; // layers[0].drm_format from the export - double pts_sec = 0.0; // pts in seconds (stream time_base) - uint32_t pitch = 0; // layer[0].pitch[0] (Y plane) - uint32_t offset = 0; // layer[0].offset[0] (Y plane) - uint32_t uv_pitch = 0; // layer[0].pitch[1] (UV plane, real tiled) - uint32_t uv_offset = 0; // layer[0].offset[1] (UV plane, real tiled) + double pts_sec = 0.0; // pts in seconds (stream time_base) + uint32_t pitch = 0; // layer[0].pitch[0] (Y plane) + uint32_t offset = 0; // layer[0].offset[0] (Y plane) + uint32_t uv_pitch = 0; // layer[0].pitch[1] (UV plane, real tiled) + uint32_t uv_offset = 0; // layer[0].offset[1] (UV plane, real tiled) uint64_t drm_format_modifier = 0; int64_t pts = AV_NOPTS_VALUE; bool valid() const { return fd >= 0; } @@ -70,7 +70,7 @@ public: double pts_sec_of(const AVFrame *f) const; bool convert_frame_to_rgba_slot(const AVFrame *nv12_frame, int slot, - DecodedFrame &out); + DecodedFrame &out); private: AVFormatContext *fmt_ctx = nullptr; @@ -84,7 +84,7 @@ private: double video_fps = 30.0; bool eof = false; bool wait_key = true; // skip non-key packets until first IDR - int vpp_div_ = 1; // VPP output downscale from DecoderOptions + int vpp_div_ = 1; // VPP output downscale from DecoderOptions }; -} +} //namespace gdvapi diff --git a/src/vk_image_import.cpp b/src/vk_image_import.cpp index 7eb17ca..907d926 100644 --- a/src/vk_image_import.cpp +++ b/src/vk_image_import.cpp @@ -37,23 +37,23 @@ T load_dev_fn(VkDevice device, const char *name) { VkFormat fourcc_to_format(uint32_t fourcc, uint32_t pitch) { (void)pitch; switch (fourcc) { - case 0x3231564e: // 'NV12' - return VK_FORMAT_G8_B8R8_2PLANE_420_UNORM; - case 0x34325241: // DRM_FORMAT_ARGB8888 'AR24' -> bytes B,G,R,A - case 0x34325258: // DRM_FORMAT_XRGB8888 'XR24' -> bytes B,G,R,A - return VK_FORMAT_B8G8R8A8_UNORM; - case 0x34324241: // DRM_FORMAT_ABGR8888 'AB24' -> bytes R,G,B,A - return VK_FORMAT_R8G8B8A8_UNORM; - default: - fprintf(stderr, "[gdvapi-import] unknown drm fourcc 0x%x\n", fourcc); - return VK_FORMAT_UNDEFINED; + case 0x3231564e: // 'NV12' + return VK_FORMAT_G8_B8R8_2PLANE_420_UNORM; + case 0x34325241: // DRM_FORMAT_ARGB8888 'AR24' -> bytes B,G,R,A + case 0x34325258: // DRM_FORMAT_XRGB8888 'XR24' -> bytes B,G,R,A + return VK_FORMAT_B8G8R8A8_UNORM; + case 0x34324241: // DRM_FORMAT_ABGR8888 'AB24' -> bytes R,G,B,A + return VK_FORMAT_R8G8B8A8_UNORM; + default: + fprintf(stderr, "[gdvapi-import] unknown drm fourcc 0x%x\n", fourcc); + return VK_FORMAT_UNDEFINED; } } -} +} //namespace VkImage import_dma_buf_image(VkDevice device, const DmaBufSurface &surf, - VkDeviceMemory *out_memory) { + VkDeviceMemory *out_memory) { if (!device || surf.fd < 0) return VK_NULL_HANDLE; if (out_memory) @@ -74,7 +74,7 @@ VkImage import_dma_buf_image(VkDevice device, const DmaBufSurface &surf, auto dev_mem_req = load_dev_fn(device, "vkGetImageMemoryRequirements"); auto dev_fd_props = load_dev_fn(device, "vkGetMemoryFdPropertiesKHR"); if (!dev_alloc || !dev_free || !dev_create_image || !dev_destroy_image || - !dev_bind_mem || !dev_mem_req || !dev_fd_props) { + !dev_bind_mem || !dev_mem_req || !dev_fd_props) { fprintf(stderr, "[gdvapi-import] required device functions unavailable\n"); return VK_NULL_HANDLE; } @@ -116,7 +116,7 @@ VkImage import_dma_buf_image(VkDevice device, const DmaBufSurface &surf, fmt_list.pNext = &ext_info; } -VkImageCreateInfo image_info{}; + VkImageCreateInfo image_info{}; image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; const void *next = &ext_info; if (multi_plane) @@ -133,7 +133,7 @@ VkImageCreateInfo image_info{}; image_info.arrayLayers = 1; image_info.samples = VK_SAMPLE_COUNT_1_BIT; image_info.tiling = linear ? VK_IMAGE_TILING_LINEAR - : VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT; + : VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT; image_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; @@ -223,4 +223,4 @@ void destroy_imported_image(VkDevice device, VkImage image, VkDeviceMemory mem) free_memory(device, mem, nullptr); } -} +} //namespace gdvapi diff --git a/src/vk_image_import.h b/src/vk_image_import.h index 4e45fa4..d0df08d 100644 --- a/src/vk_image_import.h +++ b/src/vk_image_import.h @@ -12,15 +12,15 @@ struct DmaBufSurface { uint64_t drm_format_modifier = 0; uint32_t pitch = 0; uint32_t offset = 0; - uint32_t uv_pitch = 0; // plane 1 (tiled chroma) pitch from descriptor - uint32_t uv_offset = 0; // plane 1 (tiled chroma) offset from descriptor - uint32_t fourcc = 0; // e.g. 0x3231564e "NV12" + uint32_t uv_pitch = 0; // plane 1 (tiled chroma) pitch from descriptor + uint32_t uv_offset = 0; // plane 1 (tiled chroma) offset from descriptor + uint32_t fourcc = 0; // e.g. 0x3231564e "NV12" uint32_t drm_fourcc = 0; // layers[0].drm_format from the descriptor }; VkImage import_dma_buf_image(VkDevice device, const DmaBufSurface &surf, - VkDeviceMemory *out_memory); + VkDeviceMemory *out_memory); void destroy_imported_image(VkDevice device, VkImage image, VkDeviceMemory mem); -} +} //namespace gdvapi diff --git a/src/vulkan_detour.cpp b/src/vulkan_detour.cpp index d2e9d4d..df596ab 100644 --- a/src/vulkan_detour.cpp +++ b/src/vulkan_detour.cpp @@ -27,9 +27,9 @@ constexpr int kExtCount = (int)(sizeof(kExtNames) / sizeof(kExtNames[0])); using VkCreateDeviceFn = VkResult(VKAPI_PTR *)(VkPhysicalDevice, const VkDeviceCreateInfo *, const VkAllocationCallbacks *, VkDevice *); std::atomic s_hook_installed{ false }; -uintptr_t s_target = 0; // address of vkCreateDevice in libvulkan -uintptr_t s_trampoline = 0; // executable copy of original prologue -constexpr int kPatchSize = 5; // E9 rel32 +uintptr_t s_target = 0; // address of vkCreateDevice in libvulkan +uintptr_t s_trampoline = 0; // executable copy of original prologue +constexpr int kPatchSize = 5; // E9 rel32 using PFN_vkEnumerateDeviceExtensionProperties = VkResult(VKAPI_PTR *)(VkPhysicalDevice, const char *, uint32_t *, VkExtensionProperties *); @@ -54,14 +54,13 @@ static void emit_rel32_jmp(unsigned char *dst, uintptr_t from, uintptr_t to) { } static VkResult call_original(VkPhysicalDevice pd, const VkDeviceCreateInfo *ci, - const VkAllocationCallbacks *alloc, VkDevice *dev) { - typedef VkResult(VKAPI_PTR *OrigFn)(VkPhysicalDevice, const VkDeviceCreateInfo *, - const VkAllocationCallbacks *, VkDevice *); + const VkAllocationCallbacks *alloc, VkDevice *dev) { + typedef VkResult(VKAPI_PTR * OrigFn)(VkPhysicalDevice, const VkDeviceCreateInfo *, + const VkAllocationCallbacks *, VkDevice *); OrigFn fn = (OrigFn)s_trampoline; return fn(pd, ci, alloc, dev); } - static bool device_has_extension(VkPhysicalDevice dev, const char *name) { if (!s_enumerate_ext) return false; @@ -77,7 +76,7 @@ static bool device_has_extension(VkPhysicalDevice dev, const char *name) { return false; } -} +} //namespace namespace gdvapi { @@ -93,13 +92,13 @@ VKAPI_ATTR VkResult VKAPI_CALL hooked_vk_create_device( const VkDeviceCreateInfo *p_create_info, const VkAllocationCallbacks *p_allocator, VkDevice *p_device) { - if (!s_trampoline || !p_create_info) return VK_ERROR_INITIALIZATION_FAILED; std::vector missing; uint32_t existing_count = p_create_info->enabledExtensionCount - ? p_create_info->enabledExtensionCount : 0; + ? p_create_info->enabledExtensionCount + : 0; const char *const *existing = p_create_info->ppEnabledExtensionNames; for (const char *name : kExtNames) { @@ -165,7 +164,7 @@ bool install_vk_create_device_hook() { fprintf(stderr, "[gdvapi-hook] dlsym vkEnumerateDeviceExtensionProperties: %s\n", dlerror()); void *tramp = mmap(nullptr, sysconf(_SC_PAGESIZE), PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (tramp == MAP_FAILED) { fprintf(stderr, "[gdvapi-hook] mmap trampoline failed\n"); s_hook_installed = false; @@ -190,4 +189,4 @@ bool install_vk_create_device_hook() { return true; } -} +} //namespace gdvapi diff --git a/src/vulkan_detour.h b/src/vulkan_detour.h index 362d9a8..3db14b2 100644 --- a/src/vulkan_detour.h +++ b/src/vulkan_detour.h @@ -7,4 +7,4 @@ bool install_vk_create_device_hook(); bool device_supports_external_extensions(VkPhysicalDevice physical_device); -} +} //namespace gdvapi