From 4b8fc7ca6136d559dde5e4b1ea0d7321a60f242e Mon Sep 17 00:00:00 2001 From: xdavidwu Date: Thu, 17 Feb 2022 13:34:22 +0800 Subject: [PATCH] DocumentsProvider: add video metadata support --- .../safcephfs/CephFSDocumentsProvider.java | 38 +++++++---- .../org/safcephfs/MediaMetadataReader.java | 65 +++++++++++++++++++ 2 files changed, 90 insertions(+), 13 deletions(-) create mode 100644 src/main/java/org/safcephfs/MediaMetadataReader.java diff --git a/src/main/java/org/safcephfs/CephFSDocumentsProvider.java b/src/main/java/org/safcephfs/CephFSDocumentsProvider.java index 965c07a..df916e4 100644 --- a/src/main/java/org/safcephfs/CephFSDocumentsProvider.java +++ b/src/main/java/org/safcephfs/CephFSDocumentsProvider.java @@ -343,7 +343,8 @@ public class CephFSDocumentsProvider extends DocumentsProvider { String mimeType = getMime(filename); row.add(Document.COLUMN_MIME_TYPE, mimeType); int flags = 0; - if (MetadataReader.isSupportedMimeType(mimeType) && + if (MetadataReader.isSupportedMimeType(mimeType) || + MediaMetadataReader.isSupportedMimeType(mimeType) && (!checkPermissions || (getPerm(cs) & PERM_READABLE) == PERM_READABLE)) { flags |= Document.FLAG_SUPPORTS_METADATA; @@ -398,21 +399,32 @@ public class CephFSDocumentsProvider extends DocumentsProvider { throws FileNotFoundException { Log.v(APP_NAME, "getDocumentMetadata " + documentId); String mimeType = getDocumentType(documentId); - if (!MetadataReader.isSupportedMimeType(mimeType)) { - return null; - } + if (MetadataReader.isSupportedMimeType(mimeType)) { + ParcelFileDescriptor fd = openDocument(documentId, "r", null); + AutoCloseInputStream stream = new AutoCloseInputStream(fd); - ParcelFileDescriptor fd = openDocument(documentId, "r", null); - AutoCloseInputStream stream = new AutoCloseInputStream(fd); + Bundle metadata = new Bundle(); + try { + MetadataReader.getMetadata(metadata, stream, mimeType, null); + } catch (IOException e) { + Log.e(APP_NAME, "getMetadata: ", e); + return null; + } + return metadata; + } else if (MediaMetadataReader.isSupportedMimeType(mimeType)) { + ParcelFileDescriptor fd = openDocument(documentId, "r", null); - Bundle metadata = new Bundle(); - try { - MetadataReader.getMetadata(metadata, stream, mimeType, null); - } catch (IOException e) { - Log.e(APP_NAME, "getMetadata: ", e); - return null; + Bundle metadata = new Bundle(); + MediaMetadataReader.getMetadata(metadata, fd.getFileDescriptor()); + try { + fd.close(); + } catch (IOException e) { + Log.e(APP_NAME, "getMetadata: video fd close: ", e); + return null; + } + return metadata; } - return metadata; + return null; } public Cursor queryRoots(String[] projection) diff --git a/src/main/java/org/safcephfs/MediaMetadataReader.java b/src/main/java/org/safcephfs/MediaMetadataReader.java new file mode 100644 index 0000000..20b8005 --- /dev/null +++ b/src/main/java/org/safcephfs/MediaMetadataReader.java @@ -0,0 +1,65 @@ +package org.safcephfs; + +import android.media.MediaMetadataRetriever; +import android.media.MediaMetadata; +import android.media.ExifInterface; +import android.os.Bundle; +import android.provider.DocumentsContract; + +import java.io.FileDescriptor; +import java.util.HashMap; +import java.util.Map; + +public final class MediaMetadataReader { + private static final Map NAME_MAPPING = new HashMap<>(); + + private static final int TYPE_INT = 0; + + private static final Map TYPE_MAPPING = new HashMap<>(); + + static { + NAME_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH, ExifInterface.TAG_IMAGE_WIDTH); + TYPE_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH, TYPE_INT); + + NAME_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT, ExifInterface.TAG_IMAGE_LENGTH); + TYPE_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT, TYPE_INT); + + // in ms + NAME_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_DURATION, MediaMetadata.METADATA_KEY_DURATION); + TYPE_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_DURATION, TYPE_INT); + } + + public static final String METADATA_KEY_VIDEO = "android.media.metadata.video"; + + // Not sure what formats MediaMetadataRetriever supports, let's try all videos + public static boolean isSupportedMimeType(String mimeType) { + return mimeType.startsWith("video/"); + } + + public static void getMetadata(Bundle metadata, FileDescriptor fd) { + Bundle videoMetadata = new Bundle(); + MediaMetadataRetriever retriever = new MediaMetadataRetriever(); + retriever.setDataSource(fd); + + for (int key: NAME_MAPPING.keySet()) { + String raw = retriever.extractMetadata(key); + if (raw == null) { + continue; + } + + Integer type = TYPE_MAPPING.get(key); + if (type == null) { + videoMetadata.putString(NAME_MAPPING.get(key), raw); + } else { + switch (type) { + case TYPE_INT: + videoMetadata.putInt(NAME_MAPPING.get(key), Integer.parseInt(raw)); + break; + } + } + } + metadata.putBundle(METADATA_KEY_VIDEO, videoMetadata); + String[] types = {METADATA_KEY_VIDEO}; + metadata.putStringArray(DocumentsContract.METADATA_TYPES, types); + } +} -- 2.43.0