summaryrefslogtreecommitdiffstats
path: root/core/jni
diff options
context:
space:
mode:
authorRuben Brunk <rubenbrunk@google.com>2014-09-27 02:16:29 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2014-09-27 02:16:30 +0000
commit7b28c66a6cc10b48231f8a5d8d45f5e22322e798 (patch)
treeb98606f0868552c660b5e301a601b4371b720165 /core/jni
parentc8a3e0dc9d4c1e59ad250f45c2ee416beee8dd89 (diff)
parent31798f33184fd59dd3d3cc55e6373d9f91d220b6 (diff)
downloadframeworks_base-7b28c66a6cc10b48231f8a5d8d45f5e22322e798.zip
frameworks_base-7b28c66a6cc10b48231f8a5d8d45f5e22322e798.tar.gz
frameworks_base-7b28c66a6cc10b48231f8a5d8d45f5e22322e798.tar.bz2
Merge "camera2: Fix native ImageReader test segfaults." into lmp-dev
Diffstat (limited to 'core/jni')
-rw-r--r--core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp111
1 files changed, 72 insertions, 39 deletions
diff --git a/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp b/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
index ee00161..b90e493 100644
--- a/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
+++ b/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
@@ -52,15 +52,15 @@ using namespace android;
* 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.
*/
-static void rgbToYuv420(uint8_t* rgbBuf, int32_t width, int32_t height, uint8_t* yPlane,
+static void rgbToYuv420(uint8_t* rgbBuf, size_t width, size_t height, uint8_t* yPlane,
uint8_t* uPlane, uint8_t* vPlane, size_t chromaStep, size_t yStride, size_t chromaStride) {
uint8_t R, G, B;
size_t index = 0;
- int32_t cStrideDiff = chromaStride - width;
+ size_t cStrideDiff = chromaStride - width;
- for (int32_t j = 0; j < height; j++) {
- for (int32_t i = 0; i < width; i++) {
+ for (size_t j = 0; j < height; j++) {
+ for (size_t i = 0; i < width; i++) {
R = rgbBuf[index++];
G = rgbBuf[index++];
B = rgbBuf[index++];
@@ -83,7 +83,7 @@ static void rgbToYuv420(uint8_t* rgbBuf, int32_t width, int32_t height, uint8_t*
}
}
-static void rgbToYuv420(uint8_t* rgbBuf, int32_t width, int32_t height, android_ycbcr* ycbcr) {
+static void rgbToYuv420(uint8_t* rgbBuf, size_t width, size_t height, android_ycbcr* ycbcr) {
size_t cStep = ycbcr->chroma_step;
size_t cStride = ycbcr->cstride;
size_t yStride = ycbcr->ystride;
@@ -157,15 +157,15 @@ static status_t configureSurface(const sp<ANativeWindow>& anw,
*/
static status_t produceFrame(const sp<ANativeWindow>& anw,
uint8_t* pixelBuffer,
- int32_t width, // Width of the pixelBuffer
- int32_t height, // Height of the pixelBuffer
+ int32_t bufWidth, // Width of the pixelBuffer
+ int32_t bufHeight, // Height of the pixelBuffer
int32_t pixelFmt, // Format of the pixelBuffer
int32_t bufSize) {
ATRACE_CALL();
status_t err = NO_ERROR;
ANativeWindowBuffer* anb;
ALOGV("%s: Dequeue buffer from %p %dx%d (fmt=%x, size=%x)",
- __FUNCTION__, anw.get(), width, height, pixelFmt, bufSize);
+ __FUNCTION__, anw.get(), bufWidth, bufHeight, pixelFmt, bufSize);
if (anw == 0) {
ALOGE("%s: anw must not be NULL", __FUNCTION__);
@@ -173,10 +173,10 @@ static status_t produceFrame(const sp<ANativeWindow>& anw,
} else if (pixelBuffer == NULL) {
ALOGE("%s: pixelBuffer must not be NULL", __FUNCTION__);
return BAD_VALUE;
- } else if (width < 0) {
+ } else if (bufWidth < 0) {
ALOGE("%s: width must be non-negative", __FUNCTION__);
return BAD_VALUE;
- } else if (height < 0) {
+ } else if (bufHeight < 0) {
ALOGE("%s: height must be non-negative", __FUNCTION__);
return BAD_VALUE;
} else if (bufSize < 0) {
@@ -184,24 +184,56 @@ static status_t produceFrame(const sp<ANativeWindow>& anw,
return BAD_VALUE;
}
- if (width < 0 || height < 0 || bufSize < 0) {
- ALOGE("%s: Illegal argument, negative dimension passed to produceFrame", __FUNCTION__);
- return BAD_VALUE;
- }
+ size_t width = static_cast<size_t>(bufWidth);
+ size_t height = static_cast<size_t>(bufHeight);
+ size_t bufferLength = static_cast<size_t>(bufSize);
// 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;
- // TODO: check anb is large enough to store the results
-
sp<GraphicBuffer> buf(new GraphicBuffer(anb, /*keepOwnership*/false));
+ uint32_t gBufWidth = buf->getWidth();
+ uint32_t gBufHeight = buf->getHeight();
+ if (gBufWidth != width || gBufHeight != height) {
+ ALOGE("%s: Received gralloc buffer with bad dimensions %" PRIu32 "x%" PRIu32
+ ", expecting dimensions %zu x %zu", __FUNCTION__, gBufWidth, gBufHeight,
+ width, height);
+ return BAD_VALUE;
+ }
+
+ int32_t bufFmt = 0;
+ err = anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &bufFmt);
+ if (err != NO_ERROR) {
+ ALOGE("%s: Error while querying surface pixel format %s (%d).", __FUNCTION__,
+ strerror(-err), err);
+ return err;
+ }
+
+ uint64_t tmpSize = width * height;
+ if (bufFmt != pixelFmt) {
+ if (bufFmt == HAL_PIXEL_FORMAT_RGBA_8888 && pixelFmt == HAL_PIXEL_FORMAT_BLOB) {
+ ALOGV("%s: Using BLOB to RGBA format override.", __FUNCTION__);
+ tmpSize *= 4;
+ } else {
+ ALOGW("%s: Format mismatch in produceFrame: expecting format %#" PRIx32
+ ", but received buffer with format %#" PRIx32, __FUNCTION__, pixelFmt, bufFmt);
+ }
+ }
+
+ if (tmpSize > SIZE_MAX) {
+ ALOGE("%s: Overflow calculating size, buffer with dimens %zu x %zu is absurdly large...",
+ __FUNCTION__, width, height);
+ return BAD_VALUE;
+ }
+
+ size_t totalSizeBytes = tmpSize;
switch(pixelFmt) {
case HAL_PIXEL_FORMAT_YCrCb_420_SP: {
- if (bufSize < width * height * 4) {
- ALOGE("%s: PixelBuffer size %" PRId32 " too small for given dimensions",
- __FUNCTION__, bufSize);
+ if (bufferLength < totalSizeBytes) {
+ ALOGE("%s: PixelBuffer size %zu too small for given dimensions",
+ __FUNCTION__, bufferLength);
return BAD_VALUE;
}
uint8_t* img = NULL;
@@ -221,14 +253,14 @@ static status_t produceFrame(const sp<ANativeWindow>& anw,
break;
}
case HAL_PIXEL_FORMAT_YV12: {
- if (bufSize < width * height * 4) {
- ALOGE("%s: PixelBuffer size %" PRId32 " too small for given dimensions",
- __FUNCTION__, bufSize);
+ if (bufferLength < totalSizeBytes) {
+ ALOGE("%s: PixelBuffer size %zu too small for given dimensions",
+ __FUNCTION__, bufferLength);
return BAD_VALUE;
}
if ((width & 1) || (height & 1)) {
- ALOGE("%s: Dimens %dx%d are not divisible by 2.", __FUNCTION__, width, height);
+ ALOGE("%s: Dimens %zu x %zu are not divisible by 2.", __FUNCTION__, width, height);
return BAD_VALUE;
}
@@ -258,9 +290,9 @@ static status_t produceFrame(const sp<ANativeWindow>& anw,
case HAL_PIXEL_FORMAT_YCbCr_420_888: {
// Software writes with YCbCr_420_888 format are unsupported
// by the gralloc module for now
- if (bufSize < width * height * 4) {
- ALOGE("%s: PixelBuffer size %" PRId32 " too small for given dimensions",
- __FUNCTION__, bufSize);
+ if (bufferLength < totalSizeBytes) {
+ ALOGE("%s: PixelBuffer size %zu too small for given dimensions",
+ __FUNCTION__, bufferLength);
return BAD_VALUE;
}
android_ycbcr ycbcr = android_ycbcr();
@@ -276,34 +308,35 @@ static status_t produceFrame(const sp<ANativeWindow>& anw,
break;
}
case HAL_PIXEL_FORMAT_BLOB: {
- if (bufSize != width || height != 1) {
- ALOGE("%s: Incorrect pixelBuffer size: %" PRId32, __FUNCTION__, bufSize);
- return BAD_VALUE;
- }
int8_t* img = NULL;
struct camera3_jpeg_blob footer = {
jpeg_blob_id: CAMERA3_JPEG_BLOB_ID,
jpeg_size: (uint32_t)width
};
- size_t totalSize = static_cast<size_t>(width) + sizeof(footer);
- size_t padding = ((totalSize - 1) & ~0x3) + 4; // align to next octonibble
- totalSize += padding;
- if (anb->width != totalSize) {
- ALOGE("%s: gralloc buffer wrong size to hold jpeg, failed to produce buffer.");
+ size_t totalJpegSize = bufferLength + sizeof(footer);
+ totalJpegSize = (totalJpegSize + 3) & ~0x3; // round up to nearest octonibble
+
+ if (height != 1) {
+ ALOGE("%s: Invalid height set for JPEG buffer output, %zu", __FUNCTION__, height);
+ return BAD_VALUE;
+ }
+
+ if (totalJpegSize > totalSizeBytes) {
+ ALOGE("%s: Pixel buffer needs size %zu, cannot fit in gralloc buffer of size %zu",
+ __FUNCTION__, totalJpegSize, totalSizeBytes);
return BAD_VALUE;
}
- 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: Failed to lock buffer, error %s (%d).", __FUNCTION__, strerror(-err),
err);
return err;
}
- memcpy(img, pixelBuffer, width);
- memset(img + width, 0, padding);
- memcpy(img + totalSize - sizeof(footer), &footer, sizeof(footer));
+
+ memcpy(img, pixelBuffer, bufferLength);
+ memcpy(img + totalSizeBytes - sizeof(footer), &footer, sizeof(footer));
break;
}
default: {