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