安卓。在协程上下文中使用 AudioTrack.write 方法会使应用程序崩溃

问题描述 投票:0回答:1

我有下面的代码行。我正在尝试播放流并且正在使用 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)

我尝试了上面所有的解决方案,但没有任何效果对我来说。

android kotlin coroutine audiotrack
1个回答
0
投票

我认为问题可能是在每个接收/解码的音频块上启动一个新的协程。您可以尝试使用通过 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)
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.