Downsample if larger than 1080x1080 to prevent crashing.

This commit is contained in:
Koen J
2025-12-01 11:51:26 +01:00
parent 6d6309973e
commit 0abc65a9bd
16 changed files with 37 additions and 25 deletions
@@ -5,8 +5,6 @@ import android.content.Context
import android.content.Intent
import android.content.res.Resources
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.icu.util.Output
import android.os.Build
import android.os.Looper
import android.os.OperationCanceledException
@@ -44,6 +42,7 @@ import java.util.*
import java.util.concurrent.ThreadLocalRandom
import java.util.zip.GZIPInputStream
import java.util.zip.GZIPOutputStream
import androidx.core.graphics.scale
private val _allowedCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ";
fun getRandomString(sizeOfRandomString: Int): String {
@@ -114,23 +113,6 @@ fun DocumentFile.writeBytes(context: Context, byteArray: ByteArray) = context.co
it.flush();
};
fun loadBitmap(url: String): Bitmap {
try {
val client = ManagedHttpClient();
val response = client.get(url);
if (response.isOk && response.body != null) {
val bitmapStream = response.body.byteStream();
val bitmap = BitmapFactory.decodeStream(bitmapStream);
return bitmap;
} else {
throw Exception("Failed to find data at URL.");
}
} catch (e: Throwable) {
Logger.w("Utility", "Exception thrown while downloading bitmap.", e);
throw e;
}
}
fun TextView.setPlatformPlayerLinkMovementMethod(context: Context) {
this.movementMethod = PlatformLinkMovementMethod(context);
}
@@ -16,6 +16,7 @@ import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.bitmap.DownsampleStrategy
import com.futo.platformplayer.*
import com.futo.platformplayer.api.media.models.playlists.IPlatformPlaylist
import com.futo.platformplayer.api.media.models.playlists.IPlatformPlaylistDetails
@@ -363,6 +364,7 @@ class RemotePlaylistFragment : MainFragment() {
_imagePlaylistThumbnail.let {
Glide.with(it)
.load(video.thumbnails.getHQThumbnail())
.downsample(DownsampleStrategy.AT_MOST).override(1080, 1080)
.placeholder(R.drawable.placeholder_video_thumbnail)
.crossfade()
.into(it);
@@ -2,7 +2,9 @@ package com.futo.platformplayer.fragment.mainactivity.main
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.drawable.Animatable
import android.graphics.drawable.Drawable
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.WindowManager
@@ -13,10 +15,15 @@ import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.graphics.drawable.toDrawable
import androidx.lifecycle.lifecycleScope
import androidx.media3.common.C
import androidx.media3.common.Format
import androidx.media3.common.util.UnstableApi
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.bitmap.DownsampleStrategy
import com.bumptech.glide.request.target.CustomTarget
import com.bumptech.glide.request.transition.Transition
import com.futo.platformplayer.R
import com.futo.platformplayer.Settings
import com.futo.platformplayer.UIDialogs
@@ -851,9 +858,8 @@ class ShortView : FrameLayout {
}
val thumbnail = videoDetails.thumbnails.getHQThumbnail()
/*
if (videoSource == null && !thumbnail.isNullOrBlank()) Glide.with(context).asBitmap()
.load(thumbnail).into(object : CustomTarget<Bitmap>() {
.load(thumbnail).downsample(DownsampleStrategy.AT_MOST).override(1080, 1080).into(object : CustomTarget<Bitmap>() {
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
player.setArtwork(resource.toDrawable(resources))
}
@@ -863,7 +869,6 @@ class ShortView : FrameLayout {
}
})
else player.setArtwork(null)
*/
fragment.lifecycleScope.launch(Dispatchers.Main) {
try {
@@ -42,6 +42,7 @@ import androidx.media3.datasource.HttpDataSource
import androidx.media3.ui.PlayerControlView
import androidx.media3.ui.TimeBar
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.bitmap.DownsampleStrategy
import com.bumptech.glide.request.target.CustomTarget
import com.bumptech.glide.request.transition.Transition
import com.futo.platformplayer.BuildConfig
@@ -2049,7 +2050,7 @@ class VideoDetailView : ConstraintLayout {
} else {
val thumbnail = video.thumbnails.getHQThumbnail();
if ((videoSource == null) && !thumbnail.isNullOrBlank()) // || _player.isAudioMode
Glide.with(context).asBitmap().load(thumbnail)
Glide.with(context).asBitmap().load(thumbnail).downsample(DownsampleStrategy.AT_MOST).override(1080, 1080)
.into(object: CustomTarget<Bitmap>() {
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
_player.setArtwork(BitmapDrawable(resources, resource));
@@ -14,6 +14,7 @@ import android.widget.TextView
import androidx.core.view.isVisible
import androidx.core.view.setPadding
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.bitmap.DownsampleStrategy
import com.futo.platformplayer.R
import com.futo.platformplayer.UIDialogs
import com.futo.platformplayer.UISlideOverlays
@@ -211,6 +212,7 @@ abstract class VideoListEditorView : LinearLayout {
_imagePlaylistThumbnail.let {
Glide.with(it)
.load(video.thumbnails.getHQThumbnail())
.downsample(DownsampleStrategy.AT_MOST).override(1080, 1080)
.placeholder(R.drawable.placeholder_video_thumbnail)
.crossfade()
.into(it);
@@ -4,6 +4,7 @@ import android.graphics.drawable.Drawable
import android.widget.ImageView
import com.bumptech.glide.Glide
import com.bumptech.glide.RequestBuilder
import com.bumptech.glide.load.resource.bitmap.DownsampleStrategy
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
import com.futo.platformplayer.api.media.models.Thumbnails
@@ -14,7 +15,7 @@ class GlideHelper {
fun ImageView.loadThumbnails(thumbnails: Thumbnails, isHQ: Boolean = true, continuation: ((RequestBuilder<Drawable>) -> Unit)? = null) {
val url = if(isHQ) thumbnails.getHQThumbnail() ?: thumbnails.getLQThumbnail() else thumbnails.getLQThumbnail();
val req = Glide.with(this).load(url);
val req = Glide.with(this).load(url).downsample(DownsampleStrategy.AT_MOST).override(1080, 1080);
if (thumbnails.hasMultiple() && false) { //TODO: Resolve issue where fallback triggered on second loads?
val fallbackUrl = if (isHQ) thumbnails.getLQThumbnail() else thumbnails.getHQThumbnail();
@@ -26,6 +26,7 @@ import android.util.Log
import android.view.KeyEvent
import androidx.core.app.NotificationCompat
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.bitmap.DownsampleStrategy
import com.bumptech.glide.request.target.CustomTarget
import com.bumptech.glide.request.transition.Transition
import com.futo.platformplayer.R
@@ -224,6 +225,7 @@ class MediaPlaybackService : Service() {
val tag = video;
Glide.with(this).asBitmap()
.load(thumbnail)
.downsample(DownsampleStrategy.AT_MOST).override(1080, 1080)
.into(object: CustomTarget<Bitmap>() {
override fun onResourceReady(resource: Bitmap,transition: Transition<in Bitmap>?) {
if (tag != _notif_last_video) return
@@ -10,6 +10,7 @@ import android.graphics.drawable.Drawable
import android.os.Build
import androidx.core.app.NotificationCompat
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.bitmap.DownsampleStrategy
import com.bumptech.glide.request.target.CustomTarget
import com.bumptech.glide.request.transition.Transition
import com.futo.platformplayer.activities.MainActivity
@@ -96,6 +97,7 @@ class StateNotifications {
if(thumbnail != null)
Glide.with(context).asBitmap()
.load(thumbnail)
.downsample(DownsampleStrategy.AT_MOST).override(1080, 1080)
.into(object: CustomTarget<Bitmap>() {
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
notifyNewContent(context, manager, notificationChannel, id, content, resource);
@@ -7,6 +7,7 @@ import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.bitmap.DownsampleStrategy
import com.futo.platformplayer.R
import com.futo.platformplayer.constructs.Event0
import com.futo.platformplayer.images.GlideHelper.Companion.crossfade
@@ -44,6 +45,7 @@ class PlaylistsViewHolder : ViewHolder {
if (p.videos.isNotEmpty()) {
Glide.with(_imageThumbnail)
.load(p.videos[0].thumbnails.getMinimumThumbnail(380))
.downsample(DownsampleStrategy.AT_MOST).override(1080, 1080)
.placeholder(R.drawable.placeholder_video_thumbnail)
.crossfade()
.into(_imageThumbnail);
@@ -12,6 +12,7 @@ import androidx.constraintlayout.widget.ConstraintLayout
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.bitmap.DownsampleStrategy
import com.futo.platformplayer.R
import com.futo.platformplayer.api.media.models.video.IPlatformVideo
import com.futo.platformplayer.constructs.Event1
@@ -89,6 +90,7 @@ class VideoListEditorViewHolder : ViewHolder {
fun bind(v: IPlatformVideo, canEdit: Boolean) {
Glide.with(_imageThumbnail)
.load(v.thumbnails.getHQThumbnail())
.downsample(DownsampleStrategy.AT_MOST).override(1080, 1080)
.placeholder(R.drawable.placeholder_video_thumbnail)
.crossfade()
.into(_imageThumbnail);
@@ -7,6 +7,7 @@ import android.widget.ImageView
import android.widget.TextView
import androidx.core.view.isVisible
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.bitmap.DownsampleStrategy
import com.futo.platformplayer.R
import com.futo.platformplayer.api.media.models.contents.IPlatformContent
import com.futo.platformplayer.api.media.models.video.IPlatformVideo
@@ -49,6 +50,7 @@ class LocalVideoTileViewHolder(val _viewGroup: ViewGroup) : AnyAdapter.AnyViewHo
Glide.with(it)
.load(content.thumbnails.getHQThumbnail())
.placeholder(R.drawable.unknown_music)
.downsample(DownsampleStrategy.AT_MOST).override(1080, 1080)
.into(it)
else
Glide.with(it).load(R.drawable.unknown_music).into(it);
@@ -18,6 +18,7 @@ import androidx.media3.common.util.UnstableApi
import androidx.media3.ui.DefaultTimeBar
import androidx.media3.ui.TimeBar
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.bitmap.DownsampleStrategy
import com.futo.platformplayer.R
import com.futo.platformplayer.Settings
import com.futo.platformplayer.api.media.models.chapters.IChapter
@@ -306,6 +307,7 @@ class CastView : ConstraintLayout {
Glide.with(_thumbnail)
.load(video.thumbnails.getHQThumbnail())
.placeholder(R.drawable.placeholder_video_thumbnail)
.downsample(DownsampleStrategy.AT_MOST).override(1080, 1080)
.into(_thumbnail);
_textPosition.text = (position * 1000).formatDuration();
_textDuration.text = (video.duration * 1000).formatDuration();
@@ -6,6 +6,7 @@ import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.bitmap.DownsampleStrategy
import com.futo.platformplayer.*
import com.futo.platformplayer.downloads.VideoDownload
import com.futo.platformplayer.images.GlideHelper.Companion.crossfade
@@ -60,6 +61,7 @@ class ActiveDownloadItem: LinearLayout {
}
Glide.with(_videoImage)
.downsample(DownsampleStrategy.AT_MOST).override(1080, 1080)
.load(download.thumbnail)
.crossfade()
.into(_videoImage);
@@ -5,6 +5,7 @@ import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.bitmap.DownsampleStrategy
import com.futo.platformplayer.R
import com.futo.platformplayer.images.GlideHelper.Companion.crossfade
import com.futo.platformplayer.models.PlaylistDownloaded
@@ -19,6 +20,7 @@ class PlaylistDownloadItem(context: Context, playlistName: String, playlistThumb
imageText.text = playlistName;
Glide.with(imageView)
.load(playlistThumbnail)
.downsample(DownsampleStrategy.AT_MOST).override(1080, 1080)
.crossfade()
.into(imageView);
}
@@ -15,6 +15,7 @@ import androidx.media3.common.util.UnstableApi
import androidx.media3.ui.PlayerControlView
import androidx.media3.ui.PlayerView
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.bitmap.DownsampleStrategy
import com.bumptech.glide.request.target.CustomTarget
import com.bumptech.glide.request.transition.Transition
import com.futo.platformplayer.R
@@ -135,7 +136,7 @@ class FutoThumbnailPlayer : FutoVideoPlayerBase {
if (videoSource == null && audioSource != null) {
val thumbnail = video.thumbnails.getHQThumbnail();
if (!thumbnail.isNullOrBlank()) {
Glide.with(videoView).asBitmap().load(thumbnail).into(_loadArtwork);
Glide.with(videoView).asBitmap().load(thumbnail).downsample(DownsampleStrategy.AT_MOST).override(1080, 1080).into(_loadArtwork);
} else {
Glide.with(videoView).clear(_loadArtwork);
setArtwork(null);
@@ -11,6 +11,7 @@ import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.bitmap.DownsampleStrategy
import com.futo.platformplayer.states.StatePlayer
import com.futo.platformplayer.R
import com.futo.platformplayer.constructs.Event0
@@ -160,6 +161,7 @@ class UpNextView : LinearLayout {
_textChannelName.text = nextItem.author.name;
Glide.with(_imageThumbnail)
.load(nextItem.thumbnails.getHQThumbnail())
.downsample(DownsampleStrategy.AT_MOST).override(1080, 1080)
.placeholder(R.drawable.placeholder_video_thumbnail)
.into(_imageThumbnail);
Glide.with(_imageChannelThumbnail)