From 9f44f121fe501f7953950c4d9abb28d4c78db462 Mon Sep 17 00:00:00 2001 From: Consti10 Date: Wed, 28 Feb 2024 20:51:16 +0100 Subject: [PATCH] Few fixes + audio playback (#667) * QT 6 * document audio * QT 6 * experiment - add audio * experiment - add audio * fix ip check * fix ip check * fix ip check * fix ip check * update gst location * update gst version * update gst version * back to 1,20.5 * alaw * lgstalaw * exp autoaudiosrc * exp autoaudiosrc * alaw and audio * register plugins * weird * fix * add gstautoetect * weird * weird * so no alaw --- QOpenHD.pro | 6 - android/AndroidManifest.xml | 2 +- android/src/org/openhd/IsConnected.java | 173 ------------------ .../org/openhd/LiveVideoPlayerWrapper.java | 49 ----- android/src/org/openhd/QOpenHDActivity.java | 3 - app/main.cpp | 19 +- app/telemetry/MavlinkTelemetry.cpp | 5 +- app/telemetry/MavlinkTelemetry.h | 2 +- app/telemetry/settings/documentedparam.cpp | 7 +- app/telemetry/telemetry.pri | 2 - app/util/qopenhd.cpp | 12 +- .../android/qandroidmediaplayer.cpp | 1 - .../android/qandroidmediaplayer.h | 4 - app/videostreaming/gstreamer/gst_video.pri | 7 +- .../gstreamer/gstrtpaudioplayer.cpp | 79 +++++++- .../gstreamer/gstrtpaudioplayer.h | 3 + .../vscommon/audio_playback.cpp | 34 ++++ app/videostreaming/vscommon/audio_playback.h | 9 + app/videostreaming/vscommon/vscommon.pri | 2 + .../fetch_extract_locally.sh | 5 +- .../connect/PaneConnectionMode.qml | 12 +- 21 files changed, 153 insertions(+), 283 deletions(-) delete mode 100644 android/src/org/openhd/IsConnected.java delete mode 100644 android/src/org/openhd/LiveVideoPlayerWrapper.java create mode 100644 app/videostreaming/vscommon/audio_playback.cpp create mode 100644 app/videostreaming/vscommon/audio_playback.h diff --git a/QOpenHD.pro b/QOpenHD.pro index 96d9d1cfb..a5e5a2a14 100755 --- a/QOpenHD.pro +++ b/QOpenHD.pro @@ -175,12 +175,6 @@ DISTFILES += \ android/res/values/libs.xml \ android/res/values/styles.xml \ android/src/QOpenHDActivity.java \ - android/src/SurfaceTextureListener.java \ - android/src/org/freedesktop/gstreamer/androidmedia/GstAhcCallback.java \ - android/src/org/freedesktop/gstreamer/androidmedia/GstAhsCallback.java \ - android/src/org/freedesktop/gstreamer/androidmedia/GstAmcOnFrameAvailableListener.java \ - android/src/org/openhd/IsConnected.java \ - android/src/org/openhd/LiveVideoPlayerWrapper.java \ qml/qtquickcontrols2.conf \ qml/ui/qmldir \ diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index 12bed522d..7b8e52467 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -1,6 +1,6 @@ - + diff --git a/android/src/org/openhd/IsConnected.java b/android/src/org/openhd/IsConnected.java deleted file mode 100644 index 5b8bac471..000000000 --- a/android/src/org/openhd/IsConnected.java +++ /dev/null @@ -1,173 +0,0 @@ -package org.openhd; - -import android.app.Activity; -import android.app.AlertDialog; -import android.content.ActivityNotFoundException; -import android.content.ComponentName; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.IntentFilter; -import android.net.wifi.SupplicantState; -import android.net.wifi.WifiInfo; -import android.net.wifi.WifiManager; -import android.os.Bundle; -import android.os.Looper; -import android.util.Log; -import android.widget.Toast; - -import java.net.Inet4Address; -import java.net.InetAddress; -import java.net.NetworkInterface; -import java.util.Enumeration; - -//Created for FPV-VR by Constantin -//Helps with USB status / start USB tethering - -public final class IsConnected { - - public static Context m_stored_context=null; - - public enum USB_CONNECTION{ - NOTHING,DATA,TETHERING - } - - private static boolean checkWifiConnectedToNetwork(final Context context,final String networkName){ - WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE); - WifiInfo wifiInfo; - if(wifiManager==null){ - return false; - } - wifiInfo = wifiManager.getConnectionInfo(); - if (wifiInfo.getSupplicantState() == SupplicantState.COMPLETED ) { - String ssid = wifiInfo.getSSID(); - return ssid.equals(networkName); - } - return false; - //System.out.println(wifiInfo.getSupplicantState().toString()); - } - - public static boolean checkWifiConnectedOpenHD(final Context context){ - return checkWifiConnectedToNetwork(context,"\"Open.HD\""); - } - - public static boolean checkWifiConnectedTest(final Context context){ - return checkWifiConnectedToNetwork(context,"\"TestAero\""); - } - - public static boolean checkWifiConnectedEZWB(final Context context){ - return checkWifiConnectedToNetwork(context,"\"EZ-WifiBroadcast\""); - } - - - public static USB_CONNECTION getUSBStatus(Context context){ - final Intent intent = context.registerReceiver(null, new IntentFilter("android.hardware.usb.action.USB_STATE")); - if(intent!=null){ - final Bundle extras=intent.getExtras(); - if(extras!=null){ - final boolean connected=extras.getBoolean("connected",false); - final boolean tetheringActive=extras.getBoolean("rndis",false); - if(tetheringActive){ - return USB_CONNECTION.TETHERING; - } - if(connected){ - return USB_CONNECTION.DATA; - } - } - } - //UsbManager manager=(UsbManager)context.getSystemService(Context.USB_SERVICE); - //manager.getClass().getDeclaredMethods(). - return USB_CONNECTION.NOTHING; - } - - - public static String getUSBTetheringLoopbackAddress(){ - try{ - for(Enumeration en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();){ - final NetworkInterface intf=en.nextElement(); - //System.out.println("Intf:"+intf.getName()); - if(intf.getName().contains("rndis")){ - final Enumeration inetAdresses=intf.getInetAddresses(); - while (inetAdresses.hasMoreElements()){ - final InetAddress inetAddress=inetAdresses.nextElement(); - System.out.println(inetAddress.toString()); - //if(inetAddress.isLoopbackAddress()){ - return inetAddress.toString().replace("/",""); - //} - } - } - } - }catch(Exception e){e.printStackTrace();} - return null; - } - - public static int getLastNumberOfIP(final String ip){ - String[] parts = ip.split("."); - assert (parts.length==4); - return Integer.parseInt(parts[3]); - } - - public static void openUSBTetherSettings(final Context c){ - try{ - final Intent intent = new Intent(Intent.ACTION_MAIN, null); - intent.addCategory(Intent.CATEGORY_LAUNCHER); - final ComponentName cn = new ComponentName("com.android.settings", "com.android.settings.TetherSettings"); - intent.setComponent(cn); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - c.startActivity(intent); - }catch (ActivityNotFoundException e){ - e.printStackTrace(); - Toast.makeText(c,"USB Tethering is not available on this Phone",Toast.LENGTH_LONG).show(); - } - } - - public static void makeAlertDialogOpenTetherSettings(final Context c){ - Log.d("TEST","makeAlertDialogOpenTetherSettings"); - new AlertDialog.Builder(c).setMessage("enable 'USB tethering' (not wifi,but usb hotspot)") - .setPositiveButton("Okay", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - openUSBTetherSettings(c); - } - }).show(); - } - // For QT - public static void makeAlertDialogOpenTetherSettings2(){ - Log.d("TEST","makeAlertDialogOpenTetherSettings2"); - if(m_stored_context!=null){ - ((Activity)m_stored_context).runOnUiThread(new Runnable() { - @Override - public void run() { - makeAlertDialogOpenTetherSettings(m_stored_context); - } - }); - } - } - - - // X - //get all Inet4Addresses that are - //either wifi or wifi hotspot or usb tethering - public static String getActiveInetAddresses(){ - StringBuilder s= new StringBuilder(); - try{ - final Enumeration networkInterfacesEnumeration=NetworkInterface.getNetworkInterfaces(); - while (networkInterfacesEnumeration.hasMoreElements()){ - final NetworkInterface networkInterface=networkInterfacesEnumeration.nextElement(); - if(!networkInterface.isUp() || networkInterface.getName().contains("dummy0") || networkInterface.isLoopback()){ - continue; - } - final Enumeration inetAddressesEnumeration=networkInterface.getInetAddresses(); - while (inetAddressesEnumeration.hasMoreElements()){ - InetAddress inetAddress=inetAddressesEnumeration.nextElement(); - if(inetAddress instanceof Inet4Address){ - s.append("Interface ").append(networkInterface.getName()).append(": ").append(inetAddress.getHostAddress()).append("\n"); - } - } - } - return s.toString(); - }catch(Exception e){e.printStackTrace();} - return ""; - } - -} diff --git a/android/src/org/openhd/LiveVideoPlayerWrapper.java b/android/src/org/openhd/LiveVideoPlayerWrapper.java deleted file mode 100644 index e1b556a8a..000000000 --- a/android/src/org/openhd/LiveVideoPlayerWrapper.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.openhd; - -import android.media.MediaPlayer; -import android.view.Surface; -import android.graphics.SurfaceTexture; - -import java.io.IOException; - -//import org.freedesktop.gstreamer.tutorials.tutorial_3.GstLivePlayer; - -public class LiveVideoPlayerWrapper { - - private final MediaPlayer mMediaPlayer=new MediaPlayer(); - - //private final GstLivePlayer m_live_player=new GstLivePlayer(); - - //public void x_on_create(Context c){ - //m_live_player.xx_init(c); - //} - private Surface mSurface=null; - - public void setSurfaceTexture(SurfaceTexture st){ - mSurface=new Surface(st); - setSurface(mSurface); - } - - public void setSurface(Surface surface){ - mMediaPlayer.setSurface(surface); - } - - public void playUrl(String url){ - mMediaPlayer.stop(); - mMediaPlayer.reset(); - try { - mMediaPlayer.setDataSource(url); - mMediaPlayer.prepare(); - mMediaPlayer.start(); - mMediaPlayer.setLooping(true); - } catch (IOException e) { - e.printStackTrace(); - } - } - - public void releaseAll(){ - mMediaPlayer.stop(); - mMediaPlayer.reset(); - mMediaPlayer.release(); - } -} diff --git a/android/src/org/openhd/QOpenHDActivity.java b/android/src/org/openhd/QOpenHDActivity.java index 94e81fb8e..f64f48804 100644 --- a/android/src/org/openhd/QOpenHDActivity.java +++ b/android/src/org/openhd/QOpenHDActivity.java @@ -17,8 +17,6 @@ import android.widget.RelativeLayout; // Custom video surface end -import org.openhd.IsConnected; - public class QOpenHDActivity extends QtActivity { private static QOpenHDActivity _instance = null; @@ -39,7 +37,6 @@ public static void jniOnLoad() { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - IsConnected.m_stored_context= this; // Init surface /*surfaceView = new SurfaceView(this); diff --git a/app/main.cpp b/app/main.cpp index 2bb72417a..81d9b5313 100755 --- a/app/main.cpp +++ b/app/main.cpp @@ -7,11 +7,6 @@ #include #if defined(__android__) #include -const QVector permissions({"android.permission.INTERNET", - "android.permission.WRITE_EXTERNAL_STORAGE", - "android.permission.READ_EXTERNAL_STORAGE", - "android.permission.ACCESS_NETWORK_STATE", - "android.permission.ACCESS_FINE_LOCATION"}); #endif #include "telemetry/models/fcmavlinksystem.h" @@ -48,13 +43,13 @@ const QVector permissions({"android.permission.INTERNET", #ifdef QOPENHD_ENABLE_GSTREAMER_QMLGLSINK #include "videostreaming/gstreamer/gst_helper.hpp" #include "videostreaming/gstreamer/gstqmlglsinkstream.h" -#include "videostreaming/gstreamer/gstrtpaudioplayer.h" #endif //QOPENHD_ENABLE_GSTREAMER_QMLGLSINK #ifdef QOPENHD_ENABLE_VIDEO_VIA_ANDROID #include #include #endif #include "videostreaming/vscommon/QOpenHDVideoHelper.hpp" +#include "videostreaming/vscommon/audio_playback.h" // Video end #include "util/qrenderstats.h" @@ -183,6 +178,11 @@ static void write_platform_context_properties(QQmlApplicationEngine& engine){ static void android_check_permissions(){ #if defined(__android__) + const QVector permissions({"android.permission.INTERNET", + "android.permission.WRITE_EXTERNAL_STORAGE", + "android.permission.READ_EXTERNAL_STORAGE", + "android.permission.ACCESS_NETWORK_STATE", + "android.permission.ACCESS_FINE_LOCATION"}); qDebug()<<"Android request permissions"; for(const QString &permission : permissions) { auto result = QtAndroid::checkPermission(permission); @@ -354,6 +354,8 @@ int main(int argc, char *argv[]) { auto adsbVehicleManager = ADSBVehicleManager::instance(); engine.rootContext()->setContextProperty("AdsbVehicleManager", adsbVehicleManager); adsbVehicleManager->onStarted(); + // video - a bit special + engine.rootContext()->setContextProperty("_decodingStatistics",&DecodingStatistcs::instance()); // And then the main part engine.rootContext()->setContextProperty("_mavlinkTelemetry", &MavlinkTelemetry::instance()); @@ -397,11 +399,9 @@ int main(int argc, char *argv[]) { #else engine.rootContext()->setContextProperty("QOPENHD_ENABLE_VIDEO_VIA_ANDROID", QVariant(false)); #endif - //GstRtpAudioPlayer::instance().start_playing(); + platform_start_audio_streaming_if_enabled(); // Platform - dependend video end ----------------------------------------------------------------- - engine.rootContext()->setContextProperty("_decodingStatistics",&DecodingStatistcs::instance()); - // This allows to use the defines as strings in qml engine.rootContext()->setContextProperty("QOPENHD_GIT_VERSION", #ifdef QOPENHD_GIT_VERSION @@ -443,5 +443,6 @@ int main(int argc, char *argv[]) { // Terminating needs a bit of special care due to the singleton usage and threads qDebug()<<"Terminating"; MavlinkTelemetry::instance().terminate(); + platform_audio_terminate(); return retval; } diff --git a/app/telemetry/MavlinkTelemetry.cpp b/app/telemetry/MavlinkTelemetry.cpp index 225eab8ad..46fd39271 100644 --- a/app/telemetry/MavlinkTelemetry.cpp +++ b/app/telemetry/MavlinkTelemetry.cpp @@ -314,11 +314,8 @@ void MavlinkTelemetry::change_telemetry_connection_mode(int mavlink_connection_m m_connection_mode=mavlink_connection_mode; } -bool MavlinkTelemetry::change_manual_tcp_ip(QString ip) +void MavlinkTelemetry::change_manual_tcp_ip(QString ip) { - if(!QOpenHD::instance().is_valid_ip(ip)){ - return false; - } threadsafe_set_manual_tcp_ip(ip.toStdString()); } diff --git a/app/telemetry/MavlinkTelemetry.h b/app/telemetry/MavlinkTelemetry.h index b8e952701..1a6dc4ae7 100644 --- a/app/telemetry/MavlinkTelemetry.h +++ b/app/telemetry/MavlinkTelemetry.h @@ -60,7 +60,7 @@ class MavlinkTelemetry : public QObject Q_INVOKABLE void re_apply_rates(); // Change the conenction mode Q_INVOKABLE void change_telemetry_connection_mode(int mode); - Q_INVOKABLE bool change_manual_tcp_ip(QString ip); + Q_INVOKABLE void change_manual_tcp_ip(QString ip); public: // A couple of stats exposed as QT properties L_RO_PROP(int,telemetry_pps_in,set_telemetry_pps_in,-1) diff --git a/app/telemetry/settings/documentedparam.cpp b/app/telemetry/settings/documentedparam.cpp index 188a3cf3a..4ac48cd2d 100644 --- a/app/telemetry/settings/documentedparam.cpp +++ b/app/telemetry/settings/documentedparam.cpp @@ -583,7 +583,12 @@ static std::vector> get_parameters_list(){ append_only_documented(ret,"RC_UPDATE_HZ", "Specify the update rate of RC over wifibroadcast. A higher update rate gives lower RC latency, but takes more bandwidth away from the downlink." "No effect if joy rc is disabled."); - + } + { + append_int(ret,"AUDIO_ENABLE", + ImprovedIntSetting::createEnumEnableDisable(), + "enables / disables audio streaming from air to ground. In development. Enabling automatically restarts the air unit !" + ); } return ret; } diff --git a/app/telemetry/telemetry.pri b/app/telemetry/telemetry.pri index edc81a1f3..8edef12e9 100644 --- a/app/telemetry/telemetry.pri +++ b/app/telemetry/telemetry.pri @@ -1,7 +1,5 @@ INCLUDEPATH += $$PWD -#INCLUDEPATH += $$PWD/../../lib/mavlink-headers - SOURCES += \ $$PWD/action/impl/cmdsender.cpp \ $$PWD/action/fcaction.cpp \ diff --git a/app/util/qopenhd.cpp b/app/util/qopenhd.cpp index ce461e339..3b8b76da5 100644 --- a/app/util/qopenhd.cpp +++ b/app/util/qopenhd.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -308,14 +309,9 @@ void QOpenHD::sysctl_openhd(int task) bool QOpenHD::is_valid_ip(QString ip) { -#ifdef __windows__ - //TODO fix windows - return true; -#else - // TODO - return true; - -#endif + QHostAddress addr; + bool valid=addr.setAddress(ip); + return valid; } bool QOpenHD::is_platform_rpi() diff --git a/app/videostreaming/android/qandroidmediaplayer.cpp b/app/videostreaming/android/qandroidmediaplayer.cpp index 50e455ac9..33d32b520 100644 --- a/app/videostreaming/android/qandroidmediaplayer.cpp +++ b/app/videostreaming/android/qandroidmediaplayer.cpp @@ -7,7 +7,6 @@ QAndroidMediaPlayer::QAndroidMediaPlayer(QObject *parent) : QObject(parent) - //,m_mediaPlayer("org/openhd/LiveVideoPlayerWrapper") { setup_start_video_decoder_display(); } diff --git a/app/videostreaming/android/qandroidmediaplayer.h b/app/videostreaming/android/qandroidmediaplayer.h index 5c9053ee2..4dfceff3d 100644 --- a/app/videostreaming/android/qandroidmediaplayer.h +++ b/app/videostreaming/android/qandroidmediaplayer.h @@ -31,10 +31,6 @@ class QAndroidMediaPlayer : public QObject private: QPointer m_videoOut; - // Links to LiveVideoPlayerWrapper - it is honestly easier to write java code and then copy it over into QOpenHD - // qt android (video) sucks - // replaced by our own custom logic - //QAndroidJniObject m_mediaPlayer; private: std::unique_ptr m_low_lag_decoder=nullptr; std::unique_ptr m_receiver=nullptr; diff --git a/app/videostreaming/gstreamer/gst_video.pri b/app/videostreaming/gstreamer/gst_video.pri index 3d25a6af4..aa0c7a5a8 100644 --- a/app/videostreaming/gstreamer/gst_video.pri +++ b/app/videostreaming/gstreamer/gst_video.pri @@ -20,7 +20,8 @@ android{ # this is already the "least dirty" solution I could come up with :/ #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-1.20.5 + DOWNLOADED_GST_FOLDER= $$PWD/../../../lib/gstreamer_prebuilts/gstreamer-1.0-android-universal # Set the right folder for the compile arch GSTREAMER_ARCH_FOLDER = armv7 @@ -66,7 +67,9 @@ android{ -lgstandroidmedia \ -lgstopengl \ -lgsttcp \ - -lgstapp + -lgstapp \ + -lgstalaw \ + -lgstautodetect # Rest of GStreamer dependencies diff --git a/app/videostreaming/gstreamer/gstrtpaudioplayer.cpp b/app/videostreaming/gstreamer/gstrtpaudioplayer.cpp index c8f8d2066..0c0abc369 100644 --- a/app/videostreaming/gstreamer/gstrtpaudioplayer.cpp +++ b/app/videostreaming/gstreamer/gstrtpaudioplayer.cpp @@ -4,13 +4,66 @@ #include #include - -#include #include +#include + +G_BEGIN_DECLS +// The static plugins we use +#if defined(__android__) || defined(__ios__) + GST_PLUGIN_STATIC_DECLARE(coreelements); + GST_PLUGIN_STATIC_DECLARE(playback); + GST_PLUGIN_STATIC_DECLARE(libav); + GST_PLUGIN_STATIC_DECLARE(rtp); + GST_PLUGIN_STATIC_DECLARE(rtsp); + GST_PLUGIN_STATIC_DECLARE(udp); + GST_PLUGIN_STATIC_DECLARE(videoparsersbad); + GST_PLUGIN_STATIC_DECLARE(x264); + GST_PLUGIN_STATIC_DECLARE(rtpmanager); + GST_PLUGIN_STATIC_DECLARE(isomp4); + GST_PLUGIN_STATIC_DECLARE(matroska); + GST_PLUGIN_STATIC_DECLARE(mpegtsdemux); + GST_PLUGIN_STATIC_DECLARE(opengl); + GST_PLUGIN_STATIC_DECLARE(tcp); + GST_PLUGIN_STATIC_DECLARE(app);//XX + //GST_PLUGIN_STATIC_DECLARE(alaw); + //GST_PLUGIN_STATIC_DECLARE(autodetect); +#if defined(__android__) + GST_PLUGIN_STATIC_DECLARE(androidmedia); +#elif defined(__ios__) + GST_PLUGIN_STATIC_DECLARE(applemedia); +#endif +#endif + GST_PLUGIN_STATIC_DECLARE(qmlgl); + GST_PLUGIN_STATIC_DECLARE(qgc); +G_END_DECLS + GstRtpAudioPlayer::GstRtpAudioPlayer() { - +#if defined(__android__) || defined(__ios__) + GST_PLUGIN_STATIC_REGISTER(coreelements); + GST_PLUGIN_STATIC_REGISTER(playback); + GST_PLUGIN_STATIC_REGISTER(libav); + GST_PLUGIN_STATIC_REGISTER(rtp); + GST_PLUGIN_STATIC_REGISTER(rtsp); + GST_PLUGIN_STATIC_REGISTER(udp); + GST_PLUGIN_STATIC_REGISTER(videoparsersbad); + GST_PLUGIN_STATIC_REGISTER(x264); + GST_PLUGIN_STATIC_REGISTER(rtpmanager); + GST_PLUGIN_STATIC_REGISTER(isomp4); + GST_PLUGIN_STATIC_REGISTER(matroska); + GST_PLUGIN_STATIC_REGISTER(mpegtsdemux); + GST_PLUGIN_STATIC_REGISTER(opengl); + GST_PLUGIN_STATIC_REGISTER(tcp); + GST_PLUGIN_STATIC_REGISTER(app);//XX + //GST_PLUGIN_STATIC_REGISTER(alaw); + //GST_PLUGIN_STATIC_REGISTER(autodetect); +#if defined(__android__) + GST_PLUGIN_STATIC_REGISTER(androidmedia); +#elif defined(__ios__) + GST_PLUGIN_STATIC_REGISTER(applemedia); +#endif +#endif } GstRtpAudioPlayer &GstRtpAudioPlayer::instance() @@ -23,19 +76,17 @@ GstRtpAudioPlayer &GstRtpAudioPlayer::instance() static std::string construct_gstreamer_pipeline(){ std::stringstream ss; //ss<<"audiotestsrc ! autoaudiosink"; - ss<<"udpsrc port=5610 caps=\"application/x-rtp, media=(string)audio, clock-rate=(int)8000, encoding-name=(string)L16, encoding-params=(string)1, channels=(int)1, payload=(int)96\" ! rtpL16depay ! queue ! autoaudiosink sync=false"; + //ss<<"udpsrc port=5610 caps=\"application/x-rtp, media=(string)audio, clock-rate=(int)8000, encoding-name=(string)L16, encoding-params=(string)1, channels=(int)1, payload=(int)96\" ! rtpL16depay ! queue ! autoaudiosink sync=false"; + ss<<"udpsrc port=5610 caps=\"application/x-rtp, media=(string)audio, clock-rate=(int)8000, encoding-name=(string)PCMA\""; + ss<<" ! rtppcmadepay ! audio/x-alaw, rate=8000, channels=1 ! alawdec ! "; + ss<<"autoaudiosink sync=false"; + //ss<<"openslessink"; return ss.str(); } void GstRtpAudioPlayer::start_playing() { qDebug()<<"GstRtpAudioPlayer::start_playing() begin"; - QSettings settings; - const bool dev_enable_live_audio_playback=settings.value("dev_enable_live_audio_playback", false).toBool(); - if(!dev_enable_live_audio_playback){ - qDebug()<<"Live audio playback is disabled"; - return; - } assert(m_gst_pipeline==nullptr); const auto pipeline=construct_gstreamer_pipeline(); GError *error = nullptr; @@ -43,10 +94,13 @@ void GstRtpAudioPlayer::start_playing() qDebug() << "GSTREAMER PIPE=[" << pipeline.c_str()<<"]"; if (error) { qDebug() << "gst_parse_launch error: " << error->message; + //on_error("audio parse launch error"); + on_error(error->message); return; } if(!m_gst_pipeline || !(GST_IS_PIPELINE(m_gst_pipeline))){ qDebug()<<"Cannot construct pipeline"; + on_error("audio pipeline error"); m_gst_pipeline = nullptr; return; } @@ -64,3 +118,8 @@ void GstRtpAudioPlayer::stop_playing() m_gst_pipeline=nullptr; } } + +void GstRtpAudioPlayer::on_error(std::string tag) +{ + LogMessagesModel::instanceGround().add_message_debug("QOpenHD",tag.c_str()); +} diff --git a/app/videostreaming/gstreamer/gstrtpaudioplayer.h b/app/videostreaming/gstreamer/gstrtpaudioplayer.h index ec9bcdd61..f992545ed 100644 --- a/app/videostreaming/gstreamer/gstrtpaudioplayer.h +++ b/app/videostreaming/gstreamer/gstrtpaudioplayer.h @@ -3,6 +3,8 @@ #include "gst/gstelement.h" +#include + /** * @brief Input: "RTP audio" * Output: Hopefully the system speaker ;) @@ -18,6 +20,7 @@ class GstRtpAudioPlayer private: // The gstreamer pipeline GstElement * m_gst_pipeline=nullptr; + void on_error(std::string tag); }; #endif // GSTRTPAUDIOPLAYER_H diff --git a/app/videostreaming/vscommon/audio_playback.cpp b/app/videostreaming/vscommon/audio_playback.cpp new file mode 100644 index 000000000..240694824 --- /dev/null +++ b/app/videostreaming/vscommon/audio_playback.cpp @@ -0,0 +1,34 @@ +#include "audio_playback.h" +#include "qdebug.h" + +#include + + +#ifdef QOPENHD_ENABLE_GSTREAMER_QMLGLSINK +#include "../gstreamer/gstrtpaudioplayer.h" +#endif + +#include +#include + +void platform_start_audio_streaming_if_enabled() +{ + QSettings settings; + const bool dev_enable_live_audio_playback=settings.value("dev_enable_live_audio_playback", false).toBool(); + if(!dev_enable_live_audio_playback){ + qDebug()<<"Live audio playback is disabled"; + return; + } +#ifdef QOPENHD_ENABLE_GSTREAMER_QMLGLSINK + GstRtpAudioPlayer::instance().start_playing(); + return; +#endif + LogMessagesModel::instanceGround().add_message_debug("QOpenHD","No audio playback"); +} + +void platform_audio_terminate() +{ +#ifdef QOPENHD_ENABLE_GSTREAMER_QMLGLSINK + GstRtpAudioPlayer::instance().stop_playing(); +#endif +} diff --git a/app/videostreaming/vscommon/audio_playback.h b/app/videostreaming/vscommon/audio_playback.h new file mode 100644 index 000000000..b98e0a830 --- /dev/null +++ b/app/videostreaming/vscommon/audio_playback.h @@ -0,0 +1,9 @@ +#ifndef AUDIOX_H +#define AUDIOX_H + + +void platform_start_audio_streaming_if_enabled(); + +void platform_audio_terminate(); + +#endif // AUDIOX_H diff --git a/app/videostreaming/vscommon/vscommon.pri b/app/videostreaming/vscommon/vscommon.pri index 12002a930..35a88d80a 100644 --- a/app/videostreaming/vscommon/vscommon.pri +++ b/app/videostreaming/vscommon/vscommon.pri @@ -32,8 +32,10 @@ windows { HEADERS += \ $$PWD/ExternalDecodeService.hpp \ + $$PWD/audio_playback.h \ $$PWD/custom/rawreceiver.h SOURCES += \ + $$PWD/audio_playback.cpp \ $$PWD/custom/rawreceiver.cpp diff --git a/lib/gstreamer_prebuilts/fetch_extract_locally.sh b/lib/gstreamer_prebuilts/fetch_extract_locally.sh index 320b61c3a..ce97c4eb2 100755 --- a/lib/gstreamer_prebuilts/fetch_extract_locally.sh +++ b/lib/gstreamer_prebuilts/fetch_extract_locally.sh @@ -2,9 +2,10 @@ wget --quiet https://gstreamer.freedesktop.org/data/pkg/android/1.20.5/gstreamer-1.0-android-universal-1.20.5.tar.xz -mkdir -p gstreamer-1.0-android-universal-1.20.5 +# NOTE: We intentionally do not include the version in the extracted folder +mkdir -p gstreamer-1.0-android-universal -tar xf gstreamer-1.0-android-universal-1.20.5.tar.xz -C gstreamer-1.0-android-universal-1.20.5 +tar xf gstreamer-1.0-android-universal-1.20.5.tar.xz -C gstreamer-1.0-android-universal ls diff --git a/qml/ui/configpopup/connect/PaneConnectionMode.qml b/qml/ui/configpopup/connect/PaneConnectionMode.qml index ec0de98a9..1d2e72e0d 100644 --- a/qml/ui/configpopup/connect/PaneConnectionMode.qml +++ b/qml/ui/configpopup/connect/PaneConnectionMode.qml @@ -236,10 +236,6 @@ Rectangle{ TextField { Layout.alignment: Qt.AlignCenter id: textFieldip - // TODO QT 6 - //validator: RegExpValidator { - // regExp: /^((?:[0-1]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\.){0,3}(?:[0-1]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])$/ - //} validator: RegularExpressionValidator{ regularExpression: /^((?:[0-1]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\.){0,3}(?:[0-1]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])$/ } @@ -250,11 +246,13 @@ Rectangle{ Layout.alignment: Qt.AlignCenter text: "SAVE" onClicked: { - if(!_mavlinkTelemetry.change_manual_tcp_ip(textFieldip.text)){ + const m_text=textFieldip.text; + if(!_qopenhd.is_valid_ip(m_text)){ _qopenhd.show_toast("Please enter a valid ip"); - }else{ - settings.qopenhd_mavlink_connection_manual_tcp_ip=textFieldip.text + return; } + settings.qopenhd_mavlink_connection_manual_tcp_ip=m_text; + _mavlinkTelemetry.change_manual_tcp_ip(m_text); } } Text{