• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
createProcessUniqueId()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
isSupportedFormatAndUsage(int32_t format,uint64_t usage)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
getNumPlanesForFormat(int32_t format)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
onFrameAvailable(const BufferItem &)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
setImageListener(AImageReader_ImageListener * listener)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
onBufferFreed(const wp<GraphicBuffer> & graphicBuffer)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
setBufferRemovedListener(AImageReader_BufferRemovedListener * listener)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
setImageListenerLocked(AImageReader_ImageListener * listener)170 AImageReader::setImageListenerLocked(AImageReader_ImageListener* listener) {
171     return mFrameListener->setImageListener(listener);
172 }
173 
174 media_status_t
setImageListener(AImageReader_ImageListener * listener)175 AImageReader::setImageListener(AImageReader_ImageListener* listener) {
176     Mutex::Autolock _l(mLock);
177     return setImageListenerLocked(listener);
178 }
179 
180 media_status_t
setBufferRemovedListenerLocked(AImageReader_BufferRemovedListener * listener)181 AImageReader::setBufferRemovedListenerLocked(AImageReader_BufferRemovedListener* listener) {
182     return mBufferRemovedListener->setBufferRemovedListener(listener);
183 }
184 
185 media_status_t
setBufferRemovedListener(AImageReader_BufferRemovedListener * listener)186 AImageReader::setBufferRemovedListener(AImageReader_BufferRemovedListener* listener) {
187     Mutex::Autolock _l(mLock);
188     return setBufferRemovedListenerLocked(listener);
189 }
190 
onMessageReceived(const sp<AMessage> & msg)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 
AImageReader(int32_t width,int32_t height,int32_t format,uint64_t usage,int32_t maxImages)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
init()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 
~AImageReader()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
acquireImageLocked(AImage ** image,int * acquireFenceFd)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*
getBufferItemLocked()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
returnBufferItemLocked(BufferItem * buffer)479 AImageReader::returnBufferItemLocked(BufferItem* buffer) {
480     mBuffers.push_back(buffer);
481 }
482 
483 void
releaseImageLocked(AImage * image,int releaseFenceFd)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
getBufferWidth(BufferItem * buffer)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
getBufferHeight(BufferItem * buffer)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
acquireNextImage(AImage ** image,int * acquireFenceFd)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
acquireLatestImage(AImage ** image,int * acquireFenceFd)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
AImageReader_new(int32_t width,int32_t height,int32_t format,int32_t maxImages,AImageReader ** reader)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
AImageReader_newWithUsage(int32_t width,int32_t height,int32_t format,uint64_t usage,int32_t maxImages,AImageReader ** reader)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
AImageReader_delete(AImageReader * reader)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
AImageReader_getWindow(AImageReader * reader,ANativeWindow ** window)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
AImageReader_getWidth(const AImageReader * reader,int32_t * width)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
AImageReader_getHeight(const AImageReader * reader,int32_t * height)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
AImageReader_getFormat(const AImageReader * reader,int32_t * format)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
AImageReader_getMaxImages(const AImageReader * reader,int32_t * maxImages)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
AImageReader_acquireNextImage(AImageReader * reader,AImage ** image)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
AImageReader_acquireLatestImage(AImageReader * reader,AImage ** image)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
AImageReader_acquireNextImageAsync(AImageReader * reader,AImage ** image,int * acquireFenceFd)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
AImageReader_acquireLatestImageAsync(AImageReader * reader,AImage ** image,int * acquireFenceFd)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
AImageReader_setImageListener(AImageReader * reader,AImageReader_ImageListener * listener)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
AImageReader_setBufferRemovedListener(AImageReader * reader,AImageReader_BufferRemovedListener * listener)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