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

Commit 26cb5fd5 authored by Igor Murashkin's avatar Igor Murashkin Committed by Android (Google) Code Review
Browse files

Merge "media: Update ImageReader APIs" into klp-dev

parents 311daf20 5e712064
Loading
Loading
Loading
Loading
+14 −7
Original line number Original line Diff line number Diff line
@@ -12334,7 +12334,7 @@ package android.media {
    field public static final int EULER_Z = 2; // 0x2
    field public static final int EULER_Z = 2; // 0x2
  }
  }
  public abstract interface Image implements java.lang.AutoCloseable {
  public abstract class Image implements java.lang.AutoCloseable {
    method public abstract void close();
    method public abstract void close();
    method public abstract int getFormat();
    method public abstract int getFormat();
    method public abstract int getHeight();
    method public abstract int getHeight();
@@ -12343,23 +12343,30 @@ package android.media {
    method public abstract int getWidth();
    method public abstract int getWidth();
  }
  }
  public static abstract interface Image.Plane {
  public static abstract class Image.Plane {
    method public abstract java.nio.ByteBuffer getBuffer();
    method public abstract java.nio.ByteBuffer getBuffer();
    method public abstract int getPixelStride();
    method public abstract int getPixelStride();
    method public abstract int getRowStride();
    method public abstract int getRowStride();
  }
  }
  public final class ImageReader implements java.lang.AutoCloseable {
  public class ImageReader implements java.lang.AutoCloseable {
    ctor public ImageReader(int, int, int, int);
    method public android.media.Image acquireLatestImage() throws android.media.ImageReader.MaxImagesAcquiredException;
    method public android.media.Image acquireNextImage() throws android.media.ImageReader.MaxImagesAcquiredException;
    method public void close();
    method public void close();
    method public int getHeight();
    method public int getHeight();
    method public int getImageFormat();
    method public int getImageFormat();
    method public int getMaxImages();
    method public int getMaxImages();
    method public android.media.Image getNextImage();
    method public android.view.Surface getSurface();
    method public android.view.Surface getSurface();
    method public int getWidth();
    method public int getWidth();
    method public void releaseImage(android.media.Image);
    method public static android.media.ImageReader newInstance(int, int, int, int);
    method public void setImageAvailableListener(android.media.ImageReader.OnImageAvailableListener, android.os.Handler);
    method public void setOnImageAvailableListener(android.media.ImageReader.OnImageAvailableListener, android.os.Handler);
  }
  public static class ImageReader.MaxImagesAcquiredException extends java.lang.Exception {
    ctor public ImageReader.MaxImagesAcquiredException();
    ctor public ImageReader.MaxImagesAcquiredException(java.lang.String);
    ctor public ImageReader.MaxImagesAcquiredException(java.lang.String, java.lang.Throwable);
    ctor public ImageReader.MaxImagesAcquiredException(java.lang.Throwable);
  }
  }
  public static abstract interface ImageReader.OnImageAvailableListener {
  public static abstract interface ImageReader.OnImageAvailableListener {
+10 −14
Original line number Original line Diff line number Diff line
@@ -26,6 +26,7 @@ import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.hardware.display.VirtualDisplay;
import android.media.Image;
import android.media.Image;
import android.media.ImageReader;
import android.media.ImageReader;
import android.media.ImageReader.MaxImagesAcquiredException;
import android.os.Bundle;
import android.os.Bundle;
import android.os.Handler;
import android.os.Handler;
import android.os.Looper;
import android.os.Looper;
@@ -83,8 +84,8 @@ public class VirtualDisplayTest extends AndroidTestCase {


        mImageReaderLock.lock();
        mImageReaderLock.lock();
        try {
        try {
            mImageReader = new ImageReader(WIDTH, HEIGHT, PixelFormat.RGBA_8888, 2);
            mImageReader = ImageReader.newInstance(WIDTH, HEIGHT, PixelFormat.RGBA_8888, 2);
            mImageReader.setImageAvailableListener(mImageListener, mHandler);
            mImageReader.setOnImageAvailableListener(mImageListener, mHandler);
            mSurface = mImageReader.getSurface();
            mSurface = mImageReader.getSurface();
        } finally {
        } finally {
            mImageReaderLock.unlock();
            mImageReaderLock.unlock();
@@ -409,19 +410,11 @@ public class VirtualDisplayTest extends AndroidTestCase {
                }
                }


                Log.d(TAG, "New image available from virtual display.");
                Log.d(TAG, "New image available from virtual display.");
                Image image = reader.getNextImage();

                // Get the latest buffer.
                Image image = reader.acquireLatestImage();
                if (image != null) {
                if (image != null) {
                    try {
                    try {
                        // Get the latest buffer.
                        for (;;) {
                            Image nextImage = reader.getNextImage();
                            if (nextImage == null) {
                                break;
                            }
                            reader.releaseImage(image);
                            image = nextImage;
                        }

                        // Scan for colors.
                        // Scan for colors.
                        int color = scanImage(image);
                        int color = scanImage(image);
                        synchronized (this) {
                        synchronized (this) {
@@ -431,9 +424,12 @@ public class VirtualDisplayTest extends AndroidTestCase {
                            }
                            }
                        }
                        }
                    } finally {
                    } finally {
                        reader.releaseImage(image);
                        image.close();
                    }
                    }
                }
                }
            } catch (MaxImagesAcquiredException e) {
                // We should never try to consume more buffers than maxImages.
                throw new IllegalStateException(e);
            } finally {
            } finally {
                mImageReaderLock.unlock();
                mImageReaderLock.unlock();
            }
            }
+63 −34
Original line number Original line Diff line number Diff line
@@ -16,20 +16,19 @@


package android.media;
package android.media;


import android.graphics.ImageFormat;
import java.nio.ByteBuffer;
import java.nio.ByteBuffer;
import java.lang.AutoCloseable;
import java.lang.AutoCloseable;


/**
/**
 * <p>A single complete image buffer to use with a media source such as a
 * <p>A single complete image buffer to use with a media source such as a
 * {@link MediaCodec} or a
 * {@link MediaCodec} or a
 * {@link android.hardware.camera2.CameraDevice}.</p>
 * {@link android.hardware.camera2.CameraDevice CameraDevice}.</p>
 *
 *
 * <p>This class allows for efficient direct application access to the pixel
 * <p>This class allows for efficient direct application access to the pixel
 * data of the Image through one or more
 * data of the Image through one or more
 * {@link java.nio.ByteBuffer ByteBuffers}. Each buffer is encapsulated in a
 * {@link java.nio.ByteBuffer ByteBuffers}. Each buffer is encapsulated in a
 * {@link Plane} that describes the layout of the pixel data in that plane. Due
 * {@link Plane} that describes the layout of the pixel data in that plane. Due
 * to this direct access, and unlike the {@link android.graphics.Bitmap} class,
 * to this direct access, and unlike the {@link android.graphics.Bitmap Bitmap} class,
 * Images are not directly usable as as UI resources.</p>
 * Images are not directly usable as as UI resources.</p>
 *
 *
 * <p>Since Images are often directly produced or consumed by hardware
 * <p>Since Images are often directly produced or consumed by hardware
@@ -40,19 +39,29 @@ import java.lang.AutoCloseable;
 * from various media sources, not closing old Image objects will prevent the
 * from various media sources, not closing old Image objects will prevent the
 * availability of new Images once
 * availability of new Images once
 * {@link ImageReader#getMaxImages the maximum outstanding image count} is
 * {@link ImageReader#getMaxImages the maximum outstanding image count} is
 * reached.</p>
 * reached. When this happens, the function acquiring new Images will typically
 * throw a
 * {@link ImageReader.MaxImagesAcquiredException MaxImagesAcquiredException}.</p>
 *
 *
 * @see ImageReader
 * @see ImageReader
 */
 */
public interface Image extends AutoCloseable {
public abstract class Image implements AutoCloseable {
    /**
     * @hide
     */
    protected Image() {
    }

    /**
    /**
     * Get the format for this image. This format determines the number of
     * Get the format for this image. This format determines the number of
     * ByteBuffers needed to represent the image, and the general layout of the
     * ByteBuffers needed to represent the image, and the general layout of the
     * pixel data in each in ByteBuffer.
     * pixel data in each in ByteBuffer.
     *
     *
     * <p>
     * The format is one of the values from
     * The format is one of the values from
     * {@link android.graphics.ImageFormat}. The mapping between the formats and
     * {@link android.graphics.ImageFormat ImageFormat}. The mapping between the
     * the planes is as follows:
     * formats and the planes is as follows:
     * </p>
     *
     *
     * <table>
     * <table>
     * <tr>
     * <tr>
@@ -61,13 +70,14 @@ public interface Image extends AutoCloseable {
     *   <th>Layout details</th>
     *   <th>Layout details</th>
     * </tr>
     * </tr>
     * <tr>
     * <tr>
     *   <td>{@link android.graphics.ImageFormat#JPEG}</td>
     *   <td>{@link android.graphics.ImageFormat#JPEG JPEG}</td>
     *   <td>1</td>
     *   <td>1</td>
     *   <td>Compressed data, so row and pixel strides are 0. To uncompress, use
     *   <td>Compressed data, so row and pixel strides are 0. To uncompress, use
     *      {@link android.graphics.BitmapFactory#decodeByteArray}.</td>
     *      {@link android.graphics.BitmapFactory#decodeByteArray BitmapFactory#decodeByteArray}.
     *   </td>
     * </tr>
     * </tr>
     * <tr>
     * <tr>
     *   <td>{@link android.graphics.ImageFormat#YUV_420_888}</td>
     *   <td>{@link android.graphics.ImageFormat#YUV_420_888 YUV_420_888}</td>
     *   <td>3</td>
     *   <td>3</td>
     *   <td>A luminance plane followed by the Cb and Cr chroma planes.
     *   <td>A luminance plane followed by the Cb and Cr chroma planes.
     *     The chroma planes have half the width and height of the luminance
     *     The chroma planes have half the width and height of the luminance
@@ -75,53 +85,60 @@ public interface Image extends AutoCloseable {
     *     Each plane has its own row stride and pixel stride.</td>
     *     Each plane has its own row stride and pixel stride.</td>
     * </tr>
     * </tr>
     * <tr>
     * <tr>
     *   <td>{@link android.graphics.ImageFormat#RAW_SENSOR}</td>
     *   <td>{@link android.graphics.ImageFormat#RAW_SENSOR RAW_SENSOR}</td>
     *   <td>1</td>
     *   <td>1</td>
     *   <td>A single plane of raw sensor image data, with 16 bits per color
     *   <td>A single plane of raw sensor image data, with 16 bits per color
     *     sample. The details of the layout need to be queried from the source of
     *     sample. The details of the layout need to be queried from the source of
     *     the raw sensor data, such as
     *     the raw sensor data, such as
     *     {@link android.hardware.camera2.CameraDevice}.
     *     {@link android.hardware.camera2.CameraDevice CameraDevice}.
     *   </td>
     *   </td>
     * </tr>
     * </tr>
     * </table>
     * </table>
     *
     *
     * @see android.graphics.ImageFormat
     * @see android.graphics.ImageFormat
     */
     */
    public int getFormat();
    public abstract int getFormat();


    /**
    /**
     * The width of the image in pixels. For formats where some color channels
     * The width of the image in pixels. For formats where some color channels
     * are subsampled, this is the width of the largest-resolution plane.
     * are subsampled, this is the width of the largest-resolution plane.
     */
     */
    public int getWidth();
    public abstract int getWidth();


    /**
    /**
     * The height of the image in pixels. For formats where some color channels
     * The height of the image in pixels. For formats where some color channels
     * are subsampled, this is the height of the largest-resolution plane.
     * are subsampled, this is the height of the largest-resolution plane.
     */
     */
    public int getHeight();
    public abstract int getHeight();


    /**
    /**
     * Get the timestamp associated with this frame. The timestamp is measured
     * Get the timestamp associated with this frame.
     * in nanoseconds, and is monotonically increasing. However, the zero point
     * <p>
     * and whether the timestamp can be compared against other sources of time
     * The timestamp is measured in nanoseconds, and is monotonically
     * or images depend on the source of this image.
     * increasing. However, the zero point and whether the timestamp can be
     * compared against other sources of time or images depend on the source of
     * this image.
     * </p>
     */
     */
    public long getTimestamp();
    public abstract long getTimestamp();


    /**
    /**
     * Get the array of pixel planes for this Image. The number of planes is
     * Get the array of pixel planes for this Image. The number of planes is
     * determined by the format of the Image.
     * determined by the format of the Image.
     */
     */
    public Plane[] getPlanes();
    public abstract Plane[] getPlanes();


    /**
    /**
     * Free up this frame for reuse. After calling this method, calling any
     * Free up this frame for reuse.
     * methods on this Image will result in an IllegalStateException, and
     * <p>
     * attempting to read from ByteBuffers returned by an earlier
     * After calling this method, calling any methods on this {@code Image} will
     * {@code Plane#getBuffer} call will have undefined behavior.
     * result in an {@link IllegalStateException}, and attempting to read from
     * {@link ByteBuffer ByteBuffers} returned by an earlier
     * {@link Plane#getBuffer} call will have undefined behavior.
     * </p>
     */
     */
    public void close();
    @Override
    public abstract void close();


    /**
    /**
     * <p>A single color plane of image data.</p>
     * <p>A single color plane of image data.</p>
@@ -134,29 +151,41 @@ public interface Image extends AutoCloseable {
     *
     *
     * @see #getFormat
     * @see #getFormat
     */
     */
    public interface Plane {
    public static abstract class Plane {
        /**
        /**
         * <p>The row stride for this color plane, in bytes.
         * @hide
         */
        protected Plane() {
        }

        /**
         * <p>The row stride for this color plane, in bytes.</p>
         *
         *
         * <p>This is the distance between the start of two consecutive rows of
         * <p>This is the distance between the start of two consecutive rows of
         * pixels in the image.</p>
         * pixels in the image. The row stride is always greater than 0.</p>
         */
         */
        public int getRowStride();
        public abstract int getRowStride();
        /**
        /**
         * <p>The distance between adjacent pixel samples, in bytes.</p>
         * <p>The distance between adjacent pixel samples, in bytes.</p>
         *
         *
         * <p>This is the distance between two consecutive pixel values in a row
         * <p>This is the distance between two consecutive pixel values in a row
         * of pixels. It may be larger than the size of a single pixel to
         * of pixels. It may be larger than the size of a single pixel to
         * account for interleaved image data or padded formats.</p>
         * account for interleaved image data or padded formats.
         * The pixel stride is always greater than 0.</p>
         */
         */
        public int getPixelStride();
        public abstract int getPixelStride();
        /**
        /**
         * <p>Get a set of direct {@link java.nio.ByteBuffer byte buffers}
         * <p>Get a direct {@link java.nio.ByteBuffer ByteBuffer}
         * containing the frame data.</p>
         * containing the frame data.</p>
         *
         *
         * <p>In particular, the buffer returned will always have
         * {@link java.nio.ByteBuffer#isDirect isDirect} return {@code true}, so
         * the underlying data could be mapped as a pointer in JNI without doing
         * any copies with {@code GetDirectBufferAddress}.</p>
         *
         * @return the byte buffer containing the image data for this plane.
         * @return the byte buffer containing the image data for this plane.
         */
         */
        public ByteBuffer getBuffer();
        public abstract ByteBuffer getBuffer();
    }
    }


}
}
+238 −59

File changed.

Preview size limit exceeded, changes collapsed.

+4 −4
Original line number Original line Diff line number Diff line
@@ -43,8 +43,8 @@


using namespace android;
using namespace android;


static const char* const OutOfResourcesException =
static const char* const MaxImagesAcquiredException =
    "android/view/Surface$OutOfResourcesException";
    "android/media/ImageReader$MaxImagesAcquiredException";


enum {
enum {
    IMAGE_READER_MAX_NUM_PLANES = 3,
    IMAGE_READER_MAX_NUM_PLANES = 3,
@@ -700,7 +700,7 @@ static jboolean ImageReader_imageSetup(JNIEnv* env, jobject thiz,
    if (buffer == NULL) {
    if (buffer == NULL) {
        ALOGW("Unable to acquire a lockedBuffer, very likely client tries to lock more than"
        ALOGW("Unable to acquire a lockedBuffer, very likely client tries to lock more than"
            " maxImages buffers");
            " maxImages buffers");
        jniThrowException(env, OutOfResourcesException,
        jniThrowException(env, MaxImagesAcquiredException,
                  "Too many outstanding images, close existing images"
                  "Too many outstanding images, close existing images"
                  " to be able to acquire more.");
                  " to be able to acquire more.");
        return false;
        return false;
@@ -709,7 +709,7 @@ static jboolean ImageReader_imageSetup(JNIEnv* env, jobject thiz,
    if (res != NO_ERROR) {
    if (res != NO_ERROR) {
        if (res != BAD_VALUE /*no buffers*/) {
        if (res != BAD_VALUE /*no buffers*/) {
            if (res == NOT_ENOUGH_DATA) {
            if (res == NOT_ENOUGH_DATA) {
                jniThrowException(env, OutOfResourcesException,
                jniThrowException(env, MaxImagesAcquiredException,
                          "Too many outstanding images, close existing images"
                          "Too many outstanding images, close existing images"
                          " to be able to acquire more.");
                          " to be able to acquire more.");
            } else {
            } else {
Loading