blob: 1067e24ff2db7385ccaf3e74205018c7829125e9 [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>
Jooyung Han86cbf712019-02-21 15:25:02 +090028#include <ui/PublicFormat.h>
Jooyung Han27d84b72019-02-21 15:12:59 +090029#include <private/android/AHardwareBufferHelpers.h>
Jiwen 'Steve' Cai755ca9b2017-03-31 16:59:50 -070030#include <grallocusage/GrallocUsageConversion.h>
Chong Zhang0fe4c472019-04-08 21:51:46 +000031#include <gui/bufferqueue/1.0/WGraphicBufferProducer.h>
Yin-Chia Yehc3603822016-01-18 22:11:19 -080032
33using namespace android;
34
35namespace {
36 // Get an ID that's unique within this process.
37 static int32_t createProcessUniqueId() {
38 static volatile int32_t globalCounter = 0;
39 return android_atomic_inc(&globalCounter);
40 }
41}
42
43const char* AImageReader::kCallbackFpKey = "Callback";
44const char* AImageReader::kContextKey = "Context";
Jiwen 'Steve' Caie1689962017-02-20 16:59:05 -080045const char* AImageReader::kGraphicBufferKey = "GraphicBuffer";
Yin-Chia Yehc3603822016-01-18 22:11:19 -080046
Jayant Chowdhary249e1f22018-09-24 15:07:45 -070047static constexpr int kWindowHalTokenSizeMax = 256;
48
49static native_handle_t *convertHalTokenToNativeHandle(const HalToken &halToken);
50
Yin-Chia Yehc3603822016-01-18 22:11:19 -080051bool
Jiwen 'Steve' Cai55ec2562017-04-12 15:56:41 -070052AImageReader::isSupportedFormatAndUsage(int32_t format, uint64_t usage) {
53 // Check whether usage has either CPU_READ_OFTEN or CPU_READ set. Note that check against
54 // AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN (0x6) is sufficient as it implies
55 // AHARDWAREBUFFER_USAGE_CPU_READ (0x2).
56 bool hasCpuUsage = usage & AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN;
Yin-Chia Yehc3603822016-01-18 22:11:19 -080057 switch (format) {
Jiwen 'Steve' Caide2a5442017-02-08 14:41:41 -080058 case AIMAGE_FORMAT_RGBA_8888:
59 case AIMAGE_FORMAT_RGBX_8888:
60 case AIMAGE_FORMAT_RGB_888:
61 case AIMAGE_FORMAT_RGB_565:
62 case AIMAGE_FORMAT_RGBA_FP16:
Yin-Chia Yehc3603822016-01-18 22:11:19 -080063 case AIMAGE_FORMAT_YUV_420_888:
64 case AIMAGE_FORMAT_JPEG:
65 case AIMAGE_FORMAT_RAW16:
Jayant Chowdhary5fa12762019-03-13 15:01:58 -070066 case AIMAGE_FORMAT_RAW_DEPTH:
Yin-Chia Yehc3603822016-01-18 22:11:19 -080067 case AIMAGE_FORMAT_RAW_PRIVATE:
68 case AIMAGE_FORMAT_RAW10:
69 case AIMAGE_FORMAT_RAW12:
70 case AIMAGE_FORMAT_DEPTH16:
71 case AIMAGE_FORMAT_DEPTH_POINT_CLOUD:
Shuzhen Wang1cfbbec2018-10-08 13:55:28 -070072 case AIMAGE_FORMAT_Y8:
Shuzhen Wang68ac7ad2019-01-30 14:03:28 -080073 case AIMAGE_FORMAT_HEIC:
Emilian Peev44df34d2019-02-12 09:30:15 -080074 case AIMAGE_FORMAT_DEPTH_JPEG:
Yin-Chia Yehf6e6a8e2021-04-08 11:49:42 -070075 case AIMAGE_FORMAT_RAW_DEPTH10:
Yin-Chia Yehc3603822016-01-18 22:11:19 -080076 return true;
Jiwen 'Steve' Cai55ec2562017-04-12 15:56:41 -070077 case AIMAGE_FORMAT_PRIVATE:
78 // For private format, cpu usage is prohibited.
79 return !hasCpuUsage;
Yin-Chia Yehc3603822016-01-18 22:11:19 -080080 default:
81 return false;
82 }
83}
84
85int
86AImageReader::getNumPlanesForFormat(int32_t format) {
87 switch (format) {
88 case AIMAGE_FORMAT_YUV_420_888:
89 return 3;
Jiwen 'Steve' Caide2a5442017-02-08 14:41:41 -080090 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:
Yin-Chia Yehc3603822016-01-18 22:11:19 -080095 case AIMAGE_FORMAT_JPEG:
96 case AIMAGE_FORMAT_RAW16:
Jayant Chowdhary5fa12762019-03-13 15:01:58 -070097 case AIMAGE_FORMAT_RAW_DEPTH:
Yin-Chia Yehc3603822016-01-18 22:11:19 -080098 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:
Shuzhen Wang1cfbbec2018-10-08 13:55:28 -0700103 case AIMAGE_FORMAT_Y8:
Shuzhen Wang68ac7ad2019-01-30 14:03:28 -0800104 case AIMAGE_FORMAT_HEIC:
Emilian Peev44df34d2019-02-12 09:30:15 -0800105 case AIMAGE_FORMAT_DEPTH_JPEG:
Yin-Chia Yehf6e6a8e2021-04-08 11:49:42 -0700106 case AIMAGE_FORMAT_RAW_DEPTH10:
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800107 return 1;
Jiwen 'Steve' Cai55ec2562017-04-12 15:56:41 -0700108 case AIMAGE_FORMAT_PRIVATE:
109 return 0;
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800110 default:
111 return -1;
112 }
113}
114
115void
116AImageReader::FrameListener::onFrameAvailable(const BufferItem& /*item*/) {
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800117 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 }
Jayant Chowdharyebca5b92019-07-01 13:18:17 -0700122 Mutex::Autolock _l(mLock);
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800123 if (mListener.onImageAvailable == nullptr) {
124 return; // No callback registered
125 }
126
127 sp<AMessage> msg = new AMessage(AImageReader::kWhatImageAvailable, reader->mHandler);
128 msg->setPointer(AImageReader::kCallbackFpKey, (void *) mListener.onImageAvailable);
129 msg->setPointer(AImageReader::kContextKey, mListener.context);
130 msg->post();
131}
132
133media_status_t
134AImageReader::FrameListener::setImageListener(AImageReader_ImageListener* listener) {
135 Mutex::Autolock _l(mLock);
136 if (listener == nullptr) {
Yin-Chia Yeh1d0955c2016-05-16 01:14:13 -0700137 mListener.context = nullptr;
138 mListener.onImageAvailable = nullptr;
139 } else {
140 mListener = *listener;
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800141 }
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800142 return AMEDIA_OK;
143}
144
Jiwen 'Steve' Caie1689962017-02-20 16:59:05 -0800145void
146AImageReader::BufferRemovedListener::onBufferFreed(const wp<GraphicBuffer>& graphicBuffer) {
Jiwen 'Steve' Caie1689962017-02-20 16:59:05 -0800147 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 }
Jayant Chowdharyebca5b92019-07-01 13:18:17 -0700152 Mutex::Autolock _l(mLock);
Jiwen 'Steve' Caie1689962017-02-20 16:59:05 -0800153 if (mListener.onBufferRemoved == nullptr) {
154 return; // No callback registered
155 }
156
157 sp<GraphicBuffer> gBuffer = graphicBuffer.promote();
158 if (gBuffer == nullptr) {
159 ALOGW("A buffer being freed has gone away!");
160 return; // buffer is already destroyed
161 }
162
163 sp<AMessage> msg = new AMessage(AImageReader::kWhatBufferRemoved, reader->mHandler);
164 msg->setPointer(
165 AImageReader::kCallbackFpKey, (void*) mListener.onBufferRemoved);
166 msg->setPointer(AImageReader::kContextKey, mListener.context);
167 msg->setObject(AImageReader::kGraphicBufferKey, gBuffer);
168 msg->post();
169}
170
171media_status_t
172AImageReader::BufferRemovedListener::setBufferRemovedListener(
173 AImageReader_BufferRemovedListener* listener) {
174 Mutex::Autolock _l(mLock);
175 if (listener == nullptr) {
176 mListener.context = nullptr;
177 mListener.onBufferRemoved = nullptr;
178 } else {
179 mListener = *listener;
180 }
181 return AMEDIA_OK;
182}
183
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800184media_status_t
185AImageReader::setImageListenerLocked(AImageReader_ImageListener* listener) {
186 return mFrameListener->setImageListener(listener);
187}
188
189media_status_t
190AImageReader::setImageListener(AImageReader_ImageListener* listener) {
191 Mutex::Autolock _l(mLock);
192 return setImageListenerLocked(listener);
193}
194
Jiwen 'Steve' Caie1689962017-02-20 16:59:05 -0800195media_status_t
196AImageReader::setBufferRemovedListenerLocked(AImageReader_BufferRemovedListener* listener) {
197 return mBufferRemovedListener->setBufferRemovedListener(listener);
198}
199
200media_status_t
201AImageReader::setBufferRemovedListener(AImageReader_BufferRemovedListener* listener) {
202 Mutex::Autolock _l(mLock);
203 return setBufferRemovedListenerLocked(listener);
204}
205
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800206void AImageReader::CallbackHandler::onMessageReceived(
207 const sp<AMessage> &msg) {
208 switch (msg->what()) {
Jiwen 'Steve' Caie1689962017-02-20 16:59:05 -0800209 case kWhatBufferRemoved:
210 {
211 AImageReader_BufferRemovedCallback onBufferRemoved;
212 void* context;
213 bool found = msg->findPointer(kCallbackFpKey, (void**) &onBufferRemoved);
214 if (!found || onBufferRemoved == nullptr) {
215 ALOGE("%s: Cannot find onBufferRemoved callback fp!", __FUNCTION__);
216 return;
217 }
218 found = msg->findPointer(kContextKey, &context);
219 if (!found) {
220 ALOGE("%s: Cannot find callback context!", __FUNCTION__);
221 return;
222 }
223 sp<RefBase> bufferToFree;
224 found = msg->findObject(kGraphicBufferKey, &bufferToFree);
225 if (!found || bufferToFree == nullptr) {
226 ALOGE("%s: Cannot find the buffer to free!", __FUNCTION__);
227 return;
228 }
229
230 // TODO(jwcai) Someone from Android graphics team stating this should just be a
231 // static_cast.
232 AHardwareBuffer* outBuffer = reinterpret_cast<AHardwareBuffer*>(bufferToFree.get());
233
234 // At this point, bufferToFree holds the last reference to the GraphicBuffer owned by
235 // this AImageReader, and the reference will be gone once this function returns.
236 (*onBufferRemoved)(context, mReader, outBuffer);
237 break;
238 }
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800239 case kWhatImageAvailable:
240 {
241 AImageReader_ImageCallback onImageAvailable;
242 void* context;
243 bool found = msg->findPointer(kCallbackFpKey, (void**) &onImageAvailable);
244 if (!found || onImageAvailable == nullptr) {
245 ALOGE("%s: Cannot find onImageAvailable callback fp!", __FUNCTION__);
246 return;
247 }
248 found = msg->findPointer(kContextKey, &context);
249 if (!found) {
250 ALOGE("%s: Cannot find callback context!", __FUNCTION__);
251 return;
252 }
253 (*onImageAvailable)(context, mReader);
254 break;
255 }
256 default:
257 ALOGE("%s: unknown message type %d", __FUNCTION__, msg->what());
258 break;
259 }
260}
261
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800262AImageReader::AImageReader(int32_t width,
263 int32_t height,
264 int32_t format,
Jiwen 'Steve' Caie31bc872017-04-21 17:13:18 -0700265 uint64_t usage,
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800266 int32_t maxImages)
267 : mWidth(width),
268 mHeight(height),
269 mFormat(format),
Jiwen 'Steve' Caie31bc872017-04-21 17:13:18 -0700270 mUsage(usage),
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800271 mMaxImages(maxImages),
272 mNumPlanes(getNumPlanesForFormat(format)),
Jiwen 'Steve' Caie1689962017-02-20 16:59:05 -0800273 mFrameListener(new FrameListener(this)),
274 mBufferRemovedListener(new BufferRemovedListener(this)) {}
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800275
Jayant Chowdhary9e0302f2019-07-16 11:04:06 -0700276AImageReader::~AImageReader() {
277 Mutex::Autolock _l(mLock);
Jayant Chowdhary3a4af232020-12-15 11:01:03 -0800278 LOG_FATAL_IF(mIsOpen, "AImageReader not closed before destruction");
Jayant Chowdhary9e0302f2019-07-16 11:04:06 -0700279}
280
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800281media_status_t
282AImageReader::init() {
283 PublicFormat publicFormat = static_cast<PublicFormat>(mFormat);
Jooyung Han86cbf712019-02-21 15:25:02 +0900284 mHalFormat = mapPublicFormatToHalFormat(publicFormat);
285 mHalDataSpace = mapPublicFormatToHalDataspace(publicFormat);
Jooyung Han27d84b72019-02-21 15:12:59 +0900286 mHalUsage = AHardwareBuffer_convertToGrallocUsageBits(mUsage);
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800287
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800288 sp<IGraphicBufferProducer> gbProducer;
289 sp<IGraphicBufferConsumer> gbConsumer;
290 BufferQueue::createBufferQueue(&gbProducer, &gbConsumer);
291
Jiwen 'Steve' Caie31bc872017-04-21 17:13:18 -0700292 String8 consumerName = String8::format("ImageReader-%dx%df%xu%" PRIu64 "m%d-%d-%d",
293 mWidth, mHeight, mFormat, mUsage, mMaxImages, getpid(),
Jiwen 'Steve' Caie1689962017-02-20 16:59:05 -0800294 createProcessUniqueId());
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800295
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800296 mBufferItemConsumer =
Jiwen 'Steve' Caie1689962017-02-20 16:59:05 -0800297 new BufferItemConsumer(gbConsumer, mHalUsage, mMaxImages, /*controlledByApp*/ true);
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800298 if (mBufferItemConsumer == nullptr) {
299 ALOGE("Failed to allocate BufferItemConsumer");
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800300 return AMEDIA_ERROR_UNKNOWN;
301 }
302
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800303 mProducer = gbProducer;
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800304 mBufferItemConsumer->setName(consumerName);
305 mBufferItemConsumer->setFrameAvailableListener(mFrameListener);
Jiwen 'Steve' Caie1689962017-02-20 16:59:05 -0800306 mBufferItemConsumer->setBufferFreedListener(mBufferRemovedListener);
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800307
308 status_t res;
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800309 res = mBufferItemConsumer->setDefaultBufferSize(mWidth, mHeight);
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800310 if (res != OK) {
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800311 ALOGE("Failed to set BufferItemConsumer buffer size");
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800312 return AMEDIA_ERROR_UNKNOWN;
313 }
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800314 res = mBufferItemConsumer->setDefaultBufferFormat(mHalFormat);
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800315 if (res != OK) {
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800316 ALOGE("Failed to set BufferItemConsumer buffer format");
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800317 return AMEDIA_ERROR_UNKNOWN;
318 }
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800319 res = mBufferItemConsumer->setDefaultBufferDataSpace(mHalDataSpace);
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800320 if (res != OK) {
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800321 ALOGE("Failed to set BufferItemConsumer buffer dataSpace");
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800322 return AMEDIA_ERROR_UNKNOWN;
323 }
Khushalff20fd42019-01-22 15:31:00 -0800324 if (mUsage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT) {
325 gbConsumer->setConsumerIsProtected(true);
326 }
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800327
328 mSurface = new Surface(mProducer, /*controlledByApp*/true);
329 if (mSurface == nullptr) {
330 ALOGE("Failed to create surface");
331 return AMEDIA_ERROR_UNKNOWN;
332 }
333 mWindow = static_cast<ANativeWindow*>(mSurface.get());
334
335 for (int i = 0; i < mMaxImages; i++) {
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800336 BufferItem* buffer = new BufferItem;
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800337 mBuffers.push_back(buffer);
338 }
339
340 mCbLooper = new ALooper;
341 mCbLooper->setName(consumerName.string());
Aurimas Liutikas214c8332016-02-19 14:48:23 -0800342 res = mCbLooper->start(
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800343 /*runOnCallingThread*/false,
344 /*canCallJava*/ true,
345 PRIORITY_DEFAULT);
Aurimas Liutikas214c8332016-02-19 14:48:23 -0800346 if (res != OK) {
347 ALOGE("Failed to start the looper");
348 return AMEDIA_ERROR_UNKNOWN;
349 }
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800350 mHandler = new CallbackHandler(this);
351 mCbLooper->registerHandler(mHandler);
Jayant Chowdhary3a4af232020-12-15 11:01:03 -0800352 mIsOpen = true;
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800353 return AMEDIA_OK;
354}
355
Jayant Chowdhary9e0302f2019-07-16 11:04:06 -0700356void AImageReader::close() {
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800357 Mutex::Autolock _l(mLock);
Jayant Chowdhary3a4af232020-12-15 11:01:03 -0800358 if (!mIsOpen) {
Jayant Chowdhary9e0302f2019-07-16 11:04:06 -0700359 return;
360 }
Jayant Chowdhary3a4af232020-12-15 11:01:03 -0800361 mIsOpen = false;
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800362 AImageReader_ImageListener nullListener = {nullptr, nullptr};
363 setImageListenerLocked(&nullListener);
364
Jiwen 'Steve' Caie1689962017-02-20 16:59:05 -0800365 AImageReader_BufferRemovedListener nullBufferRemovedListener = {nullptr, nullptr};
366 setBufferRemovedListenerLocked(&nullBufferRemovedListener);
367
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800368 if (mCbLooper != nullptr) {
369 mCbLooper->unregisterHandler(mHandler->id());
370 mCbLooper->stop();
371 }
372 mCbLooper.clear();
373 mHandler.clear();
374
375 // Close all previously acquired images
376 for (auto it = mAcquiredImages.begin();
377 it != mAcquiredImages.end(); it++) {
378 AImage* image = *it;
Yin-Chia Yehb29fce72017-11-06 17:16:22 -0800379 Mutex::Autolock _l(image->mLock);
Yin-Chia Yeh55baca22019-01-07 13:54:13 -0800380 // Do not alter mAcquiredImages while we are iterating on it
381 releaseImageLocked(image, /*releaseFenceFd*/-1, /*clearCache*/false);
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800382 }
Yin-Chia Yeh55baca22019-01-07 13:54:13 -0800383 mAcquiredImages.clear();
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800384
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800385 // Delete Buffer Items
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800386 for (auto it = mBuffers.begin();
387 it != mBuffers.end(); it++) {
388 delete *it;
389 }
390
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800391 if (mBufferItemConsumer != nullptr) {
392 mBufferItemConsumer->abandon();
393 mBufferItemConsumer->setFrameAvailableListener(nullptr);
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800394 }
Jayant Chowdhary249e1f22018-09-24 15:07:45 -0700395
396 if (mWindowHandle != nullptr) {
397 int size = mWindowHandle->data[0];
398 hidl_vec<uint8_t> halToken;
399 halToken.setToExternal(
400 reinterpret_cast<uint8_t *>(&mWindowHandle->data[1]), size);
401 deleteHalToken(halToken);
402 native_handle_delete(mWindowHandle);
403 }
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800404}
405
406media_status_t
Jiwen 'Steve' Caie1689962017-02-20 16:59:05 -0800407AImageReader::acquireImageLocked(/*out*/AImage** image, /*out*/int* acquireFenceFd) {
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800408 *image = nullptr;
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800409 BufferItem* buffer = getBufferItemLocked();
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800410 if (buffer == nullptr) {
411 ALOGW("Unable to acquire a lockedBuffer, very likely client tries to lock more than"
412 " maxImages buffers");
413 return AMEDIA_IMGREADER_MAX_IMAGES_ACQUIRED;
414 }
415
Jiwen 'Steve' Caie1689962017-02-20 16:59:05 -0800416 // When the output paramter fence is not NULL, we are acquiring the image asynchronously.
417 bool waitForFence = acquireFenceFd == nullptr;
418 status_t res = mBufferItemConsumer->acquireBuffer(buffer, 0, waitForFence);
419
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800420 if (res != NO_ERROR) {
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800421 returnBufferItemLocked(buffer);
422 if (res != BufferQueue::NO_BUFFER_AVAILABLE) {
423 if (res == INVALID_OPERATION) {
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800424 return AMEDIA_IMGREADER_MAX_IMAGES_ACQUIRED;
425 } else {
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800426 ALOGE("%s: Acquire image failed with some unknown error: %s (%d)",
427 __FUNCTION__, strerror(-res), res);
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800428 return AMEDIA_ERROR_UNKNOWN;
429 }
430 }
431 return AMEDIA_IMGREADER_NO_BUFFER_AVAILABLE;
432 }
433
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800434 const int bufferWidth = getBufferWidth(buffer);
435 const int bufferHeight = getBufferHeight(buffer);
436 const int bufferFmt = buffer->mGraphicBuffer->getPixelFormat();
Jiwen 'Steve' Caie1689962017-02-20 16:59:05 -0800437 const int bufferUsage = buffer->mGraphicBuffer->getUsage();
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800438
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800439 const int readerWidth = mWidth;
440 const int readerHeight = mHeight;
441 const int readerFmt = mHalFormat;
Jiwen 'Steve' Caie1689962017-02-20 16:59:05 -0800442 const int readerUsage = mHalUsage;
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800443
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800444 // Check if the producer buffer configurations match what AImageReader configured. Add some
445 // extra checks for non-opaque formats.
446 if (!isFormatOpaque(readerFmt)) {
447 // Check if the left-top corner of the crop rect is origin, we currently assume this point
448 // is zero, will revisit this once this assumption turns out problematic.
449 Point lt = buffer->mCrop.leftTop();
450 if (lt.x != 0 || lt.y != 0) {
451 ALOGE("Crop left top corner [%d, %d] not at origin", lt.x, lt.y);
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800452 return AMEDIA_ERROR_UNKNOWN;
453 }
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800454
455 // Check if the producer buffer configurations match what ImageReader configured.
Jiwen 'Steve' Cai755ca9b2017-03-31 16:59:50 -0700456 ALOGV_IF(readerWidth != bufferWidth || readerHeight != bufferHeight,
457 "%s: Buffer size: %dx%d, doesn't match AImageReader configured size: %dx%d",
458 __FUNCTION__, bufferWidth, bufferHeight, readerWidth, readerHeight);
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800459
Jiwen 'Steve' Caie1689962017-02-20 16:59:05 -0800460 // Check if the buffer usage is a super set of reader's usage bits, aka all usage bits that
461 // ImageReader requested has been supported from the producer side.
462 ALOGD_IF((readerUsage | bufferUsage) != bufferUsage,
463 "%s: Producer buffer usage: %x, doesn't cover all usage bits AImageReader "
464 "configured: %x",
465 __FUNCTION__, bufferUsage, readerUsage);
466
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800467 if (readerFmt != bufferFmt) {
468 if (readerFmt == HAL_PIXEL_FORMAT_YCbCr_420_888 && isPossiblyYUV(bufferFmt)) {
469 // Special casing for when producer switches to a format compatible with flexible
470 // YUV.
471 mHalFormat = bufferFmt;
472 ALOGD("%s: Overriding buffer format YUV_420_888 to 0x%x.", __FUNCTION__, bufferFmt);
473 } else {
474 // Return the buffer to the queue. No need to provide fence, as this buffer wasn't
475 // used anywhere yet.
476 mBufferItemConsumer->releaseBuffer(*buffer);
477 returnBufferItemLocked(buffer);
478
479 ALOGE("%s: Output buffer format: 0x%x, ImageReader configured format: 0x%x",
480 __FUNCTION__, bufferFmt, readerFmt);
481
482 return AMEDIA_ERROR_UNKNOWN;
483 }
484 }
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800485 }
486
487 if (mHalFormat == HAL_PIXEL_FORMAT_BLOB) {
Jiwen 'Steve' Caie31bc872017-04-21 17:13:18 -0700488 *image = new AImage(this, mFormat, mUsage, buffer, buffer->mTimestamp,
Jiwen 'Steve' Caie1689962017-02-20 16:59:05 -0800489 readerWidth, readerHeight, mNumPlanes);
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800490 } else {
Jiwen 'Steve' Caie31bc872017-04-21 17:13:18 -0700491 *image = new AImage(this, mFormat, mUsage, buffer, buffer->mTimestamp,
Jiwen 'Steve' Caie1689962017-02-20 16:59:05 -0800492 bufferWidth, bufferHeight, mNumPlanes);
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800493 }
494 mAcquiredImages.push_back(*image);
Jiwen 'Steve' Caie1689962017-02-20 16:59:05 -0800495
496 // When the output paramter fence is not NULL, we are acquiring the image asynchronously.
497 if (acquireFenceFd != nullptr) {
498 *acquireFenceFd = buffer->mFence->dup();
499 }
500
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800501 return AMEDIA_OK;
502}
503
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800504BufferItem*
505AImageReader::getBufferItemLocked() {
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800506 if (mBuffers.empty()) {
507 return nullptr;
508 }
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800509 // Return a BufferItem pointer and remove it from the list
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800510 auto it = mBuffers.begin();
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800511 BufferItem* buffer = *it;
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800512 mBuffers.erase(it);
513 return buffer;
514}
515
516void
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800517AImageReader::returnBufferItemLocked(BufferItem* buffer) {
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800518 mBuffers.push_back(buffer);
519}
520
521void
Yin-Chia Yeh55baca22019-01-07 13:54:13 -0800522AImageReader::releaseImageLocked(AImage* image, int releaseFenceFd, bool clearCache) {
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800523 BufferItem* buffer = image->mBuffer;
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800524 if (buffer == nullptr) {
525 // This should not happen, but is not fatal
526 ALOGW("AImage %p has no buffer!", image);
527 return;
528 }
529
Jiwen 'Steve' Caie1689962017-02-20 16:59:05 -0800530 int unlockFenceFd = -1;
531 media_status_t ret = image->unlockImageIfLocked(&unlockFenceFd);
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800532 if (ret < 0) {
533 ALOGW("%s: AImage %p is cannot be unlocked.", __FUNCTION__, image);
534 return;
535 }
536
Jiwen 'Steve' Caie1689962017-02-20 16:59:05 -0800537 sp<Fence> unlockFence = unlockFenceFd > 0 ? new Fence(unlockFenceFd) : Fence::NO_FENCE;
538 sp<Fence> releaseFence = releaseFenceFd > 0 ? new Fence(releaseFenceFd) : Fence::NO_FENCE;
539 sp<Fence> bufferFence = Fence::merge("AImageReader", unlockFence, releaseFence);
540 mBufferItemConsumer->releaseBuffer(*buffer, bufferFence);
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800541 returnBufferItemLocked(buffer);
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800542 image->mBuffer = nullptr;
Yin-Chia Yehb29fce72017-11-06 17:16:22 -0800543 image->mLockedBuffer = nullptr;
544 image->mIsClosed = true;
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800545
Yin-Chia Yeh55baca22019-01-07 13:54:13 -0800546 if (!clearCache) {
547 return;
548 }
549
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800550 bool found = false;
551 // cleanup acquired image list
552 for (auto it = mAcquiredImages.begin();
553 it != mAcquiredImages.end(); it++) {
554 AImage* readerCopy = *it;
555 if (readerCopy == image) {
556 found = true;
557 mAcquiredImages.erase(it);
558 break;
559 }
560 }
561 if (!found) {
562 ALOGE("Error: AImage %p is not generated by AImageReader %p",
563 image, this);
564 }
565}
566
Jayant Chowdhary249e1f22018-09-24 15:07:45 -0700567media_status_t AImageReader::getWindowNativeHandle(native_handle **handle) {
568 if (mWindowHandle != nullptr) {
569 *handle = mWindowHandle;
570 return AMEDIA_OK;
571 }
572 sp<HGraphicBufferProducer> hgbp =
573 new TWGraphicBufferProducer<HGraphicBufferProducer>(mProducer);
574 HalToken halToken;
575 if (!createHalToken(hgbp, &halToken)) {
576 return AMEDIA_ERROR_UNKNOWN;
577 }
578 mWindowHandle = convertHalTokenToNativeHandle(halToken);
579 if (!mWindowHandle) {
580 return AMEDIA_ERROR_UNKNOWN;
581 }
582 *handle = mWindowHandle;
583 return AMEDIA_OK;
584}
585
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800586int
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800587AImageReader::getBufferWidth(BufferItem* buffer) {
588 if (buffer == NULL) return -1;
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800589
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800590 if (!buffer->mCrop.isEmpty()) {
591 return buffer->mCrop.getWidth();
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800592 }
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800593
594 return buffer->mGraphicBuffer->getWidth();
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800595}
596
597int
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800598AImageReader::getBufferHeight(BufferItem* buffer) {
599 if (buffer == NULL) return -1;
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800600
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800601 if (!buffer->mCrop.isEmpty()) {
602 return buffer->mCrop.getHeight();
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800603 }
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800604
605 return buffer->mGraphicBuffer->getHeight();
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800606}
607
608media_status_t
Jiwen 'Steve' Caie1689962017-02-20 16:59:05 -0800609AImageReader::acquireNextImage(/*out*/AImage** image, /*out*/int* acquireFenceFd) {
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800610 Mutex::Autolock _l(mLock);
Jiwen 'Steve' Caie1689962017-02-20 16:59:05 -0800611 return acquireImageLocked(image, acquireFenceFd);
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800612}
613
614media_status_t
Jiwen 'Steve' Caie1689962017-02-20 16:59:05 -0800615AImageReader::acquireLatestImage(/*out*/AImage** image, /*out*/int* acquireFenceFd) {
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800616 if (image == nullptr) {
617 return AMEDIA_ERROR_INVALID_PARAMETER;
618 }
619 Mutex::Autolock _l(mLock);
620 *image = nullptr;
621 AImage* prevImage = nullptr;
622 AImage* nextImage = nullptr;
Jiwen 'Steve' Caie1689962017-02-20 16:59:05 -0800623 media_status_t ret = acquireImageLocked(&prevImage, acquireFenceFd);
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800624 if (prevImage == nullptr) {
625 return ret;
626 }
627 for (;;) {
Jiwen 'Steve' Caie1689962017-02-20 16:59:05 -0800628 ret = acquireImageLocked(&nextImage, acquireFenceFd);
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800629 if (nextImage == nullptr) {
630 *image = prevImage;
631 return AMEDIA_OK;
632 }
Jiwen 'Steve' Caie1689962017-02-20 16:59:05 -0800633
634 if (acquireFenceFd == nullptr) {
635 // No need for release fence here since the prevImage is unused and acquireImageLocked
636 // has already waited for acquired fence to be signaled.
637 prevImage->close();
638 } else {
639 // Use the acquire fence as release fence, so that producer can wait before trying to
640 // refill the buffer.
641 prevImage->close(*acquireFenceFd);
642 }
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800643 prevImage->free();
644 prevImage = nextImage;
645 nextImage = nullptr;
646 }
647}
648
Jayant Chowdhary249e1f22018-09-24 15:07:45 -0700649static native_handle_t *convertHalTokenToNativeHandle(
650 const HalToken &halToken) {
651 // We attempt to store halToken in the ints of the native_handle_t after its
652 // size. The first int stores the size of the token. We store this in an int
653 // to avoid alignment issues where size_t and int do not have the same
654 // alignment.
655 size_t nhDataByteSize = halToken.size();
656 if (nhDataByteSize > kWindowHalTokenSizeMax) {
657 // The size of the token isn't reasonable..
658 return nullptr;
659 }
660 size_t numInts = ceil(nhDataByteSize / sizeof(int)) + 1;
661
662 // We don't check for overflow, whether numInts can fit in an int, since we
663 // expect kWindowHalTokenSizeMax to be a reasonable limit.
664 // create a native_handle_t with 0 numFds and numInts number of ints.
665 native_handle_t *nh =
666 native_handle_create(0, numInts);
667 if (!nh) {
668 return nullptr;
669 }
670 // Store the size of the token in the first int.
671 nh->data[0] = nhDataByteSize;
672 memcpy(&(nh->data[1]), halToken.data(), nhDataByteSize);
673 return nh;
674}
675
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800676EXPORT
677media_status_t AImageReader_new(
678 int32_t width, int32_t height, int32_t format, int32_t maxImages,
679 /*out*/AImageReader** reader) {
680 ALOGV("%s", __FUNCTION__);
Jiwen 'Steve' Caie1689962017-02-20 16:59:05 -0800681 return AImageReader_newWithUsage(
Jiwen 'Steve' Caie31bc872017-04-21 17:13:18 -0700682 width, height, format, AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN, maxImages, reader);
Jiwen 'Steve' Caie1689962017-02-20 16:59:05 -0800683}
684
Jayant Chowdhary249e1f22018-09-24 15:07:45 -0700685extern "C" {
686
687EXPORT
688media_status_t AImageReader_getWindowNativeHandle(
689 AImageReader *reader, /*out*/native_handle_t **handle) {
690 if (reader == nullptr || handle == nullptr) {
691 return AMEDIA_ERROR_INVALID_PARAMETER;
692 }
693 return reader->getWindowNativeHandle(handle);
694}
695
696} //extern "C"
697
Jiwen 'Steve' Caie1689962017-02-20 16:59:05 -0800698EXPORT
699media_status_t AImageReader_newWithUsage(
Jiwen 'Steve' Caie31bc872017-04-21 17:13:18 -0700700 int32_t width, int32_t height, int32_t format, uint64_t usage,
Jiwen 'Steve' Caie1689962017-02-20 16:59:05 -0800701 int32_t maxImages, /*out*/ AImageReader** reader) {
702 ALOGV("%s", __FUNCTION__);
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800703
704 if (width < 1 || height < 1) {
705 ALOGE("%s: image dimension must be positive: w:%d h:%d",
706 __FUNCTION__, width, height);
707 return AMEDIA_ERROR_INVALID_PARAMETER;
708 }
709
710 if (maxImages < 1) {
711 ALOGE("%s: max outstanding image count must be at least 1 (%d)",
712 __FUNCTION__, maxImages);
713 return AMEDIA_ERROR_INVALID_PARAMETER;
714 }
715
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800716 if (maxImages > BufferQueueDefs::NUM_BUFFER_SLOTS) {
717 ALOGE("%s: max outstanding image count (%d) cannot be larget than %d.",
718 __FUNCTION__, maxImages, BufferQueueDefs::NUM_BUFFER_SLOTS);
719 return AMEDIA_ERROR_INVALID_PARAMETER;
720 }
721
Jiwen 'Steve' Cai55ec2562017-04-12 15:56:41 -0700722 if (!AImageReader::isSupportedFormatAndUsage(format, usage)) {
723 ALOGE("%s: format %d is not supported with usage 0x%" PRIx64 " by AImageReader",
724 __FUNCTION__, format, usage);
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800725 return AMEDIA_ERROR_INVALID_PARAMETER;
726 }
727
728 if (reader == nullptr) {
729 ALOGE("%s: reader argument is null", __FUNCTION__);
730 return AMEDIA_ERROR_INVALID_PARAMETER;
731 }
732
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800733 AImageReader* tmpReader = new AImageReader(
Jiwen 'Steve' Caie31bc872017-04-21 17:13:18 -0700734 width, height, format, usage, maxImages);
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800735 if (tmpReader == nullptr) {
736 ALOGE("%s: AImageReader allocation failed", __FUNCTION__);
737 return AMEDIA_ERROR_UNKNOWN;
738 }
739 media_status_t ret = tmpReader->init();
740 if (ret != AMEDIA_OK) {
741 ALOGE("%s: AImageReader initialization failed!", __FUNCTION__);
742 delete tmpReader;
743 return ret;
744 }
745 *reader = tmpReader;
746 (*reader)->incStrong((void*) AImageReader_new);
747 return AMEDIA_OK;
748}
749
750EXPORT
751void AImageReader_delete(AImageReader* reader) {
752 ALOGV("%s", __FUNCTION__);
753 if (reader != nullptr) {
Jayant Chowdhary9e0302f2019-07-16 11:04:06 -0700754 reader->close();
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800755 reader->decStrong((void*) AImageReader_delete);
756 }
757 return;
758}
759
760EXPORT
761media_status_t AImageReader_getWindow(AImageReader* reader, /*out*/ANativeWindow** window) {
Yin-Chia Yehe2ded212017-11-08 15:51:02 -0800762 ALOGV("%s", __FUNCTION__);
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800763 if (reader == nullptr || window == nullptr) {
764 ALOGE("%s: invalid argument. reader %p, window %p",
765 __FUNCTION__, reader, window);
766 return AMEDIA_ERROR_INVALID_PARAMETER;
767 }
768 *window = reader->getWindow();
769 return AMEDIA_OK;
770}
771
772EXPORT
773media_status_t AImageReader_getWidth(const AImageReader* reader, /*out*/int32_t* width) {
774 ALOGV("%s", __FUNCTION__);
775 if (reader == nullptr || width == nullptr) {
776 ALOGE("%s: invalid argument. reader %p, width %p",
777 __FUNCTION__, reader, width);
778 return AMEDIA_ERROR_INVALID_PARAMETER;
779 }
780 *width = reader->getWidth();
781 return AMEDIA_OK;
782}
783
784EXPORT
785media_status_t AImageReader_getHeight(const AImageReader* reader, /*out*/int32_t* height) {
786 ALOGV("%s", __FUNCTION__);
787 if (reader == nullptr || height == nullptr) {
788 ALOGE("%s: invalid argument. reader %p, height %p",
789 __FUNCTION__, reader, height);
790 return AMEDIA_ERROR_INVALID_PARAMETER;
791 }
792 *height = reader->getHeight();
793 return AMEDIA_OK;
794}
795
796EXPORT
797media_status_t AImageReader_getFormat(const AImageReader* reader, /*out*/int32_t* format) {
798 ALOGV("%s", __FUNCTION__);
799 if (reader == nullptr || format == nullptr) {
800 ALOGE("%s: invalid argument. reader %p, format %p",
801 __FUNCTION__, reader, format);
802 return AMEDIA_ERROR_INVALID_PARAMETER;
803 }
804 *format = reader->getFormat();
805 return AMEDIA_OK;
806}
807
808EXPORT
809media_status_t AImageReader_getMaxImages(const AImageReader* reader, /*out*/int32_t* maxImages) {
810 ALOGV("%s", __FUNCTION__);
811 if (reader == nullptr || maxImages == nullptr) {
812 ALOGE("%s: invalid argument. reader %p, maxImages %p",
813 __FUNCTION__, reader, maxImages);
814 return AMEDIA_ERROR_INVALID_PARAMETER;
815 }
816 *maxImages = reader->getMaxImages();
817 return AMEDIA_OK;
818}
819
820EXPORT
821media_status_t AImageReader_acquireNextImage(AImageReader* reader, /*out*/AImage** image) {
822 ALOGV("%s", __FUNCTION__);
Jiwen 'Steve' Caie1689962017-02-20 16:59:05 -0800823 return AImageReader_acquireNextImageAsync(reader, image, nullptr);
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800824}
825
826EXPORT
827media_status_t AImageReader_acquireLatestImage(AImageReader* reader, /*out*/AImage** image) {
828 ALOGV("%s", __FUNCTION__);
Jiwen 'Steve' Caie1689962017-02-20 16:59:05 -0800829 return AImageReader_acquireLatestImageAsync(reader, image, nullptr);
830}
831
832EXPORT
833media_status_t AImageReader_acquireNextImageAsync(
834 AImageReader* reader, /*out*/AImage** image, /*out*/int* acquireFenceFd) {
835 ALOGV("%s", __FUNCTION__);
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800836 if (reader == nullptr || image == nullptr) {
Jiwen 'Steve' Cai2f1a4732017-02-04 17:31:55 -0800837 ALOGE("%s: invalid argument. reader %p, image %p",
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800838 __FUNCTION__, reader, image);
839 return AMEDIA_ERROR_INVALID_PARAMETER;
840 }
Jiwen 'Steve' Caie1689962017-02-20 16:59:05 -0800841 return reader->acquireNextImage(image, acquireFenceFd);
842}
843
844EXPORT
845media_status_t AImageReader_acquireLatestImageAsync(
846 AImageReader* reader, /*out*/AImage** image, /*out*/int* acquireFenceFd) {
847 ALOGV("%s", __FUNCTION__);
848 if (reader == nullptr || image == nullptr) {
849 ALOGE("%s: invalid argument. reader %p, image %p",
850 __FUNCTION__, reader, image);
851 return AMEDIA_ERROR_INVALID_PARAMETER;
852 }
853 return reader->acquireLatestImage(image, acquireFenceFd);
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800854}
855
856EXPORT
857media_status_t AImageReader_setImageListener(
858 AImageReader* reader, AImageReader_ImageListener* listener) {
859 ALOGV("%s", __FUNCTION__);
Yin-Chia Yeh1d0955c2016-05-16 01:14:13 -0700860 if (reader == nullptr) {
861 ALOGE("%s: invalid argument! reader %p", __FUNCTION__, reader);
Yin-Chia Yehc3603822016-01-18 22:11:19 -0800862 return AMEDIA_ERROR_INVALID_PARAMETER;
863 }
864
865 reader->setImageListener(listener);
866 return AMEDIA_OK;
867}
Jiwen 'Steve' Caie1689962017-02-20 16:59:05 -0800868
869EXPORT
870media_status_t AImageReader_setBufferRemovedListener(
871 AImageReader* reader, AImageReader_BufferRemovedListener* listener) {
872 ALOGV("%s", __FUNCTION__);
873 if (reader == nullptr) {
874 ALOGE("%s: invalid argument! reader %p", __FUNCTION__, reader);
875 return AMEDIA_ERROR_INVALID_PARAMETER;
876 }
877
878 reader->setBufferRemovedListener(listener);
879 return AMEDIA_OK;
880}