am 1ae0a7d3: am dd21689b: am cceb8268: am 69421363: Merge "ImageWriter: Exception when Surface is abandoned" into mnc-dev
* commit '1ae0a7d39bfe87d0857268070cbf0ff7fa666e37': ImageWriter: Exception when Surface is abandoned
This commit is contained in:
@@ -497,8 +497,9 @@ public abstract class CameraCaptureSession implements AutoCloseable {
|
|||||||
*
|
*
|
||||||
* <p>Each reprocessable capture session has an input {@link Surface} where the reprocess
|
* <p>Each reprocessable capture session has an input {@link Surface} where the reprocess
|
||||||
* capture requests get the input images from, rather than the camera device. The application
|
* capture requests get the input images from, rather than the camera device. The application
|
||||||
* can create a {@link android.media.ImageWriter} with this input {@link Surface} and use it to
|
* can create a {@link android.media.ImageWriter ImageWriter} with this input {@link Surface}
|
||||||
* provide input images for reprocess capture requests.</p>
|
* and use it to provide input images for reprocess capture requests. When the reprocessable
|
||||||
|
* capture session is closed, the input {@link Surface} is abandoned and becomes invalid.</p>
|
||||||
*
|
*
|
||||||
* @return The {@link Surface} where reprocessing capture requests get the input images from. If
|
* @return The {@link Surface} where reprocessing capture requests get the input images from. If
|
||||||
* this is not a reprocess capture session, {@code null} will be returned.
|
* this is not a reprocess capture session, {@code null} will be returned.
|
||||||
|
|||||||
@@ -40,8 +40,8 @@ import java.util.List;
|
|||||||
* Several Android API classes can provide input {@link android.view.Surface
|
* Several Android API classes can provide input {@link android.view.Surface
|
||||||
* Surface} objects for ImageWriter to produce data into, including
|
* Surface} objects for ImageWriter to produce data into, including
|
||||||
* {@link MediaCodec MediaCodec} (encoder),
|
* {@link MediaCodec MediaCodec} (encoder),
|
||||||
* {@link android.hardware.camera2.CameraDevice CameraDevice} (reprocessing
|
* {@link android.hardware.camera2.CameraCaptureSession CameraCaptureSession}
|
||||||
* input), {@link ImageReader}, etc.
|
* (reprocessing input), {@link ImageReader}, etc.
|
||||||
* </p>
|
* </p>
|
||||||
* <p>
|
* <p>
|
||||||
* The input Image data is encapsulated in {@link Image} objects. To produce
|
* The input Image data is encapsulated in {@link Image} objects. To produce
|
||||||
@@ -64,7 +64,14 @@ import java.util.List;
|
|||||||
* {@link android.hardware.camera2.CameraDevice}) to consume the Images. If the
|
* {@link android.hardware.camera2.CameraDevice}) to consume the Images. If the
|
||||||
* downstream components cannot consume the Images at least as fast as the
|
* downstream components cannot consume the Images at least as fast as the
|
||||||
* ImageWriter production rate, the {@link #dequeueInputImage} call will
|
* ImageWriter production rate, the {@link #dequeueInputImage} call will
|
||||||
* eventually block and the application will have to drop input frames. </p>
|
* eventually block and the application will have to drop input frames.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* If the consumer component that provided the input {@link android.view.Surface Surface}
|
||||||
|
* abandons the {@link android.view.Surface Surface}, {@link #queueInputImage queueing}
|
||||||
|
* or {@link #dequeueInputImage dequeueing} an {@link Image} will throw an
|
||||||
|
* {@link IllegalStateException}.
|
||||||
|
* </p>
|
||||||
*/
|
*/
|
||||||
public class ImageWriter implements AutoCloseable {
|
public class ImageWriter implements AutoCloseable {
|
||||||
private final Object mListenerLock = new Object();
|
private final Object mListenerLock = new Object();
|
||||||
@@ -188,7 +195,9 @@ public class ImageWriter implements AutoCloseable {
|
|||||||
* @return The next available input Image from this ImageWriter.
|
* @return The next available input Image from this ImageWriter.
|
||||||
* @throws IllegalStateException if {@code maxImages} Images are currently
|
* @throws IllegalStateException if {@code maxImages} Images are currently
|
||||||
* dequeued, or the ImageWriter format is
|
* dequeued, or the ImageWriter format is
|
||||||
* {@link ImageFormat#PRIVATE PRIVATE}.
|
* {@link ImageFormat#PRIVATE PRIVATE}, or the input
|
||||||
|
* {@link android.view.Surface Surface} has been abandoned by the
|
||||||
|
* consumer component that provided the {@link android.view.Surface Surface}.
|
||||||
* @see #queueInputImage
|
* @see #queueInputImage
|
||||||
* @see Image#close
|
* @see Image#close
|
||||||
*/
|
*/
|
||||||
@@ -254,6 +263,11 @@ public class ImageWriter implements AutoCloseable {
|
|||||||
*
|
*
|
||||||
* @param image The Image to be queued back to ImageWriter for future
|
* @param image The Image to be queued back to ImageWriter for future
|
||||||
* consumption.
|
* consumption.
|
||||||
|
* @throws IllegalStateException if the image was already queued previously,
|
||||||
|
* or the image was aborted previously, or the input
|
||||||
|
* {@link android.view.Surface Surface} has been abandoned by the
|
||||||
|
* consumer component that provided the
|
||||||
|
* {@link android.view.Surface Surface}.
|
||||||
* @see #dequeueInputImage()
|
* @see #dequeueInputImage()
|
||||||
*/
|
*/
|
||||||
public void queueInputImage(Image image) {
|
public void queueInputImage(Image image) {
|
||||||
@@ -699,7 +713,7 @@ public class ImageWriter implements AutoCloseable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void clearSurfacePlanes() {
|
private void clearSurfacePlanes() {
|
||||||
if (mIsImageValid) {
|
if (mIsImageValid && mPlanes != null) {
|
||||||
for (int i = 0; i < mPlanes.length; i++) {
|
for (int i = 0; i < mPlanes.length; i++) {
|
||||||
if (mPlanes[i] != null) {
|
if (mPlanes[i] != null) {
|
||||||
mPlanes[i].clearBuffer();
|
mPlanes[i].clearBuffer();
|
||||||
|
|||||||
@@ -338,9 +338,16 @@ static void ImageWriter_dequeueImage(JNIEnv* env, jobject thiz, jlong nativeCtx,
|
|||||||
int fenceFd = -1;
|
int fenceFd = -1;
|
||||||
status_t res = anw->dequeueBuffer(anw.get(), &anb, &fenceFd);
|
status_t res = anw->dequeueBuffer(anw.get(), &anb, &fenceFd);
|
||||||
if (res != OK) {
|
if (res != OK) {
|
||||||
// TODO: handle different error cases here.
|
|
||||||
ALOGE("%s: Dequeue buffer failed: %s (%d)", __FUNCTION__, strerror(-res), res);
|
ALOGE("%s: Dequeue buffer failed: %s (%d)", __FUNCTION__, strerror(-res), res);
|
||||||
jniThrowRuntimeException(env, "dequeue buffer failed");
|
switch (res) {
|
||||||
|
case NO_INIT:
|
||||||
|
jniThrowException(env, "java/lang/IllegalStateException",
|
||||||
|
"Surface has been abandoned");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// TODO: handle other error cases here.
|
||||||
|
jniThrowRuntimeException(env, "dequeue buffer failed");
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// New GraphicBuffer object doesn't own the handle, thus the native buffer
|
// New GraphicBuffer object doesn't own the handle, thus the native buffer
|
||||||
@@ -468,7 +475,16 @@ static void ImageWriter_queueImage(JNIEnv* env, jobject thiz, jlong nativeCtx, j
|
|||||||
// Finally, queue input buffer
|
// Finally, queue input buffer
|
||||||
res = anw->queueBuffer(anw.get(), buffer, fenceFd);
|
res = anw->queueBuffer(anw.get(), buffer, fenceFd);
|
||||||
if (res != OK) {
|
if (res != OK) {
|
||||||
jniThrowRuntimeException(env, "Queue input buffer failed");
|
ALOGE("%s: Queue buffer failed: %s (%d)", __FUNCTION__, strerror(-res), res);
|
||||||
|
switch (res) {
|
||||||
|
case NO_INIT:
|
||||||
|
jniThrowException(env, "java/lang/IllegalStateException",
|
||||||
|
"Surface has been abandoned");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// TODO: handle other error cases here.
|
||||||
|
jniThrowRuntimeException(env, "Queue input buffer failed");
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -514,9 +530,16 @@ static jint ImageWriter_attachAndQueueImage(JNIEnv* env, jobject thiz, jlong nat
|
|||||||
// Step 1. Attach Image
|
// Step 1. Attach Image
|
||||||
res = surface->attachBuffer(opaqueBuffer->mGraphicBuffer.get());
|
res = surface->attachBuffer(opaqueBuffer->mGraphicBuffer.get());
|
||||||
if (res != OK) {
|
if (res != OK) {
|
||||||
// TODO: handle different error case separately.
|
|
||||||
ALOGE("Attach image failed: %s (%d)", strerror(-res), res);
|
ALOGE("Attach image failed: %s (%d)", strerror(-res), res);
|
||||||
jniThrowRuntimeException(env, "nativeAttachImage failed!!!");
|
switch (res) {
|
||||||
|
case NO_INIT:
|
||||||
|
jniThrowException(env, "java/lang/IllegalStateException",
|
||||||
|
"Surface has been abandoned");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// TODO: handle other error cases here.
|
||||||
|
jniThrowRuntimeException(env, "nativeAttachImage failed!!!");
|
||||||
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
sp < ANativeWindow > anw = surface;
|
sp < ANativeWindow > anw = surface;
|
||||||
@@ -545,7 +568,16 @@ static jint ImageWriter_attachAndQueueImage(JNIEnv* env, jobject thiz, jlong nat
|
|||||||
res = anw->queueBuffer(anw.get(), opaqueBuffer->mGraphicBuffer.get(), /*fenceFd*/
|
res = anw->queueBuffer(anw.get(), opaqueBuffer->mGraphicBuffer.get(), /*fenceFd*/
|
||||||
-1);
|
-1);
|
||||||
if (res != OK) {
|
if (res != OK) {
|
||||||
jniThrowRuntimeException(env, "Queue input buffer failed");
|
ALOGE("%s: Queue buffer failed: %s (%d)", __FUNCTION__, strerror(-res), res);
|
||||||
|
switch (res) {
|
||||||
|
case NO_INIT:
|
||||||
|
jniThrowException(env, "java/lang/IllegalStateException",
|
||||||
|
"Surface has been abandoned");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// TODO: handle other error cases here.
|
||||||
|
jniThrowRuntimeException(env, "Queue input buffer failed");
|
||||||
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user