Dana
2025-12-23 bfc959385fd59284fca3e417af217d02d80cb845
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;//如果为true,则在tfcard 根目录建一个h264文件夹,在h264目录下以当前日期为名字的文件夹(比如20250123),然后h264文件就写入以当前日前为名字的目录下
         boolean enableFileOutput; //是否开启h264文件写入
         boolean enableNetworkTransmit; //开启h264,网络实时推流
        String ip;
@@ -147,6 +149,7 @@
                config.port = 0;
                config.simPhone = null;
                config.cameraId = 1; // 默认使用第一个摄像头
                config.useTFCard = false; // 默认不使用TF卡
                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);
            
            // 解析cameraId(如果未指定,默认为1)
            if (json.has("cameraId")) {
@@ -396,6 +400,57 @@
    }
    
    /**
     * 获取输出文件目录(根据useTFCard配置)
     * @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);
            // 获取输出文件目录(根据useTFCard配置)
            String outputDir = getOutputFileDirectory(config.useTFCard);
            // 设置输出文件目录(H264Encoder会自动管理文件创建,每分钟一个文件)
            // 使用一个临时文件名来设置目录,H264Encoder会在初始化时创建第一个文件
            File tempFile = new File(outputFileDirectory, "temp.h264");
            File tempFile = new File(outputDir, "temp.h264");
        h264Encoder.setOutputFile(tempFile.getAbsolutePath());
        h264Encoder.setEnableFileOutput(config.enableFileOutput);