tried (and failed) to get a white rectangle placeholder drawing, also streaming btw

This commit is contained in:
Rhys Tumelty
2026-08-24 16:18:39 +01:00
parent dacbb2e043
commit 97ff779911
17 changed files with 163 additions and 23 deletions

View File

@@ -72,8 +72,8 @@ target_sources(${LIBNAME}
PRIVATE PRIVATE
src/register_types.cpp src/register_types.cpp
src/register_types.h src/register_types.h
src/filevideostream_class.cpp src/gdvapivideostream_class.cpp
src/filevideostream_class.h src/gdvapivideostream_class.h
) )
# Fetch a list of the xml files to use for documentation and add to our target # Fetch a list of the xml files to use for documentation and add to our target

View File

@@ -14,6 +14,11 @@
python3 python3
godot godot
pkg-config pkg-config
gst_all_1.gstreamer
gst_all_1.gst-plugins-base
gst_all_1.gst-plugins-good
gst_all_1.gst-plugins-bad
]; ];
buildInputs = with pkgs; [ buildInputs = with pkgs; [

View File

@@ -3,4 +3,5 @@ entry_symbol = "gdvapi_library_init"
compatibility_minimum = "4.7" compatibility_minimum = "4.7"
[libraries] [libraries]
linux.x86_64 = "res://bin/linux/gdvapi.linux.template_debug.x86_64.so" linux.editor.x86_64 = "res://bin/linux/gdvapi.linux.editor.x86_64.so"
linux.template_debug.x86_64 = "res://bin/linux/gdvapi.linux.template_debug.x86_64.so"

View File

@@ -2,4 +2,5 @@ extends Node
func _ready() -> void: func _ready() -> void:
$FileVideoStream.begin("res://badapple.mov") #$GDVAPIVideoStream.begin("udp://0.0.0.0:5000")
pass

View File

@@ -5,4 +5,6 @@
[node name="Node" type="Node" unique_id=2080300232] [node name="Node" type="Node" unique_id=2080300232]
script = ExtResource("1_jdh55") script = ExtResource("1_jdh55")
[node name="FileVideoStream" type="FileVideoStream" parent="." unique_id=330752336] [node name="GDVAPIVideoStream" type="GDVAPIVideoStream" parent="." unique_id=1053894928]
offset_right = 40.0
offset_bottom = 40.0

View File

@@ -0,0 +1,49 @@
[runnable_presets]
Linux="Linux"
[preset.0]
name="Linux"
platform="Linux"
dedicated_server=false
custom_features=""
export_filter="all_resources"
include_filter=""
exclude_filter=""
export_path="exports/godot cpp template.x86_64"
patches=PackedStringArray()
patch_delta_encoding=false
patch_delta_compression_level_zstd=19
patch_delta_min_reduction=0.1
patch_delta_include_filters="*"
patch_delta_exclude_filters=""
encryption_include_filters=""
encryption_exclude_filters=""
seed=0
encrypt_pck=false
encrypt_directory=false
script_export_mode=2
[preset.0.options]
custom_template/debug=""
custom_template/release=""
debug/export_console_wrapper=1
binary_format/embed_pck=false
texture_format/s3tc_bptc=true
texture_format/etc2_astc=false
shader_baker/enabled=false
binary_format/architecture="x86_64"
ssh_remote_deploy/enabled=false
ssh_remote_deploy/host="user@host_ip"
ssh_remote_deploy/port="22"
ssh_remote_deploy/extra_args_ssh=""
ssh_remote_deploy/extra_args_scp=""
ssh_remote_deploy/run_script="#!/usr/bin/env bash
export DISPLAY=:0
unzip -o -q \"{temp_dir}/{archive_name}\" -d \"{temp_dir}\"
\"{temp_dir}/{exe_name}\" {cmd_args}"
ssh_remote_deploy/cleanup_script="#!/usr/bin/env bash
pkill -x -f \"{temp_dir}/{exe_name} {cmd_args}\"
rm -rf \"{temp_dir}\""

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,4 @@
#!/bin/sh
printf '\033c\033]0;%s\a' godot cpp template
base_path="$(dirname "$(realpath "$0")")"
"$base_path/godot cpp template.x86_64" "$@"

Binary file not shown.

View File

@@ -18,3 +18,8 @@ config/name="godot cpp template"
run/main_scene="uid://dh0oj81pufivs" run/main_scene="uid://dh0oj81pufivs"
config/features=PackedStringArray("4.7", "Forward Plus") config/features=PackedStringArray("4.7", "Forward Plus")
config/icon="res://icon.svg" config/icon="res://icon.svg"
[display]
window/size/viewport_width=1920
window/size/viewport_height=1080

2
server-ffmpeg.sh Executable file
View File

@@ -0,0 +1,2 @@
#!/bin/sh
ffmpeg -re -i $1 -c copy -f mpegts udp://127.0.0.1:5000

5
server-gst.sh Normal file
View File

@@ -0,0 +1,5 @@
#!/bin/sh
gst-launch-1.0 filesrc location=$1 ! qtdemux name=demux \
demux.video_0 ! queue ! h264parse ! mpegtsmux name=mux ! udpsink host=127.0.0.1 port=5000 \
demux.audio_0 ! queue ! aacparse ! mux.

5
server_camera.sh Executable file
View File

@@ -0,0 +1,5 @@
#!/bin/sh
ffmpeg -f v4l2 -input_format mjpeg -video_size 1920x1080 -framerate 30 -i "$1" \
-c:v libx264 -preset ultrafast -tune zerolatency -g 30 -flags +global_header \
-f mpegts udp://127.0.0.1:5000?pkt_size=1316

View File

@@ -1,10 +1,12 @@
#include "filevideostream_class.h" #include "gdvapivideostream_class.h"
#include "godot_cpp/classes/project_settings.hpp" #include "godot_cpp/classes/project_settings.hpp"
#include "godot_cpp/classes/rd_texture_format.hpp" #include "godot_cpp/classes/rd_texture_format.hpp"
#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/utility_functions.hpp"
#include "godot_cpp/variant/color.hpp"
#include "godot_cpp/variant/rect2.hpp"
extern "C" { extern "C" {
#include <libavcodec/avcodec.h> #include <libavcodec/avcodec.h>
@@ -21,10 +23,20 @@ enum HWMode { HW_NONE,
HW_VAAPI }; HW_VAAPI };
static HWMode active_hw_mode = HW_NONE; static HWMode active_hw_mode = HW_NONE;
void FileVideoStream::_bind_methods() { void GDVAPIVideoStream::_bind_methods() {
godot::ClassDB::bind_method(D_METHOD("begin", "source"), &FileVideoStream::begin); godot::ClassDB::bind_method(D_METHOD("begin", "source"), &GDVAPIVideoStream::begin);
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");
} }
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) {
@@ -39,7 +51,7 @@ static enum AVPixelFormat get_hw_format(AVCodecContext *ctx, const enum AVPixelF
return AV_PIX_FMT_NONE; return AV_PIX_FMT_NONE;
} }
void FileVideoStream::begin(const Variant &source) { void GDVAPIVideoStream::begin(const Variant &source) {
String res_path = source; String res_path = source;
String global_path = ProjectSettings::get_singleton()->globalize_path(res_path); String global_path = ProjectSettings::get_singleton()->globalize_path(res_path);
CharString path_utf8 = global_path.utf8(); CharString path_utf8 = global_path.utf8();
@@ -120,7 +132,7 @@ void FileVideoStream::begin(const Variant &source) {
set_process(true); set_process(true);
} }
void FileVideoStream::_process(double delta) { void GDVAPIVideoStream::_process(double delta) {
if (!fmt_ctx || !codec_ctx) return; if (!fmt_ctx || !codec_ctx) return;
time_accumulator += delta; time_accumulator += delta;
@@ -182,11 +194,11 @@ void FileVideoStream::_process(double delta) {
} }
} }
FileVideoStream::~FileVideoStream() { GDVAPIVideoStream::~GDVAPIVideoStream() {
cleanup(); cleanup();
} }
void FileVideoStream::_notification(int p_what) { void GDVAPIVideoStream::_notification(int p_what) {
switch (p_what) { switch (p_what) {
case NOTIFICATION_EXIT_TREE: { case NOTIFICATION_EXIT_TREE: {
cleanup(); cleanup();
@@ -194,7 +206,7 @@ void FileVideoStream::_notification(int p_what) {
} }
} }
void FileVideoStream::texture_init() { void GDVAPIVideoStream::texture_init() {
RenderingDevice *rd = RenderingServer::get_singleton()->get_rendering_device(); RenderingDevice *rd = RenderingServer::get_singleton()->get_rendering_device();
if (!rd) if (!rd)
return; return;
@@ -232,7 +244,7 @@ void FileVideoStream::texture_init() {
} }
} }
void FileVideoStream::cleanup() { void GDVAPIVideoStream::cleanup() {
set_process(false); set_process(false);
RenderingDevice *rd = RenderingServer::get_singleton()->get_rendering_device(); RenderingDevice *rd = RenderingServer::get_singleton()->get_rendering_device();
@@ -268,8 +280,45 @@ void FileVideoStream::cleanup() {
} }
} }
void FileVideoStream::_draw() { void GDVAPIVideoStream::_draw() {
UtilityFunctions::print("_draw called");
if (godot_texture.is_valid()) { if (godot_texture.is_valid()) {
draw_texture(godot_texture, Point2(0, 0)); draw_texture(godot_texture, Point2(0, 0));
} else {
Rect2 rect = Rect2(0, 0, desiredWidth, desiredHeight);
Color color = Color(1.0, 1.0, 1.0, 1.0);
draw_rect(rect, color);
} }
} }
void GDVAPIVideoStream::set_desired_width(const int v) {
if (desiredWidth != v) {
desiredWidth = v;
queue_redraw();
}
}
void GDVAPIVideoStream::set_desired_height(const int v) {
if (desiredHeight != v) {
desiredHeight = v;
queue_redraw();
}
}
int GDVAPIVideoStream::get_desired_width() const {
return desiredWidth;
}
int GDVAPIVideoStream::get_desired_height() const {
return desiredHeight;
}
void GDVAPIVideoStream::_ready() {
UtilityFunctions::print("_ready called");
queue_redraw();
}

View File

@@ -1,4 +1,4 @@
#pragma once #pragma once
#include "godot_cpp/classes/control.hpp" #include "godot_cpp/classes/control.hpp"
#include "godot_cpp/classes/texture2drd.hpp" #include "godot_cpp/classes/texture2drd.hpp"
@@ -13,8 +13,8 @@ extern "C" {
namespace godot { namespace godot {
class FileVideoStream : public Control { class GDVAPIVideoStream : public Control {
GDCLASS(FileVideoStream, Control) GDCLASS(GDVAPIVideoStream, Control)
private: private:
AVFormatContext *fmt_ctx = nullptr; AVFormatContext *fmt_ctx = nullptr;
@@ -35,6 +35,10 @@ private:
RID texture_rd_rid; RID texture_rd_rid;
Ref<Texture2DRD> godot_texture; Ref<Texture2DRD> godot_texture;
int desiredWidth = 256;
int desiredHeight = 256;
void cleanup(); void cleanup();
void texture_init(); void texture_init();
@@ -42,8 +46,8 @@ protected:
static void _bind_methods(); static void _bind_methods();
public: public:
FileVideoStream() = default; GDVAPIVideoStream() = default;
~FileVideoStream() override; ~GDVAPIVideoStream() override;
void begin(const Variant &source); void begin(const Variant &source);
@@ -51,6 +55,13 @@ public:
void _notification(int p_what); void _notification(int p_what);
void _draw() override; void _draw() override;
void _ready() override;
void set_desired_width(const int v);
int get_desired_width() const;
void set_desired_height(const int v);
int get_desired_height() const;
}; };
} }

View File

@@ -5,7 +5,7 @@
#include <godot_cpp/core/defs.hpp> #include <godot_cpp/core/defs.hpp>
#include <godot_cpp/godot.hpp> #include <godot_cpp/godot.hpp>
#include "filevideostream_class.h" #include "gdvapivideostream_class.h"
using namespace godot; using namespace godot;
@@ -13,9 +13,11 @@ void initialize_gdextension_types(ModuleInitializationLevel p_level) {
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) { if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
return; return;
} }
GDREGISTER_CLASS(FileVideoStream);
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;
@@ -23,7 +25,6 @@ void uninitialize_gdextension_types(ModuleInitializationLevel p_level) {
} }
extern "C" { extern "C" {
// Initialization
GDExtensionBool GDE_EXPORT gdvapi_library_init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) { GDExtensionBool GDE_EXPORT gdvapi_library_init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) {
GDExtensionBinding::InitObject init_obj(p_get_proc_address, p_library, r_initialization); GDExtensionBinding::InitObject init_obj(p_get_proc_address, p_library, r_initialization);
init_obj.register_initializer(initialize_gdextension_types); init_obj.register_initializer(initialize_gdextension_types);