@@ -12,10 +12,14 @@ file, You can obtain one at https://mozilla.org/MPL/2.0/.
1212#include < godot_cpp/classes/engine.hpp>
1313#include < godot_cpp/classes/os.hpp>
1414#include < godot_cpp/classes/project_settings.hpp>
15+ #include < godot_cpp/classes/rd_texture_format.hpp>
16+ #include < godot_cpp/classes/rd_texture_view.hpp>
17+ #include < godot_cpp/classes/rendering_server.hpp>
1518
1619using namespace godot ;
1720
1821VideoStreamPlaybackNDI::VideoStreamPlaybackNDI () {
22+ rd = RenderingServer::get_singleton ()->get_rendering_device ();
1923 texture.instantiate ();
2024}
2125
@@ -26,6 +30,12 @@ VideoStreamPlaybackNDI::VideoStreamPlaybackNDI(NDIlib_recv_create_v3_t p_recv_de
2630
2731VideoStreamPlaybackNDI::~VideoStreamPlaybackNDI () {
2832 _stop ();
33+
34+ RID texture_rd_rid = texture->get_texture_rd_rid ();
35+ if (texture_rd_rid.is_valid ()) {
36+ rd->free_rid (texture_rd_rid);
37+ }
38+
2939 texture.unref ();
3040}
3141
@@ -114,50 +124,77 @@ void VideoStreamPlaybackNDI::_update(double p_delta) {
114124
115125void VideoStreamPlaybackNDI::_bind_methods () {}
116126
127+ void VideoStreamPlaybackNDI::update_texture (NDIlib_video_frame_v2_t p_video_frame) {
128+ Vector2i new_texture_size = Vector2i (p_video_frame.xres , p_video_frame.yres );
129+
130+ PackedByteArray data;
131+ data.resize (p_video_frame.line_stride_in_bytes * p_video_frame.yres );
132+ memcpy (data.ptrw (), p_video_frame.p_data , data.size ());
133+
134+ RID texture_rd_rid = texture->get_texture_rd_rid ();
135+
136+ if (new_texture_size == texture_size && texture_rd_rid.is_valid ()) {
137+ rd->texture_update (texture_rd_rid, 0 , data);
138+ } else {
139+ if (texture_rd_rid.is_valid ()) {
140+ rd->free_rid (texture_rd_rid);
141+ }
142+
143+ Ref<RDTextureFormat> tf;
144+ tf.instantiate ();
145+ tf->set_format (RenderingDevice::DATA_FORMAT_B8G8R8A8_UNORM);
146+ tf->set_width (new_texture_size.x );
147+ tf->set_height (new_texture_size.y );
148+ tf->set_usage_bits (RenderingDevice::TEXTURE_USAGE_SAMPLING_BIT | RenderingDevice::TEXTURE_USAGE_CAN_UPDATE_BIT);
149+
150+ // tf->set_depth(1);
151+ // tf->set_array_layers(1);
152+ // tf->set_mipmaps(1);
153+ // tf->set_samples(RenderingDevice::TEXTURE_SAMPLES_1);
154+ // tf->set_texture_type(RenderingDevice::TEXTURE_TYPE_2D);
155+
156+ Ref<RDTextureView> tv;
157+ tv.instantiate ();
158+
159+ Array texture_data = Array ();
160+ texture_data.append (data);
161+
162+ texture_rd_rid = rd->texture_create (tf, tv, texture_data);
163+ tf.unref ();
164+ tv.unref ();
165+
166+ texture->set_texture_rd_rid (texture_rd_rid);
167+
168+ texture_size = new_texture_size;
169+ }
170+ }
171+
117172void VideoStreamPlaybackNDI::wait_for_non_empty_frame () {
118173 for (size_t i = 0 ; i < 1000 ; i++) {
119- ndi->framesync_capture_video (sync, &video_frame, NDIlib_frame_format_type_progressive);
120- if (video_frame.xres != 0 && video_frame.yres != 0 ) {
121- texture->set_image (Image::create_empty (video_frame.xres , video_frame.yres , false , Image::FORMAT_RGBA8));
122- ndi->framesync_free_video (sync, &video_frame);
174+ if (render_video ()) {
123175 return ;
124176 }
125- ndi->framesync_free_video (sync, &video_frame);
126177 OS::get_singleton ()->delay_msec (10 );
127178 }
128179
129180 // Fallback resolution
130- texture->set_image (Image::create_empty (1920 , 1080 , false , Image::FORMAT_RGBA8));
131181 ERR_FAIL_MSG (" NDI: Source not found at playback start. It will play at fallback resolution of 1920x1080 once discovered. See docs for NDIOutput." );
132182}
133183
134- void VideoStreamPlaybackNDI::render_video () {
135- if (img.is_valid ()) {
136- if (texture->get_width () == img->get_width () && texture->get_height () == img->get_height ()) {
137- texture->update (img);
138- } else {
139- texture->set_image (img);
140- }
141- }
184+ bool VideoStreamPlaybackNDI::render_video () {
185+ bool updated = false ;
142186
187+ NDIlib_video_frame_v2_t video_frame;
143188 ndi->framesync_capture_video (sync, &video_frame, NDIlib_frame_format_type_progressive);
144189
145- if (video_frame.p_data != nullptr && (video_frame.FourCC == NDIlib_FourCC_type_RGBA || video_frame.FourCC == NDIlib_FourCC_type_RGBX)) {
146- video_buffer.resize (video_frame.xres * video_frame.yres * 4 );
147-
148- // memcpy(video_buffer.ptrw(), video_frame.p_data, video_buffer.size());
149-
150- for (size_t i = 0 ; i < video_frame.xres * video_frame.yres ; i++) {
151- video_buffer.set (i * 4 + 0 , video_frame.p_data [i * 4 + 2 ]);
152- video_buffer.set (i * 4 + 1 , video_frame.p_data [i * 4 + 1 ]);
153- video_buffer.set (i * 4 + 2 , video_frame.p_data [i * 4 + 0 ]);
154- video_buffer.set (i * 4 + 3 , video_frame.p_data [i * 4 + 3 ]);
155- }
156-
157- img = Image::create_from_data (video_frame.xres , video_frame.yres , false , Image::Format::FORMAT_RGBA8, video_buffer);
190+ if (video_frame.p_data != nullptr && video_frame.xres != 0 && video_frame.yres != 0 && (video_frame.FourCC == NDIlib_FourCC_type_BGRA || video_frame.FourCC == NDIlib_FourCC_type_BGRX)) {
191+ update_texture (video_frame);
192+ updated = true ;
158193 }
159194
160195 ndi->framesync_free_video (sync, &video_frame);
196+
197+ return updated;
161198}
162199
163200void VideoStreamPlaybackNDI::render_audio (double p_delta) {
0 commit comments