From d569209b52ca414d2f403713fc42b046adc28d6f Mon Sep 17 00:00:00 2001 From: Roman Buldygin Date: Sun, 1 Dec 2024 00:55:30 +0300 Subject: [PATCH 01/25] Using geodesic.h from repo --- app/telemetry/tutil/geodesi_helper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/telemetry/tutil/geodesi_helper.cpp b/app/telemetry/tutil/geodesi_helper.cpp index 4f3129e7d..4ef9f807c 100644 --- a/app/telemetry/tutil/geodesi_helper.cpp +++ b/app/telemetry/tutil/geodesi_helper.cpp @@ -3,7 +3,7 @@ #include extern "C" { -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) || defined(Q_OS_WIN) #include "lib/geographiclib-c-2.0/src/geodesic.h" #else #include "geodesic.h" From 2091286fee023e4d2c367365d702798bc782ef42 Mon Sep 17 00:00:00 2001 From: Raphael <68374617+raphaelscholle@users.noreply.github.com> Date: Sun, 1 Dec 2024 03:33:09 +0100 Subject: [PATCH 02/25] make linux work again ;) --- app/videostreaming/gstreamer/gst_video.pri | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/videostreaming/gstreamer/gst_video.pri b/app/videostreaming/gstreamer/gst_video.pri index 635c7bcf8..9b4668420 100644 --- a/app/videostreaming/gstreamer/gst_video.pri +++ b/app/videostreaming/gstreamer/gst_video.pri @@ -76,7 +76,7 @@ android { } else { message("GStreamer prebuilt directory does not exist") } -} else { +} windows { # GStreamer configuration for non-Android platforms GST_ROOT = c:/gstreamer/1.0/x86_64 @@ -103,5 +103,9 @@ android { $$GST_ROOT/lib/gstreamer-1.0/include \ $$GST_ROOT/lib/glib-2.0/include - } + }else { + message(gst linux) + CONFIG += link_pkgconfig + PKGCONFIG += gstreamer-1.0 gstreamer-video-1.0 gstreamer-gl-1.0 gstreamer-app-1.0 #gstreamer1.0-plugins-good + } From 0afe7278072588d084cc065b9f18e30be045375f Mon Sep 17 00:00:00 2001 From: Raphael <68374617+raphaelscholle@users.noreply.github.com> Date: Sun, 1 Dec 2024 03:37:20 +0100 Subject: [PATCH 03/25] revert windows gstreamer until it works --- app/videostreaming/gstreamer/gst_video.pri | 119 ++++++++++----------- 1 file changed, 54 insertions(+), 65 deletions(-) diff --git a/app/videostreaming/gstreamer/gst_video.pri b/app/videostreaming/gstreamer/gst_video.pri index 9b4668420..cf54f3331 100644 --- a/app/videostreaming/gstreamer/gst_video.pri +++ b/app/videostreaming/gstreamer/gst_video.pri @@ -1,11 +1,8 @@ -# Enable GStreamer QMLGLSink for video rendering DEFINES += QOPENHD_ENABLE_GSTREAMER_QMLGLSINK -# Uncomment for primary video, keep secondary for now -# DEFINES += QOPENHD_GSTREAMER_PRIMARY_VIDEO +#DEFINES += QOPENHD_GSTREAMER_PRIMARY_VIDEO DEFINES += QOPENHD_GSTREAMER_SECONDARY_VIDEO -# Sources and headers specific to GStreamer SOURCES += \ $$PWD/gstqmlglsinkstream.cpp \ $$PWD/gstrtpaudioplayer.cpp \ @@ -17,14 +14,16 @@ HEADERS += \ $$PWD/gstrtpaudioplayer.h \ $$PWD/gstrtpreceiver.h -# Platform-specific configurations -android { - message("Configuring GStreamer for Android") +android{ + message("gst android") + # More or less taken from QGroundControl. + # this is already the "least dirty" solution I could come up with :/ + #DOWNLOADED_GST_FOLDER= /home/hyperion/gstreamer-1.0-android-universal-1.20.5 + #DOWNLOADED_GST_FOLDER= /home/consti10/Downloads/gstreamer-1.0-android-universal-1.20.5 + #DOWNLOADED_GST_FOLDER= $$PWD/../../../lib/gstreamer_prebuilts/gstreamer-1.0-android-universal-1.20.5 + DOWNLOADED_GST_FOLDER= $$PWD/../../../lib/gstreamer_prebuilts/gstreamer-1.0-android-universal - # Define the base directory for the GStreamer prebuilt binaries - DOWNLOADED_GST_FOLDER = $$PWD/../../../lib/gstreamer_prebuilts/gstreamer-1.0-android-universal - - # Determine the GStreamer architecture folder based on the target architecture + # Set the right folder for the compile arch GSTREAMER_ARCH_FOLDER = armv7 contains(ANDROID_TARGET_ARCH, armeabi-v7a) { GSTREAMER_ARCH_FOLDER = armv7 @@ -33,79 +32,69 @@ android { } else:contains(ANDROID_TARGET_ARCH, x86_64) { GSTREAMER_ARCH_FOLDER = x86_64 } else { - message("Unknown ANDROID_TARGET_ARCH: $$ANDROID_TARGET_ARCH") + message(Unknown ANDROID_TARGET_ARCH $$ANDROID_TARGET_ARCH) GSTREAMER_ARCH_FOLDER = armv7 } - # Define the root path for GStreamer + #GSTREAMER_ARCH_FOLDER = arm64 + GSTREAMER_ROOT_ANDROID = $$DOWNLOADED_GST_FOLDER/$$GSTREAMER_ARCH_FOLDER - message("GStreamer root for Android: $$GSTREAMER_ROOT_ANDROID") + message(gstreamer root android:) + message($$GSTREAMER_ROOT_ANDROID) GST_ROOT = $$GSTREAMER_ROOT_ANDROID - - # Check if the GStreamer root directory exists exists($$GST_ROOT) { - message("Setting up GStreamer for Android build") - QMAKE_CXXFLAGS += -pthread - CONFIG += VideoEnabled + message(Doing QGC gstreamer stuff) + message($$GST_ROOT) + QMAKE_CXXFLAGS += -pthread + CONFIG += VideoEnabled - # Link GStreamer libraries LIBS += -L$$GST_ROOT/lib/gstreamer-1.0 \ - -lgstvideo-1.0 -lgstcoreelements -lgstplayback -lgstudp \ - -lgstrtp -lgstrtsp -lgstx264 -lgstlibav -lgstsdpelem \ - -lgstvideoparsersbad -lgstrtpmanager -lgstisomp4 \ - -lgstmatroska -lgstmpegtsdemux -lgstandroidmedia \ - -lgstopengl -lgsttcp -lgstapp -lgstalaw -lgstautodetect - + -lgstvideo-1.0 \ + -lgstcoreelements \ + -lgstplayback \ + -lgstudp \ + -lgstrtp \ + -lgstrtsp \ + -lgstx264 \ + -lgstlibav \ + -lgstsdpelem \ + -lgstvideoparsersbad \ + -lgstrtpmanager \ + -lgstisomp4 \ + -lgstmatroska \ + -lgstmpegtsdemux \ + -lgstandroidmedia \ + -lgstopengl \ + -lgsttcp \ + -lgstapp \ + -lgstalaw \ + -lgstautodetect + + + # Rest of GStreamer dependencies LIBS += -L$$GST_ROOT/lib \ - -lgraphene-1.0 -ljpeg -lpng16 -lgstfft-1.0 -lm \ - -lgstnet-1.0 -lgio-2.0 -lgstphotography-1.0 -lgstgl-1.0 -lEGL \ - -lgstaudio-1.0 -lgstcodecparsers-1.0 -lgstbase-1.0 -lgstreamer-1.0 \ - -lgstrtp-1.0 -lgstpbutils-1.0 -lgstrtsp-1.0 -lgsttag-1.0 \ - -lgstvideo-1.0 -lavformat -lavcodec -lavutil -lx264 -lavfilter \ - -lswresample -lgstriff-1.0 -lgstcontroller-1.0 -lgstapp-1.0 \ + -lgraphene-1.0 -ljpeg -lpng16 \ + -lgstfft-1.0 -lm \ + -lgstnet-1.0 -lgio-2.0 \ + -lgstphotography-1.0 -lgstgl-1.0 -lEGL \ + -lgstaudio-1.0 -lgstcodecparsers-1.0 -lgstbase-1.0 \ + -lgstreamer-1.0 -lgstrtp-1.0 -lgstpbutils-1.0 -lgstrtsp-1.0 -lgsttag-1.0 \ + -lgstvideo-1.0 -lavformat -lavcodec -lavutil -lx264 -lavfilter -lswresample \ + -lgstriff-1.0 -lgstcontroller-1.0 -lgstapp-1.0 \ -lgstsdp-1.0 -lbz2 -lgobject-2.0 -lgstmpegts-1.0 \ - -Wl,--export-dynamic -lgmodule-2.0 -pthread -lglib-2.0 -lorc-0.4 -liconv -lffi -lintl + -Wl,--export-dynamic -lgmodule-2.0 -pthread -lglib-2.0 -lorc-0.4 -liconv -lffi -lintl \ - # Include paths for GStreamer INCLUDEPATH += \ $$GST_ROOT/include/gstreamer-1.0 \ $$GST_ROOT/lib/gstreamer-1.0/include \ $$GST_ROOT/include/glib-2.0 \ $$GST_ROOT/lib/glib-2.0/include - } else { - message("GStreamer prebuilt directory does not exist") - } -} windows { - # GStreamer configuration for non-Android platforms - GST_ROOT = c:/gstreamer/1.0/x86_64 - - exists($$GST_ROOT) { - CONFIG += VideoEnabled - - # Link GStreamer libraries - LIBS += -L$$GST_ROOT/lib -lopengl32 - - LIBS += -lgstfft-1.0 \ - -lgstnet-1.0 -lgio-2.0 \ - -lgstaudio-1.0 -lgstcodecparsers-1.0 -lgstbase-1.0 \ - -lgstreamer-1.0 -lgstrtp-1.0 -lgstpbutils-1.0 -lgstrtsp-1.0 -lgsttag-1.0 \ - -lgstvideo-1.0 \ - -lgstriff-1.0 -lgstcontroller-1.0 -lgstapp-1.0 \ - -lgstsdp-1.0 -lbz2 -lgobject-2.0 \ - -lgstgl-1.0 -lgraphene-1.0 -lpng16 -ljpeg -lgstphotography-1.0 \ - -lgmodule-2.0 -lglib-2.0 -lorc-0.4 -lffi -lintl - - # Include paths for GStreamer - INCLUDEPATH += \ - $$GST_ROOT/include/gstreamer-1.0 \ - $$GST_ROOT/include/glib-2.0 \ - $$GST_ROOT/lib/gstreamer-1.0/include \ - $$GST_ROOT/lib/glib-2.0/include - }else { + message(Gstreamer prebuilt directory does not exist) + } +}else { message(gst linux) CONFIG += link_pkgconfig PKGCONFIG += gstreamer-1.0 gstreamer-video-1.0 gstreamer-gl-1.0 gstreamer-app-1.0 #gstreamer1.0-plugins-good - } From a6e0bb9c4e09c69c649209cba9fb3116f7ba5bad Mon Sep 17 00:00:00 2001 From: Raphael <68374617+raphaelscholle@users.noreply.github.com> Date: Sun, 1 Dec 2024 03:40:04 +0100 Subject: [PATCH 04/25] revert more windows stuff for now --- QOpenHD.pro | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/QOpenHD.pro b/QOpenHD.pro index 102e0a0be..28fb86dd0 100755 --- a/QOpenHD.pro +++ b/QOpenHD.pro @@ -234,17 +234,6 @@ JetsonBuild { WindowsBuild { # This aparently makes qt use absolute paths, otherwise we get compile issues ? QMAKE_PROJECT_DEPTH = 0 - #include(app/videostreaming/gstreamer/gst_video.pri) - #include(app/videostreaming/avcodec/avcodec_video.pri) - # Path to FFmpeg headers - # INCLUDEPATH += C:/ffmpeg - #INCLUDEPATH += C:/ffmpeg/libavutil/ - - # Path to FFmpeg libraries - #LIBS += -LC:/ffmpeg/lib - - # Link against the required FFmpeg libraries - #LIBS += -lavcodec -lavformat -lavutil -lswscale -lswresample } AndroidBuild { From 51832fefd16c0ad6c78551047df939c80967a276 Mon Sep 17 00:00:00 2001 From: Raphael <68374617+raphaelscholle@users.noreply.github.com> Date: Sun, 1 Dec 2024 13:30:15 +0100 Subject: [PATCH 05/25] Update MavlinkChoiceElement2.qml --- qml/ui/sidebar/MavlinkChoiceElement2.qml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/qml/ui/sidebar/MavlinkChoiceElement2.qml b/qml/ui/sidebar/MavlinkChoiceElement2.qml index e7bb6d387..120a85697 100644 --- a/qml/ui/sidebar/MavlinkChoiceElement2.qml +++ b/qml/ui/sidebar/MavlinkChoiceElement2.qml @@ -76,10 +76,10 @@ BaseJoyEditElement2{ } function open_choices_menu(clickable){ - // if(!m_param_exists){ - // _qopenhd.show_toast("N/A"); - // return; - // } + if(!m_param_exists){ + _qopenhd.show_toast("N/A"); + return; + } if(m_settings_model.ui_is_busy){ _qopenhd.show_toast("Busy, please try again later"); return; From d5b66cc716a2ff75ea0b8d8c16052a9a8a1d0cb7 Mon Sep 17 00:00:00 2001 From: Raphael <68374617+raphaelscholle@users.noreply.github.com> Date: Sun, 1 Dec 2024 13:36:06 +0100 Subject: [PATCH 06/25] Update MavlinkChoiceElement.qml --- qml/ui/sidebar/MavlinkChoiceElement.qml | 38 +++++++++++++------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/qml/ui/sidebar/MavlinkChoiceElement.qml b/qml/ui/sidebar/MavlinkChoiceElement.qml index 7de8ac144..684219526 100644 --- a/qml/ui/sidebar/MavlinkChoiceElement.qml +++ b/qml/ui/sidebar/MavlinkChoiceElement.qml @@ -44,21 +44,23 @@ BaseJoyEditElement{ ListElement {value: 200; verbose:"200%"} } ListModel{ - id: elements_model_exposure - ListElement {value: -3; verbose:"-3"} - ListElement {value: -2; verbose:"-2"} - ListElement {value: -1; verbose:"-1"} - ListElement {value: 0; verbose:"0"} - ListElement {value: 1; verbose:"+1%"} - ListElement {value: 2; verbose:"+2"} - ListElement {value: 3; verbose:"+3"} + id: elements_model_saturation + ListElement {value: 50; verbose:"50%"} + ListElement {value: 75; verbose:"75%"} + ListElement {value: 90; verbose:"90%"} + ListElement {value: 100; verbose:"100%\n(Default)"} + ListElement {value: 110; verbose:"110%"} + ListElement {value: 125; verbose:"125%"} + ListElement {value: 150; verbose:"150%"} } ListModel{ - id: elements_model_metering - ListElement {value: "centre"; verbose:"center"} - ListElement {value: "spot"; verbose:"spot"} - ListElement {value: "matrix"; verbose:"matrix"} - + id: elements_model_contrast + ListElement {value: 50; verbose:"50%"} + ListElement {value: 75; verbose:"75%"} + ListElement {value: 90; verbose:"90%"} + ListElement {value: 100; verbose:"100%\n(Default)"} + ListElement {value: 125; verbose:"125%"} + ListElement {value: 150; verbose:"150%"} } ListModel{ id: elements_model_sharpness @@ -89,7 +91,7 @@ BaseJoyEditElement{ id: elements_model_air_recording ListElement {value: 0; verbose:"ALWAYS\nOFF"} ListElement {value: 1; verbose:"ALWAYS\nON"} - ListElement {value: 2; verbose:"AUTO\n(WHEN ARMED)"} + ListElement {value: 2; verbose:"AUTO\n(WHEN ARMED)"} } ListModel{ id: elements_model_hotspot @@ -150,10 +152,10 @@ BaseJoyEditElement{ function get_model(){ if(m_param_id=="BRIGHTNESS"){ return elements_model_brightness; - }else if(m_param_id=="EXPOSURE"){ - return elements_model_exposure; - }else if(m_param_id=="METERING"){ - return elements_model_metering; + }else if(m_param_id=="SATURATION"){ + return elements_model_saturation; + }else if(m_param_id=="CONTRAST"){ + return elements_model_contrast; }else if(m_param_id=="SHARPNESS"){ return elements_model_sharpness; }else if(m_param_id=="ROTATION"){ From 65baa405124893968b32735df17cff0c60287b84 Mon Sep 17 00:00:00 2001 From: Roman Buldygin Date: Mon, 2 Dec 2024 02:43:09 +0300 Subject: [PATCH 07/25] Scheduling hotfix --- QOpenHD.pro | 1 + app/common/SchedulingHelper.hpp | 28 ++++++++-------------------- 2 files changed, 9 insertions(+), 20 deletions(-) diff --git a/QOpenHD.pro b/QOpenHD.pro index 102e0a0be..809d24d54 100755 --- a/QOpenHD.pro +++ b/QOpenHD.pro @@ -125,6 +125,7 @@ HEADERS += \ app/common/util_fs.h \ app/common/StringHelper.hpp \ app/common/TimeHelper.hpp \ + app/common/SchedulingHelper.hpp \ app/logging/hudlogmessagesmodel.h \ app/logging/loghelper.h \ app/logging/logmessagesmodel.h \ diff --git a/app/common/SchedulingHelper.hpp b/app/common/SchedulingHelper.hpp index 1e350e68c..4e0a72ee7 100644 --- a/app/common/SchedulingHelper.hpp +++ b/app/common/SchedulingHelper.hpp @@ -6,41 +6,29 @@ #define WIFIBROADCAST_SCHEDULINGHELPER_H #include -#include #include #include #include #include +#ifdef __windows__ +#include +#endif namespace SchedulingHelper { -static void printCurrentThreadPriority(const std::string& name) { - int which = PRIO_PROCESS; - id_t pid = (id_t) getpid(); - int priority = getpriority(which, pid); - //wifibroadcast::log::get_default()->debug("{} has priority {}",name,priority); -} - -static void printCurrentThreadSchedulingPolicy(const std::string& name) { - auto self = pthread_self(); - int policy; - sched_param param{}; - auto result = pthread_getschedparam(self, &policy, ¶m); - if (result != 0) { - qDebug()<<"Cannot get thread scheduling policy"; - } - //wifibroadcast::log::get_default()->debug("{} has policy {} and priority {}",name,policy,param.sched_priority); -} - // this thread should run as close to realtime as possible static void setThreadParamsMaxRealtime(pthread_t target) { - int policy = SCHED_FIFO; + +// TODO: windows.h contains THREAD_PRIORITY_TIME_CRITICAL but not working +#ifndef __windows__ + int policy = SCHED_FIFO; sched_param param{}; param.sched_priority = sched_get_priority_max(policy); auto result = pthread_setschedparam(target, policy, ¶m); if (result != 0) { qDebug()<<"cannot set ThreadParamsMaxRealtime"; } +#endif } static void setThreadParamsMaxRealtime() { From 91f87acc91ba222f8fb2c4768d50c8fc2b26dedb Mon Sep 17 00:00:00 2001 From: Roman Buldygin Date: Mon, 2 Dec 2024 02:45:44 +0300 Subject: [PATCH 08/25] windows build --- QOpenHD.pro | 6 +++ app/main.cpp | 4 ++ app/videostreaming/avcodec/avcodec_helper.hpp | 3 +- app/videostreaming/avcodec/avcodec_video.pri | 20 ++++++-- app/videostreaming/avcodec/color_helper.h | 22 +++++---- app/videostreaming/avcodec/gl/gl_shaders.cpp | 6 +-- .../avcodec/gl/gl_videorenderer.cpp | 12 +++-- app/videostreaming/avcodec/gl/glhelp.h | 7 ++- .../avcodec/texturerenderer.cpp | 1 - app/videostreaming/vscommon/rtp/RTP.hpp | 10 +++- .../vscommon/udp/UDPReceiver.cpp | 48 ++++++++++++++++--- app/videostreaming/vscommon/vscommon.pri | 38 ++++++--------- 12 files changed, 122 insertions(+), 55 deletions(-) diff --git a/QOpenHD.pro b/QOpenHD.pro index 809d24d54..ceab66acf 100755 --- a/QOpenHD.pro +++ b/QOpenHD.pro @@ -103,6 +103,12 @@ LinuxBuild { include(app/videostreaming/gstreamer/gst_video.pri) } +# gst Qt plugins in windows is hard +WindowsBuild { + # In future is better to use windows decoding and rendering api + include(app/videostreaming/avcodec/avcodec_video.pri) +} + # All Generic files / files that literally have 0!! dependencies other than qt SOURCES += \ app/adsb/adsbvehicle.cpp \ diff --git a/app/main.cpp b/app/main.cpp index 613a11a37..1eaec56c7 100755 --- a/app/main.cpp +++ b/app/main.cpp @@ -235,6 +235,10 @@ static void android_check_permissions(){ int main(int argc, char *argv[]) { +#if defined(__windows__) + QCoreApplication::setAttribute(Qt::AA_UseOpenGLES); +#endif + QCoreApplication::setOrganizationName("OpenHD"); QCoreApplication::setOrganizationDomain("openhd"); QCoreApplication::setApplicationName("QOpenHD"); diff --git a/app/videostreaming/avcodec/avcodec_helper.hpp b/app/videostreaming/avcodec/avcodec_helper.hpp index 1528530ee..14201e09b 100644 --- a/app/videostreaming/avcodec/avcodec_helper.hpp +++ b/app/videostreaming/avcodec/avcodec_helper.hpp @@ -16,8 +16,7 @@ extern "C" { #include #include #include -// -#include "libavutil/frame.h" +#include #include "libavutil/hwcontext.h" #include "libavutil/hwcontext_drm.h" #include "libavutil/pixdesc.h" diff --git a/app/videostreaming/avcodec/avcodec_video.pri b/app/videostreaming/avcodec/avcodec_video.pri index 4872c9809..1ad6c19a9 100644 --- a/app/videostreaming/avcodec/avcodec_video.pri +++ b/app/videostreaming/avcodec/avcodec_video.pri @@ -1,9 +1,20 @@ INCLUDEPATH += $$PWD -INCLUDEPATH += C:/ffmpeg/include -LIBS += -LC:/ffmpeg/lib -lavcodec -lavutil -lavformat # TODO dirty -LIBS += -lGLESv2 -lEGL +WindowsBuild { + INCLUDEPATH += $$PWD/../../../build-libs-windows/ffmpeg/include + LIBS += -L$$PWD/../../../build-libs-windows/ffmpeg/lib -lavcodec -lavutil -lavformat + + INCLUDEPATH += $$PWD/../../../build-libs-windows/angle-x64/include + LIBS += -L$$PWD/../../../build-libs-windows/angle-x64/bin -lGLESv2 -lEGL + + DEFINES += EGL_EGLEXT_PROTOTYPES + DEFINES += GL_GLEXT_PROTOTYPES +# LIBS += -lOpengl32 +} +else { + LIBS += -lGLESv2 -lEGL +} # just using the something something webrtc from stephen was the easiest solution. #include(../../lib/h264/h264.pri) @@ -21,8 +32,7 @@ HEADERS += \ $$PWD/gl/gl_videorenderer.h \ $$PWD/texturerenderer.h \ $$PWD/avcodec_decoder.h \ - - + $$PWD/avcodec_helper.hpp # experimental #INCLUDEPATH += /usr/local/include/uvgrtp diff --git a/app/videostreaming/avcodec/color_helper.h b/app/videostreaming/avcodec/color_helper.h index f56c24ee9..072efbb7f 100644 --- a/app/videostreaming/avcodec/color_helper.h +++ b/app/videostreaming/avcodec/color_helper.h @@ -9,14 +9,20 @@ #include static uint32_t create_pixel_rgba(uint8_t r,uint8_t g,uint8_t b,uint8_t a){ - uint8_t rgba[4]; - rgba[0]=r; - rgba[1]=g; - rgba[2]=b; - rgba[3]=a; - uint32_t ret; - memcpy(&ret,rgba,4); - return ret; +#ifdef __windows__ + return ((uint32_t)a << 24) | ((uint32_t)b << 16) | ((uint32_t)g << 8) | (uint32_t)r; +#else + uint8_t rgba[4]; + rgba[0]=r; + rgba[1]=g; + rgba[2]=b; + rgba[3]=a; + uint32_t ret; + memcpy(&ret,rgba,4); + return ret; +#endif + + } // --------------------------------------------------- from drm-howto --------------------------------------------------- diff --git a/app/videostreaming/avcodec/gl/gl_shaders.cpp b/app/videostreaming/avcodec/gl/gl_shaders.cpp index 6aa40f2a9..08afd96fc 100644 --- a/app/videostreaming/avcodec/gl/gl_shaders.cpp +++ b/app/videostreaming/avcodec/gl/gl_shaders.cpp @@ -111,9 +111,9 @@ static const GLchar* fragment_shader_source_NV12 = " texture2D(s_texture_uv,v_texCoord).xy\n" " );" " mat3 colorMatrix = mat3(\n" - " 1.1644f, 1.1644f, 1.1644f,\n" - " 0.0f, -0.3917f, 2.0172f,\n" - " 1.5960f, -0.8129f, 0.0f" + " 1.1644, 1.1644, 1.1644,\n" + " 0.0, -0.3917, 2.0172,\n" + " 1.5960, -0.8129, 0.0" " );\n" " gl_FragColor = vec4(clamp(YCbCr*colorMatrix,0.0,1.0), 1.0);\n" "}\n"; diff --git a/app/videostreaming/avcodec/gl/gl_videorenderer.cpp b/app/videostreaming/avcodec/gl/gl_videorenderer.cpp index 9aaf5c9af..47287d003 100644 --- a/app/videostreaming/avcodec/gl/gl_videorenderer.cpp +++ b/app/videostreaming/avcodec/gl/gl_videorenderer.cpp @@ -5,7 +5,12 @@ #include "gl_videorenderer.h" #include "../color_helper.h" #include +#include +#include #include +#include "../avcodec_helper.hpp" +#include +#include static EGLint texgen_attrs[] = { EGL_DMA_BUF_PLANE0_FD_EXT, @@ -34,9 +39,10 @@ static void create_rgba_texture(GLuint& tex_id,uint32_t color_rgba){ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); const int width=1280; const int height=720; - uint8_t pixels[4*width*height]; - fillFrame(pixels,width,height,width*4, color_rgba); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + std::vector pixels(4*width*height); + + fillFrame(pixels.data(), width, height, width*4, color_rgba); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data()); glBindTexture(GL_TEXTURE_2D,0); } diff --git a/app/videostreaming/avcodec/gl/glhelp.h b/app/videostreaming/avcodec/gl/glhelp.h index a015c1aaf..23add8b11 100644 --- a/app/videostreaming/avcodec/gl/glhelp.h +++ b/app/videostreaming/avcodec/gl/glhelp.h @@ -1,6 +1,7 @@ #ifndef GLHELP_H #define GLHELP_H +extern "C" { #include #include // Crude hack for QT on the rpi. Fucking hell, how annyoing this QT crap with redefining opengl is ! @@ -11,12 +12,14 @@ //#include //#include - +} #include /// Some gl extensions that don't seem to be part of raspberry gl. /// I think you could get these from other places like GLAD or libepoxy. /// + +#ifndef __windows__ EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list) __attribute__((weak)); // May not be in libEGL symbol table, resolve manually :( EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list) { @@ -61,6 +64,8 @@ void glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image) } imageTargetTexture2DOES(target, image); } + +#endif /// END Gl Extensions -------------------------------------------------- diff --git a/app/videostreaming/avcodec/texturerenderer.cpp b/app/videostreaming/avcodec/texturerenderer.cpp index 398f3ec8d..429411709 100644 --- a/app/videostreaming/avcodec/texturerenderer.cpp +++ b/app/videostreaming/avcodec/texturerenderer.cpp @@ -1,5 +1,4 @@ #include "texturerenderer.h" -#include "avcodec_helper.hpp" #include #include diff --git a/app/videostreaming/vscommon/rtp/RTP.hpp b/app/videostreaming/vscommon/rtp/RTP.hpp index 35e03d5d2..74ecb2c8b 100644 --- a/app/videostreaming/vscommon/rtp/RTP.hpp +++ b/app/videostreaming/vscommon/rtp/RTP.hpp @@ -5,13 +5,21 @@ #ifndef LIVEVIDEO10MS_RTP_HPP #define LIVEVIDEO10MS_RTP_HPP +#if defined(__windows__) +#include +#else #include +#endif + #include #include +#include // This code is written for little endian (aka ARM,x86) byte order #if defined(__macos__) static_assert(__BYTE_ORDER__==LITTLE_ENDIAN); +#elif defined(__windows__) +static_assert(__BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__); #else static_assert(__BYTE_ORDER__==__LITTLE_ENDIAN); #endif @@ -116,7 +124,7 @@ struct nal_unit_header_h265_t{ uint8_t type: 6; //1st byte uint8_t layerId:6; //2nd byte uint8_t tid: 3; //2nd byte -}__attribute__ ((packed)); +}__attribute__ ((packed)) __attribute__ ((gcc_struct)); static_assert(sizeof(nal_unit_header_h265_t)==2); // defined in 4.4.3 FU Header //+---------------+ diff --git a/app/videostreaming/vscommon/udp/UDPReceiver.cpp b/app/videostreaming/vscommon/udp/UDPReceiver.cpp index 49296bed7..971422d97 100644 --- a/app/videostreaming/vscommon/udp/UDPReceiver.cpp +++ b/app/videostreaming/vscommon/udp/UDPReceiver.cpp @@ -2,7 +2,14 @@ #include "UDPReceiver.h" #include "common/StringHelper.hpp" #include "common/SchedulingHelper.hpp" + +#if defined(__windows__) +#include +#define SHUT_RD SD_RECEIVE +#else #include +#endif + #include #include #include @@ -10,11 +17,12 @@ #include #include -#include + #include #include + UDPReceiver::UDPReceiver(std::string tag,Configuration config,DATA_CALLBACK onDataReceivedCallbackX) : m_tag(tag), @@ -58,7 +66,7 @@ void UDPReceiver::stopReceiving() { static void increase_socket_recv_buff_size(int sockfd, const int wanted_rcvbuff_size_bytes) { int recvBufferSize=0; socklen_t len=sizeof(recvBufferSize); - getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &recvBufferSize, &len); + getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, (char *)&recvBufferSize, &len); { std::stringstream ss; ss<<"Default UDP socket recv buffer size:"<(size_t)recvBufferSize){ int wanted_size=wanted_rcvbuff_size_bytes; recvBufferSize=wanted_rcvbuff_size_bytes; - if(setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &wanted_size,len)) { + if(setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, (char *)&wanted_size,len)) { std::cerr<<"Cannot increase UDP buffer size to "<data(),UDP_PACKET_MAX_SIZE, 0,(sockaddr*)&source,&sourceLen); +#ifdef QT_DEBUG + if(tmp < 0) { + auto err = WSAGetLastError(); + qDebug()<<"UDP ERR "<< err; + } +#endif + +#else + ssize_t tmp; if(m_config.enable_nonblocking){ tmp = recvfrom(m_socket,buff->data(),UDP_PACKET_MAX_SIZE, MSG_DONTWAIT,(sockaddr*)&source,&sourceLen); }else{ tmp = recvfrom(m_socket,buff->data(),UDP_PACKET_MAX_SIZE, MSG_WAITALL,(sockaddr*)&source,&sourceLen); } +#endif const ssize_t message_length=tmp; if (message_length > 0) { //else -1 was returned;timeout/No data received if(m_last_received_packet_ts!=std::chrono::steady_clock::time_point{}){ diff --git a/app/videostreaming/vscommon/vscommon.pri b/app/videostreaming/vscommon/vscommon.pri index 35a88d80a..750e08e80 100644 --- a/app/videostreaming/vscommon/vscommon.pri +++ b/app/videostreaming/vscommon/vscommon.pri @@ -3,32 +3,22 @@ INCLUDEPATH += $$PWD # just using the something something webrtc from stephen was the easiest solution. include(../../../lib/h264/h264.pri) -windows { - SOURCES += \ - $$PWD/decodingstatistcs.cpp \ - - HEADERS += \ - $$PWD/decodingstatistcs.h \ - $$PWD/QOpenHDVideoHelper.hpp \ - -} else { - - SOURCES += \ - $$PWD/rtp/ParseRTP.cpp \ - $$PWD/rtp/rtpreceiver.cpp \ - $$PWD/udp/UDPReceiver.cpp \ - $$PWD/decodingstatistcs.cpp \ +SOURCES += \ + $$PWD/rtp/ParseRTP.cpp \ + $$PWD/rtp/rtpreceiver.cpp \ + $$PWD/udp/UDPReceiver.cpp \ + $$PWD/decodingstatistcs.cpp \ - HEADERS += \ +HEADERS += \ $$PWD/nalu/CodecConfigFinder.hpp \ - $$PWD/nalu/NALUnitType.hpp \ - $$PWD/rtp/ParseRTP.h \ - $$PWD/rtp/RTP.hpp \ - $$PWD/rtp/rtpreceiver.h \ - $$PWD/udp/UDPReceiver.h \ - $$PWD/decodingstatistcs.h \ - $$PWD/QOpenHDVideoHelper.hpp \ -} + $$PWD/nalu/NALUnitType.hpp \ + $$PWD/rtp/ParseRTP.h \ + $$PWD/rtp/RTP.hpp \ + $$PWD/rtp/rtpreceiver.h \ + $$PWD/udp/UDPReceiver.h \ + $$PWD/decodingstatistcs.h \ + $$PWD/QOpenHDVideoHelper.hpp \ + HEADERS += \ $$PWD/ExternalDecodeService.hpp \ From cd77627425f1d7c0c5f868db8ba08ce25cbc705b Mon Sep 17 00:00:00 2001 From: Roman Buldygin Date: Mon, 2 Dec 2024 02:47:35 +0300 Subject: [PATCH 09/25] How to --- README.windows.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 README.windows.md diff --git a/README.windows.md b/README.windows.md new file mode 100644 index 000000000..e2f28926a --- /dev/null +++ b/README.windows.md @@ -0,0 +1,10 @@ +How to: +1. Create folder `build-libs-windows` in repository root +2. Download and extract `ffmpeg-release-full-shared.7z` into `build-libs-windows` ( from https://www.gyan.dev/ffmpeg/builds/ ) + Maybe it will be good idea to fix version and put this version in download script +3. Rename extracted folder to `ffmpeg`. Chech that `ffmpeg` folder contains `bin`, `include`, etc. folders. +4. Trying to use prebuild angle from https://github.com/mmozeiko/build-angle + Download latest release and extract to `build-libs-windows`. + Maybe it better to clone/adjust this build pipeline + +5. After build you need to copy `bin` folders content to folder with `.exe` \ No newline at end of file From 2e72a60571d3d8dc79d875663d6465a06c07ab2b Mon Sep 17 00:00:00 2001 From: Raphael <68374617+raphaelscholle@users.noreply.github.com> Date: Sun, 8 Dec 2024 01:43:10 +0100 Subject: [PATCH 10/25] Update QOpenHD.pro --- QOpenHD.pro | 1 - 1 file changed, 1 deletion(-) diff --git a/QOpenHD.pro b/QOpenHD.pro index ceab66acf..0edc7810b 100755 --- a/QOpenHD.pro +++ b/QOpenHD.pro @@ -32,7 +32,6 @@ CONFIG(debug, debug|release) { } else:CONFIG(release, debug|release) { DEFINES += QT_NO_DEBUG CONFIG += installer - CONFIG += force_debug_info DESTDIR = $${OUT_PWD}/release DEFINES += QMLJSDEBUGGER } From 07f00b5795dc64f838f9656b051364a0f3e2f224 Mon Sep 17 00:00:00 2001 From: Raphael <68374617+raphaelscholle@users.noreply.github.com> Date: Sun, 29 Dec 2024 21:28:47 +0100 Subject: [PATCH 11/25] Update gst_video.pri --- app/videostreaming/gstreamer/gst_video.pri | 49 ++++++++++++++-------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/app/videostreaming/gstreamer/gst_video.pri b/app/videostreaming/gstreamer/gst_video.pri index 635c7bcf8..58d88875f 100644 --- a/app/videostreaming/gstreamer/gst_video.pri +++ b/app/videostreaming/gstreamer/gst_video.pri @@ -18,6 +18,8 @@ HEADERS += \ $$PWD/gstrtpreceiver.h # Platform-specific configurations + +# Android-specific configuration android { message("Configuring GStreamer for Android") @@ -51,21 +53,21 @@ android { # Link GStreamer libraries LIBS += -L$$GST_ROOT/lib/gstreamer-1.0 \ - -lgstvideo-1.0 -lgstcoreelements -lgstplayback -lgstudp \ - -lgstrtp -lgstrtsp -lgstx264 -lgstlibav -lgstsdpelem \ - -lgstvideoparsersbad -lgstrtpmanager -lgstisomp4 \ - -lgstmatroska -lgstmpegtsdemux -lgstandroidmedia \ - -lgstopengl -lgsttcp -lgstapp -lgstalaw -lgstautodetect + -lgstvideo-1.0 -lgstcoreelements -lgstplayback -lgstudp \ + -lgstrtp -lgstrtsp -lgstx264 -lgstlibav -lgstsdpelem \ + -lgstvideoparsersbad -lgstrtpmanager -lgstisomp4 \ + -lgstmatroska -lgstmpegtsdemux -lgstandroidmedia \ + -lgstopengl -lgsttcp -lgstapp -lgstalaw -lgstautodetect LIBS += -L$$GST_ROOT/lib \ - -lgraphene-1.0 -ljpeg -lpng16 -lgstfft-1.0 -lm \ - -lgstnet-1.0 -lgio-2.0 -lgstphotography-1.0 -lgstgl-1.0 -lEGL \ - -lgstaudio-1.0 -lgstcodecparsers-1.0 -lgstbase-1.0 -lgstreamer-1.0 \ - -lgstrtp-1.0 -lgstpbutils-1.0 -lgstrtsp-1.0 -lgsttag-1.0 \ - -lgstvideo-1.0 -lavformat -lavcodec -lavutil -lx264 -lavfilter \ - -lswresample -lgstriff-1.0 -lgstcontroller-1.0 -lgstapp-1.0 \ - -lgstsdp-1.0 -lbz2 -lgobject-2.0 -lgstmpegts-1.0 \ - -Wl,--export-dynamic -lgmodule-2.0 -pthread -lglib-2.0 -lorc-0.4 -liconv -lffi -lintl + -lgraphene-1.0 -ljpeg -lpng16 -lgstfft-1.0 -lm \ + -lgstnet-1.0 -lgio-2.0 -lgstphotography-1.0 -lgstgl-1.0 -lEGL \ + -lgstaudio-1.0 -lgstcodecparsers-1.0 -lgstbase-1.0 -lgstreamer-1.0 \ + -lgstrtp-1.0 -lgstpbutils-1.0 -lgstrtsp-1.0 -lgsttag-1.0 \ + -lgstvideo-1.0 -lavformat -lavcodec -lavutil -lx264 -lavfilter \ + -lswresample -lgstriff-1.0 -lgstcontroller-1.0 -lgstapp-1.0 \ + -lgstsdp-1.0 -lbz2 -lgobject-2.0 -lgstmpegts-1.0 \ + -Wl,--export-dynamic -lgmodule-2.0 -pthread -lglib-2.0 -lorc-0.4 -liconv -lffi -lintl # Include paths for GStreamer INCLUDEPATH += \ @@ -76,14 +78,16 @@ android { } else { message("GStreamer prebuilt directory does not exist") } -} else { - # GStreamer configuration for non-Android platforms +} + +# Windows-specific configuration +win32 { GST_ROOT = c:/gstreamer/1.0/x86_64 exists($$GST_ROOT) { CONFIG += VideoEnabled - # Link GStreamer libraries + # Link GStreamer libraries for Windows LIBS += -L$$GST_ROOT/lib -lopengl32 LIBS += -lgstfft-1.0 \ @@ -96,12 +100,21 @@ android { -lgstgl-1.0 -lgraphene-1.0 -lpng16 -ljpeg -lgstphotography-1.0 \ -lgmodule-2.0 -lglib-2.0 -lorc-0.4 -lffi -lintl - # Include paths for GStreamer + # Include paths for GStreamer on Windows INCLUDEPATH += \ $$GST_ROOT/include/gstreamer-1.0 \ $$GST_ROOT/include/glib-2.0 \ $$GST_ROOT/lib/gstreamer-1.0/include \ $$GST_ROOT/lib/glib-2.0/include - + } else { + message("GStreamer root directory for Windows does not exist") } } + +# Linux-specific configuration +unix:!android { + message("Configuring GStreamer for Linux") + + CONFIG += link_pkgconfig + PKGCONFIG += gstreamer-1.0 gstreamer-video-1.0 gstreamer-gl-1.0 gstreamer-app-1.0 +} From dc7e3e9de0ba6fdb4eb979a483025176221f005b Mon Sep 17 00:00:00 2001 From: Raphael <68374617+raphaelscholle@users.noreply.github.com> Date: Sun, 29 Dec 2024 21:57:24 +0100 Subject: [PATCH 12/25] Update UDPReceiver.cpp --- .../vscommon/udp/UDPReceiver.cpp | 198 +++++++----------- 1 file changed, 74 insertions(+), 124 deletions(-) diff --git a/app/videostreaming/vscommon/udp/UDPReceiver.cpp b/app/videostreaming/vscommon/udp/UDPReceiver.cpp index 971422d97..eb915cd95 100644 --- a/app/videostreaming/vscommon/udp/UDPReceiver.cpp +++ b/app/videostreaming/vscommon/udp/UDPReceiver.cpp @@ -1,13 +1,17 @@ - #include "UDPReceiver.h" #include "common/StringHelper.hpp" #include "common/SchedulingHelper.hpp" -#if defined(__windows__) +#ifdef _WIN32 #include +#include #define SHUT_RD SD_RECEIVE +#pragma comment(lib, "Ws2_32.lib") #else #include +#include +#include +#include #endif #include @@ -15,174 +19,120 @@ #include #include #include - -#include - #include - #include - -UDPReceiver::UDPReceiver(std::string tag,Configuration config,DATA_CALLBACK onDataReceivedCallbackX) - : - m_tag(tag), - m_config(config), - m_on_data_received_cb(std::move(onDataReceivedCallbackX)) +UDPReceiver::UDPReceiver(std::string tag, Configuration config, DATA_CALLBACK onDataReceivedCallbackX) + : m_tag(tag), m_config(config), m_on_data_received_cb(std::move(onDataReceivedCallbackX)) { - qDebug()<<"UDPReceiver "<([this]{ - if(m_config.set_sched_param_max_realtime){ + m_receiving = true; + m_receive_thread = std::make_unique([this] { + if (m_config.set_sched_param_max_realtime) { SchedulingHelper::setThreadParamsMaxRealtime(); } - this->receiveFromUDPLoop();} - ); + this->receiveFromUDPLoop(); + }); } void UDPReceiver::stopReceiving() { - m_receiving=false; - //this stops the recvfrom even if in blocking mode - shutdown(m_socket,SHUT_RD); - if(m_receive_thread->joinable()){ + m_receiving = false; + shutdown(m_socket, SHUT_RD); + if (m_receive_thread->joinable()) { m_receive_thread->join(); } m_receive_thread.reset(); - //std::cout<<"UDPReceiver avgDeltaBetween(recvfrom) "<20MBit/s the "default" -// udp receive buffer size is often not enough and the OS might (silently) drop packets on localhost) -static void increase_socket_recv_buff_size(int sockfd, const int wanted_rcvbuff_size_bytes) { - int recvBufferSize=0; - socklen_t len=sizeof(recvBufferSize); - getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, (char *)&recvBufferSize, &len); - { - std::stringstream ss; - ss<<"Default UDP socket recv buffer size:"<(size_t)recvBufferSize){ - int wanted_size=wanted_rcvbuff_size_bytes; - recvBufferSize=wanted_rcvbuff_size_bytes; - if(setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, (char *)&wanted_size,len)) { - std::cerr<<"Cannot increase UDP buffer size to "<>(); - sockaddr_in source; - socklen_t sourceLen= sizeof(sockaddr_in); - + auto buff = std::make_unique>(); + sockaddr_in source = {}; + socklen_t sourceLen = sizeof(sockaddr_in); + while (m_receiving) { - //TODO investigate: does a big buffer size create latency with MSG_WAITALL ? - //I do not think so. recvfrom should return as soon as new data arrived,not when the buffer is full - //But with a bigger buffer we do not loose packets when the receiver thread cannot keep up for a short amount of time - // MSG_WAITALL does not wait until we have __n data, but a new UDP packet (that can be smaller than __n) - //NOTE: NONBLOCKING hogs a whole CPU core ! do not use whenever possible ! - - -#ifdef __windows__ - auto tmp = recvfrom(m_socket,(char *)buff->data(),UDP_PACKET_MAX_SIZE, 0,(sockaddr*)&source,&sourceLen); -#ifdef QT_DEBUG - if(tmp < 0) { - auto err = WSAGetLastError(); - qDebug()<<"UDP ERR "<< err; + ssize_t message_length = recvfrom(m_socket, (char *)buff->data(), UDP_PACKET_MAX_SIZE, 0, (sockaddr *)&source, &sourceLen); + +#ifdef _WIN32 + if (message_length < 0) { + int err = WSAGetLastError(); + qDebug() << "UDP Error:" << err; + continue; } #endif -#else - ssize_t tmp; - if(m_config.enable_nonblocking){ - tmp = recvfrom(m_socket,buff->data(),UDP_PACKET_MAX_SIZE, MSG_DONTWAIT,(sockaddr*)&source,&sourceLen); - }else{ - tmp = recvfrom(m_socket,buff->data(),UDP_PACKET_MAX_SIZE, MSG_WAITALL,(sockaddr*)&source,&sourceLen); - } -#endif - const ssize_t message_length=tmp; - if (message_length > 0) { //else -1 was returned;timeout/No data received - if(m_last_received_packet_ts!=std::chrono::steady_clock::time_point{}){ - //const auto delta=std::chrono::steady_clock::now()-lastReceivedPacket; - //avgDeltaBetweenPackets.add(delta); - } - m_last_received_packet_ts=std::chrono::steady_clock::now(); - //LOGD("Data size %d",(int)message_length); + if (message_length > 0) { m_on_data_received_cb(buff->data(), (size_t)message_length); + m_n_received_bytes += message_length; - m_n_received_bytes+=message_length; - //The source ip stuff - const char* p=inet_ntoa(source.sin_addr); - std::string s1=std::string(p); - if(m_sender_ip!=s1){ - m_sender_ip=s1; - } - }else{ - if(errno != EWOULDBLOCK) { - //MLOGE<<"Error on recvfrom. errno="< Date: Sun, 29 Dec 2024 21:59:23 +0100 Subject: [PATCH 13/25] Revert "Update UDPReceiver.cpp" This reverts commit dc7e3e9de0ba6fdb4eb979a483025176221f005b. --- .../vscommon/udp/UDPReceiver.cpp | 198 +++++++++++------- 1 file changed, 124 insertions(+), 74 deletions(-) diff --git a/app/videostreaming/vscommon/udp/UDPReceiver.cpp b/app/videostreaming/vscommon/udp/UDPReceiver.cpp index eb915cd95..971422d97 100644 --- a/app/videostreaming/vscommon/udp/UDPReceiver.cpp +++ b/app/videostreaming/vscommon/udp/UDPReceiver.cpp @@ -1,17 +1,13 @@ + #include "UDPReceiver.h" #include "common/StringHelper.hpp" #include "common/SchedulingHelper.hpp" -#ifdef _WIN32 +#if defined(__windows__) #include -#include #define SHUT_RD SD_RECEIVE -#pragma comment(lib, "Ws2_32.lib") #else #include -#include -#include -#include #endif #include @@ -19,120 +15,174 @@ #include #include #include + +#include + #include + #include -UDPReceiver::UDPReceiver(std::string tag, Configuration config, DATA_CALLBACK onDataReceivedCallbackX) - : m_tag(tag), m_config(config), m_on_data_received_cb(std::move(onDataReceivedCallbackX)) + +UDPReceiver::UDPReceiver(std::string tag,Configuration config,DATA_CALLBACK onDataReceivedCallbackX) + : + m_tag(tag), + m_config(config), + m_on_data_received_cb(std::move(onDataReceivedCallbackX)) { - qDebug() << "UDPReceiver " << m_tag.c_str() << "with " << m_config.to_string().c_str(); -#ifdef _WIN32 - WSADATA wsaData; - if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { - std::cerr << "WSAStartup failed\n"; - } -#endif + qDebug()<<"UDPReceiver "<([this] { - if (m_config.set_sched_param_max_realtime) { + m_receiving=true; + m_receive_thread=std::make_unique([this]{ + if(m_config.set_sched_param_max_realtime){ SchedulingHelper::setThreadParamsMaxRealtime(); } - this->receiveFromUDPLoop(); - }); + this->receiveFromUDPLoop();} + ); } void UDPReceiver::stopReceiving() { - m_receiving = false; - shutdown(m_socket, SHUT_RD); - if (m_receive_thread->joinable()) { + m_receiving=false; + //this stops the recvfrom even if in blocking mode + shutdown(m_socket,SHUT_RD); + if(m_receive_thread->joinable()){ m_receive_thread->join(); } m_receive_thread.reset(); -#ifdef _WIN32 - closesocket(m_socket); -#else - close(m_socket); -#endif + //std::cout<<"UDPReceiver avgDeltaBetween(recvfrom) "<20MBit/s the "default" +// udp receive buffer size is often not enough and the OS might (silently) drop packets on localhost) +static void increase_socket_recv_buff_size(int sockfd, const int wanted_rcvbuff_size_bytes) { + int recvBufferSize=0; + socklen_t len=sizeof(recvBufferSize); + getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, (char *)&recvBufferSize, &len); + { + std::stringstream ss; + ss<<"Default UDP socket recv buffer size:"<(size_t)recvBufferSize){ + int wanted_size=wanted_rcvbuff_size_bytes; + recvBufferSize=wanted_rcvbuff_size_bytes; + if(setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, (char *)&wanted_size,len)) { + std::cerr<<"Cannot increase UDP buffer size to "<>(); - auto buff = std::make_unique>(); - sockaddr_in source = {}; - socklen_t sourceLen = sizeof(sockaddr_in); - + sockaddr_in source; + socklen_t sourceLen= sizeof(sockaddr_in); + while (m_receiving) { - ssize_t message_length = recvfrom(m_socket, (char *)buff->data(), UDP_PACKET_MAX_SIZE, 0, (sockaddr *)&source, &sourceLen); - -#ifdef _WIN32 - if (message_length < 0) { - int err = WSAGetLastError(); - qDebug() << "UDP Error:" << err; - continue; + //TODO investigate: does a big buffer size create latency with MSG_WAITALL ? + //I do not think so. recvfrom should return as soon as new data arrived,not when the buffer is full + //But with a bigger buffer we do not loose packets when the receiver thread cannot keep up for a short amount of time + // MSG_WAITALL does not wait until we have __n data, but a new UDP packet (that can be smaller than __n) + //NOTE: NONBLOCKING hogs a whole CPU core ! do not use whenever possible ! + + +#ifdef __windows__ + auto tmp = recvfrom(m_socket,(char *)buff->data(),UDP_PACKET_MAX_SIZE, 0,(sockaddr*)&source,&sourceLen); +#ifdef QT_DEBUG + if(tmp < 0) { + auto err = WSAGetLastError(); + qDebug()<<"UDP ERR "<< err; } #endif - if (message_length > 0) { +#else + ssize_t tmp; + if(m_config.enable_nonblocking){ + tmp = recvfrom(m_socket,buff->data(),UDP_PACKET_MAX_SIZE, MSG_DONTWAIT,(sockaddr*)&source,&sourceLen); + }else{ + tmp = recvfrom(m_socket,buff->data(),UDP_PACKET_MAX_SIZE, MSG_WAITALL,(sockaddr*)&source,&sourceLen); + } +#endif + const ssize_t message_length=tmp; + if (message_length > 0) { //else -1 was returned;timeout/No data received + if(m_last_received_packet_ts!=std::chrono::steady_clock::time_point{}){ + //const auto delta=std::chrono::steady_clock::now()-lastReceivedPacket; + //avgDeltaBetweenPackets.add(delta); + } + m_last_received_packet_ts=std::chrono::steady_clock::now(); + //LOGD("Data size %d",(int)message_length); m_on_data_received_cb(buff->data(), (size_t)message_length); - m_n_received_bytes += message_length; - char ip[INET_ADDRSTRLEN]; - inet_ntop(AF_INET, &source.sin_addr, ip, INET_ADDRSTRLEN); - m_sender_ip = ip; + m_n_received_bytes+=message_length; + //The source ip stuff + const char* p=inet_ntoa(source.sin_addr); + std::string s1=std::string(p); + if(m_sender_ip!=s1){ + m_sender_ip=s1; + } + }else{ + if(errno != EWOULDBLOCK) { + //MLOGE<<"Error on recvfrom. errno="< Date: Sun, 29 Dec 2024 22:02:22 +0100 Subject: [PATCH 14/25] Update UDPReceiver.cpp --- app/videostreaming/vscommon/udp/UDPReceiver.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/videostreaming/vscommon/udp/UDPReceiver.cpp b/app/videostreaming/vscommon/udp/UDPReceiver.cpp index 971422d97..7f8dee8ff 100644 --- a/app/videostreaming/vscommon/udp/UDPReceiver.cpp +++ b/app/videostreaming/vscommon/udp/UDPReceiver.cpp @@ -3,7 +3,7 @@ #include "common/StringHelper.hpp" #include "common/SchedulingHelper.hpp" -#if defined(__windows__) +#if defined(_WIN32) #include #define SHUT_RD SD_RECEIVE #else @@ -98,7 +98,7 @@ void UDPReceiver::receiveFromUDPLoop() { } // Not awailable in windows -#ifndef __windows__ +#ifndef _WIN32 if(setsockopt(m_socket,SOL_SOCKET,SO_REUSEPORT,&enable,sizeof(int))<0){ std::cout<<"Error setting SO_REUSEPORT\n"; } @@ -113,7 +113,7 @@ void UDPReceiver::receiveFromUDPLoop() { myaddr.sin_family = AF_INET; myaddr.sin_port = htons(m_config.udp_port); if(m_config.udp_ip_address.has_value()){ -#ifdef __windows__ +#ifdef _WIN32 myaddr.sin_addr.s_addr = htonl(INADDR_ANY); //myaddr.sin_addr.s_addr = inet_addr(m_config.udp_ip_address.value().c_str()); // for Qt6 @@ -142,7 +142,7 @@ void UDPReceiver::receiveFromUDPLoop() { //NOTE: NONBLOCKING hogs a whole CPU core ! do not use whenever possible ! -#ifdef __windows__ +#ifdef _WIN32 auto tmp = recvfrom(m_socket,(char *)buff->data(),UDP_PACKET_MAX_SIZE, 0,(sockaddr*)&source,&sourceLen); #ifdef QT_DEBUG if(tmp < 0) { From 38438a1cfae684edf1c266206617ff363d1c945b Mon Sep 17 00:00:00 2001 From: Raphael <68374617+raphaelscholle@users.noreply.github.com> Date: Sun, 29 Dec 2024 22:06:51 +0100 Subject: [PATCH 15/25] Update UDPReceiver.cpp --- app/videostreaming/vscommon/udp/UDPReceiver.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/videostreaming/vscommon/udp/UDPReceiver.cpp b/app/videostreaming/vscommon/udp/UDPReceiver.cpp index 7f8dee8ff..8063cd0cc 100644 --- a/app/videostreaming/vscommon/udp/UDPReceiver.cpp +++ b/app/videostreaming/vscommon/udp/UDPReceiver.cpp @@ -124,10 +124,16 @@ void UDPReceiver::receiveFromUDPLoop() { }else{ myaddr.sin_addr.s_addr = htonl(INADDR_ANY); } + #ifdef _WIN32 if (bind(m_socket, (struct sockaddr *) &myaddr, sizeof(myaddr)) == SOCKET_ERROR) { std::cerr<<"Error binding to "<>(); From 9640d7edd41a1bc31588e4dd04e4b26a45d8891b Mon Sep 17 00:00:00 2001 From: Raphael <68374617+raphaelscholle@users.noreply.github.com> Date: Sun, 29 Dec 2024 22:09:14 +0100 Subject: [PATCH 16/25] Update UDPReceiver.cpp --- app/videostreaming/vscommon/udp/UDPReceiver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/videostreaming/vscommon/udp/UDPReceiver.cpp b/app/videostreaming/vscommon/udp/UDPReceiver.cpp index 8063cd0cc..389542d25 100644 --- a/app/videostreaming/vscommon/udp/UDPReceiver.cpp +++ b/app/videostreaming/vscommon/udp/UDPReceiver.cpp @@ -129,7 +129,7 @@ void UDPReceiver::receiveFromUDPLoop() { std::cerr<<"Error binding to "< Date: Sun, 29 Dec 2024 22:10:41 +0100 Subject: [PATCH 17/25] Update UDPReceiver.cpp --- app/videostreaming/vscommon/udp/UDPReceiver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/videostreaming/vscommon/udp/UDPReceiver.cpp b/app/videostreaming/vscommon/udp/UDPReceiver.cpp index 389542d25..1a130ce24 100644 --- a/app/videostreaming/vscommon/udp/UDPReceiver.cpp +++ b/app/videostreaming/vscommon/udp/UDPReceiver.cpp @@ -118,7 +118,7 @@ void UDPReceiver::receiveFromUDPLoop() { //myaddr.sin_addr.s_addr = inet_addr(m_config.udp_ip_address.value().c_str()); // for Qt6 // inet_pton(AF_INET, m_config.udp_ip_address.value().c_str(), (in_addr *) &myaddr.sin_addr.s_addr); -#elif +#else inet_aton(m_config.udp_ip_address.value().c_str(), (in_addr *) &myaddr.sin_addr.s_addr); #endif }else{ From 02889dbfc7a8f4398216e4233d67dc2e08626158 Mon Sep 17 00:00:00 2001 From: Raphael <68374617+raphaelscholle@users.noreply.github.com> Date: Sun, 29 Dec 2024 22:15:44 +0100 Subject: [PATCH 18/25] Update UDPReceiver.cpp --- .../vscommon/udp/UDPReceiver.cpp | 175 ++++++++---------- 1 file changed, 73 insertions(+), 102 deletions(-) diff --git a/app/videostreaming/vscommon/udp/UDPReceiver.cpp b/app/videostreaming/vscommon/udp/UDPReceiver.cpp index 1a130ce24..e2bb5b728 100644 --- a/app/videostreaming/vscommon/udp/UDPReceiver.cpp +++ b/app/videostreaming/vscommon/udp/UDPReceiver.cpp @@ -1,4 +1,3 @@ - #include "UDPReceiver.h" #include "common/StringHelper.hpp" #include "common/SchedulingHelper.hpp" @@ -22,169 +21,141 @@ #include - -UDPReceiver::UDPReceiver(std::string tag,Configuration config,DATA_CALLBACK onDataReceivedCallbackX) +UDPReceiver::UDPReceiver(std::string tag, Configuration config, DATA_CALLBACK onDataReceivedCallbackX) : m_tag(tag), m_config(config), m_on_data_received_cb(std::move(onDataReceivedCallbackX)) { - qDebug()<<"UDPReceiver "<([this]{ + m_receiving = true; + m_receive_thread = std::make_unique([this]{ if(m_config.set_sched_param_max_realtime){ SchedulingHelper::setThreadParamsMaxRealtime(); } - this->receiveFromUDPLoop();} - ); + this->receiveFromUDPLoop(); + }); } void UDPReceiver::stopReceiving() { - m_receiving=false; - //this stops the recvfrom even if in blocking mode - shutdown(m_socket,SHUT_RD); - if(m_receive_thread->joinable()){ + m_receiving = false; + // This stops the recvfrom even if in blocking mode + shutdown(m_socket, SHUT_RD); + if (m_receive_thread->joinable()) { m_receive_thread->join(); } m_receive_thread.reset(); - //std::cout<<"UDPReceiver avgDeltaBetween(recvfrom) "<20MBit/s the "default" -// udp receive buffer size is often not enough and the OS might (silently) drop packets on localhost) static void increase_socket_recv_buff_size(int sockfd, const int wanted_rcvbuff_size_bytes) { - int recvBufferSize=0; - socklen_t len=sizeof(recvBufferSize); - getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, (char *)&recvBufferSize, &len); - { - std::stringstream ss; - ss<<"Default UDP socket recv buffer size:"<(size_t)recvBufferSize){ - int wanted_size=wanted_rcvbuff_size_bytes; - recvBufferSize=wanted_rcvbuff_size_bytes; - if(setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, (char *)&wanted_size,len)) { - std::cerr<<"Cannot increase UDP buffer size to "< (size_t)recvBufferSize) { + int wanted_size = wanted_rcvbuff_size_bytes; + recvBufferSize = wanted_rcvbuff_size_bytes; + if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, (char *)&wanted_size, len)) { + std::cerr << "Cannot increase UDP buffer size to " << StringHelper::memorySizeReadable(wanted_rcvbuff_size_bytes) << "\n"; + } + recvBufferSize = -1; + getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, (char *)&recvBufferSize, &len); + std::cerr << "UDP Wanted " << StringHelper::memorySizeReadable(wanted_rcvbuff_size_bytes) + << " Set " << StringHelper::memorySizeReadable(recvBufferSize) << "\n"; + } } void UDPReceiver::receiveFromUDPLoop() { - m_socket=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + m_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (m_socket == -1) { - std::cerr<<"Error creating socket\n"; + std::cerr << "Error creating socket\n"; return; } int enable = 1; - if (setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&enable, sizeof(int)) < 0){ - std::cout<<"Error setting reuse\n"; + if (setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&enable, sizeof(int)) < 0) { + std::cout << "Error setting reuse\n"; } -// Not awailable in windows #ifndef _WIN32 - if(setsockopt(m_socket,SOL_SOCKET,SO_REUSEPORT,&enable,sizeof(int))<0){ - std::cout<<"Error setting SO_REUSEPORT\n"; + if (setsockopt(m_socket, SOL_SOCKET, SO_REUSEPORT, &enable, sizeof(int)) < 0) { + std::cout << "Error setting SO_REUSEPORT\n"; } #endif - - if(m_config.opt_os_receive_buff_size){ - increase_socket_recv_buff_size(m_socket,m_config.opt_os_receive_buff_size.value()); + if (m_config.opt_os_receive_buff_size) { + increase_socket_recv_buff_size(m_socket, m_config.opt_os_receive_buff_size.value()); } + struct sockaddr_in myaddr; - memset((uint8_t *) &myaddr, 0, sizeof(myaddr)); + memset((uint8_t *)&myaddr, 0, sizeof(myaddr)); myaddr.sin_family = AF_INET; myaddr.sin_port = htons(m_config.udp_port); - if(m_config.udp_ip_address.has_value()){ + if (m_config.udp_ip_address.has_value()) { #ifdef _WIN32 myaddr.sin_addr.s_addr = htonl(INADDR_ANY); - //myaddr.sin_addr.s_addr = inet_addr(m_config.udp_ip_address.value().c_str()); -// for Qt6 -// inet_pton(AF_INET, m_config.udp_ip_address.value().c_str(), (in_addr *) &myaddr.sin_addr.s_addr); #else - inet_aton(m_config.udp_ip_address.value().c_str(), (in_addr *) &myaddr.sin_addr.s_addr); + inet_aton(m_config.udp_ip_address.value().c_str(), (in_addr *)&myaddr.sin_addr.s_addr); #endif - }else{ + } else { myaddr.sin_addr.s_addr = htonl(INADDR_ANY); } - #ifdef _WIN32 - if (bind(m_socket, (struct sockaddr *) &myaddr, sizeof(myaddr)) == SOCKET_ERROR) { - std::cerr<<"Error binding to "<>(); + } +#endif + const auto buff = std::make_unique>(); sockaddr_in source; - socklen_t sourceLen= sizeof(sockaddr_in); - - while (m_receiving) { - //TODO investigate: does a big buffer size create latency with MSG_WAITALL ? - //I do not think so. recvfrom should return as soon as new data arrived,not when the buffer is full - //But with a bigger buffer we do not loose packets when the receiver thread cannot keep up for a short amount of time - // MSG_WAITALL does not wait until we have __n data, but a new UDP packet (that can be smaller than __n) - //NOTE: NONBLOCKING hogs a whole CPU core ! do not use whenever possible ! - + socklen_t sourceLen = sizeof(sockaddr_in); + while (m_receiving) { #ifdef _WIN32 - auto tmp = recvfrom(m_socket,(char *)buff->data(),UDP_PACKET_MAX_SIZE, 0,(sockaddr*)&source,&sourceLen); -#ifdef QT_DEBUG - if(tmp < 0) { - auto err = WSAGetLastError(); - qDebug()<<"UDP ERR "<< err; - } -#endif - + auto tmp = recvfrom(m_socket, (char *)buff->data(), UDP_PACKET_MAX_SIZE, 0, (sockaddr *)&source, &sourceLen); #else ssize_t tmp; - if(m_config.enable_nonblocking){ - tmp = recvfrom(m_socket,buff->data(),UDP_PACKET_MAX_SIZE, MSG_DONTWAIT,(sockaddr*)&source,&sourceLen); - }else{ - tmp = recvfrom(m_socket,buff->data(),UDP_PACKET_MAX_SIZE, MSG_WAITALL,(sockaddr*)&source,&sourceLen); - } + if (m_config.enable_nonblocking) { + tmp = recvfrom(m_socket, buff->data(), UDP_PACKET_MAX_SIZE, MSG_DONTWAIT, (sockaddr *)&source, &sourceLen); + } else { + tmp = recvfrom(m_socket, buff->data(), UDP_PACKET_MAX_SIZE, MSG_WAITALL, (sockaddr *)&source, &sourceLen); + } #endif - const ssize_t message_length=tmp; - if (message_length > 0) { //else -1 was returned;timeout/No data received - if(m_last_received_packet_ts!=std::chrono::steady_clock::time_point{}){ - //const auto delta=std::chrono::steady_clock::now()-lastReceivedPacket; - //avgDeltaBetweenPackets.add(delta); - } - m_last_received_packet_ts=std::chrono::steady_clock::now(); - //LOGD("Data size %d",(int)message_length); + const ssize_t message_length = tmp; + if (message_length > 0) { + m_last_received_packet_ts = std::chrono::steady_clock::now(); m_on_data_received_cb(buff->data(), (size_t)message_length); - - m_n_received_bytes+=message_length; - //The source ip stuff - const char* p=inet_ntoa(source.sin_addr); - std::string s1=std::string(p); - if(m_sender_ip!=s1){ - m_sender_ip=s1; + m_n_received_bytes += message_length; + const char *p = inet_ntoa(source.sin_addr); + std::string s1 = std::string(p); + if (m_sender_ip != s1) { + m_sender_ip = s1; } - }else{ - if(errno != EWOULDBLOCK) { - //MLOGE<<"Error on recvfrom. errno="< Date: Sun, 29 Dec 2024 22:27:39 +0100 Subject: [PATCH 19/25] Update texturerenderer.cpp --- app/videostreaming/avcodec/texturerenderer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/app/videostreaming/avcodec/texturerenderer.cpp b/app/videostreaming/avcodec/texturerenderer.cpp index 429411709..398f3ec8d 100644 --- a/app/videostreaming/avcodec/texturerenderer.cpp +++ b/app/videostreaming/avcodec/texturerenderer.cpp @@ -1,4 +1,5 @@ #include "texturerenderer.h" +#include "avcodec_helper.hpp" #include #include From 527a6537fb5e8d89c689e6292de56858e8a8d6d9 Mon Sep 17 00:00:00 2001 From: Raphael <68374617+raphaelscholle@users.noreply.github.com> Date: Sun, 29 Dec 2024 22:53:29 +0100 Subject: [PATCH 20/25] Update avcodec_video.pri --- app/videostreaming/avcodec/avcodec_video.pri | 74 +++++++++++--------- 1 file changed, 42 insertions(+), 32 deletions(-) diff --git a/app/videostreaming/avcodec/avcodec_video.pri b/app/videostreaming/avcodec/avcodec_video.pri index 1ad6c19a9..f24d7b7a6 100644 --- a/app/videostreaming/avcodec/avcodec_video.pri +++ b/app/videostreaming/avcodec/avcodec_video.pri @@ -1,24 +1,6 @@ +# Common Include Paths and Sources INCLUDEPATH += $$PWD -# TODO dirty -WindowsBuild { - INCLUDEPATH += $$PWD/../../../build-libs-windows/ffmpeg/include - LIBS += -L$$PWD/../../../build-libs-windows/ffmpeg/lib -lavcodec -lavutil -lavformat - - INCLUDEPATH += $$PWD/../../../build-libs-windows/angle-x64/include - LIBS += -L$$PWD/../../../build-libs-windows/angle-x64/bin -lGLESv2 -lEGL - - DEFINES += EGL_EGLEXT_PROTOTYPES - DEFINES += GL_GLEXT_PROTOTYPES -# LIBS += -lOpengl32 -} -else { - LIBS += -lGLESv2 -lEGL -} - -# just using the something something webrtc from stephen was the easiest solution. -#include(../../lib/h264/h264.pri) - SOURCES += \ $$PWD/QSGVideoTextureItem.cpp \ $$PWD/gl/gl_shaders.cpp \ @@ -34,22 +16,50 @@ HEADERS += \ $$PWD/avcodec_decoder.h \ $$PWD/avcodec_helper.hpp -# experimental -#INCLUDEPATH += /usr/local/include/uvgrtp -#LIBS += -L/usr/local/lib -luvgrtp +# Windows-Specific Configuration +win32 { + INCLUDEPATH += $$PWD/../../../build-libs-windows/ffmpeg/include + LIBS += -L$$PWD/../../../build-libs-windows/ffmpeg/lib -lavcodec -lavutil -lavformat -# dirty way to check if we are on rpi and therefore should use the external decode service -CONFIG += link_pkgconfig -packagesExist(mmal) { - DEFINES += IS_PLATFORM_RPI + INCLUDEPATH += $$PWD/../../../build-libs-windows/angle-x64/include + LIBS += -L$$PWD/../../../build-libs-windows/angle-x64/bin -lGLESv2 -lEGL + + DEFINES += EGL_EGLEXT_PROTOTYPES + DEFINES += GL_GLEXT_PROTOTYPES } -exists(/usr/local/share/openhd/platform/rock/) { - message(This is a Rock) - DEFINES += IS_PLATFORM_ROCK -} else { - message(This is not a Rock) +# Unix (Linux/Android) Configuration +unix { + LIBS += -lGLESv2 -lEGL + + # Optional: Include Linux-specific paths or libraries + exists(/usr/local/include/uvgrtp) { + INCLUDEPATH += /usr/local/include/uvgrtp + LIBS += -L/usr/local/lib -luvgrtp + } + + # Platform Detection for Raspberry Pi or Rock + packagesExist(mmal) { + DEFINES += IS_PLATFORM_RPI + } + exists(/usr/local/share/openhd/platform/rock/) { + message(This is a Rock) + DEFINES += IS_PLATFORM_ROCK + } else { + message(This is not a Rock) + } } -# can be used in c++, also set to be exposed in qml +# macOS-Specific Configuration (if needed) +macx { + # Add macOS-specific libraries or configurations here +} + +# Shared Definitions DEFINES += QOPENHD_ENABLE_VIDEO_VIA_AVCODEC + +# Debugging Build Information +message(Building for platform $$QMAKE_PLATFORM) +win32: message(Windows build activated.) +unix: message(Unix build activated.) +macx: message(macOS build activated.) From 290d51ead8103f8d64aa6d9ff6d0d4509e94a9ba Mon Sep 17 00:00:00 2001 From: Raphael <68374617+raphaelscholle@users.noreply.github.com> Date: Sun, 29 Dec 2024 22:57:29 +0100 Subject: [PATCH 21/25] Update avcodec_video.pri --- app/videostreaming/avcodec/avcodec_video.pri | 1 + 1 file changed, 1 insertion(+) diff --git a/app/videostreaming/avcodec/avcodec_video.pri b/app/videostreaming/avcodec/avcodec_video.pri index f24d7b7a6..bdbdded44 100644 --- a/app/videostreaming/avcodec/avcodec_video.pri +++ b/app/videostreaming/avcodec/avcodec_video.pri @@ -30,6 +30,7 @@ win32 { # Unix (Linux/Android) Configuration unix { + #include(../../lib/h264/h264.pri) LIBS += -lGLESv2 -lEGL # Optional: Include Linux-specific paths or libraries From e8b4cbdb4047dea5ab4c7cb66f22ca72ca81cd2d Mon Sep 17 00:00:00 2001 From: Raphael <68374617+raphaelscholle@users.noreply.github.com> Date: Sun, 29 Dec 2024 23:01:05 +0100 Subject: [PATCH 22/25] Update avcodec_video.pri --- app/videostreaming/avcodec/avcodec_video.pri | 63 +++++++------------- 1 file changed, 21 insertions(+), 42 deletions(-) diff --git a/app/videostreaming/avcodec/avcodec_video.pri b/app/videostreaming/avcodec/avcodec_video.pri index bdbdded44..4872c9809 100644 --- a/app/videostreaming/avcodec/avcodec_video.pri +++ b/app/videostreaming/avcodec/avcodec_video.pri @@ -1,5 +1,12 @@ -# Common Include Paths and Sources INCLUDEPATH += $$PWD +INCLUDEPATH += C:/ffmpeg/include + +LIBS += -LC:/ffmpeg/lib -lavcodec -lavutil -lavformat +# TODO dirty +LIBS += -lGLESv2 -lEGL + +# just using the something something webrtc from stephen was the easiest solution. +#include(../../lib/h264/h264.pri) SOURCES += \ $$PWD/QSGVideoTextureItem.cpp \ @@ -14,53 +21,25 @@ HEADERS += \ $$PWD/gl/gl_videorenderer.h \ $$PWD/texturerenderer.h \ $$PWD/avcodec_decoder.h \ - $$PWD/avcodec_helper.hpp - -# Windows-Specific Configuration -win32 { - INCLUDEPATH += $$PWD/../../../build-libs-windows/ffmpeg/include - LIBS += -L$$PWD/../../../build-libs-windows/ffmpeg/lib -lavcodec -lavutil -lavformat - INCLUDEPATH += $$PWD/../../../build-libs-windows/angle-x64/include - LIBS += -L$$PWD/../../../build-libs-windows/angle-x64/bin -lGLESv2 -lEGL - DEFINES += EGL_EGLEXT_PROTOTYPES - DEFINES += GL_GLEXT_PROTOTYPES -} - -# Unix (Linux/Android) Configuration -unix { - #include(../../lib/h264/h264.pri) - LIBS += -lGLESv2 -lEGL - # Optional: Include Linux-specific paths or libraries - exists(/usr/local/include/uvgrtp) { - INCLUDEPATH += /usr/local/include/uvgrtp - LIBS += -L/usr/local/lib -luvgrtp - } +# experimental +#INCLUDEPATH += /usr/local/include/uvgrtp +#LIBS += -L/usr/local/lib -luvgrtp - # Platform Detection for Raspberry Pi or Rock - packagesExist(mmal) { - DEFINES += IS_PLATFORM_RPI - } - exists(/usr/local/share/openhd/platform/rock/) { - message(This is a Rock) - DEFINES += IS_PLATFORM_ROCK - } else { - message(This is not a Rock) - } +# dirty way to check if we are on rpi and therefore should use the external decode service +CONFIG += link_pkgconfig +packagesExist(mmal) { + DEFINES += IS_PLATFORM_RPI } -# macOS-Specific Configuration (if needed) -macx { - # Add macOS-specific libraries or configurations here +exists(/usr/local/share/openhd/platform/rock/) { + message(This is a Rock) + DEFINES += IS_PLATFORM_ROCK +} else { + message(This is not a Rock) } -# Shared Definitions +# can be used in c++, also set to be exposed in qml DEFINES += QOPENHD_ENABLE_VIDEO_VIA_AVCODEC - -# Debugging Build Information -message(Building for platform $$QMAKE_PLATFORM) -win32: message(Windows build activated.) -unix: message(Unix build activated.) -macx: message(macOS build activated.) From 758e0da8fc44f76d1b5e308fcf5419cfa093d8f3 Mon Sep 17 00:00:00 2001 From: Raphael <68374617+raphaelscholle@users.noreply.github.com> Date: Sun, 29 Dec 2024 23:08:23 +0100 Subject: [PATCH 23/25] Update avcodec_video.pri --- app/videostreaming/avcodec/avcodec_video.pri | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/app/videostreaming/avcodec/avcodec_video.pri b/app/videostreaming/avcodec/avcodec_video.pri index 4872c9809..84c37bbd9 100644 --- a/app/videostreaming/avcodec/avcodec_video.pri +++ b/app/videostreaming/avcodec/avcodec_video.pri @@ -5,6 +5,18 @@ LIBS += -LC:/ffmpeg/lib -lavcodec -lavutil -lavformat # TODO dirty LIBS += -lGLESv2 -lEGL +WindowsBuild { + INCLUDEPATH += $$PWD/../../../build-libs-windows/ffmpeg/include + LIBS += -L$$PWD/../../../build-libs-windows/ffmpeg/lib -lavcodec -lavutil -lavformat + + INCLUDEPATH += $$PWD/../../../build-libs-windows/angle-x64/include + LIBS += -L$$PWD/../../../build-libs-windows/angle-x64/bin -lGLESv2 -lEGL + + DEFINES += EGL_EGLEXT_PROTOTYPES + DEFINES += GL_GLEXT_PROTOTYPES +# LIBS += -lOpengl32 +} + # just using the something something webrtc from stephen was the easiest solution. #include(../../lib/h264/h264.pri) From 8444c40b8096e0ffdb632cfd50beadd42245b80a Mon Sep 17 00:00:00 2001 From: Raphael <68374617+raphaelscholle@users.noreply.github.com> Date: Sun, 29 Dec 2024 23:14:33 +0100 Subject: [PATCH 24/25] Update avcodec_video.pri --- app/videostreaming/avcodec/avcodec_video.pri | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/videostreaming/avcodec/avcodec_video.pri b/app/videostreaming/avcodec/avcodec_video.pri index 84c37bbd9..929f44019 100644 --- a/app/videostreaming/avcodec/avcodec_video.pri +++ b/app/videostreaming/avcodec/avcodec_video.pri @@ -5,7 +5,7 @@ LIBS += -LC:/ffmpeg/lib -lavcodec -lavutil -lavformat # TODO dirty LIBS += -lGLESv2 -lEGL -WindowsBuild { +win32 { INCLUDEPATH += $$PWD/../../../build-libs-windows/ffmpeg/include LIBS += -L$$PWD/../../../build-libs-windows/ffmpeg/lib -lavcodec -lavutil -lavformat From fcc54c2c23a50d56ee17e78dc6ae5ef7fb3f3aaf Mon Sep 17 00:00:00 2001 From: Raphael <68374617+raphaelscholle@users.noreply.github.com> Date: Sun, 29 Dec 2024 23:48:44 +0100 Subject: [PATCH 25/25] Update gst_video.pri --- app/videostreaming/gstreamer/gst_video.pri | 131 ++++++++++++++------- 1 file changed, 87 insertions(+), 44 deletions(-) diff --git a/app/videostreaming/gstreamer/gst_video.pri b/app/videostreaming/gstreamer/gst_video.pri index 929f44019..cf54f3331 100644 --- a/app/videostreaming/gstreamer/gst_video.pri +++ b/app/videostreaming/gstreamer/gst_video.pri @@ -1,57 +1,100 @@ -INCLUDEPATH += $$PWD -INCLUDEPATH += C:/ffmpeg/include +DEFINES += QOPENHD_ENABLE_GSTREAMER_QMLGLSINK -LIBS += -LC:/ffmpeg/lib -lavcodec -lavutil -lavformat -# TODO dirty -LIBS += -lGLESv2 -lEGL +#DEFINES += QOPENHD_GSTREAMER_PRIMARY_VIDEO +DEFINES += QOPENHD_GSTREAMER_SECONDARY_VIDEO -win32 { - INCLUDEPATH += $$PWD/../../../build-libs-windows/ffmpeg/include - LIBS += -L$$PWD/../../../build-libs-windows/ffmpeg/lib -lavcodec -lavutil -lavformat +SOURCES += \ + $$PWD/gstqmlglsinkstream.cpp \ + $$PWD/gstrtpaudioplayer.cpp \ + $$PWD/gstrtpreceiver.cpp - INCLUDEPATH += $$PWD/../../../build-libs-windows/angle-x64/include - LIBS += -L$$PWD/../../../build-libs-windows/angle-x64/bin -lGLESv2 -lEGL +HEADERS += \ + $$PWD/gst_helper.hpp \ + $$PWD/gstqmlglsinkstream.h \ + $$PWD/gstrtpaudioplayer.h \ + $$PWD/gstrtpreceiver.h - DEFINES += EGL_EGLEXT_PROTOTYPES - DEFINES += GL_GLEXT_PROTOTYPES -# LIBS += -lOpengl32 -} +android{ + message("gst android") + # More or less taken from QGroundControl. + # this is already the "least dirty" solution I could come up with :/ + #DOWNLOADED_GST_FOLDER= /home/hyperion/gstreamer-1.0-android-universal-1.20.5 + #DOWNLOADED_GST_FOLDER= /home/consti10/Downloads/gstreamer-1.0-android-universal-1.20.5 + #DOWNLOADED_GST_FOLDER= $$PWD/../../../lib/gstreamer_prebuilts/gstreamer-1.0-android-universal-1.20.5 + DOWNLOADED_GST_FOLDER= $$PWD/../../../lib/gstreamer_prebuilts/gstreamer-1.0-android-universal -# just using the something something webrtc from stephen was the easiest solution. -#include(../../lib/h264/h264.pri) + # Set the right folder for the compile arch + GSTREAMER_ARCH_FOLDER = armv7 + contains(ANDROID_TARGET_ARCH, armeabi-v7a) { + GSTREAMER_ARCH_FOLDER = armv7 + } else:contains(ANDROID_TARGET_ARCH, arm64-v8a) { + GSTREAMER_ARCH_FOLDER = arm64 + } else:contains(ANDROID_TARGET_ARCH, x86_64) { + GSTREAMER_ARCH_FOLDER = x86_64 + } else { + message(Unknown ANDROID_TARGET_ARCH $$ANDROID_TARGET_ARCH) + GSTREAMER_ARCH_FOLDER = armv7 + } -SOURCES += \ - $$PWD/QSGVideoTextureItem.cpp \ - $$PWD/gl/gl_shaders.cpp \ - $$PWD/gl/gl_videorenderer.cpp \ - $$PWD/texturerenderer.cpp \ - $$PWD/avcodec_decoder.cpp \ + #GSTREAMER_ARCH_FOLDER = arm64 -HEADERS += \ - $$PWD/QSGVideoTextureItem.h \ - $$PWD/gl/gl_shaders.h \ - $$PWD/gl/gl_videorenderer.h \ - $$PWD/texturerenderer.h \ - $$PWD/avcodec_decoder.h \ + GSTREAMER_ROOT_ANDROID = $$DOWNLOADED_GST_FOLDER/$$GSTREAMER_ARCH_FOLDER + message(gstreamer root android:) + message($$GSTREAMER_ROOT_ANDROID) + GST_ROOT = $$GSTREAMER_ROOT_ANDROID + exists($$GST_ROOT) { + message(Doing QGC gstreamer stuff) + message($$GST_ROOT) + QMAKE_CXXFLAGS += -pthread + CONFIG += VideoEnabled + LIBS += -L$$GST_ROOT/lib/gstreamer-1.0 \ + -lgstvideo-1.0 \ + -lgstcoreelements \ + -lgstplayback \ + -lgstudp \ + -lgstrtp \ + -lgstrtsp \ + -lgstx264 \ + -lgstlibav \ + -lgstsdpelem \ + -lgstvideoparsersbad \ + -lgstrtpmanager \ + -lgstisomp4 \ + -lgstmatroska \ + -lgstmpegtsdemux \ + -lgstandroidmedia \ + -lgstopengl \ + -lgsttcp \ + -lgstapp \ + -lgstalaw \ + -lgstautodetect -# experimental -#INCLUDEPATH += /usr/local/include/uvgrtp -#LIBS += -L/usr/local/lib -luvgrtp -# dirty way to check if we are on rpi and therefore should use the external decode service -CONFIG += link_pkgconfig -packagesExist(mmal) { - DEFINES += IS_PLATFORM_RPI -} + # Rest of GStreamer dependencies + LIBS += -L$$GST_ROOT/lib \ + -lgraphene-1.0 -ljpeg -lpng16 \ + -lgstfft-1.0 -lm \ + -lgstnet-1.0 -lgio-2.0 \ + -lgstphotography-1.0 -lgstgl-1.0 -lEGL \ + -lgstaudio-1.0 -lgstcodecparsers-1.0 -lgstbase-1.0 \ + -lgstreamer-1.0 -lgstrtp-1.0 -lgstpbutils-1.0 -lgstrtsp-1.0 -lgsttag-1.0 \ + -lgstvideo-1.0 -lavformat -lavcodec -lavutil -lx264 -lavfilter -lswresample \ + -lgstriff-1.0 -lgstcontroller-1.0 -lgstapp-1.0 \ + -lgstsdp-1.0 -lbz2 -lgobject-2.0 -lgstmpegts-1.0 \ + -Wl,--export-dynamic -lgmodule-2.0 -pthread -lglib-2.0 -lorc-0.4 -liconv -lffi -lintl \ -exists(/usr/local/share/openhd/platform/rock/) { - message(This is a Rock) - DEFINES += IS_PLATFORM_ROCK -} else { - message(This is not a Rock) + INCLUDEPATH += \ + $$GST_ROOT/include/gstreamer-1.0 \ + $$GST_ROOT/lib/gstreamer-1.0/include \ + $$GST_ROOT/include/glib-2.0 \ + $$GST_ROOT/lib/glib-2.0/include + }else { + message(Gstreamer prebuilt directory does not exist) + } +}else { + message(gst linux) + CONFIG += link_pkgconfig + PKGCONFIG += gstreamer-1.0 gstreamer-video-1.0 gstreamer-gl-1.0 gstreamer-app-1.0 #gstreamer1.0-plugins-good } - -# can be used in c++, also set to be exposed in qml -DEFINES += QOPENHD_ENABLE_VIDEO_VIA_AVCODEC