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