summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java10
-rw-r--r--core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java2
-rw-r--r--core/java/android/hardware/camera2/legacy/RequestQueue.java2
-rw-r--r--core/java/android/hardware/camera2/legacy/RequestThreadManager.java7
-rw-r--r--core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java2
-rw-r--r--core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp42
-rw-r--r--media/jni/android_media_ImageReader.cpp11
7 files changed, 64 insertions, 12 deletions
diff --git a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
index 50515a2927a6..cb951b320b6a 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
@@ -174,13 +174,17 @@ public class LegacyCameraDevice implements AutoCloseable {
private final RequestThreadManager mRequestThreadManager;
/**
- * Check if a given surface uses {@link ImageFormat#YUV_420_888} format.
+ * Check if a given surface uses {@link ImageFormat#YUV_420_888} or format that can be readily
+ * converted to this; YV12 and NV21 are the two currently supported formats.
*
* @param s the surface to check.
- * @return {@code true} if the surfaces uses {@link ImageFormat#YUV_420_888}.
+ * @return {@code true} if the surfaces uses {@link ImageFormat#YUV_420_888} or a compatible
+ * format.
*/
static boolean needsConversion(Surface s) {
- return LegacyCameraDevice.nativeDetectSurfaceType(s) == ImageFormat.YUV_420_888;
+ int nativeType = LegacyCameraDevice.nativeDetectSurfaceType(s);
+ return nativeType == ImageFormat.YUV_420_888 || nativeType == ImageFormat.YV12 ||
+ nativeType == ImageFormat.NV21;
}
/**
diff --git a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
index 6fa2134571fb..7f23561d6dcb 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
@@ -49,7 +49,7 @@ public class LegacyMetadataMapper {
private static final int HAL_PIXEL_FORMAT_BLOB = 0x21;
private static final long APPROXIMATE_CAPTURE_DELAY_MS = 200; // ms
- private static final long APPROXIMATE_SENSOR_AREA = (1 << 20); // 8mp
+ private static final long APPROXIMATE_SENSOR_AREA = (1 << 23); // 8mp
private static final long APPROXIMATE_JPEG_ENCODE_TIME = 600; // ms
private static final long NS_PER_MS = 1000000;
diff --git a/core/java/android/hardware/camera2/legacy/RequestQueue.java b/core/java/android/hardware/camera2/legacy/RequestQueue.java
index 5c6830372b10..6bedc48aaa8b 100644
--- a/core/java/android/hardware/camera2/legacy/RequestQueue.java
+++ b/core/java/android/hardware/camera2/legacy/RequestQueue.java
@@ -122,7 +122,7 @@ public class RequestQueue {
for (BurstHolder b : mRequestQueue) {
total += b.getNumberOfRequests();
if (b.getRequestId() == requestId) {
- return total;
+ return total - 1;
}
}
throw new IllegalStateException(
diff --git a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
index e0f3429d8bec..a4b10997125d 100644
--- a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
+++ b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
@@ -239,6 +239,9 @@ public class RequestThreadManager {
mGLThreadManager.queueNewFrame(holder.getHolderTargets());
}
+ /**
+ * TODO: Get timestamp from GL thread after buffer update.
+ */
mLastPreviewTimestamp = surfaceTexture.getTimestamp();
mReceivedPreview.open();
}
@@ -495,7 +498,6 @@ public class RequestThreadManager {
if (holder.hasJpegTargets()) {
mReceivedJpeg.close();
doJpegCapture(holder);
- mReceivedJpeg.block();
if (!mReceivedJpeg.block(JPEG_FRAME_TIMEOUT)) {
// TODO: report error to CameraDevice
Log.e(TAG, "Hit timeout for jpeg callback!");
@@ -507,6 +509,9 @@ public class RequestThreadManager {
// TODO: err handling
throw new IOError(e);
}
+ if (timestamp == 0) {
+ timestamp = SystemClock.elapsedRealtimeNanos();
+ }
CameraMetadataNative result = LegacyMetadataMapper.convertResultMetadata(mParams,
request, timestamp);
mDeviceState.setCaptureResult(holder, result);
diff --git a/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java b/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java
index e9d32f0caa34..bbc700583981 100644
--- a/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java
+++ b/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java
@@ -439,7 +439,7 @@ public class SurfaceTextureRenderer {
for (Surface s : surfaces) {
// If pixel conversions aren't handled by egl, use a pbuffer
if (LegacyCameraDevice.needsConversion(s)) {
- LegacyCameraDevice.nativeSetSurfaceFormat(s, ImageFormat.NV21);
+ LegacyCameraDevice.nativeSetSurfaceFormat(s, ImageFormat.YV12);
EGLSurfaceHolder holder = new EGLSurfaceHolder();
holder.surface = s;
mConversionSurfaces.add(holder);
diff --git a/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp b/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
index 40e95447a41f..004842649788 100644
--- a/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
+++ b/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
@@ -35,6 +35,8 @@ using namespace android;
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(*(a)))
+#define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) )
+
/**
* Convert from RGB 888 to Y'CbCr using the conversion specified in ITU-R BT.601 for
* digital RGB with K_b = 0.114, and K_r = 0.299.
@@ -152,6 +154,11 @@ static status_t produceFrame(const sp<ANativeWindow>& anw,
ANativeWindowBuffer* anb;
ALOGV("%s: Dequeue buffer from %p",__FUNCTION__, anw.get());
+ if (width < 0 || height < 0 || bufSize < 0) {
+ ALOGE("%s: Illegal argument, negative dimension passed to produceFrame", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
// TODO: Switch to using Surface::lock and Surface::unlockAndPost
err = native_window_dequeue_buffer_and_wait(anw.get(), &anb);
if (err != NO_ERROR) return err;
@@ -181,6 +188,41 @@ static status_t produceFrame(const sp<ANativeWindow>& anw,
uPlane, vPlane, chromaStep, yStride, chromaStride);
break;
}
+ case HAL_PIXEL_FORMAT_YV12: {
+ if (bufSize < width * height * 4) {
+ ALOGE("%s: PixelBuffer size %lld to small for given dimensions", __FUNCTION__,
+ bufSize);
+ return BAD_VALUE;
+ }
+
+ if ((width & 1) || (height & 1)) {
+ ALOGE("%s: Dimens %dx%d are not divisible by 2.", __FUNCTION__, width, height);
+ return BAD_VALUE;
+ }
+
+ uint8_t* img = NULL;
+ ALOGV("%s: Lock buffer from %p for write", __FUNCTION__, anw.get());
+ err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
+ if (err != NO_ERROR) {
+ ALOGE("%s: Error %s (%d) while locking gralloc buffer for write.", __FUNCTION__,
+ strerror(-err), err);
+ return err;
+ }
+
+ uint32_t stride = buf->getStride();
+ LOG_ALWAYS_FATAL_IF(stride % 16, "Stride is not 16 pixel aligned %d", stride);
+
+ uint32_t cStride = ALIGN(stride / 2, 16);
+ size_t chromaStep = 1;
+
+ uint8_t* yPlane = img;
+ uint8_t* crPlane = img + static_cast<uint32_t>(height) * stride;
+ uint8_t* cbPlane = crPlane + cStride * static_cast<uint32_t>(height) / 2;
+
+ rgbToYuv420(pixelBuffer, width, height, yPlane,
+ crPlane, cbPlane, chromaStep, stride, cStride);
+ break;
+ }
case HAL_PIXEL_FORMAT_YCbCr_420_888: {
// Software writes with YCbCr_420_888 format are unsupported
// by the gralloc module for now
diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp
index 36cfb0fe4bee..41ed9e133706 100644
--- a/media/jni/android_media_ImageReader.cpp
+++ b/media/jni/android_media_ImageReader.cpp
@@ -767,11 +767,12 @@ static jint ImageReader_imageSetup(JNIEnv* env, jobject thiz,
int imgReaderFmt = ctx->getBufferFormat();
int bufFmt = buffer->format;
if (imgReaderFmt != bufFmt) {
- // Special casing for when producer switches format
- if (imgReaderFmt == HAL_PIXEL_FORMAT_YCbCr_420_888 && bufFmt ==
- HAL_PIXEL_FORMAT_YCrCb_420_SP) {
- ctx->setBufferFormat(HAL_PIXEL_FORMAT_YCrCb_420_SP);
- ALOGV("%s: Overriding NV21 to YUV_420_888.", __FUNCTION__);
+ // Special casing for when producer switches to a format compatible with flexible YUV
+ // (HAL_PIXEL_FORMAT_YCbCr_420_888).
+ if (imgReaderFmt == HAL_PIXEL_FORMAT_YCbCr_420_888 && (bufFmt ==
+ HAL_PIXEL_FORMAT_YCrCb_420_SP || bufFmt == HAL_PIXEL_FORMAT_YV12)) {
+ ctx->setBufferFormat(bufFmt);
+ ALOGV("%s: Overriding buffer format YUV_420_888 to %x.", __FUNCTION__, bufFmt);
} else {
// Return the buffer to the queue.
consumer->unlockBuffer(*buffer);