From 2fc938aa3f1518e7695afb589fc8e3782e66f068 Mon Sep 17 00:00:00 2001
From: Dana <Dana_Lee1016@126.com>
Date: 星期三, 03 十二月 2025 13:25:06 +0800
Subject: [PATCH] 1.1分钟循环写入h264
---
app/src/main/java/com/anyun/h264/H264Encoder.java | 172 ++++++++++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 146 insertions(+), 26 deletions(-)
diff --git a/app/src/main/java/com/anyun/h264/H264Encoder.java b/app/src/main/java/com/anyun/h264/H264Encoder.java
index b8546a0..884fe28 100644
--- a/app/src/main/java/com/anyun/h264/H264Encoder.java
+++ b/app/src/main/java/com/anyun/h264/H264Encoder.java
@@ -76,8 +76,12 @@
// 鏂囦欢杈撳嚭
private FileOutputStream fileOutputStream;
private String outputFilePath;
+ private String outputFileDirectory; // 杈撳嚭鏂囦欢鐩綍
private boolean enableFileOutput = false; // 鏄惁鍚敤鏂囦欢杈撳嚭
private boolean spsPpsWritten = false; // 鏍囪SPS/PPS鏄惁宸插啓鍏�
+ private int cameraId = 1; // 鎽勫儚澶碔D锛岄粯璁や负1锛堢涓�涓憚鍍忓ご锛�
+ private long currentFileStartTime = 0; // 褰撳墠鏂囦欢鐨勫紑濮嬫椂闂达紙姣锛�
+ private static final long FILE_DURATION_MS = 60 * 1000; // 鏂囦欢鏃堕暱锛�1鍒嗛挓锛堟绉掞級
// 缃戠粶浼犺緭鎺у埗
private boolean enableNetworkTransmission = true; // 鏄惁鍚敤TCP/UDP缃戠粶浼犺緭
@@ -135,6 +139,22 @@
*/
public void setOutputFile(String filePath) {
this.outputFilePath = filePath;
+ // 鎻愬彇鐩綍璺緞
+ if (filePath != null && !filePath.isEmpty()) {
+ File file = new File(filePath);
+ File parentDir = file.getParentFile();
+ if (parentDir != null) {
+ this.outputFileDirectory = parentDir.getAbsolutePath();
+ }
+ }
+ }
+
+ /**
+ * 璁剧疆鎽勫儚澶碔D锛堢敤浜庣敓鎴愭枃浠跺悕锛�
+ * @param cameraId 鎽勫儚澶碔D锛�1琛ㄧず绗竴涓憚鍍忓ご锛�2琛ㄧず绗簩涓憚鍍忓ご
+ */
+ public void setCameraId(int cameraId) {
+ this.cameraId = cameraId;
}
/**
@@ -241,6 +261,11 @@
*/
public boolean initialize(int[] cameraIdRange, String cameraName, int[] resolution, boolean ayCamera) {
try {
+ // 浠巆ameraIdRange涓彁鍙朿ameraId锛堜娇鐢ㄧ涓�涓�硷級
+ if (cameraIdRange != null && cameraIdRange.length > 0) {
+ this.cameraId = cameraIdRange[0];
+ }
+
// 1. setenv
usbCamera.setenv();
@@ -277,7 +302,7 @@
// 鏇存柊瀹為檯鍒嗚鲸鐜�
width = actualResolution[0];
height = actualResolution[1];
- Timber.d("Camera initialized with resolution: " + width + "x" + height);
+ Timber.d("Camera initialized with resolution: " + width + "x" + height + ", cameraId: " + cameraId);
// 3. 鍒濆鍖朒264缂栫爜鍣�
initEncoder();
@@ -293,7 +318,7 @@
}
// 5. 鍒濆鍖栨枃浠惰緭鍑猴紙浠呭垱寤烘枃浠讹紝SPS/PPS鍦ㄧ涓�娆¤緭鍑烘椂鍐欏叆锛�
- if (enableFileOutput && outputFilePath != null && !outputFilePath.isEmpty()) {
+ if (enableFileOutput) {
if (!initFileOutput()) {
Timber.w("File output initialization failed, continuing without file output");
}
@@ -333,21 +358,35 @@
*/
private boolean initFileOutput() {
try {
- File file = new File(outputFilePath);
- File parentDir = file.getParentFile();
- if (parentDir != null && !parentDir.exists()) {
- boolean created = parentDir.mkdirs();
- if (!created && !parentDir.exists()) {
- Timber.e("Failed to create parent directory: " + parentDir.getAbsolutePath());
+ // 濡傛灉outputFileDirectory涓虹┖锛屽皾璇曚粠outputFilePath鎻愬彇
+ if (outputFileDirectory == null || outputFileDirectory.isEmpty()) {
+ if (outputFilePath != null && !outputFilePath.isEmpty()) {
+ File file = new File(outputFilePath);
+ File parentDir = file.getParentFile();
+ if (parentDir != null) {
+ outputFileDirectory = parentDir.getAbsolutePath();
+ }
+ }
+ }
+
+ // 濡傛灉浠嶇劧娌℃湁鐩綍锛屼娇鐢ㄩ粯璁よ矾寰�
+ if (outputFileDirectory == null || outputFileDirectory.isEmpty()) {
+ Timber.e("Output file directory is not set");
+ return false;
+ }
+
+ // 鍒涘缓鐩綍锛堝鏋滀笉瀛樺湪锛�
+ File dir = new File(outputFileDirectory);
+ if (!dir.exists()) {
+ boolean created = dir.mkdirs();
+ if (!created && !dir.exists()) {
+ Timber.e("Failed to create output directory: " + outputFileDirectory);
return false;
}
}
-
- fileOutputStream = new FileOutputStream(file);
- spsPpsWritten = false;
-
- Timber.d("File output initialized: " + outputFilePath);
- return true;
+
+ // 鍒涘缓绗竴涓枃浠�
+ return createNewFile();
} catch (Exception e) {
Timber.e(e,"Initialize file output failed");
if (fileOutputStream != null) {
@@ -361,9 +400,67 @@
return false;
}
}
+
+ /**
+ * 鍒涘缓鏂版枃浠讹紙姣忓垎閽熻皟鐢ㄤ竴娆★級
+ * @return 鏄惁鎴愬姛
+ */
+ private boolean createNewFile() {
+ try {
+ // 鍏抽棴鏃ф枃浠�
+ if (fileOutputStream != null) {
+ try {
+ fileOutputStream.flush();
+ fileOutputStream.close();
+ Timber.d("Closed previous file: " + outputFilePath);
+ } catch (IOException e) {
+ Timber.e(e, "Error closing previous file");
+ }
+ fileOutputStream = null;
+ }
+
+ // 鐢熸垚鏂版枃浠跺悕
+ long timeFile = System.currentTimeMillis() / 1000 * 1000;
+ currentFileStartTime = timeFile;
+
+ String fileName;
+ if (cameraId == 2) {
+ fileName = "h264_camera2_" + timeFile + ".h264";
+ } else {
+ fileName = "h264_" + timeFile + ".h264";
+ }
+
+ File newFile = new File(outputFileDirectory, fileName);
+ outputFilePath = newFile.getAbsolutePath();
+
+ // 鍒涘缓鏂版枃浠�
+ fileOutputStream = new FileOutputStream(newFile);
+ spsPpsWritten = false; // 閲嶇疆SPS/PPS鏍囪锛屾柊鏂囦欢闇�瑕侀噸鏂板啓鍏�
+
+ // 濡傛灉宸茬粡鏈夌紦瀛樼殑SPS/PPS锛岀珛鍗冲啓鍏ユ柊鏂囦欢
+ if (spsBuffer != null && ppsBuffer != null) {
+ writeSpsPpsToFile();
+ Timber.d("SPS/PPS written to new file immediately");
+ }
+
+ Timber.d("Created new file: " + outputFilePath);
+ return true;
+ } catch (Exception e) {
+ Timber.e(e, "Failed to create new file");
+ if (fileOutputStream != null) {
+ try {
+ fileOutputStream.close();
+ } catch (IOException ie) {
+ Timber.e(ie, "Close file output stream failed");
+ }
+ fileOutputStream = null;
+ }
+ return false;
+ }
+ }
/**
- * 鍐欏叆SPS/PPS鍒版枃浠讹紙浠嶤SD鎴栧叧閿抚鏁版嵁涓彁鍙栵級
+ * 鍐欏叆SPS/PPS鍒版枃浠讹紙浼樺厛浣跨敤缂撳瓨鐨凷PS/PPS锛屽惁鍒欎粠CSD鑾峰彇锛�
*/
private void writeSpsPpsToFile() {
if (!enableFileOutput || fileOutputStream == null || spsPpsWritten) {
@@ -371,17 +468,29 @@
}
try {
- // 灏濊瘯浠庣紪鐮佸櫒杈撳嚭鏍煎紡涓幏鍙朇SD
- MediaFormat format = encoder.getOutputFormat();
- ByteBuffer spsBuffer = format.getByteBuffer("csd-0"); // SPS
- ByteBuffer ppsBuffer = format.getByteBuffer("csd-1"); // PPS
-
+ // 浼樺厛浣跨敤缂撳瓨鐨凷PS/PPS锛堣繖浜涙槸Annex-B鏍煎紡锛屽凡缁忓寘鍚捣濮嬬爜锛�
if (spsBuffer != null && ppsBuffer != null) {
+ // 鐩存帴鍐欏叆缂撳瓨鐨凷PS/PPS锛堝凡缁忔槸Annex-B鏍煎紡锛�
+ fileOutputStream.write(spsBuffer);
+ fileOutputStream.write(ppsBuffer);
+ fileOutputStream.flush();
+
+ spsPpsWritten = true;
+ Timber.d("SPS/PPS written to file from cache, SPS size: " + spsBuffer.length + ", PPS size: " + ppsBuffer.length);
+ return;
+ }
+
+ // 濡傛灉缂撳瓨涓病鏈夛紝灏濊瘯浠庣紪鐮佸櫒杈撳嚭鏍煎紡涓幏鍙朇SD
+ MediaFormat format = encoder.getOutputFormat();
+ ByteBuffer csdSpsBuffer = format.getByteBuffer("csd-0"); // SPS
+ ByteBuffer csdPpsBuffer = format.getByteBuffer("csd-1"); // PPS
+
+ if (csdSpsBuffer != null && csdPpsBuffer != null) {
// CSD鏍煎紡閫氬父鏄疉VCC鏍煎紡锛岄渶瑕佽浆鎹负Annex-B
- byte[] sps = new byte[spsBuffer.remaining()];
- byte[] pps = new byte[ppsBuffer.remaining()];
- spsBuffer.get(sps);
- ppsBuffer.get(pps);
+ byte[] sps = new byte[csdSpsBuffer.remaining()];
+ byte[] pps = new byte[csdPpsBuffer.remaining()];
+ csdSpsBuffer.get(sps);
+ csdPpsBuffer.get(pps);
// 鍐欏叆SPS鍜孭PS鍒版枃浠讹紙Annex-B鏍煎紡锛�
byte[] nalStartCode = {0x00, 0x00, 0x00, 0x01};
@@ -415,9 +524,9 @@
fileOutputStream.flush();
spsPpsWritten = true;
- Timber.d("SPS/PPS written to file, SPS size: " + spsLength + ", PPS size: " + ppsLength);
+ Timber.d("SPS/PPS written to file from CSD, SPS size: " + spsLength + ", PPS size: " + ppsLength);
} else {
- Timber.w("SPS/PPS not found in CSD, will extract from first key frame");
+ Timber.w("SPS/PPS not found in cache or CSD, will extract from first key frame");
}
} catch (Exception e) {
Timber.e(e,"Write SPS/PPS to file error");
@@ -680,6 +789,17 @@
}
try {
+ // 妫�鏌ユ槸鍚﹂渶瑕佸垱寤烘柊鏂囦欢锛堟瘡鍒嗛挓锛�
+ long currentTime = System.currentTimeMillis();
+ if (currentFileStartTime > 0 && (currentTime - currentFileStartTime) >= FILE_DURATION_MS) {
+ Timber.d("File duration reached 1 minute, creating new file");
+ if (!createNewFile()) {
+ Timber.e("Failed to create new file, stopping file output");
+ enableFileOutput = false;
+ return;
+ }
+ }
+
// 濡傛灉鏄涓�涓叧閿抚锛岀‘淇漇PS/PPS宸插啓鍏�
if (isKeyFrame && !spsPpsWritten) {
writeSpsPpsToFile();
--
Gitblit v1.8.0