fix(mpv): memory leak, stuck loading icon, anr, deprecated methods (#273)

* fix: memory leak and stuck loading icon

Also replace deprecated audio focus methods

* fix: use global scope for posting playback stopped

This fixes ANRs that people are having when leaving the player
This commit is contained in:
Jarne Demeulemeester 2023-02-05 01:15:43 +01:00 committed by GitHub
parent dff297513a
commit 7b5745acf1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 23 additions and 20 deletions

View file

@ -3,6 +3,7 @@ package dev.jdtech.jellyfin.mpv
import android.app.Application
import android.content.Context
import android.content.res.AssetManager
import android.media.AudioFocusRequest
import android.media.AudioManager
import android.os.Handler
import android.os.Looper
@ -49,14 +50,14 @@ import timber.log.Timber
@Suppress("SpellCheckingInspection")
class MPVPlayer(
context: Context,
requestAudioFocus: Boolean,
private val requestAudioFocus: Boolean,
private val appPreferences: AppPreferences
) : BasePlayer(), MPVLib.EventObserver, AudioManager.OnAudioFocusChangeListener {
private val audioManager: AudioManager by lazy { context.getSystemService()!! }
private var audioFocusCallback: () -> Unit = {}
private var currentIndex = 0
private var audioFocusRequest = AudioManager.AUDIOFOCUS_REQUEST_FAILED
private lateinit var audioFocusRequest: AudioFocusRequest
private val handler = Handler(context.mainLooper)
init {
@ -132,13 +133,16 @@ class MPVPlayer(
}
if (requestAudioFocus) {
@Suppress("DEPRECATION")
audioFocusRequest = audioManager.requestAudioFocus(
/* l = */ this,
/* streamType = */ AudioManager.STREAM_MUSIC,
/* durationHint = */ AudioManager.AUDIOFOCUS_GAIN
)
if (audioFocusRequest != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
val audioAttributes = android.media.AudioAttributes.Builder()
.setUsage(android.media.AudioAttributes.USAGE_MEDIA)
.setContentType(android.media.AudioAttributes.CONTENT_TYPE_MOVIE)
.build()
audioFocusRequest = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
.setAudioAttributes(audioAttributes)
.setOnAudioFocusChangeListener(this)
.build()
val res = audioManager.requestAudioFocus(audioFocusRequest)
if (res != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
MPVLib.setPropertyBoolean("pause", true)
}
}
@ -312,9 +316,7 @@ class MPVPlayer(
videoListener.onRenderedFirstFrame()
}
} else {
if (playbackState == Player.STATE_BUFFERING && bufferedPosition > currentPosition) {
setPlayerStateAndNotifyIfChanged(playbackState = Player.STATE_READY)
}
setPlayerStateAndNotifyIfChanged(playbackState = Player.STATE_READY)
}
}
else -> Unit
@ -344,9 +346,8 @@ class MPVPlayer(
playerStateChanged = true
}
if (playerStateChanged) {
listeners.queueEvent( /* eventFlag = */ C.INDEX_UNSET) { listener ->
@Suppress("DEPRECATION")
listener.onPlayerStateChanged(playWhenReady, playbackState)
listeners.queueEvent(C.INDEX_UNSET) { listener ->
listener.onPlaybackStateChanged(playbackState)
}
}
if (wasPlaying != isPlaying) {
@ -899,11 +900,11 @@ class MPVPlayer(
* player must not be used after calling this method.
*/
override fun release() {
if (audioFocusRequest == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
@Suppress("DEPRECATION")
audioManager.abandonAudioFocus(this)
if (requestAudioFocus) {
audioManager.abandonAudioFocusRequest(audioFocusRequest)
}
resetInternalState()
MPVLib.removeObserver(this)
MPVLib.destroy()
currentIndex = 0
}

View file

@ -24,9 +24,10 @@ import dev.jdtech.jellyfin.mpv.MPVPlayer
import dev.jdtech.jellyfin.mpv.TrackType
import dev.jdtech.jellyfin.repository.JellyfinRepository
import dev.jdtech.jellyfin.utils.postDownloadPlaybackProgress
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import timber.log.Timber
import java.util.UUID
@ -163,9 +164,10 @@ constructor(
}
}
@OptIn(DelicateCoroutinesApi::class)
private fun releasePlayer() {
player.let { player ->
runBlocking {
GlobalScope.launch {
try {
jellyfinRepository.postPlaybackStop(
UUID.fromString(player.currentMediaItem?.mediaId),