From a1da3cb3460e8e0c2189e387926b8b1e96c9c6e8 Mon Sep 17 00:00:00 2001 From: Raphael <68374617+raphaelscholle@users.noreply.github.com> Date: Sun, 29 Dec 2024 23:55:51 +0100 Subject: [PATCH] finally merging everyting together, thanks @buldo for your windows work (#732) * Using geodesic.h from repo * make linux work again ;) * revert windows gstreamer until it works * revert more windows stuff for now * Update MavlinkChoiceElement2.qml * Update MavlinkChoiceElement.qml * Scheduling hotfix * windows build * How to * Update QOpenHD.pro * Update gst_video.pri * Update UDPReceiver.cpp * Revert "Update UDPReceiver.cpp" This reverts commit dc7e3e9de0ba6fdb4eb979a483025176221f005b. * Update UDPReceiver.cpp * Update UDPReceiver.cpp * Update UDPReceiver.cpp * Update UDPReceiver.cpp * Update UDPReceiver.cpp * Update texturerenderer.cpp * Update avcodec_video.pri * Update avcodec_video.pri * Update avcodec_video.pri * Update avcodec_video.pri * Update avcodec_video.pri * Update gst_video.pri --------- Co-authored-by: Roman Buldygin --- QOpenHD.pro | 19 +- README.windows.md | 10 + app/common/SchedulingHelper.hpp | 28 +-- app/main.cpp | 4 + app/telemetry/tutil/geodesi_helper.cpp | 2 +- app/videostreaming/avcodec/avcodec_helper.hpp | 3 +- app/videostreaming/avcodec/avcodec_video.pri | 12 ++ 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 +- app/videostreaming/gstreamer/gst_video.pri | 121 ++++++------ app/videostreaming/vscommon/rtp/RTP.hpp | 10 +- .../vscommon/udp/UDPReceiver.cpp | 177 ++++++++++-------- app/videostreaming/vscommon/vscommon.pri | 38 ++-- qml/ui/sidebar/MavlinkChoiceElement.qml | 38 ++-- qml/ui/sidebar/MavlinkChoiceElement2.qml | 8 +- 17 files changed, 273 insertions(+), 244 deletions(-) create mode 100644 README.windows.md diff --git a/QOpenHD.pro b/QOpenHD.pro index 102e0a0be..60a082f1c 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 } @@ -103,6 +102,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 \ @@ -125,6 +130,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 \ @@ -234,17 +240,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 { 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 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() { 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/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" 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..929f44019 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 +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 +# LIBS += -lOpengl32 +} + # just using the something something webrtc from stephen was the easiest solution. #include(../../lib/h264/h264.pri) 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/gstreamer/gst_video.pri b/app/videostreaming/gstreamer/gst_video.pri index 635c7bcf8..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,75 +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") - } -} else { - # 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 } 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..e2bb5b728 100644 --- a/app/videostreaming/vscommon/udp/UDPReceiver.cpp +++ b/app/videostreaming/vscommon/udp/UDPReceiver.cpp @@ -1,8 +1,14 @@ - #include "UDPReceiver.h" #include "common/StringHelper.hpp" #include "common/SchedulingHelper.hpp" + +#if defined(_WIN32) +#include +#define SHUT_RD SD_RECEIVE +#else #include +#endif + #include #include #include @@ -10,141 +16,146 @@ #include #include -#include + #include #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, &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)) { - 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"; } - // Fetch it again to double check - recvBufferSize=-1; - getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &recvBufferSize, &len); - std::cerr<<"UDP Wanted "<>(); +#endif + const auto buff = std::make_unique>(); sockaddr_in source; - socklen_t sourceLen= sizeof(sockaddr_in); - + 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 ! - 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); - } - 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); +#ifdef _WIN32 + 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); + } +#endif + 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="<