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
17package android.media;
18
19import android.graphics.ImageFormat;
20import android.graphics.PixelFormat;
21import android.os.Handler;
22import android.os.Looper;
23import android.os.Message;
24import android.view.Surface;
25
26import dalvik.system.VMRuntime;
27
28import java.lang.ref.WeakReference;
29import java.nio.ByteBuffer;
30import java.nio.ByteOrder;
31import java.nio.NioUtils;
32import 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 */
54public 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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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         */
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
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
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     */
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     */
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
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     */
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 {
637        public ListenerHandler(Looper looper) {
638            super(looper, null, true /*async*/);
639        }
640
641        @Override
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 {
654        public SurfaceImage(int format) {
655            mFormat = format;
656        }
657
658        @Override
659        public void close() {
660            if (mIsImageValid) {
661                ImageReader.this.releaseImage(this);
662            }
663        }
664
665        public ImageReader getReader() {
666            return ImageReader.this;
667        }
668
669        @Override
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
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
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
710        public long getTimestamp() {
711            throwISEIfImageIsInvalid();
712            return mTimestamp;
713        }
714
715        @Override
716        public void setTimestamp(long timestampNs) {
717            throwISEIfImageIsInvalid();
718            mTimestamp = timestampNs;
719        }
720
721        @Override
722        public Plane[] getPlanes() {
723            throwISEIfImageIsInvalid();
724            // Shallow copy is fine.
725            return mPlanes.clone();
726        }
727
728        @Override
729        protected final void finalize() throws Throwable {
730            try {
731                close();
732            } finally {
733                super.finalize();
734            }
735        }
736
737        @Override
738        boolean isAttachable() {
739            throwISEIfImageIsInvalid();
740            return mIsDetached.get();
741        }
742
743        @Override
744        ImageReader getOwner() {
745            throwISEIfImageIsInvalid();
746            return ImageReader.this;
747        }
748
749        @Override
750        long getNativeContext() {
751            throwISEIfImageIsInvalid();
752            return mNativeBuffer;
753        }
754
755        private void setDetached(boolean detached) {
756            throwISEIfImageIsInvalid();
757            mIsDetached.getAndSet(detached);
758        }
759
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
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
779            private SurfacePlane(int index, int rowStride, int pixelStride) {
780                mIndex = index;
781                mRowStride = rowStride;
782                mPixelStride = pixelStride;
783            }
784
785            @Override
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
800            public int getPixelStride() {
801                SurfaceImage.this.throwISEIfImageIsInvalid();
802                return mPixelStride;
803            }
804
805            @Override
806            public int getRowStride() {
807                SurfaceImage.this.throwISEIfImageIsInvalid();
808                return mRowStride;
809            }
810
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
847        private synchronized native ByteBuffer nativeImageGetBuffer(int idx, int readerFormat);
848        private synchronized native SurfacePlane nativeCreatePlane(int idx, int readerFormat);
849        private synchronized native int nativeGetWidth(int format);
850        private synchronized native int nativeGetHeight(int format);
851        private synchronized native int nativeGetFormat(int readerFormat);
852    }
853
854    private synchronized native void nativeInit(Object weakSelf, int w, int h,
855                                                    int fmt, int maxImgs);
856    private synchronized native void nativeClose();
857    private synchronized native void nativeReleaseImage(Image i);
858    private synchronized native Surface nativeGetSurface();
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     */
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     */
874    private static native void nativeClassInit();
875    static {
876        System.loadLibrary("media_jni");
877        nativeClassInit();
878    }
879}
880