Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4342f08f authored by Chong Zhang's avatar Chong Zhang
Browse files

heif: support heif image sequence and dual-function files

- Add a few methods to MediaMetadataRetriever to get still
  images and frames by index.

- Declare keys in MediaFormat related to heif still images.

bug: 63633199

test:
cts-tradefed run cts-dev --module CtsMediaTestCases --compatibility:module-arg CtsMediaTestCases:include-annotation:android.platform.test.annotations.RequiresDevice

Change-Id: I9556b27f7395a163aadd01e979930061878994d0
parent 0e0621a4
Loading
Loading
Loading
Loading
+16 −1
Original line number Diff line number Diff line
@@ -22779,6 +22779,10 @@ package android.media {
    field public static final java.lang.String KEY_DURATION = "durationUs";
    field public static final java.lang.String KEY_FLAC_COMPRESSION_LEVEL = "flac-compression-level";
    field public static final java.lang.String KEY_FRAME_RATE = "frame-rate";
    field public static final java.lang.String KEY_GRID_COLS = "grid-cols";
    field public static final java.lang.String KEY_GRID_HEIGHT = "grid-height";
    field public static final java.lang.String KEY_GRID_ROWS = "grid-rows";
    field public static final java.lang.String KEY_GRID_WIDTH = "grid-width";
    field public static final java.lang.String KEY_HDR_STATIC_INFO = "hdr-static-info";
    field public static final java.lang.String KEY_HEIGHT = "height";
    field public static final java.lang.String KEY_INTRA_REFRESH_PERIOD = "intra-refresh-period";
@@ -22822,6 +22826,7 @@ package android.media {
    field public static final java.lang.String MIMETYPE_AUDIO_RAW = "audio/raw";
    field public static final java.lang.String MIMETYPE_AUDIO_SCRAMBLED = "audio/scrambled";
    field public static final java.lang.String MIMETYPE_AUDIO_VORBIS = "audio/vorbis";
    field public static final java.lang.String MIMETYPE_IMAGE_ANDROID_HEIC = "image/vnd.android.heic";
    field public static final java.lang.String MIMETYPE_TEXT_CEA_608 = "text/cea-608";
    field public static final java.lang.String MIMETYPE_TEXT_VTT = "text/vtt";
    field public static final java.lang.String MIMETYPE_VIDEO_AVC = "video/avc";
@@ -22914,9 +22919,13 @@ package android.media {
    ctor public MediaMetadataRetriever();
    method public java.lang.String extractMetadata(int);
    method public byte[] getEmbeddedPicture();
    method public android.graphics.Bitmap getFrameAtIndex(int);
    method public android.graphics.Bitmap getFrameAtTime(long, int);
    method public android.graphics.Bitmap getFrameAtTime(long);
    method public android.graphics.Bitmap getFrameAtTime();
    method public android.graphics.Bitmap[] getFramesAtIndex(int, int);
    method public android.graphics.Bitmap getImageAtIndex(int);
    method public android.graphics.Bitmap getPrimaryImage();
    method public android.graphics.Bitmap getScaledFrameAtTime(long, int, int, int);
    method public void release();
    method public void setDataSource(java.lang.String) throws java.lang.IllegalArgumentException;
@@ -22939,11 +22948,18 @@ package android.media {
    field public static final int METADATA_KEY_DURATION = 9; // 0x9
    field public static final int METADATA_KEY_GENRE = 6; // 0x6
    field public static final int METADATA_KEY_HAS_AUDIO = 16; // 0x10
    field public static final int METADATA_KEY_HAS_IMAGE = 26; // 0x1a
    field public static final int METADATA_KEY_HAS_VIDEO = 17; // 0x11
    field public static final int METADATA_KEY_IMAGE_COUNT = 27; // 0x1b
    field public static final int METADATA_KEY_IMAGE_HEIGHT = 30; // 0x1e
    field public static final int METADATA_KEY_IMAGE_PRIMARY = 28; // 0x1c
    field public static final int METADATA_KEY_IMAGE_ROTATION = 31; // 0x1f
    field public static final int METADATA_KEY_IMAGE_WIDTH = 29; // 0x1d
    field public static final int METADATA_KEY_LOCATION = 23; // 0x17
    field public static final int METADATA_KEY_MIMETYPE = 12; // 0xc
    field public static final int METADATA_KEY_NUM_TRACKS = 10; // 0xa
    field public static final int METADATA_KEY_TITLE = 7; // 0x7
    field public static final int METADATA_KEY_VIDEO_FRAME_COUNT = 32; // 0x20
    field public static final int METADATA_KEY_VIDEO_HEIGHT = 19; // 0x13
    field public static final int METADATA_KEY_VIDEO_ROTATION = 24; // 0x18
    field public static final int METADATA_KEY_VIDEO_WIDTH = 18; // 0x12
@@ -52074,7 +52090,6 @@ package android.widget {
    method public android.graphics.Typeface getTypeface();
    method public android.text.style.URLSpan[] getUrls();
    method public boolean hasSelection();
    method public void invalidate(int, int, int, int);
    method public boolean isAllCaps();
    method public boolean isCursorVisible();
    method public boolean isElegantTextHeight();
+16 −1
Original line number Diff line number Diff line
@@ -24669,6 +24669,10 @@ package android.media {
    field public static final java.lang.String KEY_DURATION = "durationUs";
    field public static final java.lang.String KEY_FLAC_COMPRESSION_LEVEL = "flac-compression-level";
    field public static final java.lang.String KEY_FRAME_RATE = "frame-rate";
    field public static final java.lang.String KEY_GRID_COLS = "grid-cols";
    field public static final java.lang.String KEY_GRID_HEIGHT = "grid-height";
    field public static final java.lang.String KEY_GRID_ROWS = "grid-rows";
    field public static final java.lang.String KEY_GRID_WIDTH = "grid-width";
    field public static final java.lang.String KEY_HDR_STATIC_INFO = "hdr-static-info";
    field public static final java.lang.String KEY_HEIGHT = "height";
    field public static final java.lang.String KEY_INTRA_REFRESH_PERIOD = "intra-refresh-period";
@@ -24712,6 +24716,7 @@ package android.media {
    field public static final java.lang.String MIMETYPE_AUDIO_RAW = "audio/raw";
    field public static final java.lang.String MIMETYPE_AUDIO_SCRAMBLED = "audio/scrambled";
    field public static final java.lang.String MIMETYPE_AUDIO_VORBIS = "audio/vorbis";
    field public static final java.lang.String MIMETYPE_IMAGE_ANDROID_HEIC = "image/vnd.android.heic";
    field public static final java.lang.String MIMETYPE_TEXT_CEA_608 = "text/cea-608";
    field public static final java.lang.String MIMETYPE_TEXT_VTT = "text/vtt";
    field public static final java.lang.String MIMETYPE_VIDEO_AVC = "video/avc";
@@ -24804,9 +24809,13 @@ package android.media {
    ctor public MediaMetadataRetriever();
    method public java.lang.String extractMetadata(int);
    method public byte[] getEmbeddedPicture();
    method public android.graphics.Bitmap getFrameAtIndex(int);
    method public android.graphics.Bitmap getFrameAtTime(long, int);
    method public android.graphics.Bitmap getFrameAtTime(long);
    method public android.graphics.Bitmap getFrameAtTime();
    method public android.graphics.Bitmap[] getFramesAtIndex(int, int);
    method public android.graphics.Bitmap getImageAtIndex(int);
    method public android.graphics.Bitmap getPrimaryImage();
    method public android.graphics.Bitmap getScaledFrameAtTime(long, int, int, int);
    method public void release();
    method public void setDataSource(java.lang.String) throws java.lang.IllegalArgumentException;
@@ -24829,11 +24838,18 @@ package android.media {
    field public static final int METADATA_KEY_DURATION = 9; // 0x9
    field public static final int METADATA_KEY_GENRE = 6; // 0x6
    field public static final int METADATA_KEY_HAS_AUDIO = 16; // 0x10
    field public static final int METADATA_KEY_HAS_IMAGE = 26; // 0x1a
    field public static final int METADATA_KEY_HAS_VIDEO = 17; // 0x11
    field public static final int METADATA_KEY_IMAGE_COUNT = 27; // 0x1b
    field public static final int METADATA_KEY_IMAGE_HEIGHT = 30; // 0x1e
    field public static final int METADATA_KEY_IMAGE_PRIMARY = 28; // 0x1c
    field public static final int METADATA_KEY_IMAGE_ROTATION = 31; // 0x1f
    field public static final int METADATA_KEY_IMAGE_WIDTH = 29; // 0x1d
    field public static final int METADATA_KEY_LOCATION = 23; // 0x17
    field public static final int METADATA_KEY_MIMETYPE = 12; // 0xc
    field public static final int METADATA_KEY_NUM_TRACKS = 10; // 0xa
    field public static final int METADATA_KEY_TITLE = 7; // 0x7
    field public static final int METADATA_KEY_VIDEO_FRAME_COUNT = 32; // 0x20
    field public static final int METADATA_KEY_VIDEO_HEIGHT = 19; // 0x13
    field public static final int METADATA_KEY_VIDEO_ROTATION = 24; // 0x18
    field public static final int METADATA_KEY_VIDEO_WIDTH = 18; // 0x12
@@ -56178,7 +56194,6 @@ package android.widget {
    method public android.graphics.Typeface getTypeface();
    method public android.text.style.URLSpan[] getUrls();
    method public boolean hasSelection();
    method public void invalidate(int, int, int, int);
    method public boolean isAllCaps();
    method public boolean isCursorVisible();
    method public boolean isElegantTextHeight();
+16 −1
Original line number Diff line number Diff line
@@ -22979,6 +22979,10 @@ package android.media {
    field public static final java.lang.String KEY_DURATION = "durationUs";
    field public static final java.lang.String KEY_FLAC_COMPRESSION_LEVEL = "flac-compression-level";
    field public static final java.lang.String KEY_FRAME_RATE = "frame-rate";
    field public static final java.lang.String KEY_GRID_COLS = "grid-cols";
    field public static final java.lang.String KEY_GRID_HEIGHT = "grid-height";
    field public static final java.lang.String KEY_GRID_ROWS = "grid-rows";
    field public static final java.lang.String KEY_GRID_WIDTH = "grid-width";
    field public static final java.lang.String KEY_HDR_STATIC_INFO = "hdr-static-info";
    field public static final java.lang.String KEY_HEIGHT = "height";
    field public static final java.lang.String KEY_INTRA_REFRESH_PERIOD = "intra-refresh-period";
@@ -23022,6 +23026,7 @@ package android.media {
    field public static final java.lang.String MIMETYPE_AUDIO_RAW = "audio/raw";
    field public static final java.lang.String MIMETYPE_AUDIO_SCRAMBLED = "audio/scrambled";
    field public static final java.lang.String MIMETYPE_AUDIO_VORBIS = "audio/vorbis";
    field public static final java.lang.String MIMETYPE_IMAGE_ANDROID_HEIC = "image/vnd.android.heic";
    field public static final java.lang.String MIMETYPE_TEXT_CEA_608 = "text/cea-608";
    field public static final java.lang.String MIMETYPE_TEXT_VTT = "text/vtt";
    field public static final java.lang.String MIMETYPE_VIDEO_AVC = "video/avc";
@@ -23114,9 +23119,13 @@ package android.media {
    ctor public MediaMetadataRetriever();
    method public java.lang.String extractMetadata(int);
    method public byte[] getEmbeddedPicture();
    method public android.graphics.Bitmap getFrameAtIndex(int);
    method public android.graphics.Bitmap getFrameAtTime(long, int);
    method public android.graphics.Bitmap getFrameAtTime(long);
    method public android.graphics.Bitmap getFrameAtTime();
    method public android.graphics.Bitmap[] getFramesAtIndex(int, int);
    method public android.graphics.Bitmap getImageAtIndex(int);
    method public android.graphics.Bitmap getPrimaryImage();
    method public android.graphics.Bitmap getScaledFrameAtTime(long, int, int, int);
    method public void release();
    method public void setDataSource(java.lang.String) throws java.lang.IllegalArgumentException;
@@ -23139,11 +23148,18 @@ package android.media {
    field public static final int METADATA_KEY_DURATION = 9; // 0x9
    field public static final int METADATA_KEY_GENRE = 6; // 0x6
    field public static final int METADATA_KEY_HAS_AUDIO = 16; // 0x10
    field public static final int METADATA_KEY_HAS_IMAGE = 26; // 0x1a
    field public static final int METADATA_KEY_HAS_VIDEO = 17; // 0x11
    field public static final int METADATA_KEY_IMAGE_COUNT = 27; // 0x1b
    field public static final int METADATA_KEY_IMAGE_HEIGHT = 30; // 0x1e
    field public static final int METADATA_KEY_IMAGE_PRIMARY = 28; // 0x1c
    field public static final int METADATA_KEY_IMAGE_ROTATION = 31; // 0x1f
    field public static final int METADATA_KEY_IMAGE_WIDTH = 29; // 0x1d
    field public static final int METADATA_KEY_LOCATION = 23; // 0x17
    field public static final int METADATA_KEY_MIMETYPE = 12; // 0xc
    field public static final int METADATA_KEY_NUM_TRACKS = 10; // 0xa
    field public static final int METADATA_KEY_TITLE = 7; // 0x7
    field public static final int METADATA_KEY_VIDEO_FRAME_COUNT = 32; // 0x20
    field public static final int METADATA_KEY_VIDEO_HEIGHT = 19; // 0x13
    field public static final int METADATA_KEY_VIDEO_ROTATION = 24; // 0x18
    field public static final int METADATA_KEY_VIDEO_WIDTH = 18; // 0x12
@@ -52683,7 +52699,6 @@ package android.widget {
    method public android.graphics.Typeface getTypeface();
    method public android.text.style.URLSpan[] getUrls();
    method public boolean hasSelection();
    method public void invalidate(int, int, int, int);
    method public boolean isAllCaps();
    method public boolean isCursorVisible();
    method public boolean isElegantTextHeight();
+90 −0
Original line number Diff line number Diff line
@@ -96,6 +96,19 @@ import java.util.Map;
 * <tr><td>{@link #KEY_MIME}</td><td>String</td><td>The type of the format.</td></tr>
 * <tr><td>{@link #KEY_LANGUAGE}</td><td>String</td><td>The language of the content.</td></tr>
 * </table>
 *
 * Image formats have the following keys:
 * <table>
 * <tr><td>{@link #KEY_MIME}</td><td>String</td><td>The type of the format.</td></tr>
 * <tr><td>{@link #KEY_WIDTH}</td><td>Integer</td><td></td></tr>
 * <tr><td>{@link #KEY_HEIGHT}</td><td>Integer</td><td></td></tr>
 * <tr><td>{@link #KEY_COLOR_FORMAT}</td><td>Integer</td><td>set by the user
 *         for encoders, readable in the output format of decoders</b></td></tr>
 * <tr><td>{@link #KEY_GRID_WIDTH}</td><td>Integer</td><td>required if the image has grid</td></tr>
 * <tr><td>{@link #KEY_GRID_HEIGHT}</td><td>Integer</td><td>required if the image has grid</td></tr>
 * <tr><td>{@link #KEY_GRID_ROWS}</td><td>Integer</td><td>required if the image has grid</td></tr>
 * <tr><td>{@link #KEY_GRID_COLS}</td><td>Integer</td><td>required if the image has grid</td></tr>
 * </table>
 */
public final class MediaFormat {
    public static final String MIMETYPE_VIDEO_VP8 = "video/x-vnd.on2.vp8";
@@ -125,6 +138,35 @@ public final class MediaFormat {
    public static final String MIMETYPE_AUDIO_EAC3 = "audio/eac3";
    public static final String MIMETYPE_AUDIO_SCRAMBLED = "audio/scrambled";

    /**
     * MIME type for HEIF still image data encoded in HEVC.
     *
     * To decode such an image, {@link MediaCodec} decoder for
     * {@ #MIMETYPE_VIDEO_HEVC} shall be used. The client needs to form
     * the correct {@link #MediaFormat} based on additional information in
     * the track format, and send it to {@link MediaCodec#configure}.
     *
     * The track's MediaFormat will come with {@link #KEY_WIDTH} and
     * {@link #KEY_HEIGHT} keys, which describes the width and height
     * of the image. If the image doesn't contain grid (i.e. none of
     * {@link #KEY_GRID_WIDTH}, {@link #KEY_GRID_HEIGHT},
     * {@link #KEY_GRID_ROWS}, {@link #KEY_GRID_COLS} are present}), the
     * track will contain a single sample of coded data for the entire image,
     * and the image width and height should be used to set up the decoder.
     *
     * If the image does come with grid, each sample from the track will
     * contain one tile in the grid, of which the size is described by
     * {@link #KEY_GRID_WIDTH} and {@link #KEY_GRID_HEIGHT}. This size
     * (instead of {@link #KEY_WIDTH} and {@link #KEY_HEIGHT}) should be
     * used to set up the decoder. The track contains {@link #KEY_GRID_ROWS}
     * by {@link #KEY_GRID_COLS} samples in row-major, top-row first,
     * left-to-right order. The output image should be reconstructed by
     * first tiling the decoding results of the tiles in the correct order,
     * then trimming (before rotation is applied) on the bottom and right
     * side, if the tiled area is larger than the image width and height.
     */
    public static final String MIMETYPE_IMAGE_ANDROID_HEIC = "image/vnd.android.heic";

    /**
     * MIME type for WebVTT subtitle data.
     */
@@ -231,6 +273,54 @@ public final class MediaFormat {
     */
    public static final String KEY_FRAME_RATE = "frame-rate";

    /**
     * A key describing the grid width of the content in a {@link #MIMETYPE_IMAGE_ANDROID_HEIC}
     * track. The associated value is an integer.
     *
     * Refer to {@link #MIMETYPE_IMAGE_ANDROID_HEIC} on decoding instructions of such tracks.
     *
     * @see #KEY_GRID_HEIGHT
     * @see #KEY_GRID_ROWS
     * @see #KEY_GRID_COLS
     */
    public static final String KEY_GRID_WIDTH = "grid-width";

    /**
     * A key describing the grid height of the content in a {@link #MIMETYPE_IMAGE_ANDROID_HEIC}
     * track. The associated value is an integer.
     *
     * Refer to {@link #MIMETYPE_IMAGE_ANDROID_HEIC} on decoding instructions of such tracks.
     *
     * @see #KEY_GRID_WIDTH
     * @see #KEY_GRID_ROWS
     * @see #KEY_GRID_COLS
     */
    public static final String KEY_GRID_HEIGHT = "grid-height";

    /**
     * A key describing the number of grid rows in the content in a
     * {@link #MIMETYPE_IMAGE_ANDROID_HEIC} track. The associated value is an integer.
     *
     * Refer to {@link #MIMETYPE_IMAGE_ANDROID_HEIC} on decoding instructions of such tracks.
     *
     * @see #KEY_GRID_WIDTH
     * @see #KEY_GRID_HEIGHT
     * @see #KEY_GRID_COLS
     */
    public static final String KEY_GRID_ROWS = "grid-rows";

    /**
     * A key describing the number of grid columns in the content in a
     * {@link #MIMETYPE_IMAGE_ANDROID_HEIC} track. The associated value is an integer.
     *
     * Refer to {@link #MIMETYPE_IMAGE_ANDROID_HEIC} on decoding instructions of such tracks.
     *
     * @see #KEY_GRID_WIDTH
     * @see #KEY_GRID_HEIGHT
     * @see #KEY_GRID_ROWS
     */
    public static final String KEY_GRID_COLS = "grid-cols";

    /**
     * A key describing the raw audio sample encoding/format.
     *
+150 −12
Original line number Diff line number Diff line
@@ -356,6 +356,109 @@ public class MediaMetadataRetriever

    private native Bitmap _getFrameAtTime(long timeUs, int option, int width, int height);

    /**
     * This method retrieves a video frame by its index. It should only be called
     * after {@link #setDataSource}.
     *
     * @param frameIndex 0-based index of the video frame. The frame index must be that of
     *        a valid frame. The total number of frames available for retrieval can be queried
     *        via the {@link #METADATA_KEY_VIDEO_FRAME_COUNT} key.
     *
     * @throws IllegalStateException if the container doesn't contain video or image sequences.
     * @throws IllegalArgumentException if the requested frame index does not exist.
     *
     * @return A Bitmap containing the requested video frame, or null if the retrieval fails.
     *
     * @see #getFramesAtIndex(int, int)
     */
    public Bitmap getFrameAtIndex(int frameIndex) {
        Bitmap[] bitmaps = getFramesAtIndex(frameIndex, 1);
        if (bitmaps == null || bitmaps.length < 1) {
            return null;
        }
        return bitmaps[0];
    }

    /**
     * This method retrieves a consecutive set of video frames starting at the
     * specified index. It should only be called after {@link #setDataSource}.
     *
     * If the caller intends to retrieve more than one consecutive video frames,
     * this method is preferred over {@link #getFrameAtIndex(int)} for efficiency.
     *
     * @param frameIndex 0-based index of the first video frame to retrieve. The frame index
     *        must be that of a valid frame. The total number of frames available for retrieval
     *        can be queried via the {@link #METADATA_KEY_VIDEO_FRAME_COUNT} key.
     * @param numFrames number of consecutive video frames to retrieve. Must be a positive
     *        value. The stream must contain at least numFrames frames starting at frameIndex.
     *
     * @throws IllegalStateException if the container doesn't contain video or image sequences.
     * @throws IllegalArgumentException if the frameIndex or numFrames is invalid, or the
     *         stream doesn't contain at least numFrames starting at frameIndex.

     * @return An array of Bitmaps containing the requested video frames. The returned
     *         array could contain less frames than requested if the retrieval fails.
     *
     * @see #getFrameAtIndex(int)
     */
    public Bitmap[] getFramesAtIndex(int frameIndex, int numFrames) {
        if (!"yes".equals(extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_VIDEO))) {
            throw new IllegalStateException("Does not contail video or image sequences");
        }
        int frameCount = Integer.parseInt(
                extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_FRAME_COUNT));
        if (frameIndex < 0 || numFrames < 1
                || frameIndex >= frameCount
                || frameIndex > frameCount - numFrames) {
            throw new IllegalArgumentException("Invalid frameIndex or numFrames: "
                + frameIndex + ", " + numFrames);
        }
        return _getFrameAtIndex(frameIndex, numFrames);
    }
    private native Bitmap[] _getFrameAtIndex(int frameIndex, int numFrames);

    /**
     * This method retrieves a still image by its index. It should only be called
     * after {@link #setDataSource}.
     *
     * @param imageIndex 0-based index of the image, with negative value indicating
     *        the primary image.
     * @throws IllegalStateException if the container doesn't contain still images.
     * @throws IllegalArgumentException if the requested image does not exist.
     *
     * @return the requested still image, or null if the image cannot be retrieved.
     *
     * @see #getPrimaryImage
     */
    public Bitmap getImageAtIndex(int imageIndex) {
        if (!"yes".equals(extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_IMAGE))) {
            throw new IllegalStateException("Does not contail still images");
        }

        String imageCount = extractMetadata(MediaMetadataRetriever.METADATA_KEY_IMAGE_COUNT);
        if (imageIndex >= Integer.parseInt(imageCount)) {
            throw new IllegalArgumentException("Invalid image index: " + imageCount);
        }

        return _getImageAtIndex(imageIndex);
    }

    /**
     * This method retrieves the primary image of the media content. It should only
     * be called after {@link #setDataSource}.
     *
     * @return the primary image, or null if it cannot be retrieved.
     *
     * @throws IllegalStateException if the container doesn't contain still images.
     *
     * @see #getImageAtIndex(int)
     */
    public Bitmap getPrimaryImage() {
        return getImageAtIndex(-1);
    }

    private native Bitmap _getImageAtIndex(int imageIndex);

    /**
     * Call this method after setDataSource(). This method finds the optional
     * graphic or album/cover art associated associated with the data source. If
@@ -572,5 +675,40 @@ public class MediaMetadataRetriever
     * number.
     */
    public static final int METADATA_KEY_CAPTURE_FRAMERATE = 25;
    /**
     * If this key exists the media contains still image content.
     */
    public static final int METADATA_KEY_HAS_IMAGE       = 26;
    /**
     * If the media contains still images, this key retrieves the number
     * of still images.
     */
    public static final int METADATA_KEY_IMAGE_COUNT     = 27;
    /**
     * If the media contains still images, this key retrieves the image
     * index of the primary image.
     */
    public static final int METADATA_KEY_IMAGE_PRIMARY   = 28;
    /**
     * If the media contains still images, this key retrieves the width
     * of the primary image.
     */
    public static final int METADATA_KEY_IMAGE_WIDTH     = 29;
    /**
     * If the media contains still images, this key retrieves the height
     * of the primary image.
     */
    public static final int METADATA_KEY_IMAGE_HEIGHT    = 30;
    /**
     * If the media contains still images, this key retrieves the rotation
     * of the primary image.
     */
    public static final int METADATA_KEY_IMAGE_ROTATION  = 31;
    /**
     * If the media contains video and this key exists, it retrieves the
     * total number of frames in the video sequence.
     */
    public static final int METADATA_KEY_VIDEO_FRAME_COUNT = 32;

    // Add more here...
}
Loading