• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.annotation.CallbackExecutor;
20 import android.annotation.IntRange;
21 import android.annotation.NonNull;
22 import android.graphics.GraphicBuffer;
23 import android.graphics.ImageFormat;
24 import android.graphics.ImageFormat.Format;
25 import android.graphics.Rect;
26 import android.hardware.HardwareBuffer;
27 import android.hardware.HardwareBuffer.Usage;
28 import android.hardware.camera2.MultiResolutionImageReader;
29 import android.os.Handler;
30 import android.os.Looper;
31 import android.os.Message;
32 import android.view.Surface;
33 
34 import dalvik.system.VMRuntime;
35 
36 import java.lang.ref.WeakReference;
37 import java.nio.ByteBuffer;
38 import java.nio.ByteOrder;
39 import java.nio.NioUtils;
40 import java.util.List;
41 import java.util.Objects;
42 import java.util.concurrent.CopyOnWriteArrayList;
43 import java.util.concurrent.Executor;
44 import java.util.concurrent.atomic.AtomicBoolean;
45 
46 /**
47  * <p>The ImageReader class allows direct application access to image data
48  * rendered into a {@link android.view.Surface}</p>
49  *
50  * <p>Several Android media API classes accept Surface objects as targets to
51  * render to, including {@link MediaPlayer}, {@link MediaCodec},
52  * {@link android.hardware.camera2.CameraDevice}, {@link ImageWriter} and
53  * {@link android.renderscript.Allocation RenderScript Allocations}. The image
54  * sizes and formats that can be used with each source vary, and should be
55  * checked in the documentation for the specific API.</p>
56  *
57  * <p>The image data is encapsulated in {@link Image} objects, and multiple such
58  * objects can be accessed at the same time, up to the number specified by the
59  * {@code maxImages} constructor parameter. New images sent to an ImageReader
60  * through its {@link Surface} are queued until accessed through the {@link #acquireLatestImage}
61  * or {@link #acquireNextImage} call. Due to memory limits, an image source will
62  * eventually stall or drop Images in trying to render to the Surface if the
63  * ImageReader does not obtain and release Images at a rate equal to the
64  * production rate.</p>
65  */
66 public class ImageReader implements AutoCloseable {
67 
68     /**
69      * Returned by nativeImageSetup when acquiring the image was successful.
70      */
71     private static final int ACQUIRE_SUCCESS = 0;
72     /**
73      * Returned by nativeImageSetup when we couldn't acquire the buffer,
74      * because there were no buffers available to acquire.
75      */
76     private static final int ACQUIRE_NO_BUFS = 1;
77     /**
78      * Returned by nativeImageSetup when we couldn't acquire the buffer
79      * because the consumer has already acquired {@maxImages} and cannot
80      * acquire more than that.
81      */
82     private static final int ACQUIRE_MAX_IMAGES = 2;
83 
84     /**
85      * <p>
86      * Create a new reader for images of the desired size and format.
87      * </p>
88      * <p>
89      * The {@code maxImages} parameter determines the maximum number of
90      * {@link Image} objects that can be be acquired from the
91      * {@code ImageReader} simultaneously. Requesting more buffers will use up
92      * more memory, so it is important to use only the minimum number necessary
93      * for the use case.
94      * </p>
95      * <p>
96      * The valid sizes and formats depend on the source of the image data.
97      * </p>
98      * <p>
99      * If the {@code format} is {@link ImageFormat#PRIVATE PRIVATE}, the created
100      * {@link ImageReader} will produce images that are not directly accessible
101      * by the application. The application can still acquire images from this
102      * {@link ImageReader}, and send them to the
103      * {@link android.hardware.camera2.CameraDevice camera} for reprocessing via
104      * {@link ImageWriter} interface. However, the {@link Image#getPlanes()
105      * getPlanes()} will return an empty array for {@link ImageFormat#PRIVATE
106      * PRIVATE} format images. The application can check if an existing reader's
107      * format by calling {@link #getImageFormat()}.
108      * </p>
109      * <p>
110      * {@link ImageFormat#PRIVATE PRIVATE} format {@link ImageReader
111      * ImageReaders} are more efficient to use when application access to image
112      * data is not necessary, compared to ImageReaders using other format such
113      * as {@link ImageFormat#YUV_420_888 YUV_420_888}.
114      * </p>
115      *
116      * @param width The default width in pixels of the Images that this reader
117      *            will produce.
118      * @param height The default height in pixels of the Images that this reader
119      *            will produce.
120      * @param format The format of the Image that this reader will produce. This
121      *            must be one of the {@link android.graphics.ImageFormat} or
122      *            {@link android.graphics.PixelFormat} constants. Note that not
123      *            all formats are supported, like ImageFormat.NV21.
124      * @param maxImages The maximum number of images the user will want to
125      *            access simultaneously. This should be as small as possible to
126      *            limit memory use. Once maxImages Images are obtained by the
127      *            user, one of them has to be released before a new Image will
128      *            become available for access through
129      *            {@link #acquireLatestImage()} or {@link #acquireNextImage()}.
130      *            Must be greater than 0.
131      * @see Image
132      */
newInstance( @ntRangefrom = 1) int width, @IntRange(from = 1) int height, @Format int format, @IntRange(from = 1) int maxImages)133     public static @NonNull ImageReader newInstance(
134             @IntRange(from = 1) int width,
135             @IntRange(from = 1) int height,
136             @Format             int format,
137             @IntRange(from = 1) int maxImages) {
138         // If the format is private don't default to USAGE_CPU_READ_OFTEN since it may not
139         // work, and is inscrutable anyway
140         return new ImageReader(width, height, format, maxImages,
141                 format == ImageFormat.PRIVATE ? 0 : HardwareBuffer.USAGE_CPU_READ_OFTEN,
142                 /*parent*/ null);
143     }
144 
145     /**
146      * <p>
147      * Create a new reader for images of the desired size, format and consumer usage flag.
148      * </p>
149      * <p>
150      * The {@code maxImages} parameter determines the maximum number of {@link Image} objects that
151      * can be be acquired from the {@code ImageReader} simultaneously. Requesting more buffers will
152      * use up more memory, so it is important to use only the minimum number necessary for the use
153      * case.
154      * </p>
155      * <p>
156      * The valid sizes and formats depend on the source of the image data.
157      * </p>
158      * <p>
159      * The format and usage flag combination describes how the buffer will be used by
160      * consumer end-points. For example, if the application intends to send the images to
161      * {@link android.media.MediaCodec} or {@link android.media.MediaRecorder} for hardware video
162      * encoding, the format and usage flag combination needs to be
163      * {@link ImageFormat#PRIVATE PRIVATE} and {@link HardwareBuffer#USAGE_VIDEO_ENCODE}. When an
164      * {@link ImageReader} object is created with a valid size and such format/usage flag
165      * combination, the application can send the {@link Image images} to an {@link ImageWriter} that
166      * is created with the input {@link android.view.Surface} provided by the
167      * {@link android.media.MediaCodec} or {@link android.media.MediaRecorder}.
168      * </p>
169      * <p>
170      * If the {@code format} is {@link ImageFormat#PRIVATE PRIVATE}, the created {@link ImageReader}
171      * will produce images that are not directly accessible by the application. The application can
172      * still acquire images from this {@link ImageReader}, and send them to the
173      * {@link android.hardware.camera2.CameraDevice camera} for reprocessing, or to the
174      * {@link android.media.MediaCodec} / {@link android.media.MediaRecorder} for hardware video
175      * encoding via {@link ImageWriter} interface. However, the {@link Image#getPlanes()
176      * getPlanes()} will return an empty array for {@link ImageFormat#PRIVATE PRIVATE} format
177      * images. The application can check if an existing reader's format by calling
178      * {@link #getImageFormat()}.
179      * </p>
180      * <p>
181      * {@link ImageFormat#PRIVATE PRIVATE} format {@link ImageReader ImageReaders} are more
182      * efficient to use when application access to image data is not necessary, compared to
183      * ImageReaders using other format such as {@link ImageFormat#YUV_420_888 YUV_420_888}.
184      * </p>
185      * <p>
186      * Note that not all format and usage flag combinations are supported by the
187      * {@link ImageReader}. Below are the supported combinations by the {@link ImageReader}
188      * (assuming the consumer end-points support the such image consumption, e.g., hardware video
189      * encoding).
190      * <table>
191      * <tr>
192      *   <th>Format</th>
193      *   <th>Compatible usage flags</th>
194      * </tr>
195      * <tr>
196      *   <td>non-{@link android.graphics.ImageFormat#PRIVATE PRIVATE} formats defined by
197      *   {@link android.graphics.ImageFormat ImageFormat} or
198      *   {@link android.graphics.PixelFormat PixelFormat}</td>
199      *   <td>{@link HardwareBuffer#USAGE_CPU_READ_RARELY} or
200      *   {@link HardwareBuffer#USAGE_CPU_READ_OFTEN}</td>
201      * </tr>
202      * <tr>
203      *   <td>{@link android.graphics.ImageFormat#PRIVATE}</td>
204      *   <td>{@link HardwareBuffer#USAGE_VIDEO_ENCODE} or
205      *   {@link HardwareBuffer#USAGE_GPU_SAMPLED_IMAGE}, or combined</td>
206      * </tr>
207      * </table>
208      * Using other combinations may result in {@link IllegalArgumentException}. Additionally,
209      * specifying {@link HardwareBuffer#USAGE_CPU_WRITE_RARELY} or
210      * {@link HardwareBuffer#USAGE_CPU_WRITE_OFTEN} and writing to the ImageReader's buffers
211      * might break assumptions made by some producers, and should be used with caution.
212      * </p>
213      * <p>
214      * If the {@link ImageReader} is used as an output target for a {@link
215      * android.hardware.camera2.CameraDevice}, and if the usage flag contains
216      * {@link HardwareBuffer#USAGE_VIDEO_ENCODE}, the timestamps of the
217      * {@link Image images} produced by the {@link ImageReader} won't be in the same timebase as
218      * {@link android.os.SystemClock#elapsedRealtimeNanos}, even if
219      * {@link android.hardware.camera2.CameraCharacteristics#SENSOR_INFO_TIMESTAMP_SOURCE} is
220      * {@link android.hardware.camera2.CameraCharacteristics#SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME}.
221      * Instead, the timestamps will be roughly in the same timebase as in
222      * {@link android.os.SystemClock#uptimeMillis}, so that A/V synchronization could work for
223      * video recording. In this case, the timestamps from the {@link ImageReader} with
224      * {@link HardwareBuffer#USAGE_VIDEO_ENCODE} usage flag may not be directly comparable with
225      * timestamps of other streams or capture result metadata.
226      * </p>
227      * @param width The default width in pixels of the Images that this reader will produce.
228      * @param height The default height in pixels of the Images that this reader will produce.
229      * @param format The format of the Image that this reader will produce. This must be one of the
230      *            {@link android.graphics.ImageFormat} or {@link android.graphics.PixelFormat}
231      *            constants. Note that not all formats are supported, like ImageFormat.NV21.
232      * @param maxImages The maximum number of images the user will want to access simultaneously.
233      *            This should be as small as possible to limit memory use. Once maxImages Images are
234      *            obtained by the user, one of them has to be released before a new Image will
235      *            become available for access through {@link #acquireLatestImage()} or
236      *            {@link #acquireNextImage()}. Must be greater than 0.
237      * @param usage The intended usage of the images produced by this ImageReader. See the usages
238      *              on {@link HardwareBuffer} for a list of valid usage bits. See also
239      *              {@link HardwareBuffer#isSupported(int, int, int, int, long)} for checking
240      *              if a combination is supported. If it's not supported this will throw
241      *              an {@link IllegalArgumentException}.
242      * @see Image
243      * @see HardwareBuffer
244      */
newInstance( @ntRangefrom = 1) int width, @IntRange(from = 1) int height, @Format int format, @IntRange(from = 1) int maxImages, @Usage long usage)245     public static @NonNull ImageReader newInstance(
246             @IntRange(from = 1) int width,
247             @IntRange(from = 1) int height,
248             @Format             int format,
249             @IntRange(from = 1) int maxImages,
250             @Usage              long usage) {
251         // TODO: Check this - can't do it just yet because format support is different
252         // Unify formats! The only reliable way to validate usage is to just try it and see.
253 
254 //        if (!HardwareBuffer.isSupported(width, height, format, 1, usage)) {
255 //            throw new IllegalArgumentException("The given format=" + Integer.toHexString(format)
256 //                + " & usage=" + Long.toHexString(usage) + " is not supported");
257 //        }
258         return new ImageReader(width, height, format, maxImages, usage, /*parent*/ null);
259     }
260 
261      /**
262       * @hide
263       */
newInstance( @ntRangefrom = 1) int width, @IntRange(from = 1) int height, @Format int format, @IntRange(from = 1) int maxImages, @NonNull MultiResolutionImageReader parent)264      public static @NonNull ImageReader newInstance(
265             @IntRange(from = 1) int width,
266             @IntRange(from = 1) int height,
267             @Format             int format,
268             @IntRange(from = 1) int maxImages,
269             @NonNull            MultiResolutionImageReader parent) {
270         // If the format is private don't default to USAGE_CPU_READ_OFTEN since it may not
271         // work, and is inscrutable anyway
272         return new ImageReader(width, height, format, maxImages,
273                 format == ImageFormat.PRIVATE ? 0 : HardwareBuffer.USAGE_CPU_READ_OFTEN,
274                 parent);
275     }
276 
277 
278     /**
279      * @hide
280      */
ImageReader(int width, int height, int format, int maxImages, long usage, MultiResolutionImageReader parent)281     protected ImageReader(int width, int height, int format, int maxImages, long usage,
282             MultiResolutionImageReader parent) {
283         mWidth = width;
284         mHeight = height;
285         mFormat = format;
286         mUsage = usage;
287         mMaxImages = maxImages;
288         mParent = parent;
289 
290         if (width < 1 || height < 1) {
291             throw new IllegalArgumentException(
292                 "The image dimensions must be positive");
293         }
294         if (mMaxImages < 1) {
295             throw new IllegalArgumentException(
296                 "Maximum outstanding image count must be at least 1");
297         }
298 
299         if (format == ImageFormat.NV21) {
300             throw new IllegalArgumentException(
301                     "NV21 format is not supported");
302         }
303 
304         mNumPlanes = ImageUtils.getNumPlanesForFormat(mFormat);
305 
306         nativeInit(new WeakReference<>(this), width, height, format, maxImages, usage);
307 
308         mSurface = nativeGetSurface();
309 
310         mIsReaderValid = true;
311         // Estimate the native buffer allocation size and register it so it gets accounted for
312         // during GC. Note that this doesn't include the buffers required by the buffer queue
313         // itself and the buffers requested by the producer.
314         // Only include memory for 1 buffer, since actually accounting for the memory used is
315         // complex, and 1 buffer is enough for the VM to treat the ImageReader as being of some
316         // size.
317         mEstimatedNativeAllocBytes = ImageUtils.getEstimatedNativeAllocBytes(
318                 width, height, format, /*buffer count*/ 1);
319         VMRuntime.getRuntime().registerNativeAllocation(mEstimatedNativeAllocBytes);
320     }
321 
322     /**
323      * The default width of {@link Image Images}, in pixels.
324      *
325      * <p>The width may be overridden by the producer sending buffers to this
326      * ImageReader's Surface. If so, the actual width of the images can be
327      * found using {@link Image#getWidth}.</p>
328      *
329      * @return the expected width of an Image
330      */
getWidth()331     public int getWidth() {
332         return mWidth;
333     }
334 
335     /**
336      * The default height of {@link Image Images}, in pixels.
337      *
338      * <p>The height may be overridden by the producer sending buffers to this
339      * ImageReader's Surface. If so, the actual height of the images can be
340      * found using {@link Image#getHeight}.</p>
341      *
342      * @return the expected height of an Image
343      */
getHeight()344     public int getHeight() {
345         return mHeight;
346     }
347 
348     /**
349      * The default {@link ImageFormat image format} of {@link Image Images}.
350      *
351      * <p>Some color formats may be overridden by the producer sending buffers to
352      * this ImageReader's Surface if the default color format allows. ImageReader
353      * guarantees that all {@link Image Images} acquired from ImageReader
354      * (for example, with {@link #acquireNextImage}) will have a "compatible"
355      * format to what was specified in {@link #newInstance}.
356      * As of now, each format is only compatible to itself.
357      * The actual format of the images can be found using {@link Image#getFormat}.</p>
358      *
359      * @return the expected format of an Image
360      *
361      * @see ImageFormat
362      */
getImageFormat()363     public int getImageFormat() {
364         return mFormat;
365     }
366 
367     /**
368      * Maximum number of images that can be acquired from the ImageReader by any time (for example,
369      * with {@link #acquireNextImage}).
370      *
371      * <p>An image is considered acquired after it's returned by a function from ImageReader, and
372      * until the Image is {@link Image#close closed} to release the image back to the ImageReader.
373      * </p>
374      *
375      * <p>Attempting to acquire more than {@code maxImages} concurrently will result in the
376      * acquire function throwing a {@link IllegalStateException}. Furthermore,
377      * while the max number of images have been acquired by the ImageReader user, the producer
378      * enqueueing additional images may stall until at least one image has been released. </p>
379      *
380      * @return Maximum number of images for this ImageReader.
381      *
382      * @see Image#close
383      */
getMaxImages()384     public int getMaxImages() {
385         return mMaxImages;
386     }
387 
388     /**
389      * <p>Get a {@link Surface} that can be used to produce {@link Image Images} for this
390      * {@code ImageReader}.</p>
391      *
392      * <p>Until valid image data is rendered into this {@link Surface}, the
393      * {@link #acquireNextImage} method will return {@code null}. Only one source
394      * can be producing data into this Surface at the same time, although the
395      * same {@link Surface} can be reused with a different API once the first source is
396      * disconnected from the {@link Surface}.</p>
397      *
398      * <p>Please note that holding on to the Surface object returned by this method is not enough
399      * to keep its parent ImageReader from being reclaimed. In that sense, a Surface acts like a
400      * {@link java.lang.ref.WeakReference weak reference} to the ImageReader that provides it.</p>
401      *
402      * @return A {@link Surface} to use for a drawing target for various APIs.
403      */
getSurface()404     public Surface getSurface() {
405         return mSurface;
406     }
407 
408     /**
409      * <p>
410      * Acquire the latest {@link Image} from the ImageReader's queue, dropping older
411      * {@link Image images}. Returns {@code null} if no new image is available.
412      * </p>
413      * <p>
414      * This operation will acquire all the images possible from the ImageReader,
415      * but {@link #close} all images that aren't the latest. This function is
416      * recommended to use over {@link #acquireNextImage} for most use-cases, as it's
417      * more suited for real-time processing.
418      * </p>
419      * <p>
420      * Note that {@link #getMaxImages maxImages} should be at least 2 for
421      * {@link #acquireLatestImage} to be any different than {@link #acquireNextImage} -
422      * discarding all-but-the-newest {@link Image} requires temporarily acquiring two
423      * {@link Image Images} at once. Or more generally, calling {@link #acquireLatestImage}
424      * with less than two images of margin, that is
425      * {@code (maxImages - currentAcquiredImages < 2)} will not discard as expected.
426      * </p>
427      * <p>
428      * This operation will fail by throwing an {@link IllegalStateException} if
429      * {@code maxImages} have been acquired with {@link #acquireLatestImage} or
430      * {@link #acquireNextImage}. In particular a sequence of {@link #acquireLatestImage}
431      * calls greater than {@link #getMaxImages} without calling {@link Image#close} in-between
432      * will exhaust the underlying queue. At such a time, {@link IllegalStateException}
433      * will be thrown until more images are
434      * released with {@link Image#close}.
435      * </p>
436      *
437      * @return latest frame of image data, or {@code null} if no image data is available.
438      * @throws IllegalStateException if too many images are currently acquired
439      */
acquireLatestImage()440     public Image acquireLatestImage() {
441         Image image = acquireNextImage();
442         if (image == null) {
443             return null;
444         }
445         try {
446             for (;;) {
447                 Image next = acquireNextImageNoThrowISE();
448                 if (next == null) {
449                     Image result = image;
450                     image = null;
451                     return result;
452                 }
453                 image.close();
454                 image = next;
455             }
456         } finally {
457             if (image != null) {
458                 image.close();
459             }
460             if (mParent != null) {
461                 mParent.flushOther(this);
462             }
463         }
464     }
465 
466     /**
467      * Don't throw IllegalStateException if there are too many images acquired.
468      *
469      * @return Image if acquiring succeeded, or null otherwise.
470      *
471      * @hide
472      */
acquireNextImageNoThrowISE()473     public Image acquireNextImageNoThrowISE() {
474         SurfaceImage si = new SurfaceImage(mFormat);
475         return acquireNextSurfaceImage(si) == ACQUIRE_SUCCESS ? si : null;
476     }
477 
478     /**
479      * Attempts to acquire the next image from the underlying native implementation.
480      *
481      * <p>
482      * Note that unexpected failures will throw at the JNI level.
483      * </p>
484      *
485      * @param si A blank SurfaceImage.
486      * @return One of the {@code ACQUIRE_*} codes that determine success or failure.
487      *
488      * @see #ACQUIRE_MAX_IMAGES
489      * @see #ACQUIRE_NO_BUFS
490      * @see #ACQUIRE_SUCCESS
491      */
acquireNextSurfaceImage(SurfaceImage si)492     private int acquireNextSurfaceImage(SurfaceImage si) {
493         synchronized (mCloseLock) {
494             // A null image will eventually be returned if ImageReader is already closed.
495             int status = ACQUIRE_NO_BUFS;
496             if (mIsReaderValid) {
497                 status = nativeImageSetup(si);
498             }
499 
500             switch (status) {
501                 case ACQUIRE_SUCCESS:
502                     si.mIsImageValid = true;
503                 case ACQUIRE_NO_BUFS:
504                 case ACQUIRE_MAX_IMAGES:
505                     break;
506                 default:
507                     throw new AssertionError("Unknown nativeImageSetup return code " + status);
508             }
509 
510             // Only keep track the successfully acquired image, as the native buffer is only mapped
511             // for such case.
512             if (status == ACQUIRE_SUCCESS) {
513                 mAcquiredImages.add(si);
514             }
515             return status;
516         }
517     }
518 
519     /**
520      * <p>
521      * Acquire the next Image from the ImageReader's queue. Returns {@code null} if
522      * no new image is available.
523      * </p>
524      *
525      * <p><i>Warning:</i> Consider using {@link #acquireLatestImage()} instead, as it will
526      * automatically release older images, and allow slower-running processing routines to catch
527      * up to the newest frame. Usage of {@link #acquireNextImage} is recommended for
528      * batch/background processing. Incorrectly using this function can cause images to appear
529      * with an ever-increasing delay, followed by a complete stall where no new images seem to
530      * appear.
531      * </p>
532      *
533      * <p>
534      * This operation will fail by throwing an {@link IllegalStateException} if
535      * {@code maxImages} have been acquired with {@link #acquireNextImage} or
536      * {@link #acquireLatestImage}. In particular a sequence of {@link #acquireNextImage} or
537      * {@link #acquireLatestImage} calls greater than {@link #getMaxImages maxImages} without
538      * calling {@link Image#close} in-between will exhaust the underlying queue. At such a time,
539      * {@link IllegalStateException} will be thrown until more images are released with
540      * {@link Image#close}.
541      * </p>
542      *
543      * @return a new frame of image data, or {@code null} if no image data is available.
544      * @throws IllegalStateException if {@code maxImages} images are currently acquired
545      * @see #acquireLatestImage
546      */
acquireNextImage()547     public Image acquireNextImage() {
548         // Initialize with reader format, but can be overwritten by native if the image
549         // format is different from the reader format.
550         SurfaceImage si = new SurfaceImage(mFormat);
551         int status = acquireNextSurfaceImage(si);
552 
553         switch (status) {
554             case ACQUIRE_SUCCESS:
555                 return si;
556             case ACQUIRE_NO_BUFS:
557                 return null;
558             case ACQUIRE_MAX_IMAGES:
559                 throw new IllegalStateException(
560                         String.format(
561                                 "maxImages (%d) has already been acquired, " +
562                                 "call #close before acquiring more.", mMaxImages));
563             default:
564                 throw new AssertionError("Unknown nativeImageSetup return code " + status);
565         }
566     }
567 
568     /**
569      * <p>Return the frame to the ImageReader for reuse.</p>
570      */
releaseImage(Image i)571     private void releaseImage(Image i) {
572         if (! (i instanceof SurfaceImage) ) {
573             throw new IllegalArgumentException(
574                 "This image was not produced by an ImageReader");
575         }
576         SurfaceImage si = (SurfaceImage) i;
577         if (si.mIsImageValid == false) {
578             return;
579         }
580 
581         if (si.getReader() != this || !mAcquiredImages.contains(i)) {
582             throw new IllegalArgumentException(
583                 "This image was not produced by this ImageReader");
584         }
585 
586         si.clearSurfacePlanes();
587         nativeReleaseImage(i);
588         si.mIsImageValid = false;
589         mAcquiredImages.remove(i);
590     }
591 
592     /**
593      * Register a listener to be invoked when a new image becomes available
594      * from the ImageReader.
595      *
596      * @param listener
597      *            The listener that will be run.
598      * @param handler
599      *            The handler on which the listener should be invoked, or null
600      *            if the listener should be invoked on the calling thread's looper.
601      * @throws IllegalArgumentException
602      *            If no handler specified and the calling thread has no looper.
603      */
setOnImageAvailableListener(OnImageAvailableListener listener, Handler handler)604     public void setOnImageAvailableListener(OnImageAvailableListener listener, Handler handler) {
605         synchronized (mListenerLock) {
606             if (listener != null) {
607                 Looper looper = handler != null ? handler.getLooper() : Looper.myLooper();
608                 if (looper == null) {
609                     throw new IllegalArgumentException(
610                             "handler is null but the current thread is not a looper");
611                 }
612                 if (mListenerHandler == null || mListenerHandler.getLooper() != looper) {
613                     mListenerHandler = new ListenerHandler(looper);
614                     mListenerExecutor = new HandlerExecutor(mListenerHandler);
615                 }
616             } else {
617                 mListenerHandler = null;
618                 mListenerExecutor = null;
619             }
620             mListener = listener;
621         }
622     }
623 
624     /**
625      * Register a listener to be invoked when a new image becomes available
626      * from the ImageReader.
627      *
628      * @param listener
629      *            The listener that will be run.
630      * @param executor
631      *            The executor which will be used to invoke the listener.
632      * @throws IllegalArgumentException
633      *            If no handler specified and the calling thread has no looper.
634      *
635      * @hide
636      */
setOnImageAvailableListenerWithExecutor(@onNull OnImageAvailableListener listener, @NonNull Executor executor)637     public void setOnImageAvailableListenerWithExecutor(@NonNull OnImageAvailableListener listener,
638             @NonNull Executor executor) {
639         if (executor == null) {
640             throw new IllegalArgumentException("executor must not be null");
641         }
642 
643         synchronized (mListenerLock) {
644             mListenerExecutor = executor;
645             mListener = listener;
646         }
647     }
648 
649     /**
650      * Callback interface for being notified that a new image is available.
651      *
652      * <p>
653      * The onImageAvailable is called per image basis, that is, callback fires for every new frame
654      * available from ImageReader.
655      * </p>
656      */
657     public interface OnImageAvailableListener {
658         /**
659          * Callback that is called when a new image is available from ImageReader.
660          *
661          * @param reader the ImageReader the callback is associated with.
662          * @see ImageReader
663          * @see Image
664          */
onImageAvailable(ImageReader reader)665         void onImageAvailable(ImageReader reader);
666     }
667 
668     /**
669      * Free up all the resources associated with this ImageReader.
670      *
671      * <p>
672      * After calling this method, this ImageReader can not be used. Calling
673      * any methods on this ImageReader and Images previously provided by
674      * {@link #acquireNextImage} or {@link #acquireLatestImage}
675      * will result in an {@link IllegalStateException}, and attempting to read from
676      * {@link ByteBuffer ByteBuffers} returned by an earlier
677      * {@link Image.Plane#getBuffer Plane#getBuffer} call will
678      * have undefined behavior.
679      * </p>
680      */
681     @Override
close()682     public void close() {
683         setOnImageAvailableListener(null, null);
684         if (mSurface != null) mSurface.release();
685 
686         /**
687          * Close all outstanding acquired images before closing the ImageReader. It is a good
688          * practice to close all the images as soon as it is not used to reduce system instantaneous
689          * memory pressure. CopyOnWrite list will use a copy of current list content. For the images
690          * being closed by other thread (e.g., GC thread), doubling the close call is harmless. For
691          * the image being acquired by other threads, mCloseLock is used to synchronize close and
692          * acquire operations.
693          */
694         synchronized (mCloseLock) {
695             mIsReaderValid = false;
696             for (Image image : mAcquiredImages) {
697                 image.close();
698             }
699             mAcquiredImages.clear();
700 
701             nativeClose();
702 
703             if (mEstimatedNativeAllocBytes > 0) {
704                 VMRuntime.getRuntime().registerNativeFree(mEstimatedNativeAllocBytes);
705                 mEstimatedNativeAllocBytes = 0;
706             }
707         }
708     }
709 
710     /**
711      * Discard any free buffers owned by this ImageReader.
712      *
713      * <p>
714      * Generally, the ImageReader caches buffers for reuse once they have been
715      * allocated, for best performance. However, sometimes it may be important to
716      * release all the cached, unused buffers to save on memory.
717      * </p>
718      * <p>
719      * Calling this method will discard all free cached buffers. This does not include any buffers
720      * associated with Images acquired from the ImageReader, any filled buffers waiting to be
721      * acquired, and any buffers currently in use by the source rendering buffers into the
722      * ImageReader's Surface.
723      * <p>
724      * The ImageReader continues to be usable after this call, but may need to reallocate buffers
725      * when more buffers are needed for rendering.
726      * </p>
727      */
discardFreeBuffers()728     public void discardFreeBuffers() {
729         synchronized (mCloseLock) {
730             nativeDiscardFreeBuffers();
731         }
732     }
733 
734     @Override
finalize()735     protected void finalize() throws Throwable {
736         try {
737             close();
738         } finally {
739             super.finalize();
740         }
741     }
742 
743     /**
744      * <p>
745      * Remove the ownership of this image from the ImageReader.
746      * </p>
747      * <p>
748      * After this call, the ImageReader no longer owns this image, and the image
749      * ownership can be transfered to another entity like {@link ImageWriter}
750      * via {@link ImageWriter#queueInputImage}. It's up to the new owner to
751      * release the resources held by this image. For example, if the ownership
752      * of this image is transfered to an {@link ImageWriter}, the image will be
753      * freed by the ImageWriter after the image data consumption is done.
754      * </p>
755      * <p>
756      * This method can be used to achieve zero buffer copy for use cases like
757      * {@link android.hardware.camera2.CameraDevice Camera2 API} PRIVATE and YUV
758      * reprocessing, where the application can select an output image from
759      * {@link ImageReader} and transfer this image directly to
760      * {@link ImageWriter}, where this image can be consumed by camera directly.
761      * For PRIVATE reprocessing, this is the only way to send input buffers to
762      * the {@link android.hardware.camera2.CameraDevice camera} for
763      * reprocessing.
764      * </p>
765      * <p>
766      * This is a package private method that is only used internally.
767      * </p>
768      *
769      * @param image The image to be detached from this ImageReader.
770      * @throws IllegalStateException If the ImageReader or image have been
771      *             closed, or the has been detached, or has not yet been
772      *             acquired.
773      * @hide
774      */
detachImage(Image image)775      public void detachImage(Image image) {
776        if (image == null) {
777            throw new IllegalArgumentException("input image must not be null");
778        }
779        if (!isImageOwnedbyMe(image)) {
780            throw new IllegalArgumentException("Trying to detach an image that is not owned by"
781                    + " this ImageReader");
782        }
783 
784         SurfaceImage si = (SurfaceImage) image;
785         si.throwISEIfImageIsInvalid();
786 
787         if (si.isAttachable()) {
788             throw new IllegalStateException("Image was already detached from this ImageReader");
789         }
790 
791         nativeDetachImage(image);
792         si.clearSurfacePlanes();
793         si.mPlanes = null;
794         si.setDetached(true);
795     }
796 
isImageOwnedbyMe(Image image)797     private boolean isImageOwnedbyMe(Image image) {
798         if (!(image instanceof SurfaceImage)) {
799             return false;
800         }
801         SurfaceImage si = (SurfaceImage) image;
802         return si.getReader() == this;
803     }
804 
805     /**
806      * Called from Native code when an Event happens.
807      *
808      * This may be called from an arbitrary Binder thread, so access to the ImageReader must be
809      * synchronized appropriately.
810      */
postEventFromNative(Object selfRef)811     private static void postEventFromNative(Object selfRef) {
812         @SuppressWarnings("unchecked")
813         WeakReference<ImageReader> weakSelf = (WeakReference<ImageReader>)selfRef;
814         final ImageReader ir = weakSelf.get();
815         if (ir == null) {
816             return;
817         }
818 
819         final Executor executor;
820         final OnImageAvailableListener listener;
821         synchronized (ir.mListenerLock) {
822             executor = ir.mListenerExecutor;
823             listener = ir.mListener;
824         }
825         final boolean isReaderValid;
826         synchronized (ir.mCloseLock) {
827             isReaderValid = ir.mIsReaderValid;
828         }
829 
830         // It's dangerous to fire onImageAvailable() callback when the ImageReader
831         // is being closed, as application could acquire next image in the
832         // onImageAvailable() callback.
833         if (executor != null && listener != null && isReaderValid) {
834             executor.execute(new Runnable() {
835                 @Override
836                 public void run() {
837                     listener.onImageAvailable(ir);
838                 }
839             });
840         }
841     }
842 
843     private final int mWidth;
844     private final int mHeight;
845     private final int mFormat;
846     private final long mUsage;
847     private final int mMaxImages;
848     private final int mNumPlanes;
849     private final Surface mSurface;
850     private int mEstimatedNativeAllocBytes;
851 
852     private final Object mListenerLock = new Object();
853     private final Object mCloseLock = new Object();
854     private boolean mIsReaderValid = false;
855     private OnImageAvailableListener mListener;
856     private Executor mListenerExecutor;
857     private ListenerHandler mListenerHandler;
858     // Keep track of the successfully acquired Images. This need to be thread safe as the images
859     // could be closed by different threads (e.g., application thread and GC thread).
860     private List<Image> mAcquiredImages = new CopyOnWriteArrayList<>();
861 
862     // Applicable if this isn't a standalone ImageReader, but belongs to a
863     // MultiResolutionImageReader.
864     private final MultiResolutionImageReader mParent;
865 
866     /**
867      * This field is used by native code, do not access or modify.
868      */
869     private long mNativeContext;
870 
871     /**
872      * This custom handler runs asynchronously so callbacks don't get queued behind UI messages.
873      */
874     private final class ListenerHandler extends Handler {
ListenerHandler(Looper looper)875         public ListenerHandler(Looper looper) {
876             super(looper, null, true /*async*/);
877         }
878     }
879 
880     /**
881      * An adapter {@link Executor} that posts all executed tasks onto the
882      * given {@link Handler}.
883      **/
884     private final class HandlerExecutor implements Executor {
885         private final Handler mHandler;
886 
HandlerExecutor(@onNull Handler handler)887         public HandlerExecutor(@NonNull Handler handler) {
888             mHandler = Objects.requireNonNull(handler);
889         }
890 
891         @Override
execute(Runnable command)892         public void execute(Runnable command) {
893             mHandler.post(command);
894         }
895     }
896 
897     private class SurfaceImage extends android.media.Image {
SurfaceImage(int format)898         public SurfaceImage(int format) {
899             mFormat = format;
900         }
901 
902         @Override
close()903         public void close() {
904             ImageReader.this.releaseImage(this);
905         }
906 
getReader()907         public ImageReader getReader() {
908             return ImageReader.this;
909         }
910 
911         @Override
getFormat()912         public int getFormat() {
913             throwISEIfImageIsInvalid();
914             int readerFormat = ImageReader.this.getImageFormat();
915             // Assume opaque reader always produce opaque images.
916             mFormat = (readerFormat == ImageFormat.PRIVATE) ? readerFormat :
917                 nativeGetFormat(readerFormat);
918             return mFormat;
919         }
920 
921         @Override
getWidth()922         public int getWidth() {
923             throwISEIfImageIsInvalid();
924             int width;
925             switch(getFormat()) {
926                 case ImageFormat.JPEG:
927                 case ImageFormat.DEPTH_POINT_CLOUD:
928                 case ImageFormat.RAW_PRIVATE:
929                 case ImageFormat.DEPTH_JPEG:
930                 case ImageFormat.HEIC:
931                     width = ImageReader.this.getWidth();
932                     break;
933                 default:
934                     width = nativeGetWidth();
935             }
936             return width;
937         }
938 
939         @Override
getHeight()940         public int getHeight() {
941             throwISEIfImageIsInvalid();
942             int height;
943             switch(getFormat()) {
944                 case ImageFormat.JPEG:
945                 case ImageFormat.DEPTH_POINT_CLOUD:
946                 case ImageFormat.RAW_PRIVATE:
947                 case ImageFormat.DEPTH_JPEG:
948                 case ImageFormat.HEIC:
949                     height = ImageReader.this.getHeight();
950                     break;
951                 default:
952                     height = nativeGetHeight();
953             }
954             return height;
955         }
956 
957         @Override
getTimestamp()958         public long getTimestamp() {
959             throwISEIfImageIsInvalid();
960             return mTimestamp;
961         }
962 
963         @Override
getTransform()964         public int getTransform() {
965             throwISEIfImageIsInvalid();
966             return mTransform;
967         }
968 
969         @Override
getScalingMode()970         public int getScalingMode() {
971             throwISEIfImageIsInvalid();
972             return mScalingMode;
973         }
974 
975         @Override
getPlaneCount()976         public int getPlaneCount() {
977             throwISEIfImageIsInvalid();
978             return ImageReader.this.mNumPlanes;
979         }
980 
981         @Override
getFenceFd()982         public int getFenceFd() {
983             throwISEIfImageIsInvalid();
984             return nativeGetFenceFd();
985         }
986 
987         @Override
getHardwareBuffer()988         public HardwareBuffer getHardwareBuffer() {
989             throwISEIfImageIsInvalid();
990             return nativeGetHardwareBuffer();
991         }
992 
993         @Override
setTimestamp(long timestampNs)994         public void setTimestamp(long timestampNs) {
995             throwISEIfImageIsInvalid();
996             mTimestamp = timestampNs;
997         }
998 
999         @Override
getPlanes()1000         public Plane[] getPlanes() {
1001             throwISEIfImageIsInvalid();
1002 
1003             if (mPlanes == null) {
1004                 mPlanes = nativeCreatePlanes(ImageReader.this.mNumPlanes, ImageReader.this.mFormat,
1005                         ImageReader.this.mUsage);
1006             }
1007             // Shallow copy is fine.
1008             return mPlanes.clone();
1009         }
1010 
1011         @Override
finalize()1012         protected final void finalize() throws Throwable {
1013             try {
1014                 close();
1015             } finally {
1016                 super.finalize();
1017             }
1018         }
1019 
1020         @Override
isAttachable()1021         public boolean isAttachable() {
1022             throwISEIfImageIsInvalid();
1023             return mIsDetached.get();
1024         }
1025 
1026         @Override
getOwner()1027         ImageReader getOwner() {
1028             throwISEIfImageIsInvalid();
1029             return ImageReader.this;
1030         }
1031 
1032         @Override
getNativeContext()1033         long getNativeContext() {
1034             throwISEIfImageIsInvalid();
1035             return mNativeBuffer;
1036         }
1037 
setDetached(boolean detached)1038         private void setDetached(boolean detached) {
1039             throwISEIfImageIsInvalid();
1040             mIsDetached.getAndSet(detached);
1041         }
1042 
clearSurfacePlanes()1043         private void clearSurfacePlanes() {
1044             // Image#getPlanes may not be called before the image is closed.
1045             if (mIsImageValid && mPlanes != null) {
1046                 for (int i = 0; i < mPlanes.length; i++) {
1047                     if (mPlanes[i] != null) {
1048                         mPlanes[i].clearBuffer();
1049                         mPlanes[i] = null;
1050                     }
1051                 }
1052             }
1053         }
1054 
1055         private class SurfacePlane extends android.media.Image.Plane {
1056             // SurfacePlane instance is created by native code when SurfaceImage#getPlanes() is
1057             // called
SurfacePlane(int rowStride, int pixelStride, ByteBuffer buffer)1058             private SurfacePlane(int rowStride, int pixelStride, ByteBuffer buffer) {
1059                 mRowStride = rowStride;
1060                 mPixelStride = pixelStride;
1061                 mBuffer = buffer;
1062                 /**
1063                  * Set the byteBuffer order according to host endianness (native
1064                  * order), otherwise, the byteBuffer order defaults to
1065                  * ByteOrder.BIG_ENDIAN.
1066                  */
1067                 mBuffer.order(ByteOrder.nativeOrder());
1068             }
1069 
1070             @Override
getBuffer()1071             public ByteBuffer getBuffer() {
1072                 throwISEIfImageIsInvalid();
1073                 return mBuffer;
1074             }
1075 
1076             @Override
getPixelStride()1077             public int getPixelStride() {
1078                 SurfaceImage.this.throwISEIfImageIsInvalid();
1079                 if (ImageReader.this.mFormat == ImageFormat.RAW_PRIVATE) {
1080                     throw new UnsupportedOperationException(
1081                             "getPixelStride is not supported for RAW_PRIVATE plane");
1082                 }
1083                 return mPixelStride;
1084             }
1085 
1086             @Override
getRowStride()1087             public int getRowStride() {
1088                 SurfaceImage.this.throwISEIfImageIsInvalid();
1089                 if (ImageReader.this.mFormat == ImageFormat.RAW_PRIVATE) {
1090                     throw new UnsupportedOperationException(
1091                             "getRowStride is not supported for RAW_PRIVATE plane");
1092                 }
1093                 return mRowStride;
1094             }
1095 
clearBuffer()1096             private void clearBuffer() {
1097                 // Need null check first, as the getBuffer() may not be called before an image
1098                 // is closed.
1099                 if (mBuffer == null) {
1100                     return;
1101                 }
1102 
1103                 if (mBuffer.isDirect()) {
1104                     NioUtils.freeDirectBuffer(mBuffer);
1105                 }
1106                 mBuffer = null;
1107             }
1108 
1109             final private int mPixelStride;
1110             final private int mRowStride;
1111 
1112             private ByteBuffer mBuffer;
1113         }
1114 
1115         /**
1116          * This field is used to keep track of native object and used by native code only.
1117          * Don't modify.
1118          */
1119         private long mNativeBuffer;
1120 
1121         /**
1122          * These fields are set by native code during nativeImageSetup().
1123          */
1124         private long mTimestamp;
1125         private int mTransform;
1126         private int mScalingMode;
1127 
1128         private SurfacePlane[] mPlanes;
1129         private int mFormat = ImageFormat.UNKNOWN;
1130         // If this image is detached from the ImageReader.
1131         private AtomicBoolean mIsDetached = new AtomicBoolean(false);
1132 
nativeCreatePlanes(int numPlanes, int readerFormat, long readerUsage)1133         private synchronized native SurfacePlane[] nativeCreatePlanes(int numPlanes,
1134                 int readerFormat, long readerUsage);
nativeGetWidth()1135         private synchronized native int nativeGetWidth();
nativeGetHeight()1136         private synchronized native int nativeGetHeight();
nativeGetFormat(int readerFormat)1137         private synchronized native int nativeGetFormat(int readerFormat);
nativeGetFenceFd()1138         private synchronized native int nativeGetFenceFd();
nativeGetHardwareBuffer()1139         private synchronized native HardwareBuffer nativeGetHardwareBuffer();
1140     }
1141 
nativeInit(Object weakSelf, int w, int h, int fmt, int maxImgs, long consumerUsage)1142     private synchronized native void nativeInit(Object weakSelf, int w, int h,
1143                                                     int fmt, int maxImgs, long consumerUsage);
nativeClose()1144     private synchronized native void nativeClose();
nativeReleaseImage(Image i)1145     private synchronized native void nativeReleaseImage(Image i);
nativeGetSurface()1146     private synchronized native Surface nativeGetSurface();
nativeDetachImage(Image i)1147     private synchronized native int nativeDetachImage(Image i);
nativeDiscardFreeBuffers()1148     private synchronized native void nativeDiscardFreeBuffers();
1149 
1150     /**
1151      * @return A return code {@code ACQUIRE_*}
1152      *
1153      * @see #ACQUIRE_SUCCESS
1154      * @see #ACQUIRE_NO_BUFS
1155      * @see #ACQUIRE_MAX_IMAGES
1156      */
nativeImageSetup(Image i)1157     private synchronized native int nativeImageSetup(Image i);
1158 
1159     /**
1160      * @hide
1161      */
1162     public static class ImagePlane extends android.media.Image.Plane {
ImagePlane(int rowStride, int pixelStride, ByteBuffer buffer)1163         private ImagePlane(int rowStride, int pixelStride, ByteBuffer buffer) {
1164             mRowStride = rowStride;
1165             mPixelStride = pixelStride;
1166             mBuffer = buffer;
1167             /**
1168              * Set the byteBuffer order according to host endianness (native
1169              * order), otherwise, the byteBuffer order defaults to
1170              * ByteOrder.BIG_ENDIAN.
1171              */
1172             mBuffer.order(ByteOrder.nativeOrder());
1173         }
1174 
1175         @Override
getBuffer()1176         public ByteBuffer getBuffer() {
1177             return mBuffer;
1178         }
1179 
1180         @Override
getPixelStride()1181         public int getPixelStride() {
1182             return mPixelStride;
1183         }
1184 
1185         @Override
getRowStride()1186         public int getRowStride() {
1187             return mRowStride;
1188         }
1189 
1190         final private int mPixelStride;
1191         final private int mRowStride;
1192 
1193         private ByteBuffer mBuffer;
1194     }
1195 
1196     /**
1197      * @hide
1198      */
initializeImagePlanes(int numPlanes, GraphicBuffer buffer, int fenceFd, int format, long timestamp, int transform, int scalingMode, Rect crop)1199     public static ImagePlane[] initializeImagePlanes(int numPlanes,
1200             GraphicBuffer buffer, int fenceFd, int format, long timestamp, int transform,
1201             int scalingMode, Rect crop) {
1202 
1203         return nativeCreateImagePlanes(numPlanes, buffer, fenceFd, format, crop.left, crop.top,
1204                 crop.right, crop.bottom);
1205     }
1206 
nativeCreateImagePlanes(int numPlanes, GraphicBuffer buffer, int fenceFd, int format, int cropLeft, int cropTop, int cropRight, int cropBottom)1207     private synchronized static native ImagePlane[] nativeCreateImagePlanes(int numPlanes,
1208             GraphicBuffer buffer, int fenceFd, int format, int cropLeft, int cropTop,
1209             int cropRight, int cropBottom);
1210 
1211     /**
1212      * @hide
1213      */
unlockGraphicBuffer(GraphicBuffer buffer)1214     public static void unlockGraphicBuffer(GraphicBuffer buffer) {
1215         nativeUnlockGraphicBuffer(buffer);
1216     }
1217 
nativeUnlockGraphicBuffer(GraphicBuffer buffer)1218     private synchronized static native void nativeUnlockGraphicBuffer(GraphicBuffer buffer);
1219 
1220     /**
1221      * We use a class initializer to allow the native code to cache some
1222      * field offsets.
1223      */
nativeClassInit()1224     private static native void nativeClassInit();
1225     static {
1226         System.loadLibrary("media_jni");
nativeClassInit()1227         nativeClassInit();
1228     }
1229 }
1230