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