From f5e45186eb4daedc7c33216766637d0dcbd1ebcf Mon Sep 17 00:00:00 2001
From: Dana <Dana_Lee1016@126.com>
Date: 星期三, 28 一月 2026 11:32:31 +0800
Subject: [PATCH] 1.readme

---
 readMe.md |  375 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 375 insertions(+), 0 deletions(-)

diff --git a/readMe.md b/readMe.md
new file mode 100644
index 0000000..228bde0
--- /dev/null
+++ b/readMe.md
@@ -0,0 +1,375 @@
+* MediaMuxer 鍚姩鍚庝笉鑳藉啀娣诲姞杞ㄩ亾
+
+* 瑙嗛鍜岄煶棰戠殑鏃堕棿鎴抽渶瑕佹纭悓姝�
+
+
+鐜板湪浠g爜搴旇锛�
+
+* 姝g‘绛夊緟涓や釜杞ㄩ亾閮藉噯澶囧ソ
+
+* 鍚屾鍚姩 MediaMuxer
+
+* 姝g‘鍐欏叆瑙嗛鍜岄煶棰戞暟鎹�
+
+* 閬垮厤鐘舵�佸啿绐佸鑷寸殑閿欒
+
+
+mp4鏂囦欢鏄庢樉鏃堕棿鍔犲揩浜嗭紝鐜板疄涓栫晫1绉掗挓锛屽彲鑳絤p4鏂囦欢鐨勮棰戝氨鏄崐绉掞紝鎵�鏈夊綍涓�鍒嗛挓鐨勮棰憁p4鏂囦欢锛岃棰戝彧鎾埌30绉掑氨涓嶅啀鎾簡
+
+妫�鏌ュ苟淇鏃堕棿鎴宠绠楅棶棰橈紝鍙兘鏄抚鐜囨垨鏃堕棿鎴宠绠椾笉姝g‘锛�
+
+淇鏃堕棿鎴宠绠楋細鏀圭敤瀹為檯鏃堕棿鑰岄潪甯х储寮曪紝纭繚鏃堕棿鎴冲噯纭細
+
+淇鏃堕棿鎴宠绠楋紝浣跨敤瀹為檯鏃堕棿鑰岄潪甯х储寮曪細
+
+UsbCameraRecordManager.java
+
+long聽frameCount聽=聽0;
+
+//聽璁板綍寮�濮嬫椂闂达紙绾崇锛岀敤浜庣簿纭椂闂存埑锛�
+
+long聽recordingStartTimeNs聽=聽System.nanoTime();
+
+long聽frameCount聽=聽0;
+
+UsbCameraRecordManager.java
+
+if聽(videoEncoder聽!=聽null聽&&聽mediaMuxer聽!=聽null)聽{
+
+encodeFrame(buffer,聽frameCount,聽width,聽height);
+
+frameCount++;
+
+encodeFrame(buffer,聽frameCount,聽width,聽height);
+
+if聽(videoEncoder聽!=聽null聽&&聽mediaMuxer聽!=聽null)聽{
+
+//聽璁$畻瀹為檯缁忚繃鐨勬椂闂达紙寰锛�
+
+long聽elapsedTimeUs聽=聽(System.nanoTime()聽-聽recordingStartTimeNs)聽/聽1000;
+
+encodeFrame(buffer,聽elapsedTimeUs,聽width,聽height);
+
+frameCount++;
+
+UsbCameraRecordManager.java
+
+*聽缂栫爜涓�甯ф暟鎹�
+
+*/
+
+*聽缂栫爜涓�甯ф暟鎹�
+
+*聽@param聽yuvData聽YUV鏁版嵁
+
+*聽@param聽presentationTimeUs聽鏃堕棿鎴筹紙寰锛夛紝鍩轰簬瀹為檯寮�濮嬫椂闂�
+
+*聽@param聽width聽瀹藉害
+
+*聽@param聽height聽楂樺害
+
+*/
+
+淇闊抽鏃堕棿鎴筹紝浣垮叾涓庤棰戞椂闂存埑鍚屾锛�
+
+UsbCameraRecordManager.java
+
++3
+
+/**
+
+//聽褰曞埗寮�濮嬫椂闂达紙绾崇锛夛紝鐢ㄤ簬鏃堕棿鎴冲悓姝�
+
+private聽volatile聽long聽recordingStartTimeNs聽=聽0;
+
+/**
+
+UsbCameraRecordManager.java
+
++1-1
+
+//聽璁板綍寮�濮嬫椂闂达紙绾崇锛岀敤浜庣簿纭椂闂存埑锛�
+
+long聽recordingStartTimeNs聽=聽System.nanoTime();
+
+long聽frameCount聽=聽0;
+
+long聽recordingStartTimeNs聽=聽System.nanoTime();
+
+//聽璁板綍寮�濮嬫椂闂达紙绾崇锛岀敤浜庣簿纭椂闂存埑锛�
+
+recordingStartTimeNs聽=聽System.nanoTime();
+
+long聽frameCount聽=聽0;
+
+UsbCameraRecordManager.java
+
++3-3
+
+byte[]聽audioBuffer聽=聽new聽byte[audioBufferSize];
+
+long聽audioFrameCount聽=聽0;
+
+//聽缂栫爜闊抽鏁版嵁
+
+long聽audioFrameCount聽=聽0;
+
+byte[]聽audioBuffer聽=聽new聽byte[audioBufferSize];
+
+long聽totalSamplesRead聽=聽0;聽//聽鎬婚噰鏍锋暟
+
+//聽缂栫爜闊抽鏁版嵁
+
+UsbCameraRecordManager.java
+
++7-2
+
+*聽缂栫爜闊抽鏁版嵁
+
+*/
+
+private聽void聽encodeAudio(byte[]聽audioData,聽int聽size,聽long聽frameCount)聽{
+
+private聽void聽encodeAudio(byte[]聽audioData,聽int聽size,聽long聽frameCount)聽{
+
+*聽缂栫爜闊抽鏁版嵁
+
+*聽@param聽audioData聽闊抽鏁版嵁
+
+*聽@param聽size聽鏁版嵁澶у皬锛堝瓧鑺傦級
+
+*聽@param聽totalSamples聽鎬婚噰鏍锋暟锛堜粠寮�濮嬪埌鐜板湪鐨勭疮璁¢噰鏍锋暟锛�
+
+*/
+
+鍦ㄥ垱寤烘柊鏂囦欢鏃堕噸缃紑濮嬫椂闂达細
+
+UsbCameraRecordManager.java
+
++3
+
+//聽閲嶆柊鍚姩闊抽褰曞埗
+
+//聽閲嶇疆寮�濮嬫椂闂�
+
+recordingStartTimeNs聽=聽System.nanoTime();
+
+//聽閲嶆柊鍚姩闊抽褰曞埗
+
+宸蹭慨澶嶆椂闂存埑璁$畻闂銆備富瑕佷慨鏀瑰涓嬶細淇鍐呭锛�
+
+* * *
+
+1. 瑙嗛鏃堕棿鎴充娇鐢ㄥ疄闄呮椂闂达細
+
+
+* 涔嬪墠锛氫娇鐢�(frameIndex * 1000000) / FRAME_RATE聽璁$畻锛屽亣璁惧浐瀹氬抚鐜�
+
+* 鐜板湪锛氫娇鐢�(System.nanoTime() - recordingStartTimeNs) / 1000锛屽熀浜庡疄闄呯粡杩囨椂闂�
+
+
+1. 闊抽鏃堕棿鎴冲熀浜庨噰鏍锋暟锛�
+
+
+* 浣跨敤聽(totalSamples * 1000000) / SAMPLE_RATE聽璁$畻
+
+* totalSamples聽鏄疮璁¢噰鏍锋暟锛岀‘淇濇椂闂存埑杩炵画
+
+
+1. 娣诲姞浜嗗綍鍒跺紑濮嬫椂闂磋褰曪細
+
+
+* 浣跨敤聽recordingStartTimeNs聽璁板綍寮�濮嬫椂闂达紙绾崇锛�
+
+* 鍦ㄥ垱寤烘柊鏂囦欢鏃堕噸缃紝纭繚姣忎釜鏂囦欢鐨勬椂闂存埑浠� 0 寮�濮�
+
+
+1. 纭繚鏃堕棿鎴冲悓姝ワ細
+
+
+* 瑙嗛鍜岄煶棰戦兘浠庡悓涓�涓熀鍑嗘椂闂村紑濮�
+
+* 姣忎釜鏂版枃浠剁殑鏃堕棿鎴抽兘浠� 0 寮�濮�
+
+
+淇鍘熺悊锛�
+
+* 闂鍘熷洜锛氫娇鐢ㄥ抚绱㈠紩璁$畻鏃堕棿鎴筹紝鍋囪鍥哄畾甯х巼銆傚疄闄呴噰闆嗗抚鐜囧彲鑳戒笉鍚岋紝瀵艰嚧鏃堕棿鎴充笉鍑嗙‘
+
+* 瑙e喅鏂规锛氫娇鐢ㄥ疄闄呯粡杩囩殑鏃堕棿璁$畻鏃堕棿鎴筹紝纭繚鏃堕棿鎴充笌瀹為檯鏃堕棿涓�鑷�
+
+
+鐜板湪锛�
+
+* 瑙嗛鏃堕棿鎴冲熀浜庡疄闄呯粡杩囩殑鏃堕棿
+
+* 闊抽鏃堕棿鎴冲熀浜庡疄闄呰鍙栫殑閲囨牱鏁�
+
+* 涓よ�呴兘浠� 0 寮�濮嬶紝纭繚鍚屾
+
+
+#### 浣跨敤
+
+          private var mediaAidlInterface: IMediaAidlInterface? = null
+        private var serviceConnection: ServiceConnection? = null
+        private var isServiceBound = false
+        private val isServiceBoundState = mutableStateOf(false)
+            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")
+               
+           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")
+                                }
+                            }, }
+            }
+    
+        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")
+            }
+        }
+    
+        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://192.168.16.143/live/livestream" // 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
+            }
+        }
\ No newline at end of file

--
Gitblit v1.8.0