Skip to content

Commit 7b28c66

Browse files
rubenbrunkAndroid (Google) Code Review
authored andcommitted
Merge "camera2: Fix native ImageReader test segfaults." into lmp-dev
2 parents c8a3e0d + 31798f3 commit 7b28c66

3 files changed

Lines changed: 95 additions & 46 deletions

File tree

core/java/android/hardware/camera2/legacy/RequestThreadManager.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -207,11 +207,18 @@ public void onPictureTaken(byte[] data, Camera camera) {
207207
Log.i(TAG, "Producing jpeg buffer...");
208208

209209
int totalSize = data.length + LegacyCameraDevice.nativeGetJpegFooterSize();
210-
totalSize += ((totalSize - 1) & ~0x3) + 4; // align to next octonibble
211-
210+
totalSize = (totalSize + 3) & ~0x3; // round up to nearest octonibble
211+
212+
if (USE_BLOB_FORMAT_OVERRIDE) {
213+
// Override to RGBA_8888 format.
214+
LegacyCameraDevice.setSurfaceFormat(s,
215+
LegacyMetadataMapper.HAL_PIXEL_FORMAT_RGBA_8888);
216+
// divide by 4 if using RGBA format (width is in pixels, not bytes).
217+
totalSize >>= 2;
218+
}
212219
LegacyCameraDevice.setSurfaceDimens(s, totalSize, /*height*/1);
213220
LegacyCameraDevice.setNextTimestamp(s, timestamp);
214-
LegacyCameraDevice.produceFrame(s, data, data.length, /*height*/1,
221+
LegacyCameraDevice.produceFrame(s, data, totalSize, /*height*/1,
215222
CameraMetadataNative.NATIVE_JPEG_FORMAT);
216223
}
217224
} catch (LegacyExceptionUtils.BufferQueueAbandonedException e) {

core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp

Lines changed: 72 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -52,15 +52,15 @@ using namespace android;
5252
* Convert from RGB 888 to Y'CbCr using the conversion specified in ITU-R BT.601 for
5353
* digital RGB with K_b = 0.114, and K_r = 0.299.
5454
*/
55-
static void rgbToYuv420(uint8_t* rgbBuf, int32_t width, int32_t height, uint8_t* yPlane,
55+
static void rgbToYuv420(uint8_t* rgbBuf, size_t width, size_t height, uint8_t* yPlane,
5656
uint8_t* uPlane, uint8_t* vPlane, size_t chromaStep, size_t yStride, size_t chromaStride) {
5757
uint8_t R, G, B;
5858
size_t index = 0;
5959

60-
int32_t cStrideDiff = chromaStride - width;
60+
size_t cStrideDiff = chromaStride - width;
6161

62-
for (int32_t j = 0; j < height; j++) {
63-
for (int32_t i = 0; i < width; i++) {
62+
for (size_t j = 0; j < height; j++) {
63+
for (size_t i = 0; i < width; i++) {
6464
R = rgbBuf[index++];
6565
G = rgbBuf[index++];
6666
B = rgbBuf[index++];
@@ -83,7 +83,7 @@ static void rgbToYuv420(uint8_t* rgbBuf, int32_t width, int32_t height, uint8_t*
8383
}
8484
}
8585

86-
static void rgbToYuv420(uint8_t* rgbBuf, int32_t width, int32_t height, android_ycbcr* ycbcr) {
86+
static void rgbToYuv420(uint8_t* rgbBuf, size_t width, size_t height, android_ycbcr* ycbcr) {
8787
size_t cStep = ycbcr->chroma_step;
8888
size_t cStride = ycbcr->cstride;
8989
size_t yStride = ycbcr->ystride;
@@ -157,51 +157,83 @@ static status_t configureSurface(const sp<ANativeWindow>& anw,
157157
*/
158158
static status_t produceFrame(const sp<ANativeWindow>& anw,
159159
uint8_t* pixelBuffer,
160-
int32_t width, // Width of the pixelBuffer
161-
int32_t height, // Height of the pixelBuffer
160+
int32_t bufWidth, // Width of the pixelBuffer
161+
int32_t bufHeight, // Height of the pixelBuffer
162162
int32_t pixelFmt, // Format of the pixelBuffer
163163
int32_t bufSize) {
164164
ATRACE_CALL();
165165
status_t err = NO_ERROR;
166166
ANativeWindowBuffer* anb;
167167
ALOGV("%s: Dequeue buffer from %p %dx%d (fmt=%x, size=%x)",
168-
__FUNCTION__, anw.get(), width, height, pixelFmt, bufSize);
168+
__FUNCTION__, anw.get(), bufWidth, bufHeight, pixelFmt, bufSize);
169169

170170
if (anw == 0) {
171171
ALOGE("%s: anw must not be NULL", __FUNCTION__);
172172
return BAD_VALUE;
173173
} else if (pixelBuffer == NULL) {
174174
ALOGE("%s: pixelBuffer must not be NULL", __FUNCTION__);
175175
return BAD_VALUE;
176-
} else if (width < 0) {
176+
} else if (bufWidth < 0) {
177177
ALOGE("%s: width must be non-negative", __FUNCTION__);
178178
return BAD_VALUE;
179-
} else if (height < 0) {
179+
} else if (bufHeight < 0) {
180180
ALOGE("%s: height must be non-negative", __FUNCTION__);
181181
return BAD_VALUE;
182182
} else if (bufSize < 0) {
183183
ALOGE("%s: bufSize must be non-negative", __FUNCTION__);
184184
return BAD_VALUE;
185185
}
186186

187-
if (width < 0 || height < 0 || bufSize < 0) {
188-
ALOGE("%s: Illegal argument, negative dimension passed to produceFrame", __FUNCTION__);
189-
return BAD_VALUE;
190-
}
187+
size_t width = static_cast<size_t>(bufWidth);
188+
size_t height = static_cast<size_t>(bufHeight);
189+
size_t bufferLength = static_cast<size_t>(bufSize);
191190

192191
// TODO: Switch to using Surface::lock and Surface::unlockAndPost
193192
err = native_window_dequeue_buffer_and_wait(anw.get(), &anb);
194193
if (err != NO_ERROR) return err;
195194

196-
// TODO: check anb is large enough to store the results
197-
198195
sp<GraphicBuffer> buf(new GraphicBuffer(anb, /*keepOwnership*/false));
196+
uint32_t gBufWidth = buf->getWidth();
197+
uint32_t gBufHeight = buf->getHeight();
198+
if (gBufWidth != width || gBufHeight != height) {
199+
ALOGE("%s: Received gralloc buffer with bad dimensions %" PRIu32 "x%" PRIu32
200+
", expecting dimensions %zu x %zu", __FUNCTION__, gBufWidth, gBufHeight,
201+
width, height);
202+
return BAD_VALUE;
203+
}
204+
205+
int32_t bufFmt = 0;
206+
err = anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &bufFmt);
207+
if (err != NO_ERROR) {
208+
ALOGE("%s: Error while querying surface pixel format %s (%d).", __FUNCTION__,
209+
strerror(-err), err);
210+
return err;
211+
}
212+
213+
uint64_t tmpSize = width * height;
214+
if (bufFmt != pixelFmt) {
215+
if (bufFmt == HAL_PIXEL_FORMAT_RGBA_8888 && pixelFmt == HAL_PIXEL_FORMAT_BLOB) {
216+
ALOGV("%s: Using BLOB to RGBA format override.", __FUNCTION__);
217+
tmpSize *= 4;
218+
} else {
219+
ALOGW("%s: Format mismatch in produceFrame: expecting format %#" PRIx32
220+
", but received buffer with format %#" PRIx32, __FUNCTION__, pixelFmt, bufFmt);
221+
}
222+
}
223+
224+
if (tmpSize > SIZE_MAX) {
225+
ALOGE("%s: Overflow calculating size, buffer with dimens %zu x %zu is absurdly large...",
226+
__FUNCTION__, width, height);
227+
return BAD_VALUE;
228+
}
229+
230+
size_t totalSizeBytes = tmpSize;
199231

200232
switch(pixelFmt) {
201233
case HAL_PIXEL_FORMAT_YCrCb_420_SP: {
202-
if (bufSize < width * height * 4) {
203-
ALOGE("%s: PixelBuffer size %" PRId32 " too small for given dimensions",
204-
__FUNCTION__, bufSize);
234+
if (bufferLength < totalSizeBytes) {
235+
ALOGE("%s: PixelBuffer size %zu too small for given dimensions",
236+
__FUNCTION__, bufferLength);
205237
return BAD_VALUE;
206238
}
207239
uint8_t* img = NULL;
@@ -221,14 +253,14 @@ static status_t produceFrame(const sp<ANativeWindow>& anw,
221253
break;
222254
}
223255
case HAL_PIXEL_FORMAT_YV12: {
224-
if (bufSize < width * height * 4) {
225-
ALOGE("%s: PixelBuffer size %" PRId32 " too small for given dimensions",
226-
__FUNCTION__, bufSize);
256+
if (bufferLength < totalSizeBytes) {
257+
ALOGE("%s: PixelBuffer size %zu too small for given dimensions",
258+
__FUNCTION__, bufferLength);
227259
return BAD_VALUE;
228260
}
229261

230262
if ((width & 1) || (height & 1)) {
231-
ALOGE("%s: Dimens %dx%d are not divisible by 2.", __FUNCTION__, width, height);
263+
ALOGE("%s: Dimens %zu x %zu are not divisible by 2.", __FUNCTION__, width, height);
232264
return BAD_VALUE;
233265
}
234266

@@ -258,9 +290,9 @@ static status_t produceFrame(const sp<ANativeWindow>& anw,
258290
case HAL_PIXEL_FORMAT_YCbCr_420_888: {
259291
// Software writes with YCbCr_420_888 format are unsupported
260292
// by the gralloc module for now
261-
if (bufSize < width * height * 4) {
262-
ALOGE("%s: PixelBuffer size %" PRId32 " too small for given dimensions",
263-
__FUNCTION__, bufSize);
293+
if (bufferLength < totalSizeBytes) {
294+
ALOGE("%s: PixelBuffer size %zu too small for given dimensions",
295+
__FUNCTION__, bufferLength);
264296
return BAD_VALUE;
265297
}
266298
android_ycbcr ycbcr = android_ycbcr();
@@ -276,34 +308,35 @@ static status_t produceFrame(const sp<ANativeWindow>& anw,
276308
break;
277309
}
278310
case HAL_PIXEL_FORMAT_BLOB: {
279-
if (bufSize != width || height != 1) {
280-
ALOGE("%s: Incorrect pixelBuffer size: %" PRId32, __FUNCTION__, bufSize);
281-
return BAD_VALUE;
282-
}
283311
int8_t* img = NULL;
284312
struct camera3_jpeg_blob footer = {
285313
jpeg_blob_id: CAMERA3_JPEG_BLOB_ID,
286314
jpeg_size: (uint32_t)width
287315
};
288316

289-
size_t totalSize = static_cast<size_t>(width) + sizeof(footer);
290-
size_t padding = ((totalSize - 1) & ~0x3) + 4; // align to next octonibble
291-
totalSize += padding;
292-
if (anb->width != totalSize) {
293-
ALOGE("%s: gralloc buffer wrong size to hold jpeg, failed to produce buffer.");
317+
size_t totalJpegSize = bufferLength + sizeof(footer);
318+
totalJpegSize = (totalJpegSize + 3) & ~0x3; // round up to nearest octonibble
319+
320+
if (height != 1) {
321+
ALOGE("%s: Invalid height set for JPEG buffer output, %zu", __FUNCTION__, height);
322+
return BAD_VALUE;
323+
}
324+
325+
if (totalJpegSize > totalSizeBytes) {
326+
ALOGE("%s: Pixel buffer needs size %zu, cannot fit in gralloc buffer of size %zu",
327+
__FUNCTION__, totalJpegSize, totalSizeBytes);
294328
return BAD_VALUE;
295329
}
296330

297-
ALOGV("%s: Lock buffer from %p for write", __FUNCTION__, anw.get());
298331
err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
299332
if (err != NO_ERROR) {
300333
ALOGE("%s: Failed to lock buffer, error %s (%d).", __FUNCTION__, strerror(-err),
301334
err);
302335
return err;
303336
}
304-
memcpy(img, pixelBuffer, width);
305-
memset(img + width, 0, padding);
306-
memcpy(img + totalSize - sizeof(footer), &footer, sizeof(footer));
337+
338+
memcpy(img, pixelBuffer, bufferLength);
339+
memcpy(img + totalSizeBytes - sizeof(footer), &footer, sizeof(footer));
307340
break;
308341
}
309342
default: {

media/jni/android_media_ImageReader.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -286,13 +286,17 @@ static int Image_getPixelFormat(JNIEnv* env, int format)
286286
return format;
287287
}
288288

289-
static uint32_t Image_getJpegSize(CpuConsumer::LockedBuffer* buffer)
289+
static uint32_t Image_getJpegSize(CpuConsumer::LockedBuffer* buffer, bool usingRGBAOverride)
290290
{
291291
ALOG_ASSERT(buffer != NULL, "Input buffer is NULL!!!");
292292
uint32_t size = 0;
293293
uint32_t width = buffer->width;
294294
uint8_t* jpegBuffer = buffer->data;
295295

296+
if (usingRGBAOverride) {
297+
width *= 4;
298+
}
299+
296300
// First check for JPEG transport header at the end of the buffer
297301
uint8_t* header = jpegBuffer + (width - sizeof(struct camera3_jpeg_blob));
298302
struct camera3_jpeg_blob *blob = (struct camera3_jpeg_blob*)(header);
@@ -317,11 +321,15 @@ static uint32_t Image_getJpegSize(CpuConsumer::LockedBuffer* buffer)
317321
return size;
318322
}
319323

324+
static bool usingRGBAToJpegOverride(int32_t bufferFormat, int32_t readerCtxFormat) {
325+
return readerCtxFormat == HAL_PIXEL_FORMAT_BLOB && bufferFormat == HAL_PIXEL_FORMAT_RGBA_8888;
326+
}
327+
320328
static int32_t applyFormatOverrides(int32_t bufferFormat, int32_t readerCtxFormat)
321329
{
322330
// Using HAL_PIXEL_FORMAT_RGBA_8888 gralloc buffers containing JPEGs to get around SW
323331
// write limitations for some platforms (b/17379185).
324-
if (readerCtxFormat == HAL_PIXEL_FORMAT_BLOB && bufferFormat == HAL_PIXEL_FORMAT_RGBA_8888) {
332+
if (usingRGBAToJpegOverride(bufferFormat, readerCtxFormat)) {
325333
return HAL_PIXEL_FORMAT_BLOB;
326334
}
327335
return bufferFormat;
@@ -345,6 +353,7 @@ static void Image_getLockedBufferInfo(JNIEnv* env, CpuConsumer::LockedBuffer* bu
345353
dataSize = ySize = cSize = cStride = 0;
346354
int32_t fmt = buffer->format;
347355

356+
bool usingRGBAOverride = usingRGBAToJpegOverride(fmt, readerFormat);
348357
fmt = applyFormatOverrides(fmt, readerFormat);
349358
switch (fmt) {
350359
case HAL_PIXEL_FORMAT_YCbCr_420_888:
@@ -416,7 +425,7 @@ static void Image_getLockedBufferInfo(JNIEnv* env, CpuConsumer::LockedBuffer* bu
416425
ALOG_ASSERT(buffer->height == 1, "JPEG should has height value %d", buffer->height);
417426

418427
pData = buffer->data;
419-
dataSize = Image_getJpegSize(buffer);
428+
dataSize = Image_getJpegSize(buffer, usingRGBAOverride);
420429
break;
421430
case HAL_PIXEL_FORMAT_RAW_SENSOR:
422431
// Single plane 16bpp bayer data.
@@ -912,7 +921,7 @@ static jobject Image_getByteBuffer(JNIEnv* env, jobject thiz, int idx, int reade
912921
if (size > static_cast<uint32_t>(INT32_MAX)) {
913922
// Byte buffer have 'int capacity', so check the range
914923
jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
915-
"Size too large for bytebuffer capacity " PRIu32, size);
924+
"Size too large for bytebuffer capacity %" PRIu32, size);
916925
return NULL;
917926
}
918927

0 commit comments

Comments
 (0)