Skip to content

Commit

Permalink
fix(player): fix decoder issue on some low-end devices.
Browse files Browse the repository at this point in the history
Basically, this is what we call a _skill issue_ 😭
  • Loading branch information
rhenwinch committed Jun 6, 2024
1 parent a3b70dd commit c498dfb
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,13 @@ abstract class BasePlayerViewModel(
client = client,
context = context,
playerCacheManager = playerCacheManager,
appSettings = appSettingsManager.localAppSettings
appSettings = appSettingsManager.localAppSettings,
showErrorCallback = {
showErrorSnackbar(
message = it,
isInternalPlayerError = true
)
}
)

val sourceData: SourceData
Expand Down Expand Up @@ -176,7 +182,10 @@ abstract class BasePlayerViewModel(
*
* @param message the global [UiText] message to be sent and parse by the player
* */
protected abstract fun showErrorOnUiCallback(message: UiText)
protected abstract fun showErrorSnackbar(
message: UiText,
isInternalPlayerError: Boolean = false
)

fun onSeasonChange(seasonNumber: Int) {
if (onSeasonChangeJob?.isActive == true)
Expand Down Expand Up @@ -227,7 +236,7 @@ abstract class BasePlayerViewModel(
runWebView = runWebView,
onError = {
updateProviderSelected(oldSelectedSource)
showErrorOnUiCallback(UiText.StringResource(UtilR.string.failed_to_retrieve_provider_message_format))
showErrorSnackbar(UiText.StringResource(UtilR.string.failed_to_retrieve_provider_message_format))
}
).onCompletion {
if (it != null) {
Expand Down Expand Up @@ -345,7 +354,7 @@ abstract class BasePlayerViewModel(
* Obtains the next episode based on the given [TMDBEpisode].
* It returns null if an error has occured or it can't find the episode to be queried.
*
* @param onError an optional callback if caller wants to call [showErrorOnUiCallback]
* @param onError an optional callback if caller wants to call [showErrorSnackbar]
*
* */
private suspend fun TMDBEpisode.getNextEpisode(
Expand Down Expand Up @@ -409,7 +418,7 @@ abstract class BasePlayerViewModel(
runWebView: (FlixclusiveWebView) -> Unit
) {
if (loadLinksFromNewProviderJob?.isActive == true || loadLinksJob?.isActive == true) {
showErrorOnUiCallback(UiText.StringResource(UtilR.string.load_link_job_active_error_message))
showErrorSnackbar(UiText.StringResource(UtilR.string.load_link_job_active_error_message))
return
}

Expand All @@ -431,7 +440,7 @@ abstract class BasePlayerViewModel(
var episode = episodeToWatch
if (isLoadingNextEpisode) {
episode = currentSelectedEpisode.value!!.getNextEpisode(
onError = { showErrorOnUiCallback(it) }
onError = { showErrorSnackbar(it) }
).also {
if (it == null) {
return@launch
Expand All @@ -453,7 +462,7 @@ abstract class BasePlayerViewModel(
runWebView: (FlixclusiveWebView) -> Unit
) {
if (loadLinksFromNewProviderJob?.isActive == true || loadLinksJob?.isActive == true) {
showErrorOnUiCallback(UiText.StringResource(UtilR.string.load_link_job_active_error_message))
showErrorSnackbar(UiText.StringResource(UtilR.string.load_link_job_active_error_message))
return
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.util.fastAny
import androidx.media3.common.C
import androidx.media3.common.C.TIME_UNSET
import androidx.media3.common.Format
import androidx.media3.common.MediaItem
import androidx.media3.common.MediaItem.SubtitleConfiguration
Expand Down Expand Up @@ -46,6 +47,7 @@ import com.flixclusive.core.ui.player.util.getLoadControl
import com.flixclusive.core.ui.player.util.getPreferredSubtitleIndex
import com.flixclusive.core.ui.player.util.getRenderers
import com.flixclusive.core.ui.player.util.getSubtitleMimeType
import com.flixclusive.core.util.common.ui.UiText
import com.flixclusive.core.util.log.debugLog
import com.flixclusive.core.util.log.errorLog
import com.flixclusive.core.util.network.USER_AGENT
Expand Down Expand Up @@ -93,7 +95,8 @@ class FlixclusivePlayerManager(
client: OkHttpClient,
private val context: Context,
private val playerCacheManager: PlayerCacheManager,
private var appSettings: AppSettings
private var appSettings: AppSettings,
private var showErrorCallback: (message: UiText) -> Unit
) : Player.Listener {
private var mediaSession: MediaSession? = null
var player: ExoPlayer? by mutableStateOf(null)
Expand Down Expand Up @@ -166,11 +169,42 @@ class FlixclusivePlayerManager(
override fun onPlayerError(error: PlaybackException) {
errorLog(error.stackTraceToString())

if (error.cause is InvalidResponseCodeException) {
val okHttpError = error.cause as InvalidResponseCodeException
errorLog("Headers: ${okHttpError.dataSpec.httpRequestHeaders}")
errorLog("Url: ${okHttpError.dataSpec.uri}")
errorLog("Body: ${String(okHttpError.responseBody)}")
when {
error.errorCode == PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED
&& player != null
&& player?.duration != TIME_UNSET -> {
player?.run {
seekToDefaultPosition()
prepare()
playWhenReady = this@FlixclusivePlayerManager.playWhenReady
}
}

error.errorCode == PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW -> {
// Re-initialize player at the current live window default position.
player?.run {
seekToDefaultPosition()
prepare()
playWhenReady = this@FlixclusivePlayerManager.playWhenReady
}
}

else -> {
if (error.cause is InvalidResponseCodeException) {
val okHttpError = error.cause as InvalidResponseCodeException
errorLog(
"""
Headers: ${okHttpError.dataSpec.httpRequestHeaders}
Url: ${okHttpError.dataSpec.uri}
Body: ${String(okHttpError.responseBody)}
""".trimIndent()
)
}

val errorMessage = UiText.StringValue("PlaybackException [${error.errorCode}]: ${error.localizedMessage}")

showErrorCallback(errorMessage)
}
}

player?.run {
Expand Down Expand Up @@ -386,6 +420,9 @@ class FlixclusivePlayerManager(
*
*/
private fun createSubtitleSources(subtitles: List<Subtitle>): Array<SingleSampleMediaSource> {
if (subtitles.isEmpty())
return arrayOf()

availableSubtitles.clear()

val sortedSubtitles = subtitles
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ internal fun Context.getRenderers(
subtitleOffset: Long,
onTextRendererChange: (CustomTextRenderer) -> Unit,
): Array<Renderer> {
return DefaultRenderersFactory(this)
return DefaultRenderersFactory(this).apply {
setEnableDecoderFallback(true)
}
.createRenderers(
eventHandler,
videoRendererEventListener,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import com.flixclusive.core.ui.player.PlayerScreenNavArgs
import com.flixclusive.core.ui.player.PlayerSnackbarMessage
import com.flixclusive.core.ui.player.PlayerSnackbarMessageType
import com.flixclusive.core.ui.player.util.PlayerCacheManager
import com.flixclusive.core.ui.player.util.PlayerUiUtil
import com.flixclusive.core.util.common.ui.UiText
import com.flixclusive.data.watch_history.WatchHistoryRepository
import com.flixclusive.domain.database.WatchTimeUpdaterUseCase
Expand Down Expand Up @@ -73,11 +74,18 @@ class PlayerScreenViewModel @Inject constructor(
resetUiState()
}

override fun showErrorOnUiCallback(message: UiText) {
override fun showErrorSnackbar(
message: UiText,
isInternalPlayerError: Boolean
) {
showSnackbar(
message = message,
type = PlayerSnackbarMessageType.Error
)

if (isInternalPlayerError) {
selectNextServer()
}
}

fun showSnackbar(message: UiText, type: PlayerSnackbarMessageType) {
Expand Down Expand Up @@ -141,4 +149,21 @@ class PlayerScreenViewModel @Inject constructor(
SnackbarDuration.Long -> 10000L
SnackbarDuration.Indefinite -> Long.MAX_VALUE
}

private fun selectNextServer() {
val nextLinkIndex = (uiState.value.selectedSourceLink + 1).takeIf { it <= sourceData.cachedLinks.lastIndex }

if (nextLinkIndex != null) {
val newLink = sourceData.cachedLinks[nextLinkIndex]
val currentPlayerTitle = PlayerUiUtil.formatPlayerTitle(film, currentSelectedEpisode.value)

onServerChange(index = nextLinkIndex)
player.prepare(
link = newLink,
title = currentPlayerTitle,
subtitles = sourceData.cachedSubtitles.toList(),
initialPlaybackPosition = player.currentPosition
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,10 @@ class PlayerScreenViewModel @AssistedInject constructor(
}
}

override fun showErrorOnUiCallback(message: UiText) {

}
override fun showErrorSnackbar(
message: UiText,
isInternalPlayerError: Boolean
) {}

/**
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,8 @@ private fun PlaybackControlsPreview() {
OkHttpClient(),
LocalContext.current,
PlayerCacheManager(LocalContext.current),
AppSettings()
AppSettings(),
{}
)
) {
Box {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,8 @@ private fun PlaybackSpeedPanelPreview() {
OkHttpClient(),
LocalContext.current,
PlayerCacheManager(LocalContext.current),
AppSettings()
AppSettings(),
{}
)
) {
Box {
Expand Down

0 comments on commit c498dfb

Please sign in to comment.