camera2: Switch to using YV12 for ImageReader.
Bug: 15116722 - Also fixes incorrect frame number for single captures. Change-Id: I8552124d18ad176e6724f089a1e3a3f49a5eeec4
This commit is contained in:
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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(
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
Reference in New Issue
Block a user