From bfc959385fd59284fca3e417af217d02d80cb845 Mon Sep 17 00:00:00 2001
From: Dana <Dana_Lee1016@126.com>
Date: 星期二, 23 十二月 2025 13:26:33 +0800
Subject: [PATCH] 1.h264文件写入tfcard 2.tfcard/h264/20251223/h264_时间戳.h264

---
 app/src/main/java/com/anyun/h264/H264EncodeService.java   |   64 +++++++++++++++
 app/src/main/java/com/anyun/h264/model/WatermarkInfo.java |    1 
 app/src/main/java/com/anyun/h264/util/FileUtil.java       |   47 +++++++++++
 如何检查test.h264文件.md                                        |    1 
 check_h264.py                                             |    1 
 app/src/main/java/com/anyun/h264/model/ResourceInfo.java  |    1 
 app/src/main/aidl/com/anyun/h264/model/ResourceInfo.aidl  |    1 
 app/src/main/java/com/anyun/h264/H264EncodeService2.java  |   69 ++++++++++++++++
 多进程方案使用说明.md                                              |    1 
 README_H264_CHECK.md                                      |    1 
 10 files changed, 181 insertions(+), 6 deletions(-)

diff --git a/README_H264_CHECK.md b/README_H264_CHECK.md
index 3481192..b681680 100644
--- a/README_H264_CHECK.md
+++ b/README_H264_CHECK.md
@@ -118,3 +118,4 @@
    ```
    搴旇鐪嬪埌锛歚00 00 00 01` 鎴� `00 00 01`锛圓nnex-B璧峰鐮侊級
 
+
diff --git a/app/src/main/aidl/com/anyun/h264/model/ResourceInfo.aidl b/app/src/main/aidl/com/anyun/h264/model/ResourceInfo.aidl
index feeb4e1..1a74ece 100644
--- a/app/src/main/aidl/com/anyun/h264/model/ResourceInfo.aidl
+++ b/app/src/main/aidl/com/anyun/h264/model/ResourceInfo.aidl
@@ -5,3 +5,4 @@
  */
 parcelable ResourceInfo;
 
+
diff --git a/app/src/main/java/com/anyun/h264/H264EncodeService.java b/app/src/main/java/com/anyun/h264/H264EncodeService.java
index afa5257..63306ac 100644
--- a/app/src/main/java/com/anyun/h264/H264EncodeService.java
+++ b/app/src/main/java/com/anyun/h264/H264EncodeService.java
@@ -11,6 +11,7 @@
 
 import com.anyun.h264.model.ResourceInfo;
 import com.anyun.h264.model.WatermarkInfo;
+import com.anyun.h264.util.FileUtil;
 
 import org.json.JSONException;
 import org.json.JSONObject;
@@ -123,6 +124,7 @@
      * 缂栫爜閰嶇疆绫�
      */
     private static class EncodeConfig {
+        boolean useTFCard=true;//濡傛灉涓簍rue锛屽垯鍦╰fcard 鏍圭洰褰曞缓涓�涓猦264鏂囦欢澶癸紝鍦╤264鐩綍涓嬩互褰撳墠鏃ユ湡涓哄悕瀛楃殑鏂囦欢澶癸紙姣斿20250123锛夛紝鐒跺悗h264鏂囦欢灏卞啓鍏ヤ互褰撳墠鏃ュ墠涓哄悕瀛楃殑鐩綍涓�
          boolean enableFileOutput; //鏄惁寮�鍚痟264鏂囦欢鍐欏叆
          boolean enableNetworkTransmit; //寮�鍚痟264锛岀綉缁滃疄鏃舵帹娴�
         String ip;
@@ -147,6 +149,7 @@
                 config.port = 0;
                 config.simPhone = null;
                 config.cameraId = 1; // 榛樿浣跨敤绗竴涓憚鍍忓ご
+                config.useTFCard = false; // 榛樿涓嶄娇鐢═F鍗�
                 return config;
             }
             
@@ -159,6 +162,7 @@
             config.ip = json.optString("ip", null);
             config.port = json.optInt("port", 0);
             config.simPhone = json.optString("simPhone", null);
+            config.useTFCard = json.optBoolean("useTFCard", false);
             
             // 瑙f瀽cameraId锛堝鏋滄湭鎸囧畾锛岄粯璁や负1锛�
             if (json.has("cameraId")) {
@@ -396,6 +400,57 @@
     }
     
     /**
+     * 鑾峰彇杈撳嚭鏂囦欢鐩綍锛堟牴鎹畊seTFCard閰嶇疆锛�
+     * @param useTFCard 鏄惁浣跨敤TF鍗�
+     * @return 杈撳嚭鐩綍璺緞
+     */
+    private String getOutputFileDirectory(boolean useTFCard) {
+        if (useTFCard) {
+            // 浣跨敤TF鍗★細/sdcard/h264/褰撳墠鏃ユ湡/
+            try {
+                String storagePath = FileUtil.getStoragePath(this, true);
+                if (storagePath == null || storagePath.trim().isEmpty()) {
+                    Timber.w("TF card storage path not available, fallback to app directory");
+                    return outputFileDirectory;
+                }
+                
+                File externalStorage = new File(storagePath);
+                if (!externalStorage.exists()) {
+                    Timber.w("TF card storage directory does not exist: %s, fallback to app directory", storagePath);
+                    return outputFileDirectory;
+                }
+                
+                // 鑾峰彇褰撳墠鏃ユ湡锛堟牸寮忥細yyyyMMdd锛屽20250123锛�
+                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd", Locale.CHINA);
+                String dateDir = dateFormat.format(new Date());
+                
+                // 鏋勫缓璺緞锛�/sdcard/h264/20250123/
+                File h264Dir = new File(externalStorage, "h264");
+                File dateDirFile = new File(h264Dir, dateDir);
+                
+                // 鍒涘缓鐩綍锛堝鏋滀笉瀛樺湪锛�
+                if (!dateDirFile.exists()) {
+                    boolean created = dateDirFile.mkdirs();
+                    if (!created && !dateDirFile.exists()) {
+                        Timber.e("Failed to create TF card directory: %s, fallback to app directory", dateDirFile.getAbsolutePath());
+                        return outputFileDirectory;
+                    }
+                }
+                
+                String tfCardPath = dateDirFile.getAbsolutePath();
+                Timber.d("Using TF card directory: %s", tfCardPath);
+                return tfCardPath;
+            } catch (Exception e) {
+                Timber.e(e, "Error getting TF card directory, fallback to app directory");
+                return outputFileDirectory;
+            }
+        } else {
+            // 浣跨敤搴旂敤澶栭儴瀛樺偍鐩綍
+            return outputFileDirectory;
+        }
+    }
+    
+    /**
      * 鍚姩缂栫爜锛堢粺涓�鏂规硶锛屾敮鎸佹枃浠跺啓鍏ュ拰缃戠粶浼犺緭鐨勭粍鍚堬級
      * @param config 缂栫爜閰嶇疆
      * @return 0-鎴愬姛锛�1-澶辫触
@@ -405,8 +460,8 @@
             Timber.e("Encode config cannot be null");
             return 1;
         }
-        Timber.d("Starting encode mode, fileOutput: %b, networkTransmit: %b",
-                config.enableFileOutput, config.enableNetworkTransmit);
+        Timber.d("Starting encode mode, fileOutput: %b, networkTransmit: %b, useTFCard: %b",
+                config.enableFileOutput, config.enableNetworkTransmit, config.useTFCard);
         
         // 濡傛灉缂栫爜鍣ㄥ凡缁忓湪杩愯锛屽彧鏇存柊閰嶇疆
         if (h264Encoder != null) {
@@ -456,9 +511,12 @@
         int framerate = config != null && config.framerate > 0 ? config.framerate : DEFAULT_FRAME_RATE;
             h264Encoder.setEncoderParams(width, height, framerate, DEFAULT_BITRATE);
 
+            // 鑾峰彇杈撳嚭鏂囦欢鐩綍锛堟牴鎹畊seTFCard閰嶇疆锛�
+            String outputDir = getOutputFileDirectory(config.useTFCard);
+            
             // 璁剧疆杈撳嚭鏂囦欢鐩綍锛圚264Encoder浼氳嚜鍔ㄧ鐞嗘枃浠跺垱寤猴紝姣忓垎閽熶竴涓枃浠讹級
             // 浣跨敤涓�涓复鏃舵枃浠跺悕鏉ヨ缃洰褰曪紝H264Encoder浼氬湪鍒濆鍖栨椂鍒涘缓绗竴涓枃浠�
-            File tempFile = new File(outputFileDirectory, "temp.h264");
+            File tempFile = new File(outputDir, "temp.h264");
         h264Encoder.setOutputFile(tempFile.getAbsolutePath());
         h264Encoder.setEnableFileOutput(config.enableFileOutput);
             
diff --git a/app/src/main/java/com/anyun/h264/H264EncodeService2.java b/app/src/main/java/com/anyun/h264/H264EncodeService2.java
index 112824b..6f4c927 100644
--- a/app/src/main/java/com/anyun/h264/H264EncodeService2.java
+++ b/app/src/main/java/com/anyun/h264/H264EncodeService2.java
@@ -8,6 +8,7 @@
 
 import com.anyun.h264.model.ResourceInfo;
 import com.anyun.h264.model.WatermarkInfo;
+import com.anyun.h264.util.FileUtil;
 
 import org.json.JSONException;
 import org.json.JSONObject;
@@ -102,6 +103,7 @@
         int height;
         int framerate;
         String simPhone;
+        boolean useTFCard = false; // 鏄惁浣跨敤TF鍗�
         
         // 浠嶫SON瑙f瀽閰嶇疆
         static EncodeConfig fromJson(String jsonConfig) throws JSONException {
@@ -114,6 +116,7 @@
                 config.ip = null;
                 config.port = 0;
                 config.simPhone = null;
+                config.useTFCard = false; // 榛樿涓嶄娇鐢═F鍗�
                 return config;
             }
             
@@ -124,6 +127,7 @@
             config.ip = json.optString("ip", null);
             config.port = json.optInt("port", 0);
             config.simPhone = json.optString("simPhone", null);
+            config.useTFCard = json.optBoolean("useTFCard", false);
             
             return config;
         }
@@ -216,10 +220,61 @@
     }
     
     /**
+     * 鑾峰彇杈撳嚭鏂囦欢鐩綍锛堟牴鎹畊seTFCard閰嶇疆锛�
+     * @param useTFCard 鏄惁浣跨敤TF鍗�
+     * @return 杈撳嚭鐩綍璺緞
+     */
+    private String getOutputFileDirectory(boolean useTFCard) {
+        if (useTFCard) {
+            // 浣跨敤TF鍗★細/sdcard/h264/褰撳墠鏃ユ湡/
+            try {
+                String storagePath = FileUtil.getStoragePath(this, true);
+                if (storagePath == null || storagePath.trim().isEmpty()) {
+                    Timber.w("TF card storage path not available, fallback to app directory (camera2)");
+                    return outputFileDirectory;
+                }
+                
+                File externalStorage = new File(storagePath);
+                if (!externalStorage.exists()) {
+                    Timber.w("TF card storage directory does not exist: %s, fallback to app directory (camera2)", storagePath);
+                    return outputFileDirectory;
+                }
+                
+                // 鑾峰彇褰撳墠鏃ユ湡锛堟牸寮忥細yyyyMMdd锛屽20250123锛�
+                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd", Locale.CHINA);
+                String dateDir = dateFormat.format(new Date());
+                
+                // 鏋勫缓璺緞锛�/sdcard/h264/20250123/
+                File h264Dir = new File(externalStorage, "h264");
+                File dateDirFile = new File(h264Dir, dateDir);
+                
+                // 鍒涘缓鐩綍锛堝鏋滀笉瀛樺湪锛�
+                if (!dateDirFile.exists()) {
+                    boolean created = dateDirFile.mkdirs();
+                    if (!created && !dateDirFile.exists()) {
+                        Timber.e("Failed to create TF card directory: %s, fallback to app directory (camera2)", dateDirFile.getAbsolutePath());
+                        return outputFileDirectory;
+                    }
+                }
+                
+                String tfCardPath = dateDirFile.getAbsolutePath();
+                Timber.d("Using TF card directory (camera2): %s", tfCardPath);
+                return tfCardPath;
+            } catch (Exception e) {
+                Timber.e(e, "Error getting TF card directory, fallback to app directory (camera2)");
+                return outputFileDirectory;
+            }
+        } else {
+            // 浣跨敤搴旂敤澶栭儴瀛樺偍鐩綍
+            return outputFileDirectory;
+        }
+    }
+    
+    /**
      * 鍚姩鏂囦欢缂栫爜妯″紡锛堝彧鍐欏叆鏂囦欢锛屼笉杩涜缃戠粶鎺ㄩ�侊級
      */
     private int startFileEncode(EncodeConfig config) {
-        Timber.d("Starting file encode mode (camera2)");
+        Timber.d("Starting file encode mode (camera2), useTFCard: %b", config != null ? config.useTFCard : false);
         
         // 濡傛灉缂栫爜鍣ㄥ凡缁忓湪杩愯锛屽厛鍋滄
         if (h264Encoder != null) {
@@ -238,9 +293,13 @@
             int framerate = config != null && config.framerate > 0 ? config.framerate : DEFAULT_FRAME_RATE;
             h264Encoder.setEncoderParams(width, height, framerate, DEFAULT_BITRATE);
 
+            // 鑾峰彇杈撳嚭鏂囦欢鐩綍锛堟牴鎹畊seTFCard閰嶇疆锛�
+            boolean useTFCard = config != null && config.useTFCard;
+            String outputDir = getOutputFileDirectory(useTFCard);
+            
             // 璁剧疆杈撳嚭鏂囦欢鐩綍锛圚264Encoder浼氳嚜鍔ㄧ鐞嗘枃浠跺垱寤猴紝姣忓垎閽熶竴涓枃浠讹級
             // 浣跨敤涓�涓复鏃舵枃浠跺悕鏉ヨ缃洰褰曪紝H264Encoder浼氬湪鍒濆鍖栨椂鍒涘缓绗竴涓枃浠�
-            File tempFile = new File(outputFileDirectory, "temp.h264");
+            File tempFile = new File(outputDir, "temp.h264");
             h264Encoder.setOutputFile(tempFile.getAbsolutePath());
             h264Encoder.setEnableFileOutput(true); // 鍚敤鏂囦欢杈撳嚭
             
@@ -299,9 +358,13 @@
             int framerate = config != null && config.framerate > 0 ? config.framerate : DEFAULT_FRAME_RATE;
             h264Encoder.setEncoderParams(width, height, framerate, DEFAULT_BITRATE);
 
+            // 鑾峰彇杈撳嚭鏂囦欢鐩綍锛堟牴鎹畊seTFCard閰嶇疆锛�
+            boolean useTFCard = config != null && config.useTFCard;
+            String outputDir = getOutputFileDirectory(useTFCard);
+            
             // 璁剧疆杈撳嚭鏂囦欢鐩綍锛圚264Encoder浼氳嚜鍔ㄧ鐞嗘枃浠跺垱寤猴紝姣忓垎閽熶竴涓枃浠讹級
             // 浣跨敤涓�涓复鏃舵枃浠跺悕鏉ヨ缃洰褰曪紝H264Encoder浼氬湪鍒濆鍖栨椂鍒涘缓绗竴涓枃浠�
-            File tempFile = new File(outputFileDirectory, "temp.h264");
+            File tempFile = new File(outputDir, "temp.h264");
             h264Encoder.setOutputFile(tempFile.getAbsolutePath());
             h264Encoder.setEnableFileOutput(true); // 鍚敤鏂囦欢杈撳嚭
 
diff --git a/app/src/main/java/com/anyun/h264/model/ResourceInfo.java b/app/src/main/java/com/anyun/h264/model/ResourceInfo.java
index a8b76b5..b61f8ec 100644
--- a/app/src/main/java/com/anyun/h264/model/ResourceInfo.java
+++ b/app/src/main/java/com/anyun/h264/model/ResourceInfo.java
@@ -156,3 +156,4 @@
 }
 
 
+
diff --git a/app/src/main/java/com/anyun/h264/model/WatermarkInfo.java b/app/src/main/java/com/anyun/h264/model/WatermarkInfo.java
index 0b7acc6..4f643fe 100644
--- a/app/src/main/java/com/anyun/h264/model/WatermarkInfo.java
+++ b/app/src/main/java/com/anyun/h264/model/WatermarkInfo.java
@@ -138,3 +138,4 @@
     }
 }
 
+
diff --git a/app/src/main/java/com/anyun/h264/util/FileUtil.java b/app/src/main/java/com/anyun/h264/util/FileUtil.java
new file mode 100644
index 0000000..9f84cd0
--- /dev/null
+++ b/app/src/main/java/com/anyun/h264/util/FileUtil.java
@@ -0,0 +1,47 @@
+package com.anyun.h264.util;
+
+import android.content.Context;
+import android.os.storage.StorageManager;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class FileUtil {
+    //鑾峰彇鎻掑叆鐨凾FCard鐩綍璺緞
+    public static String getStoragePath(Context mContext, boolean is_removale) {
+        if (mContext != null) {
+            StorageManager mStorageManager = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE);
+            Class<?> storageVolumeClazz = null;
+            try {
+                storageVolumeClazz = Class.forName("android.os.storage.StorageVolume");
+                Method getVolumeList = mStorageManager.getClass().getMethod("getVolumeList");
+                Method getPath = storageVolumeClazz.getMethod("getPath");
+                Method isRemovable = storageVolumeClazz.getMethod("isRemovable");
+                Object result = getVolumeList.invoke(mStorageManager);
+                final int length = Array.getLength(result);
+                for (int i = 0; i < length; i++) {
+                    Object storageVolumeElement = Array.get(result, i);
+                    String path = (String) getPath.invoke(storageVolumeElement);
+                    boolean removable = (Boolean) isRemovable.invoke(storageVolumeElement);
+                    if (is_removale == removable) {
+                        return path;
+                    }
+                }
+            } catch (ClassNotFoundException e) {
+                e.printStackTrace();
+            } catch (InvocationTargetException e) {
+                e.printStackTrace();
+            } catch (NoSuchMethodException e) {
+                e.printStackTrace();
+            } catch (IllegalAccessException e) {
+                e.printStackTrace();
+            }
+            return  null;
+        } else {
+
+            return null;
+        }
+
+    }
+}
diff --git a/check_h264.py b/check_h264.py
index e9d5f5d..a9f36f3 100644
--- a/check_h264.py
+++ b/check_h264.py
@@ -208,3 +208,4 @@
     sys.exit(0 if success else 1)
 
 
+
diff --git "a/\345\244\232\350\277\233\347\250\213\346\226\271\346\241\210\344\275\277\347\224\250\350\257\264\346\230\216.md" "b/\345\244\232\350\277\233\347\250\213\346\226\271\346\241\210\344\275\277\347\224\250\350\257\264\346\230\216.md"
index b8bff4c..02addf5 100644
--- "a/\345\244\232\350\277\233\347\250\213\346\226\271\346\241\210\344\275\277\347\224\250\350\257\264\346\230\216.md"
+++ "b/\345\244\232\350\277\233\347\250\213\346\226\271\346\241\210\344\275\277\347\224\250\350\257\264\346\230\216.md"
@@ -116,3 +116,4 @@
 - 鎵�鏈夋搷浣滈兘閫氳繃AIDL鎺ュ彛杩涜杩涚▼闂撮�氫俊
 
 
+
diff --git "a/\345\246\202\344\275\225\346\243\200\346\237\245test.h264\346\226\207\344\273\266.md" "b/\345\246\202\344\275\225\346\243\200\346\237\245test.h264\346\226\207\344\273\266.md"
index 8058f55..cbd700f 100644
--- "a/\345\246\202\344\275\225\346\243\200\346\237\245test.h264\346\226\207\344\273\266.md"
+++ "b/\345\246\202\344\275\225\346\243\200\346\237\245test.h264\346\226\207\344\273\266.md"
@@ -182,3 +182,4 @@
 3. **鐢╒LC鎾斁**楠岃瘉
 4. **濡傛灉杩樻湁闂**锛岃繍琛屾鏌ュ伐鍏疯幏鍙栬缁嗚瘖鏂�
 
+

--
Gitblit v1.8.0