• 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