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