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/H264EncodeService.java  |   28 ++----
 app/src/main/java/com/anyun/h264/H264Encoder.java        |  172 ++++++++++++++++++++++++++++++++++++------
 app/src/main/java/com/anyun/h264/H264EncodeService2.java |   28 ++----
 3 files changed, 166 insertions(+), 62 deletions(-)

diff --git a/app/src/main/java/com/anyun/h264/H264EncodeService.java b/app/src/main/java/com/anyun/h264/H264EncodeService.java
index a798418..5d9c404 100644
--- a/app/src/main/java/com/anyun/h264/H264EncodeService.java
+++ b/app/src/main/java/com/anyun/h264/H264EncodeService.java
@@ -391,14 +391,10 @@
             int framerate = config != null && config.framerate > 0 ? config.framerate : DEFAULT_FRAME_RATE;
             h264Encoder.setEncoderParams(width, height, framerate, DEFAULT_BITRATE);
 
-            long timeFile = System.currentTimeMillis()/1000*1000;//Date鏄锛屾墍浠ヤ负浜嗚窡涓嬪彂鐨凞ate starttime涓�鑷达紝姝ゅ闄や互1000 绉�
-            SimpleDateFormat bcdFormat = new SimpleDateFormat("yyMMddHHmmss");
-            String str = bcdFormat.format(timeFile);
-            Timber.i("鏂囦欢鍚嶏細%s", str);
-            // 璁剧疆杈撳嚭鏂囦欢
-            String fileName = "h264_" + timeFile+ ".h264";
-            File outputFile = new File(outputFileDirectory, fileName);
-            h264Encoder.setOutputFile(outputFile.getAbsolutePath());
+            // 璁剧疆杈撳嚭鏂囦欢鐩綍锛圚264Encoder浼氳嚜鍔ㄧ鐞嗘枃浠跺垱寤猴紝姣忓垎閽熶竴涓枃浠讹級
+            // 浣跨敤涓�涓复鏃舵枃浠跺悕鏉ヨ缃洰褰曪紝H264Encoder浼氬湪鍒濆鍖栨椂鍒涘缓绗竴涓枃浠�
+            File tempFile = new File(outputFileDirectory, "temp.h264");
+            h264Encoder.setOutputFile(tempFile.getAbsolutePath());
             h264Encoder.setEnableFileOutput(true); // 鍚敤鏂囦欢杈撳嚭
             
             // 绂佺敤缃戠粶浼犺緭
@@ -419,8 +415,8 @@
                     Timber.d("Applied saved watermark info to encoder");
                 }
                 h264Encoder.start();
-                Timber.d("File encode started successfully, output file: %s, resolution: %dx%d, framerate: %d", 
-                        outputFile.getAbsolutePath(), width, height, framerate);
+                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");
@@ -462,14 +458,10 @@
             int framerate = config != null && config.framerate > 0 ? config.framerate : DEFAULT_FRAME_RATE;
             h264Encoder.setEncoderParams(width, height, framerate, DEFAULT_BITRATE);
 
-            long timeFile = System.currentTimeMillis()/1000*1000;
-            SimpleDateFormat bcdFormat = new SimpleDateFormat("yyMMddHHmmss");
-            String str = bcdFormat.format(timeFile);
-            Timber.i("startNetworkEncode 鏂囦欢鍚嶏細%s", str);
-            // 璁剧疆杈撳嚭鏂囦欢
-            String fileName = "h264_" + timeFile+ ".h264";
-            File outputFile = new File(outputFileDirectory, fileName);
-            h264Encoder.setOutputFile(outputFile.getAbsolutePath());
+            // 璁剧疆杈撳嚭鏂囦欢鐩綍锛圚264Encoder浼氳嚜鍔ㄧ鐞嗘枃浠跺垱寤猴紝姣忓垎閽熶竴涓枃浠讹級
+            // 浣跨敤涓�涓复鏃舵枃浠跺悕鏉ヨ缃洰褰曪紝H264Encoder浼氬湪鍒濆鍖栨椂鍒涘缓绗竴涓枃浠�
+            File tempFile = new File(outputFileDirectory, "temp.h264");
+            h264Encoder.setOutputFile(tempFile.getAbsolutePath());
             h264Encoder.setEnableFileOutput(true); // 鍚敤鏂囦欢杈撳嚭
 
             
diff --git a/app/src/main/java/com/anyun/h264/H264EncodeService2.java b/app/src/main/java/com/anyun/h264/H264EncodeService2.java
index c78a986..112824b 100644
--- a/app/src/main/java/com/anyun/h264/H264EncodeService2.java
+++ b/app/src/main/java/com/anyun/h264/H264EncodeService2.java
@@ -238,14 +238,10 @@
             int framerate = config != null && config.framerate > 0 ? config.framerate : DEFAULT_FRAME_RATE;
             h264Encoder.setEncoderParams(width, height, framerate, DEFAULT_BITRATE);
 
-            long timeFile = System.currentTimeMillis()/1000*1000;
-            SimpleDateFormat bcdFormat = new SimpleDateFormat("yyMMddHHmmss");
-            String str = bcdFormat.format(timeFile);
-            Timber.i("鏂囦欢鍚� (camera2)锛�%s", str);
-            // 璁剧疆杈撳嚭鏂囦欢锛堟坊鍔燾amera2鏍囪瘑锛�
-            String fileName = "h264_camera2_" + timeFile+ ".h264";
-            File outputFile = new File(outputFileDirectory, fileName);
-            h264Encoder.setOutputFile(outputFile.getAbsolutePath());
+            // 璁剧疆杈撳嚭鏂囦欢鐩綍锛圚264Encoder浼氳嚜鍔ㄧ鐞嗘枃浠跺垱寤猴紝姣忓垎閽熶竴涓枃浠讹級
+            // 浣跨敤涓�涓复鏃舵枃浠跺悕鏉ヨ缃洰褰曪紝H264Encoder浼氬湪鍒濆鍖栨椂鍒涘缓绗竴涓枃浠�
+            File tempFile = new File(outputFileDirectory, "temp.h264");
+            h264Encoder.setOutputFile(tempFile.getAbsolutePath());
             h264Encoder.setEnableFileOutput(true); // 鍚敤鏂囦欢杈撳嚭
             
             // 绂佺敤缃戠粶浼犺緭
@@ -260,8 +256,8 @@
                     Timber.d("Applied saved watermark info to encoder (camera2)");
                 }
                 h264Encoder.start();
-                Timber.d("File encode started successfully (camera2), output file: %s, resolution: %dx%d, framerate: %d", 
-                        outputFile.getAbsolutePath(), width, height, framerate);
+                Timber.d("File encode started successfully (camera2), output directory: %s, resolution: %dx%d, framerate: %d", 
+                        outputFileDirectory, width, height, framerate);
                 return 0; // 鎴愬姛
             } else {
                 Timber.e("Failed to initialize encoder (camera2)");
@@ -303,14 +299,10 @@
             int framerate = config != null && config.framerate > 0 ? config.framerate : DEFAULT_FRAME_RATE;
             h264Encoder.setEncoderParams(width, height, framerate, DEFAULT_BITRATE);
 
-            long timeFile = System.currentTimeMillis()/1000*1000;
-            SimpleDateFormat bcdFormat = new SimpleDateFormat("yyMMddHHmmss");
-            String str = bcdFormat.format(timeFile);
-            Timber.i("startNetworkEncode (camera2) 鏂囦欢鍚嶏細%s", str);
-            // 璁剧疆杈撳嚭鏂囦欢锛堟坊鍔燾amera2鏍囪瘑锛�
-            String fileName = "h264_camera2_" + timeFile+ ".h264";
-            File outputFile = new File(outputFileDirectory, fileName);
-            h264Encoder.setOutputFile(outputFile.getAbsolutePath());
+            // 璁剧疆杈撳嚭鏂囦欢鐩綍锛圚264Encoder浼氳嚜鍔ㄧ鐞嗘枃浠跺垱寤猴紝姣忓垎閽熶竴涓枃浠讹級
+            // 浣跨敤涓�涓复鏃舵枃浠跺悕鏉ヨ缃洰褰曪紝H264Encoder浼氬湪鍒濆鍖栨椂鍒涘缓绗竴涓枃浠�
+            File tempFile = new File(outputFileDirectory, "temp.h264");
+            h264Encoder.setOutputFile(tempFile.getAbsolutePath());
             h264Encoder.setEnableFileOutput(true); // 鍚敤鏂囦欢杈撳嚭
 
             
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