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
isSupportedFormat(int32_t format)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
getNumPlanesForFormat(int32_t format)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
onFrameAvailable(const BufferItem &)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
setImageListener(AImageReader_ImageListener * listener)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
onBufferFreed(const wp<GraphicBuffer> & graphicBuffer)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
setBufferRemovedListener(AImageReader_BufferRemovedListener * listener)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
setImageListenerLocked(AImageReader_ImageListener * listener)161 AImageReader::setImageListenerLocked(AImageReader_ImageListener* listener) {
162     return mFrameListener->setImageListener(listener);
163 }
164 
165 media_status_t
setImageListener(AImageReader_ImageListener * listener)166 AImageReader::setImageListener(AImageReader_ImageListener* listener) {
167     Mutex::Autolock _l(mLock);
168     return setImageListenerLocked(listener);
169 }
170 
171 media_status_t
setBufferRemovedListenerLocked(AImageReader_BufferRemovedListener * listener)172 AImageReader::setBufferRemovedListenerLocked(AImageReader_BufferRemovedListener* listener) {
173     return mBufferRemovedListener->setBufferRemovedListener(listener);
174 }
175 
176 media_status_t
setBufferRemovedListener(AImageReader_BufferRemovedListener * listener)177 AImageReader::setBufferRemovedListener(AImageReader_BufferRemovedListener* listener) {
178     Mutex::Autolock _l(mLock);
179     return setBufferRemovedListenerLocked(listener);
180 }
181 
onMessageReceived(const sp<AMessage> & msg)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 
AImageReader(int32_t width,int32_t height,int32_t format,uint64_t usage,int32_t maxImages)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
init()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 
~AImageReader()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
acquireImageLocked(AImage ** image,int * acquireFenceFd)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*
getBufferItemLocked()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
returnBufferItemLocked(BufferItem * buffer)469 AImageReader::returnBufferItemLocked(BufferItem* buffer) {
470     mBuffers.push_back(buffer);
471 }
472 
473 void
releaseImageLocked(AImage * image,int releaseFenceFd)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
getBufferWidth(BufferItem * buffer)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
getBufferHeight(BufferItem * buffer)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
acquireNextImage(AImage ** image,int * acquireFenceFd)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
acquireLatestImage(AImage ** image,int * acquireFenceFd)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
AImageReader_new(int32_t width,int32_t height,int32_t format,int32_t maxImages,AImageReader ** reader)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
AImageReader_newWithUsage(int32_t width,int32_t height,int32_t format,uint64_t usage,int32_t maxImages,AImageReader ** reader)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
AImageReader_delete(AImageReader * reader)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
AImageReader_getWindow(AImageReader * reader,ANativeWindow ** window)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
AImageReader_getWidth(const AImageReader * reader,int32_t * width)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
AImageReader_getHeight(const AImageReader * reader,int32_t * height)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
AImageReader_getFormat(const AImageReader * reader,int32_t * format)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
AImageReader_getMaxImages(const AImageReader * reader,int32_t * maxImages)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
AImageReader_acquireNextImage(AImageReader * reader,AImage ** image)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
AImageReader_acquireLatestImage(AImageReader * reader,AImage ** image)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
AImageReader_acquireNextImageAsync(AImageReader * reader,AImage ** image,int * acquireFenceFd)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
AImageReader_acquireLatestImageAsync(AImageReader * reader,AImage ** image,int * acquireFenceFd)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
AImageReader_setImageListener(AImageReader * reader,AImageReader_ImageListener * listener)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
AImageReader_setBufferRemovedListener(AImageReader * reader,AImageReader_BufferRemovedListener * listener)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