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