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