~xdavidwu/saf-cephfs

4b8fc7ca6136d559dde5e4b1ea0d7321a60f242e — xdavidwu 2 years ago 5c540f7
DocumentsProvider: add video metadata support
M src/main/java/org/safcephfs/CephFSDocumentsProvider.java => src/main/java/org/safcephfs/CephFSDocumentsProvider.java +25 -13
@@ 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)

A src/main/java/org/safcephfs/MediaMetadataReader.java => src/main/java/org/safcephfs/MediaMetadataReader.java +65 -0
@@ 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<Integer, String> NAME_MAPPING = new HashMap<>();

	private static final int TYPE_INT = 0;

	private static final Map<Integer, Integer> 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);
	}
}