From 964db3e1a2d6e2ab277da1ffcb27064bd2776848 Mon Sep 17 00:00:00 2001
From: Dana <Dana_Lee1016@126.com>
Date: 星期一, 01 十二月 2025 14:53:03 +0800
Subject: [PATCH] 1.添加一个设置水印的aidl接口 2.h264Encoder 设置usbcamera加水印

---
 app/src/main/java/com/anyun/h264/H264EncodeService.java               |  111 +++++++++++++++++++++++++++
 app/src/main/java/com/anyun/h264/service/H264EncodeServiceClient.java |   27 ++++++
 app/src/main/aidl/com/anyun/h264/IH264EncodeService.aidl              |    6 +
 app/src/main/java/com/anyun/h264/H264Encoder.java                     |   84 +++++++++++++++++++++
 4 files changed, 228 insertions(+), 0 deletions(-)

diff --git a/app/src/main/aidl/com/anyun/h264/IH264EncodeService.aidl b/app/src/main/aidl/com/anyun/h264/IH264EncodeService.aidl
index 4521fe8..87f6348 100644
--- a/app/src/main/aidl/com/anyun/h264/IH264EncodeService.aidl
+++ b/app/src/main/aidl/com/anyun/h264/IH264EncodeService.aidl
@@ -33,5 +33,11 @@
      * @return 璧勬簮鍒楄〃锛堟牴鎹甁T/T 1076-2016琛�23瀹氫箟锛�
      */
     List<ResourceInfo> getResourceList(String startTime, String endTime);
+    
+    /**
+     * 璁剧疆姘村嵃淇℃伅
+     * @param watermarkInfo 姘村嵃淇℃伅瀛楃涓�
+     */
+    void setWatermarkInfo(String watermarkInfo);
 }
 
diff --git a/app/src/main/java/com/anyun/h264/H264EncodeService.java b/app/src/main/java/com/anyun/h264/H264EncodeService.java
index 0f63836..9c535de 100644
--- a/app/src/main/java/com/anyun/h264/H264EncodeService.java
+++ b/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":"浜珹12345","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;
+            }
+            
+            // 瑙f瀽JSON
+            JSONObject json = new JSONObject(watermarkInfoJson);
+            WatermarkInfo watermarkInfo = new WatermarkInfo();
+            
+            // 瑙f瀽鍚勪釜瀛楁锛堜娇鐢� 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) {
diff --git a/app/src/main/java/com/anyun/h264/H264Encoder.java b/app/src/main/java/com/anyun/h264/H264Encoder.java
index 80a992a..2aa6e5d 100644
--- a/app/src/main/java/com/anyun/h264/H264Encoder.java
+++ b/app/src/main/java/com/anyun/h264/H264Encoder.java
@@ -4,11 +4,14 @@
 import android.media.MediaCodecInfo;
 import android.media.MediaFormat;
 import com.anyun.libusbcamera.UsbCamera;
+import com.anyun.libusbcamera.WatermarkParam;
+import com.anyun.h264.model.WatermarkInfo;
 
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.nio.ByteBuffer;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.concurrent.atomic.AtomicBoolean;
 
@@ -148,6 +151,87 @@
     }
 
     /**
+     * 璁剧疆姘村嵃淇℃伅
+     * @param watermarkInfo 姘村嵃淇℃伅瀵硅薄
+     */
+    public void setWatermarkInfo(WatermarkInfo watermarkInfo) {
+        if (watermarkInfo == null) {
+            Timber.w("WatermarkInfo is null, disabling watermark");
+            usbCamera.enableWatermark(false, null);
+            return;
+        }
+
+        try {
+            // 鏋勫缓姘村嵃鏂囨湰鍒楄〃锛堝垎琛屾樉绀猴紝姣忚涓�涓俊鎭」锛�
+            ArrayList<WatermarkParam> watermarkParams = new ArrayList<>();
+            
+            // 浠庡乏涓婅寮�濮嬶紝姣忚闂撮殧25鍍忕礌
+            int yOffset = 30;
+            int xOffset = 10;
+            
+            // 杞︾墝鍙�
+            if (watermarkInfo.getPlateNumber() != null && !watermarkInfo.getPlateNumber().isEmpty()) {
+                watermarkParams.add(new WatermarkParam(xOffset, yOffset, 
+                    "杞︾墝:" + watermarkInfo.getPlateNumber()));
+                yOffset += 25;
+            }
+            
+            // 瀛﹀憳濮撳悕
+            if (watermarkInfo.getStudent() != null && !watermarkInfo.getStudent().isEmpty()) {
+                watermarkParams.add(new WatermarkParam(xOffset, yOffset, 
+                    "瀛﹀憳:" + watermarkInfo.getStudent()));
+                yOffset += 25;
+            }
+            
+            // 鏁欑粌濮撳悕
+            if (watermarkInfo.getCoach() != null && !watermarkInfo.getCoach().isEmpty()) {
+                watermarkParams.add(new WatermarkParam(xOffset, yOffset, 
+                    "鏁欑粌:" + watermarkInfo.getCoach()));
+                yOffset += 25;
+            }
+            
+            // 浣嶇疆淇℃伅锛堢含搴�,缁忓害锛�
+            if (watermarkInfo.getLongitude() != null && watermarkInfo.getLatitude() != null) {
+                watermarkParams.add(new WatermarkParam(xOffset, yOffset, 
+                    String.format("浣嶇疆:%.6f,%.6f", watermarkInfo.getLatitude(), watermarkInfo.getLongitude())));
+                yOffset += 25;
+            }
+            
+            // 椹炬牎鍚嶇О
+            if (watermarkInfo.getDrivingSchool() != null && !watermarkInfo.getDrivingSchool().isEmpty()) {
+                watermarkParams.add(new WatermarkParam(xOffset, yOffset, 
+                    "椹炬牎:" + watermarkInfo.getDrivingSchool()));
+                yOffset += 25;
+            }
+            
+            // 杞﹂��
+            if (watermarkInfo.getSpeed() != null) {
+                watermarkParams.add(new WatermarkParam(xOffset, yOffset, 
+                    String.format("杞﹂��:%.1fkm/h", watermarkInfo.getSpeed())));
+            }
+            
+            if (!watermarkParams.isEmpty()) {
+                // 鍚敤姘村嵃锛屼娇鐢ㄩ粯璁ゅ瓧浣撹矾寰勶紙濡傛灉绯荤粺鏈夊瓧浣撴枃浠讹級
+                // 棰滆壊锛�0-REVERSE锛堝弽鑹诧級锛�1-BLACK锛�2-WHITE锛�3-RED锛�4-GREEN锛�5-BLUE
+                // 瀛椾綋澶у皬銆佸�嶆暟鍙互鏍规嵁闇�瑕佽皟鏁�
+                String fontPath = "/system/fonts/DroidSans.ttf"; // 榛樿瀛椾綋璺緞锛屽鏋滀笉瀛樺湪鍙互浼爊ull
+                usbCamera.enableWatermark(true, fontPath);
+                
+                // 璁剧疆姘村嵃锛氶鑹诧紙2=鐧借壊锛夛紝瀛椾綋澶у皬锛�24锛夛紝鍊嶆暟锛�1锛夛紝鏂囨湰鍒楄〃
+                usbCamera.setWatermark(2, 24, 1, watermarkParams);
+                
+                Timber.d("Watermark set successfully: %s", watermarkInfo);
+            } else {
+                Timber.w("No watermark text to display, disabling watermark");
+                usbCamera.enableWatermark(false, null);
+            }
+        } catch (Exception e) {
+            Timber.e(e, "Failed to set watermark");
+            usbCamera.enableWatermark(false, null);
+        }
+    }
+
+    /**
      * 鍒濆鍖栨憚鍍忓ご鍜岀紪鐮佸櫒
      */
     public boolean initialize(int[] cameraIdRange, String cameraName, int[] resolution, boolean ayCamera) {
diff --git a/app/src/main/java/com/anyun/h264/service/H264EncodeServiceClient.java b/app/src/main/java/com/anyun/h264/service/H264EncodeServiceClient.java
index 728d4de..be12c39 100644
--- a/app/src/main/java/com/anyun/h264/service/H264EncodeServiceClient.java
+++ b/app/src/main/java/com/anyun/h264/service/H264EncodeServiceClient.java
@@ -40,6 +40,10 @@
  * // 鑾峰彇璧勬簮鍒楄〃
  * List<ResourceInfo> resources = client.getResourceList("240101000000", "240101235959");
  * 
+ * // 璁剧疆姘村嵃淇℃伅
+ * String watermarkJson = "{\"plateNumber\":\"浜珹12345\",\"student\":\"寮犱笁\",\"coach\":\"鏉庡洓\",\"longitude\":116.397128,\"latitude\":39.916527,\"drivingSchool\":\"XX椹炬牎\",\"speed\":60.5}";
+ * client.setWatermarkInfo(watermarkJson);
+ * 
  * // 瑙g粦鏈嶅姟
  * client.unbindService();
  * </pre>
@@ -202,5 +206,28 @@
             return null;
         }
     }
+    
+    /**
+     * 璁剧疆姘村嵃淇℃伅
+     * @param watermarkInfo JSON鏍煎紡鐨勬按鍗颁俊鎭瓧绗︿覆锛屽寘鍚細plateNumber锛堣溅鐗岋級銆乻tudent锛堝鍛橈級銆乧oach锛堟暀缁冿級銆乴ongitude锛堢粡搴︼級銆乴atitude锛堢含搴︼級銆乨rivingSchool锛堥┚鏍★級銆乻peed锛堣溅閫燂級
+     *                      绀轰緥锛歿"plateNumber":"浜珹12345","student":"寮犱笁","coach":"鏉庡洓","longitude":116.397128,"latitude":39.916527,"drivingSchool":"XX椹炬牎","speed":60.5}
+     *                      濡傛灉浼犲叆null鎴栫┖瀛楃涓诧紝灏嗘竻闄ゆ按鍗�
+     * @return true-鎴愬姛锛宖alse-澶辫触
+     */
+    public boolean setWatermarkInfo(String watermarkInfo) {
+        if (!isServiceBound()) {
+            Log.e(TAG, "Service is not bound");
+            return false;
+        }
+        
+        try {
+            service.setWatermarkInfo(watermarkInfo);
+            Log.d(TAG, "setWatermarkInfo called with: " + watermarkInfo);
+            return true;
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error calling setWatermarkInfo", e);
+            return false;
+        }
+    }
 }
 

--
Gitblit v1.8.0