1b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala/* 2b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * Copyright (C) 2013 The Android Open Source Project 3b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * 4b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * Licensed under the Apache License, Version 2.0 (the "License"); 5b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * you may not use this file except in compliance with the License. 6b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * You may obtain a copy of the License at 7b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * 8b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * http://www.apache.org/licenses/LICENSE-2.0 9b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * 10b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * Unless required by applicable law or agreed to in writing, software 11b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * distributed under the License is distributed on an "AS IS" BASIS, 12b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * See the License for the specific language governing permissions and 14b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * limitations under the License. 15b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala */ 16b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala 17b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvalapackage android.media; 18b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala 19212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Heimport android.graphics.ImageFormat; 20212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Heimport android.os.Handler; 21212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Heimport android.os.Looper; 22c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hallimport android.os.Message; 23dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun Heimport android.util.Log; 24b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvalaimport android.view.Surface; 25212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 2611c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chenimport dalvik.system.VMRuntime; 2711c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen 28212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Heimport java.lang.ref.WeakReference; 29212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Heimport java.nio.ByteBuffer; 30212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Heimport java.nio.ByteOrder; 31e09dcdba7161170a6b052dffe2a5608d1f07548bZhijun Heimport java.nio.NioUtils; 32dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun Heimport java.util.List; 33dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun Heimport java.util.concurrent.CopyOnWriteArrayList; 34f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Heimport java.util.concurrent.atomic.AtomicBoolean; 35b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala 36b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala/** 37b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * <p>The ImageReader class allows direct application access to image data 38b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * rendered into a {@link android.view.Surface}</p> 39b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * 40b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * <p>Several Android media API classes accept Surface objects as targets to 41b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * render to, including {@link MediaPlayer}, {@link MediaCodec}, 42f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * {@link android.hardware.camera2.CameraDevice}, {@link ImageWriter} and 43b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * {@link android.renderscript.Allocation RenderScript Allocations}. The image 44b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * sizes and formats that can be used with each source vary, and should be 45b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * checked in the documentation for the specific API.</p> 46b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * 47b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * <p>The image data is encapsulated in {@link Image} objects, and multiple such 48b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * objects can be accessed at the same time, up to the number specified by the 49b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * {@code maxImages} constructor parameter. New images sent to an ImageReader 505e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * through its {@link Surface} are queued until accessed through the {@link #acquireLatestImage} 515e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * or {@link #acquireNextImage} call. Due to memory limits, an image source will 52b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * eventually stall or drop Images in trying to render to the Surface if the 53b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * ImageReader does not obtain and release Images at a rate equal to the 54b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * production rate.</p> 55b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala */ 565e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkinpublic class ImageReader implements AutoCloseable { 575e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin 585e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin /** 59e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin * Returned by nativeImageSetup when acquiring the image was successful. 605e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin */ 61e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin private static final int ACQUIRE_SUCCESS = 0; 62e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin /** 63e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin * Returned by nativeImageSetup when we couldn't acquire the buffer, 64e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin * because there were no buffers available to acquire. 65e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin */ 66e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin private static final int ACQUIRE_NO_BUFS = 1; 67e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin /** 68e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin * Returned by nativeImageSetup when we couldn't acquire the buffer 69e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin * because the consumer has already acquired {@maxImages} and cannot 70e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin * acquire more than that. 71e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin */ 72e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin private static final int ACQUIRE_MAX_IMAGES = 2; 73b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala 74b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala /** 75f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * <p> 76d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He * Create a new reader for images of the desired size and format. 77f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * </p> 78f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * <p> 79f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * The {@code maxImages} parameter determines the maximum number of 80f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * {@link Image} objects that can be be acquired from the 81f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * {@code ImageReader} simultaneously. Requesting more buffers will use up 82d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He * more memory, so it is important to use only the minimum number necessary 83d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He * for the use case. 84f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * </p> 85f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * <p> 86f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * The valid sizes and formats depend on the source of the image data. 87f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * </p> 88f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * <p> 89d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He * If the {@code format} is {@link ImageFormat#PRIVATE PRIVATE}, the created 90d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He * {@link ImageReader} will produce images that are not directly accessible 91d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He * by the application. The application can still acquire images from this 92d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He * {@link ImageReader}, and send them to the 93d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He * {@link android.hardware.camera2.CameraDevice camera} for reprocessing via 94d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He * {@link ImageWriter} interface. However, the {@link Image#getPlanes() 95d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He * getPlanes()} will return an empty array for {@link ImageFormat#PRIVATE 96d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He * PRIVATE} format images. The application can check if an existing reader's 97d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He * format by calling {@link #getImageFormat()}. 98d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He * </p> 99d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He * <p> 100d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He * {@link ImageFormat#PRIVATE PRIVATE} format {@link ImageReader 101d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He * ImageReaders} are more efficient to use when application access to image 102d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He * data is not necessary, compared to ImageReaders using other format such 103d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He * as {@link ImageFormat#YUV_420_888 YUV_420_888}. 104f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * </p> 105f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * 106f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * @param width The default width in pixels of the Images that this reader 107f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * will produce. 108f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * @param height The default height in pixels of the Images that this reader 109f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * will produce. 110d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He * @param format The format of the Image that this reader will produce. This 111d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He * must be one of the {@link android.graphics.ImageFormat} or 112d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He * {@link android.graphics.PixelFormat} constants. Note that not 113d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He * all formats are supported, like ImageFormat.NV21. 114f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * @param maxImages The maximum number of images the user will want to 115f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * access simultaneously. This should be as small as possible to 116f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * limit memory use. Once maxImages Images are obtained by the 117f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * user, one of them has to be released before a new Image will 118f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * become available for access through 119f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * {@link #acquireLatestImage()} or {@link #acquireNextImage()}. 120f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * Must be greater than 0. 121f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * @see Image 122f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He */ 123d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He public static ImageReader newInstance(int width, int height, int format, int maxImages) { 124d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He return new ImageReader(width, height, format, maxImages); 125f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 126f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 127f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He /** 1285e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * @hide 1295e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin */ 1305e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin protected ImageReader(int width, int height, int format, int maxImages) { 131b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala mWidth = width; 132b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala mHeight = height; 133b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala mFormat = format; 134b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala mMaxImages = maxImages; 135b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala 136b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala if (width < 1 || height < 1) { 137b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala throw new IllegalArgumentException( 138b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala "The image dimensions must be positive"); 139b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala } 140b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala if (mMaxImages < 1) { 141b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala throw new IllegalArgumentException( 142b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala "Maximum outstanding image count must be at least 1"); 143b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala } 144212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 1454eda9f5359347c11914e47f477535c9533674d32Zhijun He if (format == ImageFormat.NV21) { 1464eda9f5359347c11914e47f477535c9533674d32Zhijun He throw new IllegalArgumentException( 1474eda9f5359347c11914e47f477535c9533674d32Zhijun He "NV21 format is not supported"); 1484eda9f5359347c11914e47f477535c9533674d32Zhijun He } 1494eda9f5359347c11914e47f477535c9533674d32Zhijun He 150dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He mNumPlanes = ImageUtils.getNumPlanesForFormat(mFormat); 151212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 152212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He nativeInit(new WeakReference<ImageReader>(this), width, height, format, maxImages); 153212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 154212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He mSurface = nativeGetSurface(); 15511c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen 1568e694e3b494b0fc857dcd981c57687ecea543c02Zhijun He mIsReaderValid = true; 15711c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen // Estimate the native buffer allocation size and register it so it gets accounted for 15811c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen // during GC. Note that this doesn't include the buffers required by the buffer queue 15911c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen // itself and the buffers requested by the producer. 16004a935162c0af649987108058f81405930408014Eino-Ville Talvala // Only include memory for 1 buffer, since actually accounting for the memory used is 16104a935162c0af649987108058f81405930408014Eino-Ville Talvala // complex, and 1 buffer is enough for the VM to treat the ImageReader as being of some 16204a935162c0af649987108058f81405930408014Eino-Ville Talvala // size. 16304a935162c0af649987108058f81405930408014Eino-Ville Talvala mEstimatedNativeAllocBytes = ImageUtils.getEstimatedNativeAllocBytes( 16404a935162c0af649987108058f81405930408014Eino-Ville Talvala width, height, format, /*buffer count*/ 1); 16511c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen VMRuntime.getRuntime().registerNativeAllocation(mEstimatedNativeAllocBytes); 166b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala } 167b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala 1685e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin /** 1698d563a20776b476df77f2a4f3de1feebcf7c255fLajos Molnar * The default width of {@link Image Images}, in pixels. 1705e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * 1718d563a20776b476df77f2a4f3de1feebcf7c255fLajos Molnar * <p>The width may be overridden by the producer sending buffers to this 1728d563a20776b476df77f2a4f3de1feebcf7c255fLajos Molnar * ImageReader's Surface. If so, the actual width of the images can be 1738d563a20776b476df77f2a4f3de1feebcf7c255fLajos Molnar * found using {@link Image#getWidth}.</p> 1745e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * 1758d563a20776b476df77f2a4f3de1feebcf7c255fLajos Molnar * @return the expected width of an Image 1765e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin */ 177b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala public int getWidth() { 178b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala return mWidth; 179b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala } 180b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala 1815e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin /** 1828d563a20776b476df77f2a4f3de1feebcf7c255fLajos Molnar * The default height of {@link Image Images}, in pixels. 1835e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * 1848d563a20776b476df77f2a4f3de1feebcf7c255fLajos Molnar * <p>The height may be overridden by the producer sending buffers to this 1858d563a20776b476df77f2a4f3de1feebcf7c255fLajos Molnar * ImageReader's Surface. If so, the actual height of the images can be 1868d563a20776b476df77f2a4f3de1feebcf7c255fLajos Molnar * found using {@link Image#getHeight}.</p> 1875e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * 1888d563a20776b476df77f2a4f3de1feebcf7c255fLajos Molnar * @return the expected height of an Image 1895e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin */ 190b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala public int getHeight() { 191b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala return mHeight; 192b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala } 193b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala 1945e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin /** 1958d563a20776b476df77f2a4f3de1feebcf7c255fLajos Molnar * The default {@link ImageFormat image format} of {@link Image Images}. 1965e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * 1978d563a20776b476df77f2a4f3de1feebcf7c255fLajos Molnar * <p>Some color formats may be overridden by the producer sending buffers to 1988d563a20776b476df77f2a4f3de1feebcf7c255fLajos Molnar * this ImageReader's Surface if the default color format allows. ImageReader 1998d563a20776b476df77f2a4f3de1feebcf7c255fLajos Molnar * guarantees that all {@link Image Images} acquired from ImageReader 2008d563a20776b476df77f2a4f3de1feebcf7c255fLajos Molnar * (for example, with {@link #acquireNextImage}) will have a "compatible" 2018d563a20776b476df77f2a4f3de1feebcf7c255fLajos Molnar * format to what was specified in {@link #newInstance}. 2028d563a20776b476df77f2a4f3de1feebcf7c255fLajos Molnar * As of now, each format is only compatible to itself. 2038d563a20776b476df77f2a4f3de1feebcf7c255fLajos Molnar * The actual format of the images can be found using {@link Image#getFormat}.</p> 2045e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * 2058d563a20776b476df77f2a4f3de1feebcf7c255fLajos Molnar * @return the expected format of an Image 2065e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * 2075e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * @see ImageFormat 2085e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin */ 209b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala public int getImageFormat() { 210b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala return mFormat; 211b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala } 212b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala 2135e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin /** 2145e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * Maximum number of images that can be acquired from the ImageReader by any time (for example, 2155e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * with {@link #acquireNextImage}). 2165e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * 2175e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * <p>An image is considered acquired after it's returned by a function from ImageReader, and 2185e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * until the Image is {@link Image#close closed} to release the image back to the ImageReader. 2195e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * </p> 2205e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * 2215e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * <p>Attempting to acquire more than {@code maxImages} concurrently will result in the 222e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin * acquire function throwing a {@link IllegalStateException}. Furthermore, 2235e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * while the max number of images have been acquired by the ImageReader user, the producer 2245e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * enqueueing additional images may stall until at least one image has been released. </p> 2255e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * 2265e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * @return Maximum number of images for this ImageReader. 2275e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * 2285e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * @see Image#close 2295e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin */ 230b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala public int getMaxImages() { 231b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala return mMaxImages; 232b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala } 233b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala 234b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala /** 2355e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * <p>Get a {@link Surface} that can be used to produce {@link Image Images} for this 2365e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * {@code ImageReader}.</p> 237b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * 2385e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * <p>Until valid image data is rendered into this {@link Surface}, the 2395e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * {@link #acquireNextImage} method will return {@code null}. Only one source 240b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * can be producing data into this Surface at the same time, although the 2415e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * same {@link Surface} can be reused with a different API once the first source is 2425e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * disconnected from the {@link Surface}.</p> 243b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * 2445e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * @return A {@link Surface} to use for a drawing target for various APIs. 245b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala */ 246b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala public Surface getSurface() { 247212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He return mSurface; 248b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala } 249b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala 250b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala /** 251dd0643202de80cc4ced37d1844e722c8a5e89154Igor Murashkin * <p> 2525e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * Acquire the latest {@link Image} from the ImageReader's queue, dropping older 2535e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * {@link Image images}. Returns {@code null} if no new image is available. 2545e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * </p> 2555e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * <p> 2565e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * This operation will acquire all the images possible from the ImageReader, 2575e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * but {@link #close} all images that aren't the latest. This function is 2585e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * recommended to use over {@link #acquireNextImage} for most use-cases, as it's 2595e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * more suited for real-time processing. 2605e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * </p> 2615e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * <p> 2625e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * Note that {@link #getMaxImages maxImages} should be at least 2 for 2635e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * {@link #acquireLatestImage} to be any different than {@link #acquireNextImage} - 2645e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * discarding all-but-the-newest {@link Image} requires temporarily acquiring two 2655e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * {@link Image Images} at once. Or more generally, calling {@link #acquireLatestImage} 2665e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * with less than two images of margin, that is 2675e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * {@code (maxImages - currentAcquiredImages < 2)} will not discard as expected. 2685e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * </p> 2695e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * <p> 270e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin * This operation will fail by throwing an {@link IllegalStateException} if 2715e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * {@code maxImages} have been acquired with {@link #acquireLatestImage} or 2725e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * {@link #acquireNextImage}. In particular a sequence of {@link #acquireLatestImage} 2735e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * calls greater than {@link #getMaxImages} without calling {@link Image#close} in-between 274e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin * will exhaust the underlying queue. At such a time, {@link IllegalStateException} 2755e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * will be thrown until more images are 2765e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * released with {@link Image#close}. 2775e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * </p> 2785e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * 2795e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * @return latest frame of image data, or {@code null} if no image data is available. 280e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin * @throws IllegalStateException if too many images are currently acquired 2815e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin */ 282e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin public Image acquireLatestImage() { 2835e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin Image image = acquireNextImage(); 2845e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin if (image == null) { 2855e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin return null; 2865e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin } 2875e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin try { 2885e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin for (;;) { 289e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin Image next = acquireNextImageNoThrowISE(); 2905e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin if (next == null) { 2915e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin Image result = image; 2925e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin image = null; 2935e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin return result; 2945e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin } 2955e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin image.close(); 2965e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin image = next; 2975e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin } 2985e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin } finally { 2995e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin if (image != null) { 3005e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin image.close(); 3015e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin } 3025e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin } 3035e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin } 3045e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin 305e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin /** 306e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin * Don't throw IllegalStateException if there are too many images acquired. 307e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin * 308e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin * @return Image if acquiring succeeded, or null otherwise. 309e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin * 310e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin * @hide 311e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin */ 312e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin public Image acquireNextImageNoThrowISE() { 313ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He SurfaceImage si = new SurfaceImage(mFormat); 314e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin return acquireNextSurfaceImage(si) == ACQUIRE_SUCCESS ? si : null; 315e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin } 316e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin 317e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin /** 318e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin * Attempts to acquire the next image from the underlying native implementation. 319e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin * 320e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin * <p> 321e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin * Note that unexpected failures will throw at the JNI level. 322e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin * </p> 323e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin * 324e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin * @param si A blank SurfaceImage. 325e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin * @return One of the {@code ACQUIRE_*} codes that determine success or failure. 326e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin * 327e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin * @see #ACQUIRE_MAX_IMAGES 328e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin * @see #ACQUIRE_NO_BUFS 329e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin * @see #ACQUIRE_SUCCESS 330e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin */ 331e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin private int acquireNextSurfaceImage(SurfaceImage si) { 332dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He synchronized (mCloseLock) { 3338e694e3b494b0fc857dcd981c57687ecea543c02Zhijun He // A null image will eventually be returned if ImageReader is already closed. 3348e694e3b494b0fc857dcd981c57687ecea543c02Zhijun He int status = ACQUIRE_NO_BUFS; 3358e694e3b494b0fc857dcd981c57687ecea543c02Zhijun He if (mIsReaderValid) { 3368e694e3b494b0fc857dcd981c57687ecea543c02Zhijun He status = nativeImageSetup(si); 3378e694e3b494b0fc857dcd981c57687ecea543c02Zhijun He } 338dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He 339dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He switch (status) { 340dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He case ACQUIRE_SUCCESS: 341dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He si.mIsImageValid = true; 342dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He case ACQUIRE_NO_BUFS: 343dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He case ACQUIRE_MAX_IMAGES: 344dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He break; 345dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He default: 346dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He throw new AssertionError("Unknown nativeImageSetup return code " + status); 347dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He } 348e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin 349dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He // Only keep track the successfully acquired image, as the native buffer is only mapped 350dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He // for such case. 351dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He if (status == ACQUIRE_SUCCESS) { 352dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He mAcquiredImages.add(si); 353dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He } 354dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He return status; 3555e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin } 3565e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin } 3575e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin 3585e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin /** 3595e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * <p> 3605e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * Acquire the next Image from the ImageReader's queue. Returns {@code null} if 361dd0643202de80cc4ced37d1844e722c8a5e89154Igor Murashkin * no new image is available. 362dd0643202de80cc4ced37d1844e722c8a5e89154Igor Murashkin * </p> 3635e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * 3645e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * <p><i>Warning:</i> Consider using {@link #acquireLatestImage()} instead, as it will 3655e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * automatically release older images, and allow slower-running processing routines to catch 3665e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * up to the newest frame. Usage of {@link #acquireNextImage} is recommended for 3675e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * batch/background processing. Incorrectly using this function can cause images to appear 3685e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * with an ever-increasing delay, followed by a complete stall where no new images seem to 3695e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * appear. 3705e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * </p> 3715e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * 372dd0643202de80cc4ced37d1844e722c8a5e89154Igor Murashkin * <p> 373e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin * This operation will fail by throwing an {@link IllegalStateException} if 3745e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * {@code maxImages} have been acquired with {@link #acquireNextImage} or 3755e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * {@link #acquireLatestImage}. In particular a sequence of {@link #acquireNextImage} or 3765e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * {@link #acquireLatestImage} calls greater than {@link #getMaxImages maxImages} without 3775e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * calling {@link Image#close} in-between will exhaust the underlying queue. At such a time, 378e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin * {@link IllegalStateException} will be thrown until more images are released with 3795e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * {@link Image#close}. 380dd0643202de80cc4ced37d1844e722c8a5e89154Igor Murashkin * </p> 381b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * 3825e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * @return a new frame of image data, or {@code null} if no image data is available. 383e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin * @throws IllegalStateException if {@code maxImages} images are currently acquired 3845e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * @see #acquireLatestImage 385b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala */ 386e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin public Image acquireNextImage() { 387ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He // Initialize with reader format, but can be overwritten by native if the image 388ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He // format is different from the reader format. 389ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He SurfaceImage si = new SurfaceImage(mFormat); 390e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin int status = acquireNextSurfaceImage(si); 391e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin 392e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin switch (status) { 393e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin case ACQUIRE_SUCCESS: 394e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin return si; 395e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin case ACQUIRE_NO_BUFS: 396e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin return null; 397e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin case ACQUIRE_MAX_IMAGES: 398e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin throw new IllegalStateException( 399e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin String.format( 400e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin "maxImages (%d) has already been acquired, " + 401e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin "call #close before acquiring more.", mMaxImages)); 402e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin default: 403e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin throw new AssertionError("Unknown nativeImageSetup return code " + status); 404212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 405b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala } 406b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala 407b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala /** 408b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * <p>Return the frame to the ImageReader for reuse.</p> 409b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala */ 4105e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin private void releaseImage(Image i) { 411b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala if (! (i instanceof SurfaceImage) ) { 412b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala throw new IllegalArgumentException( 413b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala "This image was not produced by an ImageReader"); 414b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala } 415b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala SurfaceImage si = (SurfaceImage) i; 416dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He if (si.mIsImageValid == false) { 417dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He return; 418dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He } 419dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He 420dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He if (si.getReader() != this || !mAcquiredImages.contains(i)) { 421b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala throw new IllegalArgumentException( 422b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala "This image was not produced by this ImageReader"); 423b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala } 424212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 425212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He si.clearSurfacePlanes(); 426212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He nativeReleaseImage(i); 427a58271419ee5b4d8d2a6e25c602a0c40719f33e0Zhijun He si.mIsImageValid = false; 428dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He mAcquiredImages.remove(i); 429b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala } 430b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala 431212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He /** 432212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He * Register a listener to be invoked when a new image becomes available 433212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He * from the ImageReader. 434dd0643202de80cc4ced37d1844e722c8a5e89154Igor Murashkin * 4355e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * @param listener 4365e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * The listener that will be run. 4375e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * @param handler 4385e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * The handler on which the listener should be invoked, or null 4395e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * if the listener should be invoked on the calling thread's looper. 4405e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * @throws IllegalArgumentException 4415e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * If no handler specified and the calling thread has no looper. 442212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He */ 443c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall public void setOnImageAvailableListener(OnImageAvailableListener listener, Handler handler) { 444c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall synchronized (mListenerLock) { 445c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall if (listener != null) { 446c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall Looper looper = handler != null ? handler.getLooper() : Looper.myLooper(); 447c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall if (looper == null) { 448c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall throw new IllegalArgumentException( 449c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall "handler is null but the current thread is not a looper"); 450c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall } 451c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall if (mListenerHandler == null || mListenerHandler.getLooper() != looper) { 452c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall mListenerHandler = new ListenerHandler(looper); 453c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall } 454c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall mListener = listener; 455212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } else { 456c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall mListener = null; 457c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall mListenerHandler = null; 458212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 459212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 460b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala } 461b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala 462212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He /** 463212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He * Callback interface for being notified that a new image is available. 4645e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * 4655e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * <p> 466212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He * The onImageAvailable is called per image basis, that is, callback fires for every new frame 467212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He * available from ImageReader. 4685e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * </p> 469212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He */ 470b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala public interface OnImageAvailableListener { 471212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He /** 472212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He * Callback that is called when a new image is available from ImageReader. 4735e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * 474212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He * @param reader the ImageReader the callback is associated with. 475212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He * @see ImageReader 476212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He * @see Image 477212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He */ 478b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala void onImageAvailable(ImageReader reader); 479b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala } 480b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala 481212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He /** 4825e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * Free up all the resources associated with this ImageReader. 4835e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * 4845e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * <p> 4855e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * After calling this method, this ImageReader can not be used. Calling 4865e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * any methods on this ImageReader and Images previously provided by 4875e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * {@link #acquireNextImage} or {@link #acquireLatestImage} 4885e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * will result in an {@link IllegalStateException}, and attempting to read from 4895e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * {@link ByteBuffer ByteBuffers} returned by an earlier 4905e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * {@link Image.Plane#getBuffer Plane#getBuffer} call will 491212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He * have undefined behavior. 4925e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin * </p> 493212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He */ 494212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He @Override 495212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He public void close() { 496c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall setOnImageAvailableListener(null, null); 497443ab2c7dbe2a3a482892f3171882572f10eab9aRuben Brunk if (mSurface != null) mSurface.release(); 498dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He 499dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He /** 500dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He * Close all outstanding acquired images before closing the ImageReader. It is a good 501dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He * practice to close all the images as soon as it is not used to reduce system instantaneous 502dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He * memory pressure. CopyOnWrite list will use a copy of current list content. For the images 503dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He * being closed by other thread (e.g., GC thread), doubling the close call is harmless. For 504dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He * the image being acquired by other threads, mCloseLock is used to synchronize close and 505dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He * acquire operations. 506dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He */ 507dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He synchronized (mCloseLock) { 5088e694e3b494b0fc857dcd981c57687ecea543c02Zhijun He mIsReaderValid = false; 509dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He for (Image image : mAcquiredImages) { 510dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He image.close(); 511dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He } 512dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He mAcquiredImages.clear(); 513dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He 514dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He nativeClose(); 515dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He } 516dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He 51711c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen if (mEstimatedNativeAllocBytes > 0) { 51811c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen VMRuntime.getRuntime().registerNativeFree(mEstimatedNativeAllocBytes); 51911c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen mEstimatedNativeAllocBytes = 0; 52011c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen } 521212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 522212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 523212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He @Override 524212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He protected void finalize() throws Throwable { 525212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He try { 526212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He close(); 527212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } finally { 528212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He super.finalize(); 529212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 530212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 531212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 532708e3595031fa15f4ac26c5675a53c1ed495b895Zhijun He /** 533f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * <p> 534f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * Remove the ownership of this image from the ImageReader. 535f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * </p> 536f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * <p> 537f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * After this call, the ImageReader no longer owns this image, and the image 538f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * ownership can be transfered to another entity like {@link ImageWriter} 539f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * via {@link ImageWriter#queueInputImage}. It's up to the new owner to 540f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * release the resources held by this image. For example, if the ownership 541f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * of this image is transfered to an {@link ImageWriter}, the image will be 542f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * freed by the ImageWriter after the image data consumption is done. 543f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * </p> 544f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * <p> 545f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * This method can be used to achieve zero buffer copy for use cases like 546d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He * {@link android.hardware.camera2.CameraDevice Camera2 API} PRIVATE and YUV 547f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * reprocessing, where the application can select an output image from 548f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * {@link ImageReader} and transfer this image directly to 549f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * {@link ImageWriter}, where this image can be consumed by camera directly. 550d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He * For PRIVATE reprocessing, this is the only way to send input buffers to 551f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * the {@link android.hardware.camera2.CameraDevice camera} for 552f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * reprocessing. 553f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * </p> 554f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * <p> 555f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * This is a package private method that is only used internally. 556f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * </p> 557f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * 558f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * @param image The image to be detached from this ImageReader. 559f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * @throws IllegalStateException If the ImageReader or image have been 560f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * closed, or the has been detached, or has not yet been 561f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * acquired. 562f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He */ 563f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He void detachImage(Image image) { 564f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (image == null) { 565f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He throw new IllegalArgumentException("input image must not be null"); 566f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 567f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (!isImageOwnedbyMe(image)) { 568f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He throw new IllegalArgumentException("Trying to detach an image that is not owned by" 569f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He + " this ImageReader"); 570f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 571f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 572f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He SurfaceImage si = (SurfaceImage) image; 573ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He si.throwISEIfImageIsInvalid(); 574ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He 575f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (si.isAttachable()) { 576f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He throw new IllegalStateException("Image was already detached from this ImageReader"); 577f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 578f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 579f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He nativeDetachImage(image); 580f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He si.setDetached(true); 58144581ff4db54bbaa30365ed210e67a0369576100Yin-Chia Yeh } 582f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 583f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He private boolean isImageOwnedbyMe(Image image) { 584f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (!(image instanceof SurfaceImage)) { 585f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return false; 586f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 587f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He SurfaceImage si = (SurfaceImage) image; 588f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return si.getReader() == this; 589f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 590f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 591212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He /** 592212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He * Called from Native code when an Event happens. 593c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall * 594c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall * This may be called from an arbitrary Binder thread, so access to the ImageReader must be 595c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall * synchronized appropriately. 596212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He */ 597212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He private static void postEventFromNative(Object selfRef) { 598dd0643202de80cc4ced37d1844e722c8a5e89154Igor Murashkin @SuppressWarnings("unchecked") 599dd0643202de80cc4ced37d1844e722c8a5e89154Igor Murashkin WeakReference<ImageReader> weakSelf = (WeakReference<ImageReader>)selfRef; 600dd0643202de80cc4ced37d1844e722c8a5e89154Igor Murashkin final ImageReader ir = weakSelf.get(); 601212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He if (ir == null) { 602212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He return; 603212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 604212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 605c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall final Handler handler; 606c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall synchronized (ir.mListenerLock) { 607c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall handler = ir.mListenerHandler; 608c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall } 609c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall if (handler != null) { 610c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall handler.sendEmptyMessage(0); 611212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 612212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 613212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 614b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala private final int mWidth; 615b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala private final int mHeight; 616b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala private final int mFormat; 617b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala private final int mMaxImages; 618212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He private final int mNumPlanes; 619212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He private final Surface mSurface; 62011c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen private int mEstimatedNativeAllocBytes; 621b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala 622c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall private final Object mListenerLock = new Object(); 623dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He private final Object mCloseLock = new Object(); 6248e694e3b494b0fc857dcd981c57687ecea543c02Zhijun He private boolean mIsReaderValid = false; 625c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall private OnImageAvailableListener mListener; 626c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall private ListenerHandler mListenerHandler; 627dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He // Keep track of the successfully acquired Images. This need to be thread safe as the images 628dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He // could be closed by different threads (e.g., application thread and GC thread). 629dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He private List<Image> mAcquiredImages = new CopyOnWriteArrayList<Image>(); 630b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala 631212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He /** 632212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He * This field is used by native code, do not access or modify. 633212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He */ 634212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He private long mNativeContext; 635212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 636c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall /** 637c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall * This custom handler runs asynchronously so callbacks don't get queued behind UI messages. 638c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall */ 639c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall private final class ListenerHandler extends Handler { 640c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall public ListenerHandler(Looper looper) { 641c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall super(looper, null, true /*async*/); 642c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall } 643c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall 644c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall @Override 645c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall public void handleMessage(Message msg) { 646c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall OnImageAvailableListener listener; 647c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall synchronized (mListenerLock) { 648c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall listener = mListener; 649c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall } 6508e694e3b494b0fc857dcd981c57687ecea543c02Zhijun He 6518e694e3b494b0fc857dcd981c57687ecea543c02Zhijun He // It's dangerous to fire onImageAvailable() callback when the ImageReader is being 6528e694e3b494b0fc857dcd981c57687ecea543c02Zhijun He // closed, as application could acquire next image in the onImageAvailable() callback. 6538e694e3b494b0fc857dcd981c57687ecea543c02Zhijun He boolean isReaderValid = false; 6548e694e3b494b0fc857dcd981c57687ecea543c02Zhijun He synchronized (mCloseLock) { 6558e694e3b494b0fc857dcd981c57687ecea543c02Zhijun He isReaderValid = mIsReaderValid; 6568e694e3b494b0fc857dcd981c57687ecea543c02Zhijun He } 6578e694e3b494b0fc857dcd981c57687ecea543c02Zhijun He if (listener != null && isReaderValid) { 658c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall listener.onImageAvailable(ImageReader.this); 659c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall } 660c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall } 661c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall } 662c395fffd901f5670bc2cb41a91af7ad87c39790eJesse Hall 6635e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin private class SurfaceImage extends android.media.Image { 664ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He public SurfaceImage(int format) { 665ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He mFormat = format; 666b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala } 667b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala 668b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala @Override 669b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala public void close() { 670dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He ImageReader.this.releaseImage(this); 671b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala } 672b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala 673b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala public ImageReader getReader() { 674b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala return ImageReader.this; 675b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala } 676212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 677212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He @Override 678212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He public int getFormat() { 679ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He throwISEIfImageIsInvalid(); 6807c3997d96a2571295a97457264832d54b05ee966Zhijun He int readerFormat = ImageReader.this.getImageFormat(); 6817c3997d96a2571295a97457264832d54b05ee966Zhijun He // Assume opaque reader always produce opaque images. 6827c3997d96a2571295a97457264832d54b05ee966Zhijun He mFormat = (readerFormat == ImageFormat.PRIVATE) ? readerFormat : 6837c3997d96a2571295a97457264832d54b05ee966Zhijun He nativeGetFormat(readerFormat); 684ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He return mFormat; 685212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 686212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 687212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He @Override 688212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He public int getWidth() { 689ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He throwISEIfImageIsInvalid(); 69072064af7e75f7e3b2eb2e58a3af408861eb8c4e9Eino-Ville Talvala int width; 69172064af7e75f7e3b2eb2e58a3af408861eb8c4e9Eino-Ville Talvala switch(getFormat()) { 69272064af7e75f7e3b2eb2e58a3af408861eb8c4e9Eino-Ville Talvala case ImageFormat.JPEG: 69372064af7e75f7e3b2eb2e58a3af408861eb8c4e9Eino-Ville Talvala case ImageFormat.DEPTH_POINT_CLOUD: 69444581ff4db54bbaa30365ed210e67a0369576100Yin-Chia Yeh case ImageFormat.RAW_PRIVATE: 69572064af7e75f7e3b2eb2e58a3af408861eb8c4e9Eino-Ville Talvala width = ImageReader.this.getWidth(); 69672064af7e75f7e3b2eb2e58a3af408861eb8c4e9Eino-Ville Talvala break; 69772064af7e75f7e3b2eb2e58a3af408861eb8c4e9Eino-Ville Talvala default: 6980ab416269a866c8afa8f65d9351afa2407abee4cZhijun He width = nativeGetWidth(); 69972064af7e75f7e3b2eb2e58a3af408861eb8c4e9Eino-Ville Talvala } 70072064af7e75f7e3b2eb2e58a3af408861eb8c4e9Eino-Ville Talvala return width; 701212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 702212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 703212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He @Override 704212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He public int getHeight() { 705ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He throwISEIfImageIsInvalid(); 70672064af7e75f7e3b2eb2e58a3af408861eb8c4e9Eino-Ville Talvala int height; 70772064af7e75f7e3b2eb2e58a3af408861eb8c4e9Eino-Ville Talvala switch(getFormat()) { 70872064af7e75f7e3b2eb2e58a3af408861eb8c4e9Eino-Ville Talvala case ImageFormat.JPEG: 70972064af7e75f7e3b2eb2e58a3af408861eb8c4e9Eino-Ville Talvala case ImageFormat.DEPTH_POINT_CLOUD: 71044581ff4db54bbaa30365ed210e67a0369576100Yin-Chia Yeh case ImageFormat.RAW_PRIVATE: 71172064af7e75f7e3b2eb2e58a3af408861eb8c4e9Eino-Ville Talvala height = ImageReader.this.getHeight(); 71272064af7e75f7e3b2eb2e58a3af408861eb8c4e9Eino-Ville Talvala break; 71372064af7e75f7e3b2eb2e58a3af408861eb8c4e9Eino-Ville Talvala default: 7140ab416269a866c8afa8f65d9351afa2407abee4cZhijun He height = nativeGetHeight(); 71572064af7e75f7e3b2eb2e58a3af408861eb8c4e9Eino-Ville Talvala } 71672064af7e75f7e3b2eb2e58a3af408861eb8c4e9Eino-Ville Talvala return height; 717212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 718212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 719212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He @Override 720212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He public long getTimestamp() { 721ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He throwISEIfImageIsInvalid(); 722ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He return mTimestamp; 723212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 724212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 725212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He @Override 726f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He public void setTimestamp(long timestampNs) { 727ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He throwISEIfImageIsInvalid(); 728ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He mTimestamp = timestampNs; 729f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 730f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 731f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He @Override 732212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He public Plane[] getPlanes() { 733ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He throwISEIfImageIsInvalid(); 7340ab416269a866c8afa8f65d9351afa2407abee4cZhijun He 7350ab416269a866c8afa8f65d9351afa2407abee4cZhijun He if (mPlanes == null) { 7360ab416269a866c8afa8f65d9351afa2407abee4cZhijun He mPlanes = nativeCreatePlanes(ImageReader.this.mNumPlanes, ImageReader.this.mFormat); 7370ab416269a866c8afa8f65d9351afa2407abee4cZhijun He } 738ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He // Shallow copy is fine. 739ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He return mPlanes.clone(); 740212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 741212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 742212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He @Override 743212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He protected final void finalize() throws Throwable { 744212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He try { 745212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He close(); 746212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } finally { 747212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He super.finalize(); 748212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 749212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 750212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 751f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He @Override 752f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He boolean isAttachable() { 753ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He throwISEIfImageIsInvalid(); 754f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return mIsDetached.get(); 755f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 756f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 757f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He @Override 758f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ImageReader getOwner() { 759ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He throwISEIfImageIsInvalid(); 760f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return ImageReader.this; 761f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 762f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 763ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He @Override 764ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He long getNativeContext() { 765ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He throwISEIfImageIsInvalid(); 766ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He return mNativeBuffer; 767ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He } 768ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He 769f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He private void setDetached(boolean detached) { 770ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He throwISEIfImageIsInvalid(); 771f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He mIsDetached.getAndSet(detached); 772f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 773f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 774212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He private void clearSurfacePlanes() { 7750ab416269a866c8afa8f65d9351afa2407abee4cZhijun He // Image#getPlanes may not be called before the image is closed. 7760ab416269a866c8afa8f65d9351afa2407abee4cZhijun He if (mIsImageValid && mPlanes != null) { 777212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He for (int i = 0; i < mPlanes.length; i++) { 778212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He if (mPlanes[i] != null) { 779212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He mPlanes[i].clearBuffer(); 780212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He mPlanes[i] = null; 781212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 782212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 783212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 784212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 785212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 7865e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin private class SurfacePlane extends android.media.Image.Plane { 7870ab416269a866c8afa8f65d9351afa2407abee4cZhijun He // SurfacePlane instance is created by native code when SurfaceImage#getPlanes() is 7880ab416269a866c8afa8f65d9351afa2407abee4cZhijun He // called 7890ab416269a866c8afa8f65d9351afa2407abee4cZhijun He private SurfacePlane(int rowStride, int pixelStride, ByteBuffer buffer) { 790212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He mRowStride = rowStride; 791212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He mPixelStride = pixelStride; 7920ab416269a866c8afa8f65d9351afa2407abee4cZhijun He mBuffer = buffer; 7930ab416269a866c8afa8f65d9351afa2407abee4cZhijun He /** 7940ab416269a866c8afa8f65d9351afa2407abee4cZhijun He * Set the byteBuffer order according to host endianness (native 7950ab416269a866c8afa8f65d9351afa2407abee4cZhijun He * order), otherwise, the byteBuffer order defaults to 7960ab416269a866c8afa8f65d9351afa2407abee4cZhijun He * ByteOrder.BIG_ENDIAN. 7970ab416269a866c8afa8f65d9351afa2407abee4cZhijun He */ 7980ab416269a866c8afa8f65d9351afa2407abee4cZhijun He mBuffer.order(ByteOrder.nativeOrder()); 799212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 800212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 801212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He @Override 802212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He public ByteBuffer getBuffer() { 8030ab416269a866c8afa8f65d9351afa2407abee4cZhijun He throwISEIfImageIsInvalid(); 8040ab416269a866c8afa8f65d9351afa2407abee4cZhijun He return mBuffer; 805212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 806212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 807212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He @Override 808212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He public int getPixelStride() { 809ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He SurfaceImage.this.throwISEIfImageIsInvalid(); 81044581ff4db54bbaa30365ed210e67a0369576100Yin-Chia Yeh if (ImageReader.this.mFormat == ImageFormat.RAW_PRIVATE) { 81144581ff4db54bbaa30365ed210e67a0369576100Yin-Chia Yeh throw new UnsupportedOperationException( 81244581ff4db54bbaa30365ed210e67a0369576100Yin-Chia Yeh "getPixelStride is not supported for RAW_PRIVATE plane"); 81344581ff4db54bbaa30365ed210e67a0369576100Yin-Chia Yeh } 814ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He return mPixelStride; 815212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 816212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 817212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He @Override 818212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He public int getRowStride() { 819ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He SurfaceImage.this.throwISEIfImageIsInvalid(); 82044581ff4db54bbaa30365ed210e67a0369576100Yin-Chia Yeh if (ImageReader.this.mFormat == ImageFormat.RAW_PRIVATE) { 82144581ff4db54bbaa30365ed210e67a0369576100Yin-Chia Yeh throw new UnsupportedOperationException( 82244581ff4db54bbaa30365ed210e67a0369576100Yin-Chia Yeh "getRowStride is not supported for RAW_PRIVATE plane"); 82344581ff4db54bbaa30365ed210e67a0369576100Yin-Chia Yeh } 824ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He return mRowStride; 825212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 826212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 827212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He private void clearBuffer() { 828e09dcdba7161170a6b052dffe2a5608d1f07548bZhijun He // Need null check first, as the getBuffer() may not be called before an image 829e09dcdba7161170a6b052dffe2a5608d1f07548bZhijun He // is closed. 830e09dcdba7161170a6b052dffe2a5608d1f07548bZhijun He if (mBuffer == null) { 831e09dcdba7161170a6b052dffe2a5608d1f07548bZhijun He return; 832e09dcdba7161170a6b052dffe2a5608d1f07548bZhijun He } 833e09dcdba7161170a6b052dffe2a5608d1f07548bZhijun He 834e09dcdba7161170a6b052dffe2a5608d1f07548bZhijun He if (mBuffer.isDirect()) { 835e09dcdba7161170a6b052dffe2a5608d1f07548bZhijun He NioUtils.freeDirectBuffer(mBuffer); 836e09dcdba7161170a6b052dffe2a5608d1f07548bZhijun He } 837212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He mBuffer = null; 838212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 839212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 840212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He final private int mPixelStride; 841212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He final private int mRowStride; 842212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 843212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He private ByteBuffer mBuffer; 844212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 845212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 846212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He /** 847212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He * This field is used to keep track of native object and used by native code only. 848212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He * Don't modify. 849212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He */ 850ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He private long mNativeBuffer; 851212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 852212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He /** 853212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He * This field is set by native code during nativeImageSetup(). 854212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He */ 855212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He private long mTimestamp; 856212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 857212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He private SurfacePlane[] mPlanes; 858ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He private int mFormat = ImageFormat.UNKNOWN; 859f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // If this image is detached from the ImageReader. 860f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He private AtomicBoolean mIsDetached = new AtomicBoolean(false); 861212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 8620ab416269a866c8afa8f65d9351afa2407abee4cZhijun He private synchronized native SurfacePlane[] nativeCreatePlanes(int numPlanes, 8630ab416269a866c8afa8f65d9351afa2407abee4cZhijun He int readerFormat); 8640ab416269a866c8afa8f65d9351afa2407abee4cZhijun He private synchronized native int nativeGetWidth(); 8650ab416269a866c8afa8f65d9351afa2407abee4cZhijun He private synchronized native int nativeGetHeight(); 8667c3997d96a2571295a97457264832d54b05ee966Zhijun He private synchronized native int nativeGetFormat(int readerFormat); 867212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 868212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 869212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He private synchronized native void nativeInit(Object weakSelf, int w, int h, 870212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He int fmt, int maxImgs); 871212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He private synchronized native void nativeClose(); 872212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He private synchronized native void nativeReleaseImage(Image i); 873212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He private synchronized native Surface nativeGetSurface(); 874ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He private synchronized native int nativeDetachImage(Image i); 875e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin 876e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin /** 877e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin * @return A return code {@code ACQUIRE_*} 878e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin * 879e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin * @see #ACQUIRE_SUCCESS 880e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin * @see #ACQUIRE_NO_BUFS 881e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin * @see #ACQUIRE_MAX_IMAGES 882e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin */ 883e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin private synchronized native int nativeImageSetup(Image i); 884212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 8855e712064dfe48992f8f732208fa4fc13f3455b30Igor Murashkin /** 886212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He * We use a class initializer to allow the native code to cache some 887212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He * field offsets. 888212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He */ 889212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He private static native void nativeClassInit(); 890212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He static { 891212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He System.loadLibrary("media_jni"); 892212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He nativeClassInit(); 893b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala } 894b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala} 895