kopia lustrzana https://github.com/ryukoposting/Signal-Android
Wrap DefaultAudioSink to tolerate init errors.
rodzic
99f8ba5e0c
commit
d678341399
|
@ -0,0 +1,52 @@
|
|||
package org.thoughtcrime.securesms.components.voice
|
||||
|
||||
import android.content.Context
|
||||
import com.google.android.exoplayer2.audio.AudioCapabilities
|
||||
import com.google.android.exoplayer2.audio.AudioSink
|
||||
import com.google.android.exoplayer2.audio.DefaultAudioSink
|
||||
import org.signal.core.util.logging.Log
|
||||
import java.nio.ByteBuffer
|
||||
|
||||
/**
|
||||
* Certain devices, including the incredibly popular Samsung A51, often fail to create a proper audio sink when switching from "media" mode to "communication" mode.
|
||||
* It does eventually recover, but it needs to be given ample opportunity to.
|
||||
* This class wraps the final DefaultAudioSink to provide exactly that functionality.
|
||||
*/
|
||||
class RetryableInitAudioSink(
|
||||
context: Context,
|
||||
enableFloatOutput: Boolean,
|
||||
enableAudioTrackPlaybackParams: Boolean,
|
||||
enableOffload: Boolean,
|
||||
val delegate: AudioSink = DefaultAudioSink.Builder()
|
||||
.setAudioCapabilities(AudioCapabilities.getCapabilities(context))
|
||||
.setEnableFloatOutput(enableFloatOutput)
|
||||
.setEnableAudioTrackPlaybackParams(enableAudioTrackPlaybackParams)
|
||||
.setOffloadMode(if (enableOffload) DefaultAudioSink.OFFLOAD_MODE_ENABLED_GAPLESS_REQUIRED else DefaultAudioSink.OFFLOAD_MODE_DISABLED)
|
||||
.build()
|
||||
) : AudioSink by delegate {
|
||||
|
||||
private var retriesLeft = INITIAL_RETRY_COUNT
|
||||
|
||||
override fun handleBuffer(buffer: ByteBuffer, presentationTimeUs: Long, encodedAccessUnitCount: Int): Boolean {
|
||||
return try {
|
||||
val bufferHandled = delegate.handleBuffer(buffer, presentationTimeUs, encodedAccessUnitCount)
|
||||
if (bufferHandled) {
|
||||
retriesLeft = INITIAL_RETRY_COUNT
|
||||
}
|
||||
bufferHandled
|
||||
} catch (e: AudioSink.InitializationException) {
|
||||
Log.w(TAG, "Could not handle this buffer due to an initialization exception. $retriesLeft retries remaining.", e)
|
||||
if (retriesLeft > 0) {
|
||||
retriesLeft--
|
||||
false
|
||||
} else {
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val TAG = Log.tag(RetryableInitAudioSink::class.java)
|
||||
const val INITIAL_RETRY_COUNT = 5
|
||||
}
|
||||
}
|
|
@ -4,16 +4,16 @@ import android.media.AudioManager
|
|||
import android.os.Bundle
|
||||
import android.os.ResultReceiver
|
||||
import com.google.android.exoplayer2.C
|
||||
import com.google.android.exoplayer2.ExoPlayer
|
||||
import com.google.android.exoplayer2.PlaybackParameters
|
||||
import com.google.android.exoplayer2.Player
|
||||
import com.google.android.exoplayer2.SimpleExoPlayer
|
||||
import com.google.android.exoplayer2.audio.AudioAttributes
|
||||
import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector
|
||||
import com.google.android.exoplayer2.util.Util
|
||||
import org.signal.core.util.logging.Log
|
||||
|
||||
class VoiceNotePlaybackController(
|
||||
private val player: SimpleExoPlayer,
|
||||
private val player: ExoPlayer,
|
||||
private val voiceNotePlaybackParameters: VoiceNotePlaybackParameters
|
||||
) : MediaSessionConnector.CommandReceiver {
|
||||
|
||||
|
@ -42,7 +42,6 @@ class VoiceNotePlaybackController(
|
|||
|
||||
player.playWhenReady = false
|
||||
player.setAudioAttributes(attributes, newStreamType == AudioManager.STREAM_MUSIC)
|
||||
|
||||
if (newStreamType == AudioManager.STREAM_VOICE_CALL) {
|
||||
player.playWhenReady = true
|
||||
}
|
||||
|
|
|
@ -3,14 +3,17 @@ package org.thoughtcrime.securesms.components.voice
|
|||
import android.content.Context
|
||||
import com.google.android.exoplayer2.C
|
||||
import com.google.android.exoplayer2.DefaultLoadControl
|
||||
import com.google.android.exoplayer2.DefaultRenderersFactory
|
||||
import com.google.android.exoplayer2.ExoPlayer
|
||||
import com.google.android.exoplayer2.ForwardingPlayer
|
||||
import com.google.android.exoplayer2.SimpleExoPlayer
|
||||
import com.google.android.exoplayer2.audio.AudioAttributes
|
||||
import com.google.android.exoplayer2.audio.AudioSink
|
||||
import org.thoughtcrime.securesms.video.exo.SignalMediaSourceFactory
|
||||
|
||||
class VoiceNotePlayer @JvmOverloads constructor(
|
||||
context: Context,
|
||||
val internalPlayer: SimpleExoPlayer = SimpleExoPlayer.Builder(context)
|
||||
val internalPlayer: ExoPlayer = ExoPlayer.Builder(context)
|
||||
.setRenderersFactory(WorkaroundRenderersFactory(context))
|
||||
.setMediaSourceFactory(SignalMediaSourceFactory(context))
|
||||
.setLoadControl(
|
||||
DefaultLoadControl.Builder()
|
||||
|
@ -39,3 +42,12 @@ class VoiceNotePlayer @JvmOverloads constructor(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see RetryableInitAudioSink
|
||||
*/
|
||||
class WorkaroundRenderersFactory(val context: Context) : DefaultRenderersFactory(context) {
|
||||
override fun buildAudioSink(context: Context, enableFloatOutput: Boolean, enableAudioTrackPlaybackParams: Boolean, enableOffload: Boolean): AudioSink? {
|
||||
return RetryableInitAudioSink(context, enableFloatOutput, enableAudioTrackPlaybackParams, enableOffload)
|
||||
}
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue