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