改由装置端实现RTMP server

main
Matthew 7 months ago
parent 5fa64ee06b
commit 9f31e79605

@ -121,6 +121,9 @@ mediaServerId=your_server_id
#最多等待未初始化的Track时间单位毫秒超时之后会忽略未初始化的Track #最多等待未初始化的Track时间单位毫秒超时之后会忽略未初始化的Track
wait_track_ready_ms=10000 wait_track_ready_ms=10000
#最多等待音频Track收到数据时间单位毫秒超时且完全没收到音频数据忽略音频Track
#加快某些带封装的流metadata说明有音频但是实际上没有的流ready时间比如很多厂商的GB28181 PS
wait_audio_track_data_ms=1000
#如果流只有单Track最多等待若干毫秒超时后未收到其他Track的数据则认为是单Track #如果流只有单Track最多等待若干毫秒超时后未收到其他Track的数据则认为是单Track
#如果协议元数据有声明特定track数那么无此等待时间 #如果协议元数据有声明特定track数那么无此等待时间
wait_add_track_ms=3000 wait_add_track_ms=3000
@ -128,6 +131,8 @@ wait_add_track_ms=3000
unready_frame_cache=100 unready_frame_cache=100
#是否启用观看人数变化事件广播置1则启用置0则关闭 #是否启用观看人数变化事件广播置1则启用置0则关闭
broadcast_player_count_changed=0 broadcast_player_count_changed=0
#绑定的本地网卡ip
listen_ip=::
[hls] [hls]
#hls写文件的buf大小调整参数可以提高文件io性能 #hls写文件的buf大小调整参数可以提高文件io性能
@ -369,13 +374,13 @@ start_bitrate=0
max_bitrate=0 max_bitrate=0
min_bitrate=0 min_bitrate=0
#nack接收端 #nack接收端, rtp发送端zlm发送rtc流
#Nack缓存包最早时间间隔 #rtp重发缓存列队最大长度单位毫秒
maxNackMS=5000 maxRtpCacheMS=5000
#Nack包检查间隔(包数量) #rtp重发缓存列队最大长度单位个数
rtpCacheCheckInterval=100 maxRtpCacheSize=2048
#nack发送端 #nack发送端rtp接收端zlm接收rtc推流
#最大保留的rtp丢包状态个数 #最大保留的rtp丢包状态个数
nackMaxSize=2048 nackMaxSize=2048
#rtp丢包状态最长保留时间 #rtp丢包状态最长保留时间

@ -3,6 +3,11 @@
<head> <head>
<title>ZLM RTC demo</title> <title>ZLM RTC demo</title>
<script src="./ZLMRTCClient.js"></script> <script src="./ZLMRTCClient.js"></script>
<script src="https://unpkg.com/vconsole@latest/dist/vconsole.min.js"></script>
<script>
// VConsole will be exported to `window.VConsole` by default.
var vConsole = new window.VConsole();
</script>
<style> <style>
video { video {
width: 40vw; width: 40vw;

@ -27,7 +27,7 @@
android:usesCleartextTraffic="true" android:usesCleartextTraffic="true"
android:extractNativeLibs="true" android:extractNativeLibs="true"
android:requestLegacyExternalStorage="true" android:requestLegacyExternalStorage="true"
tools:targetApi="31"> tools:targetApi="28">
<activity <activity
android:name=".StreamActivity" android:name=".StreamActivity"
android:exported="false" /> android:exported="false" />

@ -0,0 +1,107 @@
package com.xypower.mpremote;
import android.content.Context;
import android.text.TextUtils;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import dadb.AdbKeyPair;
import dadb.Dadb;
public class AdbManager {
private static class InternalAdb {
public Dadb adb;
public String ip;
public int port;
}
private static AdbKeyPair mAdbKeyPair;
private static Object mLocker = new Object();
private static Map<String, InternalAdb> mAdbs = new HashMap<>();
public static void initManager(Context context) {
File file = new File(context.getFilesDir(), ".keypair");
if (!file.exists()) {
file.mkdirs();
}
final File pubKeyFile = new File(file, "pub.key");
final File priKeyFile = new File(file, "pri.key");
if (!priKeyFile.exists() || !pubKeyFile.exists()) {
AdbKeyPair.generate(priKeyFile, pubKeyFile);
}
mAdbKeyPair = AdbKeyPair.read(priKeyFile, pubKeyFile);
}
public static Dadb getAdb(String ip, int port) {
synchronized (mLocker) {
if (mAdbs.containsKey(ip)) {
InternalAdb adb = mAdbs.get(ip);
if (adb != null && adb.port == port) {
if (adb.adb != null) {
return adb.adb;
}
}
mAdbs.remove(ip);
if (adb != null && adb.adb != null) {
try {
adb.adb.close();
} catch (Exception ex) {
ex.printStackTrace();
}
adb.adb = null;
}
adb = null;
}
InternalAdb adb = new InternalAdb();
adb.ip = ip;
adb.port = port;
adb.adb = Dadb.create(ip, port, mAdbKeyPair);
mAdbs.put(ip, adb);
return adb.adb;
}
}
public static void releaseAdb(String ip) {
synchronized (mLocker) {
if (mAdbs.containsKey(ip)) {
InternalAdb adb = mAdbs.get(ip);
mAdbs.remove(ip);
if (adb != null && adb.adb != null) {
try {
adb.adb.close();
} catch (Exception ex) {
ex.printStackTrace();
}
adb.adb = null;
}
adb = null;
}
}
}
public static void clear() {
synchronized (mLocker) {
for (InternalAdb adb : mAdbs.values()) {
if (adb != null && adb.adb != null) {
try {
adb.adb.close();
} catch (Exception ex) {
ex.printStackTrace();
}
adb.adb = null;
}
adb = null;
}
mAdbs.clear();
}
}
}

@ -92,16 +92,14 @@ public class DeviceActivity extends AppCompatActivity {
private static final String KEY_IMEI = KEY_PREFIX_GLOBAL_SETTING + "dev_imei"; private static final String KEY_IMEI = KEY_PREFIX_GLOBAL_SETTING + "dev_imei";
private static final String KEY_IMEI2 = KEY_PREFIX_GLOBAL_SETTING + "dev_imei2"; private static final String KEY_IMEI2 = KEY_PREFIX_GLOBAL_SETTING + "dev_imei2";
private static final int ADB_SERVER_PORT = 5555;
// [vendor.ril.nw.signalstrength.lte.1]: [-85,27] // [vendor.ril.nw.signalstrength.lte.1]: [-85,27]
//[vendor.ril.nw.signalstrength.lte.2]: [-86,27] //[vendor.ril.nw.signalstrength.lte.2]: [-86,27]
private ActivityDeviceBinding binding; private ActivityDeviceBinding binding;
private ProgressDialog mProgressDialog; private ProgressDialog mProgressDialog;
private Handler mHandler; private Handler mHandler;
private String mCmdId;
private String mDeviceIp; private String mDeviceIp;
private AdbKeyPair mAdbKeyPair;
private Map<String, String> mProps = new HashMap<>(); private Map<String, String> mProps = new HashMap<>();
private Map<Integer, JSONObject> mChannelCfgs = new HashMap(); private Map<Integer, JSONObject> mChannelCfgs = new HashMap();
@ -127,20 +125,6 @@ public class DeviceActivity extends AppCompatActivity {
mHandler = new Handler(); mHandler = new Handler();
File file = new File(getFilesDir(), ".keypair");
if (!file.exists()) {
file.mkdirs();
}
final File pubKeyFile = new File(file, "pub.key");
final File priKeyFile = new File(file, "pri.key");
if (!priKeyFile.exists() || !pubKeyFile.exists()) {
AdbKeyPair.generate(priKeyFile, pubKeyFile);
}
mAdbKeyPair = AdbKeyPair.read(priKeyFile, pubKeyFile);
final Context context = getApplicationContext();
binding.takePhoto1.setOnClickListener(new View.OnClickListener() { binding.takePhoto1.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
@ -197,9 +181,17 @@ public class DeviceActivity extends AppCompatActivity {
} }
}); });
final Context context = getApplicationContext();
loadDeviceInfo(context, true); loadDeviceInfo(context, true);
} }
@Override
protected void onDestroy() {
super.onDestroy();
AdbManager.releaseAdb(mDeviceIp);
}
protected void loadDeviceInfo(final Context context, boolean firstConnect) { protected void loadDeviceInfo(final Context context, boolean firstConnect) {
binding.deviceInfo.setText(""); binding.deviceInfo.setText("");
@ -240,7 +232,7 @@ public class DeviceActivity extends AppCompatActivity {
private void runImpl() { private void runImpl() {
Log.d(TAG, "Adb discovering " + mDeviceIp); Log.d(TAG, "Adb discovering " + mDeviceIp);
Dadb adb = Dadb.create(mDeviceIp, AdbUtils.DEFAULT_ADB_PORT, mAdbKeyPair); Dadb adb = AdbManager.getAdb(mDeviceIp, AdbUtils.DEFAULT_ADB_PORT);
Log.d(TAG, "Adb Connected"); Log.d(TAG, "Adb Connected");
if (adb == null) { if (adb == null) {
@ -427,7 +419,7 @@ public class DeviceActivity extends AppCompatActivity {
try { try {
Log.i(TAG, "Start connecting " + mDeviceIp); Log.i(TAG, "Start connecting " + mDeviceIp);
adb = Dadb.create(mDeviceIp, AdbUtils.DEFAULT_ADB_PORT, mAdbKeyPair); adb = AdbManager.getAdb(mDeviceIp, AdbUtils.DEFAULT_ADB_PORT);
Log.i(TAG, "Finish connecting " + mDeviceIp); Log.i(TAG, "Finish connecting " + mDeviceIp);
if (adb == null) { if (adb == null) {
@ -498,14 +490,8 @@ public class DeviceActivity extends AppCompatActivity {
} }
} }
} finally { } catch (Exception ex) {
try { ex.printStackTrace();
if (adb != null) {
adb.close();
}
} catch (Exception ex) {
ex.printStackTrace();
}
} }
} }
@ -554,12 +540,9 @@ public class DeviceActivity extends AppCompatActivity {
} }
protected long takeVideo(int channel, int preset, final boolean photoOrVideo) { protected long takeVideo(int channel, int preset, final boolean photoOrVideo) {
//
Intent intent = getIntent(); Intent intent = getIntent();
String localIp = intent.getStringExtra("localIp"); String localIp = intent.getStringExtra("localIp");
showStreaming(channel, channel - 1, "rtmp://" + localIp + "/live/0", localIp); showStreaming(channel, channel - 1, "rtmp://" + mDeviceIp + "/live/0", localIp);
return 0; return 0;
/* /*

@ -115,6 +115,8 @@ public class MainActivity extends AppCompatActivity {
loadSettings(); loadSettings();
mHandler = new Handler(); mHandler = new Handler();
AdbManager.initManager(this);
mConnectivityManager = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE); mConnectivityManager = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
binding.listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { binding.listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {

@ -40,7 +40,6 @@ public class StreamActivity extends AppCompatActivity {
private ExoPlayer exoPlayer; private ExoPlayer exoPlayer;
private String mDeviceIp; private String mDeviceIp;
private AdbKeyPair mAdbKeyPair;
private Handler mHandler; private Handler mHandler;
@Override @Override
@ -65,48 +64,7 @@ public class StreamActivity extends AppCompatActivity {
actionBar.setTitle(getResources().getString(R.string.channel) + Integer.toString(channel)); actionBar.setTitle(getResources().getString(R.string.channel) + Integer.toString(channel));
File file = new File(getFilesDir(), ".keypair"); String url = "rtmp://" + mDeviceIp + "/live/0";
if (!file.exists()) {
file.mkdirs();
}
final File pubKeyFile = new File(file, "pub.key");
final File priKeyFile = new File(file, "pri.key");
if (!priKeyFile.exists() || !pubKeyFile.exists()) {
AdbKeyPair.generate(priKeyFile, pubKeyFile);
}
mAdbKeyPair = AdbKeyPair.read(priKeyFile, pubKeyFile);
File streamingDir = new File(getDataDir(), "streaming");
if (!streamingDir.exists()) {
streamingDir.mkdirs();
}
File confFile = new File(streamingDir, "zlmediakit.ini");
InputStream inputStream = null;
FileOutputStream fos = null;
try {
inputStream = getAssets().open("config.ini");
fos = new FileOutputStream(confFile);
int len=-1;
byte[] buffer = new byte[1024];
while ((len=inputStream.read(buffer)) != -1) {
fos.write(buffer,0, len);
}
fos.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
FilesUtils.closeFriendly(inputStream);
FilesUtils.closeFriendly(fos);
}
ZLMediaKit.startServer(streamingDir.getAbsolutePath());
// localIp= "127.0.0.1";
String url = "rtmp://" + localIp + "/live/0";
String cmd = "am start -n com.xypower.mplive/com.xypower.mplive.MainActivity --ei cameraId " + Integer.toString(cameraId) + " --ei rotation " String cmd = "am start -n com.xypower.mplive/com.xypower.mplive.MainActivity --ei cameraId " + Integer.toString(cameraId) + " --ei rotation "
+ Integer.toString(rotation) + " --ei autoStart 1 --es url \"" + url + "\""; + Integer.toString(rotation) + " --ei autoStart 1 --es url \"" + url + "\"";
@ -121,7 +79,6 @@ public class StreamActivity extends AppCompatActivity {
startStreaming(cmd, runnable); startStreaming(cmd, runnable);
} }
private void startStreaming(final String cmd, final Runnable runnable) { private void startStreaming(final String cmd, final Runnable runnable) {
Log.d(TAG, cmd); Log.d(TAG, cmd);
Thread th = new Thread(new Runnable() { Thread th = new Thread(new Runnable() {
@ -132,7 +89,7 @@ public class StreamActivity extends AppCompatActivity {
try { try {
Log.i(TAG, "Start connecting " + mDeviceIp); Log.i(TAG, "Start connecting " + mDeviceIp);
adb = Dadb.create(mDeviceIp, AdbUtils.DEFAULT_ADB_PORT, mAdbKeyPair); adb = AdbManager.getAdb(mDeviceIp, AdbUtils.DEFAULT_ADB_PORT);
Log.i(TAG, "Finish connecting " + mDeviceIp); Log.i(TAG, "Finish connecting " + mDeviceIp);
if (adb == null) { if (adb == null) {
@ -164,21 +121,15 @@ public class StreamActivity extends AppCompatActivity {
if (adbShellResponse.getExitCode() == 0) { if (adbShellResponse.getExitCode() == 0) {
try { try {
Thread.sleep(4000); Thread.sleep(1000);
} catch (Exception ex) { } catch (Exception ex) {
} }
runOnUiThread(runnable); runOnUiThread(runnable);
} }
} }
} finally { } catch (Exception ex) {
try { ex.printStackTrace();
if (adb != null) {
adb.close();
}
} catch (Exception ex) {
ex.printStackTrace();
}
} }
} }
@ -198,7 +149,7 @@ public class StreamActivity extends AppCompatActivity {
try { try {
Log.i(TAG, "Start connecting " + mDeviceIp); Log.i(TAG, "Start connecting " + mDeviceIp);
adb = Dadb.create(mDeviceIp, AdbUtils.DEFAULT_ADB_PORT, mAdbKeyPair); adb = AdbManager.getAdb(mDeviceIp, AdbUtils.DEFAULT_ADB_PORT);
Log.i(TAG, "Finish connecting " + mDeviceIp); Log.i(TAG, "Finish connecting " + mDeviceIp);
if (adb == null) { if (adb == null) {
@ -216,14 +167,8 @@ public class StreamActivity extends AppCompatActivity {
if (adbShellResponse.getExitCode() == 0) { if (adbShellResponse.getExitCode() == 0) {
} }
} }
} finally { } catch (Exception ex) {
try { ex.printStackTrace();
if (adb != null) {
adb.close();
}
} catch (Exception ex) {
ex.printStackTrace();
}
} }
} }
@ -234,17 +179,10 @@ public class StreamActivity extends AppCompatActivity {
private void initializePlayer() { private void initializePlayer() {
Intent intent = getIntent();
String localIp = intent.getStringExtra("localIp");
if (TextUtils.isEmpty(localIp)) {
return;
}
PlayerView playerView = findViewById(R.id.playerView); PlayerView playerView = findViewById(R.id.playerView);
exoPlayer = new ExoPlayer.Builder(this).build(); exoPlayer = new ExoPlayer.Builder(this).build();
playerView.setPlayer(exoPlayer); playerView.setPlayer(exoPlayer);
MediaItem mediaItem = MediaItem.fromUri("rtmp://127.0.0.1/live/0"); MediaItem mediaItem = MediaItem.fromUri("rtmp://" + mDeviceIp + "/live/0");
ProgressiveMediaSource videoSource = new ProgressiveMediaSource.Factory(new RtmpDataSource.Factory()) ProgressiveMediaSource videoSource = new ProgressiveMediaSource.Factory(new RtmpDataSource.Factory())
.createMediaSource(mediaItem); .createMediaSource(mediaItem);
@ -258,9 +196,6 @@ public class StreamActivity extends AppCompatActivity {
super.onDestroy(); super.onDestroy();
stopStreaming(); stopStreaming();
ZLMediaKit.stopServer();
} }
@OptIn(markerClass = UnstableApi.class) @Override @OptIn(markerClass = UnstableApi.class) @Override

Loading…
Cancel
Save