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