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 "NdkImageReader" 21 22 #include "NdkImagePriv.h" 23 #include "NdkImageReaderPriv.h" 24 #include <private/media/NdkImage.h> 25 26 #include <cutils/atomic.h> 27 #include <utils/Log.h> 28 #include <android_media_Utils.h> 29 #include <ui/PublicFormat.h> 30 #include <private/android/AHardwareBufferHelpers.h> 31 #include <grallocusage/GrallocUsageConversion.h> 32 #include <gui/bufferqueue/1.0/WGraphicBufferProducer.h> 33 34 using namespace android; 35 36 namespace { 37 // Get an ID that's unique within this process. 38 static int32_t createProcessUniqueId() { 39 static volatile int32_t globalCounter = 0; 40 return android_atomic_inc(&globalCounter); 41 } 42 } 43 44 const char* AImageReader::kCallbackFpKey = "Callback"; 45 const char* AImageReader::kContextKey = "Context"; 46 const char* AImageReader::kGraphicBufferKey = "GraphicBuffer"; 47 48 static constexpr int kWindowHalTokenSizeMax = 256; 49 50 static native_handle_t *convertHalTokenToNativeHandle(const HalToken &halToken); 51 52 bool 53 AImageReader::isSupportedFormatAndUsage(int32_t format, uint64_t usage) { 54 // Check whether usage has either CPU_READ_OFTEN or CPU_READ set. Note that check against 55 // AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN (0x6) is sufficient as it implies 56 // AHARDWAREBUFFER_USAGE_CPU_READ (0x2). 57 bool hasCpuUsage = usage & AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN; 58 switch (format) { 59 case AIMAGE_FORMAT_RGBA_8888: 60 case AIMAGE_FORMAT_RGBX_8888: 61 case AIMAGE_FORMAT_RGB_888: 62 case AIMAGE_FORMAT_RGB_565: 63 case AIMAGE_FORMAT_RGBA_FP16: 64 case AIMAGE_FORMAT_YUV_420_888: 65 case AIMAGE_FORMAT_JPEG: 66 case AIMAGE_FORMAT_RAW16: 67 case AIMAGE_FORMAT_RAW_DEPTH: 68 case AIMAGE_FORMAT_RAW_PRIVATE: 69 case AIMAGE_FORMAT_RAW10: 70 case AIMAGE_FORMAT_RAW12: 71 case AIMAGE_FORMAT_DEPTH16: 72 case AIMAGE_FORMAT_DEPTH_POINT_CLOUD: 73 case AIMAGE_FORMAT_Y8: 74 case AIMAGE_FORMAT_HEIC: 75 case AIMAGE_FORMAT_DEPTH_JPEG: 76 return true; 77 case AIMAGE_FORMAT_PRIVATE: 78 // For private format, cpu usage is prohibited. 79 return !hasCpuUsage; 80 default: 81 return false; 82 } 83 } 84 85 int 86 AImageReader::getNumPlanesForFormat(int32_t format) { 87 switch (format) { 88 case AIMAGE_FORMAT_YUV_420_888: 89 return 3; 90 case AIMAGE_FORMAT_RGBA_8888: 91 case AIMAGE_FORMAT_RGBX_8888: 92 case AIMAGE_FORMAT_RGB_888: 93 case AIMAGE_FORMAT_RGB_565: 94 case AIMAGE_FORMAT_RGBA_FP16: 95 case AIMAGE_FORMAT_JPEG: 96 case AIMAGE_FORMAT_RAW16: 97 case AIMAGE_FORMAT_RAW_DEPTH: 98 case AIMAGE_FORMAT_RAW_PRIVATE: 99 case AIMAGE_FORMAT_RAW10: 100 case AIMAGE_FORMAT_RAW12: 101 case AIMAGE_FORMAT_DEPTH16: 102 case AIMAGE_FORMAT_DEPTH_POINT_CLOUD: 103 case AIMAGE_FORMAT_Y8: 104 case AIMAGE_FORMAT_HEIC: 105 case AIMAGE_FORMAT_DEPTH_JPEG: 106 return 1; 107 case AIMAGE_FORMAT_PRIVATE: 108 return 0; 109 default: 110 return -1; 111 } 112 } 113 114 void 115 AImageReader::FrameListener::onFrameAvailable(const BufferItem& /*item*/) { 116 Mutex::Autolock _l(mLock); 117 sp<AImageReader> reader = mReader.promote(); 118 if (reader == nullptr) { 119 ALOGW("A frame is available after AImageReader closed!"); 120 return; // reader has been closed 121 } 122 if (mListener.onImageAvailable == nullptr) { 123 return; // No callback registered 124 } 125 126 sp<AMessage> msg = new AMessage(AImageReader::kWhatImageAvailable, reader->mHandler); 127 msg->setPointer(AImageReader::kCallbackFpKey, (void *) mListener.onImageAvailable); 128 msg->setPointer(AImageReader::kContextKey, mListener.context); 129 msg->post(); 130 } 131 132 media_status_t 133 AImageReader::FrameListener::setImageListener(AImageReader_ImageListener* listener) { 134 Mutex::Autolock _l(mLock); 135 if (listener == nullptr) { 136 mListener.context = nullptr; 137 mListener.onImageAvailable = nullptr; 138 } else { 139 mListener = *listener; 140 } 141 return AMEDIA_OK; 142 } 143 144 void 145 AImageReader::BufferRemovedListener::onBufferFreed(const wp<GraphicBuffer>& graphicBuffer) { 146 Mutex::Autolock _l(mLock); 147 sp<AImageReader> reader = mReader.promote(); 148 if (reader == nullptr) { 149 ALOGW("A frame is available after AImageReader closed!"); 150 return; // reader has been closed 151 } 152 if (mListener.onBufferRemoved == nullptr) { 153 return; // No callback registered 154 } 155 156 sp<GraphicBuffer> gBuffer = graphicBuffer.promote(); 157 if (gBuffer == nullptr) { 158 ALOGW("A buffer being freed has gone away!"); 159 return; // buffer is already destroyed 160 } 161 162 sp<AMessage> msg = new AMessage(AImageReader::kWhatBufferRemoved, reader->mHandler); 163 msg->setPointer( 164 AImageReader::kCallbackFpKey, (void*) mListener.onBufferRemoved); 165 msg->setPointer(AImageReader::kContextKey, mListener.context); 166 msg->setObject(AImageReader::kGraphicBufferKey, gBuffer); 167 msg->post(); 168 } 169 170 media_status_t 171 AImageReader::BufferRemovedListener::setBufferRemovedListener( 172 AImageReader_BufferRemovedListener* listener) { 173 Mutex::Autolock _l(mLock); 174 if (listener == nullptr) { 175 mListener.context = nullptr; 176 mListener.onBufferRemoved = nullptr; 177 } else { 178 mListener = *listener; 179 } 180 return AMEDIA_OK; 181 } 182 183 media_status_t 184 AImageReader::setImageListenerLocked(AImageReader_ImageListener* listener) { 185 return mFrameListener->setImageListener(listener); 186 } 187 188 media_status_t 189 AImageReader::setImageListener(AImageReader_ImageListener* listener) { 190 Mutex::Autolock _l(mLock); 191 return setImageListenerLocked(listener); 192 } 193 194 media_status_t 195 AImageReader::setBufferRemovedListenerLocked(AImageReader_BufferRemovedListener* listener) { 196 return mBufferRemovedListener->setBufferRemovedListener(listener); 197 } 198 199 media_status_t 200 AImageReader::setBufferRemovedListener(AImageReader_BufferRemovedListener* listener) { 201 Mutex::Autolock _l(mLock); 202 return setBufferRemovedListenerLocked(listener); 203 } 204 205 void AImageReader::CallbackHandler::onMessageReceived( 206 const sp<AMessage> &msg) { 207 switch (msg->what()) { 208 case kWhatBufferRemoved: 209 { 210 AImageReader_BufferRemovedCallback onBufferRemoved; 211 void* context; 212 bool found = msg->findPointer(kCallbackFpKey, (void**) &onBufferRemoved); 213 if (!found || onBufferRemoved == nullptr) { 214 ALOGE("%s: Cannot find onBufferRemoved callback fp!", __FUNCTION__); 215 return; 216 } 217 found = msg->findPointer(kContextKey, &context); 218 if (!found) { 219 ALOGE("%s: Cannot find callback context!", __FUNCTION__); 220 return; 221 } 222 sp<RefBase> bufferToFree; 223 found = msg->findObject(kGraphicBufferKey, &bufferToFree); 224 if (!found || bufferToFree == nullptr) { 225 ALOGE("%s: Cannot find the buffer to free!", __FUNCTION__); 226 return; 227 } 228 229 // TODO(jwcai) Someone from Android graphics team stating this should just be a 230 // static_cast. 231 AHardwareBuffer* outBuffer = reinterpret_cast<AHardwareBuffer*>(bufferToFree.get()); 232 233 // At this point, bufferToFree holds the last reference to the GraphicBuffer owned by 234 // this AImageReader, and the reference will be gone once this function returns. 235 (*onBufferRemoved)(context, mReader, outBuffer); 236 break; 237 } 238 case kWhatImageAvailable: 239 { 240 AImageReader_ImageCallback onImageAvailable; 241 void* context; 242 bool found = msg->findPointer(kCallbackFpKey, (void**) &onImageAvailable); 243 if (!found || onImageAvailable == nullptr) { 244 ALOGE("%s: Cannot find onImageAvailable callback fp!", __FUNCTION__); 245 return; 246 } 247 found = msg->findPointer(kContextKey, &context); 248 if (!found) { 249 ALOGE("%s: Cannot find callback context!", __FUNCTION__); 250 return; 251 } 252 (*onImageAvailable)(context, mReader); 253 break; 254 } 255 default: 256 ALOGE("%s: unknown message type %d", __FUNCTION__, msg->what()); 257 break; 258 } 259 } 260 261 AImageReader::AImageReader(int32_t width, 262 int32_t height, 263 int32_t format, 264 uint64_t usage, 265 int32_t maxImages) 266 : mWidth(width), 267 mHeight(height), 268 mFormat(format), 269 mUsage(usage), 270 mMaxImages(maxImages), 271 mNumPlanes(getNumPlanesForFormat(format)), 272 mFrameListener(new FrameListener(this)), 273 mBufferRemovedListener(new BufferRemovedListener(this)) {} 274 275 media_status_t 276 AImageReader::init() { 277 PublicFormat publicFormat = static_cast<PublicFormat>(mFormat); 278 mHalFormat = mapPublicFormatToHalFormat(publicFormat); 279 mHalDataSpace = mapPublicFormatToHalDataspace(publicFormat); 280 mHalUsage = AHardwareBuffer_convertToGrallocUsageBits(mUsage); 281 282 sp<IGraphicBufferProducer> gbProducer; 283 sp<IGraphicBufferConsumer> gbConsumer; 284 BufferQueue::createBufferQueue(&gbProducer, &gbConsumer); 285 286 String8 consumerName = String8::format("ImageReader-%dx%df%xu%" PRIu64 "m%d-%d-%d", 287 mWidth, mHeight, mFormat, mUsage, mMaxImages, getpid(), 288 createProcessUniqueId()); 289 290 mBufferItemConsumer = 291 new BufferItemConsumer(gbConsumer, mHalUsage, mMaxImages, /*controlledByApp*/ true); 292 if (mBufferItemConsumer == nullptr) { 293 ALOGE("Failed to allocate BufferItemConsumer"); 294 return AMEDIA_ERROR_UNKNOWN; 295 } 296 297 mProducer = gbProducer; 298 mBufferItemConsumer->setName(consumerName); 299 mBufferItemConsumer->setFrameAvailableListener(mFrameListener); 300 mBufferItemConsumer->setBufferFreedListener(mBufferRemovedListener); 301 302 status_t res; 303 res = mBufferItemConsumer->setDefaultBufferSize(mWidth, mHeight); 304 if (res != OK) { 305 ALOGE("Failed to set BufferItemConsumer buffer size"); 306 return AMEDIA_ERROR_UNKNOWN; 307 } 308 res = mBufferItemConsumer->setDefaultBufferFormat(mHalFormat); 309 if (res != OK) { 310 ALOGE("Failed to set BufferItemConsumer buffer format"); 311 return AMEDIA_ERROR_UNKNOWN; 312 } 313 res = mBufferItemConsumer->setDefaultBufferDataSpace(mHalDataSpace); 314 if (res != OK) { 315 ALOGE("Failed to set BufferItemConsumer buffer dataSpace"); 316 return AMEDIA_ERROR_UNKNOWN; 317 } 318 if (mUsage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT) { 319 gbConsumer->setConsumerIsProtected(true); 320 } 321 322 mSurface = new Surface(mProducer, /*controlledByApp*/true); 323 if (mSurface == nullptr) { 324 ALOGE("Failed to create surface"); 325 return AMEDIA_ERROR_UNKNOWN; 326 } 327 mWindow = static_cast<ANativeWindow*>(mSurface.get()); 328 329 for (int i = 0; i < mMaxImages; i++) { 330 BufferItem* buffer = new BufferItem; 331 mBuffers.push_back(buffer); 332 } 333 334 mCbLooper = new ALooper; 335 mCbLooper->setName(consumerName.string()); 336 res = mCbLooper->start( 337 /*runOnCallingThread*/false, 338 /*canCallJava*/ true, 339 PRIORITY_DEFAULT); 340 if (res != OK) { 341 ALOGE("Failed to start the looper"); 342 return AMEDIA_ERROR_UNKNOWN; 343 } 344 mHandler = new CallbackHandler(this); 345 mCbLooper->registerHandler(mHandler); 346 347 return AMEDIA_OK; 348 } 349 350 AImageReader::~AImageReader() { 351 Mutex::Autolock _l(mLock); 352 AImageReader_ImageListener nullListener = {nullptr, nullptr}; 353 setImageListenerLocked(&nullListener); 354 355 AImageReader_BufferRemovedListener nullBufferRemovedListener = {nullptr, nullptr}; 356 setBufferRemovedListenerLocked(&nullBufferRemovedListener); 357 358 if (mCbLooper != nullptr) { 359 mCbLooper->unregisterHandler(mHandler->id()); 360 mCbLooper->stop(); 361 } 362 mCbLooper.clear(); 363 mHandler.clear(); 364 365 // Close all previously acquired images 366 for (auto it = mAcquiredImages.begin(); 367 it != mAcquiredImages.end(); it++) { 368 AImage* image = *it; 369 Mutex::Autolock _l(image->mLock); 370 // Do not alter mAcquiredImages while we are iterating on it 371 releaseImageLocked(image, /*releaseFenceFd*/-1, /*clearCache*/false); 372 } 373 mAcquiredImages.clear(); 374 375 // Delete Buffer Items 376 for (auto it = mBuffers.begin(); 377 it != mBuffers.end(); it++) { 378 delete *it; 379 } 380 381 if (mBufferItemConsumer != nullptr) { 382 mBufferItemConsumer->abandon(); 383 mBufferItemConsumer->setFrameAvailableListener(nullptr); 384 } 385 386 if (mWindowHandle != nullptr) { 387 int size = mWindowHandle->data[0]; 388 hidl_vec<uint8_t> halToken; 389 halToken.setToExternal( 390 reinterpret_cast<uint8_t *>(&mWindowHandle->data[1]), size); 391 deleteHalToken(halToken); 392 native_handle_delete(mWindowHandle); 393 } 394 } 395 396 media_status_t 397 AImageReader::acquireImageLocked(/*out*/AImage** image, /*out*/int* acquireFenceFd) { 398 *image = nullptr; 399 BufferItem* buffer = getBufferItemLocked(); 400 if (buffer == nullptr) { 401 ALOGW("Unable to acquire a lockedBuffer, very likely client tries to lock more than" 402 " maxImages buffers"); 403 return AMEDIA_IMGREADER_MAX_IMAGES_ACQUIRED; 404 } 405 406 // When the output paramter fence is not NULL, we are acquiring the image asynchronously. 407 bool waitForFence = acquireFenceFd == nullptr; 408 status_t res = mBufferItemConsumer->acquireBuffer(buffer, 0, waitForFence); 409 410 if (res != NO_ERROR) { 411 returnBufferItemLocked(buffer); 412 if (res != BufferQueue::NO_BUFFER_AVAILABLE) { 413 if (res == INVALID_OPERATION) { 414 return AMEDIA_IMGREADER_MAX_IMAGES_ACQUIRED; 415 } else { 416 ALOGE("%s: Acquire image failed with some unknown error: %s (%d)", 417 __FUNCTION__, strerror(-res), res); 418 return AMEDIA_ERROR_UNKNOWN; 419 } 420 } 421 return AMEDIA_IMGREADER_NO_BUFFER_AVAILABLE; 422 } 423 424 const int bufferWidth = getBufferWidth(buffer); 425 const int bufferHeight = getBufferHeight(buffer); 426 const int bufferFmt = buffer->mGraphicBuffer->getPixelFormat(); 427 const int bufferUsage = buffer->mGraphicBuffer->getUsage(); 428 429 const int readerWidth = mWidth; 430 const int readerHeight = mHeight; 431 const int readerFmt = mHalFormat; 432 const int readerUsage = mHalUsage; 433 434 // Check if the producer buffer configurations match what AImageReader configured. Add some 435 // extra checks for non-opaque formats. 436 if (!isFormatOpaque(readerFmt)) { 437 // Check if the left-top corner of the crop rect is origin, we currently assume this point 438 // is zero, will revisit this once this assumption turns out problematic. 439 Point lt = buffer->mCrop.leftTop(); 440 if (lt.x != 0 || lt.y != 0) { 441 ALOGE("Crop left top corner [%d, %d] not at origin", lt.x, lt.y); 442 return AMEDIA_ERROR_UNKNOWN; 443 } 444 445 // Check if the producer buffer configurations match what ImageReader configured. 446 ALOGV_IF(readerWidth != bufferWidth || readerHeight != bufferHeight, 447 "%s: Buffer size: %dx%d, doesn't match AImageReader configured size: %dx%d", 448 __FUNCTION__, bufferWidth, bufferHeight, readerWidth, readerHeight); 449 450 // Check if the buffer usage is a super set of reader's usage bits, aka all usage bits that 451 // ImageReader requested has been supported from the producer side. 452 ALOGD_IF((readerUsage | bufferUsage) != bufferUsage, 453 "%s: Producer buffer usage: %x, doesn't cover all usage bits AImageReader " 454 "configured: %x", 455 __FUNCTION__, bufferUsage, readerUsage); 456 457 if (readerFmt != bufferFmt) { 458 if (readerFmt == HAL_PIXEL_FORMAT_YCbCr_420_888 && isPossiblyYUV(bufferFmt)) { 459 // Special casing for when producer switches to a format compatible with flexible 460 // YUV. 461 mHalFormat = bufferFmt; 462 ALOGD("%s: Overriding buffer format YUV_420_888 to 0x%x.", __FUNCTION__, bufferFmt); 463 } else { 464 // Return the buffer to the queue. No need to provide fence, as this buffer wasn't 465 // used anywhere yet. 466 mBufferItemConsumer->releaseBuffer(*buffer); 467 returnBufferItemLocked(buffer); 468 469 ALOGE("%s: Output buffer format: 0x%x, ImageReader configured format: 0x%x", 470 __FUNCTION__, bufferFmt, readerFmt); 471 472 return AMEDIA_ERROR_UNKNOWN; 473 } 474 } 475 } 476 477 if (mHalFormat == HAL_PIXEL_FORMAT_BLOB) { 478 *image = new AImage(this, mFormat, mUsage, buffer, buffer->mTimestamp, 479 readerWidth, readerHeight, mNumPlanes); 480 } else { 481 *image = new AImage(this, mFormat, mUsage, buffer, buffer->mTimestamp, 482 bufferWidth, bufferHeight, mNumPlanes); 483 } 484 mAcquiredImages.push_back(*image); 485 486 // When the output paramter fence is not NULL, we are acquiring the image asynchronously. 487 if (acquireFenceFd != nullptr) { 488 *acquireFenceFd = buffer->mFence->dup(); 489 } 490 491 return AMEDIA_OK; 492 } 493 494 BufferItem* 495 AImageReader::getBufferItemLocked() { 496 if (mBuffers.empty()) { 497 return nullptr; 498 } 499 // Return a BufferItem pointer and remove it from the list 500 auto it = mBuffers.begin(); 501 BufferItem* buffer = *it; 502 mBuffers.erase(it); 503 return buffer; 504 } 505 506 void 507 AImageReader::returnBufferItemLocked(BufferItem* buffer) { 508 mBuffers.push_back(buffer); 509 } 510 511 void 512 AImageReader::releaseImageLocked(AImage* image, int releaseFenceFd, bool clearCache) { 513 BufferItem* buffer = image->mBuffer; 514 if (buffer == nullptr) { 515 // This should not happen, but is not fatal 516 ALOGW("AImage %p has no buffer!", image); 517 return; 518 } 519 520 int unlockFenceFd = -1; 521 media_status_t ret = image->unlockImageIfLocked(&unlockFenceFd); 522 if (ret < 0) { 523 ALOGW("%s: AImage %p is cannot be unlocked.", __FUNCTION__, image); 524 return; 525 } 526 527 sp<Fence> unlockFence = unlockFenceFd > 0 ? new Fence(unlockFenceFd) : Fence::NO_FENCE; 528 sp<Fence> releaseFence = releaseFenceFd > 0 ? new Fence(releaseFenceFd) : Fence::NO_FENCE; 529 sp<Fence> bufferFence = Fence::merge("AImageReader", unlockFence, releaseFence); 530 mBufferItemConsumer->releaseBuffer(*buffer, bufferFence); 531 returnBufferItemLocked(buffer); 532 image->mBuffer = nullptr; 533 image->mLockedBuffer = nullptr; 534 image->mIsClosed = true; 535 536 if (!clearCache) { 537 return; 538 } 539 540 bool found = false; 541 // cleanup acquired image list 542 for (auto it = mAcquiredImages.begin(); 543 it != mAcquiredImages.end(); it++) { 544 AImage* readerCopy = *it; 545 if (readerCopy == image) { 546 found = true; 547 mAcquiredImages.erase(it); 548 break; 549 } 550 } 551 if (!found) { 552 ALOGE("Error: AImage %p is not generated by AImageReader %p", 553 image, this); 554 } 555 } 556 557 media_status_t AImageReader::getWindowNativeHandle(native_handle **handle) { 558 if (mWindowHandle != nullptr) { 559 *handle = mWindowHandle; 560 return AMEDIA_OK; 561 } 562 sp<HGraphicBufferProducer> hgbp = 563 new TWGraphicBufferProducer<HGraphicBufferProducer>(mProducer); 564 HalToken halToken; 565 if (!createHalToken(hgbp, &halToken)) { 566 return AMEDIA_ERROR_UNKNOWN; 567 } 568 mWindowHandle = convertHalTokenToNativeHandle(halToken); 569 if (!mWindowHandle) { 570 return AMEDIA_ERROR_UNKNOWN; 571 } 572 *handle = mWindowHandle; 573 return AMEDIA_OK; 574 } 575 576 int 577 AImageReader::getBufferWidth(BufferItem* buffer) { 578 if (buffer == NULL) return -1; 579 580 if (!buffer->mCrop.isEmpty()) { 581 return buffer->mCrop.getWidth(); 582 } 583 584 return buffer->mGraphicBuffer->getWidth(); 585 } 586 587 int 588 AImageReader::getBufferHeight(BufferItem* buffer) { 589 if (buffer == NULL) return -1; 590 591 if (!buffer->mCrop.isEmpty()) { 592 return buffer->mCrop.getHeight(); 593 } 594 595 return buffer->mGraphicBuffer->getHeight(); 596 } 597 598 media_status_t 599 AImageReader::acquireNextImage(/*out*/AImage** image, /*out*/int* acquireFenceFd) { 600 Mutex::Autolock _l(mLock); 601 return acquireImageLocked(image, acquireFenceFd); 602 } 603 604 media_status_t 605 AImageReader::acquireLatestImage(/*out*/AImage** image, /*out*/int* acquireFenceFd) { 606 if (image == nullptr) { 607 return AMEDIA_ERROR_INVALID_PARAMETER; 608 } 609 Mutex::Autolock _l(mLock); 610 *image = nullptr; 611 AImage* prevImage = nullptr; 612 AImage* nextImage = nullptr; 613 media_status_t ret = acquireImageLocked(&prevImage, acquireFenceFd); 614 if (prevImage == nullptr) { 615 return ret; 616 } 617 for (;;) { 618 ret = acquireImageLocked(&nextImage, acquireFenceFd); 619 if (nextImage == nullptr) { 620 *image = prevImage; 621 return AMEDIA_OK; 622 } 623 624 if (acquireFenceFd == nullptr) { 625 // No need for release fence here since the prevImage is unused and acquireImageLocked 626 // has already waited for acquired fence to be signaled. 627 prevImage->close(); 628 } else { 629 // Use the acquire fence as release fence, so that producer can wait before trying to 630 // refill the buffer. 631 prevImage->close(*acquireFenceFd); 632 } 633 prevImage->free(); 634 prevImage = nextImage; 635 nextImage = nullptr; 636 } 637 } 638 639 static native_handle_t *convertHalTokenToNativeHandle( 640 const HalToken &halToken) { 641 // We attempt to store halToken in the ints of the native_handle_t after its 642 // size. The first int stores the size of the token. We store this in an int 643 // to avoid alignment issues where size_t and int do not have the same 644 // alignment. 645 size_t nhDataByteSize = halToken.size(); 646 if (nhDataByteSize > kWindowHalTokenSizeMax) { 647 // The size of the token isn't reasonable.. 648 return nullptr; 649 } 650 size_t numInts = ceil(nhDataByteSize / sizeof(int)) + 1; 651 652 // We don't check for overflow, whether numInts can fit in an int, since we 653 // expect kWindowHalTokenSizeMax to be a reasonable limit. 654 // create a native_handle_t with 0 numFds and numInts number of ints. 655 native_handle_t *nh = 656 native_handle_create(0, numInts); 657 if (!nh) { 658 return nullptr; 659 } 660 // Store the size of the token in the first int. 661 nh->data[0] = nhDataByteSize; 662 memcpy(&(nh->data[1]), halToken.data(), nhDataByteSize); 663 return nh; 664 } 665 666 EXPORT 667 media_status_t AImageReader_new( 668 int32_t width, int32_t height, int32_t format, int32_t maxImages, 669 /*out*/AImageReader** reader) { 670 ALOGV("%s", __FUNCTION__); 671 return AImageReader_newWithUsage( 672 width, height, format, AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN, maxImages, reader); 673 } 674 675 extern "C" { 676 677 EXPORT 678 media_status_t AImageReader_getWindowNativeHandle( 679 AImageReader *reader, /*out*/native_handle_t **handle) { 680 if (reader == nullptr || handle == nullptr) { 681 return AMEDIA_ERROR_INVALID_PARAMETER; 682 } 683 return reader->getWindowNativeHandle(handle); 684 } 685 686 } //extern "C" 687 688 EXPORT 689 media_status_t AImageReader_newWithUsage( 690 int32_t width, int32_t height, int32_t format, uint64_t usage, 691 int32_t maxImages, /*out*/ AImageReader** reader) { 692 ALOGV("%s", __FUNCTION__); 693 694 if (width < 1 || height < 1) { 695 ALOGE("%s: image dimension must be positive: w:%d h:%d", 696 __FUNCTION__, width, height); 697 return AMEDIA_ERROR_INVALID_PARAMETER; 698 } 699 700 if (maxImages < 1) { 701 ALOGE("%s: max outstanding image count must be at least 1 (%d)", 702 __FUNCTION__, maxImages); 703 return AMEDIA_ERROR_INVALID_PARAMETER; 704 } 705 706 if (maxImages > BufferQueueDefs::NUM_BUFFER_SLOTS) { 707 ALOGE("%s: max outstanding image count (%d) cannot be larget than %d.", 708 __FUNCTION__, maxImages, BufferQueueDefs::NUM_BUFFER_SLOTS); 709 return AMEDIA_ERROR_INVALID_PARAMETER; 710 } 711 712 if (!AImageReader::isSupportedFormatAndUsage(format, usage)) { 713 ALOGE("%s: format %d is not supported with usage 0x%" PRIx64 " by AImageReader", 714 __FUNCTION__, format, usage); 715 return AMEDIA_ERROR_INVALID_PARAMETER; 716 } 717 718 if (reader == nullptr) { 719 ALOGE("%s: reader argument is null", __FUNCTION__); 720 return AMEDIA_ERROR_INVALID_PARAMETER; 721 } 722 723 AImageReader* tmpReader = new AImageReader( 724 width, height, format, usage, maxImages); 725 if (tmpReader == nullptr) { 726 ALOGE("%s: AImageReader allocation failed", __FUNCTION__); 727 return AMEDIA_ERROR_UNKNOWN; 728 } 729 media_status_t ret = tmpReader->init(); 730 if (ret != AMEDIA_OK) { 731 ALOGE("%s: AImageReader initialization failed!", __FUNCTION__); 732 delete tmpReader; 733 return ret; 734 } 735 *reader = tmpReader; 736 (*reader)->incStrong((void*) AImageReader_new); 737 return AMEDIA_OK; 738 } 739 740 EXPORT 741 void AImageReader_delete(AImageReader* reader) { 742 ALOGV("%s", __FUNCTION__); 743 if (reader != nullptr) { 744 reader->decStrong((void*) AImageReader_delete); 745 } 746 return; 747 } 748 749 EXPORT 750 media_status_t AImageReader_getWindow(AImageReader* reader, /*out*/ANativeWindow** window) { 751 ALOGV("%s", __FUNCTION__); 752 if (reader == nullptr || window == nullptr) { 753 ALOGE("%s: invalid argument. reader %p, window %p", 754 __FUNCTION__, reader, window); 755 return AMEDIA_ERROR_INVALID_PARAMETER; 756 } 757 *window = reader->getWindow(); 758 return AMEDIA_OK; 759 } 760 761 EXPORT 762 media_status_t AImageReader_getWidth(const AImageReader* reader, /*out*/int32_t* width) { 763 ALOGV("%s", __FUNCTION__); 764 if (reader == nullptr || width == nullptr) { 765 ALOGE("%s: invalid argument. reader %p, width %p", 766 __FUNCTION__, reader, width); 767 return AMEDIA_ERROR_INVALID_PARAMETER; 768 } 769 *width = reader->getWidth(); 770 return AMEDIA_OK; 771 } 772 773 EXPORT 774 media_status_t AImageReader_getHeight(const AImageReader* reader, /*out*/int32_t* height) { 775 ALOGV("%s", __FUNCTION__); 776 if (reader == nullptr || height == nullptr) { 777 ALOGE("%s: invalid argument. reader %p, height %p", 778 __FUNCTION__, reader, height); 779 return AMEDIA_ERROR_INVALID_PARAMETER; 780 } 781 *height = reader->getHeight(); 782 return AMEDIA_OK; 783 } 784 785 EXPORT 786 media_status_t AImageReader_getFormat(const AImageReader* reader, /*out*/int32_t* format) { 787 ALOGV("%s", __FUNCTION__); 788 if (reader == nullptr || format == nullptr) { 789 ALOGE("%s: invalid argument. reader %p, format %p", 790 __FUNCTION__, reader, format); 791 return AMEDIA_ERROR_INVALID_PARAMETER; 792 } 793 *format = reader->getFormat(); 794 return AMEDIA_OK; 795 } 796 797 EXPORT 798 media_status_t AImageReader_getMaxImages(const AImageReader* reader, /*out*/int32_t* maxImages) { 799 ALOGV("%s", __FUNCTION__); 800 if (reader == nullptr || maxImages == nullptr) { 801 ALOGE("%s: invalid argument. reader %p, maxImages %p", 802 __FUNCTION__, reader, maxImages); 803 return AMEDIA_ERROR_INVALID_PARAMETER; 804 } 805 *maxImages = reader->getMaxImages(); 806 return AMEDIA_OK; 807 } 808 809 EXPORT 810 media_status_t AImageReader_acquireNextImage(AImageReader* reader, /*out*/AImage** image) { 811 ALOGV("%s", __FUNCTION__); 812 return AImageReader_acquireNextImageAsync(reader, image, nullptr); 813 } 814 815 EXPORT 816 media_status_t AImageReader_acquireLatestImage(AImageReader* reader, /*out*/AImage** image) { 817 ALOGV("%s", __FUNCTION__); 818 return AImageReader_acquireLatestImageAsync(reader, image, nullptr); 819 } 820 821 EXPORT 822 media_status_t AImageReader_acquireNextImageAsync( 823 AImageReader* reader, /*out*/AImage** image, /*out*/int* acquireFenceFd) { 824 ALOGV("%s", __FUNCTION__); 825 if (reader == nullptr || image == nullptr) { 826 ALOGE("%s: invalid argument. reader %p, image %p", 827 __FUNCTION__, reader, image); 828 return AMEDIA_ERROR_INVALID_PARAMETER; 829 } 830 return reader->acquireNextImage(image, acquireFenceFd); 831 } 832 833 EXPORT 834 media_status_t AImageReader_acquireLatestImageAsync( 835 AImageReader* reader, /*out*/AImage** image, /*out*/int* acquireFenceFd) { 836 ALOGV("%s", __FUNCTION__); 837 if (reader == nullptr || image == nullptr) { 838 ALOGE("%s: invalid argument. reader %p, image %p", 839 __FUNCTION__, reader, image); 840 return AMEDIA_ERROR_INVALID_PARAMETER; 841 } 842 return reader->acquireLatestImage(image, acquireFenceFd); 843 } 844 845 EXPORT 846 media_status_t AImageReader_setImageListener( 847 AImageReader* reader, AImageReader_ImageListener* listener) { 848 ALOGV("%s", __FUNCTION__); 849 if (reader == nullptr) { 850 ALOGE("%s: invalid argument! reader %p", __FUNCTION__, reader); 851 return AMEDIA_ERROR_INVALID_PARAMETER; 852 } 853 854 reader->setImageListener(listener); 855 return AMEDIA_OK; 856 } 857 858 EXPORT 859 media_status_t AImageReader_setBufferRemovedListener( 860 AImageReader* reader, AImageReader_BufferRemovedListener* listener) { 861 ALOGV("%s", __FUNCTION__); 862 if (reader == nullptr) { 863 ALOGE("%s: invalid argument! reader %p", __FUNCTION__, reader); 864 return AMEDIA_ERROR_INVALID_PARAMETER; 865 } 866 867 reader->setBufferRemovedListener(listener); 868 return AMEDIA_OK; 869 } 870