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 "android_media_Utils.h"
21
22 #ifdef __ANDROID__ // Layoutlib does not support hardware
23 #include <aidl/android/hardware/graphics/common/PixelFormat.h>
24 #include <aidl/android/hardware/graphics/common/PlaneLayoutComponentType.h>
25 #include <ui/GraphicBufferMapper.h>
26 #include <ui/GraphicTypes.h>
27 #endif
28 #include <utils/Log.h>
29
30 #define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) )
31
32 // Must be in sync with the value in HeicCompositeStream.cpp
33 #define CAMERA3_HEIC_BLOB_ID 0x00FE
34
35 namespace android {
36
37 // -----------Utility functions used by ImageReader/Writer JNI-----------------
38
39 #ifdef __ANDROID__
40 using AidlPixelFormat = aidl::android::hardware::graphics::common::PixelFormat;
41 #else
42 namespace AidlPixelFormat {
43 const int32_t YCBCR_P210 = 60;
44 }
45 #endif
46
47 enum {
48 IMAGE_MAX_NUM_PLANES = 3,
49 };
50
usingRGBAToJpegOverride(int32_t imageFormat,int32_t containerFormat)51 bool usingRGBAToJpegOverride(int32_t imageFormat,
52 int32_t containerFormat) {
53 return containerFormat == HAL_PIXEL_FORMAT_BLOB && imageFormat == HAL_PIXEL_FORMAT_RGBA_8888;
54 }
55
applyFormatOverrides(int32_t imageFormat,int32_t containerFormat)56 int32_t applyFormatOverrides(int32_t imageFormat, int32_t containerFormat) {
57 // Using HAL_PIXEL_FORMAT_RGBA_8888 gralloc buffers containing JPEGs to get around SW
58 // write limitations for some platforms (b/17379185).
59 if (usingRGBAToJpegOverride(imageFormat, containerFormat)) {
60 return HAL_PIXEL_FORMAT_BLOB;
61 }
62 return containerFormat;
63 }
64
isFormatOpaque(int format)65 bool isFormatOpaque(int format) {
66 // This is the only opaque format exposed in the ImageFormat public API.
67 // Note that we do support CPU access for HAL_PIXEL_FORMAT_RAW_OPAQUE
68 // (ImageFormat#RAW_PRIVATE) so it doesn't count as opaque here.
69 return format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
70 }
71
isPossiblyYUV(PixelFormat format)72 bool isPossiblyYUV(PixelFormat format) {
73 switch (static_cast<int>(format)) {
74 case HAL_PIXEL_FORMAT_RGBA_8888:
75 case HAL_PIXEL_FORMAT_RGBX_8888:
76 case HAL_PIXEL_FORMAT_RGB_888:
77 case HAL_PIXEL_FORMAT_RGB_565:
78 case HAL_PIXEL_FORMAT_BGRA_8888:
79 case HAL_PIXEL_FORMAT_Y8:
80 case HAL_PIXEL_FORMAT_Y16:
81 case HAL_PIXEL_FORMAT_RAW16:
82 case HAL_PIXEL_FORMAT_RAW12:
83 case HAL_PIXEL_FORMAT_RAW10:
84 case HAL_PIXEL_FORMAT_RAW_OPAQUE:
85 case HAL_PIXEL_FORMAT_BLOB:
86 case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
87 case HAL_PIXEL_FORMAT_YCBCR_P010:
88 case static_cast<int>(AidlPixelFormat::YCBCR_P210):
89 return false;
90
91 case HAL_PIXEL_FORMAT_YV12:
92 case HAL_PIXEL_FORMAT_YCbCr_420_888:
93 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
94 default:
95 return true;
96 }
97 }
98
isPossibly10BitYUV(PixelFormat format)99 bool isPossibly10BitYUV(PixelFormat format) {
100 switch (static_cast<int>(format)) {
101 case HAL_PIXEL_FORMAT_RGBA_8888:
102 case HAL_PIXEL_FORMAT_RGBX_8888:
103 case HAL_PIXEL_FORMAT_RGB_888:
104 case HAL_PIXEL_FORMAT_RGB_565:
105 case HAL_PIXEL_FORMAT_BGRA_8888:
106 case HAL_PIXEL_FORMAT_Y8:
107 case HAL_PIXEL_FORMAT_Y16:
108 case HAL_PIXEL_FORMAT_RAW16:
109 case HAL_PIXEL_FORMAT_RAW12:
110 case HAL_PIXEL_FORMAT_RAW10:
111 case HAL_PIXEL_FORMAT_RAW_OPAQUE:
112 case HAL_PIXEL_FORMAT_BLOB:
113 case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
114 case HAL_PIXEL_FORMAT_YV12:
115 case HAL_PIXEL_FORMAT_YCbCr_420_888:
116 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
117 return false;
118
119 case HAL_PIXEL_FORMAT_YCBCR_P010:
120 case static_cast<int>(AidlPixelFormat::YCBCR_P210):
121 default:
122 return true;
123 }
124 }
125
Image_getBlobSize(LockedImage * buffer,bool usingRGBAOverride)126 uint32_t Image_getBlobSize(LockedImage* buffer, bool usingRGBAOverride) {
127 ALOGV("%s", __FUNCTION__);
128 LOG_ALWAYS_FATAL_IF(buffer == NULL, "Input buffer is NULL!!!");
129 uint32_t size = 0;
130 uint32_t width = buffer->width;
131 uint8_t* blobBuffer = buffer->data;
132
133 if (usingRGBAOverride) {
134 width = (buffer->width + buffer->stride * (buffer->height - 1)) * 4;
135 }
136
137 // First check for BLOB transport header at the end of the buffer
138 uint8_t* header = blobBuffer + (width - sizeof(struct camera3_jpeg_blob_v2));
139
140 // read camera3_jpeg_blob_v2 from the end of the passed buffer.
141 // requires memcpy because 'header' might not be properly aligned.
142 struct camera3_jpeg_blob_v2 blob;
143 memcpy(&blob, header, sizeof(struct camera3_jpeg_blob_v2));
144
145 if (blob.jpeg_blob_id == CAMERA3_JPEG_BLOB_ID ||
146 blob.jpeg_blob_id == CAMERA3_HEIC_BLOB_ID) {
147 size = blob.jpeg_size;
148 ALOGV("%s: Jpeg/Heic size = %d", __FUNCTION__, size);
149 }
150
151 // failed to find size, default to whole buffer
152 if (size == 0) {
153 /*
154 * This is a problem because not including the JPEG/BLOB header
155 * means that in certain rare situations a regular JPEG/HEIC blob
156 * will be mis-identified as having a header, in which case
157 * we will get a garbage size value.
158 */
159 ALOGW("%s: No JPEG/HEIC header detected, defaulting to size=width=%d",
160 __FUNCTION__, width);
161 size = width;
162 }
163
164 return size;
165 }
166
getLockedImageInfo(LockedImage * buffer,int idx,int32_t containerFormat,uint8_t ** base,uint32_t * size,int * pixelStride,int * rowStride)167 status_t getLockedImageInfo(LockedImage* buffer, int idx,
168 int32_t containerFormat, uint8_t **base, uint32_t *size, int *pixelStride, int *rowStride) {
169 ALOGV("%s", __FUNCTION__);
170 LOG_ALWAYS_FATAL_IF(buffer == NULL, "Input buffer is NULL!!!");
171 LOG_ALWAYS_FATAL_IF(base == NULL, "base is NULL!!!");
172 LOG_ALWAYS_FATAL_IF(size == NULL, "size is NULL!!!");
173 LOG_ALWAYS_FATAL_IF(pixelStride == NULL, "pixelStride is NULL!!!");
174 LOG_ALWAYS_FATAL_IF(rowStride == NULL, "rowStride is NULL!!!");
175 LOG_ALWAYS_FATAL_IF((idx >= IMAGE_MAX_NUM_PLANES) || (idx < 0), "idx (%d) is illegal", idx);
176
177 ALOGV("%s: buffer: %p", __FUNCTION__, buffer);
178
179 uint32_t dataSize, ySize, cSize, cStride;
180 uint32_t pStride = 0, rStride = 0;
181 uint8_t *cb, *cr;
182 uint8_t *pData = NULL;
183 int bytesPerPixel = 0;
184
185 dataSize = ySize = cSize = cStride = 0;
186 int32_t fmt = buffer->flexFormat;
187
188 bool usingRGBAOverride = usingRGBAToJpegOverride(fmt, containerFormat);
189 fmt = applyFormatOverrides(fmt, containerFormat);
190 switch (fmt) {
191 case HAL_PIXEL_FORMAT_YCbCr_420_888:
192 // Width and height should be multiple of 2. Wrong dataSize would be returned otherwise.
193 if (buffer->width % 2 != 0) {
194 ALOGE("YCbCr_420_888: width (%d) should be a multiple of 2", buffer->width);
195 return BAD_VALUE;
196 }
197
198 if (buffer->height % 2 != 0) {
199 ALOGE("YCbCr_420_888: height (%d) should be a multiple of 2", buffer->height);
200 return BAD_VALUE;
201 }
202
203 if (buffer->width <= 0) {
204 ALOGE("YCbCr_420_888: width (%d) should be a > 0", buffer->width);
205 return BAD_VALUE;
206 }
207
208 if (buffer->height <= 0) {
209 ALOGE("YCbCr_420_888: height (%d) should be a > 0", buffer->height);
210 return BAD_VALUE;
211 }
212
213 pData =
214 (idx == 0) ?
215 buffer->data :
216 (idx == 1) ?
217 buffer->dataCb :
218 buffer->dataCr;
219 // only map until last pixel
220 if (idx == 0) {
221 pStride = 1;
222 rStride = buffer->stride;
223 dataSize = buffer->stride * (buffer->height - 1) + buffer->width;
224 } else {
225 pStride = buffer->chromaStep;
226 rStride = buffer->chromaStride;
227 dataSize = buffer->chromaStride * (buffer->height / 2 - 1) +
228 buffer->chromaStep * (buffer->width / 2 - 1) + 1;
229 }
230 break;
231 // NV21
232 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
233 // Width and height should be multiple of 2. Wrong dataSize would be returned otherwise.
234 if (buffer->width % 2 != 0) {
235 ALOGE("YCrCb_420_SP: width (%d) should be a multiple of 2", buffer->width);
236 return BAD_VALUE;
237 }
238
239 if (buffer->height % 2 != 0) {
240 ALOGE("YCrCb_420_SP: height (%d) should be a multiple of 2", buffer->height);
241 return BAD_VALUE;
242 }
243
244 if (buffer->width <= 0) {
245 ALOGE("YCrCb_420_SP: width (%d) should be a > 0", buffer->width);
246 return BAD_VALUE;
247 }
248
249 if (buffer->height <= 0) {
250 ALOGE("YCrCb_420_SP: height (%d) should be a > 0", buffer->height);
251 return BAD_VALUE;
252 }
253
254 cr = buffer->data + (buffer->stride * buffer->height);
255 cb = cr + 1;
256 // only map until last pixel
257 ySize = buffer->width * (buffer->height - 1) + buffer->width;
258 cSize = buffer->width * (buffer->height / 2 - 1) + buffer->width - 1;
259
260 pData =
261 (idx == 0) ?
262 buffer->data :
263 (idx == 1) ?
264 cb:
265 cr;
266
267 dataSize = (idx == 0) ? ySize : cSize;
268 pStride = (idx == 0) ? 1 : 2;
269 rStride = buffer->width;
270 break;
271 case HAL_PIXEL_FORMAT_YV12:
272 // Width and height should be multiple of 2. Wrong dataSize would be returned otherwise.
273 if (buffer->width % 2 != 0) {
274 ALOGE("YV12: width (%d) should be a multiple of 2", buffer->width);
275 return BAD_VALUE;
276 }
277
278 if (buffer->height % 2 != 0) {
279 ALOGE("YV12: height (%d) should be a multiple of 2", buffer->height);
280 return BAD_VALUE;
281 }
282
283 if (buffer->width <= 0) {
284 ALOGE("YV12: width (%d) should be a > 0", buffer->width);
285 return BAD_VALUE;
286 }
287
288 if (buffer->height <= 0) {
289 ALOGE("YV12: height (%d) should be a > 0", buffer->height);
290 return BAD_VALUE;
291 }
292
293 // Y and C stride need to be 16 pixel aligned.
294 LOG_ALWAYS_FATAL_IF(buffer->stride % 16,
295 "Stride is not 16 pixel aligned %d", buffer->stride);
296
297 ySize = buffer->stride * buffer->height;
298 cStride = ALIGN(buffer->stride / 2, 16);
299 cr = buffer->data + ySize;
300 cSize = cStride * buffer->height / 2;
301 cb = cr + cSize;
302
303 pData =
304 (idx == 0) ?
305 buffer->data :
306 (idx == 1) ?
307 cb :
308 cr;
309 dataSize = (idx == 0) ? ySize : cSize;
310 pStride = 1;
311 rStride = (idx == 0) ? buffer->stride : ALIGN(buffer->stride / 2, 16);
312 break;
313 case HAL_PIXEL_FORMAT_YCBCR_P010:
314 if (buffer->height % 2 != 0) {
315 ALOGE("YCBCR_P010: height (%d) should be a multiple of 2", buffer->height);
316 return BAD_VALUE;
317 }
318
319 if (buffer->width <= 0) {
320 ALOGE("YCBCR_P010: width (%d) should be a > 0", buffer->width);
321 return BAD_VALUE;
322 }
323
324 if (buffer->height <= 0) {
325 ALOGE("YCBCR_P010: height (%d) should be a > 0", buffer->height);
326 return BAD_VALUE;
327 }
328
329 if (buffer->dataCb && buffer->dataCr) {
330 pData =
331 (idx == 0) ?
332 buffer->data :
333 (idx == 1) ?
334 buffer->dataCb :
335 buffer->dataCr;
336 // only map until last pixel
337 if (idx == 0) {
338 pStride = 2;
339 rStride = buffer->stride;
340 dataSize = buffer->stride * (buffer->height - 1) + buffer->width * 2;
341 } else {
342 pStride = buffer->chromaStep;
343 rStride = buffer->chromaStride;
344 dataSize = buffer->chromaStride * (buffer->height / 2 - 1) +
345 buffer->chromaStep * (buffer->width / 2);
346 }
347 break;
348 }
349
350 ySize = (buffer->stride * 2) * buffer->height;
351 cSize = ySize / 2;
352 pStride = (idx == 0) ? 2 : 4;
353 cb = buffer->data + ySize;
354 cr = cb + 2;
355
356 pData = (idx == 0) ? buffer->data : (idx == 1) ? cb : cr;
357 dataSize = (idx == 0) ? ySize : cSize;
358 rStride = buffer->stride * 2;
359 break;
360 case static_cast<int>(AidlPixelFormat::YCBCR_P210):
361 if (buffer->height % 2 != 0) {
362 ALOGE("YCBCR_P210: height (%d) should be a multiple of 2", buffer->height);
363 return BAD_VALUE;
364 }
365
366 if (buffer->width <= 0) {
367 ALOGE("YCBCR_P210: width (%d) should be a > 0", buffer->width);
368 return BAD_VALUE;
369 }
370
371 if (buffer->height <= 0) {
372 ALOGE("YCBCR_210: height (%d) should be a > 0", buffer->height);
373 return BAD_VALUE;
374 }
375 if (buffer->dataCb && buffer->dataCr) {
376 pData = (idx == 0) ? buffer->data : (idx == 1) ? buffer->dataCb : buffer->dataCr;
377 // only map until last pixel
378 if (idx == 0) {
379 pStride = 2;
380 rStride = buffer->stride;
381 dataSize = buffer->stride * (buffer->height - 1) + buffer->width * 2;
382 } else {
383 pStride = buffer->chromaStep;
384 rStride = buffer->chromaStride;
385 dataSize = buffer->chromaStride * (buffer->height - 1) +
386 buffer->chromaStep * (buffer->width / 2);
387 }
388 break;
389 }
390
391 ySize = (buffer->stride * 2) * buffer->height;
392 cSize = ySize;
393 pStride = (idx == 0) ? 2 : 4;
394 cb = buffer->data + ySize;
395 cr = cb + 2;
396
397 pData = (idx == 0) ? buffer->data : (idx == 1) ? cb : cr;
398 dataSize = (idx == 0) ? ySize : cSize;
399 rStride = buffer->stride * 2;
400 break;
401 case HAL_PIXEL_FORMAT_Y8:
402 // Single plane, 8bpp.
403 LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
404
405 pData = buffer->data;
406 dataSize = buffer->stride * buffer->height;
407 pStride = 1;
408 rStride = buffer->stride;
409 break;
410 case HAL_PIXEL_FORMAT_Y16:
411 bytesPerPixel = 2;
412 // Single plane, 16bpp, strides are specified in pixels, not in bytes
413 LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
414
415 pData = buffer->data;
416 dataSize = buffer->stride * buffer->height * bytesPerPixel;
417 pStride = bytesPerPixel;
418 rStride = buffer->stride * 2;
419 break;
420 case HAL_PIXEL_FORMAT_BLOB:
421 // Used for JPEG data, height must be 1, width == size, single plane.
422 LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
423 // When RGBA override is being used, buffer height will be equal to width
424 if (usingRGBAOverride) {
425 LOG_ALWAYS_FATAL_IF(buffer->height != buffer->width,
426 "RGBA override BLOB format buffer should have height == width");
427 } else {
428 LOG_ALWAYS_FATAL_IF(buffer->height != 1,
429 "BLOB format buffer should have height value 1");
430 }
431
432
433 pData = buffer->data;
434 dataSize = Image_getBlobSize(buffer, usingRGBAOverride);
435 pStride = 0;
436 rStride = 0;
437 break;
438 case HAL_PIXEL_FORMAT_RAW16:
439 // Single plane 16bpp bayer data.
440 bytesPerPixel = 2;
441 LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
442 pData = buffer->data;
443 dataSize = buffer->stride * buffer->height * bytesPerPixel;
444 pStride = bytesPerPixel;
445 rStride = buffer->stride * 2;
446 break;
447 case HAL_PIXEL_FORMAT_RAW_OPAQUE:
448 // Used for RAW_OPAQUE data, height must be 1, width == size, single plane.
449 LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
450 LOG_ALWAYS_FATAL_IF(buffer->height != 1,
451 "RAW_PRIVATE should has height value one but got %d", buffer->height);
452 pData = buffer->data;
453 dataSize = buffer->width;
454 pStride = 0; // RAW OPAQUE doesn't have pixel stride
455 rStride = 0; // RAW OPAQUE doesn't have row stride
456 break;
457 case HAL_PIXEL_FORMAT_RAW10:
458 // Single plane 10bpp bayer data.
459 LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
460 LOG_ALWAYS_FATAL_IF(buffer->width % 4,
461 "Width is not multiple of 4 %d", buffer->width);
462 LOG_ALWAYS_FATAL_IF(buffer->height % 2,
463 "Height is not even %d", buffer->height);
464 LOG_ALWAYS_FATAL_IF(buffer->stride < (buffer->width * 10 / 8),
465 "stride (%d) should be at least %d",
466 buffer->stride, buffer->width * 10 / 8);
467 pData = buffer->data;
468 dataSize = buffer->stride * buffer->height;
469 pStride = 0;
470 rStride = buffer->stride;
471 break;
472 case HAL_PIXEL_FORMAT_RAW12:
473 // Single plane 10bpp bayer data.
474 LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
475 LOG_ALWAYS_FATAL_IF(buffer->width % 4,
476 "Width is not multiple of 4 %d", buffer->width);
477 LOG_ALWAYS_FATAL_IF(buffer->height % 2,
478 "Height is not even %d", buffer->height);
479 LOG_ALWAYS_FATAL_IF(buffer->stride < (buffer->width * 12 / 8),
480 "stride (%d) should be at least %d",
481 buffer->stride, buffer->width * 12 / 8);
482 pData = buffer->data;
483 dataSize = buffer->stride * buffer->height;
484 pStride = 0;
485 rStride = buffer->stride;
486 break;
487 case HAL_PIXEL_FORMAT_RGBA_8888:
488 case HAL_PIXEL_FORMAT_RGBX_8888:
489 // Single plane, 32bpp.
490 bytesPerPixel = 4;
491 LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
492 pData = buffer->data;
493 dataSize = buffer->stride * buffer->height * bytesPerPixel;
494 pStride = bytesPerPixel;
495 rStride = buffer->stride * 4;
496 break;
497 case HAL_PIXEL_FORMAT_RGB_565:
498 // Single plane, 16bpp.
499 bytesPerPixel = 2;
500 LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
501 pData = buffer->data;
502 dataSize = buffer->stride * buffer->height * bytesPerPixel;
503 pStride = bytesPerPixel;
504 rStride = buffer->stride * 2;
505 break;
506 case HAL_PIXEL_FORMAT_RGB_888:
507 // Single plane, 24bpp.
508 bytesPerPixel = 3;
509 LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
510 pData = buffer->data;
511 dataSize = buffer->stride * buffer->height * bytesPerPixel;
512 pStride = bytesPerPixel;
513 rStride = buffer->stride * 3;
514 break;
515 default:
516 ALOGV("%s: unrecognized format 0x%x", __FUNCTION__, fmt);
517 return BAD_VALUE;
518 }
519
520 *base = pData;
521 *size = dataSize;
522 *pixelStride = pStride;
523 *rowStride = rStride;
524
525 return OK;
526 }
527
528 #ifdef __ANDROID__
extractP010Gralloc4PlaneLayout(sp<GraphicBuffer> buffer,void * pData,int format,LockedImage * outputImage)529 static status_t extractP010Gralloc4PlaneLayout(
530 sp<GraphicBuffer> buffer, void *pData, int format, LockedImage *outputImage) {
531 using aidl::android::hardware::graphics::common::PlaneLayoutComponent;
532 using aidl::android::hardware::graphics::common::PlaneLayoutComponentType;
533
534 GraphicBufferMapper& mapper = GraphicBufferMapper::get();
535 std::vector<ui::PlaneLayout> planeLayouts;
536 status_t res = mapper.getPlaneLayouts(buffer->handle, &planeLayouts);
537 if (res != OK) {
538 return res;
539 }
540 constexpr int64_t Y_PLANE_COMPONENTS = int64_t(PlaneLayoutComponentType::Y);
541 constexpr int64_t CBCR_PLANE_COMPONENTS =
542 int64_t(PlaneLayoutComponentType::CB) | int64_t(PlaneLayoutComponentType::CR);
543 uint8_t *dataY = nullptr;
544 uint8_t *dataCb = nullptr;
545 uint8_t *dataCr = nullptr;
546 uint32_t strideY = 0;
547 uint32_t strideCbCr = 0;
548 for (const ui::PlaneLayout &layout : planeLayouts) {
549 ALOGV("gralloc4 plane: %s", layout.toString().c_str());
550 int64_t components = 0;
551 for (const PlaneLayoutComponent &component : layout.components) {
552 if (component.sizeInBits != 10) {
553 return BAD_VALUE;
554 }
555 components |= component.type.value;
556 }
557 if (components == Y_PLANE_COMPONENTS) {
558 if (layout.sampleIncrementInBits != 16) {
559 return BAD_VALUE;
560 }
561 if (layout.components[0].offsetInBits != 6) {
562 return BAD_VALUE;
563 }
564 dataY = (uint8_t *)pData + layout.offsetInBytes;
565 strideY = layout.strideInBytes;
566 } else if (components == CBCR_PLANE_COMPONENTS) {
567 if (layout.sampleIncrementInBits != 32) {
568 return BAD_VALUE;
569 }
570 for (const PlaneLayoutComponent &component : layout.components) {
571 if (component.type.value == int64_t(PlaneLayoutComponentType::CB)
572 && component.offsetInBits != 6) {
573 return BAD_VALUE;
574 }
575 if (component.type.value == int64_t(PlaneLayoutComponentType::CR)
576 && component.offsetInBits != 22) {
577 return BAD_VALUE;
578 }
579 }
580 dataCb = (uint8_t *)pData + layout.offsetInBytes;
581 dataCr = (uint8_t *)pData + layout.offsetInBytes + 2;
582 strideCbCr = layout.strideInBytes;
583 } else {
584 return BAD_VALUE;
585 }
586 }
587
588 outputImage->data = dataY;
589 outputImage->width = buffer->getWidth();
590 outputImage->height = buffer->getHeight();
591 outputImage->format = format;
592 outputImage->flexFormat = HAL_PIXEL_FORMAT_YCBCR_P010;
593 outputImage->stride = strideY;
594
595 outputImage->dataCb = dataCb;
596 outputImage->dataCr = dataCr;
597 outputImage->chromaStride = strideCbCr;
598 outputImage->chromaStep = 4;
599 return OK;
600 }
601
extractP210Gralloc4PlaneLayout(sp<GraphicBuffer> buffer,void * pData,int format,LockedImage * outputImage)602 static status_t extractP210Gralloc4PlaneLayout(sp<GraphicBuffer> buffer, void *pData, int format,
603 LockedImage *outputImage) {
604 using aidl::android::hardware::graphics::common::PlaneLayoutComponent;
605 using aidl::android::hardware::graphics::common::PlaneLayoutComponentType;
606
607 GraphicBufferMapper &mapper = GraphicBufferMapper::get();
608 std::vector<ui::PlaneLayout> planeLayouts;
609 status_t res = mapper.getPlaneLayouts(buffer->handle, &planeLayouts);
610 if (res != OK) {
611 return res;
612 }
613 constexpr int64_t Y_PLANE_COMPONENTS = int64_t(PlaneLayoutComponentType::Y);
614 constexpr int64_t CBCR_PLANE_COMPONENTS =
615 int64_t(PlaneLayoutComponentType::CB) | int64_t(PlaneLayoutComponentType::CR);
616 uint8_t *dataY = nullptr;
617 uint8_t *dataCb = nullptr;
618 uint8_t *dataCr = nullptr;
619 uint32_t strideY = 0;
620 uint32_t strideCbCr = 0;
621 for (const ui::PlaneLayout &layout : planeLayouts) {
622 ALOGV("gralloc4 plane: %s", layout.toString().c_str());
623 int64_t components = 0;
624 for (const PlaneLayoutComponent &component : layout.components) {
625 if (component.sizeInBits != 10) {
626 return BAD_VALUE;
627 }
628 components |= component.type.value;
629 }
630 if (components == Y_PLANE_COMPONENTS) {
631 if (layout.sampleIncrementInBits != 16) {
632 return BAD_VALUE;
633 }
634 if (layout.components[0].offsetInBits != 6) {
635 return BAD_VALUE;
636 }
637 dataY = (uint8_t *)pData + layout.offsetInBytes;
638 strideY = layout.strideInBytes;
639 } else if (components == CBCR_PLANE_COMPONENTS) {
640 if (layout.sampleIncrementInBits != 32) {
641 return BAD_VALUE;
642 }
643 for (const PlaneLayoutComponent &component : layout.components) {
644 if (component.type.value == int64_t(PlaneLayoutComponentType::CB) &&
645 component.offsetInBits != 6) {
646 return BAD_VALUE;
647 }
648 if (component.type.value == int64_t(PlaneLayoutComponentType::CR) &&
649 component.offsetInBits != 22) {
650 return BAD_VALUE;
651 }
652 }
653 dataCb = (uint8_t *)pData + layout.offsetInBytes;
654 dataCr = (uint8_t *)pData + layout.offsetInBytes + 2;
655 strideCbCr = layout.strideInBytes;
656 } else {
657 return BAD_VALUE;
658 }
659 }
660
661 outputImage->data = dataY;
662 outputImage->width = buffer->getWidth();
663 outputImage->height = buffer->getHeight();
664 outputImage->format = format;
665 outputImage->flexFormat =
666 static_cast<int>(AidlPixelFormat::YCBCR_P210);
667 outputImage->stride = strideY;
668
669 outputImage->dataCb = dataCb;
670 outputImage->dataCr = dataCr;
671 outputImage->chromaStride = strideCbCr;
672 outputImage->chromaStep = 4;
673 return OK;
674 }
675 #endif
676
lockImageFromBuffer(sp<GraphicBuffer> buffer,uint32_t inUsage,const Rect & rect,int fenceFd,LockedImage * outputImage)677 status_t lockImageFromBuffer(sp<GraphicBuffer> buffer, uint32_t inUsage,
678 const Rect& rect, int fenceFd, LockedImage* outputImage) {
679 ALOGV("%s: Try to lock the GraphicBuffer", __FUNCTION__);
680
681 if (buffer == nullptr || outputImage == nullptr) {
682 ALOGE("Input BufferItem or output LockedImage is NULL!");
683 return BAD_VALUE;
684 }
685 if (isFormatOpaque(buffer->getPixelFormat())) {
686 ALOGE("Opaque format buffer is not lockable!");
687 return BAD_VALUE;
688 }
689
690 void* pData = NULL;
691 android_ycbcr ycbcr = android_ycbcr();
692 status_t res;
693 int format = buffer->getPixelFormat();
694 int flexFormat = format;
695
696 if (isPossiblyYUV(format)) {
697 res = buffer->lockAsyncYCbCr(inUsage, rect, &ycbcr, fenceFd);
698
699 if (res != OK) {
700 ALOGW("lockAsyncYCbCr failed with error %d (format = 0x%x)", res, format);
701 }
702
703 pData = ycbcr.y;
704 flexFormat = HAL_PIXEL_FORMAT_YCbCr_420_888;
705 }
706
707 // lockAsyncYCbCr for YUV is unsuccessful.
708 if (pData == NULL) {
709 res = buffer->lockAsync(inUsage, rect, &pData, fenceFd);
710 if (res != OK) {
711 ALOGE("Lock buffer failed!");
712 return res;
713 }
714 #ifdef __ANDROID__
715 if (isPossibly10BitYUV(format)) {
716 if (format == HAL_PIXEL_FORMAT_YCBCR_P010 &&
717 OK == extractP010Gralloc4PlaneLayout(buffer, pData, format, outputImage)) {
718 ALOGV("%s: Successfully locked the P010 image", __FUNCTION__);
719 return OK;
720 } else if ((format ==
721 static_cast<int>(AidlPixelFormat::YCBCR_P210)) &&
722 OK == extractP210Gralloc4PlaneLayout(buffer, pData, format, outputImage)) {
723 ALOGV("%s: Successfully locked the P210 image", __FUNCTION__);
724 return OK;
725 }
726 }
727 #endif
728 }
729
730 outputImage->data = reinterpret_cast<uint8_t*>(pData);
731 outputImage->width = buffer->getWidth();
732 outputImage->height = buffer->getHeight();
733 outputImage->format = format;
734 outputImage->flexFormat = flexFormat;
735 outputImage->stride =
736 (ycbcr.y != NULL) ? static_cast<uint32_t>(ycbcr.ystride) : buffer->getStride();
737
738 outputImage->dataCb = reinterpret_cast<uint8_t*>(ycbcr.cb);
739 outputImage->dataCr = reinterpret_cast<uint8_t*>(ycbcr.cr);
740 outputImage->chromaStride = static_cast<uint32_t>(ycbcr.cstride);
741 outputImage->chromaStep = static_cast<uint32_t>(ycbcr.chroma_step);
742 ALOGV("%s: Successfully locked the image from the GraphicBuffer", __FUNCTION__);
743 // Crop, transform, scalingMode, timestamp, and frameNumber should be set by caller,
744 // and cann't be set them here.
745 return OK;
746 }
747
lockImageFromBuffer(BufferItem * bufferItem,uint32_t inUsage,int fenceFd,LockedImage * outputImage)748 status_t lockImageFromBuffer(BufferItem* bufferItem, uint32_t inUsage,
749 int fenceFd, LockedImage* outputImage) {
750 ALOGV("%s: Try to lock the BufferItem", __FUNCTION__);
751 if (bufferItem == nullptr || outputImage == nullptr) {
752 ALOGE("Input BufferItem or output LockedImage is NULL!");
753 return BAD_VALUE;
754 }
755
756 status_t res = lockImageFromBuffer(bufferItem->mGraphicBuffer, inUsage, bufferItem->mCrop,
757 fenceFd, outputImage);
758 if (res != OK) {
759 ALOGE("%s: lock graphic buffer failed", __FUNCTION__);
760 return res;
761 }
762
763 outputImage->crop = bufferItem->mCrop;
764 outputImage->transform = bufferItem->mTransform;
765 outputImage->scalingMode = bufferItem->mScalingMode;
766 outputImage->timestamp = bufferItem->mTimestamp;
767 outputImage->dataSpace = bufferItem->mDataSpace;
768 outputImage->frameNumber = bufferItem->mFrameNumber;
769 ALOGV("%s: Successfully locked the image from the BufferItem", __FUNCTION__);
770 return OK;
771 }
772
getBufferWidth(BufferItem * buffer)773 int getBufferWidth(BufferItem* buffer) {
774 if (buffer == NULL) return -1;
775
776 if (!buffer->mCrop.isEmpty()) {
777 return buffer->mCrop.getWidth();
778 }
779
780 ALOGV("%s: buffer->mGraphicBuffer: %p", __FUNCTION__, buffer->mGraphicBuffer.get());
781 return buffer->mGraphicBuffer->getWidth();
782 }
783
getBufferHeight(BufferItem * buffer)784 int getBufferHeight(BufferItem* buffer) {
785 if (buffer == NULL) return -1;
786
787 if (!buffer->mCrop.isEmpty()) {
788 return buffer->mCrop.getHeight();
789 }
790
791 ALOGV("%s: buffer->mGraphicBuffer: %p", __FUNCTION__, buffer->mGraphicBuffer.get());
792 return buffer->mGraphicBuffer->getHeight();
793 }
794
795 } // namespace android
796
797