From 33b4919c10b89a88141a1f508b4db5a9183e07e7 Mon Sep 17 00:00:00 2001
From: Dana <Dana_Lee1016@126.com>
Date: 星期三, 28 一月 2026 14:41:22 +0800
Subject: [PATCH] 1.usb推流加水印,1秒1tie 有问题,闪烁
---
app/src/main/java/com/safeluck/floatwindow/manager/UsbCameraPushManager.java | 229 +++++++++++++++++++++++++++++++++++++++-----------------
1 files changed, 158 insertions(+), 71 deletions(-)
diff --git a/app/src/main/java/com/safeluck/floatwindow/manager/UsbCameraPushManager.java b/app/src/main/java/com/safeluck/floatwindow/manager/UsbCameraPushManager.java
index 9cdec44..6997f18 100644
--- a/app/src/main/java/com/safeluck/floatwindow/manager/UsbCameraPushManager.java
+++ b/app/src/main/java/com/safeluck/floatwindow/manager/UsbCameraPushManager.java
@@ -3,12 +3,19 @@
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
+import android.text.TextUtils;
+import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.WindowManager;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
import com.alivc.live.pusher.AlivcAudioAACProfileEnum;
import timber.log.Timber;
@@ -27,65 +34,67 @@
import com.alivc.live.pusher.AlivcQualityModeEnum;
import com.alivc.live.pusher.AlivcResolutionEnum;
import com.anyun.libusbcamera.UsbCamera;
+import com.anyun.libusbcamera.WatermarkParam;
import com.safeluck.floatwindow.MediaArgu;
import com.safeluck.floatwindow.ResponseVO;
import com.safeluck.floatwindow.util.AudioRecordManager;
+import com.safeluck.floatwindow.util.GlobalData;
/**
* USB鎽勫儚澶存帹娴佺鐞嗗櫒
*/
public class UsbCameraPushManager {
private static final String TAG = "UsbCameraPushManager";
-
+
private Context context;
private MediaArgu mediaArgu;
private PushCallback callback;
-
+
// 闃块噷鎺ㄦ祦鐩稿叧
private AlivcLivePusher alivcPusher;
private AlivcLivePushConfig alivcLivePushConfig;
private SurfaceView previewSurfaceView;
-
+
// USB鎽勫儚澶寸浉鍏�
private UsbCamera usbCamera;
private PushThread pushThread;
private boolean isRunning = false;
private boolean cameraExists = false;
private volatile boolean pushStarted = false;
-
+
// 鎺ㄦ祦URL
private String pushUrl;
-
+
// 鍒嗚鲸鐜囨暟缁� [width, height]
private int[] resolutionArr = new int[]{640, 480};
-
+
// 鏄惁寮�鍚憚鍍忓ご鍔犲瘑
private boolean ay_encrypt = false;
-
+
// 棰勮 SurfaceView 鍜岄殣钘忕殑 Window
private WindowManager windowManager;
-
+
// 闊抽鎺ㄦ祦绾跨▼姹狅紙鍗曠嚎绋嬶級
private ExecutorService audioPushExecutor;
-
+
/**
* 鎺ㄦ祦鍥炶皟鎺ュ彛
*/
public interface PushCallback {
void onResult(ResponseVO response);
}
-
+
public UsbCameraPushManager(Context context) {
this.context = context;
}
-
+
/**
* 璁剧疆鍥炶皟
*/
public void setCallback(PushCallback callback) {
this.callback = callback;
}
-
+
/**
* 寮�濮嬫帹娴�
*/
@@ -94,45 +103,46 @@
notifyCallback(1, -1, "MediaArgu is null");
return;
}
-
+
this.mediaArgu = media;
this.pushUrl = media.getUrl();
-
+
if (pushUrl == null || pushUrl.isEmpty()) {
notifyCallback(1, -2, "Push URL is empty");
return;
}
-
+
// 璁剧疆鍒嗚鲸鐜�
if (media.getM_screen() != null) {
resolutionArr[0] = media.getM_screen().getWidth();
resolutionArr[1] = media.getM_screen().getHeight();
Timber.d("璁剧疆鍒嗚鲸鐜�: %dx%d", resolutionArr[0], resolutionArr[1]);
}
-
+
try {
// 鍒濆鍖栨帹娴丼DK
initAlivcPusher();
+ setWaterMask();
pushStarted = false;
-
+
// 妫�鏌ュ苟鎵撳紑USB鎽勫儚澶�
if (!openUsbCamera()) {
cameraExists = false;
notifyCallback(1, -1, "USB鎽勫儚澶存墦寮�澶辫触");
return;
}
-
+
cameraExists = true;
Timber.d("USB鎽勫儚澶存墦寮�鎴愬姛");
-
+
notifyCallback(1, 0, "鎺ㄦ祦绾跨▼宸插惎鍔紝绛夊緟鎺ㄦ祦鐘舵�佸氨缁�");
} catch (Exception e) {
Timber.e(e, "Failed to start push");
notifyCallback(1, -3, "鍚姩鎺ㄦ祦澶辫触: " + e.getMessage());
}
}
-
+
/**
* 鍋滄鎺ㄦ祦
*/
@@ -147,54 +157,53 @@
pushStarted = false;
notifyCallback(1, 4, "鎺ㄦ祦宸插仠姝�");
}
-
+
/**
* 鍒濆鍖栭樋閲屾帹娴�
*/
private void initAlivcPusher() {
try {
alivcLivePushConfig = new AlivcLivePushConfig();
-
+
// 鏍规嵁鍒嗚鲸鐜囪缃�
setResolutionFromArray(resolutionArr);
-
+
// 寤鸿鐢ㄦ埛浣跨敤20fps
alivcLivePushConfig.setFps(AlivcFpsEnum.FPS_20);
-
+
// 鎵撳紑鐮佺巼鑷�傚簲
alivcLivePushConfig.setEnableBitrateControl(true);
-
+
// 璁剧疆妯睆鏂瑰悜
alivcLivePushConfig.setPreviewOrientation(AlivcPreviewOrientationEnum.ORIENTATION_LANDSCAPE_HOME_LEFT);
-
+
// 璁剧疆闊抽缂栫爜妯″紡
alivcLivePushConfig.setAudioProfile(AlivcAudioAACProfileEnum.AAC_LC);
-
+
// 璁剧疆鎽勫儚澶寸被鍨�
alivcLivePushConfig.setCameraType(AlivcLivePushCameraTypeEnum.CAMERA_TYPE_BACK);
-
+
// 璁剧疆瑙嗛缂栫爜妯″紡涓虹‖缂栫爜
alivcLivePushConfig.setVideoEncodeMode(AlivcEncodeModeEnum.Encode_MODE_HARD);
-
+
// 鍏抽棴缇庨
alivcLivePushConfig.setBeautyOn(false);
-
+
// 娓呮櫚搴︿紭鍏堟ā寮�
alivcLivePushConfig.setQualityMode(AlivcQualityModeEnum.QM_RESOLUTION_FIRST);
-
+
// 璁剧疆鑷畾涔夋祦妯″紡
alivcLivePushConfig.setExternMainStream(true);
alivcLivePushConfig.setAlivcExternMainImageFormat(AlivcImageFormat.IMAGE_FORMAT_YUV420P);
-
+
// 鍒濆鍖栨帹娴佸櫒
alivcPusher = new AlivcLivePusher();
alivcPusher.init(context.getApplicationContext(), alivcLivePushConfig);
-
// 澶栭儴鑷畾涔夋祦妯″紡涓嬶紝鍚屾牱闇�瑕佸厛寮�鍚瑙堬紝璁╃姸鎬佷粠 INIT 杩涘叆 PREVIEWED
// 鍒涘缓涓�涓殣钘忕殑 Window 鏉ユ壙杞� SurfaceView锛岀‘淇� Surface 鑳藉琚垱寤�
windowManager = (WindowManager) context.getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
previewSurfaceView = new SurfaceView(context.getApplicationContext());
-
+
// 鍦� SurfaceView 鐨� surfaceCreated 鍥炶皟涓啀鍚姩棰勮锛岀‘淇� Surface 宸茬粡鍒涘缓
previewSurfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
@Override
@@ -225,7 +234,7 @@
Timber.d("previewSurfaceView surfaceDestroyed");
}
});
-
+
// 灏� SurfaceView 娣诲姞鍒伴殣钘忕殑 Window 涓紝杩欐牱 Surface 鎵嶄細琚垱寤�
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
1, 1, // 1x1 鍍忕礌锛屽嚑涔庝笉鍙
@@ -239,7 +248,7 @@
params.x = -1000; // 绉诲埌灞忓箷澶�
params.y = -1000;
params.alpha = 0.0f; // 瀹屽叏閫忔槑
-
+
try {
windowManager.addView(previewSurfaceView, params);
Timber.d("previewSurfaceView added to window");
@@ -257,12 +266,90 @@
// 璁剧疆鐩戝惉鍣�
setupListeners();
-
+
Timber.d("AlivcPusher initialized successfully");
} catch (Exception e) {
Timber.e(e, "Failed to initialize AlivcPusher");
notifyCallback(1, -3, "鍒濆鍖栨帹娴丼DK澶辫触: " + e.getMessage());
}
+ }
+
+ WatermarkParam watermarkParam;
+ ArrayList<WatermarkParam> watermarkParamList = new ArrayList<>();
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ int baseY = 20;
+ int fontSize= 24;
+ private ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
+ private void setWaterMask() {
+
+ scheduledExecutorService.scheduleWithFixedDelay(() -> {
+
+
+ if (pushStarted){
+
+ if (!TextUtils.isEmpty(GlobalData.getInstance().getWaterMaskInfo())){
+ Log.i(TAG,"tieshuiin");
+
+ if (resolutionArr[0]==320&&resolutionArr[1]==240){
+ fontSize = 24;
+ baseY = 2;
+ }else if (resolutionArr[0]==640&&resolutionArr[1]==480){
+ fontSize = 32;
+ baseY = 4;
+ }else if (resolutionArr[0]==1280&&resolutionArr[1]==720){
+ fontSize = 48;
+ baseY = 6;
+ }else{
+ baseY = 2;
+ fontSize = 24;
+ }
+ String school = GlobalData.getInstance().parseWaterMaskInfo("school", "鏃�", GlobalData.ShareType.STRING);
+ watermarkParam = new WatermarkParam(10,baseY,school);
+ watermarkParamList.clear();
+ watermarkParamList.add(watermarkParam);
+
+ String teacher = GlobalData.getInstance().parseWaterMaskInfo("teacher", "鏃�", GlobalData.ShareType.STRING);
+
+
+ String stu = GlobalData.getInstance().parseWaterMaskInfo("student", "鏃�", GlobalData.ShareType.STRING);
+ baseY = fontSize*11/10+baseY;
+ watermarkParam = new WatermarkParam(10,baseY,"鏁欑粌锛�"+teacher+" 瀛﹀憳锛�"+stu);
+ watermarkParamList.add(watermarkParam);
+
+ double speed = GlobalData.getInstance().parseWaterMaskInfo("speed", 0.0, GlobalData.ShareType.DOUBLE);
+
+
+ String czh = GlobalData.getInstance().parseWaterMaskInfo("car_license", "鏃�", GlobalData.ShareType.STRING) + GlobalData.getInstance().getCameraTag;
+ baseY = fontSize*11/10+baseY;
+ watermarkParam = new WatermarkParam(10,resolutionArr[1]-baseY,czh +" "+String.format("閫熷害锛�%.1f",speed));
+ watermarkParamList.add(watermarkParam);
+
+
+ double latitude = GlobalData.getInstance().parseWaterMaskInfo("latitude", 29.51228918, GlobalData.ShareType.DOUBLE);
+ double longitude = GlobalData.getInstance().parseWaterMaskInfo("longitude", 106.45556208, GlobalData.ShareType.DOUBLE);
+
+// new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())
+ baseY = fontSize*11/10+baseY;
+ watermarkParam = new WatermarkParam(10,resolutionArr[1]-fontSize, String.format("%.6f %.6f", latitude, longitude)+" "+sdf.format(new Date()));
+ watermarkParamList.add(watermarkParam);
+
+ if (resolutionArr[0]==320&&resolutionArr[1]==240){
+ usbCamera.enableWatermark(true,"/system/ms_unicode_24.bin");
+ usbCamera.setWatermark(3,fontSize,1,watermarkParamList);
+ }else if (resolutionArr[0]==640&&resolutionArr[1]==480){
+ usbCamera.enableWatermark(true,"/system/ms_unicode_32.bin");
+ usbCamera.setWatermark(3,fontSize,1,watermarkParamList);
+ }else if (resolutionArr[0]==1280&&resolutionArr[1]==720){
+ usbCamera.enableWatermark(true,"/system/ms_unicode_48.bin");
+ usbCamera.setWatermark(3,fontSize,1,watermarkParamList);
+ }else{
+ usbCamera.enableWatermark(true,"/system/ms_unicode_24.bin");
+ usbCamera.setWatermark(3,fontSize,1,watermarkParamList);
+ }
+ }
+ }
+
+ },1,1, TimeUnit.SECONDS);
}
private Handler mainHandler = new Handler(Looper.getMainLooper());
@@ -291,12 +378,12 @@
},1000);
}
-
+
@Override
public void onPreviewStoped(AlivcLivePusher alivcLivePusher) {
Timber.d("onPreviewStoped");
}
-
+
@Override
public void onPushStarted(AlivcLivePusher alivcLivePusher) {
Timber.d("onPushStarted");
@@ -304,50 +391,50 @@
// startAudioTransfer();
notifyCallback(1, 0, "鎺ㄦ祦宸插紑濮嬶紝鍒嗚鲸鐜�: " + resolutionArr[0] + "x" + resolutionArr[1]);
}
-
+
@Override
public void onPushPauesed(AlivcLivePusher alivcLivePusher) {
Timber.d("onPushPauesed");
}
-
+
@Override
public void onPushResumed(AlivcLivePusher alivcLivePusher) {
Timber.d("onPushResumed");
}
-
+
@Override
public void onPushStoped(AlivcLivePusher alivcLivePusher) {
Timber.d("onPushStoped");
pushStarted = false;
notifyCallback(1, 4, "鎺ㄦ祦宸插仠姝�");
}
-
+
@Override
public void onPushRestarted(AlivcLivePusher alivcLivePusher) {
Timber.d("onPushRestarted");
}
-
+
@Override
public void onFirstFramePreviewed(AlivcLivePusher alivcLivePusher) {
Timber.d("onFirstFramePreviewed");
}
-
+
@Override
public void onDropFrame(AlivcLivePusher alivcLivePusher, int i, int i1) {
// 涓㈠抚鍥炶皟
}
-
+
@Override
public void onAdjustBitRate(AlivcLivePusher alivcLivePusher, int i, int i1) {
// 鐮佺巼璋冩暣鍥炶皟
}
-
+
@Override
public void onAdjustFps(AlivcLivePusher alivcLivePusher, int i, int i1) {
// 甯х巼璋冩暣鍥炶皟
}
});
-
+
// 閿欒鐩戝惉鍣�
alivcPusher.setLivePushErrorListener(new AlivcLivePushErrorListener() {
@Override
@@ -358,7 +445,7 @@
alivcLivePusher.stopPush();
}
}
-
+
@Override
public void onSDKError(AlivcLivePusher alivcLivePusher, AlivcLivePushError alivcLivePushError) {
Timber.e("onSDKError: %s", alivcLivePushError.toString());
@@ -368,7 +455,7 @@
}
}
});
-
+
// 缃戠粶鐩戝惉鍣�
alivcPusher.setLivePushNetworkListener(new AlivcLivePushNetworkListener() {
@Override
@@ -376,54 +463,54 @@
Timber.w("onNetworkPoor");
notifyCallback(1, 3, "缃戠粶杈冨樊");
}
-
+
@Override
public void onNetworkRecovery(AlivcLivePusher alivcLivePusher) {
Timber.d("onNetworkRecovery");
notifyCallback(1, 0, "缃戠粶鎭㈠");
}
-
+
@Override
public void onReconnectStart(AlivcLivePusher alivcLivePusher) {
Timber.d("onReconnectStart");
}
-
+
@Override
public void onReconnectFail(AlivcLivePusher alivcLivePusher) {
Timber.e("onReconnectFail");
notifyCallback(1, 2, "閲嶈繛澶辫触");
}
-
+
@Override
public void onReconnectSucceed(AlivcLivePusher alivcLivePusher) {
Timber.d("onReconnectSucceed");
notifyCallback(1, 0, "閲嶈繛鎴愬姛");
}
-
+
@Override
public void onSendDataTimeout(AlivcLivePusher alivcLivePusher) {
Timber.w("onSendDataTimeout");
}
-
+
@Override
public void onConnectFail(AlivcLivePusher alivcLivePusher) {
Timber.e("onConnectFail");
notifyCallback(1, -2, "杩炴帴澶辫触");
}
-
+
@Override
public String onPushURLAuthenticationOverdue(AlivcLivePusher alivcLivePusher) {
Timber.w("onPushURLAuthenticationOverdue");
return null;
}
-
+
@Override
public void onSendMessage(AlivcLivePusher alivcLivePusher) {
// 鍙戦�佹秷鎭洖璋�
}
});
}
-
+
/**
* 鏍规嵁鍒嗚鲸鐜囨暟缁勮缃垎杈ㄧ巼
*/
@@ -454,7 +541,7 @@
}
}
}
-
+
/**
* 鎵撳紑USB鎽勫儚澶�
*/
@@ -490,7 +577,7 @@
return false;
}
}
-
+
/**
* 鍚姩鎺ㄦ祦绾跨▼
*/
@@ -502,7 +589,7 @@
Timber.d("Push thread started");
}
}
-
+
/**
* 鍋滄鎺ㄦ祦绾跨▼
*/
@@ -518,7 +605,7 @@
}
Timber.d("Push thread stopped");
}
-
+
/**
* 閲婃斁闃块噷鎺ㄦ祦璧勬簮
*/
@@ -533,13 +620,13 @@
}
previewSurfaceView = null;
}
-
+
if (alivcPusher != null) {
try {
AlivcLivePushStats stats = alivcPusher.getCurrentStatus();
Timber.d("褰撳墠鎺ㄦ祦鐘舵��: %s", stats != null ? stats.name() : "null");
-
- if (stats != null && (stats == AlivcLivePushStats.PUSHED ||
+
+ if (stats != null && (stats == AlivcLivePushStats.PUSHED ||
stats == AlivcLivePushStats.PREVIEWED)) {
alivcPusher.stopPush();
}
@@ -552,7 +639,7 @@
alivcLivePushConfig = null;
pushStarted = false;
}
-
+
/**
* 鎺ㄦ祦绾跨▼
*/
@@ -561,18 +648,18 @@
public void run() {
super.run();
Timber.d("PushThread started");
-
+
try {
int width = resolutionArr[0];
int height = resolutionArr[1];
final long startTimeNs = System.nanoTime();
-
+
// 璁$畻YUV420缂撳啿鍖哄ぇ灏�
int bufferSize = width * height * 3 / 2;
byte[] buffer = new byte[bufferSize];
-
+
Timber.d("寮�濮嬫帹閫佽棰戞暟鎹紝鍒嗚鲸鐜�: %dx%d", width, height);
-
+
// 寰幆澶勭悊鎽勫儚澶存暟鎹�
while (isRunning && cameraExists) {
// 澶勭悊鎽勫儚澶存暟鎹�
--
Gitblit v1.8.0