From 01f07011ee45d99e8b5f64824a5399b597b23be9 Mon Sep 17 00:00:00 2001
From: Dana <Dana_Lee1016@126.com>
Date: 星期二, 27 一月 2026 14:13:27 +0800
Subject: [PATCH] 1.usb rgba 2 ,正常颜色 2:使用帧索引计算时间戳,假设固定帧率。实际采集帧率可能不同,导致时间戳不准确  解决方案:使用实际经过的时间计算时间戳,确保时间戳与实际时间一致

---
 app/build.gradle.kts                                                                                      |   38 +++
 app/build/generated/aidl_source_output_dir/debug/out/com/safeluck/floatwindow/IMyCallback.java            |    2 
 key/key.jks                                                                                               |    0 
 app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at |    0 
 usbcameralib/build.gradle                                                                                 |    6 
 app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.values.at                |    0 
 key/Verify.txt                                                                                            |   41 ++++
 app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab                        |    0 
 app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.values.at              |    0 
 app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at        |    0 
 app/build/intermediates/desugar_graph/debug/dexBuilderDebug/out/currentProject/dirs_bucket_9/graph.bin    |    0 
 app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab                           |    0 
 app/src/main/java/com/safeluck/floatwindow/manager/AndroidCameraRecordManager.java                        |   18 +
 app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream                 |    0 
 app/src/main/java/com/safeluck/floatwindow/manager/UsbCameraRecordManager.java                            |  105 ++++++++--
 key/keysc626.jks                                                                                          |    0 
 key/keyrk3288.jks                                                                                         |    0 
 app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab                     |    0 
 app/src/main/java/com/safeluck/floatwindow/MediaArgu.java                                                 |    1 
 app/build/generated/aidl_source_output_dir/debug/out/com/safeluck/floatwindow/IMediaAidlInterface.java    |    2 
 app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len                       |    0 
 app/src/main/AndroidManifest.xml                                                                          |    6 
 app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i                         |    0 
 app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab.values.at           |    0 
 app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.values.at                 |    0 
 app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab                           |    0 
 app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/counters.tab                             |    2 
 app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab                          |    0 
 app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream.len             |    0 
 app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab           |    0 
 app/src/main/java/com/safeluck/floatwindow/util/VideoFileUtils.java                                       |    3 
 app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.values.at                 |    0 
 key/bjkey.jks                                                                                             |    0 
 app/src/main/java/com/safeluck/floatwindow/MainActivity.kt                                                |  368 ++++++++++++++++++++++++++++++++++--
 key/key.jks.ori                                                                                           |    0 
 app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab                  |    0 
 key/keysc200.jks                                                                                          |    0 
 keystore.properties                                                                                       |    4 
 38 files changed, 540 insertions(+), 56 deletions(-)

diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 9ee7366..ff8e19d 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -1,3 +1,6 @@
+import java.io.FileInputStream
+import java.util.Properties
+
 plugins {
     alias(libs.plugins.android.application)
     alias(libs.plugins.kotlin.android)
@@ -7,7 +10,9 @@
 android {
     namespace = "com.safeluck.floatwindow"
     compileSdk = 35
-
+    val keystorePropertiesFile = rootProject.file("keystore.properties")
+    val keystoreProperties =  Properties()
+    keystoreProperties.load(FileInputStream(keystorePropertiesFile))
     defaultConfig {
         applicationId = "com.safeluck.floatwindow"
         minSdk = 24
@@ -16,9 +21,27 @@
         versionName = "1.0"
 
         testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
+        
+        ndk {
+            abiFilters += listOf("arm64-v8a", "armeabi-v7a")
+        }
     }
     buildFeatures{
         aidl =true
+    }
+    signingConfigs {
+        create("release") {
+            keyPassword = keystoreProperties.getProperty("keyPassword")
+            keyAlias = keystoreProperties.getProperty("keyAlias")
+            storeFile = file(keystoreProperties.getProperty("storeFile") ?: "")
+            storePassword = keystoreProperties.getProperty("storePassword")
+        }
+        getByName("debug") {
+            keyPassword = keystoreProperties.getProperty("keyPassword")
+            keyAlias = keystoreProperties.getProperty("keyAlias")
+            storeFile = file(keystoreProperties.getProperty("storeFile") ?: "")
+            storePassword = keystoreProperties.getProperty("storePassword")
+        }
     }
     buildTypes {
         release {
@@ -27,6 +50,10 @@
                 getDefaultProguardFile("proguard-android-optimize.txt"),
                 "proguard-rules.pro"
             )
+            signingConfig = signingConfigs.getByName("release")
+        }
+        debug {
+            signingConfig = signingConfigs.getByName("debug")
         }
     }
     compileOptions {
@@ -39,6 +66,15 @@
     buildFeatures {
         compose = true
     }
+    
+    packaging {
+        jniLibs {
+            useLegacyPackaging = false
+        }
+        resources {
+            excludes += "/META-INF/{AL2.0,LGPL2.1}"
+        }
+    }
 }
 
 dependencies {
diff --git a/app/build/generated/aidl_source_output_dir/debug/out/com/safeluck/floatwindow/IMediaAidlInterface.java b/app/build/generated/aidl_source_output_dir/debug/out/com/safeluck/floatwindow/IMediaAidlInterface.java
index e24d126..5c6b6e0 100644
--- a/app/build/generated/aidl_source_output_dir/debug/out/com/safeluck/floatwindow/IMediaAidlInterface.java
+++ b/app/build/generated/aidl_source_output_dir/debug/out/com/safeluck/floatwindow/IMediaAidlInterface.java
@@ -1,6 +1,6 @@
 /*
  * This file is auto-generated.  DO NOT MODIFY.
- * Using: D:\Program\ Files\Android\Sdk\build-tools\35.0.0\aidl.exe -pD:\Program\ Files\Android\Sdk\platforms\android-35\framework.aidl -oD:\JetBrainsProjects\AndroidProject\anyunVideo\app\build\generated\aidl_source_output_dir\debug\out -ID:\JetBrainsProjects\AndroidProject\anyunVideo\app\src\main\aidl -ID:\JetBrainsProjects\AndroidProject\anyunVideo\app\src\debug\aidl -ID:\data\.gradle\caches\8.10.2\transforms\53a750d70626c759bd7a6dbaf50185ee\transformed\core-1.12.0\aidl -ID:\data\.gradle\caches\8.10.2\transforms\dc945394860d4e1c7d02ff0c8d3e2e6f\transformed\versionedparcelable-1.1.1\aidl -dC:\Users\Dana\AppData\Local\Temp\aidl14282392422309074909.d D:\JetBrainsProjects\AndroidProject\anyunVideo\app\src\main\aidl\com\safeluck\floatwindow\IMediaAidlInterface.aidl
+ * Using: D:\Program\ Files\Android\Sdk\build-tools\35.0.0\aidl.exe -pD:\Program\ Files\Android\Sdk\platforms\android-35\framework.aidl -oD:\JetBrainsProjects\AndroidProject\anyunVideo\app\build\generated\aidl_source_output_dir\debug\out -ID:\JetBrainsProjects\AndroidProject\anyunVideo\app\src\main\aidl -ID:\JetBrainsProjects\AndroidProject\anyunVideo\app\src\debug\aidl -ID:\data\.gradle\caches\8.10.2\transforms\53a750d70626c759bd7a6dbaf50185ee\transformed\core-1.12.0\aidl -ID:\data\.gradle\caches\8.10.2\transforms\dc945394860d4e1c7d02ff0c8d3e2e6f\transformed\versionedparcelable-1.1.1\aidl -dC:\Users\Dana\AppData\Local\Temp\aidl10441886692587460682.d D:\JetBrainsProjects\AndroidProject\anyunVideo\app\src\main\aidl\com\safeluck\floatwindow\IMediaAidlInterface.aidl
  */
 package com.safeluck.floatwindow;
 // Declare any non-default types here with import statements
diff --git a/app/build/generated/aidl_source_output_dir/debug/out/com/safeluck/floatwindow/IMyCallback.java b/app/build/generated/aidl_source_output_dir/debug/out/com/safeluck/floatwindow/IMyCallback.java
index db127f2..8b52912 100644
--- a/app/build/generated/aidl_source_output_dir/debug/out/com/safeluck/floatwindow/IMyCallback.java
+++ b/app/build/generated/aidl_source_output_dir/debug/out/com/safeluck/floatwindow/IMyCallback.java
@@ -1,6 +1,6 @@
 /*
  * This file is auto-generated.  DO NOT MODIFY.
- * Using: D:\Program\ Files\Android\Sdk\build-tools\35.0.0\aidl.exe -pD:\Program\ Files\Android\Sdk\platforms\android-35\framework.aidl -oD:\JetBrainsProjects\AndroidProject\anyunVideo\app\build\generated\aidl_source_output_dir\debug\out -ID:\JetBrainsProjects\AndroidProject\anyunVideo\app\src\main\aidl -ID:\JetBrainsProjects\AndroidProject\anyunVideo\app\src\debug\aidl -ID:\data\.gradle\caches\8.10.2\transforms\53a750d70626c759bd7a6dbaf50185ee\transformed\core-1.12.0\aidl -ID:\data\.gradle\caches\8.10.2\transforms\dc945394860d4e1c7d02ff0c8d3e2e6f\transformed\versionedparcelable-1.1.1\aidl -dC:\Users\Dana\AppData\Local\Temp\aidl6375257616930721574.d D:\JetBrainsProjects\AndroidProject\anyunVideo\app\src\main\aidl\com\safeluck\floatwindow\IMyCallback.aidl
+ * Using: D:\Program\ Files\Android\Sdk\build-tools\35.0.0\aidl.exe -pD:\Program\ Files\Android\Sdk\platforms\android-35\framework.aidl -oD:\JetBrainsProjects\AndroidProject\anyunVideo\app\build\generated\aidl_source_output_dir\debug\out -ID:\JetBrainsProjects\AndroidProject\anyunVideo\app\src\main\aidl -ID:\JetBrainsProjects\AndroidProject\anyunVideo\app\src\debug\aidl -ID:\data\.gradle\caches\8.10.2\transforms\53a750d70626c759bd7a6dbaf50185ee\transformed\core-1.12.0\aidl -ID:\data\.gradle\caches\8.10.2\transforms\dc945394860d4e1c7d02ff0c8d3e2e6f\transformed\versionedparcelable-1.1.1\aidl -dC:\Users\Dana\AppData\Local\Temp\aidl6260459078460591487.d D:\JetBrainsProjects\AndroidProject\anyunVideo\app\src\main\aidl\com\safeluck\floatwindow\IMyCallback.aidl
  */
 package com.safeluck.floatwindow;
 /**
diff --git a/app/build/intermediates/desugar_graph/debug/dexBuilderDebug/out/currentProject/dirs_bucket_9/graph.bin b/app/build/intermediates/desugar_graph/debug/dexBuilderDebug/out/currentProject/dirs_bucket_9/graph.bin
index 2f3be31..07e41e9 100644
--- a/app/build/intermediates/desugar_graph/debug/dexBuilderDebug/out/currentProject/dirs_bucket_9/graph.bin
+++ b/app/build/intermediates/desugar_graph/debug/dexBuilderDebug/out/currentProject/dirs_bucket_9/graph.bin
Binary files differ
diff --git a/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab b/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab
index bdf584a..a314e47 100644
--- a/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab
+++ b/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab
Binary files differ
diff --git a/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at b/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at
index 53b2d29..fc0e221 100644
--- a/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at
+++ b/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at
Binary files differ
diff --git a/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab b/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab
index bdf584a..c0e915b 100644
--- a/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab
+++ b/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab
Binary files differ
diff --git a/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at b/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at
index e9060a7..dac5c8e 100644
--- a/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at
+++ b/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at
Binary files differ
diff --git a/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab b/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab
index 1a1fdbf..7315934 100644
--- a/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab
+++ b/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab
Binary files differ
diff --git a/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab.values.at b/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab.values.at
index 1d49f50..960edd7 100644
--- a/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab.values.at
+++ b/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab.values.at
Binary files differ
diff --git a/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab b/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab
index bdf584a..255bbf4 100644
--- a/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab
+++ b/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab
Binary files differ
diff --git a/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.values.at b/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.values.at
index 1429ce6..5f42412 100644
--- a/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.values.at
+++ b/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.values.at
Binary files differ
diff --git a/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab b/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab
index bdf584a..0feea10 100644
--- a/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab
+++ b/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab
Binary files differ
diff --git a/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.values.at b/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.values.at
index 51508d6..043908f 100644
--- a/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.values.at
+++ b/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.values.at
Binary files differ
diff --git a/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/counters.tab b/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/counters.tab
index 26d3b09..4a12dea 100644
--- a/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/counters.tab
+++ b/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/counters.tab
@@ -1,2 +1,2 @@
-4
+5
 0
\ No newline at end of file
diff --git a/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab b/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab
index 2b3434a..f9463a0 100644
--- a/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab
+++ b/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab
Binary files differ
diff --git a/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.values.at b/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.values.at
index 3e23c2a..f6a4f17 100644
--- a/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.values.at
+++ b/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.values.at
Binary files differ
diff --git a/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab b/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab
index 4b0ca2c..f2aff74 100644
--- a/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab
+++ b/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab
Binary files differ
diff --git a/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream b/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream
index 6e7a926..1dd772c 100644
--- a/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream
+++ b/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream
Binary files differ
diff --git a/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream.len b/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream.len
index eb52963..62f3e6f 100644
--- a/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream.len
+++ b/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream.len
Binary files differ
diff --git a/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len b/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len
index 93a595b..ec8f944 100644
--- a/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len
+++ b/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len
Binary files differ
diff --git a/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.values.at b/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.values.at
index 42c4888..d073f36 100644
--- a/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.values.at
+++ b/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.values.at
Binary files differ
diff --git a/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i b/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i
index 6936967..e6ff6ac 100644
--- a/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i
+++ b/app/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i
Binary files differ
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index c7e748d..fbd24eb 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,10 +1,12 @@
 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools">
+    android:sharedUserId="android.uid.system"
+    xmlns:tools="http://schemas.android.com/tools"
+    >
 
     <uses-permission android:name="android.permission.CAMERA" />
     <uses-permission android:name="android.permission.RECORD_AUDIO" />
-
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
     <application
         android:allowBackup="true"
         android:name=".H264Application"
diff --git a/app/src/main/java/com/safeluck/floatwindow/MainActivity.kt b/app/src/main/java/com/safeluck/floatwindow/MainActivity.kt
index fe38740..5d7335d 100644
--- a/app/src/main/java/com/safeluck/floatwindow/MainActivity.kt
+++ b/app/src/main/java/com/safeluck/floatwindow/MainActivity.kt
@@ -1,47 +1,363 @@
 package com.safeluck.floatwindow
 
+import android.content.ComponentName
+import android.content.Context
+import android.content.Intent
+import android.content.ServiceConnection
 import android.os.Bundle
+import android.os.IBinder
+import android.os.RemoteException
 import androidx.activity.ComponentActivity
 import androidx.activity.compose.setContent
 import androidx.activity.enableEdgeToEdge
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.padding
-import androidx.compose.material3.Scaffold
-import androidx.compose.material3.Text
-import androidx.compose.runtime.Composable
+import androidx.compose.foundation.layout.*
+import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.verticalScroll
+import androidx.compose.material3.*
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.*
+import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
-import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
 import com.safeluck.floatwindow.ui.theme.AnyunVideoTheme
+import timber.log.Timber
 
 class MainActivity : ComponentActivity() {
+    private var mediaAidlInterface: IMediaAidlInterface? = null
+    private var serviceConnection: ServiceConnection? = null
+    private var isServiceBound = false
+    private val isServiceBoundState = mutableStateOf(false)
+    
+    private val callback = object : IMyCallback.Stub() {
+        @Throws(RemoteException::class)
+        override fun onResult(re: ResponseVO?) {
+            re?.let {
+                Timber.d("Callback received: type=${it.type}, errCode=${it.errCode}, message=${it.message}")
+            }
+        }
+    }
+    
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
         enableEdgeToEdge()
+        
+        serviceConnection = object : ServiceConnection {
+            override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
+                mediaAidlInterface = IMediaAidlInterface.Stub.asInterface(service)
+                isServiceBound = true
+                isServiceBoundState.value = true
+                Timber.d("FloatingService connected")
+            }
+            
+            override fun onServiceDisconnected(name: ComponentName?) {
+                mediaAidlInterface = null
+                isServiceBound = false
+                isServiceBoundState.value = false
+                Timber.d("FloatingService disconnected")
+            }
+        }
+        
         setContent {
             AnyunVideoTheme {
-                Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
-                    Greeting(
-                        name = "Android",
-                        modifier = Modifier.padding(innerPadding)
+                Surface(
+                    modifier = Modifier.fillMaxSize(),
+                    color = MaterialTheme.colorScheme.background
+                ) {
+                    MainScreen(
+                        isServiceBound = isServiceBoundState.value,
+                        onBindService = { 
+                            if (!isServiceBoundState.value && serviceConnection != null) {
+                                val intent = Intent(this@MainActivity, FloatingService::class.java)
+                                bindService(intent, serviceConnection!!, Context.BIND_AUTO_CREATE)
+                                Timber.d("Binding FloatingService")
+                            }
+                        },
+                        onUnbindService = { 
+                            unbindServiceInternal()
+                        },
+                        onStartAndroidRecord = { startAndroidRecord() },
+                        onStopAndroidRecord = { stopAndroidRecord() },
+                        onStartUsbRecord = { startUsbRecord() },
+                        onStopUsbRecord = { stopUsbRecord() },
+                        onStartUsbPush = { startUsbPush() },
+                        onStopUsbPush = { stopUsbPush() }
                     )
                 }
             }
         }
     }
-}
-
-@Composable
-fun Greeting(name: String, modifier: Modifier = Modifier) {
-    Text(
-        text = "Hello $name!",
-        modifier = modifier
-    )
-}
-
-@Preview(showBackground = true)
-@Composable
-fun GreetingPreview() {
-    AnyunVideoTheme {
-        Greeting("Android")
+    
+    private fun startAndroidRecord() {
+        if (mediaAidlInterface == null) {
+            Timber.w("Service not bound, cannot start Android record")
+            return
+        }
+        
+        try {
+            val mediaArgu = MediaArgu().apply {
+                isPush = false
+                isUsedOutCamera = false // Android 鍐呯疆鎽勫儚澶�
+                codeRate = 0
+                frameRate = 0
+                m_screen = MediaArgu.ScreenSolution(640, 480) // 榛樿鍒嗚鲸鐜�
+                recordTime = 0
+                tfCardFlag = 0 // 鍐呴儴瀛樺偍
+            }
+            
+            mediaAidlInterface?.registerCallback(callback)
+            mediaAidlInterface?.startMedia(mediaArgu)
+            Timber.d("Started Android camera record")
+        } catch (e: RemoteException) {
+            Timber.e(e, "Error starting Android record")
+        }
     }
-}
\ No newline at end of file
+    
+    private fun stopAndroidRecord() {
+        if (mediaAidlInterface == null) {
+            Timber.w("Service not bound, cannot stop Android record")
+            return
+        }
+        
+        try {
+            mediaAidlInterface?.stopMedia()
+            Timber.d("Stopped Android camera record")
+        } catch (e: RemoteException) {
+            Timber.e(e, "Error stopping Android record")
+        }
+    }
+    
+    private fun startUsbRecord() {
+        if (mediaAidlInterface == null) {
+            Timber.w("Service not bound, cannot start USB record")
+            return
+        }
+        
+        try {
+            val mediaArgu = MediaArgu().apply {
+                isPush = false
+                isUsedOutCamera = true // USB 鎽勫儚澶�
+                codeRate = 0
+                frameRate = 0
+                m_screen = MediaArgu.ScreenSolution(640, 480) // 榛樿鍒嗚鲸鐜�
+                recordTime = 0
+                tfCardFlag = 0 // 鍐呴儴瀛樺偍
+            }
+            
+            mediaAidlInterface?.registerCallback(callback)
+            mediaAidlInterface?.startMedia(mediaArgu)
+            Timber.d("Started USB camera record")
+        } catch (e: RemoteException) {
+            Timber.e(e, "Error starting USB record")
+        }
+    }
+    
+    private fun stopUsbRecord() {
+        if (mediaAidlInterface == null) {
+            Timber.w("Service not bound, cannot stop USB record")
+            return
+        }
+        
+        try {
+            mediaAidlInterface?.stopMedia()
+            Timber.d("Stopped USB camera record")
+        } catch (e: RemoteException) {
+            Timber.e(e, "Error stopping USB record")
+        }
+    }
+    
+    private fun startUsbPush() {
+        if (mediaAidlInterface == null) {
+            Timber.w("Service not bound, cannot start USB push")
+            return
+        }
+        
+        try {
+            val mediaArgu = MediaArgu().apply {
+                isPush = true
+                isUsedOutCamera = true // USB 鎽勫儚澶�
+                codeRate = 0
+                frameRate = 0
+                m_screen = MediaArgu.ScreenSolution(640, 480) // 榛樿鍒嗚鲸鐜�
+                url = "rtmp://your-push-url" // TODO: 闇�瑕佽缃疄闄呯殑鎺ㄦ祦鍦板潃
+                userName = ""
+                pwd = ""
+            }
+            
+            mediaAidlInterface?.registerCallback(callback)
+            mediaAidlInterface?.startMedia(mediaArgu)
+            Timber.d("Started USB camera push")
+        } catch (e: RemoteException) {
+            Timber.e(e, "Error starting USB push")
+        }
+    }
+    
+    private fun stopUsbPush() {
+        if (mediaAidlInterface == null) {
+            Timber.w("Service not bound, cannot stop USB push")
+            return
+        }
+        
+        try {
+            mediaAidlInterface?.stopMedia()
+            Timber.d("Stopped USB camera push")
+        } catch (e: RemoteException) {
+            Timber.e(e, "Error stopping USB push")
+        }
+    }
+    
+    private fun unbindServiceInternal() {
+        if (isServiceBound && serviceConnection != null) {
+            try {
+                mediaAidlInterface?.unregisterCallback(callback)
+            } catch (e: RemoteException) {
+                Timber.e(e, "Error unregistering callback")
+            }
+            try {
+                unbindService(serviceConnection!!)
+                Timber.d("Unbinding FloatingService")
+            } catch (e: Exception) {
+                Timber.e(e, "Error unbinding service")
+            }
+            isServiceBound = false
+            isServiceBoundState.value = false
+            mediaAidlInterface = null
+        }
+    }
+    
+    override fun onDestroy() {
+        super.onDestroy()
+        unbindServiceInternal()
+    }
+}
+
+@Composable
+fun MainScreen(
+    isServiceBound: Boolean,
+    onBindService: () -> Unit,
+    onUnbindService: () -> Unit,
+    onStartAndroidRecord: () -> Unit,
+    onStopAndroidRecord: () -> Unit,
+    onStartUsbRecord: () -> Unit,
+    onStopUsbRecord: () -> Unit,
+    onStartUsbPush: () -> Unit,
+    onStopUsbPush: () -> Unit
+) {
+    Column(
+        modifier = Modifier.fillMaxSize()
+    ) {
+        // 鍥哄畾椤堕儴锛氭爣棰樺拰鐘舵��
+        Column(
+            modifier = Modifier
+                .fillMaxWidth()
+                .padding(16.dp),
+            horizontalAlignment = Alignment.CenterHorizontally
+        ) {
+            Text(
+                text = "FloatingService 鎺у埗",
+                style = MaterialTheme.typography.headlineMedium,
+                modifier = Modifier.padding(bottom = 8.dp)
+            )
+            
+            Text(
+                text = if (isServiceBound) "鏈嶅姟鐘舵��: 宸茬粦瀹�" else "鏈嶅姟鐘舵��: 鏈粦瀹�",
+                style = MaterialTheme.typography.bodyMedium,
+                color = if (isServiceBound) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.error,
+                modifier = Modifier.padding(bottom = 16.dp)
+            )
+        }
+        
+        Divider()
+        
+        // 鍙粴鍔ㄧ殑鎸夐挳鍒楄〃
+        Column(
+            modifier = Modifier
+                .fillMaxSize()
+                .verticalScroll(rememberScrollState())
+                .padding(horizontal = 16.dp),
+            horizontalAlignment = Alignment.CenterHorizontally,
+            verticalArrangement = Arrangement.spacedBy(12.dp)
+        ) {
+            Spacer(modifier = Modifier.height(12.dp))
+            
+            // 鎸夐挳 1: 缁戝畾鏈嶅姟
+            Button(
+                onClick = onBindService,
+                modifier = Modifier.fillMaxWidth(),
+                enabled = !isServiceBound
+            ) {
+                Text("1. 缁戝畾 FloatingService")
+            }
+            
+            // 鎸夐挳 2: 瑙g粦鏈嶅姟
+            Button(
+                onClick = onUnbindService,
+                modifier = Modifier.fillMaxWidth(),
+                enabled = isServiceBound
+            ) {
+                Text("2. 瑙g粦 FloatingService")
+            }
+            
+            Divider(modifier = Modifier.padding(vertical = 8.dp))
+            
+            // 鎸夐挳 3: 寮�濮� Android 鐩告満褰曞儚
+            Button(
+                onClick = onStartAndroidRecord,
+                modifier = Modifier.fillMaxWidth(),
+                enabled = isServiceBound
+            ) {
+                Text("3. 寮�濮� Android 鐩告満褰曞儚")
+            }
+            
+            // 鎸夐挳 4: 缁撴潫 Android 鐩告満褰曞儚
+            Button(
+                onClick = onStopAndroidRecord,
+                modifier = Modifier.fillMaxWidth(),
+                enabled = isServiceBound
+            ) {
+                Text("4. 缁撴潫 Android 鐩告満褰曞儚")
+            }
+            
+            Divider(modifier = Modifier.padding(vertical = 8.dp))
+            
+            // 鎸夐挳 5: 寮�濮� USB 鐩告満褰曞儚
+            Button(
+                onClick = onStartUsbRecord,
+                modifier = Modifier.fillMaxWidth(),
+                enabled = isServiceBound
+            ) {
+                Text("5. 寮�濮� USB 鐩告満褰曞儚")
+            }
+            
+            // 鎸夐挳 6: 缁撴潫 USB 鐩告満褰曞儚
+            Button(
+                onClick = onStopUsbRecord,
+                modifier = Modifier.fillMaxWidth(),
+                enabled = isServiceBound
+            ) {
+                Text("6. 缁撴潫 USB 鐩告満褰曞儚")
+            }
+            
+            Divider(modifier = Modifier.padding(vertical = 8.dp))
+            
+            // 鎸夐挳 7: 寮�濮� USB 鎺ㄦ祦
+            Button(
+                onClick = onStartUsbPush,
+                modifier = Modifier.fillMaxWidth(),
+                enabled = isServiceBound
+            ) {
+                Text("7. 寮�濮� USB 鎺ㄦ祦")
+            }
+            
+            // 鎸夐挳 8: 缁撴潫 USB 鎺ㄦ祦
+            Button(
+                onClick = onStopUsbPush,
+                modifier = Modifier.fillMaxWidth(),
+                enabled = isServiceBound
+            ) {
+                Text("8. 缁撴潫 USB 鎺ㄦ祦")
+            }
+            
+            Spacer(modifier = Modifier.height(12.dp))
+        }
+    }
+}
diff --git a/app/src/main/java/com/safeluck/floatwindow/MediaArgu.java b/app/src/main/java/com/safeluck/floatwindow/MediaArgu.java
index 4d8ebb1..dff6790 100644
--- a/app/src/main/java/com/safeluck/floatwindow/MediaArgu.java
+++ b/app/src/main/java/com/safeluck/floatwindow/MediaArgu.java
@@ -107,6 +107,7 @@
         this.pwd = pwd;
     }
 
+
   public  static class ScreenSolution implements Parcelable {
         int width;
         int height;
diff --git a/app/src/main/java/com/safeluck/floatwindow/manager/AndroidCameraRecordManager.java b/app/src/main/java/com/safeluck/floatwindow/manager/AndroidCameraRecordManager.java
index 98f6fc6..a625b59 100644
--- a/app/src/main/java/com/safeluck/floatwindow/manager/AndroidCameraRecordManager.java
+++ b/app/src/main/java/com/safeluck/floatwindow/manager/AndroidCameraRecordManager.java
@@ -186,15 +186,31 @@
             }
             
             // 璁剧疆MediaRecorder
+            // 娉ㄦ剰锛歁ediaRecorder鐨勮缃『搴忛潪甯搁噸瑕侊紝蹇呴』涓ユ牸鎸夌収浠ヤ笅椤哄簭锛�
             mediaRecorder = new MediaRecorder();
+            
+            // 1. 璁剧疆鏁版嵁婧愶紙蹇呴』鍦╯etOutputFormat涔嬪墠锛�
+            mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
             mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
+            
+            // 2. 璁剧疆杈撳嚭鏍煎紡锛堝繀椤诲湪setOutputFile鍜岀紪鐮佸櫒涔嬪墠锛�
             mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
+            
+            // 3. 璁剧疆杈撳嚭鏂囦欢锛堝繀椤诲湪缂栫爜鍣ㄤ箣鍓嶏級
             mediaRecorder.setOutputFile(currentVideoFile.getAbsolutePath());
+            
+            // 4. 璁剧疆缂栫爜鍣紙蹇呴』鍦╯etOutputFormat涔嬪悗锛�
+            mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
+            mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
+            
+            // 5. 璁剧疆缂栫爜鍙傛暟锛堝繀椤诲湪缂栫爜鍣ㄤ箣鍚庯級
+            mediaRecorder.setAudioEncodingBitRate(64000); // 64kbps
+            mediaRecorder.setAudioSamplingRate(44100); // 44.1kHz
             mediaRecorder.setVideoEncodingBitRate(width * height * 3);
             mediaRecorder.setVideoFrameRate(20);
             mediaRecorder.setVideoSize(width, height);
-            mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
             
+            // 6. 鍑嗗MediaRecorder
             mediaRecorder.prepare();
             
             // 鍒涘缓Surface
diff --git a/app/src/main/java/com/safeluck/floatwindow/manager/UsbCameraRecordManager.java b/app/src/main/java/com/safeluck/floatwindow/manager/UsbCameraRecordManager.java
index d136622..1047097 100644
--- a/app/src/main/java/com/safeluck/floatwindow/manager/UsbCameraRecordManager.java
+++ b/app/src/main/java/com/safeluck/floatwindow/manager/UsbCameraRecordManager.java
@@ -70,6 +70,9 @@
     private File currentVideoFile;
     private long currentFileStartTime;
     
+    // 褰曞埗寮�濮嬫椂闂达紙绾崇锛夛紝鐢ㄤ簬鏃堕棿鎴冲悓姝�
+    private volatile long recordingStartTimeNs = 0;
+    
     /**
      * 褰曞儚鍥炶皟鎺ュ彛
      */
@@ -165,7 +168,7 @@
             usbCamera.setenv();
 
             // 浣跨敤prepareCamera鏂规硶锛宑amera_id鑼冨洿[0,9]
-            int[] cameraIds = {0, 9};
+            int[] cameraIds = {0, 2};
             String cameraName = null; // 涓嶆寚瀹氱壒瀹氬悕绉�
 
             // 濡傛灉杩斿洖闈�0锛屼唬琛ㄦ墦寮�澶辫触锛屽垯鍏坰topCamera鍐嶉噸璇曪紝鏈�澶�3娆�
@@ -366,12 +369,18 @@
                     Timber.d("闊抽褰曞埗宸插惎鍔�");
                 }
                 
+                // 娉ㄦ剰锛氫笉瑕佸湪杩欓噷涓诲姩妫�鏌ラ煶棰戠紪鐮佸櫒杈撳嚭鏍煎紡
+                // 鍥犱负 MediaCodec 鐨� getOutputFormat() 鍦ㄧ紪鐮佸櫒鍚姩鍚庡彲鑳借繑鍥� null
+                // 搴旇绛夊緟 INFO_OUTPUT_FORMAT_CHANGED 浜嬩欢
+                
                 // 鍚姩闊抽缂栫爜绾跨▼
                 audioThread = new AudioThread();
                 audioThread.start();
                 
                 Timber.d("寮�濮嬪綍鍍忥紝鍒嗚鲸鐜�: %dx%d", width, height);
                 
+                // 璁板綍寮�濮嬫椂闂达紙绾崇锛岀敤浜庣簿纭椂闂存埑锛�
+                recordingStartTimeNs = System.nanoTime();
                 long frameCount = 0;
                 long lastFileChangeTime = System.currentTimeMillis();
                 
@@ -400,6 +409,9 @@
                             break;
                         }
                         
+                        // 閲嶇疆寮�濮嬫椂闂�
+                        recordingStartTimeNs = System.nanoTime();
+                        
                         // 閲嶆柊鍚姩闊抽褰曞埗
                         if (audioRecord != null) {
                             audioRecord.startRecording();
@@ -426,11 +438,13 @@
                     }
                     
                     // 鑾峰彇YUV鏁版嵁 (鍙傛暟0琛ㄧず褰曞儚)
-                    usbCamera.rgba(0, buffer);
+                    usbCamera.rgba(2, buffer);
                     
                     // 缂栫爜骞跺啓鍏ユ枃浠�
                     if (videoEncoder != null && mediaMuxer != null) {
-                        encodeFrame(buffer, frameCount, width, height);
+                        // 璁$畻瀹為檯缁忚繃鐨勬椂闂达紙寰锛�
+                        long elapsedTimeUs = (System.nanoTime() - recordingStartTimeNs) / 1000;
+                        encodeFrame(buffer, elapsedTimeUs, width, height);
                         frameCount++;
                     }
                     
@@ -461,8 +475,12 @@
         
         /**
          * 缂栫爜涓�甯ф暟鎹�
+         * @param yuvData YUV鏁版嵁
+         * @param presentationTimeUs 鏃堕棿鎴筹紙寰锛夛紝鍩轰簬瀹為檯寮�濮嬫椂闂�
+         * @param width 瀹藉害
+         * @param height 楂樺害
          */
-        private void encodeFrame(byte[] yuvData, long frameIndex, int width, int height) {
+        private void encodeFrame(byte[] yuvData, long presentationTimeUs, int width, int height) {
             try {
                 // 鑾峰彇杈撳叆缂撳啿鍖�
                 int inputBufferIndex = videoEncoder.dequeueInputBuffer(10000);
@@ -472,7 +490,7 @@
                         inputBuffer.clear();
                         inputBuffer.put(yuvData);
                         
-                        long presentationTimeUs = (frameIndex * 1000000) / FRAME_RATE;
+                        // 浣跨敤瀹為檯缁忚繃鐨勬椂闂翠綔涓烘椂闂存埑
                         videoEncoder.queueInputBuffer(inputBufferIndex, 0, yuvData.length, 
                                 presentationTimeUs, 0);
                     }
@@ -482,18 +500,35 @@
                 MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
                 int outputBufferIndex = videoEncoder.dequeueOutputBuffer(bufferInfo, 0);
                 
-                while (outputBufferIndex >= 0) {
+                while (outputBufferIndex != MediaCodec.INFO_TRY_AGAIN_LATER) {
                     if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
                         // 杈撳嚭鏍煎紡鏀瑰彉锛屾坊鍔犺棰戣建閬�
                         MediaFormat newFormat = videoEncoder.getOutputFormat();
-                        videoTrackIndex = mediaMuxer.addTrack(newFormat);
-                        checkAndStartMuxer();
+                        synchronized (UsbCameraRecordManager.this) {
+                            // 妫�鏌� muxer 鏄惁宸插惎鍔紝濡傛灉宸插惎鍔ㄥ垯鏃犳硶娣诲姞杞ㄩ亾
+                            if (muxerStarted) {
+                                Timber.e("Muxer already started, cannot add video track");
+                                break;
+                            }
+                            if (videoTrackIndex < 0) {
+                                videoTrackIndex = mediaMuxer.addTrack(newFormat);
+                                Timber.d("瑙嗛杞ㄩ亾宸叉坊鍔�: %d", videoTrackIndex);
+                                checkAndStartMuxer();
+                            }
+                        }
+                        outputBufferIndex = videoEncoder.dequeueOutputBuffer(bufferInfo, 0);
+                        continue;
                     } else if (outputBufferIndex >= 0) {
                         ByteBuffer outputBuffer = videoEncoder.getOutputBuffer(outputBufferIndex);
+                        // 鍙湁鍦� muxer 宸插惎鍔ㄤ笖杞ㄩ亾绱㈠紩鏈夋晥鏃舵墠鍐欏叆鏁版嵁
                         if (outputBuffer != null && muxerStarted && videoTrackIndex >= 0) {
                             outputBuffer.position(bufferInfo.offset);
                             outputBuffer.limit(bufferInfo.offset + bufferInfo.size);
-                            mediaMuxer.writeSampleData(videoTrackIndex, outputBuffer, bufferInfo);
+                            try {
+                                mediaMuxer.writeSampleData(videoTrackIndex, outputBuffer, bufferInfo);
+                            } catch (Exception e) {
+                                Timber.e(e, "Error writing video sample data");
+                            }
                         }
                         videoEncoder.releaseOutputBuffer(outputBufferIndex, false);
                     }
@@ -512,9 +547,15 @@
      */
     private synchronized void checkAndStartMuxer() {
         if (!muxerStarted && videoTrackIndex >= 0 && audioTrackIndex >= 0) {
-            mediaMuxer.start();
-            muxerStarted = true;
+            try {
+                mediaMuxer.start();
+                muxerStarted = true;
                 Timber.d("Muxer started, video track: %d, audio track: %d", videoTrackIndex, audioTrackIndex);
+            } catch (Exception e) {
+                Timber.e(e, "Failed to start muxer");
+            }
+        } else {
+            Timber.d("Muxer not started yet, video track: %d, audio track: %d", videoTrackIndex, audioTrackIndex);
         }
     }
     
@@ -535,7 +576,7 @@
             
             try {
                 byte[] audioBuffer = new byte[audioBufferSize];
-                long audioFrameCount = 0;
+                long totalSamplesRead = 0; // 鎬婚噰鏍锋暟
                 
                 while (isRecording && audioRecord != null && audioEncoder != null) {
                     // 璇诲彇闊抽鏁版嵁
@@ -546,8 +587,8 @@
                     }
                     
                     // 缂栫爜闊抽鏁版嵁
-                    encodeAudio(audioBuffer, readSize, audioFrameCount);
-                    audioFrameCount += readSize / 2; // 16浣嶉噰鏍凤紝姣忎釜閲囨牱2瀛楄妭
+                    encodeAudio(audioBuffer, readSize, totalSamplesRead);
+                    totalSamplesRead += readSize / 2; // 16浣嶉噰鏍凤紝姣忎釜閲囨牱2瀛楄妭
                 }
                 
             } catch (Exception e) {
@@ -559,10 +600,13 @@
         
         /**
          * 缂栫爜闊抽鏁版嵁
+         * @param audioData 闊抽鏁版嵁
+         * @param size 鏁版嵁澶у皬锛堝瓧鑺傦級
+         * @param totalSamples 鎬婚噰鏍锋暟锛堜粠寮�濮嬪埌鐜板湪鐨勭疮璁¢噰鏍锋暟锛�
          */
-        private void encodeAudio(byte[] audioData, int size, long frameCount) {
+        private void encodeAudio(byte[] audioData, int size, long totalSamples) {
             try {
-                // 鑾峰彇杈撳叆缂撳啿鍖�
+                // 鑾峰彇杈撳叆缂撳啿鍖猴紙鍗充娇 muxer 鏈惎鍔ㄤ篃瑕佺紪鐮侊紝浠ヤ究灏藉揩鑾峰緱杈撳嚭鏍煎紡锛�
                 int inputBufferIndex = audioEncoder.dequeueInputBuffer(10000);
                 if (inputBufferIndex >= 0) {
                     ByteBuffer inputBuffer = audioEncoder.getInputBuffer(inputBufferIndex);
@@ -570,7 +614,9 @@
                         inputBuffer.clear();
                         inputBuffer.put(audioData, 0, size);
                         
-                        long presentationTimeUs = (frameCount * 1000000) / SAMPLE_RATE;
+                        // 浣跨敤閲囨牱鏁拌绠楁椂闂存埑锛堝井绉掞級
+                        // totalSamples 鏄噰鏍锋暟锛孲AMPLE_RATE 鏄瘡绉掗噰鏍锋暟
+                        long presentationTimeUs = (totalSamples * 1000000) / SAMPLE_RATE;
                         audioEncoder.queueInputBuffer(inputBufferIndex, 0, size, 
                                 presentationTimeUs, 0);
                     }
@@ -580,18 +626,35 @@
                 MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
                 int outputBufferIndex = audioEncoder.dequeueOutputBuffer(bufferInfo, 0);
                 
-                while (outputBufferIndex >= 0) {
+                while (outputBufferIndex != MediaCodec.INFO_TRY_AGAIN_LATER) {
                     if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
                         // 杈撳嚭鏍煎紡鏀瑰彉锛屾坊鍔犻煶棰戣建閬�
                         MediaFormat newFormat = audioEncoder.getOutputFormat();
-                        audioTrackIndex = mediaMuxer.addTrack(newFormat);
-                        checkAndStartMuxer();
+                        synchronized (UsbCameraRecordManager.this) {
+                            // 妫�鏌� muxer 鏄惁宸插惎鍔紝濡傛灉宸插惎鍔ㄥ垯鏃犳硶娣诲姞杞ㄩ亾
+                            if (muxerStarted) {
+                                Timber.e("Muxer already started, cannot add audio track");
+                                break;
+                            }
+                            if (audioTrackIndex < 0) {
+                                audioTrackIndex = mediaMuxer.addTrack(newFormat);
+                                Timber.d("闊抽杞ㄩ亾宸叉坊鍔�: %d", audioTrackIndex);
+                                checkAndStartMuxer();
+                            }
+                        }
+                        outputBufferIndex = audioEncoder.dequeueOutputBuffer(bufferInfo, 0);
+                        continue;
                     } else if (outputBufferIndex >= 0) {
                         ByteBuffer outputBuffer = audioEncoder.getOutputBuffer(outputBufferIndex);
+                        // 鍙湁鍦� muxer 宸插惎鍔ㄤ笖杞ㄩ亾绱㈠紩鏈夋晥鏃舵墠鍐欏叆鏁版嵁
                         if (outputBuffer != null && muxerStarted && audioTrackIndex >= 0) {
                             outputBuffer.position(bufferInfo.offset);
                             outputBuffer.limit(bufferInfo.offset + bufferInfo.size);
-                            mediaMuxer.writeSampleData(audioTrackIndex, outputBuffer, bufferInfo);
+                            try {
+                                mediaMuxer.writeSampleData(audioTrackIndex, outputBuffer, bufferInfo);
+                            } catch (Exception e) {
+                                Timber.e(e, "Error writing audio sample data");
+                            }
                         }
                         audioEncoder.releaseOutputBuffer(outputBufferIndex, false);
                     }
diff --git a/app/src/main/java/com/safeluck/floatwindow/util/VideoFileUtils.java b/app/src/main/java/com/safeluck/floatwindow/util/VideoFileUtils.java
index c51d1d3..d9b0128 100644
--- a/app/src/main/java/com/safeluck/floatwindow/util/VideoFileUtils.java
+++ b/app/src/main/java/com/safeluck/floatwindow/util/VideoFileUtils.java
@@ -1,6 +1,7 @@
 package com.safeluck.floatwindow.util;
 
 import android.content.Context;
+import android.os.Environment;
 
 import timber.log.Timber;
 
@@ -36,7 +37,7 @@
             baseDir = new File(storagePath);
         } else {
             // 鍐呴儴瀛樺偍
-            baseDir = context.getFilesDir();
+            baseDir = Environment.getExternalStorageDirectory();
         }
         
         // 鍒涘缓 AnYun_VIDEO 鐩綍
diff --git a/key/Verify.txt b/key/Verify.txt
new file mode 100644
index 0000000..f819a2e
--- /dev/null
+++ b/key/Verify.txt
@@ -0,0 +1,41 @@
+	private static PrivateKey getKey(String key, char[] password) throws Exception {
+		byte[] cabuf = new BASE64Decoder().decodeBuffer(key);
+		KeyStore keyStore = KeyStore.getInstance("PKCS12");
+		keyStore.load(new ByteArrayInputStream(cabuf), password);
+		Enumeration<String> aliases = keyStore.aliases();
+		if (!aliases.hasMoreElements()) {
+			throw new RuntimeException("no alias found");
+		}
+		String alias = aliases.nextElement();
+		PrivateKey privateKey = (RSAPrivateCrtKeyImpl) keyStore.getKey(alias, password);
+		return privateKey;
+	}
+
+	public static String sign(String data, PrivateKey key) throws Exception {
+//		MessageDigest md = MessageDigest.getInstance("SHA-256");
+		MessageDigest md = MessageDigest.getInstance("SHA-1");
+		md.update(data.getBytes("utf-8"));
+		byte[] hash = md.digest();
+//		Cipher cipher = Cipher.getInstance("RSA");
+		Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
+		cipher.init(Cipher.ENCRYPT_MODE, key);
+		byte[] encrypted = cipher.doFinal(hash);
+		return HexBin.encode(encrypted);
+	}
+
+
+	public static String sign(String data, String keyString ,String pwd ) throws Exception {
+		char[] password = pwd.toCharArray();
+
+		return sign(data,getKey(keyString,password));
+	}
+
+
+	public static void main(String[] args) {
+		try{
+			String sign = sign("xuanborobot123456nullnullnull","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","27U777");
+			System.out.println(sign);
+		}catch (Exception e){
+			e.printStackTrace();
+		}
+	}
\ No newline at end of file
diff --git a/key/bjkey.jks b/key/bjkey.jks
new file mode 100644
index 0000000..35abed1
--- /dev/null
+++ b/key/bjkey.jks
Binary files differ
diff --git a/key/key.jks b/key/key.jks
new file mode 100644
index 0000000..7b43d77
--- /dev/null
+++ b/key/key.jks
Binary files differ
diff --git a/key/key.jks.ori b/key/key.jks.ori
new file mode 100644
index 0000000..3908383
--- /dev/null
+++ b/key/key.jks.ori
Binary files differ
diff --git a/key/keyrk3288.jks b/key/keyrk3288.jks
new file mode 100644
index 0000000..2f65bee
--- /dev/null
+++ b/key/keyrk3288.jks
Binary files differ
diff --git a/key/keysc200.jks b/key/keysc200.jks
new file mode 100644
index 0000000..9fd3690
--- /dev/null
+++ b/key/keysc200.jks
Binary files differ
diff --git a/key/keysc626.jks b/key/keysc626.jks
new file mode 100644
index 0000000..bb729ce
--- /dev/null
+++ b/key/keysc626.jks
Binary files differ
diff --git a/keystore.properties b/keystore.properties
new file mode 100644
index 0000000..4504553
--- /dev/null
+++ b/keystore.properties
@@ -0,0 +1,4 @@
+storePassword = 123456
+keyPassword = 123456
+keyAlias = key0
+storeFile = ../key/key.jks
\ No newline at end of file
diff --git a/usbcameralib/build.gradle b/usbcameralib/build.gradle
index 78d2812..0afac34 100644
--- a/usbcameralib/build.gradle
+++ b/usbcameralib/build.gradle
@@ -16,6 +16,8 @@
             cmake {
                 arguments "-DANDROID_ARM_NEON=TRUE"
                 cppFlags ""
+                // 纭繚浣跨敤 c++_shared STL
+                arguments "-DANDROID_STL=c++_shared"
             }
         }
         ndk {
@@ -43,7 +45,9 @@
         pickFirst 'lib/armeabi-v7a/libturbojpeg.so'
         pickFirst 'lib/arm64-v8a/libjpeg.so'
         pickFirst 'lib/arm64-v8a/libturbojpeg.so'
-
+        // 纭繚 libc++_shared.so 琚寘鍚�
+        pickFirst 'lib/armeabi-v7a/libc++_shared.so'
+        pickFirst 'lib/arm64-v8a/libc++_shared.so'
     }
 
 }

--
Gitblit v1.8.0