From 4c95f810bb8dba8c97326293cd38ad97633dab95 Mon Sep 17 00:00:00 2001 From: kkbin505 <19462942@qq.com> Date: Fri, 5 Jun 2026 08:21:59 -0700 Subject: [PATCH 1/3] Fix: gs.key invalid link Because the main branch was renamed to master, the link in gs.key is invalid, I fixed this issue to avoid misleading. --- .gitignore | 2 ++ README.md | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 4b819f55..99a229c8 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,5 @@ local.properties /app/videonative/compile_commands.json /app/wfbngrtl8812/compile_commands.json /compile_commands.json +/tmp +video.sdp diff --git a/README.md b/README.md index f1b0f9b2..0d2155e0 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ where (brace yourself) most things actually work. - [LiveVideo10ms](https://github.com/Consti10/LiveVideo10ms): excellent video decoder from [Consti10](https://github.com/Consti10) converted into a module. - [wfb-ng](https://github.com/svpcom/wfb-ng): library allowing the broadcast of the video feed over the air. -The wfb-ng [gs.key](https://github.com/OpenIPC/PixelPilot/raw/main/app/src/main/assets/gs.key) is embedded in the app. +The wfb-ng [gs.key](https://github.com/OpenIPC/PixelPilot/raw/master/app/src/main/assets/gs.key) is embedded in the app. The settings menu allows selecting a different key from your phone. Supported rtl8812au wifi adapter are listed [here](https://github.com/OpenIPC/PixelPilot/blob/master/app/src/main/res/xml/usb_device_filter.xml). From f57ca770ff6f6d22a98b4b333c2e0003b060a39c Mon Sep 17 00:00:00 2001 From: kkbin505 <19462942@qq.com> Date: Sat, 6 Jun 2026 22:01:06 -0700 Subject: [PATCH 2/3] feat: add local network UDP packet forwarding - Implement UDP packet forwarding from OpenIPC device to custom target IP & Port - Add "UDP Forwarding" settings menu with Enable toggle and Config Target dialog - Save configurations persistently in SharedPreferences --- .gitignore | 1 + .../com/openipc/pixelpilot/VideoActivity.java | 86 +++++++++++++++++++ app/videonative/src/main/cpp/UdpReceiver.cpp | 26 ++++++ app/videonative/src/main/cpp/UdpReceiver.h | 9 ++ app/videonative/src/main/cpp/VideoPlayer.cpp | 25 ++++++ app/videonative/src/main/cpp/VideoPlayer.h | 6 ++ .../com/openipc/videonative/VideoPlayer.java | 7 ++ 7 files changed, 160 insertions(+) diff --git a/.gitignore b/.gitignore index 99a229c8..4afaccd8 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ local.properties /compile_commands.json /tmp video.sdp +plan.md diff --git a/app/src/main/java/com/openipc/pixelpilot/VideoActivity.java b/app/src/main/java/com/openipc/pixelpilot/VideoActivity.java index a834a8bb..e3c8da26 100644 --- a/app/src/main/java/com/openipc/pixelpilot/VideoActivity.java +++ b/app/src/main/java/com/openipc/pixelpilot/VideoActivity.java @@ -568,6 +568,9 @@ private void showSettingsMenu(View anchor) { // Drone submenu setupDroneSubMenu(popup); + // UDP Forwarding submenu + setupUdpForwardingSubMenu(popup); + // Help submenu setupHelpSubMenu(popup); @@ -920,6 +923,88 @@ private void setupDroneSubMenu(PopupMenu popup) { }); } + private void setupUdpForwardingSubMenu(PopupMenu popup) { + SubMenu forwardMenu = popup.getMenu().addSubMenu("UDP Forwarding"); + + SharedPreferences prefs = getSharedPreferences("general", MODE_PRIVATE); + boolean enabled = prefs.getBoolean("forward_udp_enabled", false); + String ip = prefs.getString("forward_udp_ip", "192.168.1.100"); + int port = prefs.getInt("forward_udp_port", 5600); + + MenuItem enableItem = forwardMenu.add("Enable"); + enableItem.setCheckable(true); + enableItem.setChecked(enabled); + enableItem.setOnMenuItemClickListener(item -> { + boolean newState = !item.isChecked(); + item.setChecked(newState); + SharedPreferences.Editor editor = prefs.edit(); + editor.putBoolean("forward_udp_enabled", newState); + editor.apply(); + updateUdpForwardingState(); + return true; + }); + + MenuItem configItem = forwardMenu.add("Config Target (" + ip + ":" + port + ")"); + configItem.setOnMenuItemClickListener(item -> { + showUdpForwardingDialog(); + return true; + }); + } + + private void showUdpForwardingDialog() { + SharedPreferences prefs = getSharedPreferences("general", MODE_PRIVATE); + String ip = prefs.getString("forward_udp_ip", "192.168.1.100"); + int port = prefs.getInt("forward_udp_port", 5600); + + android.widget.LinearLayout layout = new android.widget.LinearLayout(this); + layout.setOrientation(android.widget.LinearLayout.VERTICAL); + layout.setPadding(50, 30, 50, 30); + + final android.widget.EditText ipEditText = new android.widget.EditText(this); + ipEditText.setHint("Destination IP Address"); + ipEditText.setText(ip); + layout.addView(ipEditText); + + final android.widget.EditText portEditText = new android.widget.EditText(this); + portEditText.setHint("Destination Port"); + portEditText.setInputType(android.text.InputType.TYPE_CLASS_NUMBER); + portEditText.setText(String.valueOf(port)); + layout.addView(portEditText); + + new android.app.AlertDialog.Builder(this) + .setTitle("UDP Forwarding Config") + .setView(layout) + .setPositiveButton("Save", (dialog, which) -> { + String newIp = ipEditText.getText().toString().trim(); + String newPortStr = portEditText.getText().toString().trim(); + int newPort = 5600; + try { + newPort = Integer.parseInt(newPortStr); + } catch (NumberFormatException ignored) {} + + SharedPreferences.Editor editor = prefs.edit(); + editor.putString("forward_udp_ip", newIp); + editor.putInt("forward_udp_port", newPort); + editor.apply(); + + Toast.makeText(this, "Forwarding settings saved: " + newIp + ":" + newPort, Toast.LENGTH_SHORT).show(); + updateUdpForwardingState(); + }) + .setNegativeButton("Cancel", null) + .show(); + } + + private void updateUdpForwardingState() { + SharedPreferences prefs = getSharedPreferences("general", MODE_PRIVATE); + boolean enabled = prefs.getBoolean("forward_udp_enabled", false); + String ip = prefs.getString("forward_udp_ip", "192.168.1.100"); + int port = prefs.getInt("forward_udp_port", 5600); + + if (videoPlayer != null) { + videoPlayer.setUdpForwarding(ip, port, enabled); + } + } + /** * Submenu for help items, such as sending logs. */ @@ -1358,6 +1443,7 @@ protected void onResume() { wfbLinkManager.startAdapters(); videoPlayer.start(); + updateUdpForwardingState(); videoPlayer.startAudio(); osdManager.restoreOSDConfig(); diff --git a/app/videonative/src/main/cpp/UdpReceiver.cpp b/app/videonative/src/main/cpp/UdpReceiver.cpp index 3c2e071a..1fc6d17f 100644 --- a/app/videonative/src/main/cpp/UdpReceiver.cpp +++ b/app/videonative/src/main/cpp/UdpReceiver.cpp @@ -131,6 +131,16 @@ void UDPReceiver::receiveFromUDPLoop() // ssize_t message_length = recv(mSocket, buff, (size_t) mBuffsize, MSG_WAITALL); if (message_length > 0) { // else -1 was returned;timeout/No data received + // 1. Forward packet first (minimize latency) + { + std::lock_guard lock(mForwardMutex); + if (mForwardEnabled) + { + sendto(mSocket, buff->data(), message_length, 0, (struct sockaddr*) &mDestAddr, sizeof(mDestAddr)); + } + } + + // 2. Local processing onDataReceivedCallback(buff->data(), (size_t) message_length); nReceivedBytes += message_length; @@ -162,3 +172,19 @@ int UDPReceiver::getPort() const { return mPort; } + +void UDPReceiver::setForwarding(const std::string& ip, int port, bool enabled) +{ + std::lock_guard lock(mForwardMutex); + mForwardIP = ip; + mForwardPort = port; + mForwardEnabled = enabled; + + memset(&mDestAddr, 0, sizeof(mDestAddr)); + mDestAddr.sin_family = AF_INET; + mDestAddr.sin_port = htons(port); + if (inet_pton(AF_INET, ip.c_str(), &mDestAddr.sin_addr) <= 0) + { + mForwardEnabled = false; + } +} diff --git a/app/videonative/src/main/cpp/UdpReceiver.h b/app/videonative/src/main/cpp/UdpReceiver.h index 04627a06..b76a93da 100644 --- a/app/videonative/src/main/cpp/UdpReceiver.h +++ b/app/videonative/src/main/cpp/UdpReceiver.h @@ -13,6 +13,7 @@ #include #include #include +#include // Starts a new thread that continuously checks for new data on UDP port class UDPReceiver @@ -64,6 +65,8 @@ class UDPReceiver int getPort() const; + void setForwarding(const std::string& ip, int port, bool enabled); + private: void receiveFromUDPLoop(); @@ -84,6 +87,12 @@ class UDPReceiver // 65,507 bytes (65,535 − 8 byte UDP header − 20 byte IP header). static constexpr const size_t UDP_PACKET_MAX_SIZE = 65507; JavaVM* javaVm; + + std::mutex mForwardMutex; + std::string mForwardIP = ""; + int mForwardPort = 0; + bool mForwardEnabled = false; + struct sockaddr_in mDestAddr; }; #endif // FPVUE_UDPRECEIVER_H diff --git a/app/videonative/src/main/cpp/VideoPlayer.cpp b/app/videonative/src/main/cpp/VideoPlayer.cpp index 6c2f4bf8..6175d585 100644 --- a/app/videonative/src/main/cpp/VideoPlayer.cpp +++ b/app/videonative/src/main/cpp/VideoPlayer.cpp @@ -172,6 +172,7 @@ void VideoPlayer::start(JNIEnv* env, jobject androidContext) -16, [this](const uint8_t* data, size_t data_length) { onNewRTPData(data, data_length); }, WANTED_UDP_RCVBUF_SIZE); + mUDPReceiver->setForwarding(mForwardIP, mForwardPort, mForwardEnabled); mUDPReceiver->startReceiving(); mUDSReceiver.release(); @@ -250,6 +251,17 @@ void VideoPlayer::stopDvr() stopProcessing(); } +void VideoPlayer::setForwarding(const std::string& ip, int port, bool enabled) +{ + mForwardIP = ip; + mForwardPort = port; + mForwardEnabled = enabled; + if (mUDPReceiver) + { + mUDPReceiver->setForwarding(ip, port, enabled); + } +} + //----------------------------------------------------JAVA // bindings--------------------------------------------------------------- #define JNI_METHOD(return_type, method_name) \ @@ -293,6 +305,19 @@ extern "C" native(videoPlayerN)->stop(env, androidContext); } + JNI_METHOD(void, nativeSetUdpForwarding) + (JNIEnv* env, jclass jclass1, jlong nativeInstance, jstring ipStr, jint port, jboolean enabled) + { + VideoPlayer* p = native(nativeInstance); + if (p) + { + const char* ip = env->GetStringUTFChars(ipStr, nullptr); + std::string ip_cpp(ip); + env->ReleaseStringUTFChars(ipStr, ip); + p->setForwarding(ip_cpp, port, enabled); + } + } + JNI_METHOD(void, nativeSetVideoSurface) (JNIEnv* env, jclass jclass1, jlong videoPlayerN, jobject surface, jint index) { diff --git a/app/videonative/src/main/cpp/VideoPlayer.h b/app/videonative/src/main/cpp/VideoPlayer.h index db450278..830d423e 100644 --- a/app/videonative/src/main/cpp/VideoPlayer.h +++ b/app/videonative/src/main/cpp/VideoPlayer.h @@ -52,6 +52,8 @@ class VideoPlayer bool isRecording() { return (get_time_ms() - last_dvr_write) <= 500; } + void setForwarding(const std::string& ip, int port, bool enabled); + private: void onNewNALU(const NALU& nalu); @@ -112,6 +114,10 @@ class VideoPlayer void processQueue(); + std::string mForwardIP = ""; + int mForwardPort = 0; + bool mForwardEnabled = false; + public: AudioDecoder audioDecoder; VideoDecoder videoDecoder; diff --git a/app/videonative/src/main/java/com/openipc/videonative/VideoPlayer.java b/app/videonative/src/main/java/com/openipc/videonative/VideoPlayer.java index 54190856..d375921c 100644 --- a/app/videonative/src/main/java/com/openipc/videonative/VideoPlayer.java +++ b/app/videonative/src/main/java/com/openipc/videonative/VideoPlayer.java @@ -50,6 +50,8 @@ public VideoPlayer(final AppCompatActivity parent) { public static native void nativeSetVideoSurface(long nativeInstance, Surface surface, int index); + public static native void nativeSetUdpForwarding(long nativeInstance, String ip, int port, boolean enabled); + public static native void nativeStartDvr(long nativeInstance, int fd, int fmp4_enabled); public static native void nativeStopDvr(long nativeInstance); @@ -124,6 +126,11 @@ public boolean isRunning() { return timer != null; } + public void setUdpForwarding(String ip, int port, boolean enabled) { + verifyApplicationThread(); + nativeSetUdpForwarding(nativeVideoPlayer, ip, port, enabled); + } + public void startDvr(int fd, boolean enabled_fmp4) { nativeStartDvr(nativeVideoPlayer, fd, enabled_fmp4 ? 1 : 0); } From 4da40458a78e68e7ce090858cc87e0f57f0b6f6d Mon Sep 17 00:00:00 2001 From: kkbin505 <19462942@qq.com> Date: Sat, 6 Jun 2026 22:06:57 -0700 Subject: [PATCH 3/3] Create app-debug.apk --- test_APK/app-debug.apk | Bin 0 -> 12984873 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 test_APK/app-debug.apk diff --git a/test_APK/app-debug.apk b/test_APK/app-debug.apk new file mode 100644 index 0000000000000000000000000000000000000000..939e0a6f2b9042d0dd6f2741f8c9fe25067a3bf0 GIT binary patch literal 12984873 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 z zI;vCcQ+{Wx-@IEnMKzf}(w{ESJMvP)wA(GUaIeZR*QwfvF4wPY -D}0&Wx6#v< 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