info: improved media descriptions & minor fixes

This commit is contained in:
Thibault Deckers 2020-10-09 13:47:07 +09:00
parent 123a4df495
commit 120f9cd4e4
2 changed files with 74 additions and 16 deletions

View file

@ -7,7 +7,6 @@ import android.media.MediaMetadataRetriever
import android.net.Uri
import android.os.Build
import android.provider.MediaStore
import android.text.format.Formatter
import android.util.Log
import androidx.exifinterface.media.ExifInterface
import com.adobe.internal.xmp.XMPException
@ -28,6 +27,7 @@ import deckers.thibault.aves.utils.*
import deckers.thibault.aves.utils.ExifInterfaceHelper.describeAll
import deckers.thibault.aves.utils.ExifInterfaceHelper.getSafeDateMillis
import deckers.thibault.aves.utils.ExifInterfaceHelper.getSafeInt
import deckers.thibault.aves.utils.MediaMetadataRetrieverHelper.getSafeDescription
import deckers.thibault.aves.utils.MediaMetadataRetrieverHelper.getSafeInt
import deckers.thibault.aves.utils.Metadata.getRotationDegreesForExifCode
import deckers.thibault.aves.utils.Metadata.isFlippedForExifCode
@ -151,17 +151,7 @@ class MetadataHandler(private val context: Context) : MethodCallHandler {
val retriever = StorageUtils.openMetadataRetriever(context, uri) ?: return dirMap
try {
for ((code, name) in MediaMetadataRetrieverHelper.allKeys) {
val value = retriever.extractMetadata(code)
if (value != null) {
when (code) {
MediaMetadataRetriever.METADATA_KEY_BITRATE -> Formatter.formatFileSize(context, value.toLong()) + "/sec"
MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION -> "$value°"
MediaMetadataRetriever.METADATA_KEY_DURATION -> "$value ms"
MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT, MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH -> "$value pixels"
MediaMetadataRetriever.METADATA_KEY_LOCATION, MediaMetadataRetriever.METADATA_KEY_MIMETYPE -> null
else -> value
}?.let { dirMap[name] = it }
}
retriever.getSafeDescription(code, context) { dirMap[name] = it }
}
} catch (e: Exception) {
Log.w(LOG_TAG, "failed to get video metadata by MediaMetadataRetriever for uri=$uri", e)
@ -333,7 +323,8 @@ class MetadataHandler(private val context: Context) : MethodCallHandler {
try {
val latitude = latitudeString.toDoubleOrNull() ?: 0
val longitude = longitudeString.toDoubleOrNull() ?: 0
if (latitude != 0 && longitude != 0) {
// keep `0.0` as `0.0`, not `0`
if (latitude != 0.0 || longitude != 0.0) {
metadataMap[KEY_LATITUDE] = latitude
metadataMap[KEY_LONGITUDE] = longitude
}
@ -379,7 +370,7 @@ class MetadataHandler(private val context: Context) : MethodCallHandler {
val num = it.numerator
val denom = it.denominator
metadataMap[KEY_EXPOSURE_TIME] = when {
num > denom -> it.toSimpleString(true) + ""
num >= denom -> it.toSimpleString(true) + ""
num != 1L && num != 0L -> Rational(1, (denom / num.toDouble()).roundToLong()).toString()
else -> it.toString()
}

View file

@ -1,7 +1,12 @@
package deckers.thibault.aves.utils
import android.content.Context
import android.media.MediaFormat
import android.media.MediaMetadataRetriever
import android.os.Build
import android.text.format.Formatter
import java.text.SimpleDateFormat
import java.util.*
object MediaMetadataRetrieverHelper {
@JvmField
@ -21,8 +26,8 @@ object MediaMetadataRetrieverHelper {
MediaMetadataRetriever.METADATA_KEY_DATE to "Date",
MediaMetadataRetriever.METADATA_KEY_DISC_NUMBER to "Disc Number",
MediaMetadataRetriever.METADATA_KEY_DURATION to "Duration",
MediaMetadataRetriever.METADATA_KEY_EXIF_LENGTH to "EXIF Length",
MediaMetadataRetriever.METADATA_KEY_EXIF_OFFSET to "EXIF Offset",
MediaMetadataRetriever.METADATA_KEY_EXIF_LENGTH to "Exif Length",
MediaMetadataRetriever.METADATA_KEY_EXIF_OFFSET to "Exif Offset",
MediaMetadataRetriever.METADATA_KEY_GENRE to "Genre",
MediaMetadataRetriever.METADATA_KEY_HAS_AUDIO to "Has Audio",
MediaMetadataRetriever.METADATA_KEY_HAS_VIDEO to "Has Video",
@ -49,6 +54,8 @@ object MediaMetadataRetrieverHelper {
}
}
private val durationFormat = SimpleDateFormat("HH:mm:ss.SSS", Locale.ROOT).apply { timeZone = TimeZone.getTimeZone("UTC") }
// extensions
fun MediaMetadataRetriever.getSafeString(tag: Int, save: (value: String) -> Unit) {
@ -72,4 +79,64 @@ object MediaMetadataRetrieverHelper {
// some entries have an invalid default date (19040101T000000.000Z) that is before Epoch time
if (dateMillis > 0) save(dateMillis)
}
fun MediaMetadataRetriever.getSafeDescription(tag: Int, context: Context, save: (value: String) -> Unit) {
val value = this.extractMetadata(tag)
if (value != null) {
when (tag) {
// format
MediaMetadataRetriever.METADATA_KEY_IMAGE_ROTATION,
MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION -> "$value°"
MediaMetadataRetriever.METADATA_KEY_IMAGE_HEIGHT, MediaMetadataRetriever.METADATA_KEY_IMAGE_WIDTH,
MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT, MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH -> "$value pixels"
MediaMetadataRetriever.METADATA_KEY_BITRATE -> {
val bitrate = value.toLongOrNull() ?: 0
if (bitrate > 0) Formatter.formatFileSize(context, bitrate) + "/sec" else null
}
MediaMetadataRetriever.METADATA_KEY_CAPTURE_FRAMERATE -> {
val framerate = value.toDoubleOrNull() ?: 0.0
if (framerate > 0.0) "$framerate" else null
}
MediaMetadataRetriever.METADATA_KEY_DURATION -> {
val dateMillis = value.toLongOrNull() ?: 0
if (dateMillis > 0) durationFormat.format(Date(dateMillis)) else null
}
MediaMetadataRetriever.METADATA_KEY_COLOR_RANGE -> {
when (value.toIntOrNull()) {
MediaFormat.COLOR_RANGE_FULL -> "Full"
MediaFormat.COLOR_RANGE_LIMITED -> "Limited"
else -> value
}
}
MediaMetadataRetriever.METADATA_KEY_COLOR_STANDARD -> {
when (value.toIntOrNull()) {
MediaFormat.COLOR_STANDARD_BT709 -> "BT.709"
MediaFormat.COLOR_STANDARD_BT601_PAL -> "BT.601 625 (PAL)"
MediaFormat.COLOR_STANDARD_BT601_NTSC -> "BT.601 525 (NTSC)"
MediaFormat.COLOR_STANDARD_BT2020 -> "BT.2020"
else -> value
}
}
MediaMetadataRetriever.METADATA_KEY_COLOR_TRANSFER -> {
when (value.toIntOrNull()) {
MediaFormat.COLOR_TRANSFER_LINEAR -> "Linear"
MediaFormat.COLOR_TRANSFER_SDR_VIDEO -> "SMPTE 170M"
MediaFormat.COLOR_TRANSFER_ST2084 -> "SMPTE ST 2084"
MediaFormat.COLOR_TRANSFER_HLG -> "ARIB STD-B67 (HLG)"
else -> value
}
}
// hide `0` values
MediaMetadataRetriever.METADATA_KEY_COMPILATION,
MediaMetadataRetriever.METADATA_KEY_DISC_NUMBER,
MediaMetadataRetriever.METADATA_KEY_YEAR -> if (value != "0") value else null
MediaMetadataRetriever.METADATA_KEY_CD_TRACK_NUMBER -> if (value != "0/0") value else null
// hide
MediaMetadataRetriever.METADATA_KEY_LOCATION,
MediaMetadataRetriever.METADATA_KEY_MIMETYPE -> null
// as is
else -> value
}?.let { save(it) }
}
}
}