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