Merge "Camera: Populate Image tranformation in reader and writer" into pi-dev

This commit is contained in:
TreeHugger Robot
2018-03-20 12:33:37 +00:00
committed by Android (Google) Code Review
6 changed files with 67 additions and 9 deletions

View File

@@ -185,6 +185,13 @@ public abstract class Image implements AutoCloseable {
*/ */
public abstract long getTimestamp(); public abstract long getTimestamp();
/**
* Get the transformation associated with this frame.
* @return The window transformation that needs to be applied for this frame.
* @hide
*/
public abstract int getTransform();
/** /**
* Get the {@link android.hardware.HardwareBuffer HardwareBuffer} handle of the input image * Get the {@link android.hardware.HardwareBuffer HardwareBuffer} handle of the input image
* intended for GPU and/or hardware access. * intended for GPU and/or hardware access.

View File

@@ -875,6 +875,12 @@ public class ImageReader implements AutoCloseable {
return mTimestamp; return mTimestamp;
} }
@Override
public int getTransform() {
throwISEIfImageIsInvalid();
return mTransform;
}
@Override @Override
public HardwareBuffer getHardwareBuffer() { public HardwareBuffer getHardwareBuffer() {
throwISEIfImageIsInvalid(); throwISEIfImageIsInvalid();
@@ -1013,6 +1019,11 @@ public class ImageReader implements AutoCloseable {
*/ */
private long mTimestamp; private long mTimestamp;
/**
* This field is set by native code during nativeImageSetup().
*/
private int mTransform;
private SurfacePlane[] mPlanes; private SurfacePlane[] mPlanes;
private int mFormat = ImageFormat.UNKNOWN; private int mFormat = ImageFormat.UNKNOWN;
// If this image is detached from the ImageReader. // If this image is detached from the ImageReader.

View File

@@ -371,7 +371,7 @@ public class ImageWriter implements AutoCloseable {
Rect crop = image.getCropRect(); Rect crop = image.getCropRect();
nativeQueueInputImage(mNativeContext, image, image.getTimestamp(), crop.left, crop.top, nativeQueueInputImage(mNativeContext, image, image.getTimestamp(), crop.left, crop.top,
crop.right, crop.bottom); crop.right, crop.bottom, image.getTransform());
/** /**
* Only remove and cleanup the Images that are owned by this * Only remove and cleanup the Images that are owned by this
@@ -557,7 +557,8 @@ public class ImageWriter implements AutoCloseable {
// buffer caused leak. // buffer caused leak.
Rect crop = image.getCropRect(); Rect crop = image.getCropRect();
nativeAttachAndQueueImage(mNativeContext, image.getNativeContext(), image.getFormat(), nativeAttachAndQueueImage(mNativeContext, image.getNativeContext(), image.getFormat(),
image.getTimestamp(), crop.left, crop.top, crop.right, crop.bottom); image.getTimestamp(), crop.left, crop.top, crop.right, crop.bottom,
image.getTransform());
} }
/** /**
@@ -674,6 +675,8 @@ public class ImageWriter implements AutoCloseable {
private final long DEFAULT_TIMESTAMP = Long.MIN_VALUE; private final long DEFAULT_TIMESTAMP = Long.MIN_VALUE;
private long mTimestamp = DEFAULT_TIMESTAMP; private long mTimestamp = DEFAULT_TIMESTAMP;
private int mTransform = 0; //Default no transform
public WriterSurfaceImage(ImageWriter writer) { public WriterSurfaceImage(ImageWriter writer) {
mOwner = writer; mOwner = writer;
} }
@@ -710,6 +713,13 @@ public class ImageWriter implements AutoCloseable {
return mHeight; return mHeight;
} }
@Override
public int getTransform() {
throwISEIfImageIsInvalid();
return mTransform;
}
@Override @Override
public long getTimestamp() { public long getTimestamp() {
throwISEIfImageIsInvalid(); throwISEIfImageIsInvalid();
@@ -856,11 +866,11 @@ public class ImageWriter implements AutoCloseable {
private synchronized native void nativeDequeueInputImage(long nativeCtx, Image wi); private synchronized native void nativeDequeueInputImage(long nativeCtx, Image wi);
private synchronized native void nativeQueueInputImage(long nativeCtx, Image image, private synchronized native void nativeQueueInputImage(long nativeCtx, Image image,
long timestampNs, int left, int top, int right, int bottom); long timestampNs, int left, int top, int right, int bottom, int transform);
private synchronized native int nativeAttachAndQueueImage(long nativeCtx, private synchronized native int nativeAttachAndQueueImage(long nativeCtx,
long imageNativeBuffer, int imageFormat, long timestampNs, int left, long imageNativeBuffer, int imageFormat, long timestampNs, int left,
int top, int right, int bottom); int top, int right, int bottom, int transform);
private synchronized native void cancelImage(long nativeCtx, Image image); private synchronized native void cancelImage(long nativeCtx, Image image);

View File

@@ -3528,6 +3528,8 @@ final public class MediaCodec {
private final static int TYPE_YUV = 1; private final static int TYPE_YUV = 1;
private final int mTransform = 0; //Default no transform
@Override @Override
public int getFormat() { public int getFormat() {
throwISEIfImageIsInvalid(); throwISEIfImageIsInvalid();
@@ -3546,6 +3548,12 @@ final public class MediaCodec {
return mWidth; return mWidth;
} }
@Override
public int getTransform() {
throwISEIfImageIsInvalid();
return mTransform;
}
@Override @Override
public long getTimestamp() { public long getTimestamp() {
throwISEIfImageIsInvalid(); throwISEIfImageIsInvalid();

View File

@@ -45,6 +45,7 @@
#define ANDROID_MEDIA_IMAGEREADER_CTX_JNI_ID "mNativeContext" #define ANDROID_MEDIA_IMAGEREADER_CTX_JNI_ID "mNativeContext"
#define ANDROID_MEDIA_SURFACEIMAGE_BUFFER_JNI_ID "mNativeBuffer" #define ANDROID_MEDIA_SURFACEIMAGE_BUFFER_JNI_ID "mNativeBuffer"
#define ANDROID_MEDIA_SURFACEIMAGE_TS_JNI_ID "mTimestamp" #define ANDROID_MEDIA_SURFACEIMAGE_TS_JNI_ID "mTimestamp"
#define ANDROID_MEDIA_SURFACEIMAGE_TF_JNI_ID "mTransform"
#define CONSUMER_BUFFER_USAGE_UNKNOWN 0; #define CONSUMER_BUFFER_USAGE_UNKNOWN 0;
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -66,6 +67,7 @@ static struct {
static struct { static struct {
jfieldID mNativeBuffer; jfieldID mNativeBuffer;
jfieldID mTimestamp; jfieldID mTimestamp;
jfieldID mTransform;
jfieldID mPlanes; jfieldID mPlanes;
} gSurfaceImageClassInfo; } gSurfaceImageClassInfo;
@@ -307,6 +309,12 @@ static void ImageReader_classInit(JNIEnv* env, jclass clazz)
"can't find android/graphics/ImageReader.%s", "can't find android/graphics/ImageReader.%s",
ANDROID_MEDIA_SURFACEIMAGE_TS_JNI_ID); ANDROID_MEDIA_SURFACEIMAGE_TS_JNI_ID);
gSurfaceImageClassInfo.mTransform = env->GetFieldID(
imageClazz, ANDROID_MEDIA_SURFACEIMAGE_TF_JNI_ID, "I");
LOG_ALWAYS_FATAL_IF(gSurfaceImageClassInfo.mTransform == NULL,
"can't find android/graphics/ImageReader.%s",
ANDROID_MEDIA_SURFACEIMAGE_TF_JNI_ID);
gSurfaceImageClassInfo.mPlanes = env->GetFieldID( gSurfaceImageClassInfo.mPlanes = env->GetFieldID(
imageClazz, "mPlanes", "[Landroid/media/ImageReader$SurfaceImage$SurfacePlane;"); imageClazz, "mPlanes", "[Landroid/media/ImageReader$SurfaceImage$SurfacePlane;");
LOG_ALWAYS_FATAL_IF(gSurfaceImageClassInfo.mPlanes == NULL, LOG_ALWAYS_FATAL_IF(gSurfaceImageClassInfo.mPlanes == NULL,
@@ -596,6 +604,8 @@ static jint ImageReader_imageSetup(JNIEnv* env, jobject thiz, jobject image) {
Image_setBufferItem(env, image, buffer); Image_setBufferItem(env, image, buffer);
env->SetLongField(image, gSurfaceImageClassInfo.mTimestamp, env->SetLongField(image, gSurfaceImageClassInfo.mTimestamp,
static_cast<jlong>(buffer->mTimestamp)); static_cast<jlong>(buffer->mTimestamp));
env->SetIntField(image, gSurfaceImageClassInfo.mTransform,
static_cast<jint>(buffer->mTransform));
return ACQUIRE_SUCCESS; return ACQUIRE_SUCCESS;
} }

View File

@@ -421,7 +421,7 @@ static void ImageWriter_cancelImage(JNIEnv* env, jobject thiz, jlong nativeCtx,
} }
static void ImageWriter_queueImage(JNIEnv* env, jobject thiz, jlong nativeCtx, jobject image, static void ImageWriter_queueImage(JNIEnv* env, jobject thiz, jlong nativeCtx, jobject image,
jlong timestampNs, jint left, jint top, jint right, jint bottom) { jlong timestampNs, jint left, jint top, jint right, jint bottom, jint transform) {
ALOGV("%s", __FUNCTION__); ALOGV("%s", __FUNCTION__);
JNIImageWriterContext* const ctx = reinterpret_cast<JNIImageWriterContext *>(nativeCtx); JNIImageWriterContext* const ctx = reinterpret_cast<JNIImageWriterContext *>(nativeCtx);
if (ctx == NULL || thiz == NULL) { if (ctx == NULL || thiz == NULL) {
@@ -465,6 +465,12 @@ static void ImageWriter_queueImage(JNIEnv* env, jobject thiz, jlong nativeCtx, j
return; return;
} }
res = native_window_set_buffers_transform(anw.get(), transform);
if (res != OK) {
jniThrowRuntimeException(env, "Set transform failed");
return;
}
// 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) {
@@ -487,7 +493,7 @@ static void ImageWriter_queueImage(JNIEnv* env, jobject thiz, jlong nativeCtx, j
static jint ImageWriter_attachAndQueueImage(JNIEnv* env, jobject thiz, jlong nativeCtx, static jint ImageWriter_attachAndQueueImage(JNIEnv* env, jobject thiz, jlong nativeCtx,
jlong nativeBuffer, jint imageFormat, jlong timestampNs, jint left, jint top, jlong nativeBuffer, jint imageFormat, jlong timestampNs, jint left, jint top,
jint right, jint bottom) { jint right, jint bottom, jint transform) {
ALOGV("%s", __FUNCTION__); ALOGV("%s", __FUNCTION__);
JNIImageWriterContext* const ctx = reinterpret_cast<JNIImageWriterContext *>(nativeCtx); JNIImageWriterContext* const ctx = reinterpret_cast<JNIImageWriterContext *>(nativeCtx);
if (ctx == NULL || thiz == NULL) { if (ctx == NULL || thiz == NULL) {
@@ -530,7 +536,7 @@ static jint ImageWriter_attachAndQueueImage(JNIEnv* env, jobject thiz, jlong nat
} }
sp < ANativeWindow > anw = surface; sp < ANativeWindow > anw = surface;
// Step 2. Set timestamp and crop. Note that we do not need unlock the image because // Step 2. Set timestamp, crop and transform. Note that we do not need unlock the image because
// it was not locked. // it was not locked.
ALOGV("timestamp to be queued: %" PRId64, timestampNs); ALOGV("timestamp to be queued: %" PRId64, timestampNs);
res = native_window_set_buffers_timestamp(anw.get(), timestampNs); res = native_window_set_buffers_timestamp(anw.get(), timestampNs);
@@ -550,6 +556,12 @@ static jint ImageWriter_attachAndQueueImage(JNIEnv* env, jobject thiz, jlong nat
return res; return res;
} }
res = native_window_set_buffers_transform(anw.get(), transform);
if (res != OK) {
jniThrowRuntimeException(env, "Set transform failed");
return res;
}
// Step 3. Queue Image. // Step 3. Queue Image.
res = anw->queueBuffer(anw.get(), buffer->mGraphicBuffer.get(), /*fenceFd*/ res = anw->queueBuffer(anw.get(), buffer->mGraphicBuffer.get(), /*fenceFd*/
-1); -1);
@@ -785,9 +797,9 @@ static JNINativeMethod gImageWriterMethods[] = {
{"nativeInit", "(Ljava/lang/Object;Landroid/view/Surface;II)J", {"nativeInit", "(Ljava/lang/Object;Landroid/view/Surface;II)J",
(void*)ImageWriter_init }, (void*)ImageWriter_init },
{"nativeClose", "(J)V", (void*)ImageWriter_close }, {"nativeClose", "(J)V", (void*)ImageWriter_close },
{"nativeAttachAndQueueImage", "(JJIJIIII)I", (void*)ImageWriter_attachAndQueueImage }, {"nativeAttachAndQueueImage", "(JJIJIIIII)I", (void*)ImageWriter_attachAndQueueImage },
{"nativeDequeueInputImage", "(JLandroid/media/Image;)V", (void*)ImageWriter_dequeueImage }, {"nativeDequeueInputImage", "(JLandroid/media/Image;)V", (void*)ImageWriter_dequeueImage },
{"nativeQueueInputImage", "(JLandroid/media/Image;JIIII)V", (void*)ImageWriter_queueImage }, {"nativeQueueInputImage", "(JLandroid/media/Image;JIIIII)V", (void*)ImageWriter_queueImage },
{"cancelImage", "(JLandroid/media/Image;)V", (void*)ImageWriter_cancelImage }, {"cancelImage", "(JLandroid/media/Image;)V", (void*)ImageWriter_cancelImage },
}; };