From e09b3e4440f51be0a1871ca6f4f89709a297e6b9 Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Tue, 1 Apr 2025 23:38:41 +0200 Subject: [PATCH] region decoder pool --- .../channel/calls/fetchers/RegionFetcher.kt | 49 +++++++++++-------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/fetchers/RegionFetcher.kt b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/fetchers/RegionFetcher.kt index 73fad7469..f3d761fbb 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/fetchers/RegionFetcher.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/fetchers/RegionFetcher.kt @@ -29,10 +29,6 @@ import kotlin.math.roundToInt class RegionFetcher internal constructor( private val context: Context, ) { - private var lastDecoderRef: LastDecoderRef? = null - - private val exportUris = HashMap, Uri>() - // return decoded bytes in ARGB_8888, with trailer bytes: // - width (int32) // - height (int32) @@ -63,24 +59,12 @@ class RegionFetcher internal constructor( return } - var currentDecoderRef = lastDecoderRef - if (currentDecoderRef != null && currentDecoderRef.requestKey != requestKey) { - currentDecoderRef = null - } - try { - if (currentDecoderRef == null) { - val newDecoder = StorageUtils.openInputStream(context, uri)?.use { input -> - BitmapRegionDecoderCompat.newInstance(input) - } - if (newDecoder == null) { - result.error("fetch-read-null", "failed to open file for mimeType=$mimeType uri=$uri regionRect=$regionRect", null) - return - } - currentDecoderRef = LastDecoderRef(requestKey, newDecoder) + val decoder = getOrCreateDecoder(uri, requestKey) + if (decoder == null) { + result.error("fetch-read-null", "failed to open file for mimeType=$mimeType uri=$uri regionRect=$regionRect", null) + return } - val decoder = currentDecoderRef.decoder - lastDecoderRef = currentDecoderRef // with raw images, the known image size may not match the decoded image size // so we scale the requested region accordingly @@ -159,6 +143,26 @@ class RegionFetcher internal constructor( } } + private fun getOrCreateDecoder(uri: Uri, requestKey: Pair): BitmapRegionDecoder? { + var decoderRef = decoderPool.firstOrNull { it.requestKey == requestKey } + if (decoderRef == null) { + val newDecoder = StorageUtils.openInputStream(context, uri)?.use { input -> + BitmapRegionDecoderCompat.newInstance(input) + } + if (newDecoder == null) { + return null + } + decoderRef = DecoderRef(requestKey, newDecoder) + } else { + decoderPool.remove(decoderRef) + } + decoderPool.add(0, decoderRef) + while (decoderPool.size > DECODER_POOL_SIZE) { + decoderPool.removeAt(decoderPool.size - 1) + } + return decoderRef.decoder + } + private fun createTemporaryJpegExport(uri: Uri, mimeType: String, pageId: Int?): Uri { Log.d(LOG_TAG, "create JPEG export for uri=$uri mimeType=$mimeType pageId=$pageId") val target = Glide.with(context) @@ -180,7 +184,7 @@ class RegionFetcher internal constructor( } } - private data class LastDecoderRef( + private data class DecoderRef( val requestKey: Pair, val decoder: BitmapRegionDecoder, ) @@ -188,5 +192,8 @@ class RegionFetcher internal constructor( companion object { private val LOG_TAG = LogUtils.createTag() private val PREFERRED_CONFIG = Bitmap.Config.ARGB_8888 + private const val DECODER_POOL_SIZE = 3 + private val decoderPool = ArrayList() + private val exportUris = HashMap, Uri>() } }