diff --git a/app/src/main/java/com/hikoncont/manager/ScreenCaptureManager.kt b/app/src/main/java/com/hikoncont/manager/ScreenCaptureManager.kt index 2fbb0ee..91ead9f 100644 --- a/app/src/main/java/com/hikoncont/manager/ScreenCaptureManager.kt +++ b/app/src/main/java/com/hikoncont/manager/ScreenCaptureManager.kt @@ -1651,7 +1651,7 @@ class ScreenCaptureManager(private val service: AccessibilityRemoteService) { } /** - * 智能压缩Bitmap为JPEG - 动态调整质量以平衡画质和传输效率 + * 压缩Bitmap为JPEG - 单次压缩,避免多次重试浪费CPU降低帧率 */ private fun compressBitmap(bitmap: Bitmap): ByteArray { val outputStream = ByteArrayOutputStream() @@ -1660,38 +1660,17 @@ class ScreenCaptureManager(private val service: AccessibilityRemoteService) { // 计算缩放比例,确保不超过最大尺寸 val scaledBitmap = scaleDownBitmap(bitmap) - // 智能压缩:根据数据大小动态调整质量 - var quality = dynamicQuality - var compressedData: ByteArray - var attempts = 0 - val maxAttempts = 3 - val targetSize = 150 * 1024 // 目标150KB,平衡质量和传输效率 - - do { - outputStream.reset() - scaledBitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream) - compressedData = outputStream.toByteArray() - attempts++ - - if (compressedData.size > targetSize && attempts < maxAttempts) { - // 数据过大,降低质量重新压缩 - quality = maxOf(25, quality - 15) // 最低不低于25 - Log.v(TAG, "数据过大(${compressedData.size} bytes),降低质量到$quality 重新压缩") - } else { - break - } - } while (attempts < maxAttempts) + // 单次压缩:直接使用动态质量参数,不做多次重试 + // 多次压缩会显著降低帧率(每次重试都是完整的JPEG编码) + scaledBitmap.compress(Bitmap.CompressFormat.JPEG, dynamicQuality, outputStream) // 如果缩放了,释放缩放后的bitmap if (scaledBitmap != bitmap) { scaledBitmap.recycle() } - Log.d(TAG, "智能压缩完成: 原始${bitmap.width}x${bitmap.height} -> 输出${compressedData.size} bytes (质量$quality, 尝试${attempts}次)") - } catch (e: Exception) { - Log.e(TAG, "智能压缩失败,使用基础压缩", e) - // 如果智能压缩失败,使用基础压缩 + Log.e(TAG, "压缩失败,使用基础压缩", e) outputStream.reset() bitmap.compress(Bitmap.CompressFormat.JPEG, dynamicQuality, outputStream) } @@ -1739,24 +1718,12 @@ class ScreenCaptureManager(private val service: AccessibilityRemoteService) { // 启动队列处理器(只启动一次) startQueueProcessor() - // 优化队列清理策略,减少画面跳跃,提供更平滑的体验 - when { - screenDataQueue.size >= 13 -> { - // 队列接近满载,适度清理2帧保持流畅(避免5帧跳跃) - Log.w(TAG, "队列接近满载(${screenDataQueue.size}/15),轻度清理旧数据保持流畅") - repeat(2) { - screenDataQueue.poll()?.let { - droppedFrameCount++ - } - } - } - screenDataQueue.size >= 11 -> { - // 中等负载,清理1帧防止积压 - Log.v(TAG, "队列中等负载(${screenDataQueue.size}/15),清理1帧防止积压") - screenDataQueue.poll()?.let { - droppedFrameCount++ - } + // 优化队列清理策略:只在队列满时丢弃最旧1帧,减少画面跳跃 + if (screenDataQueue.remainingCapacity() == 0) { + screenDataQueue.poll()?.let { + droppedFrameCount++ } + Log.v(TAG, "队列已满(15/15),丢弃最旧1帧保持流畅") } // 尝试添加新帧,如果满了就丢弃旧帧 diff --git a/app/src/main/java/com/hikoncont/network/SocketIOManager.kt b/app/src/main/java/com/hikoncont/network/SocketIOManager.kt index bcbb12f..31a26c9 100644 --- a/app/src/main/java/com/hikoncont/network/SocketIOManager.kt +++ b/app/src/main/java/com/hikoncont/network/SocketIOManager.kt @@ -246,7 +246,7 @@ class SocketIOManager(private val service: AccessibilityRemoteService) { // Screen data send rate control private var lastScreenDataTime = 0L - private val screenDataInterval = 66L // 66ms interval, matching 15fps capture rate + private val screenDataInterval = 50L // 50ms interval, matching 20fps max throughput private val maxScreenDataSize = 2 * 1024 * 1024 // 2MB限制,避免数据过大 // 📷 摄像头数据发送控制