Merge "Camera: Populate Image tranformation in reader and writer" into pi-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
d41fed72c7
@@ -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.
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user