Home | History | Annotate | Download | only in media
      1 /*
      2  * Copyright (C) 2013 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.media;
     18 
     19 import android.graphics.ImageFormat;
     20 import android.os.Handler;
     21 import android.os.Looper;
     22 import android.os.Message;
     23 import android.util.Log;
     24 import android.view.Surface;
     25 
     26 import dalvik.system.VMRuntime;
     27 
     28 import java.lang.ref.WeakReference;
     29 import java.nio.ByteBuffer;
     30 import java.nio.ByteOrder;
     31 import java.nio.NioUtils;
     32 import java.util.List;
     33 import java.util.concurrent.CopyOnWriteArrayList;
     34 import java.util.concurrent.atomic.AtomicBoolean;
     35 
     36 /**
     37  * <p>The ImageReader class allows direct application access to image data
     38  * rendered into a {@link android.view.Surface}</p>
     39  *
     40  * <p>Several Android media API classes accept Surface objects as targets to
     41  * render to, including {@link MediaPlayer}, {@link MediaCodec},
     42  * {@link android.hardware.camera2.CameraDevice}, {@link ImageWriter} and
     43  * {@link android.renderscript.Allocation RenderScript Allocations}. The image
     44  * sizes and formats that can be used with each source vary, and should be
     45  * checked in the documentation for the specific API.</p>
     46  *
     47  * <p>The image data is encapsulated in {@link Image} objects, and multiple such
     48  * objects can be accessed at the same time, up to the number specified by the
     49  * {@code maxImages} constructor parameter. New images sent to an ImageReader
     50  * through its {@link Surface} are queued until accessed through the {@link #acquireLatestImage}
     51  * or {@link #acquireNextImage} call. Due to memory limits, an image source will
     52  * eventually stall or drop Images in trying to render to the Surface if the
     53  * ImageReader does not obtain and release Images at a rate equal to the
     54  * production rate.</p>
     55  */
     56 public class ImageReader implements AutoCloseable {
     57 
     58     /**
     59      * Returned by nativeImageSetup when acquiring the image was successful.
     60      */
     61     private static final int ACQUIRE_SUCCESS = 0;
     62     /**
     63      * Returned by nativeImageSetup when we couldn't acquire the buffer,
     64      * because there were no buffers available to acquire.
     65      */
     66     private static final int ACQUIRE_NO_BUFS = 1;
     67     /**
     68      * Returned by nativeImageSetup when we couldn't acquire the buffer
     69      * because the consumer has already acquired {@maxImages} and cannot
     70      * acquire more than that.
     71      */
     72     private static final int ACQUIRE_MAX_IMAGES = 2;
     73 
     74     /**
     75      * <p>
     76      * Create a new reader for images of the desired size and format.
     77      * </p>
     78      * <p>
     79      * The {@code maxImages} parameter determines the maximum number of
     80      * {@link Image} objects that can be be acquired from the
     81      * {@code ImageReader} simultaneously. Requesting more buffers will use up
     82      * more memory, so it is important to use only the minimum number necessary
     83      * for the use case.
     84      * </p>
     85      * <p>
     86      * The valid sizes and formats depend on the source of the image data.
     87      * </p>
     88      * <p>
     89      * If the {@code format} is {@link ImageFormat#PRIVATE PRIVATE}, the created
     90      * {@link ImageReader} will produce images that are not directly accessible
     91      * by the application. The application can still acquire images from this
     92      * {@link ImageReader}, and send them to the
     93      * {@link android.hardware.camera2.CameraDevice camera} for reprocessing via
     94      * {@link ImageWriter} interface. However, the {@link Image#getPlanes()
     95      * getPlanes()} will return an empty array for {@link ImageFormat#PRIVATE
     96      * PRIVATE} format images. The application can check if an existing reader's
     97      * format by calling {@link #getImageFormat()}.
     98      * </p>
     99      * <p>
    100      * {@link ImageFormat#PRIVATE PRIVATE} format {@link ImageReader
    101      * ImageReaders} are more efficient to use when application access to image
    102      * data is not necessary, compared to ImageReaders using other format such
    103      * as {@link ImageFormat#YUV_420_888 YUV_420_888}.
    104      * </p>
    105      *
    106      * @param width The default width in pixels of the Images that this reader
    107      *            will produce.
    108      * @param height The default height in pixels of the Images that this reader
    109      *            will produce.
    110      * @param format The format of the Image that this reader will produce. This
    111      *            must be one of the {@link android.graphics.ImageFormat} or
    112      *            {@link android.graphics.PixelFormat} constants. Note that not
    113      *            all formats are supported, like ImageFormat.NV21.
    114      * @param maxImages The maximum number of images the user will want to
    115      *            access simultaneously. This should be as small as possible to
    116      *            limit memory use. Once maxImages Images are obtained by the
    117      *            user, one of them has to be released before a new Image will
    118      *            become available for access through
    119      *            {@link #acquireLatestImage()} or {@link #acquireNextImage()}.
    120      *            Must be greater than 0.
    121      * @see Image
    122      */
    123     public static ImageReader newInstance(int width, int height, int format, int maxImages) {
    124         return new ImageReader(width, height, format, maxImages);
    125     }
    126 
    127     /**
    128      * @hide
    129      */
    130     protected ImageReader(int width, int height, int format, int maxImages) {
    131         mWidth = width;
    132         mHeight = height;
    133         mFormat = format;
    134         mMaxImages = maxImages;
    135 
    136         if (width < 1 || height < 1) {
    137             throw new IllegalArgumentException(
    138                 "The image dimensions must be positive");
    139         }
    140         if (mMaxImages < 1) {
    141             throw new IllegalArgumentException(
    142                 "Maximum outstanding image count must be at least 1");
    143         }
    144 
    145         if (format == ImageFormat.NV21) {
    146             throw new IllegalArgumentException(
    147                     "NV21 format is not supported");
    148         }
    149 
    150         mNumPlanes = ImageUtils.getNumPlanesForFormat(mFormat);
    151 
    152         nativeInit(new WeakReference<ImageReader>(this), width, height, format, maxImages);
    153 
    154         mSurface = nativeGetSurface();
    155 
    156         mIsReaderValid = true;
    157         // Estimate the native buffer allocation size and register it so it gets accounted for
    158         // during GC. Note that this doesn't include the buffers required by the buffer queue
    159         // itself and the buffers requested by the producer.
    160         // Only include memory for 1 buffer, since actually accounting for the memory used is
    161         // complex, and 1 buffer is enough for the VM to treat the ImageReader as being of some
    162         // size.
    163         mEstimatedNativeAllocBytes = ImageUtils.getEstimatedNativeAllocBytes(
    164                 width, height, format, /*buffer count*/ 1);
    165         VMRuntime.getRuntime().registerNativeAllocation(mEstimatedNativeAllocBytes);
    166     }
    167 
    168     /**
    169      * The default width of {@link Image Images}, in pixels.
    170      *
    171      * <p>The width may be overridden by the producer sending buffers to this
    172      * ImageReader's Surface. If so, the actual width of the images can be
    173      * found using {@link Image#getWidth}.</p>
    174      *
    175      * @return the expected width of an Image
    176      */
    177     public int getWidth() {
    178         return mWidth;
    179     }
    180 
    181     /**
    182      * The default height of {@link Image Images}, in pixels.
    183      *
    184      * <p>The height may be overridden by the producer sending buffers to this
    185      * ImageReader's Surface. If so, the actual height of the images can be
    186      * found using {@link Image#getHeight}.</p>
    187      *
    188      * @return the expected height of an Image
    189      */
    190     public int getHeight() {
    191         return mHeight;
    192     }
    193 
    194     /**
    195      * The default {@link ImageFormat image format} of {@link Image Images}.
    196      *
    197      * <p>Some color formats may be overridden by the producer sending buffers to
    198      * this ImageReader's Surface if the default color format allows. ImageReader
    199      * guarantees that all {@link Image Images} acquired from ImageReader
    200      * (for example, with {@link #acquireNextImage}) will have a "compatible"
    201      * format to what was specified in {@link #newInstance}.
    202      * As of now, each format is only compatible to itself.
    203      * The actual format of the images can be found using {@link Image#getFormat}.</p>
    204      *
    205      * @return the expected format of an Image
    206      *
    207      * @see ImageFormat
    208      */
    209     public int getImageFormat() {
    210         return mFormat;
    211     }
    212 
    213     /**
    214      * Maximum number of images that can be acquired from the ImageReader by any time (for example,
    215      * with {@link #acquireNextImage}).
    216      *
    217      * <p>An image is considered acquired after it's returned by a function from ImageReader, and
    218      * until the Image is {@link Image#close closed} to release the image back to the ImageReader.
    219      * </p>
    220      *
    221      * <p>Attempting to acquire more than {@code maxImages} concurrently will result in the
    222      * acquire function throwing a {@link IllegalStateException}. Furthermore,
    223      * while the max number of images have been acquired by the ImageReader user, the producer
    224      * enqueueing additional images may stall until at least one image has been released. </p>
    225      *
    226      * @return Maximum number of images for this ImageReader.
    227      *
    228      * @see Image#close
    229      */
    230     public int getMaxImages() {
    231         return mMaxImages;
    232     }
    233 
    234     /**
    235      * <p>Get a {@link Surface} that can be used to produce {@link Image Images} for this
    236      * {@code ImageReader}.</p>
    237      *
    238      * <p>Until valid image data is rendered into this {@link Surface}, the
    239      * {@link #acquireNextImage} method will return {@code null}. Only one source
    240      * can be producing data into this Surface at the same time, although the
    241      * same {@link Surface} can be reused with a different API once the first source is
    242      * disconnected from the {@link Surface}.</p>
    243      *
    244      * @return A {@link Surface} to use for a drawing target for various APIs.
    245      */
    246     public Surface getSurface() {
    247         return mSurface;
    248     }
    249 
    250     /**
    251      * <p>
    252      * Acquire the latest {@link Image} from the ImageReader's queue, dropping older
    253      * {@link Image images}. Returns {@code null} if no new image is available.
    254      * </p>
    255      * <p>
    256      * This operation will acquire all the images possible from the ImageReader,
    257      * but {@link #close} all images that aren't the latest. This function is
    258      * recommended to use over {@link #acquireNextImage} for most use-cases, as it's
    259      * more suited for real-time processing.
    260      * </p>
    261      * <p>
    262      * Note that {@link #getMaxImages maxImages} should be at least 2 for
    263      * {@link #acquireLatestImage} to be any different than {@link #acquireNextImage} -
    264      * discarding all-but-the-newest {@link Image} requires temporarily acquiring two
    265      * {@link Image Images} at once. Or more generally, calling {@link #acquireLatestImage}
    266      * with less than two images of margin, that is
    267      * {@code (maxImages - currentAcquiredImages < 2)} will not discard as expected.
    268      * </p>
    269      * <p>
    270      * This operation will fail by throwing an {@link IllegalStateException} if
    271      * {@code maxImages} have been acquired with {@link #acquireLatestImage} or
    272      * {@link #acquireNextImage}. In particular a sequence of {@link #acquireLatestImage}
    273      * calls greater than {@link #getMaxImages} without calling {@link Image#close} in-between
    274      * will exhaust the underlying queue. At such a time, {@link IllegalStateException}
    275      * will be thrown until more images are
    276      * released with {@link Image#close}.
    277      * </p>
    278      *
    279      * @return latest frame of image data, or {@code null} if no image data is available.
    280      * @throws IllegalStateException if too many images are currently acquired
    281      */
    282     public Image acquireLatestImage() {
    283         Image image = acquireNextImage();
    284         if (image == null) {
    285             return null;
    286         }
    287         try {
    288             for (;;) {
    289                 Image next = acquireNextImageNoThrowISE();
    290                 if (next == null) {
    291                     Image result = image;
    292                     image = null;
    293                     return result;
    294                 }
    295                 image.close();
    296                 image = next;
    297             }
    298         } finally {
    299             if (image != null) {
    300                 image.close();
    301             }
    302         }
    303     }
    304 
    305     /**
    306      * Don't throw IllegalStateException if there are too many images acquired.
    307      *
    308      * @return Image if acquiring succeeded, or null otherwise.
    309      *
    310      * @hide
    311      */
    312     public Image acquireNextImageNoThrowISE() {
    313         SurfaceImage si = new SurfaceImage(mFormat);
    314         return acquireNextSurfaceImage(si) == ACQUIRE_SUCCESS ? si : null;
    315     }
    316 
    317     /**
    318      * Attempts to acquire the next image from the underlying native implementation.
    319      *
    320      * <p>
    321      * Note that unexpected failures will throw at the JNI level.
    322      * </p>
    323      *
    324      * @param si A blank SurfaceImage.
    325      * @return One of the {@code ACQUIRE_*} codes that determine success or failure.
    326      *
    327      * @see #ACQUIRE_MAX_IMAGES
    328      * @see #ACQUIRE_NO_BUFS
    329      * @see #ACQUIRE_SUCCESS
    330      */
    331     private int acquireNextSurfaceImage(SurfaceImage si) {
    332         synchronized (mCloseLock) {
    333             // A null image will eventually be returned if ImageReader is already closed.
    334             int status = ACQUIRE_NO_BUFS;
    335             if (mIsReaderValid) {
    336                 status = nativeImageSetup(si);
    337             }
    338 
    339             switch (status) {
    340                 case ACQUIRE_SUCCESS:
    341                     si.mIsImageValid = true;
    342                 case ACQUIRE_NO_BUFS:
    343                 case ACQUIRE_MAX_IMAGES:
    344                     break;
    345                 default:
    346                     throw new AssertionError("Unknown nativeImageSetup return code " + status);
    347             }
    348 
    349             // Only keep track the successfully acquired image, as the native buffer is only mapped
    350             // for such case.
    351             if (status == ACQUIRE_SUCCESS) {
    352                 mAcquiredImages.add(si);
    353             }
    354             return status;
    355         }
    356     }
    357 
    358     /**
    359      * <p>
    360      * Acquire the next Image from the ImageReader's queue. Returns {@code null} if
    361      * no new image is available.
    362      * </p>
    363      *
    364      * <p><i>Warning:</i> Consider using {@link #acquireLatestImage()} instead, as it will
    365      * automatically release older images, and allow slower-running processing routines to catch
    366      * up to the newest frame. Usage of {@link #acquireNextImage} is recommended for
    367      * batch/background processing. Incorrectly using this function can cause images to appear
    368      * with an ever-increasing delay, followed by a complete stall where no new images seem to
    369      * appear.
    370      * </p>
    371      *
    372      * <p>
    373      * This operation will fail by throwing an {@link IllegalStateException} if
    374      * {@code maxImages} have been acquired with {@link #acquireNextImage} or
    375      * {@link #acquireLatestImage}. In particular a sequence of {@link #acquireNextImage} or
    376      * {@link #acquireLatestImage} calls greater than {@link #getMaxImages maxImages} without
    377      * calling {@link Image#close} in-between will exhaust the underlying queue. At such a time,
    378      * {@link IllegalStateException} will be thrown until more images are released with
    379      * {@link Image#close}.
    380      * </p>
    381      *
    382      * @return a new frame of image data, or {@code null} if no image data is available.
    383      * @throws IllegalStateException if {@code maxImages} images are currently acquired
    384      * @see #acquireLatestImage
    385      */
    386     public Image acquireNextImage() {
    387         // Initialize with reader format, but can be overwritten by native if the image
    388         // format is different from the reader format.
    389         SurfaceImage si = new SurfaceImage(mFormat);
    390         int status = acquireNextSurfaceImage(si);
    391 
    392         switch (status) {
    393             case ACQUIRE_SUCCESS:
    394                 return si;
    395             case ACQUIRE_NO_BUFS:
    396                 return null;
    397             case ACQUIRE_MAX_IMAGES:
    398                 throw new IllegalStateException(
    399                         String.format(
    400                                 "maxImages (%d) has already been acquired, " +
    401                                 "call #close before acquiring more.", mMaxImages));
    402             default:
    403                 throw new AssertionError("Unknown nativeImageSetup return code " + status);
    404         }
    405     }
    406 
    407     /**
    408      * <p>Return the frame to the ImageReader for reuse.</p>
    409      */
    410     private void releaseImage(Image i) {
    411         if (! (i instanceof SurfaceImage) ) {
    412             throw new IllegalArgumentException(
    413                 "This image was not produced by an ImageReader");
    414         }
    415         SurfaceImage si = (SurfaceImage) i;
    416         if (si.mIsImageValid == false) {
    417             return;
    418         }
    419 
    420         if (si.getReader() != this || !mAcquiredImages.contains(i)) {
    421             throw new IllegalArgumentException(
    422                 "This image was not produced by this ImageReader");
    423         }
    424 
    425         si.clearSurfacePlanes();
    426         nativeReleaseImage(i);
    427         si.mIsImageValid = false;
    428         mAcquiredImages.remove(i);
    429     }
    430 
    431     /**
    432      * Register a listener to be invoked when a new image becomes available
    433      * from the ImageReader.
    434      *
    435      * @param listener
    436      *            The listener that will be run.
    437      * @param handler
    438      *            The handler on which the listener should be invoked, or null
    439      *            if the listener should be invoked on the calling thread's looper.
    440      * @throws IllegalArgumentException
    441      *            If no handler specified and the calling thread has no looper.
    442      */
    443     public void setOnImageAvailableListener(OnImageAvailableListener listener, Handler handler) {
    444         synchronized (mListenerLock) {
    445             if (listener != null) {
    446                 Looper looper = handler != null ? handler.getLooper() : Looper.myLooper();
    447                 if (looper == null) {
    448                     throw new IllegalArgumentException(
    449                             "handler is null but the current thread is not a looper");
    450                 }
    451                 if (mListenerHandler == null || mListenerHandler.getLooper() != looper) {
    452                     mListenerHandler = new ListenerHandler(looper);
    453                 }
    454                 mListener = listener;
    455             } else {
    456                 mListener = null;
    457                 mListenerHandler = null;
    458             }
    459         }
    460     }
    461 
    462     /**
    463      * Callback interface for being notified that a new image is available.
    464      *
    465      * <p>
    466      * The onImageAvailable is called per image basis, that is, callback fires for every new frame
    467      * available from ImageReader.
    468      * </p>
    469      */
    470     public interface OnImageAvailableListener {
    471         /**
    472          * Callback that is called when a new image is available from ImageReader.
    473          *
    474          * @param reader the ImageReader the callback is associated with.
    475          * @see ImageReader
    476          * @see Image
    477          */
    478         void onImageAvailable(ImageReader reader);
    479     }
    480 
    481     /**
    482      * Free up all the resources associated with this ImageReader.
    483      *
    484      * <p>
    485      * After calling this method, this ImageReader can not be used. Calling
    486      * any methods on this ImageReader and Images previously provided by
    487      * {@link #acquireNextImage} or {@link #acquireLatestImage}
    488      * will result in an {@link IllegalStateException}, and attempting to read from
    489      * {@link ByteBuffer ByteBuffers} returned by an earlier
    490      * {@link Image.Plane#getBuffer Plane#getBuffer} call will
    491      * have undefined behavior.
    492      * </p>
    493      */
    494     @Override
    495     public void close() {
    496         setOnImageAvailableListener(null, null);
    497         if (mSurface != null) mSurface.release();
    498 
    499         /**
    500          * Close all outstanding acquired images before closing the ImageReader. It is a good
    501          * practice to close all the images as soon as it is not used to reduce system instantaneous
    502          * memory pressure. CopyOnWrite list will use a copy of current list content. For the images
    503          * being closed by other thread (e.g., GC thread), doubling the close call is harmless. For
    504          * the image being acquired by other threads, mCloseLock is used to synchronize close and
    505          * acquire operations.
    506          */
    507         synchronized (mCloseLock) {
    508             mIsReaderValid = false;
    509             for (Image image : mAcquiredImages) {
    510                 image.close();
    511             }
    512             mAcquiredImages.clear();
    513 
    514             nativeClose();
    515 
    516             if (mEstimatedNativeAllocBytes > 0) {
    517                 VMRuntime.getRuntime().registerNativeFree(mEstimatedNativeAllocBytes);
    518                 mEstimatedNativeAllocBytes = 0;
    519             }
    520         }
    521     }
    522 
    523     /**
    524      * Discard any free buffers owned by this ImageReader.
    525      *
    526      * <p>
    527      * Generally, the ImageReader caches buffers for reuse once they have been
    528      * allocated, for best performance. However, sometimes it may be important to
    529      * release all the cached, unused buffers to save on memory.
    530      * </p>
    531      * <p>
    532      * Calling this method will discard all free cached buffers. This does not include any buffers
    533      * associated with Images acquired from the ImageReader, any filled buffers waiting to be
    534      * acquired, and any buffers currently in use by the source rendering buffers into the
    535      * ImageReader's Surface.
    536      * <p>
    537      * The ImageReader continues to be usable after this call, but may need to reallocate buffers
    538      * when more buffers are needed for rendering.
    539      * </p>
    540      * @hide
    541      */
    542     public void discardFreeBuffers() {
    543         synchronized (mCloseLock) {
    544             nativeDiscardFreeBuffers();
    545         }
    546     }
    547 
    548     @Override
    549     protected void finalize() throws Throwable {
    550         try {
    551             close();
    552         } finally {
    553             super.finalize();
    554         }
    555     }
    556 
    557     /**
    558      * <p>
    559      * Remove the ownership of this image from the ImageReader.
    560      * </p>
    561      * <p>
    562      * After this call, the ImageReader no longer owns this image, and the image
    563      * ownership can be transfered to another entity like {@link ImageWriter}
    564      * via {@link ImageWriter#queueInputImage}. It's up to the new owner to
    565      * release the resources held by this image. For example, if the ownership
    566      * of this image is transfered to an {@link ImageWriter}, the image will be
    567      * freed by the ImageWriter after the image data consumption is done.
    568      * </p>
    569      * <p>
    570      * This method can be used to achieve zero buffer copy for use cases like
    571      * {@link android.hardware.camera2.CameraDevice Camera2 API} PRIVATE and YUV
    572      * reprocessing, where the application can select an output image from
    573      * {@link ImageReader} and transfer this image directly to
    574      * {@link ImageWriter}, where this image can be consumed by camera directly.
    575      * For PRIVATE reprocessing, this is the only way to send input buffers to
    576      * the {@link android.hardware.camera2.CameraDevice camera} for
    577      * reprocessing.
    578      * </p>
    579      * <p>
    580      * This is a package private method that is only used internally.
    581      * </p>
    582      *
    583      * @param image The image to be detached from this ImageReader.
    584      * @throws IllegalStateException If the ImageReader or image have been
    585      *             closed, or the has been detached, or has not yet been
    586      *             acquired.
    587      */
    588      void detachImage(Image image) {
    589        if (image == null) {
    590            throw new IllegalArgumentException("input image must not be null");
    591        }
    592        if (!isImageOwnedbyMe(image)) {
    593            throw new IllegalArgumentException("Trying to detach an image that is not owned by"
    594                    + " this ImageReader");
    595        }
    596 
    597         SurfaceImage si = (SurfaceImage) image;
    598         si.throwISEIfImageIsInvalid();
    599 
    600         if (si.isAttachable()) {
    601             throw new IllegalStateException("Image was already detached from this ImageReader");
    602         }
    603 
    604         nativeDetachImage(image);
    605         si.setDetached(true);
    606     }
    607 
    608     private boolean isImageOwnedbyMe(Image image) {
    609         if (!(image instanceof SurfaceImage)) {
    610             return false;
    611         }
    612         SurfaceImage si = (SurfaceImage) image;
    613         return si.getReader() == this;
    614     }
    615 
    616     /**
    617      * Called from Native code when an Event happens.
    618      *
    619      * This may be called from an arbitrary Binder thread, so access to the ImageReader must be
    620      * synchronized appropriately.
    621      */
    622     private static void postEventFromNative(Object selfRef) {
    623         @SuppressWarnings("unchecked")
    624         WeakReference<ImageReader> weakSelf = (WeakReference<ImageReader>)selfRef;
    625         final ImageReader ir = weakSelf.get();
    626         if (ir == null) {
    627             return;
    628         }
    629 
    630         final Handler handler;
    631         synchronized (ir.mListenerLock) {
    632             handler = ir.mListenerHandler;
    633         }
    634         if (handler != null) {
    635             handler.sendEmptyMessage(0);
    636         }
    637     }
    638 
    639     private final int mWidth;
    640     private final int mHeight;
    641     private final int mFormat;
    642     private final int mMaxImages;
    643     private final int mNumPlanes;
    644     private final Surface mSurface;
    645     private int mEstimatedNativeAllocBytes;
    646 
    647     private final Object mListenerLock = new Object();
    648     private final Object mCloseLock = new Object();
    649     private boolean mIsReaderValid = false;
    650     private OnImageAvailableListener mListener;
    651     private ListenerHandler mListenerHandler;
    652     // Keep track of the successfully acquired Images. This need to be thread safe as the images
    653     // could be closed by different threads (e.g., application thread and GC thread).
    654     private List<Image> mAcquiredImages = new CopyOnWriteArrayList<Image>();
    655 
    656     /**
    657      * This field is used by native code, do not access or modify.
    658      */
    659     private long mNativeContext;
    660 
    661     /**
    662      * This custom handler runs asynchronously so callbacks don't get queued behind UI messages.
    663      */
    664     private final class ListenerHandler extends Handler {
    665         public ListenerHandler(Looper looper) {
    666             super(looper, null, true /*async*/);
    667         }
    668 
    669         @Override
    670         public void handleMessage(Message msg) {
    671             OnImageAvailableListener listener;
    672             synchronized (mListenerLock) {
    673                 listener = mListener;
    674             }
    675 
    676             // It's dangerous to fire onImageAvailable() callback when the ImageReader is being
    677             // closed, as application could acquire next image in the onImageAvailable() callback.
    678             boolean isReaderValid = false;
    679             synchronized (mCloseLock) {
    680                 isReaderValid = mIsReaderValid;
    681             }
    682             if (listener != null && isReaderValid) {
    683                 listener.onImageAvailable(ImageReader.this);
    684             }
    685         }
    686     }
    687 
    688     private class SurfaceImage extends android.media.Image {
    689         public SurfaceImage(int format) {
    690             mFormat = format;
    691         }
    692 
    693         @Override
    694         public void close() {
    695             ImageReader.this.releaseImage(this);
    696         }
    697 
    698         public ImageReader getReader() {
    699             return ImageReader.this;
    700         }
    701 
    702         @Override
    703         public int getFormat() {
    704             throwISEIfImageIsInvalid();
    705             int readerFormat = ImageReader.this.getImageFormat();
    706             // Assume opaque reader always produce opaque images.
    707             mFormat = (readerFormat == ImageFormat.PRIVATE) ? readerFormat :
    708                 nativeGetFormat(readerFormat);
    709             return mFormat;
    710         }
    711 
    712         @Override
    713         public int getWidth() {
    714             throwISEIfImageIsInvalid();
    715             int width;
    716             switch(getFormat()) {
    717                 case ImageFormat.JPEG:
    718                 case ImageFormat.DEPTH_POINT_CLOUD:
    719                 case ImageFormat.RAW_PRIVATE:
    720                     width = ImageReader.this.getWidth();
    721                     break;
    722                 default:
    723                     width = nativeGetWidth();
    724             }
    725             return width;
    726         }
    727 
    728         @Override
    729         public int getHeight() {
    730             throwISEIfImageIsInvalid();
    731             int height;
    732             switch(getFormat()) {
    733                 case ImageFormat.JPEG:
    734                 case ImageFormat.DEPTH_POINT_CLOUD:
    735                 case ImageFormat.RAW_PRIVATE:
    736                     height = ImageReader.this.getHeight();
    737                     break;
    738                 default:
    739                     height = nativeGetHeight();
    740             }
    741             return height;
    742         }
    743 
    744         @Override
    745         public long getTimestamp() {
    746             throwISEIfImageIsInvalid();
    747             return mTimestamp;
    748         }
    749 
    750         @Override
    751         public void setTimestamp(long timestampNs) {
    752             throwISEIfImageIsInvalid();
    753             mTimestamp = timestampNs;
    754         }
    755 
    756         @Override
    757         public Plane[] getPlanes() {
    758             throwISEIfImageIsInvalid();
    759 
    760             if (mPlanes == null) {
    761                 mPlanes = nativeCreatePlanes(ImageReader.this.mNumPlanes, ImageReader.this.mFormat);
    762             }
    763             // Shallow copy is fine.
    764             return mPlanes.clone();
    765         }
    766 
    767         @Override
    768         protected final void finalize() throws Throwable {
    769             try {
    770                 close();
    771             } finally {
    772                 super.finalize();
    773             }
    774         }
    775 
    776         @Override
    777         boolean isAttachable() {
    778             throwISEIfImageIsInvalid();
    779             return mIsDetached.get();
    780         }
    781 
    782         @Override
    783         ImageReader getOwner() {
    784             throwISEIfImageIsInvalid();
    785             return ImageReader.this;
    786         }
    787 
    788         @Override
    789         long getNativeContext() {
    790             throwISEIfImageIsInvalid();
    791             return mNativeBuffer;
    792         }
    793 
    794         private void setDetached(boolean detached) {
    795             throwISEIfImageIsInvalid();
    796             mIsDetached.getAndSet(detached);
    797         }
    798 
    799         private void clearSurfacePlanes() {
    800             // Image#getPlanes may not be called before the image is closed.
    801             if (mIsImageValid && mPlanes != null) {
    802                 for (int i = 0; i < mPlanes.length; i++) {
    803                     if (mPlanes[i] != null) {
    804                         mPlanes[i].clearBuffer();
    805                         mPlanes[i] = null;
    806                     }
    807                 }
    808             }
    809         }
    810 
    811         private class SurfacePlane extends android.media.Image.Plane {
    812             // SurfacePlane instance is created by native code when SurfaceImage#getPlanes() is
    813             // called
    814             private SurfacePlane(int rowStride, int pixelStride, ByteBuffer buffer) {
    815                 mRowStride = rowStride;
    816                 mPixelStride = pixelStride;
    817                 mBuffer = buffer;
    818                 /**
    819                  * Set the byteBuffer order according to host endianness (native
    820                  * order), otherwise, the byteBuffer order defaults to
    821                  * ByteOrder.BIG_ENDIAN.
    822                  */
    823                 mBuffer.order(ByteOrder.nativeOrder());
    824             }
    825 
    826             @Override
    827             public ByteBuffer getBuffer() {
    828                 throwISEIfImageIsInvalid();
    829                 return mBuffer;
    830             }
    831 
    832             @Override
    833             public int getPixelStride() {
    834                 SurfaceImage.this.throwISEIfImageIsInvalid();
    835                 if (ImageReader.this.mFormat == ImageFormat.RAW_PRIVATE) {
    836                     throw new UnsupportedOperationException(
    837                             "getPixelStride is not supported for RAW_PRIVATE plane");
    838                 }
    839                 return mPixelStride;
    840             }
    841 
    842             @Override
    843             public int getRowStride() {
    844                 SurfaceImage.this.throwISEIfImageIsInvalid();
    845                 if (ImageReader.this.mFormat == ImageFormat.RAW_PRIVATE) {
    846                     throw new UnsupportedOperationException(
    847                             "getRowStride is not supported for RAW_PRIVATE plane");
    848                 }
    849                 return mRowStride;
    850             }
    851 
    852             private void clearBuffer() {
    853                 // Need null check first, as the getBuffer() may not be called before an image
    854                 // is closed.
    855                 if (mBuffer == null) {
    856                     return;
    857                 }
    858 
    859                 if (mBuffer.isDirect()) {
    860                     NioUtils.freeDirectBuffer(mBuffer);
    861                 }
    862                 mBuffer = null;
    863             }
    864 
    865             final private int mPixelStride;
    866             final private int mRowStride;
    867 
    868             private ByteBuffer mBuffer;
    869         }
    870 
    871         /**
    872          * This field is used to keep track of native object and used by native code only.
    873          * Don't modify.
    874          */
    875         private long mNativeBuffer;
    876 
    877         /**
    878          * This field is set by native code during nativeImageSetup().
    879          */
    880         private long mTimestamp;
    881 
    882         private SurfacePlane[] mPlanes;
    883         private int mFormat = ImageFormat.UNKNOWN;
    884         // If this image is detached from the ImageReader.
    885         private AtomicBoolean mIsDetached = new AtomicBoolean(false);
    886 
    887         private synchronized native SurfacePlane[] nativeCreatePlanes(int numPlanes,
    888                 int readerFormat);
    889         private synchronized native int nativeGetWidth();
    890         private synchronized native int nativeGetHeight();
    891         private synchronized native int nativeGetFormat(int readerFormat);
    892     }
    893 
    894     private synchronized native void nativeInit(Object weakSelf, int w, int h,
    895                                                     int fmt, int maxImgs);
    896     private synchronized native void nativeClose();
    897     private synchronized native void nativeReleaseImage(Image i);
    898     private synchronized native Surface nativeGetSurface();
    899     private synchronized native int nativeDetachImage(Image i);
    900     private synchronized native void nativeDiscardFreeBuffers();
    901 
    902     /**
    903      * @return A return code {@code ACQUIRE_*}
    904      *
    905      * @see #ACQUIRE_SUCCESS
    906      * @see #ACQUIRE_NO_BUFS
    907      * @see #ACQUIRE_MAX_IMAGES
    908      */
    909     private synchronized native int nativeImageSetup(Image i);
    910 
    911     /**
    912      * We use a class initializer to allow the native code to cache some
    913      * field offsets.
    914      */
    915     private static native void nativeClassInit();
    916     static {
    917         System.loadLibrary("media_jni");
    918         nativeClassInit();
    919     }
    920 }
    921