From e4b7cbea399e3dcc40011eaa2d2fe25696d7e894 Mon Sep 17 00:00:00 2001
From: Dana <Dana_Lee1016@126.com>
Date: 星期四, 04 十二月 2025 16:57:19 +0800
Subject: [PATCH] 1.可以先见h264 写入文件。再发推流都可以;边录边推
---
app/src/main/java/com/anyun/h264/H264EncodeService.java | 183 ++++++++++++++++++++++-----------------------
app/src/main/java/com/anyun/h264/H264Encoder.java | 12 +++
app/src/main/java/com/anyun/h264/JT1076ProtocolHelper.java | 12 ++
3 files changed, 114 insertions(+), 93 deletions(-)
diff --git a/app/src/main/java/com/anyun/h264/H264EncodeService.java b/app/src/main/java/com/anyun/h264/H264EncodeService.java
index c2655fa..afa5257 100644
--- a/app/src/main/java/com/anyun/h264/H264EncodeService.java
+++ b/app/src/main/java/com/anyun/h264/H264EncodeService.java
@@ -36,7 +36,7 @@
private H264FileTransmitter h264FileTransmitter; // H264鏂囦欢浼犺緭鍣�
private String outputFileDirectory; // H264鏂囦欢杈撳嚭鐩綍
private WatermarkInfo currentWatermarkInfo; // 褰撳墠姘村嵃淇℃伅
- private static final int H264_FILE_RETENTION_DAYS = 5; // 鍙牴鎹渶姹傝皟鏁翠负3鎴�5澶�
+ private static final int H264_FILE_RETENTION_DAYS = 1; // 鍙牴鎹渶姹傝皟鏁翠负3鎴�5澶�
// 澶氳繘绋嬫敮鎸侊細绗簩涓憚鍍忓ご鐨勬湇鍔¤繛鎺�
private IH264EncodeService camera2Service;
@@ -141,6 +141,8 @@
config.width = DEFAULT_WIDTH;
config.height = DEFAULT_HEIGHT;
config.framerate = DEFAULT_FRAME_RATE;
+ config.enableFileOutput = false;
+ config.enableNetworkTransmit = false;
config.ip = null;
config.port = 0;
config.simPhone = null;
@@ -152,6 +154,8 @@
config.width = json.optInt("width", DEFAULT_WIDTH);
config.height = json.optInt("height", DEFAULT_HEIGHT);
config.framerate = json.optInt("framerate", DEFAULT_FRAME_RATE);
+ config.enableFileOutput = json.optBoolean("enableFileOutput", false);
+ config.enableNetworkTransmit = json.optBoolean("enableNetworkTransmit", false);
config.ip = json.optString("ip", null);
config.port = json.optInt("port", 0);
config.simPhone = json.optString("simPhone", null);
@@ -240,7 +244,9 @@
case 0: // 寮�鍚痟264鏂囦欢鍐欏叆
try {
EncodeConfig config0 = EncodeConfig.fromJson(jsonConfig);
- return startFileEncode(config0);
+ config0.enableFileOutput = true;
+ config0.enableNetworkTransmit = false;
+ return startEncode(config0);
} catch (JSONException e) {
Timber.e(e, "Failed to parse JSON config: %s", jsonConfig);
return 1;
@@ -253,21 +259,35 @@
}
return stopEncoder();
- case 2: // 寮�鍚綉缁滄帹閫乭264锛堜笉鍐欏叆鏂囦欢锛�
+ case 2: // 寮�鍚綉缁滄帹閫乭264锛堝彲鍚屾椂鍐欏叆鏂囦欢锛�
try {
EncodeConfig config2 = EncodeConfig.fromJson(jsonConfig);
- return startNetworkEncode(config2);
+ // 妫�鏌ュ繀闇�鐨勯厤缃弬鏁�
+ if (config2 == null || config2.ip == null || config2.ip.trim().isEmpty() || config2.port <= 0) {
+ Timber.e("Network encode requires valid ip and port in config");
+ return 1; // 澶辫触
+ }
+ config2.enableNetworkTransmit = true;
+ return startEncode(config2);
} catch (JSONException e) {
Timber.e(e, "Failed to parse JSON config: %s", jsonConfig);
return 1;
}
- case 3: // 鍋滄h264缂栫爜骞跺仠姝㈢綉缁滄帹閫�
+ case 3: // 鍋滄缃戠粶鎺ㄩ�侊紙淇濇寔鏂囦欢鍐欏叆锛�
// 妫�鏌ユ槸鍚︽寚瀹氫簡cameraId=2
if (cameraId != null && cameraId == 2) {
return controlEncodeInProcess2(action, jsonConfig);
}
- return stopEncoder();
+ // 鍙叧闂綉缁滀紶杈擄紝淇濇寔鏂囦欢鍐欏叆
+ if (h264Encoder != null) {
+ h264Encoder.setEnableNetworkTransmission(false);
+ Timber.d("Network transmission stopped, file output continues");
+ return 0;
+ } else {
+ Timber.w("Encoder is not running");
+ return 0; // 鎴愬姛锛堟病鏈夎繍琛岀殑缂栫爜鍣紝瑙嗕负鎴愬姛锛�
+ }
case 4: // 寮�濮嬩紶杈揌264鏂囦欢
try {
@@ -376,35 +396,82 @@
}
/**
- * 鍚姩鏂囦欢缂栫爜妯″紡锛堝彧鍐欏叆鏂囦欢锛屼笉杩涜缃戠粶鎺ㄩ�侊級
+ * 鍚姩缂栫爜锛堢粺涓�鏂规硶锛屾敮鎸佹枃浠跺啓鍏ュ拰缃戠粶浼犺緭鐨勭粍鍚堬級
+ * @param config 缂栫爜閰嶇疆
+ * @return 0-鎴愬姛锛�1-澶辫触
*/
- private int startFileEncode(EncodeConfig config) {
- Timber.d("Starting file encode mode");
+ private int startEncode(EncodeConfig config) {
+ if (config == null) {
+ Timber.e("Encode config cannot be null");
+ return 1;
+ }
+ Timber.d("Starting encode mode, fileOutput: %b, networkTransmit: %b",
+ config.enableFileOutput, config.enableNetworkTransmit);
- // 濡傛灉缂栫爜鍣ㄥ凡缁忓湪杩愯锛屽厛鍋滄
+ // 濡傛灉缂栫爜鍣ㄥ凡缁忓湪杩愯锛屽彧鏇存柊閰嶇疆
if (h264Encoder != null) {
- Timber.w("Encoder is already running, stopping it first");
- stopEncoder();
+ Timber.d("Encoder is already running, updating configuration");
+ try {
+ h264Encoder.setEnableFileOutput(config.enableFileOutput);
+
+
+ // 濡傛灉寮�鍚綉缁滀紶杈擄紝闇�瑕佽缃湇鍔″櫒鍦板潃鍜屽崗璁弬鏁�
+ if (config.enableNetworkTransmit) {
+ if (config == null || config.ip == null || config.ip.trim().isEmpty() || config.port <= 0) {
+ Timber.e("Network transmit requires valid ip and port in config");
+ return 1; // 澶辫触
+ }
+ h264Encoder.setServerAddress(config.ip, config.port);
+
+ // 璁剧疆鍗忚鍙傛暟锛堜娇鐢ㄩ厤缃腑鐨剆imPhone锛屽鏋滄湭鎻愪緵鍒欎娇鐢ㄩ粯璁ゅ�硷級
+ String simPhone = config.simPhone != null && !config.simPhone.trim().isEmpty()
+ ? config.simPhone : "013120122580";
+ h264Encoder.setProtocolParams(simPhone, (byte)1);
+ }
+ h264Encoder.setEnableNetworkTransmission(config.enableNetworkTransmit);
+ Timber.d("Encoder configuration updated successfully");
+ return 0; // 鎴愬姛
+ } catch (Exception e) {
+ Timber.e(e, "Error updating encoder configuration");
+ return 1; // 澶辫触
+ }
}
+ // 缂栫爜鍣ㄦ湭杩愯锛岄渶瑕佸垵濮嬪寲骞跺惎鍔�
try {
+ // 濡傛灉寮�鍚綉缁滀紶杈擄紝妫�鏌ュ繀闇�鐨勯厤缃弬鏁�
+ if (config.enableNetworkTransmit) {
+ if (config == null || config.ip == null || config.ip.trim().isEmpty() || config.port <= 0) {
+ Timber.e("Network transmit requires valid ip and port in config");
+ return 1; // 澶辫触
+ }
+ }
+
// 鍒涘缓缂栫爜鍣�
h264Encoder = new H264Encoder();
// 璁剧疆缂栫爜鍙傛暟锛堜娇鐢ㄩ厤缃腑鐨勫弬鏁帮級
int width = config != null && config.width > 0 ? config.width : DEFAULT_WIDTH;
int height = config != null && config.height > 0 ? config.height : DEFAULT_HEIGHT;
- int framerate = config != null && config.framerate > 0 ? config.framerate : DEFAULT_FRAME_RATE;
+ int framerate = config != null && config.framerate > 0 ? config.framerate : DEFAULT_FRAME_RATE;
h264Encoder.setEncoderParams(width, height, framerate, DEFAULT_BITRATE);
// 璁剧疆杈撳嚭鏂囦欢鐩綍锛圚264Encoder浼氳嚜鍔ㄧ鐞嗘枃浠跺垱寤猴紝姣忓垎閽熶竴涓枃浠讹級
// 浣跨敤涓�涓复鏃舵枃浠跺悕鏉ヨ缃洰褰曪紝H264Encoder浼氬湪鍒濆鍖栨椂鍒涘缓绗竴涓枃浠�
File tempFile = new File(outputFileDirectory, "temp.h264");
- h264Encoder.setOutputFile(tempFile.getAbsolutePath());
- h264Encoder.setEnableFileOutput(true); // 鍚敤鏂囦欢杈撳嚭
+ h264Encoder.setOutputFile(tempFile.getAbsolutePath());
+ h264Encoder.setEnableFileOutput(config.enableFileOutput);
- // 绂佺敤缃戠粶浼犺緭
- h264Encoder.setEnableNetworkTransmission(false);
+ // 璁剧疆缃戠粶浼犺緭
+ h264Encoder.setEnableNetworkTransmission(config.enableNetworkTransmit);
+ if (config.enableNetworkTransmit) {
+ h264Encoder.setServerAddress(config.ip, config.port);
+
+ // 璁剧疆鍗忚鍙傛暟锛堜娇鐢ㄩ厤缃腑鐨剆imPhone锛屽鏋滄湭鎻愪緵鍒欎娇鐢ㄩ粯璁ゅ�硷級
+ String simPhone = config.simPhone != null && !config.simPhone.trim().isEmpty()
+ ? config.simPhone : "013120122580";
+ h264Encoder.setProtocolParams(simPhone, (byte)1);
+ }
// 鍒濆鍖栧苟鍚姩锛堜娇鐢ㄩ厤缃腑鐨勫垎杈ㄧ巼锛�
// 鏍规嵁cameraId閫夋嫨鎽勫儚澶磋寖鍥�
@@ -418,79 +485,11 @@
Timber.d("Applied saved watermark info to encoder");
}
h264Encoder.start();
- Timber.d("File encode started successfully, output directory: %s, resolution: %dx%d, framerate: %d",
- outputFileDirectory, width, height, framerate);
- return 0; // 鎴愬姛
- } else {
- Timber.e("Failed to initialize encoder");
- h264Encoder = null;
- return 1; // 澶辫触
- }
- } catch (Exception e) {
- Timber.e(e, "Failed to start file encode");
- h264Encoder = null;
- return 1; // 澶辫触
- }
- }
-
- /**
- * 鍚姩缃戠粶鎺ㄩ�佹ā寮忥紙鍙繘琛岀綉缁滄帹閫侊紝涓嶅啓鍏ユ枃浠讹級
- */
- private int startNetworkEncode(EncodeConfig config) {
- Timber.d("Starting network encode mode");
-
- // 濡傛灉缂栫爜鍣ㄥ凡缁忓湪杩愯锛屽厛鍋滄
- if (h264Encoder != null) {
- Timber.w("Encoder is already running, stopping it first");
- stopEncoder();
- }
-
- // 妫�鏌ュ繀闇�鐨勯厤缃弬鏁�
- if (config == null || config.ip == null || config.ip.trim().isEmpty() || config.port <= 0) {
- Timber.e("Network encode requires valid ip and port in config");
- return 1; // 澶辫触
- }
-
- try {
- // 鍒涘缓缂栫爜鍣�
- h264Encoder = new H264Encoder();
-
- // 璁剧疆缂栫爜鍙傛暟锛堜娇鐢ㄩ厤缃腑鐨勫弬鏁帮級
- int width = config != null && config.width > 0 ? config.width : DEFAULT_WIDTH;
- int height = config != null && config.height > 0 ? config.height : DEFAULT_HEIGHT;
- int framerate = config != null && config.framerate > 0 ? config.framerate : DEFAULT_FRAME_RATE;
- h264Encoder.setEncoderParams(width, height, framerate, DEFAULT_BITRATE);
-
- // 璁剧疆杈撳嚭鏂囦欢鐩綍锛圚264Encoder浼氳嚜鍔ㄧ鐞嗘枃浠跺垱寤猴紝姣忓垎閽熶竴涓枃浠讹級
- // 浣跨敤涓�涓复鏃舵枃浠跺悕鏉ヨ缃洰褰曪紝H264Encoder浼氬湪鍒濆鍖栨椂鍒涘缓绗竴涓枃浠�
- File tempFile = new File(outputFileDirectory, "temp.h264");
- h264Encoder.setOutputFile(tempFile.getAbsolutePath());
- h264Encoder.setEnableFileOutput(config.enableFileOutput); // 鍚敤鏂囦欢杈撳嚭
-
-
- // 鍚敤缃戠粶浼犺緭骞惰缃湇鍔″櫒鍦板潃
- h264Encoder.setEnableNetworkTransmission(config.enableNetworkTransmit);
- h264Encoder.setServerAddress(config.ip, config.port);
-
- // 璁剧疆鍗忚鍙傛暟锛堜娇鐢ㄩ厤缃腑鐨剆imPhone锛屽鏋滄湭鎻愪緵鍒欎娇鐢ㄩ粯璁ゅ�硷級
- String simPhone = config.simPhone != null && !config.simPhone.trim().isEmpty()
- ? config.simPhone : "013120122580";
- h264Encoder.setProtocolParams(simPhone, (byte)1);
-
- // 鍒濆鍖栧苟鍚姩锛堜娇鐢ㄩ厤缃腑鐨勫垎杈ㄧ巼锛�
- // 鏍规嵁cameraId閫夋嫨鎽勫儚澶磋寖鍥�
- int[] cameraIdRange = DEFAULT_CAMERA_ID_RANGE;
-
- int[] resolution = {width, height};
- if (h264Encoder.initialize(cameraIdRange, null, resolution, false)) {
- // 搴旂敤宸蹭繚瀛樼殑姘村嵃淇℃伅锛堝鏋滄湁锛�
- if (currentWatermarkInfo != null) {
- h264Encoder.setWatermarkInfo(currentWatermarkInfo);
- Timber.d("Applied saved watermark info to encoder");
+ Timber.d("Encode started successfully, fileOutput: %b, networkTransmit: %b, resolution: %dx%d, framerate: %d",
+ config.enableFileOutput, config.enableNetworkTransmit, width, height, framerate);
+ if (config.enableNetworkTransmit) {
+ Timber.d("Network server: %s:%d", config.ip, config.port);
}
- h264Encoder.start();
- Timber.d("Network encode started successfully, server: %s:%d, resolution: %dx%d, framerate: %d",
- config.ip, config.port, width, height, framerate);
return 0; // 鎴愬姛
} else {
Timber.e("Failed to initialize encoder");
@@ -498,7 +497,7 @@
return 1; // 澶辫触
}
} catch (Exception e) {
- Timber.e(e, "Failed to start network encode");
+ Timber.e(e, "Failed to start encode");
h264Encoder = null;
return 1; // 澶辫触
}
@@ -581,8 +580,8 @@
h264FileTransmitter.setOnTransmitProgressCallback(new H264FileTransmitter.OnTransmitProgressCallback() {
@Override
public void onProgress(int currentFrame, int totalFrames) {
- Timber.d("File transmit progress: frame %d%s", currentFrame,
- totalFrames > 0 ? " of " + totalFrames : "");
+// Timber.d("File transmit progress: frame %d%s", currentFrame,
+// totalFrames > 0 ? " of " + totalFrames : "");
}
@Override
diff --git a/app/src/main/java/com/anyun/h264/H264Encoder.java b/app/src/main/java/com/anyun/h264/H264Encoder.java
index 7c187ad..59525d2 100644
--- a/app/src/main/java/com/anyun/h264/H264Encoder.java
+++ b/app/src/main/java/com/anyun/h264/H264Encoder.java
@@ -173,6 +173,18 @@
public void setEnableNetworkTransmission(boolean enable) {
this.enableNetworkTransmission = enable;
Timber.d("Network transmission " + (enable ? "enabled" : "disabled"));
+
+ // 濡傛灉鍦ㄧ紪鐮佽繃绋嬩腑鍔ㄦ�佸紑鍚綉缁滀紶杈擄紝闇�瑕佺‘淇濆簳灞係ocket宸茬粡寤虹珛
+ if (enable) {
+ if (!protocolHelper.initializeSocket()) {
+ Timber.e("Failed to initialize socket when enabling network transmission");
+ }
+ } else {
+ // 鍔ㄦ�佸叧闂綉缁滀紶杈撴椂锛屽強鏃堕噴鏀惧簳灞係ocket璧勬簮
+ if (protocolHelper != null) {
+ protocolHelper.closeSocket();
+ }
+ }
}
/**
diff --git a/app/src/main/java/com/anyun/h264/JT1076ProtocolHelper.java b/app/src/main/java/com/anyun/h264/JT1076ProtocolHelper.java
index c438f89..aa7e565 100644
--- a/app/src/main/java/com/anyun/h264/JT1076ProtocolHelper.java
+++ b/app/src/main/java/com/anyun/h264/JT1076ProtocolHelper.java
@@ -55,6 +55,8 @@
// TCP鍙傛暟
private JT1076TcpClient tcpClient;
+ // 鎺у埗鏈繛鎺ユ棩蹇楃殑杈撳嚭棰戠巼锛岄伩鍏嶅埛灞�
+ private boolean tcpNotConnectedLogged = false;
// RTP鍗忚鍙傛暟
private String simCardNumber = "123456789012"; // 12浣峉IM鍗″彿
@@ -162,6 +164,8 @@
@Override
public void onConnected() {
Timber.d("TCP connection established");
+ // 杩炴帴鎴愬姛鍚庯紝鍏佽涓嬫鏂紑鏃跺啀娆℃墦鍗版湭杩炴帴鍛婅
+ tcpNotConnectedLogged = false;
}
@Override
@@ -255,8 +259,14 @@
public void sendTcpPacket(byte[] packet) {
if (tcpClient != null && tcpClient.isConnected()) {
tcpClient.sendPacket(packet);
+ // 鍙戦�佹垚鍔燂紝閲嶇疆鏈繛鎺ユ棩蹇楁爣璁�
+ tcpNotConnectedLogged = false;
} else {
- Timber.w("TCP socket not connected");
+ // 浠呭湪绗竴娆℃娴嬪埌鏈繛鎺ユ椂鎵撳嵃warn锛岄伩鍏嶆棩蹇楀埛灞�
+ if (!tcpNotConnectedLogged) {
+ Timber.w("TCP socket not connected");
+ tcpNotConnectedLogged = true;
+ }
}
}
--
Gitblit v1.8.0