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