changed media retriever failure handling
This commit is contained in:
parent
2fc15a126b
commit
fe12767b4a
4 changed files with 116 additions and 107 deletions
|
@ -199,27 +199,29 @@ public class MetadataHandler implements MethodChannel.MethodCallHandler {
|
||||||
private Map<String, String> getVideoAllMetadataByMediaMetadataRetriever(String uri) {
|
private Map<String, String> getVideoAllMetadataByMediaMetadataRetriever(String uri) {
|
||||||
Map<String, String> dirMap = new HashMap<>();
|
Map<String, String> dirMap = new HashMap<>();
|
||||||
MediaMetadataRetriever retriever = StorageUtils.openMetadataRetriever(context, Uri.parse(uri));
|
MediaMetadataRetriever retriever = StorageUtils.openMetadataRetriever(context, Uri.parse(uri));
|
||||||
try {
|
if (retriever != null) {
|
||||||
for (Map.Entry<Integer, String> kv : VIDEO_MEDIA_METADATA_KEYS.entrySet()) {
|
try {
|
||||||
Integer key = kv.getKey();
|
for (Map.Entry<Integer, String> kv : VIDEO_MEDIA_METADATA_KEYS.entrySet()) {
|
||||||
String value = retriever.extractMetadata(key);
|
Integer key = kv.getKey();
|
||||||
if (value != null) {
|
String value = retriever.extractMetadata(key);
|
||||||
switch (key) {
|
if (value != null) {
|
||||||
case MediaMetadataRetriever.METADATA_KEY_BITRATE:
|
switch (key) {
|
||||||
value = Formatter.formatFileSize(context, Long.parseLong(value)) + "/sec";
|
case MediaMetadataRetriever.METADATA_KEY_BITRATE:
|
||||||
break;
|
value = Formatter.formatFileSize(context, Long.parseLong(value)) + "/sec";
|
||||||
case MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION:
|
break;
|
||||||
value += "°";
|
case MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION:
|
||||||
break;
|
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;
|
return dirMap;
|
||||||
}
|
}
|
||||||
|
@ -317,45 +319,47 @@ public class MetadataHandler implements MethodChannel.MethodCallHandler {
|
||||||
private Map<String, Object> getVideoCatalogMetadataByMediaMetadataRetriever(String uri) {
|
private Map<String, Object> getVideoCatalogMetadataByMediaMetadataRetriever(String uri) {
|
||||||
Map<String, Object> metadataMap = new HashMap<>();
|
Map<String, Object> metadataMap = new HashMap<>();
|
||||||
MediaMetadataRetriever retriever = StorageUtils.openMetadataRetriever(context, Uri.parse(uri));
|
MediaMetadataRetriever retriever = StorageUtils.openMetadataRetriever(context, Uri.parse(uri));
|
||||||
try {
|
if (retriever != null) {
|
||||||
String dateString = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DATE);
|
try {
|
||||||
String rotationString = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION);
|
String dateString = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DATE);
|
||||||
String locationString = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_LOCATION);
|
String rotationString = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION);
|
||||||
|
String locationString = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_LOCATION);
|
||||||
|
|
||||||
if (dateString != null) {
|
if (dateString != null) {
|
||||||
long dateMillis = MetadataHelper.parseVideoMetadataDate(dateString);
|
long dateMillis = MetadataHelper.parseVideoMetadataDate(dateString);
|
||||||
// some entries have an invalid default date (19040101T000000.000Z) that is before Epoch time
|
// some entries have an invalid default date (19040101T000000.000Z) that is before Epoch time
|
||||||
if (dateMillis > 0) {
|
if (dateMillis > 0) {
|
||||||
metadataMap.put(KEY_DATE_MILLIS, dateMillis);
|
metadataMap.put(KEY_DATE_MILLIS, dateMillis);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
if (rotationString != null) {
|
||||||
if (rotationString != null) {
|
metadataMap.put(KEY_VIDEO_ROTATION, Integer.parseInt(rotationString));
|
||||||
metadataMap.put(KEY_VIDEO_ROTATION, Integer.parseInt(rotationString));
|
}
|
||||||
}
|
if (locationString != null) {
|
||||||
if (locationString != null) {
|
Matcher locationMatcher = VIDEO_LOCATION_PATTERN.matcher(locationString);
|
||||||
Matcher locationMatcher = VIDEO_LOCATION_PATTERN.matcher(locationString);
|
if (locationMatcher.find() && locationMatcher.groupCount() >= 2) {
|
||||||
if (locationMatcher.find() && locationMatcher.groupCount() >= 2) {
|
String latitudeString = locationMatcher.group(1);
|
||||||
String latitudeString = locationMatcher.group(1);
|
String longitudeString = locationMatcher.group(2);
|
||||||
String longitudeString = locationMatcher.group(2);
|
if (latitudeString != null && longitudeString != null) {
|
||||||
if (latitudeString != null && longitudeString != null) {
|
try {
|
||||||
try {
|
double latitude = Double.parseDouble(latitudeString);
|
||||||
double latitude = Double.parseDouble(latitudeString);
|
double longitude = Double.parseDouble(longitudeString);
|
||||||
double longitude = Double.parseDouble(longitudeString);
|
if (latitude != 0 && longitude != 0) {
|
||||||
if (latitude != 0 && longitude != 0) {
|
metadataMap.put(KEY_LATITUDE, latitude);
|
||||||
metadataMap.put(KEY_LATITUDE, latitude);
|
metadataMap.put(KEY_LONGITUDE, longitude);
|
||||||
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;
|
return metadataMap;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,25 +25,27 @@ class VideoThumbnailFetcher implements DataFetcher<InputStream> {
|
||||||
@Override
|
@Override
|
||||||
public void loadData(@NonNull Priority priority, @NonNull DataCallback<? super InputStream> callback) {
|
public void loadData(@NonNull Priority priority, @NonNull DataCallback<? super InputStream> callback) {
|
||||||
MediaMetadataRetriever retriever = StorageUtils.openMetadataRetriever(model.getContext(), model.getUri());
|
MediaMetadataRetriever retriever = StorageUtils.openMetadataRetriever(model.getContext(), model.getUri());
|
||||||
try {
|
if (retriever != null) {
|
||||||
byte[] picture = retriever.getEmbeddedPicture();
|
try {
|
||||||
if (picture != null) {
|
byte[] picture = retriever.getEmbeddedPicture();
|
||||||
callback.onDataReady(new ByteArrayInputStream(picture));
|
if (picture != null) {
|
||||||
} else {
|
callback.onDataReady(new ByteArrayInputStream(picture));
|
||||||
// not ideal: bitmap -> byte[] -> bitmap
|
} else {
|
||||||
// but simple fallback and we cache result
|
// not ideal: bitmap -> byte[] -> bitmap
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
// but simple fallback and we cache result
|
||||||
Bitmap bitmap = retriever.getFrameAtTime();
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
if (bitmap != null) {
|
Bitmap bitmap = retriever.getFrameAtTime();
|
||||||
bitmap.compress(Bitmap.CompressFormat.PNG, 0, bos);
|
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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -135,49 +135,51 @@ public class SourceImageEntry {
|
||||||
// finds: width, height, orientation/rotation, date, title, duration
|
// finds: width, height, orientation/rotation, date, title, duration
|
||||||
private void fillByMediaMetadataRetriever(@NonNull Context context) {
|
private void fillByMediaMetadataRetriever(@NonNull Context context) {
|
||||||
MediaMetadataRetriever retriever = StorageUtils.openMetadataRetriever(context, uri);
|
MediaMetadataRetriever retriever = StorageUtils.openMetadataRetriever(context, uri);
|
||||||
try {
|
if (retriever != null) {
|
||||||
String width = null, height = null, rotation = null, durationMillis = null;
|
try {
|
||||||
if (isImage()) {
|
String width = null, height = null, rotation = null, durationMillis = null;
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
if (isImage()) {
|
||||||
width = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_IMAGE_WIDTH);
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||||
height = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_IMAGE_HEIGHT);
|
width = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_IMAGE_WIDTH);
|
||||||
rotation = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_IMAGE_ROTATION);
|
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);
|
String dateString = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DATE);
|
||||||
long dateMillis = MetadataHelper.parseVideoMetadataDate(dateString);
|
long dateMillis = MetadataHelper.parseVideoMetadataDate(dateString);
|
||||||
// some entries have an invalid default date (19040101T000000.000Z) that is before Epoch time
|
// some entries have an invalid default date (19040101T000000.000Z) that is before Epoch time
|
||||||
if (dateMillis > 0) {
|
if (dateMillis > 0) {
|
||||||
this.sourceDateTakenMillis = dateMillis;
|
this.sourceDateTakenMillis = dateMillis;
|
||||||
}
|
}
|
||||||
|
|
||||||
String title = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
|
String title = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
|
||||||
if (title != null) {
|
if (title != null) {
|
||||||
this.title = title;
|
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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -460,7 +460,8 @@ public class StorageUtils {
|
||||||
}
|
}
|
||||||
retriever.setDataSource(context, uri);
|
retriever.setDataSource(context, uri);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e(LOG_TAG, "failed to open MediaMetadataRetriever for uri=" + uri, e);
|
// unsupported format
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
return retriever;
|
return retriever;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue