blob: e580dae580d82e3460a64c9ac3ff5d6d292437df [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>
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -080027#include <android_media_Utils.h>
Yin-Chia Yehc3603822016-01-18 22:11:19 -080028#include <android_runtime/android_view_Surface.h>
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -080029#include <android_runtime/android_hardware_HardwareBuffer.h>
Yin-Chia Yehc3603822016-01-18 22:11:19 -080030
31using namespace android;
32
33namespace {
34 // Get an ID that's unique within this process.
35 static int32_t createProcessUniqueId() {
36 static volatile int32_t globalCounter = 0;
37 return android_atomic_inc(&globalCounter);
38 }
39}
40
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -080041const int32_t AImageReader::kDefaultUsage = AHARDWAREBUFFER_USAGE0_CPU_READ_OFTEN;
Yin-Chia Yehc3603822016-01-18 22:11:19 -080042const char* AImageReader::kCallbackFpKey = "Callback";
43const char* AImageReader::kContextKey = "Context";
44
45bool
46AImageReader::isSupportedFormat(int32_t format) {
47 switch (format) {
Jiwen 'Steve' Caide2a5442017-02-08 14:41:41 -080048 case AIMAGE_FORMAT_RGBA_8888:
49 case AIMAGE_FORMAT_RGBX_8888:
50 case AIMAGE_FORMAT_RGB_888:
51 case AIMAGE_FORMAT_RGB_565:
52 case AIMAGE_FORMAT_RGBA_FP16:
Yin-Chia Yehc3603822016-01-18 22:11:19 -080053 case AIMAGE_FORMAT_YUV_420_888:
54 case AIMAGE_FORMAT_JPEG:
55 case AIMAGE_FORMAT_RAW16:
56 case AIMAGE_FORMAT_RAW_PRIVATE:
57 case AIMAGE_FORMAT_RAW10:
58 case AIMAGE_FORMAT_RAW12:
59 case AIMAGE_FORMAT_DEPTH16:
60 case AIMAGE_FORMAT_DEPTH_POINT_CLOUD:
61 return true;
62 default:
63 return false;
64 }
65}
66
67int
68AImageReader::getNumPlanesForFormat(int32_t format) {
69 switch (format) {
70 case AIMAGE_FORMAT_YUV_420_888:
71 return 3;
Jiwen 'Steve' Caide2a5442017-02-08 14:41:41 -080072 case AIMAGE_FORMAT_RGBA_8888:
73 case AIMAGE_FORMAT_RGBX_8888:
74 case AIMAGE_FORMAT_RGB_888:
75 case AIMAGE_FORMAT_RGB_565:
76 case AIMAGE_FORMAT_RGBA_FP16:
Yin-Chia Yehc3603822016-01-18 22:11:19 -080077 case AIMAGE_FORMAT_JPEG:
78 case AIMAGE_FORMAT_RAW16:
79 case AIMAGE_FORMAT_RAW_PRIVATE:
80 case AIMAGE_FORMAT_RAW10:
81 case AIMAGE_FORMAT_RAW12:
82 case AIMAGE_FORMAT_DEPTH16:
83 case AIMAGE_FORMAT_DEPTH_POINT_CLOUD:
84 return 1;
85 default:
86 return -1;
87 }
88}
89
90void
91AImageReader::FrameListener::onFrameAvailable(const BufferItem& /*item*/) {
92 Mutex::Autolock _l(mLock);
93 sp<AImageReader> reader = mReader.promote();
94 if (reader == nullptr) {
95 ALOGW("A frame is available after AImageReader closed!");
96 return; // reader has been closed
97 }
98 if (mListener.onImageAvailable == nullptr) {
99 return; // No callback registered
100 }
101
102 sp<AMessage> msg = new AMessage(AImageReader::kWhatImageAvailable, reader->mHandler);
103 msg->setPointer(AImageReader::kCallbackFpKey, (void *) mListener.onImageAvailable);
104 msg->setPointer(AImageReader::kContextKey, mListener.context);
105 msg->post();
106}
107
108media_status_t
109AImageReader::FrameListener::setImageListener(AImageReader_ImageListener* listener) {
110 Mutex::Autolock _l(mLock);
111 if (listener == nullptr) {
Yin-Chia Yeh1d0955c2016-05-16 01:14:13 -0700112 mListener.context = nullptr;
113 mListener.onImageAvailable = nullptr;
114 } else {
115 mListener = *listener;
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800116 }
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800117 return AMEDIA_OK;
118}
119
120media_status_t
121AImageReader::setImageListenerLocked(AImageReader_ImageListener* listener) {
122 return mFrameListener->setImageListener(listener);
123}
124
125media_status_t
126AImageReader::setImageListener(AImageReader_ImageListener* listener) {
127 Mutex::Autolock _l(mLock);
128 return setImageListenerLocked(listener);
129}
130
131void AImageReader::CallbackHandler::onMessageReceived(
132 const sp<AMessage> &msg) {
133 switch (msg->what()) {
134 case kWhatImageAvailable:
135 {
136 AImageReader_ImageCallback onImageAvailable;
137 void* context;
138 bool found = msg->findPointer(kCallbackFpKey, (void**) &onImageAvailable);
139 if (!found || onImageAvailable == nullptr) {
140 ALOGE("%s: Cannot find onImageAvailable callback fp!", __FUNCTION__);
141 return;
142 }
143 found = msg->findPointer(kContextKey, &context);
144 if (!found) {
145 ALOGE("%s: Cannot find callback context!", __FUNCTION__);
146 return;
147 }
148 (*onImageAvailable)(context, mReader);
149 break;
150 }
151 default:
152 ALOGE("%s: unknown message type %d", __FUNCTION__, msg->what());
153 break;
154 }
155}
156
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800157AImageReader::AImageReader(int32_t width,
158 int32_t height,
159 int32_t format,
160 uint64_t usage,
161 int32_t maxImages)
162 : mWidth(width),
163 mHeight(height),
164 mFormat(format),
165 mUsage(usage),
166 mMaxImages(maxImages),
167 mNumPlanes(getNumPlanesForFormat(format)),
168 mFrameListener(new FrameListener(this)) {}
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800169
170media_status_t
171AImageReader::init() {
172 PublicFormat publicFormat = static_cast<PublicFormat>(mFormat);
173 mHalFormat = android_view_Surface_mapPublicFormatToHalFormat(publicFormat);
174 mHalDataSpace = android_view_Surface_mapPublicFormatToHalDataspace(publicFormat);
175
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800176 uint64_t producerUsage;
177 uint64_t consumerUsage;
178 android_hardware_HardwareBuffer_convertToGrallocUsageBits(
179 &producerUsage, &consumerUsage, mUsage, 0);
180
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800181 sp<IGraphicBufferProducer> gbProducer;
182 sp<IGraphicBufferConsumer> gbConsumer;
183 BufferQueue::createBufferQueue(&gbProducer, &gbConsumer);
184
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800185 String8 consumerName = String8::format(
186 "ImageReader-%dx%df%xu%" PRIu64 "m%d-%d-%d", mWidth, mHeight, mFormat, mUsage,
187 mMaxImages, getpid(), createProcessUniqueId());
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800188
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800189 mBufferItemConsumer =
190 new BufferItemConsumer(gbConsumer, consumerUsage, mMaxImages, /*controlledByApp*/ true);
191 if (mBufferItemConsumer == nullptr) {
192 ALOGE("Failed to allocate BufferItemConsumer");
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800193 return AMEDIA_ERROR_UNKNOWN;
194 }
195
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800196 mProducer = gbProducer;
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800197 mBufferItemConsumer->setName(consumerName);
198 mBufferItemConsumer->setFrameAvailableListener(mFrameListener);
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800199
200 status_t res;
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800201 res = mBufferItemConsumer->setDefaultBufferSize(mWidth, mHeight);
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800202 if (res != OK) {
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800203 ALOGE("Failed to set BufferItemConsumer buffer size");
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800204 return AMEDIA_ERROR_UNKNOWN;
205 }
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800206 res = mBufferItemConsumer->setDefaultBufferFormat(mHalFormat);
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800207 if (res != OK) {
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800208 ALOGE("Failed to set BufferItemConsumer buffer format");
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800209 return AMEDIA_ERROR_UNKNOWN;
210 }
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800211 res = mBufferItemConsumer->setDefaultBufferDataSpace(mHalDataSpace);
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800212 if (res != OK) {
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800213 ALOGE("Failed to set BufferItemConsumer buffer dataSpace");
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800214 return AMEDIA_ERROR_UNKNOWN;
215 }
216
217 mSurface = new Surface(mProducer, /*controlledByApp*/true);
218 if (mSurface == nullptr) {
219 ALOGE("Failed to create surface");
220 return AMEDIA_ERROR_UNKNOWN;
221 }
222 mWindow = static_cast<ANativeWindow*>(mSurface.get());
223
224 for (int i = 0; i < mMaxImages; i++) {
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800225 BufferItem* buffer = new BufferItem;
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800226 mBuffers.push_back(buffer);
227 }
228
229 mCbLooper = new ALooper;
230 mCbLooper->setName(consumerName.string());
Aurimas Liutikas214c8332016-02-19 14:48:23 -0800231 res = mCbLooper->start(
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800232 /*runOnCallingThread*/false,
233 /*canCallJava*/ true,
234 PRIORITY_DEFAULT);
Aurimas Liutikas214c8332016-02-19 14:48:23 -0800235 if (res != OK) {
236 ALOGE("Failed to start the looper");
237 return AMEDIA_ERROR_UNKNOWN;
238 }
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800239 mHandler = new CallbackHandler(this);
240 mCbLooper->registerHandler(mHandler);
241
242 return AMEDIA_OK;
243}
244
245AImageReader::~AImageReader() {
246 Mutex::Autolock _l(mLock);
247 AImageReader_ImageListener nullListener = {nullptr, nullptr};
248 setImageListenerLocked(&nullListener);
249
250 if (mCbLooper != nullptr) {
251 mCbLooper->unregisterHandler(mHandler->id());
252 mCbLooper->stop();
253 }
254 mCbLooper.clear();
255 mHandler.clear();
256
257 // Close all previously acquired images
258 for (auto it = mAcquiredImages.begin();
259 it != mAcquiredImages.end(); it++) {
260 AImage* image = *it;
261 image->close();
262 }
263
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800264 // Delete Buffer Items
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800265 for (auto it = mBuffers.begin();
266 it != mBuffers.end(); it++) {
267 delete *it;
268 }
269
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800270 if (mBufferItemConsumer != nullptr) {
271 mBufferItemConsumer->abandon();
272 mBufferItemConsumer->setFrameAvailableListener(nullptr);
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800273 }
274}
275
276media_status_t
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800277AImageReader::acquireImageLocked(/*out*/AImage** image) {
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800278 *image = nullptr;
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800279 BufferItem* buffer = getBufferItemLocked();
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800280 if (buffer == nullptr) {
281 ALOGW("Unable to acquire a lockedBuffer, very likely client tries to lock more than"
282 " maxImages buffers");
283 return AMEDIA_IMGREADER_MAX_IMAGES_ACQUIRED;
284 }
285
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800286 status_t res = mBufferItemConsumer->acquireBuffer(buffer, 0);
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800287 if (res != NO_ERROR) {
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800288 returnBufferItemLocked(buffer);
289 if (res != BufferQueue::NO_BUFFER_AVAILABLE) {
290 if (res == INVALID_OPERATION) {
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800291 return AMEDIA_IMGREADER_MAX_IMAGES_ACQUIRED;
292 } else {
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800293 ALOGE("%s: Acquire image failed with some unknown error: %s (%d)",
294 __FUNCTION__, strerror(-res), res);
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800295 return AMEDIA_ERROR_UNKNOWN;
296 }
297 }
298 return AMEDIA_IMGREADER_NO_BUFFER_AVAILABLE;
299 }
300
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800301 const int bufferWidth = getBufferWidth(buffer);
302 const int bufferHeight = getBufferHeight(buffer);
303 const int bufferFmt = buffer->mGraphicBuffer->getPixelFormat();
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800304
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800305 const int readerWidth = mWidth;
306 const int readerHeight = mHeight;
307 const int readerFmt = mHalFormat;
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800308
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800309 // Check if the producer buffer configurations match what AImageReader configured. Add some
310 // extra checks for non-opaque formats.
311 if (!isFormatOpaque(readerFmt)) {
312 // Check if the left-top corner of the crop rect is origin, we currently assume this point
313 // is zero, will revisit this once this assumption turns out problematic.
314 Point lt = buffer->mCrop.leftTop();
315 if (lt.x != 0 || lt.y != 0) {
316 ALOGE("Crop left top corner [%d, %d] not at origin", lt.x, lt.y);
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800317 return AMEDIA_ERROR_UNKNOWN;
318 }
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800319
320 // Check if the producer buffer configurations match what ImageReader configured.
321 if ((bufferFmt != HAL_PIXEL_FORMAT_BLOB) && (readerFmt != HAL_PIXEL_FORMAT_BLOB) &&
322 (readerWidth != bufferWidth || readerHeight != bufferHeight)) {
323 ALOGW("%s: Buffer size: %dx%d, doesn't match AImageReader configured size: %dx%d",
324 __FUNCTION__, bufferWidth, bufferHeight, readerWidth, readerHeight);
325 }
326
327 if (readerFmt != bufferFmt) {
328 if (readerFmt == HAL_PIXEL_FORMAT_YCbCr_420_888 && isPossiblyYUV(bufferFmt)) {
329 // Special casing for when producer switches to a format compatible with flexible
330 // YUV.
331 mHalFormat = bufferFmt;
332 ALOGD("%s: Overriding buffer format YUV_420_888 to 0x%x.", __FUNCTION__, bufferFmt);
333 } else {
334 // Return the buffer to the queue. No need to provide fence, as this buffer wasn't
335 // used anywhere yet.
336 mBufferItemConsumer->releaseBuffer(*buffer);
337 returnBufferItemLocked(buffer);
338
339 ALOGE("%s: Output buffer format: 0x%x, ImageReader configured format: 0x%x",
340 __FUNCTION__, bufferFmt, readerFmt);
341
342 return AMEDIA_ERROR_UNKNOWN;
343 }
344 }
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800345 }
346
347 if (mHalFormat == HAL_PIXEL_FORMAT_BLOB) {
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800348 *image = new AImage(this, mFormat, mUsage, buffer, buffer->mTimestamp,
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800349 readerWidth, readerHeight, mNumPlanes);
350 } else {
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800351 *image = new AImage(this, mFormat, mUsage, buffer, buffer->mTimestamp,
352 bufferWidth, bufferHeight, mNumPlanes);
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800353 }
354 mAcquiredImages.push_back(*image);
355 return AMEDIA_OK;
356}
357
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800358BufferItem*
359AImageReader::getBufferItemLocked() {
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800360 if (mBuffers.empty()) {
361 return nullptr;
362 }
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800363 // Return a BufferItem pointer and remove it from the list
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800364 auto it = mBuffers.begin();
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800365 BufferItem* buffer = *it;
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800366 mBuffers.erase(it);
367 return buffer;
368}
369
370void
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800371AImageReader::returnBufferItemLocked(BufferItem* buffer) {
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800372 mBuffers.push_back(buffer);
373}
374
375void
376AImageReader::releaseImageLocked(AImage* image) {
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800377 BufferItem* buffer = image->mBuffer;
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800378 if (buffer == nullptr) {
379 // This should not happen, but is not fatal
380 ALOGW("AImage %p has no buffer!", image);
381 return;
382 }
383
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800384 int fenceFd = -1;
385 media_status_t ret = image->unlockImageIfLocked(&fenceFd);
386 if (ret < 0) {
387 ALOGW("%s: AImage %p is cannot be unlocked.", __FUNCTION__, image);
388 return;
389 }
390
391 sp<Fence> releaseFence = fenceFd > 0 ? new Fence(fenceFd) : Fence::NO_FENCE;
392 mBufferItemConsumer->releaseBuffer(*buffer, releaseFence);
393 returnBufferItemLocked(buffer);
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800394 image->mBuffer = nullptr;
395
396 bool found = false;
397 // cleanup acquired image list
398 for (auto it = mAcquiredImages.begin();
399 it != mAcquiredImages.end(); it++) {
400 AImage* readerCopy = *it;
401 if (readerCopy == image) {
402 found = true;
403 mAcquiredImages.erase(it);
404 break;
405 }
406 }
407 if (!found) {
408 ALOGE("Error: AImage %p is not generated by AImageReader %p",
409 image, this);
410 }
411}
412
413int
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800414AImageReader::getBufferWidth(BufferItem* buffer) {
415 if (buffer == NULL) return -1;
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800416
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800417 if (!buffer->mCrop.isEmpty()) {
418 return buffer->mCrop.getWidth();
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800419 }
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800420
421 return buffer->mGraphicBuffer->getWidth();
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800422}
423
424int
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800425AImageReader::getBufferHeight(BufferItem* buffer) {
426 if (buffer == NULL) return -1;
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800427
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800428 if (!buffer->mCrop.isEmpty()) {
429 return buffer->mCrop.getHeight();
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800430 }
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800431
432 return buffer->mGraphicBuffer->getHeight();
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800433}
434
435media_status_t
436AImageReader::acquireNextImage(/*out*/AImage** image) {
437 Mutex::Autolock _l(mLock);
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800438 return acquireImageLocked(image);
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800439}
440
441media_status_t
442AImageReader::acquireLatestImage(/*out*/AImage** image) {
443 if (image == nullptr) {
444 return AMEDIA_ERROR_INVALID_PARAMETER;
445 }
446 Mutex::Autolock _l(mLock);
447 *image = nullptr;
448 AImage* prevImage = nullptr;
449 AImage* nextImage = nullptr;
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800450 media_status_t ret = acquireImageLocked(&prevImage);
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800451 if (prevImage == nullptr) {
452 return ret;
453 }
454 for (;;) {
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800455 ret = acquireImageLocked(&nextImage);
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800456 if (nextImage == nullptr) {
457 *image = prevImage;
458 return AMEDIA_OK;
459 }
460 prevImage->close();
461 prevImage->free();
462 prevImage = nextImage;
463 nextImage = nullptr;
464 }
465}
466
467EXPORT
468media_status_t AImageReader_new(
469 int32_t width, int32_t height, int32_t format, int32_t maxImages,
470 /*out*/AImageReader** reader) {
471 ALOGV("%s", __FUNCTION__);
472
473 if (width < 1 || height < 1) {
474 ALOGE("%s: image dimension must be positive: w:%d h:%d",
475 __FUNCTION__, width, height);
476 return AMEDIA_ERROR_INVALID_PARAMETER;
477 }
478
479 if (maxImages < 1) {
480 ALOGE("%s: max outstanding image count must be at least 1 (%d)",
481 __FUNCTION__, maxImages);
482 return AMEDIA_ERROR_INVALID_PARAMETER;
483 }
484
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800485 if (maxImages > BufferQueueDefs::NUM_BUFFER_SLOTS) {
486 ALOGE("%s: max outstanding image count (%d) cannot be larget than %d.",
487 __FUNCTION__, maxImages, BufferQueueDefs::NUM_BUFFER_SLOTS);
488 return AMEDIA_ERROR_INVALID_PARAMETER;
489 }
490
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800491 if (!AImageReader::isSupportedFormat(format)) {
492 ALOGE("%s: format %d is not supported by AImageReader",
493 __FUNCTION__, format);
494 return AMEDIA_ERROR_INVALID_PARAMETER;
495 }
496
497 if (reader == nullptr) {
498 ALOGE("%s: reader argument is null", __FUNCTION__);
499 return AMEDIA_ERROR_INVALID_PARAMETER;
500 }
501
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800502 // Set consumer usage to AHARDWAREBUFFER_USAGE0_CPU_READ_OFTEN by default so that
503 // AImageReader_new behaves as if it's backed by CpuConsumer.
504 AImageReader* tmpReader = new AImageReader(
505 width, height, format, AImageReader::kDefaultUsage, maxImages);
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800506 if (tmpReader == nullptr) {
507 ALOGE("%s: AImageReader allocation failed", __FUNCTION__);
508 return AMEDIA_ERROR_UNKNOWN;
509 }
510 media_status_t ret = tmpReader->init();
511 if (ret != AMEDIA_OK) {
512 ALOGE("%s: AImageReader initialization failed!", __FUNCTION__);
513 delete tmpReader;
514 return ret;
515 }
516 *reader = tmpReader;
517 (*reader)->incStrong((void*) AImageReader_new);
518 return AMEDIA_OK;
519}
520
521EXPORT
522void AImageReader_delete(AImageReader* reader) {
523 ALOGV("%s", __FUNCTION__);
524 if (reader != nullptr) {
525 reader->decStrong((void*) AImageReader_delete);
526 }
527 return;
528}
529
530EXPORT
531media_status_t AImageReader_getWindow(AImageReader* reader, /*out*/ANativeWindow** window) {
532 ALOGE("%s", __FUNCTION__);
533 if (reader == nullptr || window == nullptr) {
534 ALOGE("%s: invalid argument. reader %p, window %p",
535 __FUNCTION__, reader, window);
536 return AMEDIA_ERROR_INVALID_PARAMETER;
537 }
538 *window = reader->getWindow();
539 return AMEDIA_OK;
540}
541
542EXPORT
543media_status_t AImageReader_getWidth(const AImageReader* reader, /*out*/int32_t* width) {
544 ALOGV("%s", __FUNCTION__);
545 if (reader == nullptr || width == nullptr) {
546 ALOGE("%s: invalid argument. reader %p, width %p",
547 __FUNCTION__, reader, width);
548 return AMEDIA_ERROR_INVALID_PARAMETER;
549 }
550 *width = reader->getWidth();
551 return AMEDIA_OK;
552}
553
554EXPORT
555media_status_t AImageReader_getHeight(const AImageReader* reader, /*out*/int32_t* height) {
556 ALOGV("%s", __FUNCTION__);
557 if (reader == nullptr || height == nullptr) {
558 ALOGE("%s: invalid argument. reader %p, height %p",
559 __FUNCTION__, reader, height);
560 return AMEDIA_ERROR_INVALID_PARAMETER;
561 }
562 *height = reader->getHeight();
563 return AMEDIA_OK;
564}
565
566EXPORT
567media_status_t AImageReader_getFormat(const AImageReader* reader, /*out*/int32_t* format) {
568 ALOGV("%s", __FUNCTION__);
569 if (reader == nullptr || format == nullptr) {
570 ALOGE("%s: invalid argument. reader %p, format %p",
571 __FUNCTION__, reader, format);
572 return AMEDIA_ERROR_INVALID_PARAMETER;
573 }
574 *format = reader->getFormat();
575 return AMEDIA_OK;
576}
577
578EXPORT
579media_status_t AImageReader_getMaxImages(const AImageReader* reader, /*out*/int32_t* maxImages) {
580 ALOGV("%s", __FUNCTION__);
581 if (reader == nullptr || maxImages == nullptr) {
582 ALOGE("%s: invalid argument. reader %p, maxImages %p",
583 __FUNCTION__, reader, maxImages);
584 return AMEDIA_ERROR_INVALID_PARAMETER;
585 }
586 *maxImages = reader->getMaxImages();
587 return AMEDIA_OK;
588}
589
590EXPORT
591media_status_t AImageReader_acquireNextImage(AImageReader* reader, /*out*/AImage** image) {
592 ALOGV("%s", __FUNCTION__);
593 if (reader == nullptr || image == nullptr) {
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800594 ALOGE("%s: invalid argument. reader %p, image %p",
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800595 __FUNCTION__, reader, image);
596 return AMEDIA_ERROR_INVALID_PARAMETER;
597 }
598 return reader->acquireNextImage(image);
599}
600
601EXPORT
602media_status_t AImageReader_acquireLatestImage(AImageReader* reader, /*out*/AImage** image) {
603 ALOGV("%s", __FUNCTION__);
604 if (reader == nullptr || image == nullptr) {
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800605 ALOGE("%s: invalid argument. reader %p, image %p",
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800606 __FUNCTION__, reader, image);
607 return AMEDIA_ERROR_INVALID_PARAMETER;
608 }
609 return reader->acquireLatestImage(image);
610}
611
612EXPORT
613media_status_t AImageReader_setImageListener(
614 AImageReader* reader, AImageReader_ImageListener* listener) {
615 ALOGV("%s", __FUNCTION__);
Yin-Chia Yeh1d0955c2016-05-16 01:14:13 -0700616 if (reader == nullptr) {
617 ALOGE("%s: invalid argument! reader %p", __FUNCTION__, reader);
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800618 return AMEDIA_ERROR_INVALID_PARAMETER;
619 }
620
621 reader->setImageListener(listener);
622 return AMEDIA_OK;
623}