blob: ab3829ea2a0eb8b92b4b7e1a5803328dece905f9 [file] [log] [blame]
Yin-Chia Yehc3603822016-01-18 22:11:19 -08001/*
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
Mathias Agopian05d19b02017-02-28 16:28:19 -080025#include <cutils/atomic.h>
Yin-Chia Yehc3603822016-01-18 22:11:19 -080026#include <utils/Log.h>
27#include <android_runtime/android_view_Surface.h>
28
29using namespace android;
30
31namespace {
32 // Get an ID that's unique within this process.
33 static int32_t createProcessUniqueId() {
34 static volatile int32_t globalCounter = 0;
35 return android_atomic_inc(&globalCounter);
36 }
37}
38
39const char* AImageReader::kCallbackFpKey = "Callback";
40const char* AImageReader::kContextKey = "Context";
41
42bool
43AImageReader::isSupportedFormat(int32_t format) {
44 switch (format) {
Jiwen 'Steve' Caide2a5442017-02-08 14:41:41 -080045 case AIMAGE_FORMAT_RGBA_8888:
46 case AIMAGE_FORMAT_RGBX_8888:
47 case AIMAGE_FORMAT_RGB_888:
48 case AIMAGE_FORMAT_RGB_565:
49 case AIMAGE_FORMAT_RGBA_FP16:
Yin-Chia Yehc3603822016-01-18 22:11:19 -080050 case AIMAGE_FORMAT_YUV_420_888:
51 case AIMAGE_FORMAT_JPEG:
52 case AIMAGE_FORMAT_RAW16:
53 case AIMAGE_FORMAT_RAW_PRIVATE:
54 case AIMAGE_FORMAT_RAW10:
55 case AIMAGE_FORMAT_RAW12:
56 case AIMAGE_FORMAT_DEPTH16:
57 case AIMAGE_FORMAT_DEPTH_POINT_CLOUD:
58 return true;
59 default:
60 return false;
61 }
62}
63
64int
65AImageReader::getNumPlanesForFormat(int32_t format) {
66 switch (format) {
67 case AIMAGE_FORMAT_YUV_420_888:
68 return 3;
Jiwen 'Steve' Caide2a5442017-02-08 14:41:41 -080069 case AIMAGE_FORMAT_RGBA_8888:
70 case AIMAGE_FORMAT_RGBX_8888:
71 case AIMAGE_FORMAT_RGB_888:
72 case AIMAGE_FORMAT_RGB_565:
73 case AIMAGE_FORMAT_RGBA_FP16:
Yin-Chia Yehc3603822016-01-18 22:11:19 -080074 case AIMAGE_FORMAT_JPEG:
75 case AIMAGE_FORMAT_RAW16:
76 case AIMAGE_FORMAT_RAW_PRIVATE:
77 case AIMAGE_FORMAT_RAW10:
78 case AIMAGE_FORMAT_RAW12:
79 case AIMAGE_FORMAT_DEPTH16:
80 case AIMAGE_FORMAT_DEPTH_POINT_CLOUD:
81 return 1;
82 default:
83 return -1;
84 }
85}
86
87void
88AImageReader::FrameListener::onFrameAvailable(const BufferItem& /*item*/) {
89 Mutex::Autolock _l(mLock);
90 sp<AImageReader> reader = mReader.promote();
91 if (reader == nullptr) {
92 ALOGW("A frame is available after AImageReader closed!");
93 return; // reader has been closed
94 }
95 if (mListener.onImageAvailable == nullptr) {
96 return; // No callback registered
97 }
98
99 sp<AMessage> msg = new AMessage(AImageReader::kWhatImageAvailable, reader->mHandler);
100 msg->setPointer(AImageReader::kCallbackFpKey, (void *) mListener.onImageAvailable);
101 msg->setPointer(AImageReader::kContextKey, mListener.context);
102 msg->post();
103}
104
105media_status_t
106AImageReader::FrameListener::setImageListener(AImageReader_ImageListener* listener) {
107 Mutex::Autolock _l(mLock);
108 if (listener == nullptr) {
Yin-Chia Yeh1d0955c2016-05-16 01:14:13 -0700109 mListener.context = nullptr;
110 mListener.onImageAvailable = nullptr;
111 } else {
112 mListener = *listener;
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800113 }
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800114 return AMEDIA_OK;
115}
116
117media_status_t
118AImageReader::setImageListenerLocked(AImageReader_ImageListener* listener) {
119 return mFrameListener->setImageListener(listener);
120}
121
122media_status_t
123AImageReader::setImageListener(AImageReader_ImageListener* listener) {
124 Mutex::Autolock _l(mLock);
125 return setImageListenerLocked(listener);
126}
127
128void AImageReader::CallbackHandler::onMessageReceived(
129 const sp<AMessage> &msg) {
130 switch (msg->what()) {
131 case kWhatImageAvailable:
132 {
133 AImageReader_ImageCallback onImageAvailable;
134 void* context;
135 bool found = msg->findPointer(kCallbackFpKey, (void**) &onImageAvailable);
136 if (!found || onImageAvailable == nullptr) {
137 ALOGE("%s: Cannot find onImageAvailable callback fp!", __FUNCTION__);
138 return;
139 }
140 found = msg->findPointer(kContextKey, &context);
141 if (!found) {
142 ALOGE("%s: Cannot find callback context!", __FUNCTION__);
143 return;
144 }
145 (*onImageAvailable)(context, mReader);
146 break;
147 }
148 default:
149 ALOGE("%s: unknown message type %d", __FUNCTION__, msg->what());
150 break;
151 }
152}
153
154AImageReader::AImageReader(int32_t width, int32_t height, int32_t format, int32_t maxImages) :
155 mWidth(width), mHeight(height), mFormat(format), mMaxImages(maxImages),
156 mNumPlanes(getNumPlanesForFormat(format)),
157 mFrameListener(new FrameListener(this)) {}
158
159media_status_t
160AImageReader::init() {
161 PublicFormat publicFormat = static_cast<PublicFormat>(mFormat);
162 mHalFormat = android_view_Surface_mapPublicFormatToHalFormat(publicFormat);
163 mHalDataSpace = android_view_Surface_mapPublicFormatToHalDataspace(publicFormat);
164
165 sp<IGraphicBufferProducer> gbProducer;
166 sp<IGraphicBufferConsumer> gbConsumer;
167 BufferQueue::createBufferQueue(&gbProducer, &gbConsumer);
168
169 sp<CpuConsumer> cpuConsumer;
170 String8 consumerName = String8::format("ImageReader-%dx%df%xm%d-%d-%d",
171 mWidth, mHeight, mFormat, mMaxImages, getpid(),
172 createProcessUniqueId());
173
174 cpuConsumer = new CpuConsumer(gbConsumer, mMaxImages, /*controlledByApp*/true);
175 if (cpuConsumer == nullptr) {
176 ALOGE("Failed to allocate CpuConsumer");
177 return AMEDIA_ERROR_UNKNOWN;
178 }
179
180 mCpuConsumer = cpuConsumer;
181 mCpuConsumer->setName(consumerName);
182 mProducer = gbProducer;
183
184 sp<ConsumerBase> consumer = cpuConsumer;
185 consumer->setFrameAvailableListener(mFrameListener);
186
187 status_t res;
188 res = cpuConsumer->setDefaultBufferSize(mWidth, mHeight);
189 if (res != OK) {
190 ALOGE("Failed to set CpuConsumer buffer size");
191 return AMEDIA_ERROR_UNKNOWN;
192 }
193 res = cpuConsumer->setDefaultBufferFormat(mHalFormat);
194 if (res != OK) {
195 ALOGE("Failed to set CpuConsumer buffer format");
196 return AMEDIA_ERROR_UNKNOWN;
197 }
198 res = cpuConsumer->setDefaultBufferDataSpace(mHalDataSpace);
199 if (res != OK) {
200 ALOGE("Failed to set CpuConsumer buffer dataSpace");
201 return AMEDIA_ERROR_UNKNOWN;
202 }
203
204 mSurface = new Surface(mProducer, /*controlledByApp*/true);
205 if (mSurface == nullptr) {
206 ALOGE("Failed to create surface");
207 return AMEDIA_ERROR_UNKNOWN;
208 }
209 mWindow = static_cast<ANativeWindow*>(mSurface.get());
210
211 for (int i = 0; i < mMaxImages; i++) {
212 CpuConsumer::LockedBuffer* buffer = new CpuConsumer::LockedBuffer;
213 mBuffers.push_back(buffer);
214 }
215
216 mCbLooper = new ALooper;
217 mCbLooper->setName(consumerName.string());
Aurimas Liutikas214c8332016-02-19 14:48:23 -0800218 res = mCbLooper->start(
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800219 /*runOnCallingThread*/false,
220 /*canCallJava*/ true,
221 PRIORITY_DEFAULT);
Aurimas Liutikas214c8332016-02-19 14:48:23 -0800222 if (res != OK) {
223 ALOGE("Failed to start the looper");
224 return AMEDIA_ERROR_UNKNOWN;
225 }
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800226 mHandler = new CallbackHandler(this);
227 mCbLooper->registerHandler(mHandler);
228
229 return AMEDIA_OK;
230}
231
232AImageReader::~AImageReader() {
233 Mutex::Autolock _l(mLock);
234 AImageReader_ImageListener nullListener = {nullptr, nullptr};
235 setImageListenerLocked(&nullListener);
236
237 if (mCbLooper != nullptr) {
238 mCbLooper->unregisterHandler(mHandler->id());
239 mCbLooper->stop();
240 }
241 mCbLooper.clear();
242 mHandler.clear();
243
244 // Close all previously acquired images
245 for (auto it = mAcquiredImages.begin();
246 it != mAcquiredImages.end(); it++) {
247 AImage* image = *it;
248 image->close();
249 }
250
251 // Delete LockedBuffers
252 for (auto it = mBuffers.begin();
253 it != mBuffers.end(); it++) {
254 delete *it;
255 }
256
257 if (mCpuConsumer != nullptr) {
258 mCpuConsumer->abandon();
259 mCpuConsumer->setFrameAvailableListener(nullptr);
260 }
261}
262
263media_status_t
264AImageReader::acquireCpuConsumerImageLocked(/*out*/AImage** image) {
265 *image = nullptr;
266 CpuConsumer::LockedBuffer* buffer = getLockedBufferLocked();
267 if (buffer == nullptr) {
268 ALOGW("Unable to acquire a lockedBuffer, very likely client tries to lock more than"
269 " maxImages buffers");
270 return AMEDIA_IMGREADER_MAX_IMAGES_ACQUIRED;
271 }
272
273 status_t res = mCpuConsumer->lockNextBuffer(buffer);
274 if (res != NO_ERROR) {
275 returnLockedBufferLocked(buffer);
276 if (res != BAD_VALUE /*no buffers*/) {
277 if (res == NOT_ENOUGH_DATA) {
278 return AMEDIA_IMGREADER_MAX_IMAGES_ACQUIRED;
279 } else {
280 ALOGE("%s Fail to lockNextBuffer with error: %d ",
281 __FUNCTION__, res);
282 return AMEDIA_ERROR_UNKNOWN;
283 }
284 }
285 return AMEDIA_IMGREADER_NO_BUFFER_AVAILABLE;
286 }
287
288 if (buffer->flexFormat == HAL_PIXEL_FORMAT_YCrCb_420_SP) {
289 ALOGE("NV21 format is not supported by AImageReader");
290 return AMEDIA_ERROR_UNSUPPORTED;
291 }
292
293 // Check if the left-top corner of the crop rect is origin, we currently assume this point is
294 // zero, will revist this once this assumption turns out problematic.
295 Point lt = buffer->crop.leftTop();
296 if (lt.x != 0 || lt.y != 0) {
297 ALOGE("crop left top corner [%d, %d] need to be at origin", lt.x, lt.y);
298 return AMEDIA_ERROR_UNKNOWN;
299 }
300
301 // Check if the producer buffer configurations match what ImageReader configured.
302 int outputWidth = getBufferWidth(buffer);
303 int outputHeight = getBufferHeight(buffer);
304
305 int readerFmt = mHalFormat;
306 int readerWidth = mWidth;
307 int readerHeight = mHeight;
308
309 if ((buffer->format != HAL_PIXEL_FORMAT_BLOB) && (readerFmt != HAL_PIXEL_FORMAT_BLOB) &&
310 (readerWidth != outputWidth || readerHeight != outputHeight)) {
311 ALOGW("%s: Producer buffer size: %dx%d, doesn't match AImageReader configured size: %dx%d",
312 __FUNCTION__, outputWidth, outputHeight, readerWidth, readerHeight);
313 }
314
315 int bufFmt = buffer->format;
316 if (readerFmt == HAL_PIXEL_FORMAT_YCbCr_420_888) {
317 bufFmt = buffer->flexFormat;
318 }
319
320 if (readerFmt != bufFmt) {
321 if (readerFmt == HAL_PIXEL_FORMAT_YCbCr_420_888 && (bufFmt ==
322 HAL_PIXEL_FORMAT_YCrCb_420_SP || bufFmt == HAL_PIXEL_FORMAT_YV12)) {
323 // Special casing for when producer switches to a format compatible with flexible YUV
324 // (HAL_PIXEL_FORMAT_YCbCr_420_888).
325 mHalFormat = bufFmt;
326 ALOGD("%s: Overriding buffer format YUV_420_888 to %x.", __FUNCTION__, bufFmt);
327 } else {
328 // Return the buffer to the queue.
329 mCpuConsumer->unlockBuffer(*buffer);
330 returnLockedBufferLocked(buffer);
331
332 ALOGE("Producer output buffer format: 0x%x, ImageReader configured format: 0x%x",
333 buffer->format, readerFmt);
334
335 return AMEDIA_ERROR_UNKNOWN;
336 }
337 }
338
339 if (mHalFormat == HAL_PIXEL_FORMAT_BLOB) {
340 *image = new AImage(this, mFormat, buffer, buffer->timestamp,
341 readerWidth, readerHeight, mNumPlanes);
342 } else {
343 *image = new AImage(this, mFormat, buffer, buffer->timestamp,
344 outputWidth, outputHeight, mNumPlanes);
345 }
346 mAcquiredImages.push_back(*image);
347 return AMEDIA_OK;
348}
349
350CpuConsumer::LockedBuffer*
351AImageReader::getLockedBufferLocked() {
352 if (mBuffers.empty()) {
353 return nullptr;
354 }
355 // Return a LockedBuffer pointer and remove it from the list
356 auto it = mBuffers.begin();
357 CpuConsumer::LockedBuffer* buffer = *it;
358 mBuffers.erase(it);
359 return buffer;
360}
361
362void
363AImageReader::returnLockedBufferLocked(CpuConsumer::LockedBuffer* buffer) {
364 mBuffers.push_back(buffer);
365}
366
367void
368AImageReader::releaseImageLocked(AImage* image) {
369 CpuConsumer::LockedBuffer* buffer = image->mBuffer;
370 if (buffer == nullptr) {
371 // This should not happen, but is not fatal
372 ALOGW("AImage %p has no buffer!", image);
373 return;
374 }
375
376 mCpuConsumer->unlockBuffer(*buffer);
377 returnLockedBufferLocked(buffer);
378 image->mBuffer = nullptr;
379
380 bool found = false;
381 // cleanup acquired image list
382 for (auto it = mAcquiredImages.begin();
383 it != mAcquiredImages.end(); it++) {
384 AImage* readerCopy = *it;
385 if (readerCopy == image) {
386 found = true;
387 mAcquiredImages.erase(it);
388 break;
389 }
390 }
391 if (!found) {
392 ALOGE("Error: AImage %p is not generated by AImageReader %p",
393 image, this);
394 }
395}
396
397int
398AImageReader::getBufferWidth(CpuConsumer::LockedBuffer* buffer) {
399 if (buffer == nullptr) return -1;
400
401 if (!buffer->crop.isEmpty()) {
402 return buffer->crop.getWidth();
403 }
404 return buffer->width;
405}
406
407int
408AImageReader::getBufferHeight(CpuConsumer::LockedBuffer* buffer) {
409 if (buffer == nullptr) return -1;
410
411 if (!buffer->crop.isEmpty()) {
412 return buffer->crop.getHeight();
413 }
414 return buffer->height;
415}
416
417media_status_t
418AImageReader::acquireNextImage(/*out*/AImage** image) {
419 Mutex::Autolock _l(mLock);
420 return acquireCpuConsumerImageLocked(image);
421}
422
423media_status_t
424AImageReader::acquireLatestImage(/*out*/AImage** image) {
425 if (image == nullptr) {
426 return AMEDIA_ERROR_INVALID_PARAMETER;
427 }
428 Mutex::Autolock _l(mLock);
429 *image = nullptr;
430 AImage* prevImage = nullptr;
431 AImage* nextImage = nullptr;
432 media_status_t ret = acquireCpuConsumerImageLocked(&prevImage);
433 if (prevImage == nullptr) {
434 return ret;
435 }
436 for (;;) {
437 ret = acquireCpuConsumerImageLocked(&nextImage);
438 if (nextImage == nullptr) {
439 *image = prevImage;
440 return AMEDIA_OK;
441 }
442 prevImage->close();
443 prevImage->free();
444 prevImage = nextImage;
445 nextImage = nullptr;
446 }
447}
448
449EXPORT
450media_status_t AImageReader_new(
451 int32_t width, int32_t height, int32_t format, int32_t maxImages,
452 /*out*/AImageReader** reader) {
453 ALOGV("%s", __FUNCTION__);
454
455 if (width < 1 || height < 1) {
456 ALOGE("%s: image dimension must be positive: w:%d h:%d",
457 __FUNCTION__, width, height);
458 return AMEDIA_ERROR_INVALID_PARAMETER;
459 }
460
461 if (maxImages < 1) {
462 ALOGE("%s: max outstanding image count must be at least 1 (%d)",
463 __FUNCTION__, maxImages);
464 return AMEDIA_ERROR_INVALID_PARAMETER;
465 }
466
467 if (!AImageReader::isSupportedFormat(format)) {
468 ALOGE("%s: format %d is not supported by AImageReader",
469 __FUNCTION__, format);
470 return AMEDIA_ERROR_INVALID_PARAMETER;
471 }
472
473 if (reader == nullptr) {
474 ALOGE("%s: reader argument is null", __FUNCTION__);
475 return AMEDIA_ERROR_INVALID_PARAMETER;
476 }
477
478 //*reader = new AImageReader(width, height, format, maxImages);
479 AImageReader* tmpReader = new AImageReader(width, height, format, maxImages);
480 if (tmpReader == nullptr) {
481 ALOGE("%s: AImageReader allocation failed", __FUNCTION__);
482 return AMEDIA_ERROR_UNKNOWN;
483 }
484 media_status_t ret = tmpReader->init();
485 if (ret != AMEDIA_OK) {
486 ALOGE("%s: AImageReader initialization failed!", __FUNCTION__);
487 delete tmpReader;
488 return ret;
489 }
490 *reader = tmpReader;
491 (*reader)->incStrong((void*) AImageReader_new);
492 return AMEDIA_OK;
493}
494
495EXPORT
496void AImageReader_delete(AImageReader* reader) {
497 ALOGV("%s", __FUNCTION__);
498 if (reader != nullptr) {
499 reader->decStrong((void*) AImageReader_delete);
500 }
501 return;
502}
503
504EXPORT
505media_status_t AImageReader_getWindow(AImageReader* reader, /*out*/ANativeWindow** window) {
506 ALOGE("%s", __FUNCTION__);
507 if (reader == nullptr || window == nullptr) {
508 ALOGE("%s: invalid argument. reader %p, window %p",
509 __FUNCTION__, reader, window);
510 return AMEDIA_ERROR_INVALID_PARAMETER;
511 }
512 *window = reader->getWindow();
513 return AMEDIA_OK;
514}
515
516EXPORT
517media_status_t AImageReader_getWidth(const AImageReader* reader, /*out*/int32_t* width) {
518 ALOGV("%s", __FUNCTION__);
519 if (reader == nullptr || width == nullptr) {
520 ALOGE("%s: invalid argument. reader %p, width %p",
521 __FUNCTION__, reader, width);
522 return AMEDIA_ERROR_INVALID_PARAMETER;
523 }
524 *width = reader->getWidth();
525 return AMEDIA_OK;
526}
527
528EXPORT
529media_status_t AImageReader_getHeight(const AImageReader* reader, /*out*/int32_t* height) {
530 ALOGV("%s", __FUNCTION__);
531 if (reader == nullptr || height == nullptr) {
532 ALOGE("%s: invalid argument. reader %p, height %p",
533 __FUNCTION__, reader, height);
534 return AMEDIA_ERROR_INVALID_PARAMETER;
535 }
536 *height = reader->getHeight();
537 return AMEDIA_OK;
538}
539
540EXPORT
541media_status_t AImageReader_getFormat(const AImageReader* reader, /*out*/int32_t* format) {
542 ALOGV("%s", __FUNCTION__);
543 if (reader == nullptr || format == nullptr) {
544 ALOGE("%s: invalid argument. reader %p, format %p",
545 __FUNCTION__, reader, format);
546 return AMEDIA_ERROR_INVALID_PARAMETER;
547 }
548 *format = reader->getFormat();
549 return AMEDIA_OK;
550}
551
552EXPORT
553media_status_t AImageReader_getMaxImages(const AImageReader* reader, /*out*/int32_t* maxImages) {
554 ALOGV("%s", __FUNCTION__);
555 if (reader == nullptr || maxImages == nullptr) {
556 ALOGE("%s: invalid argument. reader %p, maxImages %p",
557 __FUNCTION__, reader, maxImages);
558 return AMEDIA_ERROR_INVALID_PARAMETER;
559 }
560 *maxImages = reader->getMaxImages();
561 return AMEDIA_OK;
562}
563
564EXPORT
565media_status_t AImageReader_acquireNextImage(AImageReader* reader, /*out*/AImage** image) {
566 ALOGV("%s", __FUNCTION__);
567 if (reader == nullptr || image == nullptr) {
568 ALOGE("%s: invalid argument. reader %p, maxImages %p",
569 __FUNCTION__, reader, image);
570 return AMEDIA_ERROR_INVALID_PARAMETER;
571 }
572 return reader->acquireNextImage(image);
573}
574
575EXPORT
576media_status_t AImageReader_acquireLatestImage(AImageReader* reader, /*out*/AImage** image) {
577 ALOGV("%s", __FUNCTION__);
578 if (reader == nullptr || image == nullptr) {
579 ALOGE("%s: invalid argument. reader %p, maxImages %p",
580 __FUNCTION__, reader, image);
581 return AMEDIA_ERROR_INVALID_PARAMETER;
582 }
583 return reader->acquireLatestImage(image);
584}
585
586EXPORT
587media_status_t AImageReader_setImageListener(
588 AImageReader* reader, AImageReader_ImageListener* listener) {
589 ALOGV("%s", __FUNCTION__);
Yin-Chia Yeh1d0955c2016-05-16 01:14:13 -0700590 if (reader == nullptr) {
591 ALOGE("%s: invalid argument! reader %p", __FUNCTION__, reader);
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800592 return AMEDIA_ERROR_INVALID_PARAMETER;
593 }
594
595 reader->setImageListener(listener);
596 return AMEDIA_OK;
597}