@@ -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 */
158158static 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 : {
0 commit comments