Merge "media: Fix ImageReader only using maxImages=1 no matter what" into klp-dev

This commit is contained in:
Igor Murashkin
2013-08-16 21:02:11 +00:00
committed by Android (Google) Code Review
2 changed files with 40 additions and 8 deletions

View File

@ -20,7 +20,6 @@ import android.graphics.ImageFormat;
import android.graphics.PixelFormat; import android.graphics.PixelFormat;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.os.Message;
import android.view.Surface; import android.view.Surface;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
@ -130,11 +129,26 @@ public final class ImageReader implements AutoCloseable {
} }
/** /**
* <p>Get the next Image from the ImageReader's queue. Returns {@code null} * <p>
* if no new image is available.</p> * Get the next Image from the ImageReader's queue. Returns {@code null} if
* no new image is available.
* </p>
* <p>
* This operation will fail by throwing an
* {@link Surface.OutOfResourcesException OutOfResourcesException} if too
* many images have been acquired with {@link #getNextImage}. In particular
* a sequence of {@link #getNextImage} calls greater than {@link #getMaxImages}
* without calling {@link Image#close} or {@link #releaseImage} in-between
* will exhaust the underlying queue. At such a time,
* {@link Surface.OutOfResourcesException OutOfResourcesException} will be
* thrown until more images are released with {@link Image#close} or
* {@link #releaseImage}.
* </p>
* *
* @return a new frame of image data, or {@code null} if no image data is * @return a new frame of image data, or {@code null} if no image data is
* available. * available.
* @throws Surface.OutOfResourcesException if too many images are currently
* acquired
*/ */
public Image getNextImage() { public Image getNextImage() {
SurfaceImage si = new SurfaceImage(); SurfaceImage si = new SurfaceImage();
@ -172,6 +186,8 @@ public final class ImageReader implements AutoCloseable {
* @param listener the listener that will be run * @param listener the listener that will be run
* @param handler The handler on which the listener should be invoked, or null * @param handler The handler on which the listener should be invoked, or null
* if the listener should be invoked on the calling thread's looper. * if the listener should be invoked on the calling thread's looper.
*
* @throws IllegalArgumentException if no handler specified and the calling thread has no looper
*/ */
public void setImageAvailableListener(OnImageAvailableListener listener, Handler handler) { public void setImageAvailableListener(OnImageAvailableListener listener, Handler handler) {
mImageListener = listener; mImageListener = listener;
@ -260,8 +276,9 @@ public final class ImageReader implements AutoCloseable {
* Called from Native code when an Event happens. * Called from Native code when an Event happens.
*/ */
private static void postEventFromNative(Object selfRef) { private static void postEventFromNative(Object selfRef) {
WeakReference weakSelf = (WeakReference)selfRef; @SuppressWarnings("unchecked")
final ImageReader ir = (ImageReader)weakSelf.get(); WeakReference<ImageReader> weakSelf = (WeakReference<ImageReader>)selfRef;
final ImageReader ir = weakSelf.get();
if (ir == null) { if (ir == null) {
return; return;
} }

View File

@ -44,6 +44,9 @@
using namespace android; using namespace android;
static const char* const OutOfResourcesException =
"android/view/Surface$OutOfResourcesException";
enum { enum {
IMAGE_READER_MAX_NUM_PLANES = 3, IMAGE_READER_MAX_NUM_PLANES = 3,
}; };
@ -609,7 +612,8 @@ static void ImageReader_init(JNIEnv* env, jobject thiz, jobject weakThiz,
nativeFormat = Image_getPixelFormat(env, format); nativeFormat = Image_getPixelFormat(env, format);
sp<BufferQueue> bq = new BufferQueue(); sp<BufferQueue> bq = new BufferQueue();
sp<CpuConsumer> consumer = new CpuConsumer(bq, true, maxImages); sp<CpuConsumer> consumer = new CpuConsumer(bq, maxImages,
/*controlledByApp*/true);
// TODO: throw dvm exOutOfMemoryError? // TODO: throw dvm exOutOfMemoryError?
if (consumer == NULL) { if (consumer == NULL) {
jniThrowRuntimeException(env, "Failed to allocate native CpuConsumer"); jniThrowRuntimeException(env, "Failed to allocate native CpuConsumer");
@ -702,7 +706,17 @@ static jboolean ImageReader_imageSetup(JNIEnv* env, jobject thiz,
status_t res = consumer->lockNextBuffer(buffer); status_t res = consumer->lockNextBuffer(buffer);
if (res != NO_ERROR) { if (res != NO_ERROR) {
if (res != BAD_VALUE /*no buffers*/) { if (res != BAD_VALUE /*no buffers*/) {
ALOGE("%s Fail to lockNextBuffer with error: %d ", __FUNCTION__, res); if (res == NOT_ENOUGH_DATA) {
jniThrowException(env, OutOfResourcesException,
"Too many outstanding images, close existing images"
" to be able to acquire more.");
} else {
ALOGE("%s Fail to lockNextBuffer with error: %d ",
__FUNCTION__, res);
jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
"Unknown error (%d) when we tried to lock buffer.",
res);
}
} }
return false; return false;
} }
@ -714,6 +728,7 @@ static jboolean ImageReader_imageSetup(JNIEnv* env, jobject thiz,
ALOGE("crop left: %d, top = %d", lt.x, lt.y); ALOGE("crop left: %d, top = %d", lt.x, lt.y);
jniThrowException(env, "java/lang/UnsupportedOperationException", jniThrowException(env, "java/lang/UnsupportedOperationException",
"crop left top corner need to at origin"); "crop left top corner need to at origin");
return false;
} }
// Check if the producer buffer configurations match what ImageReader configured. // Check if the producer buffer configurations match what ImageReader configured.