• 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 <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