我有下面的代码行。我正在尝试播放流并且正在使用 AudioTrack。
CoroutineScope(Dispatchers.IO).launch {
withContext(Dispatchers.IO) {
try {
decodedFrames.forEach {frame ->
audioTrack?.write(frame,0,frame.size)
}
} catch (e : Exception) {
Log.e("ERROR",e.message!!)
}
}
}
当我在没有协程上下文的情况下使用 write 方法时,声音很好,但应用程序变得缓慢。如果我使用带有 WRITE_NON_BLOCKING 的写入方法,那么声音会被中断,但应用程序不再延迟。当我在协程上下文中使用 write 方法(如上面的方法)时,声音很好,应用程序不再延迟,但几秒钟或几分钟后,应用程序崩溃并出现以下错误。下面的错误是一个很长的错误,表明有问题的行是
audiotrack?.write
one
releaseBuffer: mUnreleased out of range, !(stepCount:952 <= mUnreleased:0 <= mFrameCount:3848), BufferSizeInFrames:3848 2023-11-09 07:52:54.652 18535-18615 A runtime.cc:691] Runtime aborting... runtime.cc:691] Dumping all threads without mutator lock held runtime.cc:691] All threads: runtime.cc:691] DALVIK THREADS (26): runtime.cc:691] "main" prio=10 tid=1 Native runtime.cc:691] | group="" sCount=1 ucsCount=0 flags=1 obj=0x73500d40 self=0xb40000781c02c7b0 runtime.cc:691] | sysTid=18535 nice=-10 cgrp=top-app sched=0/0 handle=0x79ce39d500 runtime.cc:691] | state=S schedstat=( 10320252622 172287193 3307 ) utm=972 stm=59 core=5 HZ=100 runtime.cc:691] | stack=0x7fe496a000-0x7fe496c000 stackSize=8188KB runtime.cc:691] | held mutexes= runtime.cc:691] native: #00 pc 0004e1dc /apex/com.android.runtime/lib64/bionic/libc.so (syscall+28) (BuildId: 7464f932fe1115e080f728808bf0ade7) runtime.cc:691] native: #01 pc 0023746c /apex/com.android.art/lib64/libart.so (art::ConditionVariable::WaitHoldingLocks+140) (BuildId: 4cfdaa9e5146c43e20ae36ee1caf9b7f) runtime.cc:691] native: #02 pc 004676ac /apex/com.android.art/lib64/libart.so (artQuickGenericJniEndTrampoline+1008) (BuildId: 4cfdaa9e5146c43e20ae36ee1caf9b7f) runtime.cc:691] native: #03 pc 0034aa40 /apex/com.android.art/lib64/libart.so (art_quick_generic_jni_trampoline+160) (BuildId: 4cfdaa9e5146c43e20ae36ee1caf9b7f) runtime.cc:691] native: #04 pc 00333fa4 /apex/com.android.art/lib64/libart.so (art_quick_invoke_stub+612) (BuildId: 4cfdaa9e5146c43e20ae36ee1caf9b7f) runtime.cc:691] native: #05 pc 00511078 /apex/com.android.art/lib64/libart.so (bool art::interpreter::DoCall<false>+1976) (BuildId: 4cfdaa9e5146c43e20ae36ee1caf9b7f) runtime.cc:691] native: #06 pc 0049e538 /apex/com.android.art/lib64/libart.so (void art::interpreter::ExecuteSwitchImplCpp<false>+2040) (BuildId: 4cfdaa9e5146c43e20ae36ee1caf9b7f) runtime.cc:691] native: #07 pc 0034d1d8 /apex/com.android.art/lib64/libart.so (ExecuteSwitchImplAsm+8) (BuildId: 4cfdaa9e5146c43e20ae36ee1caf9b7f) runtime.cc:691] native: #08 pc 001fe800 /system/framework/framework.jar (android.os.MessageQueue.next) runtime.cc:691] native: #09 pc 00378bb0 /apex/com.android.art/lib64/libart.so (art::interpreter::Execute +232) (BuildId: 4cfdaa9e5146c43e20ae36ee1caf9b7f) runtime.cc:691] native: #10 pc 00511d44 /apex/com.android.art/lib64/libart.so (bool art::interpreter::DoCall<false>+5252) (BuildId: 4cfdaa9e5146c43e20ae36ee1caf9b7f) runtime.cc:691] native: #11 pc 0049e100 /apex/com.android.art/lib64/libart.so (void art::interpreter::ExecuteSwitchImplCpp<false>+960) (BuildId: 4cfdaa9e5146c43e20ae36ee1caf9b7f) runtime.cc:691] native: #12 pc 0034d1d8 /apex/com.android.art/lib64/libart.so (ExecuteSwitchImplAsm+8) (BuildId: 4cfdaa9e5146c43e20ae36ee1caf9b7f) runtime.cc:691] native: #13 pc 001fd700 /system/framework/framework.jar (android.os.Looper.loopOnce) runtime.cc:691] native: #14 pc 00378bb0 /apex/com.android.art/lib64/libart.so (art::interpreter::Execute +232) (BuildId: 4cfdaa9e5146c43e20ae36ee1caf9b7f) runtime.cc:691] native: #15 pc 00511d44 /apex/com.android.art/lib64/libart.so (bool art::interpreter::DoCall<false>+5252) (BuildId: 4cfdaa9e5146c43e20ae36ee1caf9b7f) runtime.cc:691] native: #16 pc 0049e470 /apex/com.android.art/lib64/libart.so (void art::interpreter::ExecuteSwitchImplCpp<false>+1840) (BuildId: 4cfdaa9e5146c43e20ae36ee1caf9b7f) runtime.cc:691] native: #17 pc 0034d1d8 /apex/com.android.art/lib64/libart.so (ExecuteSwitchImplAsm+8) (BuildId: 4cfdaa9e5146c43e20ae36ee1caf9b7f) runtime.cc:691] native: #18 pc 001fdf24 /system/framework/framework.jar (android.os.Looper.loop) runtime.cc:691] native: #19 pc 00378bb0 /apex/com.android.art/lib64/libart.so (art::interpreter::Execute +232) (BuildId: 4cfdaa9e5146c43e20ae36ee1caf9b7f) runtime.cc:691] native: #20 pc 00511d44 /apex/com.android.art/lib64/libart.so (bool art::interpreter::DoCall<false>+5252) (BuildId: 4cfdaa9e5146c43e20ae36ee1caf9b7f)
我尝试了上面所有的解决方案,但没有任何效果对我来说。
我认为问题可能是在每个接收/解码的音频块上启动一个新的协程。您可以尝试使用通过 Kotlin Channel 接收数据的单人协程。
创建频道。
var decodedAudio = Channel<ShortArray>(10, BufferOverflow.DROP_OLDEST)
然后写入解码器中。
val decodedData: ShortArray = //decode
decodedAudio.send(decodedData)
并在播放器中读取它。
scope.launch {
audioTrack.play()
while (isActive) {
val chunk = decodedAudio.receive()
audioTrack?.write(chunk, 0, chunk.size, AudioTrack.WRITE_NON_BLOCKING)
}
}