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