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