blob: b7ad6dcf93540a7e45096e7e7f3e4c26023ddfb8 [file] [log] [blame]
James Dong79f407c2011-05-05 12:50:04 -07001/*
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
Wonsik Kim584cde22022-04-07 16:51:46 -070020#include <aidl/android/hardware/graphics/common/PlaneLayoutComponentType.h>
Wonsik Kim584cde22022-04-07 16:51:46 -070021#include <ui/GraphicBufferMapper.h>
22#include <ui/GraphicTypes.h>
James Dong79f407c2011-05-05 12:50:04 -070023#include <utils/Log.h>
Jayant Chowdhary0644a5f2022-04-22 17:44:59 +000024
James Dong79f407c2011-05-05 12:50:04 -070025#include "android_media_Utils.h"
26
Zhijun He0ab41622016-02-25 16:00:38 -080027#define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) )
28
Shuzhen Wangf655b1c2018-12-28 15:40:36 -080029// Must be in sync with the value in HeicCompositeStream.cpp
30#define CAMERA3_HEIC_BLOB_ID 0x00FE
31
James Dong79f407c2011-05-05 12:50:04 -070032namespace android {
33
Zhijun He0ab41622016-02-25 16:00:38 -080034// -----------Utility functions used by ImageReader/Writer JNI-----------------
35
36enum {
37 IMAGE_MAX_NUM_PLANES = 3,
38};
39
40bool usingRGBAToJpegOverride(int32_t imageFormat,
41 int32_t containerFormat) {
42 return containerFormat == HAL_PIXEL_FORMAT_BLOB && imageFormat == HAL_PIXEL_FORMAT_RGBA_8888;
43}
44
45int32_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
54bool 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
61bool 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:
Emilian Peev62d40542021-11-04 15:22:02 -070071 case HAL_PIXEL_FORMAT_RAW12:
Zhijun He0ab41622016-02-25 16:00:38 -080072 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:
Emilian Peevfd37b042021-01-21 11:38:34 -080076 case HAL_PIXEL_FORMAT_YCBCR_P010:
Zhijun He0ab41622016-02-25 16:00:38 -080077 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
Wonsik Kim584cde22022-04-07 16:51:46 -070087bool 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
Shuzhen Wangf655b1c2018-12-28 15:40:36 -0800113uint32_t Image_getBlobSize(LockedImage* buffer, bool usingRGBAOverride) {
Zhijun He0ab41622016-02-25 16:00:38 -0800114 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;
Shuzhen Wangf655b1c2018-12-28 15:40:36 -0800118 uint8_t* blobBuffer = buffer->data;
Zhijun He0ab41622016-02-25 16:00:38 -0800119
120 if (usingRGBAOverride) {
121 width = (buffer->width + buffer->stride * (buffer->height - 1)) * 4;
122 }
123
Shuzhen Wangf655b1c2018-12-28 15:40:36 -0800124 // First check for BLOB transport header at the end of the buffer
Jayant Chowdhary0644a5f2022-04-22 17:44:59 +0000125 uint8_t* header = blobBuffer + (width - sizeof(struct camera3_jpeg_blob_v2));
126 struct camera3_jpeg_blob_v2 *blob = (struct camera3_jpeg_blob_v2*)(header);
Shuzhen Wangf655b1c2018-12-28 15:40:36 -0800127 if (blob->jpeg_blob_id == CAMERA3_JPEG_BLOB_ID ||
128 blob->jpeg_blob_id == CAMERA3_HEIC_BLOB_ID) {
Zhijun He0ab41622016-02-25 16:00:38 -0800129 size = blob->jpeg_size;
Shuzhen Wangf655b1c2018-12-28 15:40:36 -0800130 ALOGV("%s: Jpeg/Heic size = %d", __FUNCTION__, size);
Zhijun He0ab41622016-02-25 16:00:38 -0800131 }
132
133 // failed to find size, default to whole buffer
134 if (size == 0) {
135 /*
Shuzhen Wangf655b1c2018-12-28 15:40:36 -0800136 * This is a problem because not including the JPEG/BLOB header
137 * means that in certain rare situations a regular JPEG/HEIC blob
Zhijun He0ab41622016-02-25 16:00:38 -0800138 * will be mis-identified as having a header, in which case
139 * we will get a garbage size value.
140 */
Shuzhen Wangf655b1c2018-12-28 15:40:36 -0800141 ALOGW("%s: No JPEG/HEIC header detected, defaulting to size=width=%d",
Zhijun He0ab41622016-02-25 16:00:38 -0800142 __FUNCTION__, width);
143 size = width;
144 }
145
146 return size;
147}
148
149status_t getLockedImageInfo(LockedImage* buffer, int idx,
150 int32_t containerFormat, uint8_t **base, uint32_t *size, int *pixelStride, int *rowStride) {
151 ALOGV("%s", __FUNCTION__);
152 LOG_ALWAYS_FATAL_IF(buffer == NULL, "Input buffer is NULL!!!");
153 LOG_ALWAYS_FATAL_IF(base == NULL, "base is NULL!!!");
154 LOG_ALWAYS_FATAL_IF(size == NULL, "size is NULL!!!");
155 LOG_ALWAYS_FATAL_IF(pixelStride == NULL, "pixelStride is NULL!!!");
156 LOG_ALWAYS_FATAL_IF(rowStride == NULL, "rowStride is NULL!!!");
157 LOG_ALWAYS_FATAL_IF((idx >= IMAGE_MAX_NUM_PLANES) || (idx < 0), "idx (%d) is illegal", idx);
158
159 ALOGV("%s: buffer: %p", __FUNCTION__, buffer);
160
161 uint32_t dataSize, ySize, cSize, cStride;
162 uint32_t pStride = 0, rStride = 0;
163 uint8_t *cb, *cr;
164 uint8_t *pData = NULL;
165 int bytesPerPixel = 0;
166
167 dataSize = ySize = cSize = cStride = 0;
168 int32_t fmt = buffer->flexFormat;
169
170 bool usingRGBAOverride = usingRGBAToJpegOverride(fmt, containerFormat);
171 fmt = applyFormatOverrides(fmt, containerFormat);
172 switch (fmt) {
173 case HAL_PIXEL_FORMAT_YCbCr_420_888:
Clément Julliard2b644212020-09-09 14:15:29 +0000174 // Width and height should be multiple of 2. Wrong dataSize would be returned otherwise.
175 if (buffer->width % 2 != 0) {
176 ALOGE("YCbCr_420_888: width (%d) should be a multiple of 2", buffer->width);
177 return BAD_VALUE;
178 }
179
180 if (buffer->height % 2 != 0) {
181 ALOGE("YCbCr_420_888: height (%d) should be a multiple of 2", buffer->height);
182 return BAD_VALUE;
183 }
184
185 if (buffer->width <= 0) {
186 ALOGE("YCbCr_420_888: width (%d) should be a > 0", buffer->width);
187 return BAD_VALUE;
188 }
189
190 if (buffer->height <= 0) {
191 ALOGE("YCbCr_420_888: height (%d) should be a > 0", buffer->height);
192 return BAD_VALUE;
193 }
194
Zhijun He0ab41622016-02-25 16:00:38 -0800195 pData =
196 (idx == 0) ?
197 buffer->data :
198 (idx == 1) ?
199 buffer->dataCb :
200 buffer->dataCr;
201 // only map until last pixel
202 if (idx == 0) {
203 pStride = 1;
204 rStride = buffer->stride;
205 dataSize = buffer->stride * (buffer->height - 1) + buffer->width;
206 } else {
207 pStride = buffer->chromaStep;
208 rStride = buffer->chromaStride;
209 dataSize = buffer->chromaStride * (buffer->height / 2 - 1) +
210 buffer->chromaStep * (buffer->width / 2 - 1) + 1;
211 }
212 break;
213 // NV21
214 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
Clément Julliard2b644212020-09-09 14:15:29 +0000215 // Width and height should be multiple of 2. Wrong dataSize would be returned otherwise.
216 if (buffer->width % 2 != 0) {
217 ALOGE("YCrCb_420_SP: width (%d) should be a multiple of 2", buffer->width);
218 return BAD_VALUE;
219 }
220
221 if (buffer->height % 2 != 0) {
222 ALOGE("YCrCb_420_SP: height (%d) should be a multiple of 2", buffer->height);
223 return BAD_VALUE;
224 }
225
226 if (buffer->width <= 0) {
227 ALOGE("YCrCb_420_SP: width (%d) should be a > 0", buffer->width);
228 return BAD_VALUE;
229 }
230
231 if (buffer->height <= 0) {
232 ALOGE("YCrCb_420_SP: height (%d) should be a > 0", buffer->height);
233 return BAD_VALUE;
234 }
235
Zhijun He0ab41622016-02-25 16:00:38 -0800236 cr = buffer->data + (buffer->stride * buffer->height);
237 cb = cr + 1;
238 // only map until last pixel
239 ySize = buffer->width * (buffer->height - 1) + buffer->width;
240 cSize = buffer->width * (buffer->height / 2 - 1) + buffer->width - 1;
241
242 pData =
243 (idx == 0) ?
244 buffer->data :
245 (idx == 1) ?
246 cb:
247 cr;
248
249 dataSize = (idx == 0) ? ySize : cSize;
250 pStride = (idx == 0) ? 1 : 2;
251 rStride = buffer->width;
252 break;
253 case HAL_PIXEL_FORMAT_YV12:
Clément Julliard2b644212020-09-09 14:15:29 +0000254 // Width and height should be multiple of 2. Wrong dataSize would be returned otherwise.
255 if (buffer->width % 2 != 0) {
256 ALOGE("YV12: width (%d) should be a multiple of 2", buffer->width);
257 return BAD_VALUE;
258 }
259
260 if (buffer->height % 2 != 0) {
261 ALOGE("YV12: height (%d) should be a multiple of 2", buffer->height);
262 return BAD_VALUE;
263 }
264
265 if (buffer->width <= 0) {
266 ALOGE("YV12: width (%d) should be a > 0", buffer->width);
267 return BAD_VALUE;
268 }
269
270 if (buffer->height <= 0) {
271 ALOGE("YV12: height (%d) should be a > 0", buffer->height);
272 return BAD_VALUE;
273 }
274
Zhijun He0ab41622016-02-25 16:00:38 -0800275 // Y and C stride need to be 16 pixel aligned.
276 LOG_ALWAYS_FATAL_IF(buffer->stride % 16,
277 "Stride is not 16 pixel aligned %d", buffer->stride);
278
279 ySize = buffer->stride * buffer->height;
280 cStride = ALIGN(buffer->stride / 2, 16);
281 cr = buffer->data + ySize;
282 cSize = cStride * buffer->height / 2;
283 cb = cr + cSize;
284
285 pData =
286 (idx == 0) ?
287 buffer->data :
288 (idx == 1) ?
289 cb :
290 cr;
291 dataSize = (idx == 0) ? ySize : cSize;
292 pStride = 1;
293 rStride = (idx == 0) ? buffer->stride : ALIGN(buffer->stride / 2, 16);
294 break;
Emilian Peevfd37b042021-01-21 11:38:34 -0800295 case HAL_PIXEL_FORMAT_YCBCR_P010:
296 if (buffer->height % 2 != 0) {
297 ALOGE("YCBCR_P010: height (%d) should be a multiple of 2", buffer->height);
298 return BAD_VALUE;
299 }
300
301 if (buffer->width <= 0) {
302 ALOGE("YCBCR_P010: width (%d) should be a > 0", buffer->width);
303 return BAD_VALUE;
304 }
305
306 if (buffer->height <= 0) {
307 ALOGE("YCBCR_P010: height (%d) should be a > 0", buffer->height);
308 return BAD_VALUE;
309 }
310
Wonsik Kim584cde22022-04-07 16:51:46 -0700311 if (buffer->dataCb && buffer->dataCr) {
312 pData =
313 (idx == 0) ?
314 buffer->data :
315 (idx == 1) ?
316 buffer->dataCb :
317 buffer->dataCr;
318 // only map until last pixel
319 if (idx == 0) {
320 pStride = 2;
321 rStride = buffer->stride;
322 dataSize = buffer->stride * (buffer->height - 1) + buffer->width * 2;
323 } else {
324 pStride = buffer->chromaStep;
325 rStride = buffer->chromaStride;
326 dataSize = buffer->chromaStride * (buffer->height / 2 - 1) +
327 buffer->chromaStep * (buffer->width / 2);
328 }
329 break;
330 }
331
Emilian Peevfd37b042021-01-21 11:38:34 -0800332 ySize = (buffer->stride * 2) * buffer->height;
333 cSize = ySize / 2;
334 pStride = (idx == 0) ? 2 : 4;
335 cb = buffer->data + ySize;
336 cr = cb + 2;
337
338 pData = (idx == 0) ? buffer->data : (idx == 1) ? cb : cr;
339 dataSize = (idx == 0) ? ySize : cSize;
340 rStride = buffer->stride * 2;
341 break;
Zhijun He0ab41622016-02-25 16:00:38 -0800342 case HAL_PIXEL_FORMAT_Y8:
343 // Single plane, 8bpp.
344 LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
345
346 pData = buffer->data;
347 dataSize = buffer->stride * buffer->height;
348 pStride = 1;
349 rStride = buffer->stride;
350 break;
351 case HAL_PIXEL_FORMAT_Y16:
352 bytesPerPixel = 2;
353 // Single plane, 16bpp, strides are specified in pixels, not in bytes
354 LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
355
356 pData = buffer->data;
357 dataSize = buffer->stride * buffer->height * bytesPerPixel;
358 pStride = bytesPerPixel;
359 rStride = buffer->stride * 2;
360 break;
361 case HAL_PIXEL_FORMAT_BLOB:
362 // Used for JPEG data, height must be 1, width == size, single plane.
363 LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
Yin-Chia Yeh7b790902016-03-14 16:17:38 -0700364 // When RGBA override is being used, buffer height will be equal to width
365 if (usingRGBAOverride) {
366 LOG_ALWAYS_FATAL_IF(buffer->height != buffer->width,
367 "RGBA override BLOB format buffer should have height == width");
368 } else {
369 LOG_ALWAYS_FATAL_IF(buffer->height != 1,
370 "BLOB format buffer should have height value 1");
371 }
372
Zhijun He0ab41622016-02-25 16:00:38 -0800373
374 pData = buffer->data;
Shuzhen Wangf655b1c2018-12-28 15:40:36 -0800375 dataSize = Image_getBlobSize(buffer, usingRGBAOverride);
Zhijun He0ab41622016-02-25 16:00:38 -0800376 pStride = 0;
377 rStride = 0;
378 break;
379 case HAL_PIXEL_FORMAT_RAW16:
380 // Single plane 16bpp bayer data.
381 bytesPerPixel = 2;
382 LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
383 pData = buffer->data;
384 dataSize = buffer->stride * buffer->height * bytesPerPixel;
385 pStride = bytesPerPixel;
386 rStride = buffer->stride * 2;
387 break;
388 case HAL_PIXEL_FORMAT_RAW_OPAQUE:
389 // Used for RAW_OPAQUE data, height must be 1, width == size, single plane.
390 LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
391 LOG_ALWAYS_FATAL_IF(buffer->height != 1,
392 "RAW_PRIVATE should has height value one but got %d", buffer->height);
393 pData = buffer->data;
394 dataSize = buffer->width;
395 pStride = 0; // RAW OPAQUE doesn't have pixel stride
396 rStride = 0; // RAW OPAQUE doesn't have row stride
397 break;
398 case HAL_PIXEL_FORMAT_RAW10:
399 // Single plane 10bpp bayer data.
400 LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
401 LOG_ALWAYS_FATAL_IF(buffer->width % 4,
402 "Width is not multiple of 4 %d", buffer->width);
403 LOG_ALWAYS_FATAL_IF(buffer->height % 2,
404 "Height is not even %d", buffer->height);
405 LOG_ALWAYS_FATAL_IF(buffer->stride < (buffer->width * 10 / 8),
406 "stride (%d) should be at least %d",
407 buffer->stride, buffer->width * 10 / 8);
408 pData = buffer->data;
409 dataSize = buffer->stride * buffer->height;
410 pStride = 0;
411 rStride = buffer->stride;
412 break;
413 case HAL_PIXEL_FORMAT_RAW12:
414 // Single plane 10bpp bayer data.
415 LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
416 LOG_ALWAYS_FATAL_IF(buffer->width % 4,
417 "Width is not multiple of 4 %d", buffer->width);
418 LOG_ALWAYS_FATAL_IF(buffer->height % 2,
419 "Height is not even %d", buffer->height);
420 LOG_ALWAYS_FATAL_IF(buffer->stride < (buffer->width * 12 / 8),
421 "stride (%d) should be at least %d",
422 buffer->stride, buffer->width * 12 / 8);
423 pData = buffer->data;
424 dataSize = buffer->stride * buffer->height;
425 pStride = 0;
426 rStride = buffer->stride;
427 break;
428 case HAL_PIXEL_FORMAT_RGBA_8888:
429 case HAL_PIXEL_FORMAT_RGBX_8888:
430 // Single plane, 32bpp.
431 bytesPerPixel = 4;
432 LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
433 pData = buffer->data;
434 dataSize = buffer->stride * buffer->height * bytesPerPixel;
435 pStride = bytesPerPixel;
436 rStride = buffer->stride * 4;
437 break;
438 case HAL_PIXEL_FORMAT_RGB_565:
439 // Single plane, 16bpp.
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_RGB_888:
448 // Single plane, 24bpp.
449 bytesPerPixel = 3;
450 LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
451 pData = buffer->data;
452 dataSize = buffer->stride * buffer->height * bytesPerPixel;
453 pStride = bytesPerPixel;
454 rStride = buffer->stride * 3;
455 break;
456 default:
Wonsik Kim584cde22022-04-07 16:51:46 -0700457 ALOGV("%s: unrecognized format 0x%x", __FUNCTION__, fmt);
Zhijun He0ab41622016-02-25 16:00:38 -0800458 return BAD_VALUE;
459 }
460
461 *base = pData;
462 *size = dataSize;
463 *pixelStride = pStride;
464 *rowStride = rStride;
465
466 return OK;
467}
468
Wonsik Kim584cde22022-04-07 16:51:46 -0700469static status_t extractP010Gralloc4PlaneLayout(
470 sp<GraphicBuffer> buffer, void *pData, int format, LockedImage *outputImage) {
471 using aidl::android::hardware::graphics::common::PlaneLayoutComponent;
472 using aidl::android::hardware::graphics::common::PlaneLayoutComponentType;
473
474 GraphicBufferMapper& mapper = GraphicBufferMapper::get();
475 std::vector<ui::PlaneLayout> planeLayouts;
476 status_t res = mapper.getPlaneLayouts(buffer->handle, &planeLayouts);
477 if (res != OK) {
478 return res;
479 }
480 constexpr int64_t Y_PLANE_COMPONENTS = int64_t(PlaneLayoutComponentType::Y);
481 constexpr int64_t CBCR_PLANE_COMPONENTS =
482 int64_t(PlaneLayoutComponentType::CB) | int64_t(PlaneLayoutComponentType::CR);
483 uint8_t *dataY = nullptr;
484 uint8_t *dataCb = nullptr;
485 uint8_t *dataCr = nullptr;
486 uint32_t strideY = 0;
487 uint32_t strideCbCr = 0;
488 for (const ui::PlaneLayout &layout : planeLayouts) {
489 ALOGV("gralloc4 plane: %s", layout.toString().c_str());
490 int64_t components = 0;
491 for (const PlaneLayoutComponent &component : layout.components) {
492 if (component.sizeInBits != 10) {
493 return BAD_VALUE;
494 }
495 components |= component.type.value;
496 }
497 if (components == Y_PLANE_COMPONENTS) {
498 if (layout.sampleIncrementInBits != 16) {
499 return BAD_VALUE;
500 }
501 if (layout.components[0].offsetInBits != 6) {
502 return BAD_VALUE;
503 }
504 dataY = (uint8_t *)pData + layout.offsetInBytes;
505 strideY = layout.strideInBytes;
506 } else if (components == CBCR_PLANE_COMPONENTS) {
507 if (layout.sampleIncrementInBits != 32) {
508 return BAD_VALUE;
509 }
510 for (const PlaneLayoutComponent &component : layout.components) {
511 if (component.type.value == int64_t(PlaneLayoutComponentType::CB)
512 && component.offsetInBits != 6) {
513 return BAD_VALUE;
514 }
515 if (component.type.value == int64_t(PlaneLayoutComponentType::CR)
516 && component.offsetInBits != 22) {
517 return BAD_VALUE;
518 }
519 }
520 dataCb = (uint8_t *)pData + layout.offsetInBytes;
521 dataCr = (uint8_t *)pData + layout.offsetInBytes + 2;
522 strideCbCr = layout.strideInBytes;
523 } else {
524 return BAD_VALUE;
525 }
526 }
527
528 outputImage->data = dataY;
529 outputImage->width = buffer->getWidth();
530 outputImage->height = buffer->getHeight();
531 outputImage->format = format;
532 outputImage->flexFormat = HAL_PIXEL_FORMAT_YCBCR_P010;
533 outputImage->stride = strideY;
534
535 outputImage->dataCb = dataCb;
536 outputImage->dataCr = dataCr;
537 outputImage->chromaStride = strideCbCr;
538 outputImage->chromaStep = 4;
539 return OK;
540}
541
Zhijun He0ab41622016-02-25 16:00:38 -0800542status_t lockImageFromBuffer(sp<GraphicBuffer> buffer, uint32_t inUsage,
543 const Rect& rect, int fenceFd, LockedImage* outputImage) {
544 ALOGV("%s: Try to lock the GraphicBuffer", __FUNCTION__);
545
546 if (buffer == nullptr || outputImage == nullptr) {
547 ALOGE("Input BufferItem or output LockedImage is NULL!");
548 return BAD_VALUE;
549 }
550 if (isFormatOpaque(buffer->getPixelFormat())) {
551 ALOGE("Opaque format buffer is not lockable!");
552 return BAD_VALUE;
553 }
554
555 void* pData = NULL;
556 android_ycbcr ycbcr = android_ycbcr();
557 status_t res;
558 int format = buffer->getPixelFormat();
559 int flexFormat = format;
Wonsik Kim584cde22022-04-07 16:51:46 -0700560
Zhijun He0ab41622016-02-25 16:00:38 -0800561 if (isPossiblyYUV(format)) {
562 res = buffer->lockAsyncYCbCr(inUsage, rect, &ycbcr, fenceFd);
Clément Julliard2b644212020-09-09 14:15:29 +0000563
564 if (res != OK) {
Wonsik Kim584cde22022-04-07 16:51:46 -0700565 ALOGW("lockAsyncYCbCr failed with error %d (format = 0x%x)", res, format);
Clément Julliard2b644212020-09-09 14:15:29 +0000566 }
567
Zhijun He0ab41622016-02-25 16:00:38 -0800568 pData = ycbcr.y;
569 flexFormat = HAL_PIXEL_FORMAT_YCbCr_420_888;
570 }
571
572 // lockAsyncYCbCr for YUV is unsuccessful.
573 if (pData == NULL) {
574 res = buffer->lockAsync(inUsage, rect, &pData, fenceFd);
575 if (res != OK) {
576 ALOGE("Lock buffer failed!");
577 return res;
578 }
Wonsik Kim584cde22022-04-07 16:51:46 -0700579 if (isPossibly10BitYUV(format)
580 && OK == extractP010Gralloc4PlaneLayout(buffer, pData, format, outputImage)) {
581 ALOGV("%s: Successfully locked the P010 image", __FUNCTION__);
582 return OK;
583 }
Zhijun He0ab41622016-02-25 16:00:38 -0800584 }
585
586 outputImage->data = reinterpret_cast<uint8_t*>(pData);
587 outputImage->width = buffer->getWidth();
588 outputImage->height = buffer->getHeight();
589 outputImage->format = format;
590 outputImage->flexFormat = flexFormat;
591 outputImage->stride =
592 (ycbcr.y != NULL) ? static_cast<uint32_t>(ycbcr.ystride) : buffer->getStride();
593
594 outputImage->dataCb = reinterpret_cast<uint8_t*>(ycbcr.cb);
595 outputImage->dataCr = reinterpret_cast<uint8_t*>(ycbcr.cr);
596 outputImage->chromaStride = static_cast<uint32_t>(ycbcr.cstride);
597 outputImage->chromaStep = static_cast<uint32_t>(ycbcr.chroma_step);
598 ALOGV("%s: Successfully locked the image from the GraphicBuffer", __FUNCTION__);
599 // Crop, transform, scalingMode, timestamp, and frameNumber should be set by caller,
600 // and cann't be set them here.
601 return OK;
602}
603
604status_t lockImageFromBuffer(BufferItem* bufferItem, uint32_t inUsage,
605 int fenceFd, LockedImage* outputImage) {
606 ALOGV("%s: Try to lock the BufferItem", __FUNCTION__);
607 if (bufferItem == nullptr || outputImage == nullptr) {
608 ALOGE("Input BufferItem or output LockedImage is NULL!");
609 return BAD_VALUE;
610 }
611
612 status_t res = lockImageFromBuffer(bufferItem->mGraphicBuffer, inUsage, bufferItem->mCrop,
613 fenceFd, outputImage);
614 if (res != OK) {
615 ALOGE("%s: lock graphic buffer failed", __FUNCTION__);
616 return res;
617 }
618
619 outputImage->crop = bufferItem->mCrop;
620 outputImage->transform = bufferItem->mTransform;
621 outputImage->scalingMode = bufferItem->mScalingMode;
622 outputImage->timestamp = bufferItem->mTimestamp;
623 outputImage->dataSpace = bufferItem->mDataSpace;
624 outputImage->frameNumber = bufferItem->mFrameNumber;
625 ALOGV("%s: Successfully locked the image from the BufferItem", __FUNCTION__);
626 return OK;
627}
628
629int getBufferWidth(BufferItem* buffer) {
630 if (buffer == NULL) return -1;
631
632 if (!buffer->mCrop.isEmpty()) {
633 return buffer->mCrop.getWidth();
634 }
635
636 ALOGV("%s: buffer->mGraphicBuffer: %p", __FUNCTION__, buffer->mGraphicBuffer.get());
637 return buffer->mGraphicBuffer->getWidth();
638}
639
640int getBufferHeight(BufferItem* buffer) {
641 if (buffer == NULL) return -1;
642
643 if (!buffer->mCrop.isEmpty()) {
644 return buffer->mCrop.getHeight();
645 }
646
647 ALOGV("%s: buffer->mGraphicBuffer: %p", __FUNCTION__, buffer->mGraphicBuffer.get());
648 return buffer->mGraphicBuffer->getHeight();
649}
650
James Dong79f407c2011-05-05 12:50:04 -0700651} // namespace android
652