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