1 /*
2 * Copyright 2011, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 // #define LOG_NDEBUG 0
18 #define LOG_TAG "AndroidMediaUtils"
19
20 #include <hardware/camera3.h>
21 #include <utils/Log.h>
22 #include "android_media_Utils.h"
23
24 #define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) )
25
26 // Must be in sync with the value in HeicCompositeStream.cpp
27 #define CAMERA3_HEIC_BLOB_ID 0x00FE
28
29 namespace android {
30
31 // -----------Utility functions used by ImageReader/Writer JNI-----------------
32
33 enum {
34 IMAGE_MAX_NUM_PLANES = 3,
35 };
36
usingRGBAToJpegOverride(int32_t imageFormat,int32_t containerFormat)37 bool usingRGBAToJpegOverride(int32_t imageFormat,
38 int32_t containerFormat) {
39 return containerFormat == HAL_PIXEL_FORMAT_BLOB && imageFormat == HAL_PIXEL_FORMAT_RGBA_8888;
40 }
41
applyFormatOverrides(int32_t imageFormat,int32_t containerFormat)42 int32_t applyFormatOverrides(int32_t imageFormat, int32_t containerFormat) {
43 // Using HAL_PIXEL_FORMAT_RGBA_8888 gralloc buffers containing JPEGs to get around SW
44 // write limitations for some platforms (b/17379185).
45 if (usingRGBAToJpegOverride(imageFormat, containerFormat)) {
46 return HAL_PIXEL_FORMAT_BLOB;
47 }
48 return containerFormat;
49 }
50
isFormatOpaque(int format)51 bool isFormatOpaque(int format) {
52 // This is the only opaque format exposed in the ImageFormat public API.
53 // Note that we do support CPU access for HAL_PIXEL_FORMAT_RAW_OPAQUE
54 // (ImageFormat#RAW_PRIVATE) so it doesn't count as opaque here.
55 return format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
56 }
57
isPossiblyYUV(PixelFormat format)58 bool isPossiblyYUV(PixelFormat format) {
59 switch (static_cast<int>(format)) {
60 case HAL_PIXEL_FORMAT_RGBA_8888:
61 case HAL_PIXEL_FORMAT_RGBX_8888:
62 case HAL_PIXEL_FORMAT_RGB_888:
63 case HAL_PIXEL_FORMAT_RGB_565:
64 case HAL_PIXEL_FORMAT_BGRA_8888:
65 case HAL_PIXEL_FORMAT_Y8:
66 case HAL_PIXEL_FORMAT_Y16:
67 case HAL_PIXEL_FORMAT_RAW16:
68 case HAL_PIXEL_FORMAT_RAW10:
69 case HAL_PIXEL_FORMAT_RAW_OPAQUE:
70 case HAL_PIXEL_FORMAT_BLOB:
71 case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
72 case HAL_PIXEL_FORMAT_YCBCR_P010:
73 return false;
74
75 case HAL_PIXEL_FORMAT_YV12:
76 case HAL_PIXEL_FORMAT_YCbCr_420_888:
77 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
78 default:
79 return true;
80 }
81 }
82
Image_getBlobSize(LockedImage * buffer,bool usingRGBAOverride)83 uint32_t Image_getBlobSize(LockedImage* buffer, bool usingRGBAOverride) {
84 ALOGV("%s", __FUNCTION__);
85 LOG_ALWAYS_FATAL_IF(buffer == NULL, "Input buffer is NULL!!!");
86 uint32_t size = 0;
87 uint32_t width = buffer->width;
88 uint8_t* blobBuffer = buffer->data;
89
90 if (usingRGBAOverride) {
91 width = (buffer->width + buffer->stride * (buffer->height - 1)) * 4;
92 }
93
94 // First check for BLOB transport header at the end of the buffer
95 uint8_t* header = blobBuffer + (width - sizeof(struct camera3_jpeg_blob));
96 struct camera3_jpeg_blob *blob = (struct camera3_jpeg_blob*)(header);
97 if (blob->jpeg_blob_id == CAMERA3_JPEG_BLOB_ID ||
98 blob->jpeg_blob_id == CAMERA3_HEIC_BLOB_ID) {
99 size = blob->jpeg_size;
100 ALOGV("%s: Jpeg/Heic size = %d", __FUNCTION__, size);
101 }
102
103 // failed to find size, default to whole buffer
104 if (size == 0) {
105 /*
106 * This is a problem because not including the JPEG/BLOB header
107 * means that in certain rare situations a regular JPEG/HEIC blob
108 * will be mis-identified as having a header, in which case
109 * we will get a garbage size value.
110 */
111 ALOGW("%s: No JPEG/HEIC header detected, defaulting to size=width=%d",
112 __FUNCTION__, width);
113 size = width;
114 }
115
116 return size;
117 }
118
getLockedImageInfo(LockedImage * buffer,int idx,int32_t containerFormat,uint8_t ** base,uint32_t * size,int * pixelStride,int * rowStride)119 status_t getLockedImageInfo(LockedImage* buffer, int idx,
120 int32_t containerFormat, uint8_t **base, uint32_t *size, int *pixelStride, int *rowStride) {
121 ALOGV("%s", __FUNCTION__);
122 LOG_ALWAYS_FATAL_IF(buffer == NULL, "Input buffer is NULL!!!");
123 LOG_ALWAYS_FATAL_IF(base == NULL, "base is NULL!!!");
124 LOG_ALWAYS_FATAL_IF(size == NULL, "size is NULL!!!");
125 LOG_ALWAYS_FATAL_IF(pixelStride == NULL, "pixelStride is NULL!!!");
126 LOG_ALWAYS_FATAL_IF(rowStride == NULL, "rowStride is NULL!!!");
127 LOG_ALWAYS_FATAL_IF((idx >= IMAGE_MAX_NUM_PLANES) || (idx < 0), "idx (%d) is illegal", idx);
128
129 ALOGV("%s: buffer: %p", __FUNCTION__, buffer);
130
131 uint32_t dataSize, ySize, cSize, cStride;
132 uint32_t pStride = 0, rStride = 0;
133 uint8_t *cb, *cr;
134 uint8_t *pData = NULL;
135 int bytesPerPixel = 0;
136
137 dataSize = ySize = cSize = cStride = 0;
138 int32_t fmt = buffer->flexFormat;
139
140 bool usingRGBAOverride = usingRGBAToJpegOverride(fmt, containerFormat);
141 fmt = applyFormatOverrides(fmt, containerFormat);
142 switch (fmt) {
143 case HAL_PIXEL_FORMAT_YCbCr_420_888:
144 // Width and height should be multiple of 2. Wrong dataSize would be returned otherwise.
145 if (buffer->width % 2 != 0) {
146 ALOGE("YCbCr_420_888: width (%d) should be a multiple of 2", buffer->width);
147 return BAD_VALUE;
148 }
149
150 if (buffer->height % 2 != 0) {
151 ALOGE("YCbCr_420_888: height (%d) should be a multiple of 2", buffer->height);
152 return BAD_VALUE;
153 }
154
155 if (buffer->width <= 0) {
156 ALOGE("YCbCr_420_888: width (%d) should be a > 0", buffer->width);
157 return BAD_VALUE;
158 }
159
160 if (buffer->height <= 0) {
161 ALOGE("YCbCr_420_888: height (%d) should be a > 0", buffer->height);
162 return BAD_VALUE;
163 }
164
165 pData =
166 (idx == 0) ?
167 buffer->data :
168 (idx == 1) ?
169 buffer->dataCb :
170 buffer->dataCr;
171 // only map until last pixel
172 if (idx == 0) {
173 pStride = 1;
174 rStride = buffer->stride;
175 dataSize = buffer->stride * (buffer->height - 1) + buffer->width;
176 } else {
177 pStride = buffer->chromaStep;
178 rStride = buffer->chromaStride;
179 dataSize = buffer->chromaStride * (buffer->height / 2 - 1) +
180 buffer->chromaStep * (buffer->width / 2 - 1) + 1;
181 }
182 break;
183 // NV21
184 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
185 // Width and height should be multiple of 2. Wrong dataSize would be returned otherwise.
186 if (buffer->width % 2 != 0) {
187 ALOGE("YCrCb_420_SP: width (%d) should be a multiple of 2", buffer->width);
188 return BAD_VALUE;
189 }
190
191 if (buffer->height % 2 != 0) {
192 ALOGE("YCrCb_420_SP: height (%d) should be a multiple of 2", buffer->height);
193 return BAD_VALUE;
194 }
195
196 if (buffer->width <= 0) {
197 ALOGE("YCrCb_420_SP: width (%d) should be a > 0", buffer->width);
198 return BAD_VALUE;
199 }
200
201 if (buffer->height <= 0) {
202 ALOGE("YCrCb_420_SP: height (%d) should be a > 0", buffer->height);
203 return BAD_VALUE;
204 }
205
206 cr = buffer->data + (buffer->stride * buffer->height);
207 cb = cr + 1;
208 // only map until last pixel
209 ySize = buffer->width * (buffer->height - 1) + buffer->width;
210 cSize = buffer->width * (buffer->height / 2 - 1) + buffer->width - 1;
211
212 pData =
213 (idx == 0) ?
214 buffer->data :
215 (idx == 1) ?
216 cb:
217 cr;
218
219 dataSize = (idx == 0) ? ySize : cSize;
220 pStride = (idx == 0) ? 1 : 2;
221 rStride = buffer->width;
222 break;
223 case HAL_PIXEL_FORMAT_YV12:
224 // Width and height should be multiple of 2. Wrong dataSize would be returned otherwise.
225 if (buffer->width % 2 != 0) {
226 ALOGE("YV12: width (%d) should be a multiple of 2", buffer->width);
227 return BAD_VALUE;
228 }
229
230 if (buffer->height % 2 != 0) {
231 ALOGE("YV12: height (%d) should be a multiple of 2", buffer->height);
232 return BAD_VALUE;
233 }
234
235 if (buffer->width <= 0) {
236 ALOGE("YV12: width (%d) should be a > 0", buffer->width);
237 return BAD_VALUE;
238 }
239
240 if (buffer->height <= 0) {
241 ALOGE("YV12: height (%d) should be a > 0", buffer->height);
242 return BAD_VALUE;
243 }
244
245 // Y and C stride need to be 16 pixel aligned.
246 LOG_ALWAYS_FATAL_IF(buffer->stride % 16,
247 "Stride is not 16 pixel aligned %d", buffer->stride);
248
249 ySize = buffer->stride * buffer->height;
250 cStride = ALIGN(buffer->stride / 2, 16);
251 cr = buffer->data + ySize;
252 cSize = cStride * buffer->height / 2;
253 cb = cr + cSize;
254
255 pData =
256 (idx == 0) ?
257 buffer->data :
258 (idx == 1) ?
259 cb :
260 cr;
261 dataSize = (idx == 0) ? ySize : cSize;
262 pStride = 1;
263 rStride = (idx == 0) ? buffer->stride : ALIGN(buffer->stride / 2, 16);
264 break;
265 case HAL_PIXEL_FORMAT_YCBCR_P010:
266 if (buffer->height % 2 != 0) {
267 ALOGE("YCBCR_P010: height (%d) should be a multiple of 2", buffer->height);
268 return BAD_VALUE;
269 }
270
271 if (buffer->width <= 0) {
272 ALOGE("YCBCR_P010: width (%d) should be a > 0", buffer->width);
273 return BAD_VALUE;
274 }
275
276 if (buffer->height <= 0) {
277 ALOGE("YCBCR_P010: height (%d) should be a > 0", buffer->height);
278 return BAD_VALUE;
279 }
280
281 ySize = (buffer->stride * 2) * buffer->height;
282 cSize = ySize / 2;
283 pStride = (idx == 0) ? 2 : 4;
284 cb = buffer->data + ySize;
285 cr = cb + 2;
286
287 pData = (idx == 0) ? buffer->data : (idx == 1) ? cb : cr;
288 dataSize = (idx == 0) ? ySize : cSize;
289 rStride = buffer->stride * 2;
290 break;
291 case HAL_PIXEL_FORMAT_Y8:
292 // Single plane, 8bpp.
293 LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
294
295 pData = buffer->data;
296 dataSize = buffer->stride * buffer->height;
297 pStride = 1;
298 rStride = buffer->stride;
299 break;
300 case HAL_PIXEL_FORMAT_Y16:
301 bytesPerPixel = 2;
302 // Single plane, 16bpp, strides are specified in pixels, not in bytes
303 LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
304
305 pData = buffer->data;
306 dataSize = buffer->stride * buffer->height * bytesPerPixel;
307 pStride = bytesPerPixel;
308 rStride = buffer->stride * 2;
309 break;
310 case HAL_PIXEL_FORMAT_BLOB:
311 // Used for JPEG data, height must be 1, width == size, single plane.
312 LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
313 // When RGBA override is being used, buffer height will be equal to width
314 if (usingRGBAOverride) {
315 LOG_ALWAYS_FATAL_IF(buffer->height != buffer->width,
316 "RGBA override BLOB format buffer should have height == width");
317 } else {
318 LOG_ALWAYS_FATAL_IF(buffer->height != 1,
319 "BLOB format buffer should have height value 1");
320 }
321
322
323 pData = buffer->data;
324 dataSize = Image_getBlobSize(buffer, usingRGBAOverride);
325 pStride = 0;
326 rStride = 0;
327 break;
328 case HAL_PIXEL_FORMAT_RAW16:
329 // Single plane 16bpp bayer data.
330 bytesPerPixel = 2;
331 LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
332 pData = buffer->data;
333 dataSize = buffer->stride * buffer->height * bytesPerPixel;
334 pStride = bytesPerPixel;
335 rStride = buffer->stride * 2;
336 break;
337 case HAL_PIXEL_FORMAT_RAW_OPAQUE:
338 // Used for RAW_OPAQUE data, height must be 1, width == size, single plane.
339 LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
340 LOG_ALWAYS_FATAL_IF(buffer->height != 1,
341 "RAW_PRIVATE should has height value one but got %d", buffer->height);
342 pData = buffer->data;
343 dataSize = buffer->width;
344 pStride = 0; // RAW OPAQUE doesn't have pixel stride
345 rStride = 0; // RAW OPAQUE doesn't have row stride
346 break;
347 case HAL_PIXEL_FORMAT_RAW10:
348 // Single plane 10bpp bayer data.
349 LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
350 LOG_ALWAYS_FATAL_IF(buffer->width % 4,
351 "Width is not multiple of 4 %d", buffer->width);
352 LOG_ALWAYS_FATAL_IF(buffer->height % 2,
353 "Height is not even %d", buffer->height);
354 LOG_ALWAYS_FATAL_IF(buffer->stride < (buffer->width * 10 / 8),
355 "stride (%d) should be at least %d",
356 buffer->stride, buffer->width * 10 / 8);
357 pData = buffer->data;
358 dataSize = buffer->stride * buffer->height;
359 pStride = 0;
360 rStride = buffer->stride;
361 break;
362 case HAL_PIXEL_FORMAT_RAW12:
363 // Single plane 10bpp bayer data.
364 LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
365 LOG_ALWAYS_FATAL_IF(buffer->width % 4,
366 "Width is not multiple of 4 %d", buffer->width);
367 LOG_ALWAYS_FATAL_IF(buffer->height % 2,
368 "Height is not even %d", buffer->height);
369 LOG_ALWAYS_FATAL_IF(buffer->stride < (buffer->width * 12 / 8),
370 "stride (%d) should be at least %d",
371 buffer->stride, buffer->width * 12 / 8);
372 pData = buffer->data;
373 dataSize = buffer->stride * buffer->height;
374 pStride = 0;
375 rStride = buffer->stride;
376 break;
377 case HAL_PIXEL_FORMAT_RGBA_8888:
378 case HAL_PIXEL_FORMAT_RGBX_8888:
379 // Single plane, 32bpp.
380 bytesPerPixel = 4;
381 LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
382 pData = buffer->data;
383 dataSize = buffer->stride * buffer->height * bytesPerPixel;
384 pStride = bytesPerPixel;
385 rStride = buffer->stride * 4;
386 break;
387 case HAL_PIXEL_FORMAT_RGB_565:
388 // Single plane, 16bpp.
389 bytesPerPixel = 2;
390 LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
391 pData = buffer->data;
392 dataSize = buffer->stride * buffer->height * bytesPerPixel;
393 pStride = bytesPerPixel;
394 rStride = buffer->stride * 2;
395 break;
396 case HAL_PIXEL_FORMAT_RGB_888:
397 // Single plane, 24bpp.
398 bytesPerPixel = 3;
399 LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
400 pData = buffer->data;
401 dataSize = buffer->stride * buffer->height * bytesPerPixel;
402 pStride = bytesPerPixel;
403 rStride = buffer->stride * 3;
404 break;
405 default:
406 return BAD_VALUE;
407 }
408
409 *base = pData;
410 *size = dataSize;
411 *pixelStride = pStride;
412 *rowStride = rStride;
413
414 return OK;
415 }
416
lockImageFromBuffer(sp<GraphicBuffer> buffer,uint32_t inUsage,const Rect & rect,int fenceFd,LockedImage * outputImage)417 status_t lockImageFromBuffer(sp<GraphicBuffer> buffer, uint32_t inUsage,
418 const Rect& rect, int fenceFd, LockedImage* outputImage) {
419 ALOGV("%s: Try to lock the GraphicBuffer", __FUNCTION__);
420
421 if (buffer == nullptr || outputImage == nullptr) {
422 ALOGE("Input BufferItem or output LockedImage is NULL!");
423 return BAD_VALUE;
424 }
425 if (isFormatOpaque(buffer->getPixelFormat())) {
426 ALOGE("Opaque format buffer is not lockable!");
427 return BAD_VALUE;
428 }
429
430 void* pData = NULL;
431 android_ycbcr ycbcr = android_ycbcr();
432 status_t res;
433 int format = buffer->getPixelFormat();
434 int flexFormat = format;
435 if (isPossiblyYUV(format)) {
436 res = buffer->lockAsyncYCbCr(inUsage, rect, &ycbcr, fenceFd);
437
438 if (res != OK) {
439 ALOGW("lockAsyncYCbCr failed with error %d", res);
440 }
441
442 pData = ycbcr.y;
443 flexFormat = HAL_PIXEL_FORMAT_YCbCr_420_888;
444 }
445
446 // lockAsyncYCbCr for YUV is unsuccessful.
447 if (pData == NULL) {
448 res = buffer->lockAsync(inUsage, rect, &pData, fenceFd);
449 if (res != OK) {
450 ALOGE("Lock buffer failed!");
451 return res;
452 }
453 }
454
455 outputImage->data = reinterpret_cast<uint8_t*>(pData);
456 outputImage->width = buffer->getWidth();
457 outputImage->height = buffer->getHeight();
458 outputImage->format = format;
459 outputImage->flexFormat = flexFormat;
460 outputImage->stride =
461 (ycbcr.y != NULL) ? static_cast<uint32_t>(ycbcr.ystride) : buffer->getStride();
462
463 outputImage->dataCb = reinterpret_cast<uint8_t*>(ycbcr.cb);
464 outputImage->dataCr = reinterpret_cast<uint8_t*>(ycbcr.cr);
465 outputImage->chromaStride = static_cast<uint32_t>(ycbcr.cstride);
466 outputImage->chromaStep = static_cast<uint32_t>(ycbcr.chroma_step);
467 ALOGV("%s: Successfully locked the image from the GraphicBuffer", __FUNCTION__);
468 // Crop, transform, scalingMode, timestamp, and frameNumber should be set by caller,
469 // and cann't be set them here.
470 return OK;
471 }
472
lockImageFromBuffer(BufferItem * bufferItem,uint32_t inUsage,int fenceFd,LockedImage * outputImage)473 status_t lockImageFromBuffer(BufferItem* bufferItem, uint32_t inUsage,
474 int fenceFd, LockedImage* outputImage) {
475 ALOGV("%s: Try to lock the BufferItem", __FUNCTION__);
476 if (bufferItem == nullptr || outputImage == nullptr) {
477 ALOGE("Input BufferItem or output LockedImage is NULL!");
478 return BAD_VALUE;
479 }
480
481 status_t res = lockImageFromBuffer(bufferItem->mGraphicBuffer, inUsage, bufferItem->mCrop,
482 fenceFd, outputImage);
483 if (res != OK) {
484 ALOGE("%s: lock graphic buffer failed", __FUNCTION__);
485 return res;
486 }
487
488 outputImage->crop = bufferItem->mCrop;
489 outputImage->transform = bufferItem->mTransform;
490 outputImage->scalingMode = bufferItem->mScalingMode;
491 outputImage->timestamp = bufferItem->mTimestamp;
492 outputImage->dataSpace = bufferItem->mDataSpace;
493 outputImage->frameNumber = bufferItem->mFrameNumber;
494 ALOGV("%s: Successfully locked the image from the BufferItem", __FUNCTION__);
495 return OK;
496 }
497
getBufferWidth(BufferItem * buffer)498 int getBufferWidth(BufferItem* buffer) {
499 if (buffer == NULL) return -1;
500
501 if (!buffer->mCrop.isEmpty()) {
502 return buffer->mCrop.getWidth();
503 }
504
505 ALOGV("%s: buffer->mGraphicBuffer: %p", __FUNCTION__, buffer->mGraphicBuffer.get());
506 return buffer->mGraphicBuffer->getWidth();
507 }
508
getBufferHeight(BufferItem * buffer)509 int getBufferHeight(BufferItem* buffer) {
510 if (buffer == NULL) return -1;
511
512 if (!buffer->mCrop.isEmpty()) {
513 return buffer->mCrop.getHeight();
514 }
515
516 ALOGV("%s: buffer->mGraphicBuffer: %p", __FUNCTION__, buffer->mGraphicBuffer.get());
517 return buffer->mGraphicBuffer->getHeight();
518 }
519
520 } // namespace android
521
522