fixed page identification in multipage HEIC with non-unique track IDs

This commit is contained in:
Thibault Deckers 2021-02-27 11:10:47 +09:00
parent ef528c4c90
commit 8fb349fc6e
5 changed files with 16 additions and 16 deletions

View file

@ -593,10 +593,11 @@ class MetadataHandler(private val context: Context) : MethodCallHandler {
KEY_PAGE to i,
KEY_MIME_TYPE to trackMime,
)
// do not use `MediaFormat.KEY_TRACK_ID` as it is actually not unique between tracks
// e.g. there could be both a video track and an image track with KEY_TRACK_ID == 1
format.getSafeInt(MediaFormat.KEY_IS_DEFAULT) { page[KEY_IS_DEFAULT] = it != 0 }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
format.getSafeInt(MediaFormat.KEY_TRACK_ID) { page[KEY_TRACK_ID] = it }
}
format.getSafeInt(MediaFormat.KEY_WIDTH) { page[KEY_WIDTH] = it }
format.getSafeInt(MediaFormat.KEY_HEIGHT) { page[KEY_HEIGHT] = it }
if (isVideo(trackMime)) {
@ -875,7 +876,6 @@ class MetadataHandler(private val context: Context) : MethodCallHandler {
private const val KEY_HEIGHT = "height"
private const val KEY_WIDTH = "width"
private const val KEY_PAGE = "page"
private const val KEY_TRACK_ID = "trackId"
private const val KEY_IS_DEFAULT = "isDefault"
private const val KEY_DURATION = "durationMillis"

View file

@ -27,7 +27,7 @@ class MultiTrackImageGlideModule : LibraryGlideModule() {
}
}
class MultiTrackImage(val context: Context, val uri: Uri, val trackId: Int?)
class MultiTrackImage(val context: Context, val uri: Uri, val trackIndex: Int?)
internal class MultiTrackThumbnailLoader : ModelLoader<MultiTrackImage, Bitmap> {
override fun buildLoadData(model: MultiTrackImage, width: Int, height: Int, options: Options): ModelLoader.LoadData<Bitmap> {
@ -52,9 +52,9 @@ internal class MultiTrackImageFetcher(val model: MultiTrackImage, val width: Int
val context = model.context
val uri = model.uri
val trackId = model.trackId
val trackIndex = model.trackIndex
val bitmap = MultiTrackMedia.getImage(context, uri, trackId)
val bitmap = MultiTrackMedia.getImage(context, uri, trackIndex)
if (bitmap == null) {
callback.onLoadFailed(Exception("null bitmap"))
} else {

View file

@ -16,17 +16,17 @@ object MultiTrackMedia {
private val LOG_TAG = LogUtils.createTag(MultiTrackMedia::class.java)
@RequiresApi(Build.VERSION_CODES.P)
fun getImage(context: Context, uri: Uri, trackId: Int?): Bitmap? {
fun getImage(context: Context, uri: Uri, trackIndex: Int?): Bitmap? {
val retriever = StorageUtils.openMetadataRetriever(context, uri) ?: return null
try {
return if (trackId != null) {
val imageIndex = trackIdToImageIndex(context, uri, trackId) ?: return null
return if (trackIndex != null) {
val imageIndex = trackIndexToImageIndex(context, uri, trackIndex) ?: return null
retriever.getImageAtIndex(imageIndex)
} else {
retriever.primaryImage
}
} catch (e: Exception) {
Log.w(LOG_TAG, "failed to extract image from uri=$uri trackId=$trackId", e)
Log.w(LOG_TAG, "failed to extract image from uri=$uri trackIndex=$trackIndex", e)
} finally {
// cannot rely on `MediaMetadataRetriever` being `AutoCloseable` on older APIs
retriever.release()
@ -34,7 +34,7 @@ object MultiTrackMedia {
return null
}
private fun trackIdToImageIndex(context: Context, uri: Uri, trackId: Int): Int? {
private fun trackIndexToImageIndex(context: Context, uri: Uri, trackIndex: Int): Int? {
val extractor = MediaExtractor()
try {
extractor.setDataSource(context, uri, null)
@ -42,7 +42,7 @@ object MultiTrackMedia {
var imageIndex = 0
for (i in 0 until trackCount) {
val trackFormat = extractor.getTrackFormat(i)
if (trackId == trackFormat.getInteger(MediaFormat.KEY_TRACK_ID)) {
if (trackIndex == i) {
return imageIndex
}
if (MimeTypes.isImage(trackFormat.getString(MediaFormat.KEY_MIME))) {
@ -50,7 +50,7 @@ object MultiTrackMedia {
}
}
} catch (e: Exception) {
Log.w(LOG_TAG, "failed to get image index for uri=$uri, trackId=$trackId", e)
Log.w(LOG_TAG, "failed to get image index for uri=$uri, trackIndex=$trackIndex", e)
} finally {
extractor.release()
}

View file

@ -1,6 +1,6 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = '1.4.30'
ext.kotlin_version = '1.4.31'
repositories {
google()
mavenCentral()

View file

@ -71,7 +71,7 @@ class SinglePageInfo implements Comparable<SinglePageInfo> {
final index = map['page'] as int;
return SinglePageInfo(
index: index,
pageId: map['trackId'] as int ?? index,
pageId: index,
mimeType: map['mimeType'] as String,
isDefault: map['isDefault'] as bool ?? false,
width: map['width'] as int ?? 0,