Dana
2025-12-01 964db3e1a2d6e2ab277da1ffcb27064bd2776848
app/src/main/java/com/anyun/h264/H264EncodeService.java
@@ -7,6 +7,7 @@
import timber.log.Timber;
import com.anyun.h264.model.ResourceInfo;
import com.anyun.h264.model.WatermarkInfo;
import org.json.JSONException;
import org.json.JSONObject;
@@ -29,6 +30,7 @@
    private H264Encoder h264Encoder;
    private H264FileTransmitter h264FileTransmitter; // H264文件传输器
    private String outputFileDirectory; // H264文件输出目录
    private WatermarkInfo currentWatermarkInfo; // 当前水印信息
    
    // 默认编码参数
    private static final int DEFAULT_WIDTH = 640;
@@ -50,6 +52,11 @@
        @Override
        public List<ResourceInfo> getResourceList(String startTime, String endTime) throws RemoteException {
            return H264EncodeService.this.getResourceList(startTime, endTime);
        }
        @Override
        public void setWatermarkInfo(String watermarkInfo) throws RemoteException {
            H264EncodeService.this.setWatermarkInfo(watermarkInfo);
        }
    };
    
@@ -259,6 +266,11 @@
            // 初始化并启动(使用配置中的分辨率)
            int[] resolution = {width, height};
            if (h264Encoder.initialize(DEFAULT_CAMERA_ID_RANGE, null, resolution, false)) {
                // 应用已保存的水印信息(如果有)
                if (currentWatermarkInfo != null) {
                    h264Encoder.setWatermarkInfo(currentWatermarkInfo);
                    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);
@@ -321,6 +333,11 @@
            // 初始化并启动(使用配置中的分辨率)
            int[] resolution = {width, height};
            if (h264Encoder.initialize(DEFAULT_CAMERA_ID_RANGE, null, resolution, false)) {
                // 应用已保存的水印信息(如果有)
                if (currentWatermarkInfo != null) {
                    h264Encoder.setWatermarkInfo(currentWatermarkInfo);
                    Timber.d("Applied saved watermark info to encoder");
                }
                h264Encoder.start();
                Timber.d("Network encode started successfully, server: %s:%d, resolution: %dx%d, framerate: %d", 
                        config.ip, config.port, width, height, framerate);
@@ -534,6 +551,100 @@
    }
    
    /**
     * 设置水印信息
     * @param watermarkInfoJson 水印信息JSON字符串,包含:车牌(plateNumber)、学员(student)、教练(coach)、
     *                          经度(longitude)、纬度(latitude)、驾校(drivingSchool)、车速(speed)
     *                          示例:{"plateNumber":"京A12345","student":"张三","coach":"李四",
     *                                "longitude":116.397128,"latitude":39.916527,"drivingSchool":"XX驾校","speed":60.5}
     */
    private void setWatermarkInfo(String watermarkInfoJson) {
        Timber.d("setWatermarkInfo called, watermarkInfoJson: %s", watermarkInfoJson);
        try {
            if (watermarkInfoJson == null || watermarkInfoJson.trim().isEmpty()) {
                Timber.w("Watermark info JSON is null or empty, clearing watermark");
                currentWatermarkInfo = null;
                // 如果编码器正在运行,清除水印
                if (h264Encoder != null) {
                    h264Encoder.setWatermarkInfo(null);
                }
                return;
            }
            // 解析JSON
            JSONObject json = new JSONObject(watermarkInfoJson);
            WatermarkInfo watermarkInfo = new WatermarkInfo();
            // 解析各个字段(使用 optString/optDouble 避免字段不存在时抛出异常)
            watermarkInfo.setPlateNumber(json.optString("plateNumber", null));
            watermarkInfo.setStudent(json.optString("student", null));
            watermarkInfo.setCoach(json.optString("coach", null));
            // 经度和纬度可能是数字或字符串
            if (json.has("longitude")) {
                Object lonObj = json.get("longitude");
                if (lonObj instanceof Number) {
                    watermarkInfo.setLongitude(((Number) lonObj).doubleValue());
                } else if (lonObj instanceof String) {
                    try {
                        watermarkInfo.setLongitude(Double.parseDouble((String) lonObj));
                    } catch (NumberFormatException e) {
                        Timber.w("Invalid longitude format: %s", lonObj);
                    }
                }
            }
            if (json.has("latitude")) {
                Object latObj = json.get("latitude");
                if (latObj instanceof Number) {
                    watermarkInfo.setLatitude(((Number) latObj).doubleValue());
                } else if (latObj instanceof String) {
                    try {
                        watermarkInfo.setLatitude(Double.parseDouble((String) latObj));
                    } catch (NumberFormatException e) {
                        Timber.w("Invalid latitude format: %s", latObj);
                    }
                }
            }
            watermarkInfo.setDrivingSchool(json.optString("drivingSchool", null));
            // 车速可能是数字或字符串
            if (json.has("speed")) {
                Object speedObj = json.get("speed");
                if (speedObj instanceof Number) {
                    watermarkInfo.setSpeed(((Number) speedObj).doubleValue());
                } else if (speedObj instanceof String) {
                    try {
                        watermarkInfo.setSpeed(Double.parseDouble((String) speedObj));
                    } catch (NumberFormatException e) {
                        Timber.w("Invalid speed format: %s", speedObj);
                    }
                }
            }
            // 保存水印信息
            currentWatermarkInfo = watermarkInfo;
            Timber.i("Watermark info parsed successfully: %s", watermarkInfo);
            // 如果编码器正在运行,立即应用水印
            if (h264Encoder != null) {
                h264Encoder.setWatermarkInfo(watermarkInfo);
                Timber.d("Watermark applied to encoder");
            } else {
                Timber.d("Encoder not running, watermark will be applied when encoder starts");
            }
        } catch (JSONException e) {
            Timber.e(e, "Failed to parse watermark info JSON: %s", watermarkInfoJson);
            currentWatermarkInfo = null;
        } catch (Exception e) {
            Timber.e(e, "Unexpected error setting watermark info");
            currentWatermarkInfo = null;
        }
    }
    /**
     * 从文件创建资源信息(如果文件在时间范围内)
     */
    private ResourceInfo createResourceInfoFromFile(File file, Date startDate, Date endDate) {