From fe12767b4a05ab5f9f148cda76f5bb029b092239 Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Fri, 18 Sep 2020 15:35:57 +0900 Subject: [PATCH] changed media retriever failure handling --- .../aves/channel/calls/MetadataHandler.java | 104 +++++++++--------- .../aves/decoder/VideoThumbnailFetcher.java | 36 +++--- .../thibault/aves/model/SourceImageEntry.java | 80 +++++++------- .../thibault/aves/utils/StorageUtils.java | 3 +- 4 files changed, 116 insertions(+), 107 deletions(-) diff --git a/android/app/src/main/java/deckers/thibault/aves/channel/calls/MetadataHandler.java b/android/app/src/main/java/deckers/thibault/aves/channel/calls/MetadataHandler.java index ae91abfe2..5dd54d6d3 100644 --- a/android/app/src/main/java/deckers/thibault/aves/channel/calls/MetadataHandler.java +++ b/android/app/src/main/java/deckers/thibault/aves/channel/calls/MetadataHandler.java @@ -199,27 +199,29 @@ public class MetadataHandler implements MethodChannel.MethodCallHandler { private Map getVideoAllMetadataByMediaMetadataRetriever(String uri) { Map dirMap = new HashMap<>(); MediaMetadataRetriever retriever = StorageUtils.openMetadataRetriever(context, Uri.parse(uri)); - try { - for (Map.Entry 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 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 getVideoCatalogMetadataByMediaMetadataRetriever(String uri) { Map 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; } diff --git a/android/app/src/main/java/deckers/thibault/aves/decoder/VideoThumbnailFetcher.java b/android/app/src/main/java/deckers/thibault/aves/decoder/VideoThumbnailFetcher.java index 111d6468e..8ee573f45 100644 --- a/android/app/src/main/java/deckers/thibault/aves/decoder/VideoThumbnailFetcher.java +++ b/android/app/src/main/java/deckers/thibault/aves/decoder/VideoThumbnailFetcher.java @@ -25,25 +25,27 @@ class VideoThumbnailFetcher implements DataFetcher { @Override public void loadData(@NonNull Priority priority, @NonNull DataCallback 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(); } } diff --git a/android/app/src/main/java/deckers/thibault/aves/model/SourceImageEntry.java b/android/app/src/main/java/deckers/thibault/aves/model/SourceImageEntry.java index e8bba04fa..50efa6b54 100644 --- a/android/app/src/main/java/deckers/thibault/aves/model/SourceImageEntry.java +++ b/android/app/src/main/java/deckers/thibault/aves/model/SourceImageEntry.java @@ -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(); } } diff --git a/android/app/src/main/java/deckers/thibault/aves/utils/StorageUtils.java b/android/app/src/main/java/deckers/thibault/aves/utils/StorageUtils.java index b0a814ab3..e2ec2986f 100644 --- a/android/app/src/main/java/deckers/thibault/aves/utils/StorageUtils.java +++ b/android/app/src/main/java/deckers/thibault/aves/utils/StorageUtils.java @@ -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; }