1 /* 2 * Copyright (C) 2016 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 #include <inttypes.h> 18 19 //#define LOG_NDEBUG 0 20 #define LOG_TAG "NdkImage" 21 22 #include "NdkImagePriv.h" 23 #include "NdkImageReaderPriv.h" 24 25 #include <android_media_Utils.h> 26 #include <android_runtime/android_hardware_HardwareBuffer.h> 27 #include <utils/Log.h> 28 #include "hardware/camera3.h" 29 30 using namespace android; 31 32 #define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) ) 33 34 AImage::AImage(AImageReader* reader, int32_t format, uint64_t usage, BufferItem* buffer, 35 int64_t timestamp, int32_t width, int32_t height, int32_t numPlanes) : 36 mReader(reader), mFormat(format), mUsage(usage), mBuffer(buffer), mLockedBuffer(nullptr), 37 mTimestamp(timestamp), mWidth(width), mHeight(height), mNumPlanes(numPlanes) { 38 } 39 40 // Can only be called by free() with mLock hold 41 AImage::~AImage() { 42 if (!mIsClosed) { 43 LOG_ALWAYS_FATAL( 44 "Error: AImage %p is deleted before returning buffer to AImageReader!", this); 45 } 46 } 47 48 bool 49 AImage::isClosed() const { 50 Mutex::Autolock _l(mLock); 51 return mIsClosed; 52 } 53 54 void 55 AImage::close(int releaseFenceFd) { 56 Mutex::Autolock _l(mLock); 57 if (mIsClosed) { 58 return; 59 } 60 sp<AImageReader> reader = mReader.promote(); 61 if (reader != nullptr) { 62 reader->releaseImageLocked(this, releaseFenceFd); 63 } else if (mBuffer != nullptr) { 64 LOG_ALWAYS_FATAL("%s: parent AImageReader closed without releasing image %p", 65 __FUNCTION__, this); 66 } 67 68 // Should have been set to nullptr in releaseImageLocked 69 // Set to nullptr here for extra safety only 70 mBuffer = nullptr; 71 mLockedBuffer = nullptr; 72 mIsClosed = true; 73 } 74 75 void 76 AImage::free() { 77 if (!isClosed()) { 78 ALOGE("Cannot free AImage before close!"); 79 return; 80 } 81 Mutex::Autolock _l(mLock); 82 delete this; 83 } 84 85 void 86 AImage::lockReader() const { 87 sp<AImageReader> reader = mReader.promote(); 88 if (reader == nullptr) { 89 // Reader has been closed 90 return; 91 } 92 reader->mLock.lock(); 93 } 94 95 void 96 AImage::unlockReader() const { 97 sp<AImageReader> reader = mReader.promote(); 98 if (reader == nullptr) { 99 // Reader has been closed 100 return; 101 } 102 reader->mLock.unlock(); 103 } 104 105 media_status_t 106 AImage::getWidth(int32_t* width) const { 107 if (width == nullptr) { 108 return AMEDIA_ERROR_INVALID_PARAMETER; 109 } 110 *width = -1; 111 if (isClosed()) { 112 ALOGE("%s: image %p has been closed!", __FUNCTION__, this); 113 return AMEDIA_ERROR_INVALID_OBJECT; 114 } 115 *width = mWidth; 116 return AMEDIA_OK; 117 } 118 119 media_status_t 120 AImage::getHeight(int32_t* height) const { 121 if (height == nullptr) { 122 return AMEDIA_ERROR_INVALID_PARAMETER; 123 } 124 *height = -1; 125 if (isClosed()) { 126 ALOGE("%s: image %p has been closed!", __FUNCTION__, this); 127 return AMEDIA_ERROR_INVALID_OBJECT; 128 } 129 *height = mHeight; 130 return AMEDIA_OK; 131 } 132 133 media_status_t 134 AImage::getFormat(int32_t* format) const { 135 if (format == nullptr) { 136 return AMEDIA_ERROR_INVALID_PARAMETER; 137 } 138 *format = -1; 139 if (isClosed()) { 140 ALOGE("%s: image %p has been closed!", __FUNCTION__, this); 141 return AMEDIA_ERROR_INVALID_OBJECT; 142 } 143 *format = mFormat; 144 return AMEDIA_OK; 145 } 146 147 media_status_t 148 AImage::getNumPlanes(int32_t* numPlanes) const { 149 if (numPlanes == nullptr) { 150 return AMEDIA_ERROR_INVALID_PARAMETER; 151 } 152 *numPlanes = -1; 153 if (isClosed()) { 154 ALOGE("%s: image %p has been closed!", __FUNCTION__, this); 155 return AMEDIA_ERROR_INVALID_OBJECT; 156 } 157 *numPlanes = mNumPlanes; 158 return AMEDIA_OK; 159 } 160 161 media_status_t 162 AImage::getTimestamp(int64_t* timestamp) const { 163 if (timestamp == nullptr) { 164 return AMEDIA_ERROR_INVALID_PARAMETER; 165 } 166 *timestamp = -1; 167 if (isClosed()) { 168 ALOGE("%s: image %p has been closed!", __FUNCTION__, this); 169 return AMEDIA_ERROR_INVALID_OBJECT; 170 } 171 *timestamp = mTimestamp; 172 return AMEDIA_OK; 173 } 174 175 media_status_t AImage::lockImage() { 176 if (mBuffer == nullptr || mBuffer->mGraphicBuffer == nullptr) { 177 LOG_ALWAYS_FATAL("%s: AImage %p has no buffer.", __FUNCTION__, this); 178 return AMEDIA_ERROR_INVALID_OBJECT; 179 } 180 181 if ((mUsage & AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN) == 0) { 182 ALOGE("%s: AImage %p does not have any software read usage bits set, usage=%" PRIu64 "", 183 __FUNCTION__, this, mUsage); 184 return AMEDIA_IMGREADER_CANNOT_LOCK_IMAGE; 185 } 186 187 if (mLockedBuffer != nullptr) { 188 // Return immediately if the image has already been locked. 189 return AMEDIA_OK; 190 } 191 192 auto lockedBuffer = std::make_unique<CpuConsumer::LockedBuffer>(); 193 194 uint64_t grallocUsage = android_hardware_HardwareBuffer_convertToGrallocUsageBits(mUsage); 195 196 status_t ret = 197 lockImageFromBuffer(mBuffer, grallocUsage, mBuffer->mFence->dup(), lockedBuffer.get()); 198 if (ret != OK) { 199 ALOGE("%s: AImage %p failed to lock, error=%d", __FUNCTION__, this, ret); 200 return AMEDIA_IMGREADER_CANNOT_LOCK_IMAGE; 201 } 202 203 ALOGV("%s: Successfully locked the image %p.", __FUNCTION__, this); 204 mLockedBuffer = std::move(lockedBuffer); 205 206 return AMEDIA_OK; 207 } 208 209 media_status_t AImage::unlockImageIfLocked(int* fenceFd) { 210 if (fenceFd == nullptr) { 211 LOG_ALWAYS_FATAL("%s: fenceFd cannot be null.", __FUNCTION__); 212 return AMEDIA_ERROR_INVALID_PARAMETER; 213 } 214 215 if (mBuffer == nullptr || mBuffer->mGraphicBuffer == nullptr) { 216 LOG_ALWAYS_FATAL("%s: AImage %p has no buffer.", __FUNCTION__, this); 217 return AMEDIA_ERROR_INVALID_OBJECT; 218 } 219 220 if (mLockedBuffer == nullptr) { 221 // This image hasn't been locked yet, no need to unlock. 222 *fenceFd = -1; 223 return AMEDIA_OK; 224 } 225 226 // No fence by default. 227 int releaseFenceFd = -1; 228 status_t res = mBuffer->mGraphicBuffer->unlockAsync(&releaseFenceFd); 229 if (res != OK) { 230 ALOGE("%s unlock buffer failed on iamge %p.", __FUNCTION__, this); 231 *fenceFd = -1; 232 return AMEDIA_IMGREADER_CANNOT_UNLOCK_IMAGE; 233 } 234 235 *fenceFd = releaseFenceFd; 236 return AMEDIA_OK; 237 } 238 239 media_status_t 240 AImage::getPlanePixelStride(int planeIdx, /*out*/int32_t* pixelStride) const { 241 if (mLockedBuffer == nullptr) { 242 ALOGE("%s: buffer not locked.", __FUNCTION__); 243 return AMEDIA_IMGREADER_IMAGE_NOT_LOCKED; 244 } 245 246 if (planeIdx < 0 || planeIdx >= mNumPlanes) { 247 ALOGE("Error: planeIdx %d out of bound [0,%d]", 248 planeIdx, mNumPlanes - 1); 249 return AMEDIA_ERROR_INVALID_PARAMETER; 250 } 251 if (pixelStride == nullptr) { 252 return AMEDIA_ERROR_INVALID_PARAMETER; 253 } 254 if (isClosed()) { 255 ALOGE("%s: image %p has been closed!", __FUNCTION__, this); 256 return AMEDIA_ERROR_INVALID_OBJECT; 257 } 258 int32_t fmt = mLockedBuffer->flexFormat; 259 switch (fmt) { 260 case HAL_PIXEL_FORMAT_YCbCr_420_888: 261 *pixelStride = (planeIdx == 0) ? 1 : mLockedBuffer->chromaStep; 262 return AMEDIA_OK; 263 case HAL_PIXEL_FORMAT_YCrCb_420_SP: 264 *pixelStride = (planeIdx == 0) ? 1 : 2; 265 return AMEDIA_OK; 266 case HAL_PIXEL_FORMAT_Y8: 267 *pixelStride = 1; 268 return AMEDIA_OK; 269 case HAL_PIXEL_FORMAT_YV12: 270 *pixelStride = 1; 271 return AMEDIA_OK; 272 case HAL_PIXEL_FORMAT_Y16: 273 case HAL_PIXEL_FORMAT_RAW16: 274 case HAL_PIXEL_FORMAT_RGB_565: 275 // Single plane 16bpp data. 276 *pixelStride = 2; 277 return AMEDIA_OK; 278 case HAL_PIXEL_FORMAT_RGBA_8888: 279 case HAL_PIXEL_FORMAT_RGBX_8888: 280 *pixelStride = 4; 281 return AMEDIA_OK; 282 case HAL_PIXEL_FORMAT_RGB_888: 283 // Single plane, 24bpp. 284 *pixelStride = 3; 285 return AMEDIA_OK; 286 case HAL_PIXEL_FORMAT_BLOB: 287 case HAL_PIXEL_FORMAT_RAW10: 288 case HAL_PIXEL_FORMAT_RAW12: 289 case HAL_PIXEL_FORMAT_RAW_OPAQUE: 290 // Blob is used for JPEG data, RAW10 and RAW12 is used for 10-bit and 12-bit raw data, 291 // those are single plane data without pixel stride defined 292 return AMEDIA_ERROR_UNSUPPORTED; 293 default: 294 ALOGE("Pixel format: 0x%x is unsupported", fmt); 295 return AMEDIA_ERROR_UNSUPPORTED; 296 } 297 } 298 299 media_status_t 300 AImage::getPlaneRowStride(int planeIdx, /*out*/int32_t* rowStride) const { 301 if (mLockedBuffer == nullptr) { 302 ALOGE("%s: buffer not locked.", __FUNCTION__); 303 return AMEDIA_IMGREADER_IMAGE_NOT_LOCKED; 304 } 305 306 if (planeIdx < 0 || planeIdx >= mNumPlanes) { 307 ALOGE("Error: planeIdx %d out of bound [0,%d]", 308 planeIdx, mNumPlanes - 1); 309 return AMEDIA_ERROR_INVALID_PARAMETER; 310 } 311 if (rowStride == nullptr) { 312 return AMEDIA_ERROR_INVALID_PARAMETER; 313 } 314 if (isClosed()) { 315 ALOGE("%s: image %p has been closed!", __FUNCTION__, this); 316 return AMEDIA_ERROR_INVALID_OBJECT; 317 } 318 int32_t fmt = mLockedBuffer->flexFormat; 319 switch (fmt) { 320 case HAL_PIXEL_FORMAT_YCbCr_420_888: 321 *rowStride = (planeIdx == 0) ? mLockedBuffer->stride 322 : mLockedBuffer->chromaStride; 323 return AMEDIA_OK; 324 case HAL_PIXEL_FORMAT_YCrCb_420_SP: 325 *rowStride = mLockedBuffer->width; 326 return AMEDIA_OK; 327 case HAL_PIXEL_FORMAT_YV12: 328 if (mLockedBuffer->stride % 16) { 329 ALOGE("Stride %d is not 16 pixel aligned!", mLockedBuffer->stride); 330 return AMEDIA_ERROR_UNKNOWN; 331 } 332 *rowStride = (planeIdx == 0) ? mLockedBuffer->stride 333 : ALIGN(mLockedBuffer->stride / 2, 16); 334 return AMEDIA_OK; 335 case HAL_PIXEL_FORMAT_RAW10: 336 case HAL_PIXEL_FORMAT_RAW12: 337 // RAW10 and RAW12 are used for 10-bit and 12-bit raw data, they are single plane 338 *rowStride = mLockedBuffer->stride; 339 return AMEDIA_OK; 340 case HAL_PIXEL_FORMAT_Y8: 341 if (mLockedBuffer->stride % 16) { 342 ALOGE("Stride %d is not 16 pixel aligned!", 343 mLockedBuffer->stride); 344 return AMEDIA_ERROR_UNKNOWN; 345 } 346 *rowStride = mLockedBuffer->stride; 347 return AMEDIA_OK; 348 case HAL_PIXEL_FORMAT_Y16: 349 case HAL_PIXEL_FORMAT_RAW16: 350 // In native side, strides are specified in pixels, not in bytes. 351 // Single plane 16bpp bayer data. even width/height, 352 // row stride multiple of 16 pixels (32 bytes) 353 if (mLockedBuffer->stride % 16) { 354 ALOGE("Stride %d is not 16 pixel aligned!", 355 mLockedBuffer->stride); 356 return AMEDIA_ERROR_UNKNOWN; 357 } 358 *rowStride = mLockedBuffer->stride * 2; 359 return AMEDIA_OK; 360 case HAL_PIXEL_FORMAT_RGB_565: 361 *rowStride = mLockedBuffer->stride * 2; 362 return AMEDIA_OK; 363 case HAL_PIXEL_FORMAT_RGBA_8888: 364 case HAL_PIXEL_FORMAT_RGBX_8888: 365 *rowStride = mLockedBuffer->stride * 4; 366 return AMEDIA_OK; 367 case HAL_PIXEL_FORMAT_RGB_888: 368 // Single plane, 24bpp. 369 *rowStride = mLockedBuffer->stride * 3; 370 return AMEDIA_OK; 371 case HAL_PIXEL_FORMAT_BLOB: 372 case HAL_PIXEL_FORMAT_RAW_OPAQUE: 373 // Blob is used for JPEG/Raw opaque data. It is single plane and has 0 row stride and 374 // no row stride defined 375 return AMEDIA_ERROR_UNSUPPORTED; 376 default: 377 ALOGE("%s Pixel format: 0x%x is unsupported", __FUNCTION__, fmt); 378 return AMEDIA_ERROR_UNSUPPORTED; 379 } 380 } 381 382 uint32_t 383 AImage::getJpegSize() const { 384 if (mLockedBuffer == nullptr) { 385 LOG_ALWAYS_FATAL("Error: buffer is null"); 386 } 387 388 uint32_t size = 0; 389 uint32_t width = mLockedBuffer->width; 390 uint8_t* jpegBuffer = mLockedBuffer->data; 391 392 // First check for JPEG transport header at the end of the buffer 393 uint8_t* header = jpegBuffer + (width - sizeof(struct camera3_jpeg_blob)); 394 struct camera3_jpeg_blob* blob = (struct camera3_jpeg_blob*)(header); 395 if (blob->jpeg_blob_id == CAMERA3_JPEG_BLOB_ID) { 396 size = blob->jpeg_size; 397 ALOGV("%s: Jpeg size = %d", __FUNCTION__, size); 398 } 399 400 // failed to find size, default to whole buffer 401 if (size == 0) { 402 /* 403 * This is a problem because not including the JPEG header 404 * means that in certain rare situations a regular JPEG blob 405 * will be misidentified as having a header, in which case 406 * we will get a garbage size value. 407 */ 408 ALOGW("%s: No JPEG header detected, defaulting to size=width=%d", 409 __FUNCTION__, width); 410 size = width; 411 } 412 413 return size; 414 } 415 416 media_status_t 417 AImage::getPlaneData(int planeIdx,/*out*/uint8_t** data, /*out*/int* dataLength) const { 418 if (mLockedBuffer == nullptr) { 419 ALOGE("%s: buffer not locked.", __FUNCTION__); 420 return AMEDIA_IMGREADER_IMAGE_NOT_LOCKED; 421 } 422 423 if (planeIdx < 0 || planeIdx >= mNumPlanes) { 424 ALOGE("Error: planeIdx %d out of bound [0,%d]", 425 planeIdx, mNumPlanes - 1); 426 return AMEDIA_ERROR_INVALID_PARAMETER; 427 } 428 if (data == nullptr || dataLength == nullptr) { 429 return AMEDIA_ERROR_INVALID_PARAMETER; 430 } 431 if (isClosed()) { 432 ALOGE("%s: image %p has been closed!", __FUNCTION__, this); 433 return AMEDIA_ERROR_INVALID_OBJECT; 434 } 435 436 uint32_t dataSize, ySize, cSize, cStride; 437 uint8_t* cb = nullptr; 438 uint8_t* cr = nullptr; 439 uint8_t* pData = nullptr; 440 int bytesPerPixel = 0; 441 int32_t fmt = mLockedBuffer->flexFormat; 442 443 switch (fmt) { 444 case HAL_PIXEL_FORMAT_YCbCr_420_888: 445 pData = (planeIdx == 0) ? mLockedBuffer->data 446 : (planeIdx == 1) ? mLockedBuffer->dataCb 447 : mLockedBuffer->dataCr; 448 // only map until last pixel 449 if (planeIdx == 0) { 450 dataSize = mLockedBuffer->stride * (mLockedBuffer->height - 1) + 451 mLockedBuffer->width; 452 } else { 453 dataSize = 454 mLockedBuffer->chromaStride * 455 (mLockedBuffer->height / 2 - 1) + 456 mLockedBuffer->chromaStep * (mLockedBuffer->width / 2 - 1) + 457 1; 458 } 459 break; 460 // NV21 461 case HAL_PIXEL_FORMAT_YCrCb_420_SP: 462 cr = mLockedBuffer->data + 463 (mLockedBuffer->stride * mLockedBuffer->height); 464 cb = cr + 1; 465 // only map until last pixel 466 ySize = mLockedBuffer->width * (mLockedBuffer->height - 1) + 467 mLockedBuffer->width; 468 cSize = mLockedBuffer->width * (mLockedBuffer->height / 2 - 1) + 469 mLockedBuffer->width - 1; 470 pData = (planeIdx == 0) ? mLockedBuffer->data 471 : (planeIdx == 1) ? cb : cr; 472 dataSize = (planeIdx == 0) ? ySize : cSize; 473 break; 474 case HAL_PIXEL_FORMAT_YV12: 475 // Y and C stride need to be 16 pixel aligned. 476 if (mLockedBuffer->stride % 16) { 477 ALOGE("Stride %d is not 16 pixel aligned!", 478 mLockedBuffer->stride); 479 return AMEDIA_ERROR_UNKNOWN; 480 } 481 482 ySize = mLockedBuffer->stride * mLockedBuffer->height; 483 cStride = ALIGN(mLockedBuffer->stride / 2, 16); 484 cr = mLockedBuffer->data + ySize; 485 cSize = cStride * mLockedBuffer->height / 2; 486 cb = cr + cSize; 487 488 pData = (planeIdx == 0) ? mLockedBuffer->data 489 : (planeIdx == 1) ? cb : cr; 490 dataSize = (planeIdx == 0) ? ySize : cSize; 491 break; 492 case HAL_PIXEL_FORMAT_Y8: 493 // Single plane, 8bpp. 494 495 pData = mLockedBuffer->data; 496 dataSize = mLockedBuffer->stride * mLockedBuffer->height; 497 break; 498 case HAL_PIXEL_FORMAT_Y16: 499 bytesPerPixel = 2; 500 501 pData = mLockedBuffer->data; 502 dataSize = 503 mLockedBuffer->stride * mLockedBuffer->height * bytesPerPixel; 504 break; 505 case HAL_PIXEL_FORMAT_BLOB: 506 // Used for JPEG data, height must be 1, width == size, single plane. 507 if (mLockedBuffer->height != 1) { 508 ALOGE("Jpeg should have height value one but got %d", 509 mLockedBuffer->height); 510 return AMEDIA_ERROR_UNKNOWN; 511 } 512 513 pData = mLockedBuffer->data; 514 dataSize = getJpegSize(); 515 break; 516 case HAL_PIXEL_FORMAT_RAW16: 517 // Single plane 16bpp bayer data. 518 bytesPerPixel = 2; 519 pData = mLockedBuffer->data; 520 dataSize = 521 mLockedBuffer->stride * mLockedBuffer->height * bytesPerPixel; 522 break; 523 case HAL_PIXEL_FORMAT_RAW_OPAQUE: 524 // Used for RAW_OPAQUE data, height must be 1, width == size, single plane. 525 if (mLockedBuffer->height != 1) { 526 ALOGE("RAW_OPAQUE should have height value one but got %d", 527 mLockedBuffer->height); 528 return AMEDIA_ERROR_UNKNOWN; 529 } 530 pData = mLockedBuffer->data; 531 dataSize = mLockedBuffer->width; 532 break; 533 case HAL_PIXEL_FORMAT_RAW10: 534 // Single plane 10bpp bayer data. 535 if (mLockedBuffer->width % 4) { 536 ALOGE("Width is not multiple of 4 %d", mLockedBuffer->width); 537 return AMEDIA_ERROR_UNKNOWN; 538 } 539 if (mLockedBuffer->height % 2) { 540 ALOGE("Height is not multiple of 2 %d", mLockedBuffer->height); 541 return AMEDIA_ERROR_UNKNOWN; 542 } 543 if (mLockedBuffer->stride < (mLockedBuffer->width * 10 / 8)) { 544 ALOGE("stride (%d) should be at least %d", 545 mLockedBuffer->stride, mLockedBuffer->width * 10 / 8); 546 return AMEDIA_ERROR_UNKNOWN; 547 } 548 pData = mLockedBuffer->data; 549 dataSize = mLockedBuffer->stride * mLockedBuffer->height; 550 break; 551 case HAL_PIXEL_FORMAT_RAW12: 552 // Single plane 10bpp bayer data. 553 if (mLockedBuffer->width % 4) { 554 ALOGE("Width is not multiple of 4 %d", mLockedBuffer->width); 555 return AMEDIA_ERROR_UNKNOWN; 556 } 557 if (mLockedBuffer->height % 2) { 558 ALOGE("Height is not multiple of 2 %d", mLockedBuffer->height); 559 return AMEDIA_ERROR_UNKNOWN; 560 } 561 if (mLockedBuffer->stride < (mLockedBuffer->width * 12 / 8)) { 562 ALOGE("stride (%d) should be at least %d", 563 mLockedBuffer->stride, mLockedBuffer->width * 12 / 8); 564 return AMEDIA_ERROR_UNKNOWN; 565 } 566 pData = mLockedBuffer->data; 567 dataSize = mLockedBuffer->stride * mLockedBuffer->height; 568 break; 569 case HAL_PIXEL_FORMAT_RGBA_8888: 570 case HAL_PIXEL_FORMAT_RGBX_8888: 571 // Single plane, 32bpp. 572 bytesPerPixel = 4; 573 pData = mLockedBuffer->data; 574 dataSize = 575 mLockedBuffer->stride * mLockedBuffer->height * bytesPerPixel; 576 break; 577 case HAL_PIXEL_FORMAT_RGB_565: 578 // Single plane, 16bpp. 579 bytesPerPixel = 2; 580 pData = mLockedBuffer->data; 581 dataSize = 582 mLockedBuffer->stride * mLockedBuffer->height * bytesPerPixel; 583 break; 584 case HAL_PIXEL_FORMAT_RGB_888: 585 // Single plane, 24bpp. 586 bytesPerPixel = 3; 587 pData = mLockedBuffer->data; 588 dataSize = mLockedBuffer->stride * mLockedBuffer->height * bytesPerPixel; 589 break; 590 default: 591 ALOGE("Pixel format: 0x%x is unsupported", fmt); 592 return AMEDIA_ERROR_UNSUPPORTED; 593 } 594 595 *data = pData; 596 *dataLength = dataSize; 597 return AMEDIA_OK; 598 } 599 600 media_status_t 601 AImage::getHardwareBuffer(/*out*/AHardwareBuffer** buffer) const { 602 if (mBuffer == nullptr || mBuffer->mGraphicBuffer == nullptr) { 603 ALOGE("%s: AImage %p has no buffer.", __FUNCTION__, this); 604 return AMEDIA_ERROR_INVALID_OBJECT; 605 } 606 607 // TODO(jwcai) Someone from Android graphics team stating this should just be a static_cast. 608 *buffer = reinterpret_cast<AHardwareBuffer*>(mBuffer->mGraphicBuffer.get()); 609 return AMEDIA_OK; 610 } 611 612 EXPORT 613 void AImage_delete(AImage* image) { 614 ALOGV("%s", __FUNCTION__); 615 AImage_deleteAsync(image, -1); 616 return; 617 } 618 619 EXPORT 620 void AImage_deleteAsync(AImage* image, int releaseFenceFd) { 621 ALOGV("%s", __FUNCTION__); 622 if (image != nullptr) { 623 image->lockReader(); 624 image->close(releaseFenceFd); 625 image->unlockReader(); 626 if (!image->isClosed()) { 627 LOG_ALWAYS_FATAL("Image close failed!"); 628 } 629 image->free(); 630 } 631 return; 632 } 633 634 EXPORT 635 media_status_t AImage_getWidth(const AImage* image, /*out*/int32_t* width) { 636 ALOGV("%s", __FUNCTION__); 637 if (image == nullptr || width == nullptr) { 638 ALOGE("%s: bad argument. image %p width %p", 639 __FUNCTION__, image, width); 640 return AMEDIA_ERROR_INVALID_PARAMETER; 641 } 642 return image->getWidth(width); 643 } 644 645 EXPORT 646 media_status_t AImage_getHeight(const AImage* image, /*out*/int32_t* height) { 647 ALOGV("%s", __FUNCTION__); 648 if (image == nullptr || height == nullptr) { 649 ALOGE("%s: bad argument. image %p height %p", 650 __FUNCTION__, image, height); 651 return AMEDIA_ERROR_INVALID_PARAMETER; 652 } 653 return image->getHeight(height); 654 } 655 656 EXPORT 657 media_status_t AImage_getFormat(const AImage* image, /*out*/int32_t* format) { 658 ALOGV("%s", __FUNCTION__); 659 if (image == nullptr || format == nullptr) { 660 ALOGE("%s: bad argument. image %p format %p", 661 __FUNCTION__, image, format); 662 return AMEDIA_ERROR_INVALID_PARAMETER; 663 } 664 return image->getFormat(format); 665 } 666 667 EXPORT 668 media_status_t AImage_getCropRect(const AImage* image, /*out*/AImageCropRect* rect) { 669 ALOGV("%s", __FUNCTION__); 670 if (image == nullptr || rect == nullptr) { 671 ALOGE("%s: bad argument. image %p rect %p", 672 __FUNCTION__, image, rect); 673 return AMEDIA_ERROR_INVALID_PARAMETER; 674 } 675 // For now AImage only supports camera outputs where cropRect is always full window 676 int32_t width = -1; 677 media_status_t ret = image->getWidth(&width); 678 if (ret != AMEDIA_OK) { 679 return ret; 680 } 681 int32_t height = -1; 682 ret = image->getHeight(&height); 683 if (ret != AMEDIA_OK) { 684 return ret; 685 } 686 rect->left = 0; 687 rect->top = 0; 688 rect->right = width; 689 rect->bottom = height; 690 return AMEDIA_OK; 691 } 692 693 EXPORT 694 media_status_t AImage_getTimestamp(const AImage* image, /*out*/int64_t* timestampNs) { 695 ALOGV("%s", __FUNCTION__); 696 if (image == nullptr || timestampNs == nullptr) { 697 ALOGE("%s: bad argument. image %p timestampNs %p", 698 __FUNCTION__, image, timestampNs); 699 return AMEDIA_ERROR_INVALID_PARAMETER; 700 } 701 return image->getTimestamp(timestampNs); 702 } 703 704 EXPORT 705 media_status_t AImage_getNumberOfPlanes(const AImage* image, /*out*/int32_t* numPlanes) { 706 ALOGV("%s", __FUNCTION__); 707 if (image == nullptr || numPlanes == nullptr) { 708 ALOGE("%s: bad argument. image %p numPlanes %p", 709 __FUNCTION__, image, numPlanes); 710 return AMEDIA_ERROR_INVALID_PARAMETER; 711 } 712 return image->getNumPlanes(numPlanes); 713 } 714 715 EXPORT 716 media_status_t AImage_getPlanePixelStride( 717 const AImage* image, int planeIdx, /*out*/int32_t* pixelStride) { 718 ALOGV("%s", __FUNCTION__); 719 if (image == nullptr || pixelStride == nullptr) { 720 ALOGE("%s: bad argument. image %p pixelStride %p", 721 __FUNCTION__, image, pixelStride); 722 return AMEDIA_ERROR_INVALID_PARAMETER; 723 } 724 media_status_t ret = const_cast<AImage*>(image)->lockImage(); 725 if (ret != AMEDIA_OK) { 726 ALOGE("%s: failed to lock buffer for CPU access. image %p, error=%d.", 727 __FUNCTION__, image, ret); 728 return ret; 729 } 730 return image->getPlanePixelStride(planeIdx, pixelStride); 731 } 732 733 EXPORT 734 media_status_t AImage_getPlaneRowStride( 735 const AImage* image, int planeIdx, /*out*/int32_t* rowStride) { 736 ALOGV("%s", __FUNCTION__); 737 if (image == nullptr || rowStride == nullptr) { 738 ALOGE("%s: bad argument. image %p rowStride %p", 739 __FUNCTION__, image, rowStride); 740 return AMEDIA_ERROR_INVALID_PARAMETER; 741 } 742 media_status_t ret = const_cast<AImage*>(image)->lockImage(); 743 if (ret != AMEDIA_OK) { 744 ALOGE("%s: failed to lock buffer for CPU access. image %p, error=%d.", 745 __FUNCTION__, image, ret); 746 return ret; 747 } 748 return image->getPlaneRowStride(planeIdx, rowStride); 749 } 750 751 EXPORT 752 media_status_t AImage_getPlaneData( 753 const AImage* image, int planeIdx, 754 /*out*/uint8_t** data, /*out*/int* dataLength) { 755 ALOGV("%s", __FUNCTION__); 756 if (image == nullptr || data == nullptr || dataLength == nullptr) { 757 ALOGE("%s: bad argument. image %p data %p dataLength %p", 758 __FUNCTION__, image, data, dataLength); 759 return AMEDIA_ERROR_INVALID_PARAMETER; 760 } 761 media_status_t ret = const_cast<AImage*>(image)->lockImage(); 762 if (ret != AMEDIA_OK) { 763 ALOGE("%s: failed to lock buffer for CPU access. image %p, error=%d.", 764 __FUNCTION__, image, ret); 765 return ret; 766 } 767 return image->getPlaneData(planeIdx, data, dataLength); 768 } 769 770 EXPORT 771 media_status_t AImage_getHardwareBuffer( 772 const AImage* image, /*out*/AHardwareBuffer** buffer) { 773 ALOGV("%s", __FUNCTION__); 774 775 if (image == nullptr || buffer == nullptr) { 776 ALOGE("%s: bad argument. image %p buffer %p", __FUNCTION__, image, buffer); 777 return AMEDIA_ERROR_INVALID_PARAMETER; 778 } 779 return image->getHardwareBuffer(buffer); 780 } 781