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             return false;
73 
74         case HAL_PIXEL_FORMAT_YV12:
75         case HAL_PIXEL_FORMAT_YCbCr_420_888:
76         case HAL_PIXEL_FORMAT_YCrCb_420_SP:
77         default:
78             return true;
79     }
80 }
81 
Image_getBlobSize(LockedImage * buffer,bool usingRGBAOverride)82 uint32_t Image_getBlobSize(LockedImage* buffer, bool usingRGBAOverride) {
83     ALOGV("%s", __FUNCTION__);
84     LOG_ALWAYS_FATAL_IF(buffer == NULL, "Input buffer is NULL!!!");
85     uint32_t size = 0;
86     uint32_t width = buffer->width;
87     uint8_t* blobBuffer = buffer->data;
88 
89     if (usingRGBAOverride) {
90         width = (buffer->width + buffer->stride * (buffer->height - 1)) * 4;
91     }
92 
93     // First check for BLOB transport header at the end of the buffer
94     uint8_t* header = blobBuffer + (width - sizeof(struct camera3_jpeg_blob));
95     struct camera3_jpeg_blob *blob = (struct camera3_jpeg_blob*)(header);
96     if (blob->jpeg_blob_id == CAMERA3_JPEG_BLOB_ID ||
97             blob->jpeg_blob_id == CAMERA3_HEIC_BLOB_ID) {
98         size = blob->jpeg_size;
99         ALOGV("%s: Jpeg/Heic size = %d", __FUNCTION__, size);
100     }
101 
102     // failed to find size, default to whole buffer
103     if (size == 0) {
104         /*
105          * This is a problem because not including the JPEG/BLOB header
106          * means that in certain rare situations a regular JPEG/HEIC blob
107          * will be mis-identified as having a header, in which case
108          * we will get a garbage size value.
109          */
110         ALOGW("%s: No JPEG/HEIC header detected, defaulting to size=width=%d",
111                 __FUNCTION__, width);
112         size = width;
113     }
114 
115     return size;
116 }
117 
getLockedImageInfo(LockedImage * buffer,int idx,int32_t containerFormat,uint8_t ** base,uint32_t * size,int * pixelStride,int * rowStride)118 status_t getLockedImageInfo(LockedImage* buffer, int idx,
119         int32_t containerFormat, uint8_t **base, uint32_t *size, int *pixelStride, int *rowStride) {
120     ALOGV("%s", __FUNCTION__);
121     LOG_ALWAYS_FATAL_IF(buffer == NULL, "Input buffer is NULL!!!");
122     LOG_ALWAYS_FATAL_IF(base == NULL, "base is NULL!!!");
123     LOG_ALWAYS_FATAL_IF(size == NULL, "size is NULL!!!");
124     LOG_ALWAYS_FATAL_IF(pixelStride == NULL, "pixelStride is NULL!!!");
125     LOG_ALWAYS_FATAL_IF(rowStride == NULL, "rowStride is NULL!!!");
126     LOG_ALWAYS_FATAL_IF((idx >= IMAGE_MAX_NUM_PLANES) || (idx < 0), "idx (%d) is illegal", idx);
127 
128     ALOGV("%s: buffer: %p", __FUNCTION__, buffer);
129 
130     uint32_t dataSize, ySize, cSize, cStride;
131     uint32_t pStride = 0, rStride = 0;
132     uint8_t *cb, *cr;
133     uint8_t *pData = NULL;
134     int bytesPerPixel = 0;
135 
136     dataSize = ySize = cSize = cStride = 0;
137     int32_t fmt = buffer->flexFormat;
138 
139     bool usingRGBAOverride = usingRGBAToJpegOverride(fmt, containerFormat);
140     fmt = applyFormatOverrides(fmt, containerFormat);
141     switch (fmt) {
142         case HAL_PIXEL_FORMAT_YCbCr_420_888:
143             pData =
144                 (idx == 0) ?
145                     buffer->data :
146                 (idx == 1) ?
147                     buffer->dataCb :
148                 buffer->dataCr;
149             // only map until last pixel
150             if (idx == 0) {
151                 pStride = 1;
152                 rStride = buffer->stride;
153                 dataSize = buffer->stride * (buffer->height - 1) + buffer->width;
154             } else {
155                 pStride = buffer->chromaStep;
156                 rStride = buffer->chromaStride;
157                 dataSize = buffer->chromaStride * (buffer->height / 2 - 1) +
158                         buffer->chromaStep * (buffer->width / 2 - 1) + 1;
159             }
160             break;
161         // NV21
162         case HAL_PIXEL_FORMAT_YCrCb_420_SP:
163             cr = buffer->data + (buffer->stride * buffer->height);
164             cb = cr + 1;
165             // only map until last pixel
166             ySize = buffer->width * (buffer->height - 1) + buffer->width;
167             cSize = buffer->width * (buffer->height / 2 - 1) + buffer->width - 1;
168 
169             pData =
170                 (idx == 0) ?
171                     buffer->data :
172                 (idx == 1) ?
173                     cb:
174                 cr;
175 
176             dataSize = (idx == 0) ? ySize : cSize;
177             pStride = (idx == 0) ? 1 : 2;
178             rStride = buffer->width;
179             break;
180         case HAL_PIXEL_FORMAT_YV12:
181             // Y and C stride need to be 16 pixel aligned.
182             LOG_ALWAYS_FATAL_IF(buffer->stride % 16,
183                                 "Stride is not 16 pixel aligned %d", buffer->stride);
184 
185             ySize = buffer->stride * buffer->height;
186             cStride = ALIGN(buffer->stride / 2, 16);
187             cr = buffer->data + ySize;
188             cSize = cStride * buffer->height / 2;
189             cb = cr + cSize;
190 
191             pData =
192                 (idx == 0) ?
193                     buffer->data :
194                 (idx == 1) ?
195                     cb :
196                 cr;
197             dataSize = (idx == 0) ? ySize : cSize;
198             pStride = 1;
199             rStride = (idx == 0) ? buffer->stride : ALIGN(buffer->stride / 2, 16);
200             break;
201         case HAL_PIXEL_FORMAT_Y8:
202             // Single plane, 8bpp.
203             LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
204 
205             pData = buffer->data;
206             dataSize = buffer->stride * buffer->height;
207             pStride = 1;
208             rStride = buffer->stride;
209             break;
210         case HAL_PIXEL_FORMAT_Y16:
211             bytesPerPixel = 2;
212             // Single plane, 16bpp, strides are specified in pixels, not in bytes
213             LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
214 
215             pData = buffer->data;
216             dataSize = buffer->stride * buffer->height * bytesPerPixel;
217             pStride = bytesPerPixel;
218             rStride = buffer->stride * 2;
219             break;
220         case HAL_PIXEL_FORMAT_BLOB:
221             // Used for JPEG data, height must be 1, width == size, single plane.
222             LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
223             // When RGBA override is being used, buffer height will be equal to width
224             if (usingRGBAOverride) {
225                 LOG_ALWAYS_FATAL_IF(buffer->height != buffer->width,
226                         "RGBA override BLOB format buffer should have height == width");
227             } else {
228                 LOG_ALWAYS_FATAL_IF(buffer->height != 1,
229                         "BLOB format buffer should have height value 1");
230             }
231 
232 
233             pData = buffer->data;
234             dataSize = Image_getBlobSize(buffer, usingRGBAOverride);
235             pStride = 0;
236             rStride = 0;
237             break;
238         case HAL_PIXEL_FORMAT_RAW16:
239             // Single plane 16bpp bayer data.
240             bytesPerPixel = 2;
241             LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
242             pData = buffer->data;
243             dataSize = buffer->stride * buffer->height * bytesPerPixel;
244             pStride = bytesPerPixel;
245             rStride = buffer->stride * 2;
246             break;
247         case HAL_PIXEL_FORMAT_RAW_OPAQUE:
248             // Used for RAW_OPAQUE data, height must be 1, width == size, single plane.
249             LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
250             LOG_ALWAYS_FATAL_IF(buffer->height != 1,
251                     "RAW_PRIVATE should has height value one but got %d", buffer->height);
252             pData = buffer->data;
253             dataSize = buffer->width;
254             pStride = 0; // RAW OPAQUE doesn't have pixel stride
255             rStride = 0; // RAW OPAQUE doesn't have row stride
256             break;
257         case HAL_PIXEL_FORMAT_RAW10:
258             // Single plane 10bpp bayer data.
259             LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
260             LOG_ALWAYS_FATAL_IF(buffer->width % 4,
261                                 "Width is not multiple of 4 %d", buffer->width);
262             LOG_ALWAYS_FATAL_IF(buffer->height % 2,
263                                 "Height is not even %d", buffer->height);
264             LOG_ALWAYS_FATAL_IF(buffer->stride < (buffer->width * 10 / 8),
265                                 "stride (%d) should be at least %d",
266                                 buffer->stride, buffer->width * 10 / 8);
267             pData = buffer->data;
268             dataSize = buffer->stride * buffer->height;
269             pStride = 0;
270             rStride = buffer->stride;
271             break;
272         case HAL_PIXEL_FORMAT_RAW12:
273             // Single plane 10bpp bayer data.
274             LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
275             LOG_ALWAYS_FATAL_IF(buffer->width % 4,
276                                 "Width is not multiple of 4 %d", buffer->width);
277             LOG_ALWAYS_FATAL_IF(buffer->height % 2,
278                                 "Height is not even %d", buffer->height);
279             LOG_ALWAYS_FATAL_IF(buffer->stride < (buffer->width * 12 / 8),
280                                 "stride (%d) should be at least %d",
281                                 buffer->stride, buffer->width * 12 / 8);
282             pData = buffer->data;
283             dataSize = buffer->stride * buffer->height;
284             pStride = 0;
285             rStride = buffer->stride;
286             break;
287         case HAL_PIXEL_FORMAT_RGBA_8888:
288         case HAL_PIXEL_FORMAT_RGBX_8888:
289             // Single plane, 32bpp.
290             bytesPerPixel = 4;
291             LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
292             pData = buffer->data;
293             dataSize = buffer->stride * buffer->height * bytesPerPixel;
294             pStride = bytesPerPixel;
295             rStride = buffer->stride * 4;
296             break;
297         case HAL_PIXEL_FORMAT_RGB_565:
298             // Single plane, 16bpp.
299             bytesPerPixel = 2;
300             LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
301             pData = buffer->data;
302             dataSize = buffer->stride * buffer->height * bytesPerPixel;
303             pStride = bytesPerPixel;
304             rStride = buffer->stride * 2;
305             break;
306         case HAL_PIXEL_FORMAT_RGB_888:
307             // Single plane, 24bpp.
308             bytesPerPixel = 3;
309             LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
310             pData = buffer->data;
311             dataSize = buffer->stride * buffer->height * bytesPerPixel;
312             pStride = bytesPerPixel;
313             rStride = buffer->stride * 3;
314             break;
315         default:
316             return BAD_VALUE;
317     }
318 
319     *base = pData;
320     *size = dataSize;
321     *pixelStride = pStride;
322     *rowStride = rStride;
323 
324     return OK;
325 }
326 
lockImageFromBuffer(sp<GraphicBuffer> buffer,uint32_t inUsage,const Rect & rect,int fenceFd,LockedImage * outputImage)327 status_t lockImageFromBuffer(sp<GraphicBuffer> buffer, uint32_t inUsage,
328         const Rect& rect, int fenceFd, LockedImage* outputImage) {
329     ALOGV("%s: Try to lock the GraphicBuffer", __FUNCTION__);
330 
331     if (buffer == nullptr || outputImage == nullptr) {
332         ALOGE("Input BufferItem or output LockedImage is NULL!");
333         return BAD_VALUE;
334     }
335     if (isFormatOpaque(buffer->getPixelFormat())) {
336         ALOGE("Opaque format buffer is not lockable!");
337         return BAD_VALUE;
338     }
339 
340     void* pData = NULL;
341     android_ycbcr ycbcr = android_ycbcr();
342     status_t res;
343     int format = buffer->getPixelFormat();
344     int flexFormat = format;
345     if (isPossiblyYUV(format)) {
346         res = buffer->lockAsyncYCbCr(inUsage, rect, &ycbcr, fenceFd);
347         pData = ycbcr.y;
348         flexFormat = HAL_PIXEL_FORMAT_YCbCr_420_888;
349     }
350 
351     // lockAsyncYCbCr for YUV is unsuccessful.
352     if (pData == NULL) {
353         res = buffer->lockAsync(inUsage, rect, &pData, fenceFd);
354         if (res != OK) {
355             ALOGE("Lock buffer failed!");
356             return res;
357         }
358     }
359 
360     outputImage->data = reinterpret_cast<uint8_t*>(pData);
361     outputImage->width = buffer->getWidth();
362     outputImage->height = buffer->getHeight();
363     outputImage->format = format;
364     outputImage->flexFormat = flexFormat;
365     outputImage->stride =
366             (ycbcr.y != NULL) ? static_cast<uint32_t>(ycbcr.ystride) : buffer->getStride();
367 
368     outputImage->dataCb = reinterpret_cast<uint8_t*>(ycbcr.cb);
369     outputImage->dataCr = reinterpret_cast<uint8_t*>(ycbcr.cr);
370     outputImage->chromaStride = static_cast<uint32_t>(ycbcr.cstride);
371     outputImage->chromaStep = static_cast<uint32_t>(ycbcr.chroma_step);
372     ALOGV("%s: Successfully locked the image from the GraphicBuffer", __FUNCTION__);
373     // Crop, transform, scalingMode, timestamp, and frameNumber should be set by caller,
374     // and cann't be set them here.
375     return OK;
376 }
377 
lockImageFromBuffer(BufferItem * bufferItem,uint32_t inUsage,int fenceFd,LockedImage * outputImage)378 status_t lockImageFromBuffer(BufferItem* bufferItem, uint32_t inUsage,
379         int fenceFd, LockedImage* outputImage) {
380     ALOGV("%s: Try to lock the BufferItem", __FUNCTION__);
381     if (bufferItem == nullptr || outputImage == nullptr) {
382         ALOGE("Input BufferItem or output LockedImage is NULL!");
383         return BAD_VALUE;
384     }
385 
386     status_t res = lockImageFromBuffer(bufferItem->mGraphicBuffer, inUsage, bufferItem->mCrop,
387             fenceFd, outputImage);
388     if (res != OK) {
389         ALOGE("%s: lock graphic buffer failed", __FUNCTION__);
390         return res;
391     }
392 
393     outputImage->crop        = bufferItem->mCrop;
394     outputImage->transform   = bufferItem->mTransform;
395     outputImage->scalingMode = bufferItem->mScalingMode;
396     outputImage->timestamp   = bufferItem->mTimestamp;
397     outputImage->dataSpace   = bufferItem->mDataSpace;
398     outputImage->frameNumber = bufferItem->mFrameNumber;
399     ALOGV("%s: Successfully locked the image from the BufferItem", __FUNCTION__);
400     return OK;
401 }
402 
getBufferWidth(BufferItem * buffer)403 int getBufferWidth(BufferItem* buffer) {
404     if (buffer == NULL) return -1;
405 
406     if (!buffer->mCrop.isEmpty()) {
407         return buffer->mCrop.getWidth();
408     }
409 
410     ALOGV("%s: buffer->mGraphicBuffer: %p", __FUNCTION__, buffer->mGraphicBuffer.get());
411     return buffer->mGraphicBuffer->getWidth();
412 }
413 
getBufferHeight(BufferItem * buffer)414 int getBufferHeight(BufferItem* buffer) {
415     if (buffer == NULL) return -1;
416 
417     if (!buffer->mCrop.isEmpty()) {
418         return buffer->mCrop.getHeight();
419     }
420 
421     ALOGV("%s: buffer->mGraphicBuffer: %p", __FUNCTION__, buffer->mGraphicBuffer.get());
422     return buffer->mGraphicBuffer->getHeight();
423 }
424 
425 }  // namespace android
426 
427