From 2cc0a2eca995b5f5d1ebe193a34f880439fb62ec Mon Sep 17 00:00:00 2001 From: Chong Zhang Date: Wed, 4 Apr 2018 13:35:59 -0700 Subject: [PATCH] Extract exif data from mp4 extractor if available Query the extractor for the exif data offset and length, if it's available, read the exif block from the file. Otherwise, set image dimension and rotation only. bug: 76149934 Change-Id: I85f24b526fb356a9227941e20807fc96369c8536 --- media/java/android/media/ExifInterface.java | 92 ++++++++++++++-------- .../java/android/media/MediaMetadataRetriever.java | 9 +++ 2 files changed, 67 insertions(+), 34 deletions(-) diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java index bc0e43b5e9c6..78884367e3f8 100644 --- a/media/java/android/media/ExifInterface.java +++ b/media/java/android/media/ExifInterface.java @@ -66,7 +66,7 @@ import libcore.io.Streams; /** * This is a class for reading and writing Exif tags in a JPEG file or a RAW image file. *

- * Supported formats are: JPEG, DNG, CR2, NEF, NRW, ARW, RW2, ORF, PEF, SRW and RAF. + * Supported formats are: JPEG, DNG, CR2, NEF, NRW, ARW, RW2, ORF, PEF, SRW, RAF and HEIF. *

* Attribute mutation is supported for JPEG image files. */ @@ -2524,46 +2524,46 @@ public class ExifInterface { private void getHeifAttributes(ByteOrderedDataInputStream in) throws IOException { MediaMetadataRetriever retriever = new MediaMetadataRetriever(); try { - if (mSeekableFileDescriptor != null) { - retriever.setDataSource(mSeekableFileDescriptor); - } else { - retriever.setDataSource(new MediaDataSource() { - long mPosition; - - @Override - public void close() throws IOException {} + retriever.setDataSource(new MediaDataSource() { + long mPosition; - @Override - public int readAt(long position, byte[] buffer, int offset, int size) - throws IOException { - if (size == 0) { - return 0; - } - if (position < 0) { - return -1; - } - if (mPosition != position) { - in.seek(position); - mPosition = position; - } + @Override + public void close() throws IOException {} - int bytesRead = in.read(buffer, offset, size); - if (bytesRead < 0) { - mPosition = -1; // need to seek on next read - return -1; - } - - mPosition += bytesRead; - return bytesRead; + @Override + public int readAt(long position, byte[] buffer, int offset, int size) + throws IOException { + if (size == 0) { + return 0; + } + if (position < 0) { + return -1; + } + if (mPosition != position) { + in.seek(position); + mPosition = position; } - @Override - public long getSize() throws IOException { + int bytesRead = in.read(buffer, offset, size); + if (bytesRead < 0) { + mPosition = -1; // need to seek on next read return -1; } - }); - } + mPosition += bytesRead; + return bytesRead; + } + + @Override + public long getSize() throws IOException { + return -1; + } + }); + + String exifOffsetStr = retriever.extractMetadata( + MediaMetadataRetriever.METADATA_KEY_EXIF_OFFSET); + String exifLengthStr = retriever.extractMetadata( + MediaMetadataRetriever.METADATA_KEY_EXIF_LENGTH); String hasImage = retriever.extractMetadata( MediaMetadataRetriever.METADATA_KEY_HAS_IMAGE); String hasVideo = retriever.extractMetadata( @@ -2622,6 +2622,30 @@ public class ExifInterface { ExifAttribute.createUShort(orientation, mExifByteOrder)); } + if (exifOffsetStr != null && exifLengthStr != null) { + int offset = Integer.parseInt(exifOffsetStr); + int length = Integer.parseInt(exifLengthStr); + if (length <= 6) { + throw new IOException("Invalid exif length"); + } + in.seek(offset); + byte[] identifier = new byte[6]; + if (in.read(identifier) != 6) { + throw new IOException("Can't read identifier"); + } + offset += 6; + length -= 6; + if (!Arrays.equals(identifier, IDENTIFIER_EXIF_APP1)) { + throw new IOException("Invalid identifier"); + } + + byte[] bytes = new byte[length]; + if (in.read(bytes) != length) { + throw new IOException("Can't read exif"); + } + readExifSegment(bytes, IFD_TYPE_PRIMARY); + } + if (DEBUG) { Log.d(TAG, "Heif meta: " + width + "x" + height + ", rotation " + rotation); } diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java index 0955dd633c1c..8ab5ec447cf9 100644 --- a/media/java/android/media/MediaMetadataRetriever.java +++ b/media/java/android/media/MediaMetadataRetriever.java @@ -890,5 +890,14 @@ public class MediaMetadataRetriever */ public static final int METADATA_KEY_VIDEO_FRAME_COUNT = 32; + /** + * @hide + */ + public static final int METADATA_KEY_EXIF_OFFSET = 33; + + /** + * @hide + */ + public static final int METADATA_KEY_EXIF_LENGTH = 34; // Add more here... } -- 2.11.0