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