• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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