changed media retriever failure handling

This commit is contained in:
Thibault Deckers 2020-09-18 15:35:57 +09:00
parent 2fc15a126b
commit fe12767b4a
4 changed files with 116 additions and 107 deletions

View file

@ -199,27 +199,29 @@ public class MetadataHandler implements MethodChannel.MethodCallHandler {
private Map<String, String> getVideoAllMetadataByMediaMetadataRetriever(String uri) {
Map<String, String> dirMap = new HashMap<>();
MediaMetadataRetriever retriever = StorageUtils.openMetadataRetriever(context, Uri.parse(uri));
try {
for (Map.Entry<Integer, String> kv : VIDEO_MEDIA_METADATA_KEYS.entrySet()) {
Integer key = kv.getKey();
String value = retriever.extractMetadata(key);
if (value != null) {
switch (key) {
case MediaMetadataRetriever.METADATA_KEY_BITRATE:
value = Formatter.formatFileSize(context, Long.parseLong(value)) + "/sec";
break;
case MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION:
value += "°";
break;
if (retriever != null) {
try {
for (Map.Entry<Integer, String> kv : VIDEO_MEDIA_METADATA_KEYS.entrySet()) {
Integer key = kv.getKey();
String value = retriever.extractMetadata(key);
if (value != null) {
switch (key) {
case MediaMetadataRetriever.METADATA_KEY_BITRATE:
value = Formatter.formatFileSize(context, Long.parseLong(value)) + "/sec";
break;
case MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION:
value += "°";
break;
}
dirMap.put(kv.getValue(), value);
}
dirMap.put(kv.getValue(), value);
}
} catch (Exception e) {
Log.w(LOG_TAG, "failed to get video metadata by MediaMetadataRetriever for uri=" + uri, e);
} finally {
// cannot rely on `MediaMetadataRetriever` being `AutoCloseable` on older APIs
retriever.release();
}
} catch (Exception e) {
Log.w(LOG_TAG, "failed to get video metadata by MediaMetadataRetriever for uri=" + uri, e);
} finally {
// cannot rely on `MediaMetadataRetriever` being `AutoCloseable` on older APIs
retriever.release();
}
return dirMap;
}
@ -317,45 +319,47 @@ public class MetadataHandler implements MethodChannel.MethodCallHandler {
private Map<String, Object> getVideoCatalogMetadataByMediaMetadataRetriever(String uri) {
Map<String, Object> metadataMap = new HashMap<>();
MediaMetadataRetriever retriever = StorageUtils.openMetadataRetriever(context, Uri.parse(uri));
try {
String dateString = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DATE);
String rotationString = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION);
String locationString = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_LOCATION);
if (retriever != null) {
try {
String dateString = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DATE);
String rotationString = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION);
String locationString = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_LOCATION);
if (dateString != null) {
long dateMillis = MetadataHelper.parseVideoMetadataDate(dateString);
// some entries have an invalid default date (19040101T000000.000Z) that is before Epoch time
if (dateMillis > 0) {
metadataMap.put(KEY_DATE_MILLIS, dateMillis);
if (dateString != null) {
long dateMillis = MetadataHelper.parseVideoMetadataDate(dateString);
// some entries have an invalid default date (19040101T000000.000Z) that is before Epoch time
if (dateMillis > 0) {
metadataMap.put(KEY_DATE_MILLIS, dateMillis);
}
}
}
if (rotationString != null) {
metadataMap.put(KEY_VIDEO_ROTATION, Integer.parseInt(rotationString));
}
if (locationString != null) {
Matcher locationMatcher = VIDEO_LOCATION_PATTERN.matcher(locationString);
if (locationMatcher.find() && locationMatcher.groupCount() >= 2) {
String latitudeString = locationMatcher.group(1);
String longitudeString = locationMatcher.group(2);
if (latitudeString != null && longitudeString != null) {
try {
double latitude = Double.parseDouble(latitudeString);
double longitude = Double.parseDouble(longitudeString);
if (latitude != 0 && longitude != 0) {
metadataMap.put(KEY_LATITUDE, latitude);
metadataMap.put(KEY_LONGITUDE, longitude);
if (rotationString != null) {
metadataMap.put(KEY_VIDEO_ROTATION, Integer.parseInt(rotationString));
}
if (locationString != null) {
Matcher locationMatcher = VIDEO_LOCATION_PATTERN.matcher(locationString);
if (locationMatcher.find() && locationMatcher.groupCount() >= 2) {
String latitudeString = locationMatcher.group(1);
String longitudeString = locationMatcher.group(2);
if (latitudeString != null && longitudeString != null) {
try {
double latitude = Double.parseDouble(latitudeString);
double longitude = Double.parseDouble(longitudeString);
if (latitude != 0 && longitude != 0) {
metadataMap.put(KEY_LATITUDE, latitude);
metadataMap.put(KEY_LONGITUDE, longitude);
}
} catch (NumberFormatException ex) {
// ignore
}
} catch (NumberFormatException ex) {
// ignore
}
}
}
} catch (Exception e) {
Log.w(LOG_TAG, "failed to get catalog metadata by MediaMetadataRetriever for uri=" + uri, e);
} finally {
// cannot rely on `MediaMetadataRetriever` being `AutoCloseable` on older APIs
retriever.release();
}
} catch (Exception e) {
Log.w(LOG_TAG, "failed to get catalog metadata by MediaMetadataRetriever for uri=" + uri, e);
} finally {
// cannot rely on `MediaMetadataRetriever` being `AutoCloseable` on older APIs
retriever.release();
}
return metadataMap;
}

View file

@ -25,25 +25,27 @@ class VideoThumbnailFetcher implements DataFetcher<InputStream> {
@Override
public void loadData(@NonNull Priority priority, @NonNull DataCallback<? super InputStream> callback) {
MediaMetadataRetriever retriever = StorageUtils.openMetadataRetriever(model.getContext(), model.getUri());
try {
byte[] picture = retriever.getEmbeddedPicture();
if (picture != null) {
callback.onDataReady(new ByteArrayInputStream(picture));
} else {
// not ideal: bitmap -> byte[] -> bitmap
// but simple fallback and we cache result
ByteArrayOutputStream bos = new ByteArrayOutputStream();
Bitmap bitmap = retriever.getFrameAtTime();
if (bitmap != null) {
bitmap.compress(Bitmap.CompressFormat.PNG, 0, bos);
if (retriever != null) {
try {
byte[] picture = retriever.getEmbeddedPicture();
if (picture != null) {
callback.onDataReady(new ByteArrayInputStream(picture));
} else {
// not ideal: bitmap -> byte[] -> bitmap
// but simple fallback and we cache result
ByteArrayOutputStream bos = new ByteArrayOutputStream();
Bitmap bitmap = retriever.getFrameAtTime();
if (bitmap != null) {
bitmap.compress(Bitmap.CompressFormat.PNG, 0, bos);
}
callback.onDataReady(new ByteArrayInputStream(bos.toByteArray()));
}
callback.onDataReady(new ByteArrayInputStream(bos.toByteArray()));
} catch (Exception ex) {
callback.onLoadFailed(ex);
} finally {
// cannot rely on `MediaMetadataRetriever` being `AutoCloseable` on older APIs
retriever.release();
}
} catch (Exception ex) {
callback.onLoadFailed(ex);
} finally {
// cannot rely on `MediaMetadataRetriever` being `AutoCloseable` on older APIs
retriever.release();
}
}

View file

@ -135,49 +135,51 @@ public class SourceImageEntry {
// finds: width, height, orientation/rotation, date, title, duration
private void fillByMediaMetadataRetriever(@NonNull Context context) {
MediaMetadataRetriever retriever = StorageUtils.openMetadataRetriever(context, uri);
try {
String width = null, height = null, rotation = null, durationMillis = null;
if (isImage()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
width = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_IMAGE_WIDTH);
height = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_IMAGE_HEIGHT);
rotation = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_IMAGE_ROTATION);
if (retriever != null) {
try {
String width = null, height = null, rotation = null, durationMillis = null;
if (isImage()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
width = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_IMAGE_WIDTH);
height = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_IMAGE_HEIGHT);
rotation = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_IMAGE_ROTATION);
}
} else if (isVideo()) {
width = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH);
height = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT);
rotation = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION);
durationMillis = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
}
if (width != null) {
this.width = Integer.parseInt(width);
}
if (height != null) {
this.height = Integer.parseInt(height);
}
if (rotation != null) {
this.orientationDegrees = Integer.parseInt(rotation);
}
if (durationMillis != null) {
this.durationMillis = Long.parseLong(durationMillis);
}
} else if (isVideo()) {
width = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH);
height = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT);
rotation = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION);
durationMillis = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
}
if (width != null) {
this.width = Integer.parseInt(width);
}
if (height != null) {
this.height = Integer.parseInt(height);
}
if (rotation != null) {
this.orientationDegrees = Integer.parseInt(rotation);
}
if (durationMillis != null) {
this.durationMillis = Long.parseLong(durationMillis);
}
String dateString = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DATE);
long dateMillis = MetadataHelper.parseVideoMetadataDate(dateString);
// some entries have an invalid default date (19040101T000000.000Z) that is before Epoch time
if (dateMillis > 0) {
this.sourceDateTakenMillis = dateMillis;
}
String dateString = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DATE);
long dateMillis = MetadataHelper.parseVideoMetadataDate(dateString);
// some entries have an invalid default date (19040101T000000.000Z) that is before Epoch time
if (dateMillis > 0) {
this.sourceDateTakenMillis = dateMillis;
}
String title = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
if (title != null) {
this.title = title;
String title = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
if (title != null) {
this.title = title;
}
} catch (Exception e) {
// ignore
} finally {
// cannot rely on `MediaMetadataRetriever` being `AutoCloseable` on older APIs
retriever.release();
}
} catch (Exception e) {
// ignore
} finally {
// cannot rely on `MediaMetadataRetriever` being `AutoCloseable` on older APIs
retriever.release();
}
}

View file

@ -460,7 +460,8 @@ public class StorageUtils {
}
retriever.setDataSource(context, uri);
} catch (Exception e) {
Log.e(LOG_TAG, "failed to open MediaMetadataRetriever for uri=" + uri, e);
// unsupported format
return null;
}
return retriever;
}